PSARC 2008/766 native zones p2v
6667924 physical to virtual utility for native zones
--- a/usr/src/Targetdirs Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/Targetdirs Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -78,6 +78,8 @@
/devices \
/devices/pseudo \
/etc \
+ /etc/brand \
+ /etc/brand/native \
/etc/certs \
/etc/cron.d \
/etc/crypto \
@@ -259,6 +261,7 @@
/usr/lib/abi \
/usr/lib/brand \
/usr/lib/brand/native \
+ /usr/lib/brand/shared \
/usr/lib/brand/sn1 \
/usr/lib/class \
/usr/lib/class/FSS \
--- a/usr/src/cmd/zoneadm/zoneadm.c Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/cmd/zoneadm/zoneadm.c Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -102,7 +102,6 @@
static zone_entry_t *zents;
static size_t nzents;
-static boolean_t is_native_zone = B_TRUE;
#define LOOPBACK_IF "lo0"
#define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
@@ -1087,10 +1086,6 @@
return (Z_ERR);
}
if ((res = stat(rootpath, &stbuf)) == 0) {
- struct dirent *dp;
- DIR *dirp;
- boolean_t empty = B_TRUE;
-
if (zonecfg_detached(rpath)) {
(void) fprintf(stderr,
gettext("Cannot %s detached "
@@ -1119,32 +1114,6 @@
"0755.\n"), rootpath);
return (Z_ERR);
}
-
- if ((dirp = opendir(rootpath)) == NULL) {
- (void) fprintf(stderr, gettext("Could not "
- "open rootpath %s\n"), rootpath);
- return (Z_ERR);
- }
-
- /* Verify that the dir is empty. */
- while ((dp = readdir(dirp)) != NULL) {
- if (strcmp(dp->d_name, ".") == 0 ||
- strcmp(dp->d_name, "..") == 0)
- continue;
-
- empty = B_FALSE;
- break;
- }
- (void) closedir(dirp);
-
- if (!empty) {
- (void) fprintf(stderr, gettext("Rootpath %s "
- "exists and contains data; remove or move "
- "aside prior to %s.\n"), rootpath,
- cmd_to_str(cmd_num));
- return (Z_ERR);
- }
-
}
}
@@ -1713,6 +1682,17 @@
}
break;
case CMD_ATTACH:
+ if (state == ZONE_STATE_INSTALLED) {
+ zerror(gettext("is already %s."),
+ zone_state_str(ZONE_STATE_INSTALLED));
+ return (Z_ERR);
+ } else if (state == ZONE_STATE_INCOMPLETE && !force) {
+ zerror(gettext("zone is %s; %s required."),
+ zone_state_str(ZONE_STATE_INCOMPLETE),
+ cmd_to_str(CMD_UNINSTALL));
+ return (Z_ERR);
+ }
+ break;
case CMD_CLONE:
case CMD_INSTALL:
if (state == ZONE_STATE_INSTALLED) {
@@ -1735,15 +1715,11 @@
if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
force)
min_state = ZONE_STATE_INCOMPLETE;
+ else if (cmd_num == CMD_MARK)
+ min_state = ZONE_STATE_CONFIGURED;
else
min_state = ZONE_STATE_INSTALLED;
- if (force && cmd_num == CMD_BOOT && is_native_zone) {
- zerror(gettext("Only branded zones may be "
- "force-booted."));
- return (Z_ERR);
- }
-
if (state < min_state) {
zerror(gettext("must be %s before %s."),
zone_state_str(min_state),
@@ -4625,6 +4601,10 @@
int manifest_pos;
brand_handle_t bh = NULL;
int status;
+ int last_index = 0;
+ int offset;
+ char *up;
+ boolean_t forced_update = B_FALSE;
if (zonecfg_in_alt_root()) {
zerror(gettext("cannot attach zone in alternate root"));
@@ -4634,7 +4614,7 @@
/* Check the argv string for args we handle internally */
optind = 0;
opterr = 0;
- while ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
+ while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
switch (arg) {
case '?':
if (optopt == '?') {
@@ -4651,10 +4631,25 @@
manifest_path = optarg;
manifest_pos = optind - 1;
break;
+ case 'U':
+ /*
+ * Undocumented 'force update' option for p2v update on
+ * attach when zone is in the incomplete state. Change
+ * the option back to 'u' and set forced_update flag.
+ */
+ if (optind == last_index)
+ offset = optind;
+ else
+ offset = optind - 1;
+ if ((up = index(argv[offset], 'U')) != NULL)
+ *up = 'u';
+ forced_update = B_TRUE;
+ break;
default:
/* Ignore unknown options - may be brand specific. */
break;
}
+ last_index = optind;
}
if (brand_help) {
@@ -4676,7 +4671,7 @@
if (execute) {
if (!brand_help) {
if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
- B_TRUE, B_FALSE) != Z_OK)
+ B_TRUE, forced_update) != Z_OK)
return (Z_ERR);
if (verify_details(CMD_ATTACH, argv) != Z_OK)
return (Z_ERR);
@@ -4749,14 +4744,14 @@
*/
if (cmdbuf[0] != '\0') {
/* Run the attach hook */
- status = do_subproc_interactive(cmdbuf);
+ status = do_subproc(cmdbuf);
if ((status = subproc_status(gettext("brand-specific "
"attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
if (status == ZONE_SUBPROC_USAGE && !brand_help)
sub_usage(SHELP_ATTACH, CMD_ATTACH);
if (execute && !brand_help) {
- assert(lockfd >= 0);
+ assert(zonecfg_lock_file_held(&lockfd));
zonecfg_release_lock_file(target_zone,
lockfd);
lockfd = -1;
@@ -4799,7 +4794,7 @@
zperror(gettext("could not reset state"), B_TRUE);
}
- assert(lockfd >= 0);
+ assert(zonecfg_lock_file_held(&lockfd));
zonecfg_release_lock_file(target_zone, lockfd);
lockfd = -1;
@@ -5118,10 +5113,38 @@
mark_func(int argc, char *argv[])
{
int err, lockfd;
-
- if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
+ int arg;
+ boolean_t force = B_FALSE;
+ int state;
+
+ optind = 0;
+ opterr = 0;
+ while ((arg = getopt(argc, argv, "F")) != EOF) {
+ switch (arg) {
+ case 'F':
+ force = B_TRUE;
+ break;
+ default:
+ return (Z_USAGE);
+ }
+ }
+
+ if (argc != (optind + 1))
return (Z_USAGE);
- if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
+
+ if (strcmp(argv[optind], "configured") == 0)
+ state = ZONE_STATE_CONFIGURED;
+ else if (strcmp(argv[optind], "incomplete") == 0)
+ state = ZONE_STATE_INCOMPLETE;
+ else if (strcmp(argv[optind], "installed") == 0)
+ state = ZONE_STATE_INSTALLED;
+ else
+ return (Z_USAGE);
+
+ if (state != ZONE_STATE_INCOMPLETE && !force)
+ return (Z_USAGE);
+
+ if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
!= Z_OK)
return (Z_ERR);
@@ -5137,7 +5160,7 @@
return (Z_ERR);
}
- err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
+ err = zone_set_state(target_zone, state);
if (err != Z_OK) {
errno = err;
zperror2(target_zone, gettext("could not set state"));
@@ -5592,7 +5615,6 @@
zerror(gettext("missing or invalid brand"));
exit(Z_ERR);
}
- is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
}
err = parse_and_run(argc - optind, &argv[optind]);
--- a/usr/src/head/libzonecfg.h Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/head/libzonecfg.h Wed Feb 11 09:33:05 2009 -0700
@@ -558,6 +558,7 @@
extern void zonecfg_init_lock_file(const char *, char **);
extern void zonecfg_release_lock_file(const char *, int);
extern int zonecfg_grab_lock_file(const char *, int *);
+extern boolean_t zonecfg_lock_file_held(int *);
extern int zonecfg_ping_zoneadmd(const char *);
extern int zonecfg_call_zoneadmd(const char *, zone_cmd_arg_t *, char *,
boolean_t);
--- a/usr/src/lib/brand/Makefile.brand Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/Makefile.brand Wed Feb 11 09:33:05 2009 -0700
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
include $(SRC)/Makefile.master
@@ -30,10 +29,12 @@
ROOTTEMPLATEDIR= $(ROOT)/etc/zones
ROOTBRANDDIR= $(ROOTDIR)/$(BRAND)
ROOTBRANDDIR64= $(ROOTDIR)/$(BRAND)/$(MACH64)
+ROOTSHAREDDIR= $(ROOTDIR)/shared
ROOTPROGS= $(PROGS:%=$(ROOTBRANDDIR)/%)
ROOTTXTS= $(TXTS:%=$(ROOTBRANDDIR)/%)
ROOTXMLDOCS= $(XMLDOCS:%=$(ROOTBRANDDIR)/%)
+ROOTSHARED= $(SHARED:%=$(ROOTSHAREDDIR)/%)
ROOTTEMPLATES= $(TEMPLATES:%=$(ROOTTEMPLATEDIR)/%)
@@ -45,6 +46,10 @@
$(ROOTXMLDOCS) := OWNER = root
$(ROOTXMLDOCS) := GROUP = bin
+$(ROOTSHARED) := FILEMODE = 444
+$(ROOTSHARED) := OWNER = root
+$(ROOTSHARED) := GROUP = bin
+
$(ROOTTEMPLATEDIR) := FILEMODE = 755
$(ROOTTEMPLATEDIR) := OWNER = root
$(ROOTTEMPLATEDIR) := GROUP = sys
@@ -61,7 +66,7 @@
$(ROOTPROGS) := OWNER = root
$(ROOTPROGS) := GROUP = bin
-$(ROOTBRANDDIR)/% $(ROOTBRANDDIR64)/% $(ROOTTEMPLATEDIR)/%: %
+$(ROOTBRANDDIR)/% $(ROOTBRANDDIR64)/% $(ROOTTEMPLATEDIR)/% $(ROOTSHAREDDIR)/%: %
$(INS.file)
.SUFFIXES: .ksh
--- a/usr/src/lib/brand/lx/zone/lx_install.ksh Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/lx/zone/lx_install.ksh Wed Feb 11 09:33:05 2009 -0700
@@ -85,6 +85,8 @@
no_log=$(gettext "Could not create log directory '%s'")
no_logfile=$(gettext "Could not create log file '%s'")
+root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
+
install_zone=$(gettext "Installing zone '%s' at root directory '%s'")
install_from=$(gettext "from archive '%s'")
@@ -457,6 +459,15 @@
fi
fi
+#
+# Check for a non-empty root.
+#
+cnt=`ls $install_root | wc -l`
+if [ $cnt -ne 0 ]; then
+ screenlog "$root_full" "$install_root"
+ exit $int_code
+fi
+
if [[ ! -d "$logdir" ]]
then
if ! mkdir -p "$logdir" 2>/dev/null; then
--- a/usr/src/lib/brand/native/zone/Makefile Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/Makefile Wed Feb 11 09:33:05 2009 -0700
@@ -20,18 +20,28 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
+
+ETCBRANDDIR= $(ROOT)/etc/brand/native
+ETCUSER= $(USERFILES:%=$(ETCBRANDDIR)/%)
+$(ETCUSER) := FILEMODE = 644
+$(ETCUSER) := OWNER = root
+$(ETCUSER) := GROUP = sys
+
+$(ETCBRANDDIR)/%: %
+ $(INS.file)
PROG= sw_support
BRAND= native
-PROGS= attach_update $(PROG)
-XMLDOCS= config.xml platform.xml
+PROGS= attach_update image_install p2v $(PROG)
+XMLDOCS= config.xml platform.xml smf_disable.lst pkgrm.lst
+USERFILES= smf_disable.conf pkgrm.conf
+SHARED= common.ksh
TEMPLATES= SUNWdefault.xml SUNWblank.xml
-CLOBBERFILES= $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES)
+CLOBBERFILES= $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES) $(ROOTSHARED) \
+ $(ETCUSER)
all: $(PROGS)
@@ -52,7 +62,8 @@
lint: lint_PROG
-install: $(PROGS) $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES)
+install: $(PROGS) $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES) $(ROOTSHARED) \
+ $(ETCUSER)
clean:
-$(RM) $(PROGS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/common.ksh Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,516 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Send the error message to the screen and to the logfile.
+#
+error()
+{
+ typeset fmt="$1"
+ shift
+
+ printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
+ [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
+}
+
+fatal()
+{
+ typeset fmt="$1"
+ shift
+
+ error "$fmt" "$@"
+ exit $EXIT_CODE
+}
+
+#
+# Send the provided printf()-style arguments to the screen and to the logfile.
+#
+log()
+{
+ typeset fmt="$1"
+ shift
+
+ printf "${MSG_PREFIX}${fmt}\n" "$@"
+ [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
+}
+
+#
+# Print provided text to the screen if the shell variable "OPT_V" is set.
+# The text is always sent to the logfile.
+#
+vlog()
+{
+ typeset fmt="$1"
+ shift
+
+ [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
+ [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
+}
+
+# Validate that the directory is safe.
+safe_dir()
+{
+ typeset dir="$1"
+
+ if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
+ fatal "$e_baddir" "$dir"
+ fi
+}
+
+# Only make a copy if we haven't already done so.
+safe_backup()
+{
+ typeset src="$1"
+ typeset dst="$2"
+
+ if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
+ /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
+ fi
+}
+
+# Make a copy even if the destination already exists.
+safe_copy()
+{
+ typeset src="$1"
+ typeset dst="$2"
+
+ if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
+ /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
+ fi
+}
+
+# Move a file
+safe_move()
+{
+ typeset src="$1"
+ typeset dst="$2"
+
+ if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
+ /usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
+ fi
+}
+
+#
+# Read zonecfg ipd and fs entries and save the relevant data, one entry per
+# line.
+# This assumes the properties from the zonecfg output, e.g.:
+# inherit-pkg-dir:
+# dir: /usr
+# fs:
+# dir: /opt
+# special: /opt
+# raw not specified
+# type: lofs
+# options: [noexec,ro,noatime]
+#
+# and it assumes the order of the fs properties as above. This also saves the
+# inherit-pkg-dir patterns into the ipd.{cpio|pax} temporary files for
+# filtering while extracting the image into the zonepath. We have to save the
+# IPD patterns in the appropriate format for filtering with the different
+# archivers and we don't know what format we'll get until after the flash
+# archive is unpacked.
+#
+get_fs_info()
+{
+ zonecfg -z $zonename info inherit-pkg-dir | \
+ nawk -v ipdcpiof=$ipdcpiofile -v ipdpaxf=$ipdpaxfile '{
+ if ($1 == "dir:") {
+ dir=$2;
+ printf("%s lofs %s ro\n", dir, dir);
+
+ if (substr(dir, 1, 1) == "/") {
+ printf("%s\n", substr(dir, 2)) >> ipdcpiof
+ printf("%s/*\n", substr(dir, 2)) >> ipdcpiof
+ } else {
+ printf("%s\n", dir) >> ipdcpiof
+ printf("%s/*\n", dir) >> ipdcpiof
+ }
+
+ if (substr(dir, 1, 1) == "/") {
+ printf("%s ", substr(dir, 2)) >> ipdpaxf
+ } else {
+ printf("%s ", dir) >> ipdpaxf
+ }
+ }
+ }' >> $fstmpfile
+
+ zonecfg -z $zonename info fs | nawk '{
+ if ($1 == "options:") {
+ # Remove brackets.
+ options=substr($2, 2, length($2) - 2);
+ printf("%s %s %s %s\n", dir, type, special, options);
+ } else if ($1 == "dir:") {
+ dir=$2;
+ } else if ($1 == "special:") {
+ special=$2;
+ } else if ($1 == "type:") {
+ type=$2
+ }
+ }' >> $fstmpfile
+}
+
+#
+# Mount zonecfg fs entries into the zonepath.
+#
+mnt_fs()
+{
+ if [ ! -s $fstmpfile ]; then
+ return;
+ fi
+
+ # Sort the fs entries so we can handle nested mounts.
+ sort $fstmpfile | nawk -v zonepath=$zonepath '{
+ if (NF == 4)
+ options="-o " $4;
+ else
+ options=""
+
+ # Create the mount point. Ignore errors since we might have
+ # a nested mount with a pre-existing mount point.
+ cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
+ system(cmd);
+
+ cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
+ zonepath "/root" $1;
+ if (system(cmd) != 0) {
+ printf("command failed: %s\n", cmd);
+ exit 1;
+ }
+ }' >>$LOGFILE
+}
+
+#
+# Unmount zonecfg fs entries from the zonepath.
+#
+umnt_fs()
+{
+ if [ ! -s $fstmpfile ]; then
+ return;
+ fi
+
+ # Reverse sort the fs entries so we can handle nested unmounts.
+ sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
+ cmd="/usr/sbin/umount " zonepath "/root" $1
+ if (system(cmd) != 0) {
+ printf("command failed: %s\n", cmd);
+ }
+ }' >>$LOGFILE
+}
+
+#
+# Determine flar compression style from identification file.
+#
+get_compression()
+{
+ typeset ident=$1
+ typeset line=$(grep "^files_compressed_method=" $ident)
+
+ print ${line##*=}
+}
+
+#
+# Determine flar archive style from identification file.
+#
+get_archiver()
+{
+ typeset ident=$1
+ typeset line=$(grep "^files_archived_method=" $ident)
+
+ print ${line##*=}
+}
+
+#
+# Unpack flar into current directory (which should be zoneroot). The flash
+# archive is standard input. See flash_archive(4) man page.
+#
+# We can't use "flar split" since it will only unpack into a directory called
+# "archive". We need to unpack in place in order to properly handle nested
+# fs mounts within the zone root. This function does the unpacking into the
+# current directory.
+#
+# This code is derived from the gen_split() function in /usr/sbin/flar so
+# we keep the same style as the original.
+#
+install_flar()
+{
+ typeset result
+ typeset archiver_command
+ typeset archiver_arguments
+
+ vlog "cd $ZONEROOT && do_flar < \"$install_archive\""
+
+ # Read cookie
+ read -r input_line
+ if (( $? != 0 )); then
+ log "$not_readable" "$install_media"
+ return 1
+ fi
+ # The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
+ if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
+ log "$not_flar"
+ return 1
+ fi
+
+ while [ true ]
+ do
+ # We should always be at the start of a section here
+ read -r input_line
+ if [[ ${input_line%%=*} != "section_begin" ]]; then
+ log "$bad_flar"
+ return 1
+ fi
+ section_name=${input_line##*=}
+
+ # If we're at the archive, we're done skipping sections.
+ if [[ "$section_name" == "archive" ]]; then
+ break
+ fi
+
+ #
+ # Save identification section to a file so we can determine
+ # how to unpack the archive.
+ #
+ if [[ "$section_name" == "identification" ]]; then
+ /usr/bin/rm -f identification
+ while read -r input_line
+ do
+ if [[ ${input_line%%=*} == \
+ "section_begin" ]]; then
+ /usr/bin/rm -f identification
+ log "$bad_flar"
+ return 1
+ fi
+
+ if [[ $input_line == \
+ "section_end=$section_name" ]]; then
+ break;
+ fi
+ echo $input_line >> identification
+ done
+
+ continue
+ fi
+
+ #
+ # Otherwise skip past this section; read lines until detecting
+ # section_end. According to flash_archive(4) we can have
+ # an arbitrary number of sections but the archive section
+ # must be last.
+ #
+ success=0
+ while read -r input_line
+ do
+ if [[ $input_line == "section_end=$section_name" ]];
+ then
+ success=1
+ break
+ fi
+ # Fail if we miss the end of the section
+ if [[ ${input_line%%=*} == "section_begin" ]]; then
+ /usr/bin/rm -f identification
+ log "$bad_flar"
+ return 1
+ fi
+ done
+ if (( $success == 0 )); then
+ #
+ # If we get here we read to the end of the file before
+ # seeing the end of the section we were reading.
+ #
+ /usr/bin/rm -f identification
+ log "$bad_flar"
+ return 1
+ fi
+ done
+
+ # Get the information needed to unpack the archive.
+ archiver=$(get_archiver identification)
+ if [[ $archiver == "pax" ]]; then
+ # pax archiver specified
+ archiver_command="/usr/bin/pax"
+ if [[ -s $ipdpaxfile ]]; then
+ archiver_arguments="-r -p e -c \
+ $(/usr/bin/cat $ipdpaxfile)"
+ else
+ archiver_arguments="-r -p e"
+ fi
+ elif [[ $archiver == "cpio" || -z $archiver ]]; then
+ # cpio archived specified OR no archiver specified - use default
+ archiver_command="/usr/bin/cpio"
+ archiver_arguments="-icdumfE $ipdcpiofile"
+ else
+ # unknown archiver specified
+ log "$unknown_archiver" $archiver
+ return 1
+ fi
+
+ if [[ ! -x $archiver_command ]]; then
+ /usr/bin/rm -f identification
+ log "$cmd_not_exec" $archiver_command
+ return 1
+ fi
+
+ compression=$(get_compression identification)
+
+ # We're done with the identification file
+ /usr/bin/rm -f identification
+
+ # Extract archive
+ if [[ $compression == "compress" ]]; then
+ /usr/bin/zcat | ppriv -e -s A=all,-sys_devices \
+ $archiver_command $archiver_arguments 2>/dev/null
+ else
+ ppriv -e -s A=all,-sys_devices \
+ $archiver_command $archiver_arguments 2>/dev/null
+ fi
+ result=$?
+
+ (( $result != 0 )) && return 1
+
+ return 0
+}
+
+#
+# Unpack cpio archive into zoneroot.
+#
+install_cpio()
+{
+ stage1=$1
+ archive=$2
+
+ cpioopts="-idmfE $ipdcpiofile"
+
+ vlog "cd \"$ZONEROOT\" && $stage1 \"$archive\" | "
+ vlog "ppriv -e -s A=all,-sys_devices cpio $cpioopts"
+
+ ( cd "$ZONEROOT" && $stage1 "$archive" | \
+ ppriv -e -s A=all,-sys_devices cpio $cpioopts )
+}
+
+#
+# Unpack pax archive into zoneroot.
+#
+install_pax()
+{
+ archive=$1
+
+ if [[ -s $ipdpaxfile ]]; then
+ filtopt="-c $(/usr/bin/cat $ipdpaxfile)"
+ fi
+
+ vlog "cd \"$ZONEROOT\" && "
+ vlog "ppriv -e -s A=all,-sys_devices pax -r -f \"$archive\" $filtopt"
+
+ ( cd "$ZONEROOT" && ppriv -e -s A=all,-sys_devices \
+ pax -r -f "$archive" $filtopt )
+}
+
+#
+# Unpack UFS dump into zoneroot.
+#
+install_ufsdump()
+{
+ archive=$1
+
+ vlog "cd \"$ZONEROOT\" && "
+ vlog "ppriv -e -s A=all,-sys_devices ufsrestore rf \"$archive\""
+
+ #
+ # ufsrestore goes interactive if you ^C it. To prevent that,
+ # we make sure its stdin is not a terminal.
+ # Note that there is no way to filter inherit-pkg-dirs for a full
+ # restore so there will be warnings in the log file.
+ #
+ ( cd "$ZONEROOT" && ppriv -e -s A=all,-sys_devices \
+ ufsrestore rf "$archive" < /dev/null )
+}
+
+#
+# Copy directory hierarchy into zoneroot.
+#
+install_dir()
+{
+ source_dir=$1
+
+ cpioopts="-pdm"
+
+ first=1
+ filt=$(for i in $(cat $ipdpaxfile)
+ do
+ echo $i | egrep -s "/" && continue
+ if [[ $first == 1 ]]; then
+ printf "^%s" $i
+ first=0
+ else
+ printf "|^%s" $i
+ fi
+ done)
+
+ list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
+ flist=$(for i in $list
+ do
+ printf "%s " "$i"
+ done)
+ findopts="-xdev ( -type d -o -type f -o -type l ) -print"
+
+ vlog "cd \"$source_dir\" && find $flist $findopts | "
+ vlog "ppriv -e -s A=all,-sys_devices cpio $cpioopts \"$ZONEROOT\""
+
+ ( cd "$source_dir" && find $flist $findopts | \
+ ppriv -e -s A=all,-sys_devices cpio $cpioopts "$ZONEROOT" )
+}
+
+# Setup i18n output
+TEXTDOMAIN="SUNW_OST_OSCMD"
+export TEXTDOMAIN
+
+e_baddir=$(gettext "Invalid '%s' directory within the zone")
+e_badfile=$(gettext "Invalid '%s' file within the zone")
+
+#
+# Exit values used by the script, as #defined in <sys/zone.h>
+#
+# ZONE_SUBPROC_OK
+# ===============
+# Installation was successful
+#
+# ZONE_SUBPROC_USAGE
+# ==================
+# Improper arguments were passed, so print a usage message before exiting
+#
+# ZONE_SUBPROC_NOTCOMPLETE
+# ========================
+# Installation did not complete, but another installation attempt can be
+# made without an uninstall
+#
+# ZONE_SUBPROC_FATAL
+# ==================
+# Installation failed and an uninstall will be required before another
+# install can be attempted
+#
+ZONE_SUBPROC_OK=0
+ZONE_SUBPROC_USAGE=253
+ZONE_SUBPROC_NOTCOMPLETE=254
+ZONE_SUBPROC_FATAL=255
+
--- a/usr/src/lib/brand/native/zone/config.xml Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/config.xml Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
CDDL HEADER END
- Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
DO NOT EDIT THIS FILE.
@@ -37,6 +37,7 @@
<user_cmd>/usr/bin/getent passwd %u</user_cmd>
<install>/usr/lib/brand/native/sw_support install %z %R</install>
+ <installopts>a:b:d:psuv</installopts>
<verify_cfg></verify_cfg>
<verify_adm></verify_adm>
<postclone>/usr/lib/brand/native/sw_support postclone %z %R</postclone>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/image_install.ksh Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,517 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. /usr/lib/brand/shared/common.ksh
+
+# Restrict executables to /bin, /usr/bin and /usr/sfw/bin
+PATH=/bin:/usr/bin:/usr/sbin:/usr/sfw/bin
+export PATH
+
+cmd_not_found=$(gettext "Required command '%s' cannot be found!")
+cmd_not_exec=$(gettext "Required command '%s' not executable!")
+zone_initfail=$(gettext "Attempt to initialize zone '%s' FAILED.")
+path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
+
+e_tmpfile=$(gettext "Unable to create temporary file")
+
+both_modes=$(gettext "%s: cannot select both silent and verbose modes")
+
+both_choices=$(gettext "%s: cannot select both preserve and unconfigure options")
+
+both_kinds=$(gettext "%s: cannot specify both archive and directory")
+
+not_found=$(gettext "%s: error: file or directory not found.")
+
+wrong_dir_type=$(gettext "error: must be a directory")
+
+not_readable=$(gettext "Cannot read file '%s'")
+
+no_install=$(gettext "Could not create install directory '%s'")
+no_log=$(gettext "Could not create log directory '%s'")
+
+media_taste=$(gettext " Media Type: %s")
+bad_archive=$(gettext "ERROR: must be a flash archive, a cpio archive (can also
+be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.")
+
+product_vers=$(gettext " Product: %s")
+install_vers=$(gettext " Installer: %s")
+install_zone=$(gettext " Zone: %s")
+install_path=$(gettext " Path: %s")
+install_from=$(gettext " Source: %s")
+installing=$(gettext " Installing: This may take several minutes...")
+no_installing=$(gettext " Installing: Using pre-existing data in zonepath")
+install_prog=$(gettext " Installing: %s")
+
+install_fail=$(gettext " Result: *** Installation FAILED ***")
+install_log=$(gettext " Log File: %s")
+
+install_abort=$(gettext " Result: Installation aborted.")
+install_good=$(gettext " Result: Installation completed successfully.")
+
+not_native_image=$(gettext " Sanity Check: %s doesn't look like a native image.")
+sanity_ok=$(gettext " Sanity Check: Passed. Looks like a native system.")
+sanity_fail_detail=$(gettext " Sanity Check: Missing %s at %s")
+sanity_fail_vers=$(gettext " Sanity Check: image release version %s does not match system release version %s, the zone is not usable on this system.")
+sanity_fail=$(gettext " Sanity Check: FAILED (see log for details).")
+
+
+p2ving=$(gettext "Postprocessing: This may take a while...")
+p2v_prog=$(gettext " Postprocess: ")
+p2v_done=$(gettext " Result: Postprocessing complete.")
+p2v_fail=$(gettext " Result: Postprocessing failed.")
+
+root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
+
+media_missing=\
+$(gettext "%s: you must specify an installation source using '-a' or '-d'.")
+
+cfgchoice_missing=\
+$(gettext "%s: you must specify -u (sys-unconfig) or -p (preserve identity).")
+
+mount_failed=$(gettext "ERROR: zonecfg(1M) 'fs' mount failed")
+
+not_flar=$(gettext "Input is not a flash archive")
+bad_flar=$(gettext "Flash archive is a corrupt")
+unknown_archiver=$(gettext "Archiver %s is not supported")
+
+e_baddir=$(gettext "Invalid '%s' directory within the zone")
+
+# Clean up on interrupt
+trap_cleanup()
+{
+ msg=$(gettext "Installation cancelled due to interrupt.")
+ log "$msg"
+
+ # umount IPDs
+ umnt_fs
+
+ exit $EXIT_CODE
+}
+
+sanity_check()
+{
+ typeset dir="$1"
+ shift
+ ret=0
+
+ # These checks must work with a sparse zone.
+ checks="etc etc/svc usr sbin lib var var/svc"
+ for x in $checks; do
+ if [[ ! -e $dir/$x ]]; then
+ vlog "$sanity_fail_detail" "$x" "$dir"
+ ret=1
+ fi
+ done
+
+ #
+ # Check image release against system release. We only work on the
+ # same minor release as the system is running.
+ #
+ sys_vers=0
+ image_vers=-1
+ if [[ -f /var/sadm/system/admin/INST_RELEASE ]]; then
+ sys_vers=$(nawk -F= '{if ($1 == "VERSION") print $2}' \
+ /var/sadm/system/admin/INST_RELEASE)
+ fi
+
+ if [[ -f $dir/var/sadm/system/admin/INST_RELEASE ]]; then
+ image_vers=$(nawk -F= '{if ($1 == "VERSION") print $2}' \
+ $dir/var/sadm/system/admin/INST_RELEASE)
+ fi
+
+ if (( $sys_vers != $image_vers )); then
+ vlog "$sanity_fail_vers" "$image_vers" "$sys_vers"
+ ret=1
+ fi
+
+ return $ret
+}
+
+#
+# The main body of the script starts here.
+#
+# This script should never be called directly by a user but rather should
+# only be called by zoneadm to install a native system image into a zone.
+#
+
+#
+# Exit code to return if install is interrupted or exit code is otherwise
+# unspecified.
+#
+EXIT_CODE=$ZONE_SUBPROC_USAGE
+
+trap trap_cleanup INT
+
+# If we weren't passed at least two arguments, exit now.
+(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
+
+zonename="$1"
+zonepath="$2"
+
+ZONEROOT="$zonepath/root"
+logdir="$ZONEROOT/var/log"
+
+shift; shift # remove zonename and zonepath from arguments array
+
+unset backout
+unset install_archive
+unset source_dir
+unset msg
+unset silent_mode
+unset OPT_V
+
+#
+# It is worth noting here that we require the end user to pick one of
+# -u (sys-unconfig) or -p (preserve config). This is because we can't
+# really know in advance which option makes a better default. Forcing
+# the user to pick one or the other means that they will consider their
+# choice and hopefully not be surprised or disappointed with the result.
+#
+unset unconfig_zone
+unset preserve_zone
+
+while getopts "a:b:d:psuv" opt
+do
+ case "$opt" in
+ a) install_archive="$OPTARG" ; install_media="$OPTARG";;
+ b) if [[ -n "$backout" ]]; then
+ backout="$backout -b $OPTARG"
+ else
+ backout="-b $OPTARG"
+ fi
+ ;;
+ d) source_dir="$OPTARG" ; install_media="$OPTARG";;
+ p) preserve_zone="-p";;
+ s) silent_mode=1;;
+ u) unconfig_zone="-u";;
+ v) OPT_V="-v";;
+ *) exit $ZONE_SUBPROC_USAGE;;
+ esac
+done
+shift OPTIND-1
+
+# The install can't be both verbose AND silent...
+if [[ -n $silent_mode && -n $OPT_V ]]; then
+ fatal "$both_modes" "zoneadm install"
+fi
+
+if [[ -z $install_media ]]; then
+ fatal "$media_missing" "zoneadm install"
+fi
+
+if [[ -n $install_archive && -n $source_dir ]]; then
+ fatal "$both_kinds" "zoneadm install"
+fi
+
+# The install can't both preserve and unconfigure
+if [[ -n $unconfig_zone && -n $preserve_zone ]]; then
+ fatal "$both_choices" "zoneadm install"
+fi
+
+# Must pick one or the other.
+if [[ -z $unconfig_zone && -z $preserve_zone ]]; then
+ fatal "$cfgchoice_missing" "zoneadm install"
+fi
+
+#
+# Handle "-d -" option to use whatever is already installed into the zonepath.
+#
+if [ "$source_dir" != "-" ]; then
+ #
+ # Validate $install_media (things common to archive/dir)
+ #
+ if [[ "$(echo $install_media | cut -c 1)" != "/" ]]; then
+ fatal "$path_abs" "$install_media"
+ fi
+
+ if [[ ! -e "$install_media" ]]; then
+ log "$not_found" "$install_media"
+ fatal "$install_abort" "$zonename"
+ fi
+
+ if [[ ! -r "$install_media" ]]; then
+ log "$not_readable" "$install_media"
+ fatal "$install_abort" "$zonename"
+ fi
+
+ if [[ -n $install_archive ]]; then
+ if [[ ! -f "$install_archive" ]]; then
+ log "$media_taste" "$bad_archive"
+ fatal "$install_abort" "$zonename"
+ fi
+ fi
+
+ if [[ -n $source_dir ]]; then
+ if [[ ! -d "$source_dir" ]]; then
+ log "$media_taste" "$wrong_dir_type"
+ fatal "$install_abort" "$zonename"
+ fi
+ fi
+fi
+
+LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $zonename.install_log.XXXXXX)
+if [[ -z "$LOGFILE" ]]; then
+ fatal "$e_tmpfile"
+fi
+zone_logfile="${logdir}/$zonename.install$$.log"
+exec 2>>"$LOGFILE"
+log "$install_log" "$LOGFILE"
+
+vlog "Starting pre-installation tasks."
+
+if [[ -z $install_archive && -n $source_dir ]]; then
+ #
+ # Minimal check to make sure that the user is passing
+ # us something that at least seems to be a native image.
+ #
+ if [[ "$source_dir" == "-" ]]; then
+ filetype="existing"
+ filetypename="existing"
+ else
+ sanity_check $source_dir
+ if (( $? != 0 )); then
+ fatal "$not_native_image" "$source_dir"
+ fi
+
+ filetype="directory"
+ filetypename="directory"
+ fi
+else
+ ftype="$(LC_ALL=C file $install_archive | cut -d: -f 2)"
+ case "$ftype" in
+ *cpio*) filetype="cpio"
+ filetypename="cpio archive"
+ ;;
+ *bzip2*) filetype="bzip2"
+ filetypename="bzipped cpio archive"
+ ;;
+ *gzip*) filetype="gzip"
+ filetypename="gzipped cpio archive"
+ ;;
+ *ufsdump*) filetype="ufsdump"
+ filetypename="ufsdump archive"
+ ;;
+ *Flash\ Archive*) filetype="flar"
+ filetypename="flash archive"
+ ;;
+ *USTAR\ tar\ archive\ extended\ format*) filetype="xustar"
+ filetypename="pax (xustar) archive"
+ ;;
+ *) log "$media_taste" "$bad_archive"
+ fatal "$install_abort" "$zonename"
+ ;;
+ esac
+fi
+
+#
+# From here on out, an unspecified exit or interrupt should exit with
+# ZONE_SUBPROC_NOTCOMPLETE, meaning a user will need to do an uninstall before
+# attempting another install, as we've modified the directories we were going
+# to install to in some way.
+#
+EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
+
+if [[ ! -d "$ZONEROOT" ]]
+then
+ if ! mkdir -p "$ZONEROOT" 2>/dev/null; then
+ fatal "$no_install" "$ZONEROOT"
+ fi
+fi
+
+#
+# Check for a non-empty root if no '-d -' option.
+#
+if [[ "$filetype" != "existing" ]]; then
+ cnt=$(ls $ZONEROOT | wc -l)
+ if (( $cnt != 0 )); then
+ fatal "$root_full" "$ZONEROOT"
+ fi
+fi
+
+vlog "Installation started for zone \"$zonename\""
+
+log "$install_from" "$install_media"
+vlog "$media_taste" "$filetypename"
+
+fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
+if [[ -z "$fstmpfile" ]]; then
+ fatal "$e_tmpfile"
+fi
+
+# Make sure we always have the files holding the directories to filter
+# out when extracting from a CPIO or PAX archive. We'll add the IPDs to these
+# files in get_fs_info().
+ipdcpiofile=$(/usr/bin/mktemp -t -p /var/tmp ipd.cpio.XXXXXX)
+if [[ -z "$ipdcpiofile" ]]; then
+ rm -f $fstmpfile
+ fatal "$e_tmpfile"
+fi
+
+# In addition to the IPDs, also filter out these directories.
+echo 'dev/*' >>$ipdcpiofile
+echo 'devices/*' >>$ipdcpiofile
+echo 'devices' >>$ipdcpiofile
+echo 'proc/*' >>$ipdcpiofile
+echo 'tmp/*' >>$ipdcpiofile
+echo 'var/run/*' >>$ipdcpiofile
+echo 'system/contract/*' >>$ipdcpiofile
+echo 'system/object/*' >>$ipdcpiofile
+
+ipdpaxfile=$(/usr/bin/mktemp -t -p /var/tmp ipd.pax.XXXXXX)
+if [[ -z "$ipdpaxfile" ]]; then
+ rm -f $fstmpfile $ipdcpiofile
+ fatal "$e_tmpfile"
+fi
+
+printf "%s " "dev devices proc tmp var/run system/contract system/object" \
+ >>$ipdpaxfile
+
+# Set up any fs mounts so the archive will install into the correct locations.
+get_fs_info
+mnt_fs
+if (( $? != 0 )); then
+ umnt_fs >/dev/null 2>&1
+ rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
+ fatal "$mount_failed"
+fi
+
+if [[ "$filetype" == "existing" ]]; then
+ log "$no_installing"
+else
+ log "$installing"
+fi
+
+unpack_result=0
+stage1="cat"
+if [[ "$filetype" == "gzip" ]]; then
+ stage1="gzcat"
+ filetype="cpio"
+fi
+
+if [[ "$filetype" == "bzip2" ]]; then
+ stage1="bzcat"
+ filetype="cpio"
+fi
+
+if [[ "$filetype" == "cpio" ]]; then
+ install_cpio "$stage1" "$install_archive"
+ unpack_result=$?
+
+elif [[ "$filetype" == "flar" ]]; then
+ ( cd "$ZONEROOT" && install_flar < "$install_archive" )
+ unpack_result=$?
+
+elif [[ "$filetype" == "xustar" ]]; then
+ install_pax "$install_archive"
+ unpack_result=$?
+
+elif [[ "$filetype" == "ufsdump" ]]; then
+ install_ufsdump "$install_archive"
+ unpack_result=$?
+
+elif [[ "$filetype" == "directory" ]]; then
+ install_dir "$source_dir"
+ unpack_result=$?
+fi
+
+# Clean up any fs mounts used during unpacking.
+umnt_fs
+rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
+
+#
+# Do a sanity check to see if various things we think should be present
+# are present. If not, the user might have supplied a cpio archive which was
+# not created properly.
+#
+if (( $unpack_result == 0 )); then
+ sanity_check $ZONEROOT
+ if (( $? != 0 )); then
+ log "$sanity_fail"
+ log ""
+ log "$install_log" "$LOGFILE"
+ fatal "$install_fail" "$zonename"
+ else
+ vlog "$sanity_ok"
+ fi
+fi
+
+chmod 700 $zonepath
+
+log "$p2ving"
+vlog "running: p2v $OPT_V $unconfig_zone $backout $zonename $zonepath"
+
+#
+# Run p2v.
+#
+# Getting the output to the right places is a little tricky because what
+# we want is for p2v to output in the same way the installer does: verbose
+# messages to the log file always, and verbose messages printed to the
+# user if the user passes -v. This rules out simple redirection. And
+# we can't use tee or other tricks because they cause us to lose the
+# return value from the p2v script due to the way shell pipelines work.
+#
+# The simplest way to do this seems to be to hand off the management of
+# the log file to the p2v script. So we run p2v with -l to tell it where
+# to find the log file and then reopen the log (O_APPEND) when p2v is done.
+#
+/usr/lib/brand/native/p2v -l "$LOGFILE" -m "$p2v_prog" \
+ $OPT_V $unconfig_zone $backout $zonename $zonepath
+p2v_result=$?
+exec 2>>$LOGFILE
+
+if (( $p2v_result == 0 )); then
+ vlog "$p2v_done"
+else
+ log "$p2v_fail"
+ log ""
+ log "$install_fail"
+ log "$install_log" "$LOGFILE"
+ exit $ZONE_SUBPROC_FATAL
+fi
+
+EXIT_CODE=$ZONE_SUBPROC_OK
+
+log ""
+log "$install_good" "$zonename"
+
+if [[ -h $ZONEROOT/var || ! -d $ZONEROOT/var || -h $ZONEROOT/var/log ]]; then
+ log "$e_baddir" "/var/log"
+ exit $ZONE_SUBPROC_FATAL
+fi
+
+# Just in case the log directory isn't present...
+if [[ ! -d "$logdir" ]]; then
+ if ! mkdir -p "$logdir" 2>/dev/null; then
+ log "$no_log" "$logdir"
+ fi
+fi
+
+if [[ ! -h $zone_logfile && ! -d $zone_logfile ]]; then
+ cp $LOGFILE $zone_logfile
+fi
+log "$install_log" "$zone_logfile"
+rm -f $LOGFILE
+
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/p2v.ksh Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,680 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# NOTE: this script runs in the global zone and touches the non-global
+# zone, so care should be taken to validate any modifications so that they
+# are safe.
+
+. /usr/lib/brand/shared/common.ksh
+
+LOGFILE=
+MSG_PREFIX="p2v: "
+EXIT_CODE=1
+
+usage()
+{
+ echo "$0 [-s] [-m msgprefix] [-u] [-v] [-b patchid]* zonename" >&2
+ exit $EXIT_CODE
+}
+
+# Clean up on interrupt
+trap_cleanup()
+{
+ msg=$(gettext "Postprocessing cancelled due to interrupt.")
+ error "$msg"
+
+ if (( $zone_is_running != 0 )); then
+ error "$e_shutdown" "$ZONENAME"
+ /usr/sbin/zoneadm -z $ZONENAME halt
+ fi
+
+ exit $EXIT_CODE
+}
+
+#
+# For an exclusive stack zone, fix up the network configuration files.
+# We need to do this even if unconfiguring the zone so sys-unconfig works
+# correctly.
+#
+fix_net()
+{
+ [[ "$STACK_TYPE" == "shared" ]] && return
+
+ NETIF_CNT=$(/usr/bin/ls $ZONEROOT/etc/hostname.* 2>/dev/null | \
+ /usr/bin/wc -l)
+ if (( $NETIF_CNT != 1 )); then
+ vlog "$v_nonetfix"
+ return
+ fi
+
+ NET=$(LC_ALL=C /usr/sbin/zonecfg -z $ZONENAME info net)
+ if (( $? != 0 )); then
+ error "$e_badinfo" "net"
+ return
+ fi
+
+ NETIF=$(echo $NET | /usr/bin/nawk '{
+ for (i = 1; i < NF; i++) {
+ if ($i == "physical:") {
+ if (length(net) == 0) {
+ i++
+ net = $i
+ } else {
+ multiple=1
+ }
+ }
+ }
+ }
+ END { if (!multiple)
+ print net
+ }')
+
+ if [[ -z "$NETIF" ]]; then
+ vlog "$v_nonetfix"
+ return
+ fi
+
+ OLD_HOSTNET=$(/usr/bin/ls $ZONEROOT/etc/hostname.*)
+ if [[ "$OLD_HOSTNET" != "$ZONEROOT/etc/hostname.$NETIF" ]]; then
+ safe_move $OLD_HOSTNET $ZONEROOT/etc/hostname.$NETIF
+ fi
+}
+
+#
+# Disable all of the shares since the zone cannot be an NFS server.
+# Note that we disable the various instances of the svc:/network/shares/group
+# SMF service in the fix_smf function.
+#
+fix_nfs()
+{
+ zonedfs=$ZONEROOT/etc/dfs
+
+ if [[ -h $zonedfs/dfstab || ! -f $zonedfs/dfstab ]]; then
+ error "$e_badfile" "/etc/dfs/dfstab"
+ return
+ fi
+
+ tmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
+ if [[ -z "$tmpfile" ]]; then
+ error "$e_tmpfile"
+ return
+ fi
+
+ /usr/bin/nawk '{
+ if (substr($1, 0, 1) == "#") {
+ print $0
+ } else {
+ print "#", $0
+ modified=1
+ }
+ }
+ END {
+ if (modified == 1) {
+ printf("# Modified by p2v ")
+ system("/usr/bin/date")
+ exit 0
+ }
+ exit 1
+ }' $zonedfs/dfstab >>$tmpfile
+
+ if (( $? == 0 )); then
+ if [[ ! -f $zonedfs/dfstab.pre_p2v ]]; then
+ safe_copy $zonedfs/dfstab $zonedfs/dfstab.pre_p2v
+ fi
+ safe_copy $tmpfile $zonedfs/dfstab
+ fi
+ /usr/bin/rm -f $tmpfile
+}
+
+#
+# Comment out most of the old mounts since they are either unneeded or
+# likely incorrect within a zone. Specific mounts can be manually
+# reenabled if the corresponding device is added to the zone.
+#
+fix_vfstab()
+{
+ if [[ -h $ZONEROOT/etc/vfstab || ! -f $ZONEROOT/etc/vfstab ]]; then
+ error "$e_badfile" "/etc/vfstab"
+ return
+ fi
+
+ tmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
+ if [[ -z "$tmpfile" ]]; then
+ error "$e_tmpfile"
+ return
+ fi
+
+ /usr/bin/nawk '{
+ if (substr($1, 0, 1) == "#") {
+ print $0
+ } else if ($1 == "fd" || $1 == "/proc" || $1 == "swap" ||
+ $1 == "ctfs" || $1 == "objfs" || $1 == "sharefs" ||
+ $4 == "nfs" || $4 == "lofs") {
+ print $0
+ } else {
+ print "#", $0
+ modified=1
+ }
+ }
+ END {
+ if (modified == 1) {
+ printf("# Modified by p2v ")
+ system("/usr/bin/date")
+ exit 0
+ }
+ exit 1
+ }' $ZONEROOT/etc/vfstab >>$tmpfile
+
+ if (( $? == 0 )); then
+ if [[ ! -f $ZONEROOT/etc/vfstab.pre_p2v ]]; then
+ safe_copy $ZONEROOT/etc/vfstab \
+ $ZONEROOT/etc/vfstab.pre_p2v
+ fi
+ safe_copy $tmpfile $ZONEROOT/etc/vfstab
+ fi
+ /usr/bin/rm -f $tmpfile
+}
+
+#
+# Delete or disable SMF services.
+# Zone is booted to milestone=none when this function is called.
+#
+fix_smf()
+{
+ #
+ # Delete services that are delivered in hollow pkgs.
+ #
+ # Start by getting the svc manifests that are delivered by hollow
+ # pkgs then use 'svccfg inventory' to get the names of the svcs
+ # delivered by those manifests. The svc names are saved into a
+ # temporary file. We then login to the zone and delete them from SMF
+ # so that the various dependencies also get cleaned up properly.
+ #
+
+ smftmpfile=$(/usr/bin/mktemp -t -p /var/tmp smf.XXXXXX)
+ if [[ -z "$smftmpfile" ]]; then
+ error "$e_tmpfile"
+ return
+ fi
+
+ for i in /var/sadm/pkg/*
+ do
+ pkg=$(/usr/bin/basename $i)
+ [[ ! -f /var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap ]] && \
+ continue
+
+ manifests=$(/usr/bin/nawk '{if ($2 == "f" &&
+ substr($4, 1, 17) == "var/svc/manifest/") print $4}' \
+ /var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap)
+
+ if [[ -n "$manifests" ]]; then
+ /usr/bin/egrep -s "SUNW_PKG_HOLLOW=true" \
+ /var/sadm/pkg/$pkg/pkginfo || continue
+
+ for j in $manifests
+ do
+ svcs=$(SVCCFG_NOVALIDATE=1 /usr/sbin/svccfg \
+ inventory /$j)
+ for k in $svcs
+ do
+ case $k in
+ *:default)
+ # ignore default instance
+ ;;
+ *)
+ echo $k >> $smftmpfile
+ ;;
+ esac
+ done
+ done
+ fi
+ done
+
+ #
+ # Zone was already booted to milestone=none, wait until SMF door exists.
+ #
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ [[ -r $ZONEROOT/etc/svc/volatile/repository_door ]] && break
+ sleep 5
+ done
+
+ if [[ $i -eq 9 && ! -r $ZONEROOT/etc/svc/volatile/repository_door ]];
+ then
+ error "$e_nosmf"
+ /usr/bin/rm -f $smftmpfile
+ return
+ fi
+
+ insttmpfile=$(/usr/bin/mktemp -t -p /var/tmp instsmf.XXXXXX)
+ if [[ -z "$insttmpfile" ]]; then
+ error "$e_tmpfile"
+ /usr/bin/rm -f $smftmpfile
+ return
+ fi
+
+ # Get a list of the svcs that exist in the zone.
+ /usr/sbin/zlogin -S $ZONENAME /usr/bin/svcs -aH | \
+ /usr/bin/nawk '{print $3}' >>$insttmpfile
+
+ [[ -n $LOGFILE ]] && \
+ printf "[$(date)] ${MSG_PREFIX}${v_svcsinzone}\n" >&2
+ [[ -n $LOGFILE ]] && cat $insttmpfile >&2
+
+ vlog "$v_rmhollowsvcs"
+ for i in $(cat $smftmpfile)
+ do
+ # Skip svcs not installed in the zone.
+ /usr/bin/egrep -s "$i:" $insttmpfile || continue
+
+ # Delete the svc.
+ vlog "$v_delsvc" "$i"
+ /usr/sbin/zlogin -S $ZONENAME /usr/sbin/svccfg delete $i >&2 \
+ || error "$e_delsvc" $i
+ done
+
+ /usr/bin/rm -f $smftmpfile
+
+ #
+ # Fix network services if shared stack.
+ #
+ if [[ "$STACK_TYPE" == "shared" ]]; then
+ vlog "$v_fixnetsvcs"
+
+ NETPHYSDEF="svc:/network/physical:default"
+ NETPHYSNWAM="svc:/network/physical:nwam"
+
+ /usr/bin/egrep -s "$NETPHYSDEF" $insttmpfile
+ if (( $? == 0 )); then
+ vlog "$v_enblsvc" "$NETPHYSDEF"
+ /usr/sbin/zlogin -S $ZONENAME \
+ /usr/sbin/svcadm enable $NETPHYSDEF || \
+ error "$e_dissvc" "$NETPHYSDEF"
+ fi
+
+ /usr/bin/egrep -s "$NETPHYSNWAM" $insttmpfile
+ if (( $? == 0 )); then
+ vlog "$v_dissvc" "$NETPHYSNWAM"
+ /usr/sbin/zlogin -S $ZONENAME \
+ /usr/sbin/svcadm disable $NETPHYSNWAM || \
+ error "$e_enblsvc" "$NETPHYSNWAM"
+ fi
+
+ for i in $(/usr/bin/egrep network/routing $insttmpfile)
+ do
+ # Disable the svc.
+ vlog "$v_dissvc" "$i"
+ /usr/sbin/zlogin -S $ZONENAME \
+ /usr/sbin/svcadm disable $i || \
+ error "$e_dissvc" $i
+ done
+ fi
+
+ #
+ # Disable well-known services that don't run in a zone.
+ #
+ vlog "$v_rminvalidsvcs"
+ for i in $(/usr/bin/egrep -hv "^#" \
+ /usr/lib/brand/native/smf_disable.lst \
+ /etc/brand/native/smf_disable.conf)
+ do
+ # Skip svcs not installed in the zone.
+ /usr/bin/egrep -s "$i:" $insttmpfile || continue
+
+ # Disable the svc.
+ vlog "$v_dissvc" "$i"
+ /usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $i || \
+ error "$e_dissvc" $i
+ done
+
+ #
+ # Since zones can't be NFS servers, disable all of the instances of
+ # the shares svc.
+ #
+ for i in $(/usr/bin/egrep network/shares/group $insttmpfile)
+ do
+ vlog "$v_dissvc" "$i"
+ /usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $i || \
+ error "$e_dissvc" $i
+ done
+
+ /usr/bin/rm -f $insttmpfile
+}
+
+#
+# Remove well-known pkgs that do not work inside a zone.
+#
+rm_pkgs()
+{
+ /usr/bin/cat <<-EOF > $ZONEROOT/tmp/admin || fatal "$e_adminf"
+ mail=
+ instance=overwrite
+ partial=nocheck
+ runlevel=nocheck
+ idepend=nocheck
+ rdepend=nocheck
+ space=nocheck
+ setuid=nocheck
+ conflict=nocheck
+ action=nocheck
+ basedir=default
+ EOF
+
+ for i in $(/usr/bin/egrep -hv "^#" /usr/lib/brand/native/pkgrm.lst \
+ /etc/brand/native/pkgrm.conf)
+ do
+ [[ ! -d $ZONEROOT/var/sadm/pkg/$i ]] && continue
+
+ vlog "$v_rmpkg" "$i"
+ /usr/sbin/zlogin -S $ZONENAME \
+ /usr/sbin/pkgrm -na /tmp/admin $i >&2 || error "$e_rmpkg" $i
+ done
+}
+
+#
+# Zoneadmd writes a one-line index file into the zone when the zone boots,
+# so any information about installed zones from the original system will
+# be lost at that time. Here we'll warn the sysadmin about any pre-existing
+# zones that they might want to clean up by hand, but we'll leave the zonepaths
+# in place in case they're on shared storage and will be migrated to
+# a new host.
+#
+warn_zones()
+{
+ zoneconfig=$ZONEROOT/etc/zones
+
+ if [[ -h $zoneconfig/index || ! -f $zoneconfig/index ]]; then
+ error "$e_badfile" "/etc/zones/index"
+ return
+ fi
+
+ NGZ=$(/usr/bin/nawk -F: '{
+ if (substr($1, 0, 1) == "#" || $1 == "global")
+ continue
+
+ if ($2 == "installed")
+ printf("%s ", $1)
+ }' $zoneconfig/index)
+
+ # Return if there are no installed zones to warn about.
+ [[ -z "$NGZ" ]] && return
+
+ log "$v_rmzones" "$NGZ"
+
+ NGZP=$(/usr/bin/nawk -F: '{
+ if (substr($1, 0, 1) == "#" || $1 == "global")
+ continue
+
+ if ($2 == "installed")
+ printf("%s ", $3)
+ }' $zoneconfig/index)
+
+ log "$v_rmzonepaths"
+
+ for i in $NGZP
+ do
+ log " %s" "$i"
+ done
+}
+
+unset LD_LIBRARY_PATH
+PATH=/usr/sbin:/usr/bin
+export PATH
+
+#
+# ^C Should cleanup; if the zone is running, it should try to halt it.
+#
+zone_is_running=0
+trap trap_cleanup INT
+
+#
+# Parse the command line options.
+#
+unset backout
+OPT_U=
+OPT_V=
+OPT_M=
+OPT_L=
+while getopts "b:uvm:l:" opt
+do
+ case "$opt" in
+ b) if [[ -n "$backout" ]]; then
+ backout="$backout -b $OPTARG"
+ else
+ backout="-b $OPTARG"
+ fi
+ ;;
+ u) OPT_U="-u";;
+ v) OPT_V="-v";;
+ m) MSG_PREFIX="$OPTARG"; OPT_M="-m \"$OPTARG\"";;
+ l) LOGFILE="$OPTARG"; OPT_L="-l \"$OPTARG\"";;
+ *) usage;;
+ esac
+done
+shift OPTIND-1
+
+(( $# < 1 )) && usage
+
+(( $# > 2 )) && usage
+
+[[ -n $LOGFILE ]] && exec 2>>$LOGFILE
+
+ZONENAME=$1
+ZONEPATH=$2
+ZONEROOT=$ZONEPATH/root
+
+e_badinfo=$(gettext "Failed to get '%s' zone resource")
+e_badfile=$(gettext "Invalid '%s' file within the zone")
+e_tmpfile=$(gettext "Unable to create temporary file")
+v_mkdirs=$(gettext "Creating mount points")
+v_nonetfix=$(gettext "Cannot update /etc/hostname.{net} file")
+v_update=$(gettext "Updating the zone software to match the global zone...")
+v_updatedone=$(gettext "Zone software update complete")
+e_badupdate=$(gettext "Updating the Zone software failed")
+v_adjust=$(gettext "Updating the image to run within a zone")
+v_stacktype=$(gettext "Stack type '%s'")
+v_booting=$(gettext "Booting zone to single user mode")
+e_badboot=$(gettext "Zone boot failed")
+e_nosmf=$(gettext "ERROR: SMF repository unavailable.")
+e_nosingleuser=$(gettext "ERROR: zone did not finish booting to single-user.")
+v_svcsinzone=$(gettext "The following SMF services are installed:")
+v_rmhollowsvcs=$(gettext "Deleting SMF services from hollow packages")
+v_fixnetsvcs=$(gettext "Adjusting network SMF services")
+v_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
+v_delsvc=$(gettext "Delete SMF svc '%s'")
+e_delsvc=$(gettext "deleting SMF svc '%s'")
+v_enblsvc=$(gettext "Enable SMF svc '%s'")
+e_enblsvc=$(gettext "enabling SMF svc '%s'")
+v_dissvc=$(gettext "Disable SMF svc '%s'")
+e_dissvc=$(gettext "disabling SMF svc '%s'")
+e_adminf=$(gettext "Unable to create admin file")
+v_rmpkg=$(gettext "Remove package '%s'")
+e_rmpkg=$(gettext "removing package '%s'")
+v_rmzones=$(gettext "The following zones in this image will be unusable: %s")
+v_rmzonepaths=$(gettext "These zonepaths could be removed from this image:")
+v_unconfig=$(gettext "Performing zone sys-unconfig")
+e_unconfig=$(gettext "sys-unconfig failed")
+v_halting=$(gettext "Halting zone")
+e_shutdown=$(gettext "Shutting down zone %s...")
+e_badhalt=$(gettext "Zone halt failed")
+v_exitgood=$(gettext "Postprocessing successful.")
+e_exitfail=$(gettext "Postprocessing failed.")
+
+#
+# Do some validation on the paths we'll be accessing
+#
+safe_dir etc
+safe_dir etc/dfs
+safe_dir etc/zones
+safe_dir var
+
+# Now do the work to update the zone.
+
+# Before booting the zone we may need to create a few mnt points, just in
+# case they don't exist for some reason.
+#
+# Whenever we reach into the zone while running in the global zone we
+# need to validate that none of the interim directories are symlinks
+# that could cause us to inadvertently modify the global zone.
+vlog "$v_mkdirs"
+if [[ ! -f $ZONEROOT/tmp && ! -d $ZONEROOT/tmp ]]; then
+ mkdir -m 1777 -p $ZONEROOT/tmp || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/var/run && ! -d $ZONEROOT/var/run ]]; then
+ mkdir -m 1755 -p $ZONEROOT/var/run || exit $EXIT_CODE
+fi
+if [[ ! -h $ZONEROOT/etc && ! -f $ZONEROOT/etc/mnttab ]]; then
+ /usr/bin/touch $ZONEROOT/etc/mnttab || exit $EXIT_CODE
+ /usr/bin/chmod 444 $ZONEROOT/etc/mnttab || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/proc && ! -d $ZONEROOT/proc ]]; then
+ mkdir -m 755 -p $ZONEROOT/proc || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/dev && ! -d $ZONEROOT/dev ]]; then
+ mkdir -m 755 -p $ZONEROOT/dev || exit $EXIT_CODE
+fi
+if [[ ! -h $ZONEROOT/etc && ! -h $ZONEROOT/etc/svc && ! -d $ZONEROOT/etc/svc ]]
+then
+ mkdir -m 755 -p $ZONEROOT/etc/svc/volatile || exit $EXIT_CODE
+fi
+
+# Check for zones inside of image.
+warn_zones
+
+#
+# Run update on attach. State is currently 'incomplete' so use the private
+# force-update option.
+#
+log "$v_update"
+/usr/sbin/zoneadm -z $ZONENAME attach -U $backout >&2
+res=$?
+if (( $? != 0 )); then
+ fatal "$e_badupdate"
+else
+ log "$v_updatedone"
+fi
+
+log "$v_adjust"
+
+#
+# Any errors in these functions are not considered fatal. The zone can be
+# be fixed up manually afterwards and it may need some additional manual
+# cleanup in any case.
+#
+
+STACK_TYPE=$(/usr/sbin/zoneadm -z $ZONENAME list -p | \
+ /usr/bin/nawk -F: '{print $7}')
+if (( $? != 0 )); then
+ error "$e_badinfo" "stacktype"
+fi
+vlog "$v_stacktype" "$STACK_TYPE"
+
+fix_net
+fix_nfs
+fix_vfstab
+
+vlog "$v_booting"
+
+#
+# Boot the zone so that we can do all of the SMF updates needed on the zone's
+# repository.
+#
+
+zone_is_running=1
+
+# The 'update on attach' left the zone installed.
+/usr/sbin/zoneadm -z $ZONENAME boot -f -- -m milestone=none
+if (( $? != 0 )); then
+ error "$e_badboot"
+ fatal "$e_exitfail"
+fi
+
+# cleanup SMF services
+fix_smf
+
+# remove invalid pkgs
+rm_pkgs
+
+vlog "$v_halting"
+/usr/sbin/zoneadm -z $ZONENAME halt
+if (( $? != 0 )); then
+ error "$e_badhalt"
+ failed=1
+fi
+zone_is_running=0
+
+if [[ -z $failed && -n $OPT_U ]]; then
+ #
+ # We're sys-unconfiging the zone. This will halt the zone, however
+ # there are problems with sys-unconfig and it usually hangs when the
+ # zone is booted to milestone=none. This is why we previously halted
+ # the zone. We now boot to milestone=single-user. Again, the
+ # sys-unconfig can hang if the zone is still in the process of
+ # booting when we try to run sys-unconfig. Wait until the boot is
+ # done, which we do by checking for sulogin, or waiting 30 seconds,
+ # whichever comes first.
+ #
+
+ vlog "$v_unconfig"
+
+ zone_is_running=1
+ /usr/sbin/zoneadm -z $ZONENAME boot -- -m milestone=single-user
+ if (( $? != 0 )); then
+ error "$e_badboot"
+ fatal "$e_exitfail"
+ fi
+
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ sleep 10
+ /usr/sbin/zlogin $ZONENAME \
+ /usr/bin/svcs -H svc:/milestone/single-user:default 2>&1 |
+ /usr/bin/nawk '{
+ if ($1 == "online")
+ exit 0
+ else
+ exit 1
+ }' && break
+ done
+
+ if (( $i == 9 )); then
+ vlog "$e_nosingleuser"
+ fi
+
+ echo "yes" | /usr/sbin/zlogin -S $ZONENAME \
+ /usr/sbin/sys-unconfig >/dev/null 2>&1
+ if (( $? != 0 )); then
+ error "$e_unconfig"
+ failed=1
+ fi
+fi
+
+
+if [[ -n $failed ]]; then
+ fatal "$e_exitfail"
+fi
+
+vlog "$v_exitgood"
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/pkgrm.conf Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SVr4 packages which should be removed when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option). Site-specific packages which must be
+# removed should be listed in this file. During the zone installation, the
+# packages will be removed if they existed on the original physical system.
+#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/pkgrm.lst Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SVr4 packages which should be removed when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option). Do not edit this file. Site-specific
+# packages which must be removed should be listed in the
+# /etc/brand/native/pkgrm.conf file. During the zone installation, the
+# packages will be removed if they existed on the original physical system.
+#
+VRTSvxvm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/smf_disable.conf Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SMF services which should be disabled when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option). Site-specific services which must be
+# disabled should be listed in this file. During the zone installation, the
+# services will be disabled if they existed on the original physical system.
+#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/smf_disable.lst Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SMF services which should be disabled when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option). Do not edit this file. Site-specific
+# services which must be disabled should be listed in the
+# /etc/brand/native/smf_disable.conf file. During the zone installation, the
+# services will be disabled if they existed on the original physical system.
+#
+svc:/network/smb/server
+svc:/system/virtualbox/vboxservice
--- a/usr/src/lib/brand/native/zone/sw_support.c Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/sw_support.c Wed Feb 11 09:33:05 2009 -0700
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* sw_support does install, detach and attach processing for svr4 pkgs.
*/
@@ -3646,23 +3644,62 @@
return (res);
}
+static boolean_t
+add_opts(char *buf, int bsize, char opt, char *arg)
+{
+ char argbuf[MAXPATHLEN];
+
+ if (snprintf(argbuf, sizeof (argbuf), " -%c '%s'", opt, arg)
+ > sizeof (argbuf) || strlcat(buf, argbuf, bsize) >= bsize) {
+ (void) fprintf(stderr, gettext("Command line too long"));
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+static boolean_t
+add_opt(char *buf, int bsize, char opt)
+{
+ char argbuf[4];
+
+ (void) snprintf(argbuf, sizeof (argbuf), " -%c", opt);
+ if (strlcat(buf, argbuf, bsize) >= bsize) {
+ (void) fprintf(stderr, gettext("Command line too long"));
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
static void
install_usage()
{
- (void) fprintf(stderr, gettext("usage:\t%s brand options: none\n"),
+ (void) fprintf(stderr, gettext("usage:\t%s brand options:\n"
+ "\tWith no options the zone is freshly installed:\n"
+ "\t\tinstall\n"
+ "\tAlternatively, the zone may be installed using an existing\n"
+ "\tsystem image from an archive or a directory:\n"
+ "\t\tinstall -a archive (-u | -p) [-v | -s] [-b patchid]*\n"
+ "\t\tinstall -d directory (-u | -p) [-v | -s] [-b patchid]*\n"),
MY_BRAND_NAME);
}
static int
install_func(int argc, char *argv[])
{
- char cmdbuf[MAXPATHLEN];
+ char cmdbuf[NCARGS];
+ char argbuf[NCARGS];
int arg;
int status;
+ boolean_t image_install = B_FALSE;
+ char image_install_arg = '\0';
+
+ argbuf[0] = '\0';
opterr = 0;
optind = 0;
- while ((arg = getopt(argc, argv, "?x:")) != EOF) {
+ while ((arg = getopt(argc, argv, "?a:b:d:psuvx:")) != EOF) {
switch (arg) {
case '?':
if (optopt != '?') {
@@ -3672,6 +3709,50 @@
}
install_usage();
return (optopt == '?' ? Z_OK : ZONE_SUBPROC_USAGE);
+
+ case 'a':
+ if (image_install) {
+ install_usage();
+ return (ZONE_SUBPROC_USAGE);
+ }
+ image_install = B_TRUE;
+ if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+ return (Z_ERR);
+ break;
+ case 'b':
+ image_install_arg = optopt;
+ if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+ return (Z_ERR);
+ break;
+ case 'd':
+ if (image_install) {
+ install_usage();
+ return (ZONE_SUBPROC_USAGE);
+ }
+ image_install = B_TRUE;
+ if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+ return (Z_ERR);
+ break;
+ case 'p':
+ image_install_arg = optopt;
+ if (add_opt(argbuf, sizeof (argbuf), arg))
+ return (Z_ERR);
+ break;
+ case 's':
+ image_install_arg = optopt;
+ if (add_opt(argbuf, sizeof (argbuf), arg))
+ return (Z_ERR);
+ break;
+ case 'u':
+ image_install_arg = optopt;
+ if (add_opt(argbuf, sizeof (argbuf), arg))
+ return (Z_ERR);
+ break;
+ case 'v':
+ image_install_arg = optopt;
+ if (add_opt(argbuf, sizeof (argbuf), arg))
+ return (Z_ERR);
+ break;
case 'x':
if (strcmp(optarg, "nodataset") != 0) {
(void) fprintf(stderr, gettext("%s brand: "
@@ -3693,9 +3774,70 @@
return (ZONE_SUBPROC_USAGE);
}
- if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/lu/lucreatezone -z %s",
- zonename) >= sizeof (cmdbuf))
- return (Z_ERR);
+ /*
+ * Either install the zone using a system image or using the
+ * traditional lu support.
+ */
+ if (image_install) {
+ if (snprintf(cmdbuf, sizeof (cmdbuf),
+ "/usr/lib/brand/native/image_install %s %s %s", zonename,
+ zonepath, argbuf) >= sizeof (cmdbuf))
+ return (Z_ERR);
+
+ } else {
+ struct stat stbuf;
+ char rootpath[MAXPATHLEN]; /* zone root path */
+
+ if (snprintf(rootpath, sizeof (rootpath), "%s/root", zonepath)
+ >= sizeof (rootpath)) {
+ (void) fprintf(stderr,
+ gettext("Zonepath %s is too long.\n"), zonepath);
+ return (Z_ERR);
+ }
+
+ if (stat(rootpath, &stbuf) == 0) {
+ struct dirent *dp;
+ DIR *dirp;
+ boolean_t empty = B_TRUE;
+
+ if ((dirp = opendir(rootpath)) == NULL) {
+ (void) fprintf(stderr, gettext("Could not "
+ "open rootpath %s\n"), rootpath);
+ return (Z_ERR);
+ }
+
+ /* Verify that the dir is empty. */
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+
+ empty = B_FALSE;
+ break;
+ }
+ (void) closedir(dirp);
+
+ if (!empty) {
+ (void) fprintf(stderr, gettext("Zonepath root "
+ "%s exists and contains data; remove or "
+ "move aside prior to install.\n"),
+ rootpath);
+ return (Z_ERR);
+ }
+ }
+
+ if (image_install_arg != '\0') {
+ (void) fprintf(stderr, gettext("%s brand: option: %c "
+ "is only valid with -a or -d\n"), MY_BRAND_NAME,
+ image_install_arg);
+ return (ZONE_SUBPROC_USAGE);
+ }
+
+ if (snprintf(cmdbuf, sizeof (cmdbuf),
+ "/usr/lib/lu/lucreatezone -z %s", zonename) >=
+ sizeof (cmdbuf))
+ return (Z_ERR);
+ }
/*
* According to the Application Packaging Developer's Guide, a
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c Wed Feb 11 09:33:05 2009 -0700
@@ -7161,6 +7161,14 @@
return (Z_OK);
}
+boolean_t
+zonecfg_lock_file_held(int *lockfd)
+{
+ if (*lockfd >= 0 || zone_lock_cnt > 0)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
static boolean_t
get_doorname(const char *zone_name, char *buffer)
{
--- a/usr/src/lib/libzonecfg/common/mapfile-vers Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers Wed Feb 11 09:33:05 2009 -0700
@@ -146,6 +146,7 @@
zonecfg_init_lock_file;
zonecfg_is_rctl;
zonecfg_is_scratch;
+ zonecfg_lock_file_held;
zonecfg_lock_scratch;
zonecfg_lookup_attr;
zonecfg_lookup_dev;
--- a/usr/src/pkgdefs/SUNWzoner/prototype_com Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/pkgdefs/SUNWzoner/prototype_com Wed Feb 11 09:33:05 2009 -0700
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -49,6 +47,10 @@
# SUNWzoner
#
d none etc 755 root sys
+d none etc/brand 755 root sys
+d none etc/brand/native 755 root sys
+e none etc/brand/native/pkgrm.conf 644 root sys
+e none etc/brand/native/smf_disable.conf 644 root sys
d none etc/zones 755 root sys
e preserve etc/zones/index 644 root sys
f none etc/zones/SUNWdefault.xml 444 root bin
--- a/usr/src/pkgdefs/SUNWzoneu/prototype_com Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/pkgdefs/SUNWzoneu/prototype_com Wed Feb 11 09:33:05 2009 -0700
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -54,8 +52,14 @@
d none usr/lib/brand/native 755 root sys
f none usr/lib/brand/native/attach_update 755 root bin
f none usr/lib/brand/native/config.xml 444 root bin
+f none usr/lib/brand/native/image_install 755 root bin
+f none usr/lib/brand/native/p2v 755 root bin
+f none usr/lib/brand/native/pkgrm.lst 444 root bin
f none usr/lib/brand/native/platform.xml 444 root bin
+f none usr/lib/brand/native/smf_disable.lst 444 root bin
f none usr/lib/brand/native/sw_support 755 root bin
+d none usr/lib/brand/shared 755 root sys
+f none usr/lib/brand/shared/common.ksh 444 root bin
f none usr/lib/libbrand.so.1 755 root bin
f none usr/lib/libzonecfg.so.1 755 root bin
d none usr/lib/zones 755 root bin