Print this page
OS-200 need a better mechanism for storing persistent zone_did
Small comment-out because we don't include OS-200
OS-4019 zoneadm is slow with 1000s of zones
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-3429 Expose zone's init exit status
OS-399 zone phys. mem. cap should be a rctl and have associated kstat
        
*** 21,30 ****
--- 21,31 ----
  
  /*
   * 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 2015, 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,108 ****
--- 100,110 ----
          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,450 ****
--- 443,453 ----
                      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,467 ****
                  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);
                  return;
          }
          if (zent->zstate_str != NULL) {
                  if (zent->zid == ZONE_ID_UNDEFINED)
                          (void) printf("%*s", ZONEID_WIDTH, "-");
--- 459,474 ----
                  cp = zent->zroot;
                  while ((clim = strchr(cp, ':')) != NULL) {
                          (void) printf("%.*s\\:", clim - cp, cp);
                          cp = clim + 1;
                  }
!                 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,561 ****
--- 559,584 ----
          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,601 ****
                      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);
!         }
  
-         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);
  }
  
  /*
--- 595,610 ----
                      sizeof (flags)) >= 0) {
                          if (flags & ZF_NET_EXCL)
                                  zent->ziptype = ZS_EXCLUSIVE;
                          else
                                  zent->ziptype = ZS_SHARED;
                  }
          }
  
!         zent->zdid = zonecfg_get_did(handle);
  
          zonecfg_fini_handle(handle);
  
          return (Z_OK);
  }
  
  /*
*** 764,785 ****
  
  /*
   * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
   */
  static zone_entry_t *
! lookup_running_zone(const char *str)
  {
!         int i;
  
!         if (fetch_zents() != Z_OK)
                  return (NULL);
  
!         for (i = 0; i < nzents; i++) {
!                 if (strcmp(str, zents[i].zname) == 0)
!                         return (&zents[i]);
!         }
          return (NULL);
  }
  
  /*
   * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
   * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
--- 773,798 ----
  
  /*
   * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
   */
  static zone_entry_t *
! lookup_running_zone(const char *name)
  {
!         zoneid_t zid;
!         zone_entry_t *zent;
  
!         if ((zid = getzoneidbyname(name)) == -1)
                  return (NULL);
  
!         if ((zent = malloc(sizeof (zone_entry_t))) == NULL)
                  return (NULL);
+ 
+         if (lookup_zone_info(name, zid, zent) != Z_OK) {
+                 free(zent);
+                 return (NULL);
+         }
+         return (zent);
  }
  
  /*
   * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
   * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
*** 2781,2790 ****
--- 2794,2858 ----
                  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];
*** 2840,2849 ****
--- 2908,2929 ----
          }
  
          if (verify_handle(cmd_num, handle, argv) != Z_OK)
                  return_code = Z_ERR;
  
+         if (cmd_num == CMD_READY || cmd_num == CMD_BOOT) {
+                 int vcommit = 0, obscommit = 0;
+ 
+                 vcommit = verify_fix_did(handle);
+                 obscommit = zonecfg_fix_obsolete(handle);
+ 
+                 if (vcommit || obscommit)
+                         if (zonecfg_save(handle) != Z_OK)
+                                 (void) fprintf(stderr, gettext("Could not save "
+                                     "updated configuration.\n"));
+         }
+ 
          zonecfg_fini_handle(handle);
          if (return_code == Z_ERR)
                  (void) fprintf(stderr,
                      gettext("%s: zone %s failed to verify\n"),
                      execname, target_zone);
*** 3863,3876 ****
                          /*
                           * The SUNWattached.xml file is expected since it might
                           * exist if the zone was force-attached after a
                           * migration.
                           */
!         char            *std_entries[] = {"dev", "lu", "root",
!                             "SUNWattached.xml", NULL};
!                         /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
!         char            cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
  
          /*
           * We shouldn't need these checks but lets be paranoid since we
           * could blow away the whole system here if we got the wrong zonepath.
           */
--- 3943,3956 ----
                          /*
                           * The SUNWattached.xml file is expected since it might
                           * exist if the zone was force-attached after a
                           * migration.
                           */
!         char            *std_entries[] = {"dev", "lastexited", "logs", "lu",
!                             "root", "SUNWattached.xml", NULL};
!                         /* (MAXPATHLEN * 5) is for the 5 std_entries dirs */
!         char            cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 5) + 64];
  
          /*
           * We shouldn't need these checks but lets be paranoid since we
           * could blow away the whole system here if we got the wrong zonepath.
           */
*** 5373,5383 ****
          int err;
          int res = Z_OK;
          priv_set_t *privset;
          zoneid_t zoneid;
          zone_dochandle_t handle;
!         struct zone_mcaptab mcap;
          char pool_err[128];
  
          zoneid = getzoneid();
  
          if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
--- 5453,5463 ----
          int err;
          int res = Z_OK;
          priv_set_t *privset;
          zoneid_t zoneid;
          zone_dochandle_t handle;
!         uint64_t mcap;
          char pool_err[128];
  
          zoneid = getzoneid();
  
          if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
*** 5464,5486 ****
                          }
                  }
          }
  
          /*
!          * If a memory cap is configured, set the cap in the kernel using
!          * zone_setattr() and make sure the rcapd SMF service is enabled.
           */
!         if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
!                 uint64_t num;
                  char smf_err[128];
  
-                 num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
-                 if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
-                         zerror(gettext("could not set zone memory cap"));
-                         res = Z_ERR;
-                 }
- 
                  if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
                          zerror(gettext("enabling system/rcap service failed: "
                              "%s"), smf_err);
                          res = Z_ERR;
                  }
--- 5544,5559 ----
                          }
                  }
          }
  
          /*
!          * If a memory cap is configured, make sure the rcapd SMF service is
!          * enabled.
           */
!         if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &mcap) == Z_OK) {
                  char smf_err[128];
  
                  if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
                          zerror(gettext("enabling system/rcap service failed: "
                              "%s"), smf_err);
                          res = Z_ERR;
                  }