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