Print this page
OS-192 zone_create() warning on headnode

@@ -21,10 +21,11 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
  */
 
 /*
  * zoneadm is a command interpreter for zone administration.  It is all in
  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.

@@ -99,10 +100,11 @@
         zone_state_t    zstate_num;
         char            zbrand[MAXNAMELEN];
         char            zroot[MAXPATHLEN];
         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
         zone_iptype_t   ziptype;
+        zoneid_t        zdid;
 } zone_entry_t;
 
 #define CLUSTER_BRAND_NAME      "cluster"
 
 static zone_entry_t *zents;

@@ -441,10 +443,11 @@
                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
                     "IP");
         }
         if (!verbose) {
                 char *cp, *clim;
+                char zdid[80];
 
                 if (!parsable) {
                         (void) printf("%s\n", zent->zname);
                         return;
                 }

@@ -456,12 +459,16 @@
                 cp = zent->zroot;
                 while ((clim = strchr(cp, ':')) != NULL) {
                         (void) printf("%.*s\\:", clim - cp, cp);
                         cp = clim + 1;
                 }
-                (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
-                    ip_type_str);
+                if (zent->zdid == -1)
+                        zdid[0] = '\0';
+                else
+                        (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid);
+                (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
+                    ip_type_str, zdid);
                 return;
         }
         if (zent->zstate_str != NULL) {
                 if (zent->zid == ZONE_ID_UNDEFINED)
                         (void) printf("%*s", ZONEID_WIDTH, "-");

@@ -552,10 +559,26 @@
         if (zid == GLOBAL_ZONEID) {
                 zent->ziptype = ZS_SHARED;
                 return (Z_OK);
         }
 
+        if ((handle = zonecfg_init_handle()) == NULL) {
+                zperror2(zent->zname, gettext("could not init handle"));
+                return (Z_ERR);
+        }
+        if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
+                zperror2(zent->zname, gettext("could not get handle"));
+                zonecfg_fini_handle(handle);
+                return (Z_ERR);
+        }
+
+        if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
+                zperror2(zent->zname, gettext("could not get ip-type"));
+                zonecfg_fini_handle(handle);
+                return (Z_ERR);
+        }
+
         /*
          * There is a race condition where the zone could boot while
          * we're walking the index file.  In this case the zone state
          * could be seen as running from the call above, but the zoneid
          * would be undefined.

@@ -572,30 +595,16 @@
                     sizeof (flags)) >= 0) {
                         if (flags & ZF_NET_EXCL)
                                 zent->ziptype = ZS_EXCLUSIVE;
                         else
                                 zent->ziptype = ZS_SHARED;
-                        return (Z_OK);
                 }
         }
 
-        if ((handle = zonecfg_init_handle()) == NULL) {
-                zperror2(zent->zname, gettext("could not init handle"));
-                return (Z_ERR);
-        }
-        if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
-                zperror2(zent->zname, gettext("could not get handle"));
-                zonecfg_fini_handle(handle);
-                return (Z_ERR);
-        }
+        zent->zdid = zonecfg_get_did(handle);
 
-        if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
-                zperror2(zent->zname, gettext("could not get ip-type"));
                 zonecfg_fini_handle(handle);
-                return (Z_ERR);
-        }
-        zonecfg_fini_handle(handle);
 
         return (Z_OK);
 }
 
 /*

@@ -2790,10 +2799,65 @@
                 return_code = Z_ERR;
 
         return (return_code);
 }
 
+/*
+ * Called when readying or booting a zone.  We double check that the zone's
+ * debug ID is set and is unique.  This covers the case of pre-existing zones
+ * with no ID.  Also, its possible that a zone was migrated to this host
+ * and as a result it has a duplicate ID.  In this case we preserve the ID
+ * of the first zone we match on in the index file (since it was there before
+ * the current zone) and we assign a new unique ID to the current zone.
+ * Return true if we assigned a new ID, indicating that the zone configuration
+ * needs to be saved.
+ */
+static boolean_t
+verify_fix_did(zone_dochandle_t handle)
+{
+        zoneid_t mydid;
+        zone_entry_t zent;
+        FILE *cookie;
+        char *name;
+        boolean_t fix = B_FALSE;
+
+        mydid = zonecfg_get_did(handle);
+        if (mydid == -1) {
+                zonecfg_set_did(handle);
+                return (B_TRUE);
+        }
+
+        /* Get the full list of zones from the configuration. */
+        cookie = setzoneent();
+        while ((name = getzoneent(cookie)) != NULL) {
+                if (strcmp(target_zone, name) == 0) {
+                        free(name);
+                        break;  /* Once we find our entry, stop. */
+                }
+
+                if (strcmp(name, "global") == 0 ||
+                    lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
+                        free(name);
+                        continue;
+                }
+
+                free(name);
+                if (zent.zdid == mydid) {
+                        fix = B_TRUE;
+                        break;
+                }
+        }
+        endzoneent(cookie);
+
+        if (fix) {
+                zonecfg_set_did(handle);
+                return (B_TRUE);
+        }
+
+        return (B_FALSE);
+}
+
 static int
 verify_details(int cmd_num, char *argv[])
 {
         zone_dochandle_t handle;
         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];

@@ -2849,10 +2913,16 @@
         }
 
         if (verify_handle(cmd_num, handle, argv) != Z_OK)
                 return_code = Z_ERR;
 
+        if (cmd_num == CMD_READY || cmd_num == CMD_BOOT)
+                if (verify_fix_did(handle))
+                        if (zonecfg_save(handle) != Z_OK)
+                                (void) fprintf(stderr, gettext("Could not save "
+                                    "debug ID.\n"));
+
         zonecfg_fini_handle(handle);
         if (return_code == Z_ERR)
                 (void) fprintf(stderr,
                     gettext("%s: zone %s failed to verify\n"),
                     execname, target_zone);