[zones-discuss] Zone boot/reboot hooks
Hi, I want to file an RFE but I thought I should discuss a little before I do: I would like a way to run a script in the global zone when a non-global zone boots. My use case is: I'm a developer for NexentaCP and I would like to make an autobuilder using zones. In particular I want to have a zone that will always come back in the same state on reboot so that I have minimal packages installed and everything gets pulled as defined by source package dependencies. The process might look like: (global zone) zone_hook(pre-boot, ...) - a script/action occurs for the zone zone_boot(...) (non-global zone) init (the autobuilder will have a svc that builds packages and reports status to a server) reboot (perhaps with specific args that the hook script can grab) (global zone) zone_halt(...) zone_hook(post-halt, ...) I think it would make sense to configure the hooks via a zonecfg section: --- add hook set type=[pre-boot | post-boot | pre-halt | post-halt] set action=script set path=/path/to/zone_hook.sh end --- In my particular use-case I would have a pre-boot hook that rolled the zone filesystem to a particular snapshot. This way the zone would always come back in the same state: --- add hook set type=pre-boot set action=script set path=/path/to/zone_scripts/pre-boot.sh end --- For a decent interface we would need to pass information to the scripts about the zone name, boot args, previous state, ... which might be done through the environment? An example script might hackishly look like: --- #!/bin/sh # Check for fs reset condition echo $ZONE_BOOT_ARGS | grep -w 'reset_zone_fs=yes' /dev/null if [ $? != 0 ]; then exit 0 fi # get fs to reset path=`zonecfg -z $ZONE_NAME info zonepath | cut -d: -f2` zfs_dataset=`zfs list -H -t filesystem -o mountpoint,name | grep ^$path | awk '{print $2}'` # If no fs then exit with an error status if [ X$zfs_dataset = X ]; then echo Danger Will Robinson... Danger: exit -1 fi # make sure the snapshot exists and rollback zfs list -H -o name -t snapshot -r $zfs_dataset | grep @snapshot_name$ /dev/null if [ $? != 0 ]; then echo Error: required snapshot does not exist exit -1 fi zfs rollback [EMAIL PROTECTED] exit 0 --- Comments/criticisms/flying chunkules appreciated. -Tim ___ zones-discuss mailing list zones-discuss@opensolaris.org
Re: [zones-discuss] Making zoneadm more like the other adms...
Your code changes for both zoneadm and zonecfg would preserve the current zonexxx -z zonename for backwards compatibility purposes, is that correct? Thank you, On Mon, Jun 9, 2008 at 11:51 AM, Darren Reed [EMAIL PROTECTED] wrote: Someone mentioned zonecfg was the cause of some similar awkwardness... So here's a patch attached for that. Darren --- usr/src/cmd/zonecfg/zonecfg.c --- Index: usr/src/cmd/zonecfg/zonecfg.c *** /biscuit/onnv/usr/src/cmd/zonecfg/zonecfg.c Mon Mar 24 17:30:38 2008 --- /biscuit/onnv_20080608/usr/src/cmd/zonecfg/zonecfg.cMon Jun 9 11:47:41 2008 *** *** 1071,1076 --- 1071,1077 execname, cmd_to_str(CMD_HELP)); (void) fprintf(fp, \t%s -z zone\t\t\t(%s)\n, execname, gettext(interactive)); + (void) fprintf(fp, \t%s command zone\n, execname); (void) fprintf(fp, \t%s -z zone command\n, execname); (void) fprintf(fp, \t%s -z zone -f command-file\n, execname); *** *** 6653,6689 return (execbasename); } ! int ! main(int argc, char *argv[]) { ! int err, arg; ! struct stat st; ! ! /* This must be before anything goes to stdout. */ ! setbuf(stdout, NULL); ! ! saw_error = B_FALSE; ! cmd_file_mode = B_FALSE; ! execname = get_execbasename(argv[0]); ! ! (void) setlocale(LC_ALL, ); ! (void) textdomain(TEXT_DOMAIN); ! ! if (getzoneid() != GLOBAL_ZONEID) { ! zerr(gettext(%s can only be run from the global zone.), ! execname); ! exit(Z_ERR); ! } ! ! if (argc 2) { ! usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS); exit(Z_USAGE); } ! if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) { ! (void) one_command_at_a_time(argc - 1, (argv[1])); ! exit(Z_OK); ! } while ((arg = getopt(argc, argv, ?f:R:z:)) != EOF) { switch (arg) { case '?': --- 6654,6679 return (execbasename); } ! static void ! set_zonename(char *zonename) { ! if (strcmp(zonename, GLOBAL_ZONENAME) == 0) { ! global_zone = B_TRUE; ! } else if (zonecfg_validate_zonename(zonename) != Z_OK) { ! zone_perror(zonename, Z_BOGUS_ZONE_NAME, B_TRUE); ! usage(B_FALSE, HELP_SYNTAX); exit(Z_USAGE); } ! (void) strlcpy(zone, zonename, sizeof (zone)); ! (void) strlcpy(revert_zone, zonename, sizeof (zone)); ! } + static void + get_clioptions(int argc, char *argv[]) + { + struct stat st; + int arg; + while ((arg = getopt(argc, argv, ?f:R:z:)) != EOF) { switch (arg) { case '?': *** *** 6712,6726 zonecfg_set_root(optarg); break; case 'z': ! if (strcmp(optarg, GLOBAL_ZONENAME) == 0) { ! global_zone = B_TRUE; ! } else if (zonecfg_validate_zonename(optarg) != Z_OK) { ! zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE); ! usage(B_FALSE, HELP_SYNTAX); ! exit(Z_USAGE); ! } ! (void) strlcpy(zone, optarg, sizeof (zone)); ! (void) strlcpy(revert_zone, optarg, sizeof (zone)); break; default: usage(B_FALSE, HELP_USAGE); --- 6702,6708 zonecfg_set_root(optarg); break; case 'z': ! set_zonename(optarg); break; default: usage(B_FALSE, HELP_USAGE); *** *** 6727,6733 --- 6709,6761 exit(Z_USAGE); } } + } + int + main(int argc, char *argv[]) + { + int err; + + /* This must be before anything goes to stdout. */ + setbuf(stdout, NULL); + + saw_error = B_FALSE; + cmd_file_mode = B_FALSE; + execname = get_execbasename(argv[0]); + + (void) setlocale(LC_ALL, ); + (void) textdomain(TEXT_DOMAIN); + + if (getzoneid() != GLOBAL_ZONEID) { + zerr(gettext(%s can only be run from the global zone.), + execname); + exit(Z_ERR); + } + + if (argc 2) { + usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS); + exit(Z_USAGE); + } + if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) { + (void) one_command_at_a_time(argc - 1, (argv[1])); + exit(Z_OK); + } + + if
Re: [zones-discuss] Making zoneadm more like the other adms...
Tony Ambrozie wrote: Your code changes for both zoneadm and zonecfg would preserve the current zonexxx -z zonename for backwards compatibility purposes, is that correct? Correct. There are some command line options that the changes I've made don't support, such as using -R. That's quite deliberate. The aim of the changes was to address the common use cases of the commands and make their use more intuitive when viewed with the other commands in OpenSolaris. Darren Thank you, On Mon, Jun 9, 2008 at 11:51 AM, Darren Reed [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] wrote: Someone mentioned zonecfg was the cause of some similar awkwardness... So here's a patch attached for that. Darren --- usr/src/cmd/zonecfg/zonecfg.c --- Index: usr/src/cmd/zonecfg/zonecfg.c *** /biscuit/onnv/usr/src/cmd/zonecfg/zonecfg.c Mon Mar 24 17:30:38 2008 --- /biscuit/onnv_20080608/usr/src/cmd/zonecfg/zonecfg.c Mon Jun 9 11:47:41 2008 *** *** 1071,1076 --- 1071,1077 execname, cmd_to_str(CMD_HELP)); (void) fprintf(fp, \t%s -z zone\t\t\t(%s)\n, execname, gettext(interactive)); + (void) fprintf(fp, \t%s command zone\n, execname); (void) fprintf(fp, \t%s -z zone command\n, execname); (void) fprintf(fp, \t%s -z zone -f command-file\n, execname); *** *** 6653,6689 return (execbasename); } ! int ! main(int argc, char *argv[]) { ! int err, arg; ! struct stat st; ! ! /* This must be before anything goes to stdout. */ ! setbuf(stdout, NULL); ! ! saw_error = B_FALSE; ! cmd_file_mode = B_FALSE; ! execname = get_execbasename(argv[0]); ! ! (void) setlocale(LC_ALL, ); ! (void) textdomain(TEXT_DOMAIN); ! ! if (getzoneid() != GLOBAL_ZONEID) { ! zerr(gettext(%s can only be run from the global zone.), ! execname); ! exit(Z_ERR); ! } ! ! if (argc 2) { ! usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS); exit(Z_USAGE); } ! if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) { ! (void) one_command_at_a_time(argc - 1, (argv[1])); ! exit(Z_OK); ! } while ((arg = getopt(argc, argv, ?f:R:z:)) != EOF) { switch (arg) { case '?': --- 6654,6679 return (execbasename); } ! static void ! set_zonename(char *zonename) { ! if (strcmp(zonename, GLOBAL_ZONENAME) == 0) { ! global_zone = B_TRUE; ! } else if (zonecfg_validate_zonename(zonename) != Z_OK) { ! zone_perror(zonename, Z_BOGUS_ZONE_NAME, B_TRUE); ! usage(B_FALSE, HELP_SYNTAX); exit(Z_USAGE); } ! (void) strlcpy(zone, zonename, sizeof (zone)); ! (void) strlcpy(revert_zone, zonename, sizeof (zone)); ! } + static void + get_clioptions(int argc, char *argv[]) + { + struct stat st; + int arg; + while ((arg = getopt(argc, argv, ?f:R:z:)) != EOF) { switch (arg) { case '?': *** *** 6712,6726 zonecfg_set_root(optarg); break; case 'z': ! if (strcmp(optarg, GLOBAL_ZONENAME) == 0) { ! global_zone = B_TRUE; ! } else if (zonecfg_validate_zonename(optarg) != Z_OK) { ! zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE); ! usage(B_FALSE, HELP_SYNTAX); ! exit(Z_USAGE); ! } ! (void) strlcpy(zone, optarg, sizeof (zone)); ! (void) strlcpy(revert_zone, optarg, sizeof (zone)); break; default: usage(B_FALSE, HELP_USAGE); --- 6702,6708 zonecfg_set_root(optarg); break; case 'z': ! set_zonename(optarg); break; default: usage(B_FALSE, HELP_USAGE); *** *** 6727,6733 --- 6709,6761 exit(Z_USAGE); } } + } + int