6945131 SMF should support multiple administrative profiles
authorTruong Nguyen <Truong.Q.Nguyen@Sun.COM>
Sat, 15 May 2010 15:42:08 -0700
changeset 12418 1acff790c718
parent 12417 0748cebf4fed
child 12419 cc09af548fc8
6945131 SMF should support multiple administrative profiles 6945268 awk syntax error in /lib/svc/method/manifest-import 6945638 broken /var/svc/profile/platform.xml after upgrade to 137
usr/src/Targetdirs
usr/src/cmd/svc/common/manifest_find.c
usr/src/cmd/svc/common/manifest_find.h
usr/src/cmd/svc/milestone/manifest-import
usr/src/cmd/svc/svccfg/svccfg_engine.c
usr/src/pkg/manifests/SUNWcs.mf
--- a/usr/src/Targetdirs	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/Targetdirs	Sat May 15 15:42:08 2010 -0700
@@ -19,8 +19,7 @@
 #
 
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 #
@@ -152,6 +151,7 @@
 	/etc/sfw \
 	/etc/svc \
 	/etc/svc/profile \
+	/etc/svc/profile/site \
 	/etc/svc/volatile \
 	/etc/tm  \
 	/etc/usb   \
--- a/usr/src/cmd/svc/common/manifest_find.c	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/cmd/svc/common/manifest_find.c	Sat May 15 15:42:08 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -164,15 +163,19 @@
 /*
  * This function is called by nftw(3C) every time that it finds an object
  * in a directory of interest.  If the object is a file, process() checks
- * to see if it is a manifest file by insuring that it has a .xml
+ * to see if it is a service bundle file by insuring that it has a .xml
  * extension.
  *
- * If the file is a manifest file, and the CHECKHASH flag is set process()
- * calls mhash_test_file() to see if it is a new manifest.  Manfest data
- * for selected manifests is added to tsd_array in our thread specific data.
+ * If the file is a service bundle file, and the CHECKHASH flag is set process()
+ * calls mhash_test_file() to see if it is a new bundle.  Bundle file data
+ * for selected bundles is added to tsd_array in our thread specific data.
+ *
+ * Assume given file is a manifest unless BUNDLE_PROF flag is set to indicate
+ * it's a profile. For profile bundles, call mhash_test_file() with the
+ * appropriate argument.
  *
  * The CHECKEXT flag may be set if this was not a directory search request
- * but a single manifest file check that was determined by the caller to
+ * but a single service bundle file check that was determined by the caller to
  * be found based not on the extension of the file.
  */
 /*ARGSUSED*/
@@ -180,6 +183,7 @@
 process(const char *fn, const struct stat *sp, int ftw_type,
     struct FTW *ftws)
 {
+	int is_profile;
 	char *suffix_match;
 	uchar_t hash[MHASH_SIZE];
 	char *pname;
@@ -203,8 +207,9 @@
 	}
 
 	if (tsdp->tsd_flags & CHECKHASH) {
-		if (mhash_test_file(tsdp->tsd_hndl, fn, 0, &pname, hash) ==
-		    MHASH_NEWFILE) {
+		is_profile = (tsdp->tsd_flags & BUNDLE_PROF) ? 1 : 0;
+		if (mhash_test_file(tsdp->tsd_hndl, fn, is_profile, &pname,
+		    hash) == MHASH_NEWFILE) {
 			return (add_pointer(tsdp, fn, pname, hash));
 		}
 	} else {
@@ -216,22 +221,22 @@
 
 /*
  * This function returns a pointer to an array of manifest_info_t pointers.
- * There is one manifest_info_t pointer for each manifest file in the
+ * There is one manifest_info_t pointer for each service bundle file in the
  * directory, dir, that satifies the selection criteria.  The array is
  * returned to arrayp.  The array will be terminated with a NULL pointer.
  * It is the responsibility of the caller to free the memory associated
  * with the array by calling free_manifest_array().
  *
  * flags :
- * 	0x1 - CHECKHASH - do the hash check and only return manifest
+ * 	0x1 - CHECKHASH - do the hash check and only return bundle
  * 	files that do not have a hash entry in the smf/manifest table
- * 	or the hash value has changed due to the manifest file having
- * 	been modified.  If not set then all manifest files found are
- * 	returned, regardless of the hash status.
+ * 	or the hash value has changed due to the bundle file having
+ * 	been modified.  If not set then all service bundle files found
+ * 	are returned, regardless of the hash status.
  *
  * 	0x2 - CHECKEXT - Check the extension of the file is .xml
  *
- * On success a count of the number of selected manifests is returned.
+ * On success a count of the number of selected bundles is returned.
  * Note, however, that *arrayp will be set to NULL if the selection is
  * empty, and a count of 0 will be returned.  In the case of failure, -1
  * will be returned and errno will be set.
--- a/usr/src/cmd/svc/common/manifest_find.h	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/cmd/svc/common/manifest_find.h	Sat May 15 15:42:08 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _MANIFEST_FIND_H
@@ -36,6 +35,8 @@
 
 #define	CHECKHASH	0x1
 #define	CHECKEXT	0x2
+#define	BUNDLE_PROF	0x4
+#define	BUNDLE_MFST	0x8
 
 typedef struct manifest_info {
 	const char	*mi_path;	/* Path of manifest file */
@@ -44,7 +45,7 @@
 } manifest_info_t;
 
 /*
- * Declare functions that are used for finding manifest files in a
+ * Declare functions that are used for finding service bundle files in a
  * directory.
  */
 
--- a/usr/src/cmd/svc/milestone/manifest-import	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/cmd/svc/milestone/manifest-import	Sat May 15 15:42:08 2010 -0700
@@ -19,9 +19,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 # 0a  Initialization.
@@ -33,6 +31,7 @@
 activity=false
 
 EMI_SERVICE="svc:/system/early-manifest-import:default"
+PROFILE_DIR_SITE="/etc/svc/profile/site"
 
 X=
 early=false
@@ -59,7 +58,7 @@
 function cleanup_needwork {
 	if [ "$early" == true ]; then
 		smfmfiles=`/usr/bin/svcprop smf/manifest | \
-		    awk '(/^lib_) && (/\/manifestfile /) {print $3}'`
+		    awk '(/^lib_/ && /\/manifestfile /) {print $3}'`
 	else
 		smfmfiles=`/usr/bin/svcprop smf/manifest | \
 		    awk '/\/manifestfile / {print $3}'`
@@ -164,9 +163,11 @@
 	generic_prof="/var/svc/profile/generic.xml"
 	ns_prof="/var/svc/profile/name_service.xml"
 	inetd_prof="/var/svc/profile/inetd_services.xml"
+	platform_prof="/var/svc/profile/platform.xml"
 	[ -L "$generic_prof" ] && mv $generic_prof /etc/svc/profile/
 	[ -L "$ns_prof" ] && mv $ns_prof /etc/svc/profile/
 	[ -L "$inetd_prof" ] && mv $inetd_prof /etc/svc/profile/
+	[ -L "$platform_prof" ] && mv $platform_prof /etc/svc/profile/
 
 	return 0
 }
@@ -318,11 +319,16 @@
 }
 
 #
-# 5.  Site profile is applied last to give administrator the final say.
+# 5.  Giving administrator the final say, apply site.xml profile and profiles
+#     under /etc/svc/profile/site directory.
 #
 function apply_site_profile {
         typeset prefix="$1/svc/profile"
 	[ -f $prefix/site.xml ] && svccfg_apply $prefix/site.xml
+
+	if [ -d $PROFILE_DIR_SITE -a "$1" = "/etc" ]; then
+		svccfg_apply $PROFILE_DIR_SITE
+	fi
 }
 
 #
--- a/usr/src/cmd/svc/svccfg/svccfg_engine.c	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/cmd/svc/svccfg/svccfg_engine.c	Sat May 15 15:42:08 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ *  Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 
@@ -852,23 +851,12 @@
 	return (r);
 }
 
-int
-engine_apply(const char *file, int apply_changes)
+static int
+apply_profile(manifest_info_t *info, int apply_changes)
 {
-	int ret;
-	bundle_t *b;
-	char *pname;
-	uchar_t hash[MHASH_SIZE];
+	bundle_t *b = internal_bundle_new();
 
-	lscf_prep_hndl();
-
-	ret = mhash_test_file(g_hndl, file, 1, &pname, hash);
-	if (ret != MHASH_NEWFILE)
-		return (ret);
-
-	b = internal_bundle_new();
-
-	if (lxml_get_bundle_file(b, file, SVCCFG_OP_APPLY) != 0) {
+	if (lxml_get_bundle_file(b, info->mi_path, SVCCFG_OP_APPLY) != 0) {
 		internal_bundle_free(b);
 		return (-1);
 	}
@@ -878,30 +866,124 @@
 		return (0);
 	}
 
-	if (lscf_bundle_apply(b, file) != 0) {
+	if (lscf_bundle_apply(b, info->mi_path) != 0) {
 		internal_bundle_free(b);
 		return (-1);
 	}
 
 	internal_bundle_free(b);
 
-	if (pname) {
+	if (info->mi_prop) {
 		apply_action_t apply;
 		char *errstr;
 
 		apply = (est->sc_in_emi == 1) ? APPLY_LATE : APPLY_NONE;
-		if (mhash_store_entry(g_hndl, pname, file, hash, apply,
-		    &errstr)) {
+		if (mhash_store_entry(g_hndl, info->mi_prop, info->mi_path,
+		    info->mi_hash, apply, &errstr)) {
 			semerr(errstr);
 		}
-
-		free(pname);
 	}
 
 	return (0);
 }
 
 int
+engine_apply(const char *file, int apply_changes)
+{
+	int rc = 0;
+	int isdir;
+	int dont_exit;
+	int profile_count;
+	int fm_flags;
+	struct stat sb;
+	manifest_info_t **profiles = NULL;
+	manifest_info_t **entry;
+	manifest_info_t *pfile;
+
+	lscf_prep_hndl();
+
+	/* Determine which profile(s) must be applied. */
+
+	profile_count = 0;
+	fm_flags = BUNDLE_PROF | CHECKHASH;
+
+	/* Determine if argument is a directory or file. */
+	if (stat(file, &sb) == -1) {
+		semerr(gettext("Unable to stat file %s.  %s\n"), file,
+		    strerror(errno));
+		rc = -1;
+		goto out;
+	}
+
+	if (sb.st_mode & S_IFDIR) {
+		fm_flags |= CHECKEXT;
+		isdir = 1;
+	} else if (sb.st_mode & S_IFREG) {
+		isdir = 0;
+	} else {
+		semerr(gettext("%s is not a directory or regular "
+		    "file\n"), file);
+		rc = -1;
+		goto out;
+	}
+
+	/* Get list of profiles to be applied. */
+	if ((profile_count = find_manifests(file, &profiles, fm_flags)) < 0) {
+		if (isdir) {
+			semerr(gettext("Could not hash directory %s\n"), file);
+		} else {
+			semerr(gettext("Could not hash file %s\n"), file);
+		}
+		rc = -1;
+		goto out;
+	}
+
+	if (profile_count == 0) {
+		/* No profiles to process. */
+		if (g_verbose) {
+			warn(gettext("No changes were necessary\n"));
+		}
+		goto out;
+	}
+
+	/*
+	 * We don't want to exit if we encounter an error.  We should go ahead
+	 * and process all of the profiles.
+	 */
+	dont_exit = est->sc_cmd_flags & SC_CMD_DONT_EXIT;
+	est->sc_cmd_flags |= SC_CMD_DONT_EXIT;
+
+	for (entry = profiles; *entry != NULL; entry++) {
+		pfile = *entry;
+
+		if (apply_profile(pfile, apply_changes) == 0) {
+			if (g_verbose) {
+				warn(gettext("Successfully applied: %s\n"),
+				    pfile->mi_path);
+			}
+		} else {
+			warn(gettext("WARNING: Failed to apply %s\n"),
+			    pfile->mi_path);
+			rc = -1;
+		}
+	}
+
+	if (dont_exit == 0)
+		est->sc_cmd_flags &= ~SC_CMD_DONT_EXIT;
+
+	/* exit(1) appropriately if any profile failed to be applied. */
+	if ((rc == -1) &&
+	    (est->sc_cmd_flags & (SC_CMD_IACTIVE | SC_CMD_DONT_EXIT)) == 0) {
+		free_manifest_array(profiles);
+		exit(1);
+	}
+
+out:
+	free_manifest_array(profiles);
+	return (rc);
+}
+
+int
 engine_restore(const char *file)
 {
 	bundle_t *b;
--- a/usr/src/pkg/manifests/SUNWcs.mf	Fri May 14 22:03:24 2010 -0700
+++ b/usr/src/pkg/manifests/SUNWcs.mf	Sat May 15 15:42:08 2010 -0700
@@ -75,6 +75,7 @@
 dir path=etc/skel group=sys
 dir path=etc/svc group=sys
 dir path=etc/svc/profile group=sys
+dir path=etc/svc/profile/site group=sys
 dir path=etc/svc/volatile group=sys
 dir path=etc/sysevent group=sys
 dir path=etc/sysevent/config group=sys