Print this page
PSARC 2008/766 native zones p2v
6667924 physical to virtual utility for native zones

@@ -18,11 +18,11 @@
  *
  * 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.
  */
 
 /*
  * zoneadm is a command interpreter for zone administration.  It is all in

@@ -100,11 +100,10 @@
 
 #define CLUSTER_BRAND_NAME      "cluster"
 
 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))
 
 struct net_if {

@@ -1085,14 +1084,10 @@
                         (void) fprintf(stderr,
                             gettext("Zonepath %s is too long.\n"), rpath);
                         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 "
                                     "zone.\nUse attach or remove %s "
                                     "directory.\n"), cmd_to_str(cmd_num),

@@ -1117,39 +1112,13 @@
                         if ((stbuf.st_mode & 0777) != 0755) {
                                 (void) fprintf(stderr, gettext("%s mode is not "
                                     "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);
-                        }
-
-                }
-        }
-
         return (err ? Z_ERR : Z_OK);
 }
 
 static int
 invoke_brand_handler(int cmd_num, char *argv[])

@@ -1711,10 +1680,21 @@
                                     zone_state_str(ZONE_STATE_CONFIGURED));
                                 return (Z_ERR);
                         }
                         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) {
                                 zerror(gettext("is already %s."),
                                     zone_state_str(ZONE_STATE_INSTALLED));

@@ -1733,19 +1713,15 @@
                 case CMD_MOUNT:
                 case CMD_MARK:
                         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),
                                     cmd_to_str(cmd_num));
                                 return (Z_ERR);

@@ -4623,20 +4599,24 @@
         char *manifest_path;
         char tmpmanifest[80];
         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"));
                 return (Z_ERR);
         }
 
         /* 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 == '?') {
                                 sub_usage(SHELP_ATTACH, CMD_ATTACH);
                                 brand_help = B_TRUE;

@@ -4649,14 +4629,29 @@
                 case 'n':
                         execute = B_FALSE;
                         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) {
                 force = B_FALSE;
                 execute = B_TRUE;

@@ -4674,11 +4669,11 @@
          * configured for this option.
          */
         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);
                 }
 

@@ -4747,18 +4742,18 @@
                 /*
                  * Not a force-attach, so we need to actually do the work.
                  */
                 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;
                                 }
 

@@ -4797,11 +4792,11 @@
             (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
                 errno = err;
                 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;
 
         /* If we have a brand postattach hook, run it. */
         if (err == Z_OK && !force && postcmdbuf[0] != '\0') {

@@ -5116,14 +5111,42 @@
 
 static int
 mark_func(int argc, char *argv[])
 {
         int err, lockfd;
+        int arg;
+        boolean_t force = B_FALSE;
+        int state;
 
-        if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
+        optind = 0;
+        opterr = 0;
+        while ((arg = getopt(argc, argv, "F")) != EOF) {
+                switch (arg) {
+                case 'F':
+                        force = B_TRUE;
+                        break;
+                default:
                 return (Z_USAGE);
-        if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
+                }
+        }
+
+        if (argc != (optind + 1))
+                return (Z_USAGE);
+
+        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);
 
         /*
          * Invoke brand-specific handler.

@@ -5135,11 +5158,11 @@
                 zerror(gettext("another %s may have an operation in progress."),
                     "zoneadm");
                 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"));
         }
         zonecfg_release_lock_file(target_zone, lockfd);

@@ -5590,11 +5613,10 @@
                 if (zone_get_brand(target_zone, target_brand,
                     sizeof (target_brand)) != Z_OK) {
                         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]);
 
         return (err);