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
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * zoneadm is a command interpreter for zone administration. It is all in
29 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
30 * main() calls parse_and_run() which calls cmd_match(), then invokes the
31 * appropriate command's handler function. The rest of the program is the
32 * handler functions and their helper functions.
33 *
34 * Some of the helper functions are used largely to simplify I18N: reducing
35 * the need for translation notes. This is particularly true of many of
36 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
37 * than zerror(gettext("foo failed")) with a translation note indicating
38 * that "foo" need not be translated.
39 */
40
41 #include <stdio.h>
42 #include <errno.h>
43 #include <unistd.h>
85 #include "zoneadm.h"
86
87 #define MAXARGS 8
88
89 /* Reflects kernel zone entries */
90 typedef struct zone_entry {
91 zoneid_t zid;
92 char zname[ZONENAME_MAX];
93 char *zstate_str;
94 zone_state_t zstate_num;
95 char zbrand[MAXNAMELEN];
96 char zroot[MAXPATHLEN];
97 char zuuid[UUID_PRINTABLE_STRING_LENGTH];
98 zone_iptype_t ziptype;
99 } zone_entry_t;
100
101 #define CLUSTER_BRAND_NAME "cluster"
102
103 static zone_entry_t *zents;
104 static size_t nzents;
105 static boolean_t is_native_zone = B_TRUE;
106
107 #define LOOPBACK_IF "lo0"
108 #define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
109
110 struct net_if {
111 char *name;
112 int af;
113 };
114
115 /* 0755 is the default directory mode. */
116 #define DEFAULT_DIR_MODE \
117 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
118
119 struct cmd {
120 uint_t cmd_num; /* command number */
121 char *cmd_name; /* command name */
122 char *short_usage; /* short form help */
123 int (*handler)(int argc, char *argv[]); /* function to call */
124
125 };
1070 }
1071 /*
1072 * The existence of the root path is only bad in the configured state,
1073 * as it is *supposed* to be there at the installed and later states.
1074 * However, the root path is expected to be there if the zone is
1075 * detached.
1076 * State/command mismatches are caught earlier in verify_details().
1077 */
1078 if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1079 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1080 sizeof (rootpath)) {
1081 /*
1082 * TRANSLATION_NOTE
1083 * Zonepath is a literal that should not be translated.
1084 */
1085 (void) fprintf(stderr,
1086 gettext("Zonepath %s is too long.\n"), rpath);
1087 return (Z_ERR);
1088 }
1089 if ((res = stat(rootpath, &stbuf)) == 0) {
1090 struct dirent *dp;
1091 DIR *dirp;
1092 boolean_t empty = B_TRUE;
1093
1094 if (zonecfg_detached(rpath)) {
1095 (void) fprintf(stderr,
1096 gettext("Cannot %s detached "
1097 "zone.\nUse attach or remove %s "
1098 "directory.\n"), cmd_to_str(cmd_num),
1099 rpath);
1100 return (Z_ERR);
1101 }
1102
1103 /* Not detached, check if it really looks ok. */
1104
1105 if (!S_ISDIR(stbuf.st_mode)) {
1106 (void) fprintf(stderr, gettext("%s is not a "
1107 "directory.\n"), rootpath);
1108 return (Z_ERR);
1109 }
1110
1111 if (stbuf.st_uid != 0) {
1112 (void) fprintf(stderr, gettext("%s is not "
1113 "owned by root.\n"), rootpath);
1114 return (Z_ERR);
1115 }
1116
1117 if ((stbuf.st_mode & 0777) != 0755) {
1118 (void) fprintf(stderr, gettext("%s mode is not "
1119 "0755.\n"), rootpath);
1120 return (Z_ERR);
1121 }
1122
1123 if ((dirp = opendir(rootpath)) == NULL) {
1124 (void) fprintf(stderr, gettext("Could not "
1125 "open rootpath %s\n"), rootpath);
1126 return (Z_ERR);
1127 }
1128
1129 /* Verify that the dir is empty. */
1130 while ((dp = readdir(dirp)) != NULL) {
1131 if (strcmp(dp->d_name, ".") == 0 ||
1132 strcmp(dp->d_name, "..") == 0)
1133 continue;
1134
1135 empty = B_FALSE;
1136 break;
1137 }
1138 (void) closedir(dirp);
1139
1140 if (!empty) {
1141 (void) fprintf(stderr, gettext("Rootpath %s "
1142 "exists and contains data; remove or move "
1143 "aside prior to %s.\n"), rootpath,
1144 cmd_to_str(cmd_num));
1145 return (Z_ERR);
1146 }
1147
1148 }
1149 }
1150
1151 return (err ? Z_ERR : Z_OK);
1152 }
1153
1154 static int
1155 invoke_brand_handler(int cmd_num, char *argv[])
1156 {
1157 zone_dochandle_t handle;
1158 int err;
1159
1160 if ((handle = zonecfg_init_handle()) == NULL) {
1161 zperror(cmd_to_str(cmd_num), B_TRUE);
1162 return (Z_ERR);
1163 }
1164 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1165 errno = err;
1166 zperror(cmd_to_str(cmd_num), B_TRUE);
1167 zonecfg_fini_handle(handle);
1168 return (Z_ERR);
1169 }
1170 if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1696 zone_state_str(zent->zstate_num);
1697 }
1698 zerror(gettext("%s operation is invalid for %s zones."),
1699 cmd_to_str(cmd_num), zent->zstate_str);
1700 return (Z_ERR);
1701 }
1702 if ((err = zone_get_state(zone, &state)) != Z_OK) {
1703 errno = err;
1704 zperror2(zone, gettext("could not get state"));
1705 return (Z_ERR);
1706 }
1707 switch (cmd_num) {
1708 case CMD_UNINSTALL:
1709 if (state == ZONE_STATE_CONFIGURED) {
1710 zerror(gettext("is already in state '%s'."),
1711 zone_state_str(ZONE_STATE_CONFIGURED));
1712 return (Z_ERR);
1713 }
1714 break;
1715 case CMD_ATTACH:
1716 case CMD_CLONE:
1717 case CMD_INSTALL:
1718 if (state == ZONE_STATE_INSTALLED) {
1719 zerror(gettext("is already %s."),
1720 zone_state_str(ZONE_STATE_INSTALLED));
1721 return (Z_ERR);
1722 } else if (state == ZONE_STATE_INCOMPLETE) {
1723 zerror(gettext("zone is %s; %s required."),
1724 zone_state_str(ZONE_STATE_INCOMPLETE),
1725 cmd_to_str(CMD_UNINSTALL));
1726 return (Z_ERR);
1727 }
1728 break;
1729 case CMD_DETACH:
1730 case CMD_MOVE:
1731 case CMD_READY:
1732 case CMD_BOOT:
1733 case CMD_MOUNT:
1734 case CMD_MARK:
1735 if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
1736 force)
1737 min_state = ZONE_STATE_INCOMPLETE;
1738 else
1739 min_state = ZONE_STATE_INSTALLED;
1740
1741 if (force && cmd_num == CMD_BOOT && is_native_zone) {
1742 zerror(gettext("Only branded zones may be "
1743 "force-booted."));
1744 return (Z_ERR);
1745 }
1746
1747 if (state < min_state) {
1748 zerror(gettext("must be %s before %s."),
1749 zone_state_str(min_state),
1750 cmd_to_str(cmd_num));
1751 return (Z_ERR);
1752 }
1753 break;
1754 case CMD_VERIFY:
1755 if (state == ZONE_STATE_INCOMPLETE) {
1756 zerror(gettext("zone is %s; %s required."),
1757 zone_state_str(ZONE_STATE_INCOMPLETE),
1758 cmd_to_str(CMD_UNINSTALL));
1759 return (Z_ERR);
1760 }
1761 break;
1762 case CMD_UNMOUNT:
1763 if (state != ZONE_STATE_MOUNTED) {
1764 zerror(gettext("must be %s before %s."),
1765 zone_state_str(ZONE_STATE_MOUNTED),
1766 cmd_to_str(cmd_num));
4608 }
4609
4610 /* ARGSUSED */
4611 static int
4612 attach_func(int argc, char *argv[])
4613 {
4614 int lockfd = -1;
4615 int err, arg;
4616 boolean_t force = B_FALSE;
4617 zone_dochandle_t handle;
4618 char zonepath[MAXPATHLEN];
4619 char cmdbuf[MAXPATHLEN];
4620 char postcmdbuf[MAXPATHLEN];
4621 boolean_t execute = B_TRUE;
4622 boolean_t brand_help = B_FALSE;
4623 char *manifest_path;
4624 char tmpmanifest[80];
4625 int manifest_pos;
4626 brand_handle_t bh = NULL;
4627 int status;
4628
4629 if (zonecfg_in_alt_root()) {
4630 zerror(gettext("cannot attach zone in alternate root"));
4631 return (Z_ERR);
4632 }
4633
4634 /* Check the argv string for args we handle internally */
4635 optind = 0;
4636 opterr = 0;
4637 while ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
4638 switch (arg) {
4639 case '?':
4640 if (optopt == '?') {
4641 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4642 brand_help = B_TRUE;
4643 }
4644 /* Ignore unknown options - may be brand specific. */
4645 break;
4646 case 'F':
4647 force = B_TRUE;
4648 break;
4649 case 'n':
4650 execute = B_FALSE;
4651 manifest_path = optarg;
4652 manifest_pos = optind - 1;
4653 break;
4654 default:
4655 /* Ignore unknown options - may be brand specific. */
4656 break;
4657 }
4658 }
4659
4660 if (brand_help) {
4661 force = B_FALSE;
4662 execute = B_TRUE;
4663 }
4664
4665 /* dry-run and force flags are mutually exclusive */
4666 if (!execute && force) {
4667 zerror(gettext("-F and -n flags are mutually exclusive"));
4668 return (Z_ERR);
4669 }
4670
4671 /*
4672 * If the no-execute option was specified, we don't do validation and
4673 * need to figure out the brand, since there is no zone required to be
4674 * configured for this option.
4675 */
4676 if (execute) {
4677 if (!brand_help) {
4678 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
4679 B_TRUE, B_FALSE) != Z_OK)
4680 return (Z_ERR);
4681 if (verify_details(CMD_ATTACH, argv) != Z_OK)
4682 return (Z_ERR);
4683 }
4684
4685 if ((err = zone_get_zonepath(target_zone, zonepath,
4686 sizeof (zonepath))) != Z_OK) {
4687 errno = err;
4688 zperror2(target_zone,
4689 gettext("could not get zone path"));
4690 return (Z_ERR);
4691 }
4692 } else {
4693 if (dryrun_get_brand(manifest_path, tmpmanifest,
4694 sizeof (tmpmanifest)) != Z_OK)
4695 return (Z_ERR);
4696
4697 argv[manifest_pos] = tmpmanifest;
4698 target_zone = "-";
4699 (void) strlcpy(zonepath, "-", sizeof (zonepath));
4732 return (Z_ERR);
4733
4734 /* Append all options to postattach hook. */
4735 if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
4736 return (Z_ERR);
4737
4738 if (execute && !brand_help) {
4739 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4740 zerror(gettext("another %s may have an operation in "
4741 "progress."), "zoneadm");
4742 return (Z_ERR);
4743 }
4744 }
4745
4746 if (!force) {
4747 /*
4748 * Not a force-attach, so we need to actually do the work.
4749 */
4750 if (cmdbuf[0] != '\0') {
4751 /* Run the attach hook */
4752 status = do_subproc_interactive(cmdbuf);
4753 if ((status = subproc_status(gettext("brand-specific "
4754 "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
4755 if (status == ZONE_SUBPROC_USAGE && !brand_help)
4756 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4757
4758 if (execute && !brand_help) {
4759 assert(lockfd >= 0);
4760 zonecfg_release_lock_file(target_zone,
4761 lockfd);
4762 lockfd = -1;
4763 }
4764
4765 assert(lockfd == -1);
4766 return (Z_ERR);
4767 }
4768 }
4769
4770 /*
4771 * Else run the built-in attach support.
4772 * This is a no-op since there is nothing to validate.
4773 */
4774
4775 /* If dry-run or help, then we're done. */
4776 if (!execute || brand_help) {
4777 if (!execute)
4778 (void) unlink(tmpmanifest);
4779 assert(lockfd == -1);
4782 }
4783
4784 if ((handle = zonecfg_init_handle()) == NULL) {
4785 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4786 err = Z_ERR;
4787 } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4788 errno = err;
4789 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4790 zonecfg_fini_handle(handle);
4791 } else {
4792 zonecfg_rm_detached(handle, force);
4793 zonecfg_fini_handle(handle);
4794 }
4795
4796 if (err == Z_OK &&
4797 (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4798 errno = err;
4799 zperror(gettext("could not reset state"), B_TRUE);
4800 }
4801
4802 assert(lockfd >= 0);
4803 zonecfg_release_lock_file(target_zone, lockfd);
4804 lockfd = -1;
4805
4806 /* If we have a brand postattach hook, run it. */
4807 if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
4808 status = do_subproc(postcmdbuf);
4809 if (subproc_status(gettext("brand-specific postattach"),
4810 status, B_FALSE) != ZONE_SUBPROC_OK) {
4811 if ((err = zone_set_state(target_zone,
4812 ZONE_STATE_CONFIGURED)) != Z_OK) {
4813 errno = err;
4814 zperror(gettext("could not reset state"),
4815 B_TRUE);
4816 }
4817 }
4818 }
4819
4820 assert(lockfd == -1);
4821 return ((err == Z_OK) ? Z_OK : Z_ERR);
4822 }
5101 zone_cmd_arg_t zarg;
5102
5103 if (argc > 0)
5104 return (Z_USAGE);
5105 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5106 != Z_OK)
5107 return (Z_ERR);
5108
5109 zarg.cmd = Z_UNMOUNT;
5110 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5111 zerror(gettext("call to %s failed"), "zoneadmd");
5112 return (Z_ERR);
5113 }
5114 return (Z_OK);
5115 }
5116
5117 static int
5118 mark_func(int argc, char *argv[])
5119 {
5120 int err, lockfd;
5121
5122 if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
5123 return (Z_USAGE);
5124 if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
5125 != Z_OK)
5126 return (Z_ERR);
5127
5128 /*
5129 * Invoke brand-specific handler.
5130 */
5131 if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5132 return (Z_ERR);
5133
5134 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5135 zerror(gettext("another %s may have an operation in progress."),
5136 "zoneadm");
5137 return (Z_ERR);
5138 }
5139
5140 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
5141 if (err != Z_OK) {
5142 errno = err;
5143 zperror2(target_zone, gettext("could not set state"));
5144 }
5145 zonecfg_release_lock_file(target_zone, lockfd);
5146
5147 return (err);
5148 }
5149
5150 /*
5151 * Check what scheduling class we're running under and print a warning if
5152 * we're not using FSS.
5153 */
5154 static int
5155 check_sched_fss(zone_dochandle_t handle)
5156 {
5157 char class_name[PC_CLNMSZ];
5158
5159 if (zonecfg_get_dflt_sched_class(handle, class_name,
5160 sizeof (class_name)) != Z_OK) {
5575 /*
5576 * See if we have inherited the right to manipulate this zone from
5577 * a zoneadm instance in our ancestry. If so, set zone_lock_cnt to
5578 * indicate it. If not, make that explicit in our environment.
5579 */
5580 zonecfg_init_lock_file(target_zone, &zone_lock_env);
5581 if (zone_lock_env != NULL)
5582 zoneadm_is_nested = B_TRUE;
5583
5584 /*
5585 * If we are going to be operating on a single zone, retrieve its
5586 * brand type and determine whether it is native or not.
5587 */
5588 if ((target_zone != NULL) &&
5589 (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
5590 if (zone_get_brand(target_zone, target_brand,
5591 sizeof (target_brand)) != Z_OK) {
5592 zerror(gettext("missing or invalid brand"));
5593 exit(Z_ERR);
5594 }
5595 is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
5596 }
5597
5598 err = parse_and_run(argc - optind, &argv[optind]);
5599
5600 return (err);
5601 }
|
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
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * zoneadm is a command interpreter for zone administration. It is all in
29 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
30 * main() calls parse_and_run() which calls cmd_match(), then invokes the
31 * appropriate command's handler function. The rest of the program is the
32 * handler functions and their helper functions.
33 *
34 * Some of the helper functions are used largely to simplify I18N: reducing
35 * the need for translation notes. This is particularly true of many of
36 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
37 * than zerror(gettext("foo failed")) with a translation note indicating
38 * that "foo" need not be translated.
39 */
40
41 #include <stdio.h>
42 #include <errno.h>
43 #include <unistd.h>
85 #include "zoneadm.h"
86
87 #define MAXARGS 8
88
89 /* Reflects kernel zone entries */
90 typedef struct zone_entry {
91 zoneid_t zid;
92 char zname[ZONENAME_MAX];
93 char *zstate_str;
94 zone_state_t zstate_num;
95 char zbrand[MAXNAMELEN];
96 char zroot[MAXPATHLEN];
97 char zuuid[UUID_PRINTABLE_STRING_LENGTH];
98 zone_iptype_t ziptype;
99 } zone_entry_t;
100
101 #define CLUSTER_BRAND_NAME "cluster"
102
103 static zone_entry_t *zents;
104 static size_t nzents;
105
106 #define LOOPBACK_IF "lo0"
107 #define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
108
109 struct net_if {
110 char *name;
111 int af;
112 };
113
114 /* 0755 is the default directory mode. */
115 #define DEFAULT_DIR_MODE \
116 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
117
118 struct cmd {
119 uint_t cmd_num; /* command number */
120 char *cmd_name; /* command name */
121 char *short_usage; /* short form help */
122 int (*handler)(int argc, char *argv[]); /* function to call */
123
124 };
1069 }
1070 /*
1071 * The existence of the root path is only bad in the configured state,
1072 * as it is *supposed* to be there at the installed and later states.
1073 * However, the root path is expected to be there if the zone is
1074 * detached.
1075 * State/command mismatches are caught earlier in verify_details().
1076 */
1077 if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1078 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1079 sizeof (rootpath)) {
1080 /*
1081 * TRANSLATION_NOTE
1082 * Zonepath is a literal that should not be translated.
1083 */
1084 (void) fprintf(stderr,
1085 gettext("Zonepath %s is too long.\n"), rpath);
1086 return (Z_ERR);
1087 }
1088 if ((res = stat(rootpath, &stbuf)) == 0) {
1089 if (zonecfg_detached(rpath)) {
1090 (void) fprintf(stderr,
1091 gettext("Cannot %s detached "
1092 "zone.\nUse attach or remove %s "
1093 "directory.\n"), cmd_to_str(cmd_num),
1094 rpath);
1095 return (Z_ERR);
1096 }
1097
1098 /* Not detached, check if it really looks ok. */
1099
1100 if (!S_ISDIR(stbuf.st_mode)) {
1101 (void) fprintf(stderr, gettext("%s is not a "
1102 "directory.\n"), rootpath);
1103 return (Z_ERR);
1104 }
1105
1106 if (stbuf.st_uid != 0) {
1107 (void) fprintf(stderr, gettext("%s is not "
1108 "owned by root.\n"), rootpath);
1109 return (Z_ERR);
1110 }
1111
1112 if ((stbuf.st_mode & 0777) != 0755) {
1113 (void) fprintf(stderr, gettext("%s mode is not "
1114 "0755.\n"), rootpath);
1115 return (Z_ERR);
1116 }
1117 }
1118 }
1119
1120 return (err ? Z_ERR : Z_OK);
1121 }
1122
1123 static int
1124 invoke_brand_handler(int cmd_num, char *argv[])
1125 {
1126 zone_dochandle_t handle;
1127 int err;
1128
1129 if ((handle = zonecfg_init_handle()) == NULL) {
1130 zperror(cmd_to_str(cmd_num), B_TRUE);
1131 return (Z_ERR);
1132 }
1133 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1134 errno = err;
1135 zperror(cmd_to_str(cmd_num), B_TRUE);
1136 zonecfg_fini_handle(handle);
1137 return (Z_ERR);
1138 }
1139 if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1665 zone_state_str(zent->zstate_num);
1666 }
1667 zerror(gettext("%s operation is invalid for %s zones."),
1668 cmd_to_str(cmd_num), zent->zstate_str);
1669 return (Z_ERR);
1670 }
1671 if ((err = zone_get_state(zone, &state)) != Z_OK) {
1672 errno = err;
1673 zperror2(zone, gettext("could not get state"));
1674 return (Z_ERR);
1675 }
1676 switch (cmd_num) {
1677 case CMD_UNINSTALL:
1678 if (state == ZONE_STATE_CONFIGURED) {
1679 zerror(gettext("is already in state '%s'."),
1680 zone_state_str(ZONE_STATE_CONFIGURED));
1681 return (Z_ERR);
1682 }
1683 break;
1684 case CMD_ATTACH:
1685 if (state == ZONE_STATE_INSTALLED) {
1686 zerror(gettext("is already %s."),
1687 zone_state_str(ZONE_STATE_INSTALLED));
1688 return (Z_ERR);
1689 } else if (state == ZONE_STATE_INCOMPLETE && !force) {
1690 zerror(gettext("zone is %s; %s required."),
1691 zone_state_str(ZONE_STATE_INCOMPLETE),
1692 cmd_to_str(CMD_UNINSTALL));
1693 return (Z_ERR);
1694 }
1695 break;
1696 case CMD_CLONE:
1697 case CMD_INSTALL:
1698 if (state == ZONE_STATE_INSTALLED) {
1699 zerror(gettext("is already %s."),
1700 zone_state_str(ZONE_STATE_INSTALLED));
1701 return (Z_ERR);
1702 } else if (state == ZONE_STATE_INCOMPLETE) {
1703 zerror(gettext("zone is %s; %s required."),
1704 zone_state_str(ZONE_STATE_INCOMPLETE),
1705 cmd_to_str(CMD_UNINSTALL));
1706 return (Z_ERR);
1707 }
1708 break;
1709 case CMD_DETACH:
1710 case CMD_MOVE:
1711 case CMD_READY:
1712 case CMD_BOOT:
1713 case CMD_MOUNT:
1714 case CMD_MARK:
1715 if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
1716 force)
1717 min_state = ZONE_STATE_INCOMPLETE;
1718 else if (cmd_num == CMD_MARK)
1719 min_state = ZONE_STATE_CONFIGURED;
1720 else
1721 min_state = ZONE_STATE_INSTALLED;
1722
1723 if (state < min_state) {
1724 zerror(gettext("must be %s before %s."),
1725 zone_state_str(min_state),
1726 cmd_to_str(cmd_num));
1727 return (Z_ERR);
1728 }
1729 break;
1730 case CMD_VERIFY:
1731 if (state == ZONE_STATE_INCOMPLETE) {
1732 zerror(gettext("zone is %s; %s required."),
1733 zone_state_str(ZONE_STATE_INCOMPLETE),
1734 cmd_to_str(CMD_UNINSTALL));
1735 return (Z_ERR);
1736 }
1737 break;
1738 case CMD_UNMOUNT:
1739 if (state != ZONE_STATE_MOUNTED) {
1740 zerror(gettext("must be %s before %s."),
1741 zone_state_str(ZONE_STATE_MOUNTED),
1742 cmd_to_str(cmd_num));
4584 }
4585
4586 /* ARGSUSED */
4587 static int
4588 attach_func(int argc, char *argv[])
4589 {
4590 int lockfd = -1;
4591 int err, arg;
4592 boolean_t force = B_FALSE;
4593 zone_dochandle_t handle;
4594 char zonepath[MAXPATHLEN];
4595 char cmdbuf[MAXPATHLEN];
4596 char postcmdbuf[MAXPATHLEN];
4597 boolean_t execute = B_TRUE;
4598 boolean_t brand_help = B_FALSE;
4599 char *manifest_path;
4600 char tmpmanifest[80];
4601 int manifest_pos;
4602 brand_handle_t bh = NULL;
4603 int status;
4604 int last_index = 0;
4605 int offset;
4606 char *up;
4607 boolean_t forced_update = B_FALSE;
4608
4609 if (zonecfg_in_alt_root()) {
4610 zerror(gettext("cannot attach zone in alternate root"));
4611 return (Z_ERR);
4612 }
4613
4614 /* Check the argv string for args we handle internally */
4615 optind = 0;
4616 opterr = 0;
4617 while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
4618 switch (arg) {
4619 case '?':
4620 if (optopt == '?') {
4621 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4622 brand_help = B_TRUE;
4623 }
4624 /* Ignore unknown options - may be brand specific. */
4625 break;
4626 case 'F':
4627 force = B_TRUE;
4628 break;
4629 case 'n':
4630 execute = B_FALSE;
4631 manifest_path = optarg;
4632 manifest_pos = optind - 1;
4633 break;
4634 case 'U':
4635 /*
4636 * Undocumented 'force update' option for p2v update on
4637 * attach when zone is in the incomplete state. Change
4638 * the option back to 'u' and set forced_update flag.
4639 */
4640 if (optind == last_index)
4641 offset = optind;
4642 else
4643 offset = optind - 1;
4644 if ((up = index(argv[offset], 'U')) != NULL)
4645 *up = 'u';
4646 forced_update = B_TRUE;
4647 break;
4648 default:
4649 /* Ignore unknown options - may be brand specific. */
4650 break;
4651 }
4652 last_index = optind;
4653 }
4654
4655 if (brand_help) {
4656 force = B_FALSE;
4657 execute = B_TRUE;
4658 }
4659
4660 /* dry-run and force flags are mutually exclusive */
4661 if (!execute && force) {
4662 zerror(gettext("-F and -n flags are mutually exclusive"));
4663 return (Z_ERR);
4664 }
4665
4666 /*
4667 * If the no-execute option was specified, we don't do validation and
4668 * need to figure out the brand, since there is no zone required to be
4669 * configured for this option.
4670 */
4671 if (execute) {
4672 if (!brand_help) {
4673 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
4674 B_TRUE, forced_update) != Z_OK)
4675 return (Z_ERR);
4676 if (verify_details(CMD_ATTACH, argv) != Z_OK)
4677 return (Z_ERR);
4678 }
4679
4680 if ((err = zone_get_zonepath(target_zone, zonepath,
4681 sizeof (zonepath))) != Z_OK) {
4682 errno = err;
4683 zperror2(target_zone,
4684 gettext("could not get zone path"));
4685 return (Z_ERR);
4686 }
4687 } else {
4688 if (dryrun_get_brand(manifest_path, tmpmanifest,
4689 sizeof (tmpmanifest)) != Z_OK)
4690 return (Z_ERR);
4691
4692 argv[manifest_pos] = tmpmanifest;
4693 target_zone = "-";
4694 (void) strlcpy(zonepath, "-", sizeof (zonepath));
4727 return (Z_ERR);
4728
4729 /* Append all options to postattach hook. */
4730 if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
4731 return (Z_ERR);
4732
4733 if (execute && !brand_help) {
4734 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4735 zerror(gettext("another %s may have an operation in "
4736 "progress."), "zoneadm");
4737 return (Z_ERR);
4738 }
4739 }
4740
4741 if (!force) {
4742 /*
4743 * Not a force-attach, so we need to actually do the work.
4744 */
4745 if (cmdbuf[0] != '\0') {
4746 /* Run the attach hook */
4747 status = do_subproc(cmdbuf);
4748 if ((status = subproc_status(gettext("brand-specific "
4749 "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
4750 if (status == ZONE_SUBPROC_USAGE && !brand_help)
4751 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4752
4753 if (execute && !brand_help) {
4754 assert(zonecfg_lock_file_held(&lockfd));
4755 zonecfg_release_lock_file(target_zone,
4756 lockfd);
4757 lockfd = -1;
4758 }
4759
4760 assert(lockfd == -1);
4761 return (Z_ERR);
4762 }
4763 }
4764
4765 /*
4766 * Else run the built-in attach support.
4767 * This is a no-op since there is nothing to validate.
4768 */
4769
4770 /* If dry-run or help, then we're done. */
4771 if (!execute || brand_help) {
4772 if (!execute)
4773 (void) unlink(tmpmanifest);
4774 assert(lockfd == -1);
4777 }
4778
4779 if ((handle = zonecfg_init_handle()) == NULL) {
4780 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4781 err = Z_ERR;
4782 } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4783 errno = err;
4784 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4785 zonecfg_fini_handle(handle);
4786 } else {
4787 zonecfg_rm_detached(handle, force);
4788 zonecfg_fini_handle(handle);
4789 }
4790
4791 if (err == Z_OK &&
4792 (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4793 errno = err;
4794 zperror(gettext("could not reset state"), B_TRUE);
4795 }
4796
4797 assert(zonecfg_lock_file_held(&lockfd));
4798 zonecfg_release_lock_file(target_zone, lockfd);
4799 lockfd = -1;
4800
4801 /* If we have a brand postattach hook, run it. */
4802 if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
4803 status = do_subproc(postcmdbuf);
4804 if (subproc_status(gettext("brand-specific postattach"),
4805 status, B_FALSE) != ZONE_SUBPROC_OK) {
4806 if ((err = zone_set_state(target_zone,
4807 ZONE_STATE_CONFIGURED)) != Z_OK) {
4808 errno = err;
4809 zperror(gettext("could not reset state"),
4810 B_TRUE);
4811 }
4812 }
4813 }
4814
4815 assert(lockfd == -1);
4816 return ((err == Z_OK) ? Z_OK : Z_ERR);
4817 }
5096 zone_cmd_arg_t zarg;
5097
5098 if (argc > 0)
5099 return (Z_USAGE);
5100 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5101 != Z_OK)
5102 return (Z_ERR);
5103
5104 zarg.cmd = Z_UNMOUNT;
5105 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5106 zerror(gettext("call to %s failed"), "zoneadmd");
5107 return (Z_ERR);
5108 }
5109 return (Z_OK);
5110 }
5111
5112 static int
5113 mark_func(int argc, char *argv[])
5114 {
5115 int err, lockfd;
5116 int arg;
5117 boolean_t force = B_FALSE;
5118 int state;
5119
5120 optind = 0;
5121 opterr = 0;
5122 while ((arg = getopt(argc, argv, "F")) != EOF) {
5123 switch (arg) {
5124 case 'F':
5125 force = B_TRUE;
5126 break;
5127 default:
5128 return (Z_USAGE);
5129 }
5130 }
5131
5132 if (argc != (optind + 1))
5133 return (Z_USAGE);
5134
5135 if (strcmp(argv[optind], "configured") == 0)
5136 state = ZONE_STATE_CONFIGURED;
5137 else if (strcmp(argv[optind], "incomplete") == 0)
5138 state = ZONE_STATE_INCOMPLETE;
5139 else if (strcmp(argv[optind], "installed") == 0)
5140 state = ZONE_STATE_INSTALLED;
5141 else
5142 return (Z_USAGE);
5143
5144 if (state != ZONE_STATE_INCOMPLETE && !force)
5145 return (Z_USAGE);
5146
5147 if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
5148 != Z_OK)
5149 return (Z_ERR);
5150
5151 /*
5152 * Invoke brand-specific handler.
5153 */
5154 if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5155 return (Z_ERR);
5156
5157 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5158 zerror(gettext("another %s may have an operation in progress."),
5159 "zoneadm");
5160 return (Z_ERR);
5161 }
5162
5163 err = zone_set_state(target_zone, state);
5164 if (err != Z_OK) {
5165 errno = err;
5166 zperror2(target_zone, gettext("could not set state"));
5167 }
5168 zonecfg_release_lock_file(target_zone, lockfd);
5169
5170 return (err);
5171 }
5172
5173 /*
5174 * Check what scheduling class we're running under and print a warning if
5175 * we're not using FSS.
5176 */
5177 static int
5178 check_sched_fss(zone_dochandle_t handle)
5179 {
5180 char class_name[PC_CLNMSZ];
5181
5182 if (zonecfg_get_dflt_sched_class(handle, class_name,
5183 sizeof (class_name)) != Z_OK) {
5598 /*
5599 * See if we have inherited the right to manipulate this zone from
5600 * a zoneadm instance in our ancestry. If so, set zone_lock_cnt to
5601 * indicate it. If not, make that explicit in our environment.
5602 */
5603 zonecfg_init_lock_file(target_zone, &zone_lock_env);
5604 if (zone_lock_env != NULL)
5605 zoneadm_is_nested = B_TRUE;
5606
5607 /*
5608 * If we are going to be operating on a single zone, retrieve its
5609 * brand type and determine whether it is native or not.
5610 */
5611 if ((target_zone != NULL) &&
5612 (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
5613 if (zone_get_brand(target_zone, target_brand,
5614 sizeof (target_brand)) != Z_OK) {
5615 zerror(gettext("missing or invalid brand"));
5616 exit(Z_ERR);
5617 }
5618 }
5619
5620 err = parse_and_run(argc - optind, &argv[optind]);
5621
5622 return (err);
5623 }
|