1 #!/bin/sh
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 
  25 #
  26 # Description:
  27 #       Sets up client data specific for a particular client, in the
  28 #       non-default case. In general, client setup is not required and all
  29 #       clients will boot the default service as tagged in create-service.
  30 #       If it is desired to have a client boot and utilize specific services
  31 #       and manifests, this command is used to do so. The following
  32 #       functionality is provided:
  33 #
  34 #       1. Allow for specification of installation service for client to use.
  35 #          This will bypass the service discovery mechanism and use a specific
  36 #          service. The administrator can set up manifiests with that service
  37 #          to serve the clients.
  38 #
  39 #       2. For x86, creates a bootfile and /tftpboot entries. The bootfile
  40 #          name is derived from the MAC address.
  41 #          For sparc, create wanboot.conf file in following location:
  42 #
  43 #          /etc/netboot/<network_address>/<client_id>/wanboot.conf
  44 #
  45 #          where <client_id>=01<mac_address_without_collons>
  46 #          e.g. 0100144FA2574C
  47 #
  48 #       3. Setup the dhcp macro with the server and bootfile information
  49 #          if it doesn't exist.
  50 #
  51 # Files potentially changed on server:
  52 # /tftpboot/ - directory created/populated with pxegrub files and links.
  53 # /etc/inetd.conf - to turn on tftpboot daemon
  54 # /etc/netboot/<network number>/<MACID>/wanboot.conf
  55 
  56 # make sure path is ok
  57 PATH=/usr/bin:/usr/sbin:/sbin:${PATH}; export PATH
  58 
  59 # tr may fail in some locales. Hence set the env LANG=C and LC_ALL=C
  60 TR='env LC_ALL=C LANG=C /bin/tr'
  61 
  62 # Constants
  63 #
  64 SIGHUP=1
  65 SIGINT=2
  66 SIGQUIT=3
  67 SIGTERM=15
  68 
  69 # Variables 
  70 #
  71 DHCP_CLIENT_ID=""
  72 DIRNAME="/usr/lib/installadm"
  73 INSTALL_TYPE="_OSInstall._tcp"
  74 Bootdir="/tftpboot"
  75 
  76 # Settings for client specific properties, to be passed via grub menu
  77 #
  78 BARGLIST=""
  79 
  80 # import common functions
  81 #
  82 . ${DIRNAME}/installadm-common
  83 
  84 
  85 # usage
  86 #
  87 # Purpose : Print the usage message in the event the user
  88 #           has input illegal command line parameters and
  89 #           then exit
  90 #
  91 # Arguments : 
  92 #   none
  93 #
  94 usage () {
  95         echo "Usage: $0 [-b <property>=<value>,...]"
  96         echo "\t\t-e <macaddr> -t <imagepath> -n <svcname>"
  97         
  98         exit 1
  99 }
 100 
 101 abort()
 102 {
 103         echo "${myname}: Aborted"
 104         exit 1
 105 }
 106 
 107 
 108 #
 109 # MAIN - Program
 110 #
 111 
 112 myname=`basename $0`
 113 ID=`id`
 114 USER=`expr "${ID}" : 'uid=\([^(]*\).*'`
 115 
 116 unset BOOT_FILE IMAGE_PATH IMAGE_SERVER MAC_ADDR
 117 unset SERVER SERVICE_NAME
 118 
 119 trap abort $SIGHUP $SIGINT $SIGQUIT $SIGTERM
 120 
 121 # Verify user ID before proceeding - must be root
 122 #
 123 if [ "${USER}" != "0" ]; then
 124         echo "You must be root to run $0"
 125         exit 1
 126 fi
 127 
 128 
 129 # Get SERVER info
 130 #
 131 SERVER_IP=`get_server_ip`
 132 if [ -z $SERVER_IP ] ; then
 133         echo "Failed to get server's IP address."
 134         exit 1
 135 fi
 136 
 137 # Parse the command line options.
 138 #
 139 while [ "$1"x != "x" ]; do
 140     case $1 in
 141     -e) MAC_ADDR="$2";
 142         if [ "X$MAC_ADDR" = "X" ]; then
 143             usage ;
 144         fi
 145 
 146         fnum=`echo "${MAC_ADDR}" | awk 'BEGIN { FS = ":" } { print NF } ' `
 147         if [ $fnum != 6 ]; then
 148                 echo "${myname}: malformed MAC address: $MAC_ADDR"
 149                 exit 1
 150         fi
 151 
 152         MAC_ADDR=`expr $MAC_ADDR : '\([0-9a-fA-F][0-9a-fA-F]*\:[0-9a-fA-F][0-9a-fA-F]*\:[0-9a-fA-F][0-9a-fA-F]*\:[0-9a-fA-F][0-9a-fA-F]*\:[0-9a-fA-F][0-9a-fA-F]*\:[0-9a-fA-F][0-9a-fA-F]*\)'`
 153 
 154         if [ ! "${MAC_ADDR}" ] ; then
 155                 echo "${myname}: malformed MAC address:  $2"
 156                 exit 1
 157         fi
 158         shift 2;;
 159     -n) SERVICE_NAME=$2
 160         if [ ! "$SERVICE_NAME" ]; then
 161             usage ;
 162         fi
 163         shift 2;;
 164 
 165     # Accept value for -t as either <server:/path> or </path>.
 166     #
 167     -t) if [ ! "$2" ]; then
 168                 usage;
 169         fi
 170         IMAGE_SERVER=`expr $2 : '\(.*\):.*'`
 171         if [ -n "${IMAGE_SERVER}" ]; then
 172                 IMAGE_PATH=`expr $2 : '.*:\(.*\)'`
 173         else
 174                 # no server provided, just get path
 175                 IMAGE_PATH=$2
 176         fi
 177         if [ ! "$IMAGE_PATH" ]; then
 178                 echo "${myname}: Invalid image pathname"
 179             usage ;
 180         fi
 181         shift 2;;
 182     -f) BOOT_FILE=$2
 183         if [ ! "$BOOT_FILE" ] ; then
 184             usage ;
 185         fi
 186         shift 2;;
 187 
 188     # -b option is used to introduce changes in a client,
 189     # e.g. console=ttya
 190     #
 191     -b) BARGLIST="$BARGLIST"$2","
 192         shift 2;;
 193 
 194     -*) # -anything else is an unknown argument
 195         usage ;
 196         ;;
 197     *)  # all else is spurious
 198         usage ;
 199         ;;
 200     esac
 201 done
 202 
 203 if [ -z "${MAC_ADDR}" -o -z "${IMAGE_PATH}" -o -z "${SERVICE_NAME}" ]; then
 204         echo "${myname}: Missing one or more required options."
 205         usage
 206 fi 
 207 
 208 # If IMAGE_SERVER is passed in, check that it is equal to the local system
 209 # since we don't yet support a remote system being the image server.
 210 #
 211 if [ -n "${IMAGE_SERVER}" ]; then
 212         IMAGE_IP=`get_host_ip ${IMAGE_SERVER}`
 213         if [ -z $IMAGE_IP ] ; then
 214                 echo "${myname}: Failed to get IP address for ${IMAGE_SERVER}"
 215                 exit 1
 216         fi
 217 
 218         if [ "${IMAGE_IP}" != "${SERVER_IP}" ]; then
 219             echo "${myname}: Remote image server is not supported at this time."
 220             exit 1
 221         fi
 222 fi
 223 
 224 # Verify that IMAGE_PATH is a valid directory
 225 #
 226 if [ ! -d ${IMAGE_PATH} ]; then
 227     echo "${myname}: Install image directory ${IMAGE_PATH} does not exist."
 228     exit 1
 229 fi
 230 
 231 # Verify valid image
 232 #
 233 if [ ! -f ${IMAGE_PATH}/solaris.zlib ]; then
 234         echo "${myname}: ${IMAGE_PATH}/solaris.zlib does not exist. " \
 235             "The specified image is not an OpenSolaris image."
 236         exit 1
 237 fi
 238 
 239 
 240 # Determine if image is sparc or x86
 241 #
 242 IMAGE_TYPE=`get_image_type ${IMAGE_PATH}`
 243 
 244 # For sparc, make sure the user hasn't specified a boot file via
 245 # the "-f" option. If they have, the BOOT_FILE variable will be set.
 246 #
 247 if [ "${IMAGE_TYPE}" = "${SPARC_IMAGE}" ]; then
 248         if [ "X$BOOT_FILE" != "X" ] ; then
 249             echo "${myname}: \"-f\" is an invalid option for SPARC"
 250             exit 1
 251         fi
 252 fi
 253 
 254 # Verify that service corresponding to SERVICE_NAME exists
 255 #
 256 ${DIRNAME}/setup-service lookup ${SERVICE_NAME} ${INSTALL_TYPE} local
 257 if [ $? -ne 0 ] ; then
 258         echo "${myname}: Service does not exist: ${SERVICE_NAME}"
 259         exit 1
 260 fi
 261 
 262 
 263 # Convert the Ethernet address to DHCP "default client-ID" form:
 264 #    uppercase hex, preceded by the hardware
 265 #    address type ("01" for ethernet)
 266 #
 267 DHCP_CLIENT_ID=01`echo "${MAC_ADDR}" | ${TR} '[a-z]' '[A-Z]' |
 268     awk -F: '
 269         {
 270             for (i = 1; i <= 6 ; i++)
 271                 if (length($i) == 1) {
 272                     printf("0%s", $i)
 273                 } else {
 274                     printf("%s", $i);
 275                 }
 276         }'`
 277 
 278 
 279 # Perform x86/sparc specific setup activities
 280 #
 281 if [ "${IMAGE_TYPE}" = "${X86_IMAGE}" ]; then
 282         echo "Setting up X86 client..." 
 283         if [ "${BARGLIST}" = "" ]; then
 284                 # Set to null as a placeholder in the argument list
 285                 BARGLIST="null"
 286         fi
 287 
 288         #
 289         # pass service location as "unknown" - it will be 
 290         # determined later when creating configuration file
 291         #
 292         ${DIRNAME}/setup-tftp-links client ${SERVICE_NAME} \
 293             ${SERVICE_ADDRESS_UNKNOWN} ${IMAGE_PATH} ${DHCP_CLIENT_ID} \
 294             ${BARGLIST} ${BOOT_FILE}
 295         status=$?
 296         if [ $status -ne 0 ]; then
 297                 echo "${myname}: Unable to setup x86 client"
 298                 exit 1
 299         fi
 300 
 301         # Set value of DHCP_BOOT_FILE.
 302         DHCP_BOOT_FILE=${DHCP_CLIENT_ID}
 303         if [ "X${BOOT_FILE}" != "X" ] ; then
 304             DHCP_BOOT_FILE=${BOOT_FILE}
 305         fi
 306         dhcptype="x86"
 307 else
 308         echo "Setting up SPARC client..." 
 309         # For sparc, set value of DHCP_BOOT_FILE and setup wanboot.conf file.
 310         #
 311         DHCP_BOOT_FILE="http://${SERVER_IP}:${HTTP_PORT}/${CGIBIN_WANBOOTCGI}"
 312         ${DIRNAME}/setup-sparc client ${DHCP_CLIENT_ID} ${IMAGE_PATH}
 313         status=$?
 314         if [ $status -ne 0 ]; then
 315                 echo "${myname}: Unable to setup SPARC client"
 316                 exit 1
 317         fi
 318         dhcptype="sparc"
 319 fi
 320 
 321 
 322 # Try to update the DHCP server automatically. If not possible,
 323 # then tell the user how to define the DHCP macro.
 324 #
 325 ${DIRNAME}/setup-dhcp client ${dhcptype} ${SERVER_IP} ${DHCP_CLIENT_ID} \
 326     ${DHCP_BOOT_FILE}
 327 
 328 status=$?
 329 
 330 # Print nothing if setup-dhcp returns non-zero. setup-dhcp takes care of
 331 # providing instructions for the user in that case.
 332 #
 333 if [ $status -eq 0 ]; then
 334         echo "Enabled network boot by adding a macro named ${DHCP_CLIENT_ID}"
 335         echo "to DHCP server with:"
 336         echo "  Boot server IP     (BootSrvA) : ${SERVER_IP}"
 337         echo "  Boot file          (BootFile) : ${DHCP_BOOT_FILE}"
 338 fi
 339 
 340 exit 0