Print this page
PSARC 2008/766 native zones p2v
6667924 physical to virtual utility for native zones
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/brand/lx/zone/lx_install.ksh
+++ new/usr/src/lib/brand/lx/zone/lx_install.ksh
1 1 #!/bin/ksh -p
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22 #
23 23 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 # Use is subject to license terms.
25 25 #
26 26
27 27 # Restrict executables to /bin, /usr/bin, /usr/sbin and /usr/sfw/bin
28 28 PATH=/bin:/usr/bin:/usr/sbin:/usr/sfw/bin
29 29
30 30 export PATH
31 31 umask 022
32 32
33 33 # Setup i18n output
34 34 TEXTDOMAIN="SUNW_OST_OSCMD"
35 35 export TEXTDOMAIN
36 36
37 37 # Log passed arguments to file descriptor 2
38 38 log()
39 39 {
40 40 [[ -n $logfile ]] && echo "$@" >&2
41 41 }
42 42
43 43 #
44 44 # Send the provided printf()-style arguments to the screen and to the
45 45 # logfile.
46 46 #
47 47 screenlog()
48 48 {
49 49 typeset fmt="$1"
50 50 shift
51 51
52 52 printf "$fmt\n" "$@"
53 53 [[ -n $logfile ]] && printf "$fmt\n" "$@" >&2
54 54 }
55 55
56 56 # Print and log provided text if the shell variable "verbose_mode" is set
57 57 verbose()
58 58 {
59 59 [[ -n $verbose_mode ]] && echo "$@"
60 60 [[ -n $logfile ]] && [[ -n $verbose_mode ]] && echo "$@" >&2
61 61 }
62 62
63 63 unsupported_cpu=\
64 64 $(gettext "ERROR: Cannot install branded zone: processor must be %s-compatible")
65 65
66 66 cmd_not_found=$(gettext "Required command '%s' cannot be found!")
67 67 cmd_not_exec=$(gettext "Required command '%s' not executable!")
68 68 zone_initfail=$(gettext "Attempt to initialize zone '%s' FAILED.")
69 69 path_abs=$(gettext "Pathname specified to -d '%s' must be absolute.")
70 70
71 71 cmd_h=$(gettext "%s -z <zone name> %s -h")
72 72 cmd_full=\
73 73 $(gettext "%s -z <zone name> %s [-v | -s] [-d <dir>|<device>] [<cluster> ... ]")
74 74
75 75 both_modes=$(gettext "%s: error: cannot select both silent and verbose modes")
76 76
77 77 not_found=$(gettext "%s: error: file or directory not found.")
|
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
78 78
79 79 wrong_type=\
80 80 $(gettext "%s: error: must be a gzip, bzip2, .Z or uncompressed tar archive.")
81 81
82 82 not_readable=$(gettext "Cannot read file '%s'")
83 83
84 84 no_install=$(gettext "Could not create install directory '%s'")
85 85 no_log=$(gettext "Could not create log directory '%s'")
86 86 no_logfile=$(gettext "Could not create log file '%s'")
87 87
88 +root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
89 +
88 90 install_zone=$(gettext "Installing zone '%s' at root directory '%s'")
89 91 install_from=$(gettext "from archive '%s'")
90 92
91 93 install_fail=$(gettext "Installation of zone '%s' FAILED.")
92 94 see_log=$(gettext "See the log file:\n '%s'\nfor details.")
93 95
94 96 install_abort=$(gettext "Installation of zone '%s' aborted.")
95 97 install_good=$(gettext "Installation of zone '%s' completed successfully.")
96 98
97 99 # Check if commands passed in exist and are executable.
98 100 check_cmd()
99 101 {
100 102 for cmd in "$@"; do
101 103 if [[ ! -f $cmd ]]; then
102 104 screenlog "$cmd_not_found" "$cmd"
103 105 screenlog "$install_abort" "$zonename"
104 106 exit $ZONE_SUBPROC_NOTCOMPLETE
105 107 fi
106 108
107 109 if [[ ! -x $cmd ]]; then
108 110 screenlog "$cmd_not_exec" "$cmd"
109 111 screenlog "$install_abort" "$zonename"
110 112 exit $ZONE_SUBPROC_NOTCOMPLETE
111 113 fi
112 114 done
113 115 }
114 116
115 117 # Post process as tarball-installed zone for use by BrandZ.
116 118 init_tarzone()
117 119 {
118 120 typeset rootdir="$1"
119 121
120 122 if ! $branddir/lx_init_zone "$rootdir"; then
121 123 screenlog "$zone_initfail" "$zonename"
122 124 return 1
123 125 fi
124 126 }
125 127
126 128 # Clean up on interrupt
127 129 trap_cleanup()
128 130 {
129 131 msg=$(gettext "Installation cancelled due to interrupt.")
130 132
131 133 screenlog "$msg"
132 134 exit $int_code
133 135 }
134 136
135 137 #
136 138 # Output the usage message.
137 139 #
138 140 # This is done this way due to limitations in the way gettext strings are
139 141 # extracted from shell scripts and processed. Use of this somewhat awkward
140 142 # syntax allows us to produce longer lines of text than otherwise would be
141 143 # possible without wrapping lines across more than one line of code.
142 144 #
143 145 usage()
144 146 {
145 147 int_code=$ZONE_SUBPROC_USAGE
146 148
147 149 echo $(gettext "Usage:")
148 150 printf " $cmd_h\n" "zoneadm" "install"
149 151 printf " $cmd_full\n" "zoneadm" "install"
150 152
151 153 echo
152 154
153 155 echo $(gettext "The installer will attempt to use the default system") \
154 156 $(gettext "removable disc device if <archive dir> is not") \
155 157 $(gettext "specified.") | fmt -80
156 158
157 159 echo
158 160
159 161 echo $(gettext "<cluster> specifies which package cluster you wish") \
160 162 $(gettext "to install.") | fmt -80
161 163
162 164 echo
163 165 echo $(gettext "The 'desktop' cluster will be installed by default.")
164 166 echo
165 167 echo $(gettext "The available clusters are:")
166 168 echo " + core"
167 169 echo " + server"
168 170 echo " + desktop"
169 171 echo " + development"
170 172 echo " + all"
171 173 echo
172 174
173 175 echo $(gettext "Each cluster includes all of the clusters preceding") \
174 176 $(gettext "it, so the 'server' cluster includes the 'core'") \
175 177 $(gettext "cluster, the 'desktop' cluster includes the 'core'") \
176 178 $(gettext "and 'server' clusters, and so on.") | fmt -80
177 179
178 180 echo
179 181 echo $(gettext "Examples")
180 182 echo "========"
181 183
182 184 echo $(gettext "Example 1: Install a base Linux system from CDs or a") \
183 185 $(gettext "DVD using the system default removable disc device:") |
184 186 fmt -80
185 187
186 188 echo
187 189 echo " # zoneadm -z myzone install"
188 190 echo
189 191
190 192 echo $(gettext "Example 2: Install the 'server' cluster from CDs or") \
191 193 $(gettext "a DVD via an alternative removable disc device:") |
192 194 fmt -80
193 195
194 196 echo
195 197 echo " # zoneadm -z myzone install -d /cdrom/cdrom1 server"
196 198 echo
197 199
198 200 echo $(gettext "Example 3: Install the desktop Linux environment") \
199 201 $(gettext "from an ISO image made available as '/dev/lofi/1' by") \
200 202 $(gettext "use of lofiadm(1M):") | fmt -80
201 203
202 204 echo
203 205 echo " # zoneadm -z myzone install -d /dev/lofi/1 desktop"
204 206 echo
205 207
206 208 echo $(gettext "Example 4: Install the entire Linux environment from") \
207 209 $(gettext "ISO images located in the directory") \
208 210 "'/export/centos_3.8/isos':" | fmt -80
209 211
210 212 echo
211 213 echo " # zoneadm -z myzone install -d /export/centos_3.8/isos all"
212 214 echo
213 215
214 216 echo $(gettext "Example 5: Install from a compressed tar archive of") \
215 217 $(gettext "an existing Linux installation (a tar ball) with") \
216 218 $(gettext "verbose output regarding the progress of the") \
217 219 $(gettext "installation:") | fmt -80
218 220
219 221 echo
220 222 echo " # zoneadm -z myzone install -v -d /tmp/linux_full.tar.gz"
221 223 echo
222 224
223 225 echo $(gettext "Example 6: Install from a compressed tar archive of") \
224 226 $(gettext "an existing Linux installation (a tar ball) with NO") \
225 227 $(gettext "output regarding the progress of the installation") \
226 228 $(gettext "(silent mode.)") | fmt -80
227 229
228 230 echo
229 231
230 232 echo $(gettext "NOTE: Silent mode is only recommended for use by") \
231 233 $(gettext "shell scripts and other non-interactive programs:") |
232 234 fmt -80
233 235
234 236 echo
235 237 echo " # zoneadm -z myzone install -d /tmp/linux_full.tar.gz -s"
236 238 echo
237 239
238 240 exit $int_code
239 241 }
240 242
241 243 #
242 244 # The main body of the script starts here.
243 245 #
244 246 # This script should never be called directly by a user but rather should
245 247 # only be called by zoneadm to install a BrandZ Linux zone.
246 248 #
247 249
248 250 #
249 251 # Exit values used by the script, as #defined in <sys/zone.h>
250 252 #
251 253 # ZONE_SUBPROC_OK
252 254 # ===============
253 255 # Installation was successful
254 256 #
255 257 # ZONE_SUBPROC_USAGE
256 258 # ==================
257 259 # Improper arguments were passed, so print a usage message before exiting
258 260 #
259 261 # ZONE_SUBPROC_NOTCOMPLETE
260 262 # ========================
261 263 # Installation did not complete, but another installation attempt can be
262 264 # made without an uninstall
263 265 #
264 266 # ZONE_SUBPROC_FATAL
265 267 # ==================
266 268 # Installation failed and an uninstall will be required before another
267 269 # install can be attempted
268 270 #
269 271 ZONE_SUBPROC_OK=0
270 272 ZONE_SUBPROC_USAGE=253
271 273 ZONE_SUBPROC_NOTCOMPLETE=254
272 274 ZONE_SUBPROC_FATAL=255
273 275
274 276 #
275 277 # An unspecified exit or interrupt should exit with ZONE_SUBPROC_NOTCOMPLETE,
276 278 # meaning a user will not need to do an uninstall before attempting another
277 279 # install.
278 280 #
279 281 int_code=$ZONE_SUBPROC_NOTCOMPLETE
280 282
281 283 trap trap_cleanup INT
282 284
283 285 # If we weren't passed at least two arguments, exit now.
284 286 [[ $# -lt 2 ]] && usage
285 287
286 288 #
287 289 # This script is always started with a full path so we can extract the
288 290 # brand directory name here.
289 291 #
290 292 branddir=$(dirname "$0")
291 293 zonename="$1"
292 294 zoneroot="$2"
293 295
294 296 install_root="$zoneroot/root"
295 297 logdir="$install_root/var/log"
296 298
297 299 shift; shift # remove zonename and zoneroot from arguments array
298 300
299 301 unset gtaropts
300 302 unset install_opts
301 303 unset install_src
302 304 unset msg
303 305 unset silent_mode
304 306 unset verbose_mode
305 307
306 308 while getopts "d:hsvX" opt
307 309 do
308 310 case "$opt" in
309 311 h) usage;;
310 312 s) silent_mode=1;;
311 313 v) verbose_mode=1;;
312 314 d) install_src="$OPTARG" ;;
313 315 X) install_opts="$install_opts -x" ;;
314 316 *) usage;;
315 317 esac
316 318 done
317 319 shift OPTIND-1
318 320
319 321 # Providing more than one passed argument generates a usage message
320 322 if [[ $# -gt 1 ]]; then
321 323 msg=$(gettext "ERROR: Too many arguments provided:")
322 324
323 325 screenlog "$msg"
324 326 screenlog " \"%s\"" "$@"
325 327 screenlog ""
326 328 usage
327 329 fi
328 330
329 331 # Validate any free-form arguments
330 332 if [[ $# -eq 1 && "$1" != "core" && "$1" != "server" && "$1" != "desktop" &&
331 333 "$1" != "development" && "$1" != "all" ]]; then
332 334 msg=$(gettext "ERROR: Unknown cluster name specified: %s")
333 335
334 336 screenlog "$msg" "\"$1\""
335 337 screenlog ""
336 338 usage
337 339 fi
338 340
339 341 # The install can't be both verbose AND silent...
340 342 if [[ -n $silent_mode && -n $verbose_mode ]]; then
341 343 screenlog "$both_modes" "zoneadm install"
342 344 screenlog ""
343 345 usage
344 346 fi
345 347
346 348 #
347 349 # Validate that we're running on a i686-compatible CPU; abort the zone
348 350 # installation now if we're not.
349 351 #
350 352 procinfo=$(LC_ALL=C psrinfo -vp | grep family)
351 353
352 354 #
353 355 # All x86 processors in CPUID families 6 or 15 should be i686-compatible,
354 356 # assuming third party processor vendors follow AMD and Intel's lead.
355 357 #
356 358 if [[ "$procinfo" != *" x86 "* ]] ||
357 359 [[ "$procinfo" != *" family 6 "* && "$procinfo" != *" family 15 "* ]] ; then
358 360 screenlog "$unsupported_cpu" "i686"
359 361 exit $int_code
360 362 fi
361 363
362 364 if [[ -n $install_src ]]; then
363 365 #
364 366 # Validate $install_src.
365 367 #
366 368 # If install_src is a directory, assume it contains ISO images to
367 369 # install from, otherwise treat the argument as if it points to a tar
368 370 # ball file.
369 371 #
370 372 if [[ "`echo $install_src | cut -c 1`" != "/" ]]; then
371 373 screenlog "$path_abs" "$install_src"
372 374 exit $int_code
373 375 fi
374 376
375 377 if [[ ! -a "$install_src" ]]; then
376 378 screenlog "$not_found" "$install_src"
377 379 screenlog "$install_abort" "$zonename"
378 380 exit $int_code
379 381 fi
380 382
381 383 if [[ ! -r "$install_src" ]]; then
382 384 screenlog "$not_readable" "$install_src"
383 385 screenlog "$install_abort" "$zonename"
384 386 exit $int_code
385 387 fi
386 388
387 389 #
388 390 # If install_src is a block device, a directory, a possible device
389 391 # created via lofiadm(1M), or the directory used by a standard volume
390 392 # management daemon, pass it on to the secondary install script.
391 393 #
392 394 # Otherwise, validate the passed filename to prepare for a tar ball
393 395 # install.
394 396 #
395 397 if [[ ! -b "$install_src" && ! -d "$install_src" &&
396 398 "$install_src" != /dev/lofi/* && "$install_src" != /cdrom/* &&
397 399 "$install_src" != /media/* ]]; then
398 400 if [[ ! -f "$install_src" ]]; then
399 401 screenlog "$wrong_type" "$install_src"
400 402 screenlog "$install_abort" "$zonename"
401 403 exit $int_code
402 404 fi
403 405
404 406 filetype=`{ LC_ALL=C file $install_src |
405 407 awk '{print $2}' ; } 2>/dev/null`
406 408
407 409 if [[ "$filetype" = "gzip" ]]; then
408 410 verbose "\"$install_src\": \"gzip\" archive"
409 411 gtaropts="-xz"
410 412 elif [[ "$filetype" = "bzip2" ]]; then
411 413 verbose "\"$install_src\": \"bzip2\" archive"
412 414 gtaropts="-xj"
413 415 elif [[ "$filetype" = "compressed" ]]; then
414 416 verbose "\"$install_src\": Lempel-Ziv" \
415 417 "compressed (\".Z\") archive."
416 418 gtaropts="-xZ"
417 419 elif [[ "$filetype" = "USTAR" ]]; then
418 420 verbose "\"$install_src\":" \
419 421 "uncompressed (\"tar\") archive."
420 422 gtaropts="-x"
421 423 else
422 424 screenlog "$wrong_type" "$install_src"
423 425 screenlog "$install_abort" "$zonename"
424 426 exit $int_code
425 427 fi
426 428 fi
427 429 fi
428 430
429 431 #
430 432 # Start silent operation and pass the flag to prepare pass the flag to
431 433 # the ISO installer, if needed.
432 434 #
433 435 if [[ -n $silent_mode ]]
434 436 then
435 437 exec 1>/dev/null
436 438 install_opts="$install_opts -s"
437 439 fi
438 440
439 441 #
440 442 # If verbose mode was specified, pass the verbose flag to lx_distro_install
441 443 # for ISO or disc installations and to gtar for tarball-based installs.
442 444 #
443 445 if [[ -n $verbose_mode ]]
444 446 then
445 447 echo $(gettext "Verbose output mode enabled.")
446 448 install_opts="$install_opts -v"
447 449 [[ -n $gtaropts ]] && gtaropts="${gtaropts}v"
448 450 fi
449 451
|
↓ open down ↓ |
352 lines elided |
↑ open up ↑ |
450 452 [[ -n $gtaropts ]] && gtaropts="${gtaropts}f"
451 453
452 454 if [[ ! -d "$install_root" ]]
453 455 then
454 456 if ! mkdir -p "$install_root" 2>/dev/null; then
455 457 screenlog "$no_install" "$install_root"
456 458 exit $int_code
457 459 fi
458 460 fi
459 461
462 +#
463 +# Check for a non-empty root.
464 +#
465 +cnt=`ls $install_root | wc -l`
466 +if [ $cnt -ne 0 ]; then
467 + screenlog "$root_full" "$install_root"
468 + exit $int_code
469 +fi
470 +
460 471 if [[ ! -d "$logdir" ]]
461 472 then
462 473 if ! mkdir -p "$logdir" 2>/dev/null; then
463 474 screenlog "$no_log" "$logdir"
464 475 exit $int_code
465 476 fi
466 477 fi
467 478
468 479 logfile="${logdir}/$zonename.install.$$.log"
469 480
470 481 if ! > $logfile; then
471 482 screenlog "$no_logfile" "$logfile"
472 483 exit $int_code
473 484 fi
474 485
475 486 # Redirect stderr to the log file to automatically log any error messages
476 487 exec 2>>"$logfile"
477 488
478 489 #
479 490 # From here on out, an unspecified exit or interrupt should exit with
480 491 # ZONE_SUBPROC_FATAL, meaning a user will need to do an uninstall before
481 492 # attempting another install, as we've modified the directories we were going
482 493 # to install to in some way.
483 494 #
484 495 int_code=$ZONE_SUBPROC_FATAL
485 496
486 497 log "Installation started for zone \"$zonename\" `/usr/bin/date`"
487 498
488 499 if [[ -n $gtaropts ]]; then
489 500 check_cmd /usr/sfw/bin/gtar $branddir/lx_init_zone
490 501
491 502 screenlog "$install_zone" "$zonename" "$zoneroot"
492 503 screenlog "$install_from" "$install_src"
493 504 echo
494 505 echo $(gettext "This process may take several minutes.")
495 506 echo
496 507
497 508 if ! ( cd "$install_root" && gtar "$gtaropts" "$install_src" ) ; then
498 509 log "Error: extraction from tar archive failed."
499 510 else
500 511 if ! [[ -d "${install_root}/bin" &&
501 512 -d "${install_root}/sbin" ]]; then
502 513 log "Error: improper or incomplete tar archive."
503 514 else
504 515 $branddir/lx_init_zone "$install_root" &&
505 516 init_tarzone "$install_root"
506 517
507 518 #
508 519 # Emit the same code from here whether we're
509 520 # interrupted or exiting normally.
510 521 #
511 522 int_code=$?
512 523 fi
513 524 fi
514 525
515 526 if [[ $int_code -eq ZONE_SUBPROC_OK ]]; then
516 527 log "Tar install completed for zone '$zonename' `date`."
517 528 else
518 529 log "Tar install failed for zone \"$zonename\" `date`."
519 530
520 531 fi
521 532 else
522 533 check_cmd $branddir/lx_distro_install
523 534
524 535 $branddir/lx_distro_install -z "$zonename" -r "$zoneroot" \
525 536 -d "$install_src" -l "$logfile" $install_opts "$@"
526 537
527 538 #
528 539 # Emit the same code from here whether we're interrupted or exiting
529 540 # normally.
530 541 #
531 542 int_code=$?
532 543
533 544 [[ $int_code -eq $ZONE_SUBPROC_USAGE ]] && usage
534 545 fi
535 546
536 547 if [[ $int_code -ne $ZONE_SUBPROC_OK ]]; then
537 548 screenlog ""
538 549 screenlog "$install_fail" "$zonename"
539 550 screenlog ""
540 551
541 552 #
542 553 # Only make a reference to the log file if one will exist after
543 554 # zoneadm exits.
544 555 #
545 556 [[ $int_code -ne $ZONE_SUBPROC_NOTCOMPLETE ]] &&
546 557 screenlog "$see_log" "$logfile"
547 558
548 559 exit $int_code
549 560 fi
550 561
551 562 #
552 563 # After the install completes, we've likely moved a new copy of the logfile into
553 564 # place atop the logfile we WERE writing to, so if we don't reopen the logfile
554 565 # here the shell will continue writing to the old logfile's inode, meaning we
555 566 # would lose all log information from this point on.
556 567 #
557 568 exec 2>>"$logfile"
558 569
559 570 screenlog ""
560 571 screenlog "$install_good" "$zonename"
561 572 screenlog ""
562 573
563 574 echo $(gettext "Details saved to log file:")
564 575 echo " \"$logfile\""
565 576 echo
566 577
567 578 exit $ZONE_SUBPROC_OK
|
↓ open down ↓ |
98 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX