1013 TI shouldn't destroy 'rpool' on other than target disk
authorJan Damborsky <Jan.Damborsky@Sun.COM>
Tue, 08 Apr 2008 19:19:26 -0600
changeset 98 e6f4c48366dc
parent 97 e6b5bbb883f7
child 99 1c97afbc10fc
1013 TI shouldn't destroy 'rpool' on other than target disk
usr/src/lib/liborchestrator/orchestrator_api.h
usr/src/lib/liborchestrator/orchestrator_private.h
usr/src/lib/liborchestrator/perform_slim_install.c
usr/src/lib/libtd/td_mg.c
--- a/usr/src/lib/liborchestrator/orchestrator_api.h	Tue Apr 08 17:49:52 2008 -0700
+++ b/usr/src/lib/liborchestrator/orchestrator_api.h	Tue Apr 08 19:19:26 2008 -0600
@@ -297,6 +297,7 @@
 #define	OM_NO_UPGRADE_TARGET_NAME		112
 #define	OM_UNSUPPORTED_CONFIG			113
 #define	OM_TRANSFER_FAILED			114
+#define	OM_ZFS_ROOT_POOL_EXISTS			115
 
 #define	OM_NO_INSTALL_TARGET			201
 #define	OM_BAD_INSTALL_TARGET			202
--- a/usr/src/lib/liborchestrator/orchestrator_private.h	Tue Apr 08 17:49:52 2008 -0700
+++ b/usr/src/lib/liborchestrator/orchestrator_private.h	Tue Apr 08 19:19:26 2008 -0600
@@ -124,6 +124,7 @@
  * Definitions for ZFS pool
  */
 #define	ROOTPOOL_NAME		"rpool"
+#define	ROOTPOOL_TMPNAME	"rpool_tmp"
 #define	ROOTPOOL_SNAPSHOT	ROOTPOOL_NAME "@install"
 
 /*
--- a/usr/src/lib/liborchestrator/perform_slim_install.c	Tue Apr 08 17:49:52 2008 -0700
+++ b/usr/src/lib/liborchestrator/perform_slim_install.c	Tue Apr 08 19:19:26 2008 -0600
@@ -41,6 +41,7 @@
 #include <libgen.h>
 #include <netdb.h>
 #include <locale.h>
+#include <wait.h>
 
 #include "td_lib.h"
 #include "cl_database_parms.h"
@@ -186,7 +187,7 @@
 static void	notify_install_complete();
 static void	enable_nwam();
 static void	create_user_directory();
-static void	transfer_log_files(char *target);
+static int	call_transfer_module(char *target_dir, om_callback_t cb);
 static void	run_install_finish_script(char *target);
 static void 	setup_users_default_environ(char *target);
 static void	setup_etc_vfstab_for_zfs_root(char *target);
@@ -195,6 +196,11 @@
 static void	run_installgrub(char *target, char *device);
 static void	transfer_config_files(char *target);
 static void	handle_TM_callback(const int percent, const char *message);
+static int	prepare_zfs_root_pool_attrs(nvlist_t **attrs, char *disk_name);
+static int	prepare_be_container_fs_attrs(nvlist_t **attrs);
+static int	prepare_be_attrs(nvlist_t **attrs);
+static int	obtain_image_info(image_info_t *info);
+static char	*get_rootpool_id(char *rpool_name);
 
 void 		*do_transfer(void *arg);
 void		*do_ti(void *args);
@@ -451,6 +457,52 @@
 	snprintf(swap_device, sizeof (swap_device), "/dev/dsk/%ss1", name);
 
 	/*
+	 * delete temporary root pool if previously created.
+	 * It should be done in TI, but since we don't have simple
+	 * way for now, how to determine if disk is part of root pool
+	 * and we need to destroy it before TI starts to modify
+	 * disk partition table, destroy pool right now.
+	 */
+
+	ret = td_safe_system("/usr/sbin/zpool list " ROOTPOOL_TMPNAME, B_TRUE);
+	if ((ret == -1) || WEXITSTATUS(ret) != 0) {
+		om_debug_print(OM_DBGLVL_INFO, "Root pool " ROOTPOOL_TMPNAME
+		    " doesn't exist\n");
+	} else {
+		om_log_print("Root pool " ROOTPOOL_TMPNAME " already exists,"
+		    " will be destroyed\n");
+
+		ret = td_safe_system("/usr/sbin/zpool destroy -f "
+		    ROOTPOOL_TMPNAME, B_TRUE);
+
+		if ((ret == -1) || WEXITSTATUS(ret) != 0) {
+			om_log_print("Couldn't destroy " ROOTPOOL_TMPNAME
+			    " root pool\n");
+
+			om_set_error(OM_TARGET_INSTANTIATION_FAILED);
+			return (OM_FAILURE);
+		}
+	}
+
+	/*
+	 * if there is a root pool imported with name which will be finally
+	 * picked up by installer for target root pool, there is nothing
+	 * we can do at this point. Log warning message and exit.
+	 */
+
+	ret = td_safe_system("/usr/sbin/zpool list " ROOTPOOL_NAME, B_TRUE);
+	if ((ret == -1) || WEXITSTATUS(ret) != 0) {
+		om_debug_print(OM_DBGLVL_INFO, "Root pool " ROOTPOOL_NAME
+		    " doesn't exist\n");
+	} else {
+		om_log_print("Root pool " ROOTPOOL_NAME " exists,"
+		    " we can't proceed with the installation\n");
+
+		om_set_error(OM_ZFS_ROOT_POOL_EXISTS);
+		return (OM_FAILURE);
+	}
+
+	/*
 	 * Start a thread to call TI module for fdisk & vtoc targets.
 	 */
 
@@ -739,6 +791,9 @@
 	struct transfer_callback	*tcb_args;
 	nvlist_t			*transfer_attr;
 	int				status;
+	char				cmd[MAXPATHLEN];
+	char				*rpool_id;
+	int				ret;
 	void				*exit_val;
 
 	(void) pthread_join(ti_thread, &exit_val);
@@ -843,16 +898,95 @@
 		 * End of code to address temporary set hostid fix.
 		 */
 
-		run_install_finish_script(tcb_args->target);
-		reset_zfs_mount_property(tcb_args->target);
 		activate_be(INIT_BE_NAME);
 		run_installgrub(tcb_args->target, zfs_device);
 		transfer_config_files(tcb_args->target);
+		reset_zfs_mount_property(tcb_args->target);
+
+		/*
+		 * change the root pool name from temporary to the final one
+		 * [1] Get the pool id
+		 * [2] Export the pool
+		 * [3] Import the pool with new name - refer it by id obtained
+		 */
+
+		rpool_id = get_rootpool_id(ROOTPOOL_TMPNAME);
+
+		if (rpool_id == NULL) {
+			om_log_print("Couldn't obtain id for root pool");
+			status = -1;
+			notify_error_status(status);
+			pthread_exit((void *)&status);
+		} else
+			om_debug_print(OM_DBGLVL_INFO,
+			    ROOTPOOL_TMPNAME " id is %s\n", rpool_id);
+
+		ret = td_safe_system("/usr/sbin/zpool export -f "
+		    ROOTPOOL_TMPNAME, B_TRUE);
+
+		if ((ret == -1) || WEXITSTATUS(ret) != 0) {
+			om_log_print("Error: Couldn't export " ROOTPOOL_TMPNAME
+			    ", err = %d\n", ret);
+
+			free(rpool_id);
+			status = -1;
+			notify_error_status(status);
+			pthread_exit((void *)&status);
+		}
+
+		(void) snprintf(cmd, sizeof (cmd),
+		    "/usr/sbin/zpool import -f %s " ROOTPOOL_NAME, rpool_id);
+
+		free(rpool_id);
 
 		/*
-		 * Transfer log files to the destination
+		 * import is allowed to fail, since some datasets can
+		 * fail to mount
+		 */
+		(void) td_safe_system(cmd, B_TRUE);
+
+		/* check that pool is available */
+		(void) snprintf(cmd, sizeof (cmd),
+		    "/usr/sbin/zpool list " ROOTPOOL_NAME);
+
+		if ((ret == -1) || WEXITSTATUS(ret) != 0) {
+			om_log_print("Error: Couldn't import " ROOTPOOL_NAME
+			    "\n");
+
+			status = -1;
+			notify_error_status(status);
+			pthread_exit((void *)&status);
+		}
+
+		/*
+		 * mount "/" once more, since we need run
+		 * install finish scipt
 		 */
-		ls_transfer("/", tcb_args->target);
+
+		(void) snprintf(cmd, sizeof (cmd),
+		    "/sbin/mount -F zfs %s/ROOT/%s %s",
+		    ROOTPOOL_NAME, INIT_BE_NAME, tcb_args->target);
+
+		om_log_print("%s\n", cmd);
+		td_safe_system(cmd, B_TRUE);
+
+		/*
+		 * copy updated zpool.cache
+		 */
+
+		(void) snprintf(cmd, sizeof (cmd),
+		    "/bin/cp /etc/zfs/zpool.cache %s/etc/zfs/",
+		    tcb_args->target);
+
+		om_log_print("%s\n", cmd);
+		td_safe_system(cmd, B_TRUE);
+
+		/*
+		 * run install finish script after pool is imported
+		 * under its final name, otherwise it fails
+		 */
+
+		run_install_finish_script(tcb_args->target);
 
 		/*
 		 * Take a snapshot of the installation.
@@ -861,6 +995,12 @@
 		    B_TRUE);
 
 		/*
+		 * Transfer log files to the destination now,
+		 * when everything is finished
+		 */
+		ls_transfer("/", tcb_args->target);
+
+		/*
 		 * Notify the caller that install is completed
 		 */
 
@@ -1801,7 +1941,7 @@
 	for (i = ZFS_SHARED_FS_NUM - 1; i >= 0; i--) {
 		(void) snprintf(cmd, sizeof (cmd),
 		    "/usr/sbin/zfs set mountpoint=%s %s%s",
-		    zfs_shared_fs_names[i], ROOTPOOL_NAME,
+		    zfs_shared_fs_names[i], ROOTPOOL_TMPNAME,
 		    zfs_shared_fs_names[i]);
 
 		om_log_print("%s\n", cmd);
@@ -1824,18 +1964,6 @@
 	(void) be_unmount(attrs);
 
 	nvlist_free(attrs);
-
-	/*
-	 * mount "/" once more, since we need copy there
-	 * configuration and log files
-	 */
-
-	(void) snprintf(cmd, sizeof (cmd),
-	    "/sbin/mount -F zfs %s/ROOT/%s %s",
-	    ROOTPOOL_NAME, INIT_BE_NAME, target);
-
-	om_log_print("%s\n", cmd);
-	td_safe_system(cmd, B_TRUE);
 }
 
 /*
@@ -1854,7 +1982,7 @@
 
 	(void) snprintf(cmd, sizeof (cmd),
 	    "/usr/sbin/zpool set bootfs=%s/ROOT/%s %s",
-	    ROOTPOOL_NAME, be_name, ROOTPOOL_NAME);
+	    ROOTPOOL_TMPNAME, be_name, ROOTPOOL_TMPNAME);
 
 	om_log_print("%s\n", cmd);
 	td_safe_system(cmd, B_TRUE);
@@ -1995,7 +2123,7 @@
 	}
 
 	if (nvlist_add_string(*attrs, TI_ATTR_ZFS_RPOOL_NAME,
-	    ROOTPOOL_NAME) != 0) {
+	    ROOTPOOL_TMPNAME) != 0) {
 		om_log_print("ZFS root pool name could not be added. \n");
 
 		return (OM_FAILURE);
@@ -2047,7 +2175,7 @@
 	}
 
 	if (nvlist_add_string(*attrs, TI_ATTR_ZFS_FS_POOL_NAME,
-	    ROOTPOOL_NAME) != 0) {
+	    ROOTPOOL_TMPNAME) != 0) {
 		om_log_print("FS root pool name could not be added. \n");
 
 		return (OM_FAILURE);
@@ -2133,7 +2261,7 @@
 	}
 
 	if (nvlist_add_string(*attrs, TI_ATTR_BE_RPOOL_NAME,
-	    ROOTPOOL_NAME) != 0) {
+	    ROOTPOOL_TMPNAME) != 0) {
 		om_log_print("BE root pool name could not be added. \n");
 
 		return (OM_FAILURE);
@@ -2325,6 +2453,67 @@
 
 
 /*
+ * get_rootpool_id
+ *
+ * Obtains id for given root pool name
+ * it allocates memory for id returned - should be freed by caller
+ * Return:	== NULL - couldn't obtain pool id
+ *		!= NULL - pointer to id string
+ * Notes:
+ */
+
+static char *
+get_rootpool_id(char *rpool_name)
+{
+	FILE	*p;
+	char	cmd[MAXPATHLEN];
+	char	*strbuf;
+	int	ret;
+
+	strbuf = malloc(MAXPATHLEN);
+
+	if (strbuf == NULL) {
+		om_log_print("Out of memory\n");
+		return (NULL);
+	}
+
+	(void) snprintf(cmd, sizeof (cmd), "/usr/sbin/zpool list -H -o guid %s",
+	    rpool_name);
+
+	om_log_print("%s\n", cmd);
+
+	if ((p = popen(cmd, "r")) == NULL) {
+		om_log_print("Couldn't obtain pool id\n");
+
+		free(strbuf);
+		return (NULL);
+	}
+
+	if (fgets(strbuf, MAXPATHLEN, p) == NULL) {
+		om_log_print("Couldn't obtain pool id\n");
+
+		free(strbuf);
+		(void) pclose(p);
+		return (NULL);
+	}
+
+	ret = WEXITSTATUS(pclose(p));
+
+	if (ret != 0) {
+		om_log_print("Command failed with error %d\n", ret);
+		free(strbuf);
+		return (NULL);
+	}
+
+	/* strip new line */
+	if (strbuf[strlen(strbuf) - 1] == '\n')
+		strbuf[strlen(strbuf) - 1] = '\0';
+
+	return (strbuf);
+}
+
+
+/*
  * Start of code to address temporary set hostid fix.
  *
  * The below section of code will be used temporarily set the hostid.
--- a/usr/src/lib/libtd/td_mg.c	Tue Apr 08 17:49:52 2008 -0700
+++ b/usr/src/lib/libtd/td_mg.c	Tue Apr 08 19:19:26 2008 -0600
@@ -2297,7 +2297,7 @@
 boolean_t
 td_is_slice(const char *name)
 {
-	return (search_disks_for_slices(name) != NULL);
+	return (search_disks_for_slices((char *)name) != NULL);
 }
 
 static void