zoneadm.c (4785:9606b9fd0ed6) zoneadm.c (5829:20241b1ccadc)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 6 unchanged lines hidden (view full) ---

15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 6 unchanged lines hidden (view full) ---

15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29/*
30 * zoneadm is a command interpreter for zone administration. It is all in
31 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.

--- 102 unchanged lines hidden (view full) ---

134#define SHELP_REBOOT "reboot [-- boot_arguments]"
135#define SHELP_LIST "list [-cipv]"
136#define SHELP_VERIFY "verify"
137#define SHELP_INSTALL "install [-x nodataset] [brand-specific args]"
138#define SHELP_UNINSTALL "uninstall [-F]"
139#define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] zonename"
140#define SHELP_MOVE "move zonepath"
141#define SHELP_DETACH "detach [-n]"
24 * Use is subject to license terms.
25 */
26
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29/*
30 * zoneadm is a command interpreter for zone administration. It is all in
31 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.

--- 102 unchanged lines hidden (view full) ---

134#define SHELP_REBOOT "reboot [-- boot_arguments]"
135#define SHELP_LIST "list [-cipv]"
136#define SHELP_VERIFY "verify"
137#define SHELP_INSTALL "install [-x nodataset] [brand-specific args]"
138#define SHELP_UNINSTALL "uninstall [-F]"
139#define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] zonename"
140#define SHELP_MOVE "move zonepath"
141#define SHELP_DETACH "detach [-n]"
142#define SHELP_ATTACH "attach [-F] [-n ]"
142#define SHELP_ATTACH "attach [-F] [-n <path>] [-u]"
143#define SHELP_MARK "mark incomplete"
144
145#define EXEC_PREFIX "exec "
146#define EXEC_LEN (strlen(EXEC_PREFIX))
147#define RMCOMMAND "/usr/bin/rm -rf"
148
149static int cleanup_zonepath(char *, boolean_t);
150

--- 50 unchanged lines hidden (view full) ---

201static char *execname;
202static char target_brand[MAXNAMELEN];
203static char *locale;
204char *target_zone;
205static char *target_uuid;
206
207/* used in do_subproc() and signal handler */
208static volatile boolean_t child_killed;
143#define SHELP_MARK "mark incomplete"
144
145#define EXEC_PREFIX "exec "
146#define EXEC_LEN (strlen(EXEC_PREFIX))
147#define RMCOMMAND "/usr/bin/rm -rf"
148
149static int cleanup_zonepath(char *, boolean_t);
150

--- 50 unchanged lines hidden (view full) ---

201static char *execname;
202static char target_brand[MAXNAMELEN];
203static char *locale;
204char *target_zone;
205static char *target_uuid;
206
207/* used in do_subproc() and signal handler */
208static volatile boolean_t child_killed;
209/* used in attach_func() and signal handler */
210static volatile boolean_t attach_interupted;
209static int do_subproc_cnt = 0;
210
211/*
212 * Used to indicate whether this zoneadm instance has another zoneadm
213 * instance in its ancestry.
214 */
215static boolean_t zoneadm_is_nested = B_FALSE;
216

--- 83 unchanged lines hidden (view full) ---

300 "needed to attach\n\tthe zone is sent to standard output "
301 "but the zone is not actually\n\tdetached."));
302 case CMD_ATTACH:
303 return (gettext("Attach the zone to the system. The zone "
304 "state must be 'configured'\n\tprior to attach; upon "
305 "successful completion, the zone state will be\n\t"
306 "'installed'. The system software on the current "
307 "system must be\n\tcompatible with the software on the "
211static int do_subproc_cnt = 0;
212
213/*
214 * Used to indicate whether this zoneadm instance has another zoneadm
215 * instance in its ancestry.
216 */
217static boolean_t zoneadm_is_nested = B_FALSE;
218

--- 83 unchanged lines hidden (view full) ---

302 "needed to attach\n\tthe zone is sent to standard output "
303 "but the zone is not actually\n\tdetached."));
304 case CMD_ATTACH:
305 return (gettext("Attach the zone to the system. The zone "
306 "state must be 'configured'\n\tprior to attach; upon "
307 "successful completion, the zone state will be\n\t"
308 "'installed'. The system software on the current "
309 "system must be\n\tcompatible with the software on the "
308 "zone's original system.\n\tSpecify -F to force the attach "
309 "and skip software compatibility tests.\n\tThe -n option "
310 "can be used to specify 'no-execute' mode. When -n is\n\t"
311 "used, the information needed to attach the zone is read "
312 "from the\n\tspecified path and the configuration is only "
313 "validated. The path can\n\tbe '-' to specify standard "
314 "input."));
310 "zone's original system or use\n\tthe -u option to update "
311 "the zone to the current system software.\n\tSpecify -F "
312 "to force the attach and skip software compatibility "
313 "tests.\n\tThe -n option can be used to specify "
314 "'no-execute' mode. When -n is\n\tused, the information "
315 "needed to attach the zone is read from the\n\tspecified "
316 "path and the configuration is only validated. The path "
317 "can\n\tbe '-' to specify standard input. The -F, -n and "
318 "-u options are\n\tmutually exclusive."));
315 case CMD_MARK:
316 return (gettext("Set the state of the zone. This can be used "
317 "to force the zone\n\tstate to 'incomplete' "
318 "administratively if some activity has rendered\n\tthe "
319 "zone permanently unusable. The only valid state that "
320 "may be\n\tspecified is 'incomplete'."));
321 default:
322 return ("");

--- 4554 unchanged lines hidden (view full) ---

4877cleanup:
4878 /* Cleanup from the previous actions. */
4879 if (mounted) {
4880 if (snprintf(cmdbuf, sizeof (cmdbuf),
4881 "/usr/sbin/zlogin -S %s '/usr/bin/rm -f /etc/zones/%s.xml'",
4882 target_zone, target_zone) >= sizeof (cmdbuf)) {
4883 res = B_FALSE;
4884 } else {
319 case CMD_MARK:
320 return (gettext("Set the state of the zone. This can be used "
321 "to force the zone\n\tstate to 'incomplete' "
322 "administratively if some activity has rendered\n\tthe "
323 "zone permanently unusable. The only valid state that "
324 "may be\n\tspecified is 'incomplete'."));
325 default:
326 return ("");

--- 4554 unchanged lines hidden (view full) ---

4881cleanup:
4882 /* Cleanup from the previous actions. */
4883 if (mounted) {
4884 if (snprintf(cmdbuf, sizeof (cmdbuf),
4885 "/usr/sbin/zlogin -S %s '/usr/bin/rm -f /etc/zones/%s.xml'",
4886 target_zone, target_zone) >= sizeof (cmdbuf)) {
4887 res = B_FALSE;
4888 } else {
4885 status = do_subproc(cmdbuf);
4889 status = do_subproc_interactive(cmdbuf);
4886 if (subproc_status("rm", status, B_TRUE)
4887 != ZONE_SUBPROC_OK)
4888 res = B_FALSE;
4889 }
4890
4891 if (unmount_func(0, NULL) != Z_OK)
4892 res = B_FALSE;
4893 }
4894
4895 if (zone_set_state(target_zone, ZONE_STATE_CONFIGURED) != Z_OK)
4896 res = B_FALSE;
4897
4898 return (res);
4899}
4900
4890 if (subproc_status("rm", status, B_TRUE)
4891 != ZONE_SUBPROC_OK)
4892 res = B_FALSE;
4893 }
4894
4895 if (unmount_func(0, NULL) != Z_OK)
4896 res = B_FALSE;
4897 }
4898
4899 if (zone_set_state(target_zone, ZONE_STATE_CONFIGURED) != Z_OK)
4900 res = B_FALSE;
4901
4902 return (res);
4903}
4904
4905/*
4906 * The zone needs to be updated so set it up for the update and initiate the
4907 * update within the scratch zone. First set the state to incomplete so we can
4908 * force-mount the zone for the update operation. We pass the -U option to the
4909 * mount so that the scratch zone is mounted without the zone's /etc and /var
4910 * being lofs mounted back into the scratch zone root. This is done by
4911 * overloading the bootbuf string in the zone_cmd_arg_t to pass -U as an option
4912 * to the mount cmd.
4913 */
4901static int
4914static int
4915attach_update(zone_dochandle_t handle, char *zonepath)
4916{
4917 int err;
4918 int update_res;
4919 int status;
4920 zone_cmd_arg_t zarg;
4921 FILE *fp;
4922 struct zone_fstab fstab;
4923 char cmdbuf[(4 * MAXPATHLEN) + 20];
4924
4925 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
4926 != Z_OK) {
4927 errno = err;
4928 zperror(gettext("could not set state"), B_TRUE);
4929 return (Z_ERR);
4930 }
4931
4932 zarg.cmd = Z_FORCEMOUNT;
4933 (void) strlcpy(zarg.bootbuf, "-U", sizeof (zarg.bootbuf));
4934 if (call_zoneadmd(target_zone, &zarg) != 0) {
4935 zerror(gettext("could not mount zone"));
4936
4937 /* We reset the state since the zone wasn't modified yet. */
4938 if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED))
4939 != Z_OK) {
4940 errno = err;
4941 zperror(gettext("could not reset state"), B_TRUE);
4942 }
4943 return (Z_ERR);
4944 }
4945
4946 /*
4947 * Move data files generated by sw_up_to_date() into the scratch
4948 * zone's /tmp.
4949 */
4950 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec /usr/bin/mv "
4951 "%s/pkg_add %s/pkg_rm %s/lu/tmp",
4952 zonepath, zonepath, zonepath);
4953
4954 status = do_subproc_interactive(cmdbuf);
4955 if (subproc_status("mv", status, B_TRUE) != ZONE_SUBPROC_OK) {
4956 zperror(gettext("could not mv data files"), B_FALSE);
4957 goto fail;
4958 }
4959
4960 /*
4961 * Save list of inherit-pkg-dirs into zone. Since the file is in
4962 * /tmp we don't have to worry about deleting it.
4963 */
4964 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/lu/tmp/inherited",
4965 zonepath);
4966 if ((fp = fopen(cmdbuf, "w")) == NULL) {
4967 zperror(gettext("could not save inherit-pkg-dirs"), B_FALSE);
4968 goto fail;
4969 }
4970 if (zonecfg_setipdent(handle) != Z_OK) {
4971 zperror(gettext("could not enumerate inherit-pkg-dirs"),
4972 B_TRUE);
4973 goto fail;
4974 }
4975 while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
4976 if (fprintf(fp, "%s\n", fstab.zone_fs_dir) < 0) {
4977 zperror(gettext("could not save inherit-pkg-dirs"),
4978 B_FALSE);
4979 (void) fclose(fp);
4980 goto fail;
4981 }
4982 }
4983 (void) zonecfg_endipdent(handle);
4984 if (fclose(fp) != 0) {
4985 zperror(gettext("could not save inherit-pkg-dirs"), B_FALSE);
4986 goto fail;
4987 }
4988
4989 /* run the updater inside the scratch zone */
4990 (void) snprintf(cmdbuf, sizeof (cmdbuf),
4991 "exec /usr/sbin/zlogin -S %s "
4992 "/usr/lib/brand/native/attach_update %s", target_zone, target_zone);
4993
4994 update_res = Z_OK;
4995 status = do_subproc_interactive(cmdbuf);
4996 if (subproc_status("attach_update", status, B_TRUE)
4997 != ZONE_SUBPROC_OK) {
4998 zerror(gettext("could not update zone"));
4999 update_res = Z_ERR;
5000 }
5001
5002 zarg.cmd = Z_UNMOUNT;
5003 if (call_zoneadmd(target_zone, &zarg) != 0) {
5004 zerror(gettext("could not unmount zone"));
5005 return (Z_ERR);
5006 }
5007
5008 /*
5009 * If the update script within the scratch zone failed for some reason
5010 * we will now leave the zone in the incomplete state since we no
5011 * longer know the state of the files within the zonepath.
5012 */
5013 if (update_res == Z_ERR)
5014 return (Z_ERR);
5015
5016 zonecfg_rm_detached(handle, B_FALSE);
5017
5018 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
5019 errno = err;
5020 zperror(gettext("could not set state"), B_TRUE);
5021 return (Z_ERR);
5022 }
5023
5024 return (Z_OK);
5025
5026fail:
5027 zarg.cmd = Z_UNMOUNT;
5028 if (call_zoneadmd(target_zone, &zarg) != 0)
5029 zerror(gettext("could not unmount zone"));
5030
5031 /* We reset the state since the zone wasn't modified yet. */
5032 if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED))
5033 != Z_OK) {
5034 errno = err;
5035 zperror(gettext("could not reset state"), B_TRUE);
5036 }
5037
5038 return (Z_ERR);
5039}
5040
5041/* ARGSUSED */
5042static void
5043sigcleanup(int sig)
5044{
5045 attach_interupted = B_TRUE;
5046}
5047
5048
5049static int
4902attach_func(int argc, char *argv[])
4903{
4904 int lockfd;
4905 int err, arg;
4906 boolean_t force = B_FALSE;
4907 zone_dochandle_t handle;
4908 zone_dochandle_t athandle = NULL;
4909 char zonepath[MAXPATHLEN];
4910 char brand[MAXNAMELEN], atbrand[MAXNAMELEN];
4911 char cmdbuf[MAXPATHLEN];
4912 boolean_t execute = B_TRUE;
4913 boolean_t retried = B_FALSE;
5050attach_func(int argc, char *argv[])
5051{
5052 int lockfd;
5053 int err, arg;
5054 boolean_t force = B_FALSE;
5055 zone_dochandle_t handle;
5056 zone_dochandle_t athandle = NULL;
5057 char zonepath[MAXPATHLEN];
5058 char brand[MAXNAMELEN], atbrand[MAXNAMELEN];
5059 char cmdbuf[MAXPATHLEN];
5060 boolean_t execute = B_TRUE;
5061 boolean_t retried = B_FALSE;
5062 boolean_t update = B_FALSE;
4914 char *manifest_path;
4915 brand_handle_t bh = NULL;
4916
4917 if (zonecfg_in_alt_root()) {
4918 zerror(gettext("cannot attach zone in alternate root"));
4919 return (Z_ERR);
4920 }
4921
4922 optind = 0;
5063 char *manifest_path;
5064 brand_handle_t bh = NULL;
5065
5066 if (zonecfg_in_alt_root()) {
5067 zerror(gettext("cannot attach zone in alternate root"));
5068 return (Z_ERR);
5069 }
5070
5071 optind = 0;
4923 if ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
5072 if ((arg = getopt(argc, argv, "?Fn:u")) != EOF) {
4924 switch (arg) {
4925 case '?':
4926 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4927 return (optopt == '?' ? Z_OK : Z_USAGE);
4928 case 'F':
4929 force = B_TRUE;
4930 break;
4931 case 'n':
4932 execute = B_FALSE;
4933 manifest_path = optarg;
4934 break;
5073 switch (arg) {
5074 case '?':
5075 sub_usage(SHELP_ATTACH, CMD_ATTACH);
5076 return (optopt == '?' ? Z_OK : Z_USAGE);
5077 case 'F':
5078 force = B_TRUE;
5079 break;
5080 case 'n':
5081 execute = B_FALSE;
5082 manifest_path = optarg;
5083 break;
5084 case 'u':
5085 update = B_TRUE;
5086 break;
4935 default:
4936 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4937 return (Z_USAGE);
4938 }
4939 }
4940
5087 default:
5088 sub_usage(SHELP_ATTACH, CMD_ATTACH);
5089 return (Z_USAGE);
5090 }
5091 }
5092
5093 /* dry-run and update flags are mutually exclusive */
5094 if (!execute && update) {
5095 zerror(gettext("-n and -u flags are mutually exclusive"));
5096 return (Z_ERR);
5097 }
5098
4941 /*
4942 * If the no-execute option was specified, we need to branch down
4943 * a completely different path since there is no zone required to be
4944 * configured for this option.
4945 */
4946 if (!execute)
4947 return (dryrun_attach(manifest_path, argv));
4948

--- 118 unchanged lines hidden (view full) ---

5067
5068 if (strcmp(atbrand, brand) != NULL) {
5069 err = Z_ERR;
5070 zerror(gettext("Trying to attach a '%s' zone to a '%s' "
5071 "configuration."), atbrand, brand);
5072 goto done;
5073 }
5074
5099 /*
5100 * If the no-execute option was specified, we need to branch down
5101 * a completely different path since there is no zone required to be
5102 * configured for this option.
5103 */
5104 if (!execute)
5105 return (dryrun_attach(manifest_path, argv));
5106

--- 118 unchanged lines hidden (view full) ---

5225
5226 if (strcmp(atbrand, brand) != NULL) {
5227 err = Z_ERR;
5228 zerror(gettext("Trying to attach a '%s' zone to a '%s' "
5229 "configuration."), atbrand, brand);
5230 goto done;
5231 }
5232
5075 /* sw_cmp prints error msgs as necessary */
5076 if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
5077 goto done;
5233 /*
5234 * If we're doing an update on attach, and the zone does need to be
5235 * updated, then run the update.
5236 */
5237 if (update) {
5238 char fname[MAXPATHLEN];
5078
5239
5079 if ((err = dev_fix(athandle)) != Z_OK)
5080 goto done;
5240 (void) sigset(SIGINT, sigcleanup);
5081
5241
5242 if ((err = sw_up_to_date(handle, athandle, zonepath)) != Z_OK) {
5243 if (err != Z_FATAL && !attach_interupted) {
5244 err = Z_FATAL;
5245 err = attach_update(handle, zonepath);
5246 }
5247 if (!attach_interupted || err == Z_OK)
5248 goto done;
5249 }
5250
5251 (void) sigset(SIGINT, SIG_DFL);
5252
5253 /* clean up data files left behind by sw_up_to_date() */
5254 (void) snprintf(fname, sizeof (fname), "%s/pkg_add", zonepath);
5255 (void) unlink(fname);
5256 (void) snprintf(fname, sizeof (fname), "%s/pkg_rm", zonepath);
5257 (void) unlink(fname);
5258
5259 if (attach_interupted) {
5260 err = Z_FATAL;
5261 goto done;
5262 }
5263
5264 } else {
5265 /* sw_cmp prints error msgs as necessary */
5266 if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
5267 goto done;
5268
5269 if ((err = dev_fix(athandle)) != Z_OK)
5270 goto done;
5271 }
5272
5082forced:
5083
5084 zonecfg_rm_detached(handle, force);
5085
5086 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
5087 errno = err;
5088 zperror(gettext("could not reset state"), B_TRUE);
5089 }

--- 231 unchanged lines hidden (view full) ---

5321
5322 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
5323 != Z_OK)
5324 return (Z_ERR);
5325 if (verify_details(CMD_MOUNT, argv) != Z_OK)
5326 return (Z_ERR);
5327
5328 zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
5273forced:
5274
5275 zonecfg_rm_detached(handle, force);
5276
5277 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
5278 errno = err;
5279 zperror(gettext("could not reset state"), B_TRUE);
5280 }

--- 231 unchanged lines hidden (view full) ---

5512
5513 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
5514 != Z_OK)
5515 return (Z_ERR);
5516 if (verify_details(CMD_MOUNT, argv) != Z_OK)
5517 return (Z_ERR);
5518
5519 zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
5520 zarg.bootbuf[0] = '\0';
5329 if (call_zoneadmd(target_zone, &zarg) != 0) {
5330 zerror(gettext("call to %s failed"), "zoneadmd");
5331 return (Z_ERR);
5332 }
5333 return (Z_OK);
5334}
5335
5336/* ARGSUSED */

--- 514 unchanged lines hidden ---
5521 if (call_zoneadmd(target_zone, &zarg) != 0) {
5522 zerror(gettext("call to %s failed"), "zoneadmd");
5523 return (Z_ERR);
5524 }
5525 return (Z_OK);
5526}
5527
5528/* ARGSUSED */

--- 514 unchanged lines hidden ---