changeset 10718:77613d4558c6

6866411 RFE: need a system boot brand hook
author jv227347 <Jordan.Vaughan@Sun.com>
date Mon, 05 Oct 2009 11:35:02 -0700
parents fe0545fc3cdd
children 203f5727fba9
files usr/src/cmd/zoneadm/svc-zones usr/src/cmd/zoneadm/zoneadm.c usr/src/cmd/zoneadm/zoneadm.h usr/src/lib/libbrand/common/libbrand.c usr/src/lib/libbrand/common/libbrand.h usr/src/lib/libbrand/common/mapfile-vers usr/src/lib/libbrand/dtd/brand.dtd.1
diffstat 7 files changed, 133 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/zoneadm/svc-zones	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/cmd/zoneadm/svc-zones	Mon Oct 05 11:35:02 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.
 
 . /lib/svc/share/smf_include.sh
@@ -54,6 +54,11 @@
 case "$1" in
 'start')
 	egrep -vs '^#|^global:' /etc/zones/index || exit 0  # no local zones
+
+	#
+	# Boot the installed zones for which the "autoboot" zone property is
+	# set and invoke the sysboot hook for all other installed zones.
+	#
 	ZONES=""
 	for zone in `zoneadm list -pi | nawk -F: '{
 			if ($3 == "installed") {
@@ -72,8 +77,11 @@
 			# to be in an orphaned contract.
 			#
 			zoneadm -z $zone boot &
+		else
+			zoneadm -z $zone sysboot &
 		fi
 	done
+
 	#
 	# Wait for all zoneadm processes to finish before allowing the
 	# start method to exit.
--- a/usr/src/cmd/zoneadm/zoneadm.c	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/cmd/zoneadm/zoneadm.c	Mon Oct 05 11:35:02 2009 -0700
@@ -162,6 +162,7 @@
 static int attach_func(int argc, char *argv[]);
 static int mark_func(int argc, char *argv[]);
 static int apply_func(int argc, char *argv[]);
+static int sysboot_func(int argc, char *argv[]);
 static int sanity_check(char *zone, int cmd_num, boolean_t running,
     boolean_t unsafe_when_running, boolean_t force);
 static int cmd_match(char *cmd);
@@ -188,7 +189,8 @@
 	{ CMD_DETACH,		"detach",	SHELP_DETACH,	detach_func },
 	{ CMD_ATTACH,		"attach",	SHELP_ATTACH,	attach_func },
 	{ CMD_MARK,		"mark",		SHELP_MARK,	mark_func },
-	{ CMD_APPLY,		"apply",	NULL,		apply_func }
+	{ CMD_APPLY,		"apply",	NULL,		apply_func },
+	{ CMD_SYSBOOT,		"sysboot",	NULL,		sysboot_func }
 };
 
 /* global variables */
@@ -1697,6 +1699,14 @@
 				return (Z_ERR);
 			}
 			break;
+		case CMD_SYSBOOT:
+			if (state != ZONE_STATE_INSTALLED) {
+				zerror(gettext("%s operation is invalid for %s "
+				    "zones."), cmd_to_str(cmd_num),
+				    zone_state_str(state));
+				return (Z_ERR);
+			}
+			break;
 		}
 	}
 	return (Z_OK);
@@ -5402,6 +5412,77 @@
 	return (res);
 }
 
+/*
+ * This is an undocumented interface that is invoked by the zones SMF service
+ * for installed zones that won't automatically boot.
+ */
+/* ARGSUSED */
+static int
+sysboot_func(int argc, char *argv[])
+{
+	int err;
+	zone_dochandle_t zone_handle;
+	brand_handle_t brand_handle;
+	char cmdbuf[MAXPATHLEN];
+	char zonepath[MAXPATHLEN];
+
+	/*
+	 * This subcommand can only be executed in the global zone on non-global
+	 * zones.
+	 */
+	if (zonecfg_in_alt_root())
+		return (usage(B_FALSE));
+	if (sanity_check(target_zone, CMD_SYSBOOT, B_FALSE, B_TRUE, B_FALSE) !=
+	    Z_OK)
+		return (Z_ERR);
+
+	/*
+	 * Fetch the sysboot hook from the target zone's brand.
+	 */
+	if ((zone_handle = zonecfg_init_handle()) == NULL) {
+		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
+		return (Z_ERR);
+	}
+	if ((err = zonecfg_get_handle(target_zone, zone_handle)) != Z_OK) {
+		errno = err;
+		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
+		zonecfg_fini_handle(zone_handle);
+		return (Z_ERR);
+	}
+	if ((err = zonecfg_get_zonepath(zone_handle, zonepath,
+	    sizeof (zonepath))) != Z_OK) {
+		errno = err;
+		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
+		zonecfg_fini_handle(zone_handle);
+		return (Z_ERR);
+	}
+	if ((brand_handle = brand_open(target_brand)) == NULL) {
+		zerror(gettext("missing or invalid brand during %s operation: "
+		    "%s"), cmd_to_str(CMD_SYSBOOT), target_brand);
+		zonecfg_fini_handle(zone_handle);
+		return (Z_ERR);
+	}
+	err = get_hook(brand_handle, cmdbuf, sizeof (cmdbuf), brand_get_sysboot,
+	    target_zone, zonepath);
+	brand_close(brand_handle);
+	zonecfg_fini_handle(zone_handle);
+	if (err != Z_OK) {
+		zerror(gettext("unable to get brand hook from brand %s for %s "
+		    "operation"), target_brand, cmd_to_str(CMD_SYSBOOT));
+		return (Z_ERR);
+	}
+
+	/*
+	 * If the hook wasn't defined (which is OK), then indicate success and
+	 * return.  Otherwise, execute the hook.
+	 */
+	if (cmdbuf[0] != '\0')
+		return ((subproc_status(gettext("brand sysboot operation"),
+		    do_subproc(cmdbuf), B_FALSE) == ZONE_SUBPROC_OK) ? Z_OK :
+		    Z_BRAND_ERROR);
+	return (Z_OK);
+}
+
 static int
 help_func(int argc, char *argv[])
 {
--- a/usr/src/cmd/zoneadm/zoneadm.h	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/cmd/zoneadm/zoneadm.h	Mon Oct 05 11:35:02 2009 -0700
@@ -44,9 +44,10 @@
 #define	CMD_ATTACH	14
 #define	CMD_MARK	15
 #define	CMD_APPLY	16
+#define	CMD_SYSBOOT	17
 
 #define	CMD_MIN		CMD_HELP
-#define	CMD_MAX		CMD_APPLY
+#define	CMD_MAX		CMD_SYSBOOT
 
 #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
 #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
--- a/usr/src/lib/libbrand/common/libbrand.c	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/lib/libbrand/common/libbrand.c	Mon Oct 05 11:35:02 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.
  */
 
@@ -72,6 +72,7 @@
 #define	DTD_ELEM_PRIVILEGE	((const xmlChar *) "privilege")
 #define	DTD_ELEM_QUERY		((const xmlChar *) "query")
 #define	DTD_ELEM_SYMLINK	((const xmlChar *) "symlink")
+#define	DTD_ELEM_SYSBOOT	((const xmlChar *) "sysboot")
 #define	DTD_ELEM_UNINSTALL	((const xmlChar *) "uninstall")
 #define	DTD_ELEM_USER_CMD	((const xmlChar *) "user_cmd")
 #define	DTD_ELEM_VALIDSNAP	((const xmlChar *) "validatesnap")
@@ -679,6 +680,15 @@
 }
 
 int
+brand_get_sysboot(brand_handle_t bh, const char *zonename,
+    const char *zonepath, char *buf, size_t len)
+{
+	struct brand_handle *bhp = (struct brand_handle *)bh;
+	return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
+	    buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE));
+}
+
+int
 brand_is_native(brand_handle_t bh)
 {
 	struct brand_handle *bhp = (struct brand_handle *)bh;
--- a/usr/src/lib/libbrand/common/libbrand.h	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/lib/libbrand/common/libbrand.h	Mon Oct 05 11:35:02 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.
  */
 
@@ -93,6 +93,8 @@
 extern int brand_get_verify_cfg(brand_handle_t, char *, size_t);
 extern int brand_get_verify_adm(brand_handle_t, const char *, const char *,
     char *, size_t);
+extern int brand_get_sysboot(brand_handle_t, const char *, const char *, char *,
+    size_t);
 
 extern int brand_config_iter_privilege(brand_handle_t,
     int (*func)(void *, priv_iter_t *), void *);
--- a/usr/src/lib/libbrand/common/mapfile-vers	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/lib/libbrand/common/mapfile-vers	Mon Oct 05 11:35:02 2009 -0700
@@ -63,6 +63,7 @@
 	brand_get_prestatechange;
 	brand_get_preuninstall;
 	brand_get_query;
+	brand_get_sysboot;
 	brand_get_uninstall;
 	brand_get_user_cmd;
 	brand_get_validatesnap;
--- a/usr/src/lib/libbrand/dtd/brand.dtd.1	Mon Oct 05 11:03:34 2009 -0700
+++ b/usr/src/lib/libbrand/dtd/brand.dtd.1	Mon Oct 05 11:35:02 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.
@@ -114,6 +114,27 @@
 <!ATTLIST boot>
 
 <!--
+  sysboot
+
+    This is a program that will be run by zoneadm during system boot for an
+    installed zone that won't automatically boot.
+
+    If the program succeeds, then it should not generate output.
+    If the program returns an error, then the output it generates will be
+    sent to the zones SMF service's message log.
+
+    The following replacements are performed:
+
+      %z	Name of the target zone
+      %R	Zonepath of the target zone
+      Additional arguments, if any, are appended.
+
+    This element has no attributes.
+-->
+<!ELEMENT sysboot	(#PCDATA) >
+<!ATTLIST sysboot>
+
+<!--
   halt
 
     This is a program which gets run by zoneadmd when a zone is being
@@ -568,9 +589,9 @@
 -->
 
 <!ELEMENT brand		(modname?, initname, login_cmd, user_cmd, install,
-			installopts?, boot?, halt?, verify_cfg?, verify_adm?,
-			postattach?, postclone?, postinstall?, predetach?,
-			attach?, detach?, clone?,
+			installopts?, boot?, sysboot?, halt?, verify_cfg?,
+			verify_adm?, postattach?, postclone?, postinstall?,
+			predetach?, attach?, detach?, clone?,
 			presnap?, postsnap?, validatesnap?,
 			preuninstall?, uninstall?,
 			prestatechange?, poststatechange?, query?,