--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/rad/mod/zones/api_zones.c Wed May 12 16:54:43 2010 -0700
@@ -0,0 +1,1544 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <libdladm.h>
+#include <libdllink.h>
+#include <libzonecfg.h>
+#include <limits.h>
+#include <locale.h>
+#include <netinet/in.h>
+#include <sys/priocntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stropts.h>
+#include <sys/fork.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+#include <zone.h>
+#include "api_zones.h"
+#include "rad_object.h"
+#include "rad_adr.h"
+
+/*
+ * Creates a zone error struct based on a zones error code
+ */
+static data_t *
+zone_create_error(char *string)
+{
+ data_t *error = NULL;
+ data_t *ecode = NULL;
+ data_t *msg = NULL;
+
+ error = data_new_struct(&t__ZonesError);
+ if (error == NULL)
+ goto err;
+ ecode = data_new_enum_byname(&t__ZonesErrorCode, string);
+ if (ecode == NULL)
+ goto err;
+
+ struct_set(error, "error", ecode);
+
+ msg = data_new_string(string, lt_copy);
+ struct_set(error, "message", msg);
+
+ return (error);
+err:
+ if (error)
+ data_free(error);
+ return (NULL);
+}
+
+
+conerr_t
+api_SchedulerManagement_invoke_setDefaultScheduler(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_SchedulerManagement_invoke_setDefaultScheduler\n");
+ return (ce_system);
+}
+
+void
+delete_configured_interfaces(zone_dochandle_t handle)
+{
+ struct zone_nwiftab tab;
+
+ for (;;) {
+ if (zonecfg_setnwifent(handle) != Z_OK)
+ return;
+
+ if (zonecfg_getnwifent(handle, &tab) != Z_OK)
+ break;
+
+ (void) zonecfg_delete_nwif(handle, &tab);
+ zonecfg_endnwifent(handle);
+ }
+ zonecfg_endnwifent(handle);
+}
+
+int
+set_configured_interfaces(zone_dochandle_t handle, data_t *cfg,
+ zone_iptype_t ziptype, data_t **error)
+{
+ data_t *networks;
+ data_t *net;
+ data_t *string;
+ int i;
+ struct zone_nwiftab tab;
+
+ networks = struct_get(cfg, "networks");
+ if (networks == NULL)
+ return (0);
+
+ for (i = 0; i < array_size(networks); i++) {
+
+ net = array_get(networks, i);
+ if (net == NULL)
+ continue;
+
+ tab.zone_nwif_address[0] = '\0';
+ tab.zone_nwif_physical[0] = '\0';
+ tab.zone_nwif_defrouter[0] = '\0';
+
+ /* XXX need some funcs to validate physical and address */
+ string = struct_get(net, "physical");
+ (void) strlcpy(tab.zone_nwif_physical, data_to_string(string),
+ sizeof (tab.zone_nwif_physical));
+
+ string = struct_get(net, "address");
+ (void) strlcpy(tab.zone_nwif_address, data_to_string(string),
+ sizeof (tab.zone_nwif_address));
+
+ /* physical must be specified */
+ if (tab.zone_nwif_physical[0] == '\0') {
+ *error = zone_create_error("INVALIDNETWORK");
+ return (-1);
+ }
+ /* Exclusive stack zones cannot specify ip addresses */
+ if (ziptype == ZS_EXCLUSIVE &&
+ tab.zone_nwif_address[0] != '\0') {
+ *error = zone_create_error("INVALIDNETWORK");
+ return (-1);
+ }
+
+ /* Shared stack zones must specify ip addresses */
+ if (ziptype == ZS_SHARED &&
+ tab.zone_nwif_address[0] == '\0') {
+ *error = zone_create_error("INVALIDNETWORK");
+ return (-1);
+ }
+
+ /* Add network to zone's configuation */
+ if (zonecfg_add_nwif(handle, &tab) != Z_OK) {
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static data_t *
+get_configured_interfaces(zone_dochandle_t handle, boolean_t noglobalcfg)
+{
+ data_t *networks, *net, *string;
+ struct zone_nwiftab tab;
+
+ networks = data_new_array(&t_array__Network, 0);
+ if (networks == NULL)
+ goto err;
+
+ if (noglobalcfg)
+ return (networks);
+
+ if (zonecfg_setnwifent(handle) != Z_OK)
+ return (NULL);
+
+ while (zonecfg_getnwifent(handle, &tab) == Z_OK) {
+
+ net = data_new_struct(&t__Network);
+ if (net == NULL)
+ goto err;
+
+ if (array_add(networks, net) != 0) {
+ data_free(net);
+ goto err;
+ }
+
+ string = data_new_string(tab.zone_nwif_physical, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(net, "physical", string);
+
+ string = data_new_string(tab.zone_nwif_address, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(net, "address", string);
+
+ }
+ zonecfg_endnwifent(handle);
+ return (networks);
+err:
+ zonecfg_endnwifent(handle);
+
+ if (networks != NULL)
+ data_free(networks);
+
+ return (NULL);
+}
+
+conerr_t
+api_zonesManagement_invoke_getZoneConfig(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count,
+ data_t **error)
+{
+ const char *zonename;
+ data_t *config = NULL;
+ data_t *string;
+ data_t *iptype;
+ data_t *networks;
+ data_t *err = NULL;
+ char path[MAXPATHLEN];
+ char class[PC_CLNMSZ];
+ char shares[22];
+ int res;
+ uint64_t val;
+ zone_iptype_t ziptype;
+ zone_dochandle_t handle = NULL;
+ int d = 0;
+ boolean_t noglobalcfg = B_FALSE;
+
+ zonename = data_to_string(args[0]);
+
+ /* Make sure zone exists */
+ res = zone_get_zonepath((char *)zonename, path, sizeof (path));
+ if (res != Z_OK) {
+ if (res == Z_NO_ZONE) {
+ err = zone_create_error("ZONENOTEXISTS");
+ goto err;
+ } else {
+ return (ce_system);
+ }
+ }
+
+ /* Create the zoneconfig struct to return */
+ config = data_new_struct(&t__ZoneConfig);
+ if (config == NULL)
+ goto err;
+
+ /* Set zonename */
+ string = data_new_string(zonename, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(config, "zoneName", string);
+
+ /* Set zonepath */
+ string = data_new_string(path, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(config, "zonePath", string);
+
+ /* Get handle to read zone configuration */
+ handle = zonecfg_init_handle();
+ if (handle == NULL)
+ goto err;
+
+ res = zonecfg_get_handle(zonename, handle);
+ if (res != Z_OK) {
+ if (strcmp(zonename, "global") == 0)
+ noglobalcfg = B_TRUE;
+ else
+ goto err;
+ }
+
+ /* Get cpu shares */
+ res = zonecfg_get_aliased_rctl(handle, ALIAS_SHARES, &val);
+ if (res == Z_OK)
+ (void) snprintf(shares, sizeof (shares), "%llu", val);
+ else if (res == Z_NO_ENTRY)
+ shares[0] = '\0';
+ else if (noglobalcfg)
+ shares[0] = '\0';
+ else
+ goto err;
+
+ /* make up stuff for global zone iptype and scheduler */
+ if (strcmp(zonename, "global") == 0) {
+ ziptype = ZS_SHARED;
+ class[0] = '\0';
+
+ } else {
+ res = zonecfg_get_iptype(handle, &ziptype);
+ if (res != Z_OK)
+ goto err;
+
+ res = zonecfg_get_sched_class(handle, class, sizeof (class));
+ if (res != Z_OK)
+ goto err;
+
+ }
+
+ /* Set config struct values */
+ if (ziptype == ZS_SHARED)
+ iptype = data_new_enum_byname(&t__IpType, "SHARED");
+ else
+ iptype = data_new_enum_byname(&t__IpType, "EXCLUSIVE");
+ if (iptype == NULL)
+ goto err;
+ struct_set(config, "iptype", iptype);
+
+ if ((string = data_new_string(class, lt_copy)) == NULL)
+ goto err;
+ struct_set(config, "scheduler", string);
+
+ if ((string = data_new_string(shares, lt_copy)) == NULL)
+ goto err;
+ struct_set(config, "cpuShares", string);
+
+ networks = get_configured_interfaces(handle, noglobalcfg);
+ if (networks == NULL)
+ goto err;
+
+ struct_set(config, "networks", networks);
+ zonecfg_fini_handle(handle);
+
+ /* Get the configured networks for the zone */
+ *ret = config;
+ return (ce_ok);
+err:
+
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
+
+ if (config != NULL)
+ data_free(config);
+
+ if (err != NULL) {
+ *error = err;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_getAllZoneConfig(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED:"
+ " api_zonesManagement_invoke_getAllZoneConfig\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_verifyZoneConfig(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED:"
+ "api_zonesManagement_invoke_verifyZoneConfig\n");
+ return (ce_system);
+}
+
+/*
+ * Shared function used by setZoneConfig and zoneConfigure
+ */
+static int
+set_zone_config(zone_dochandle_t handle, data_t *cfg, const char *zonename,
+ zone_state_t state, boolean_t new, data_t **error)
+{
+ char oldpath[MAXPATHLEN];
+ const char *newpath;
+ const char *oldname, *newname;
+ const char *iptype, *sched, *shares;
+ int res;
+ zone_iptype_t ziptype;
+ uint64_t val;
+ /* Zonename can only be changed for configured or installed zones */
+ newname = data_to_string(struct_get(cfg, "zoneName"));
+ oldname = zonename;
+ if (new == B_FALSE && state != ZONE_STATE_CONFIGURED &&
+ state != ZONE_STATE_INSTALLED) {
+ if (strcmp(oldname, newname) != 0) {
+ *error = zone_create_error("ZONENAMEIMMUTABLE");
+ goto err;
+ }
+ }
+ res = zonecfg_validate_zonename(newname);
+ if (res == Z_BOGUS_ZONE_NAME) {
+ *error = zone_create_error("INVALIDZONENAME");
+ goto err;
+ } else if (res != Z_OK) {
+ goto err;
+ }
+ if (zonecfg_set_name(handle, (char *)newname) != Z_OK)
+ goto err;
+
+ /* Zonepath can only be changed for configured zones */
+ newpath = data_to_string(struct_get(cfg, "zonePath"));
+ if (new == B_FALSE && state != ZONE_STATE_CONFIGURED) {
+ if (zonecfg_get_zonepath(handle, oldpath, sizeof (oldpath))
+ != Z_OK)
+ goto err;
+ if (strcmp(oldpath, newpath) != 0) {
+ *error = zone_create_error("ZONEPATHIMMUTABLE");
+ goto err;
+ }
+ }
+ /* XXX no zonecfg function exists to validate zonepath! */
+ if (zonecfg_set_zonepath(handle, (char *)newpath) != Z_OK)
+ goto err;
+
+
+ /* set scheduler. XXX Need func to validate sched */
+ sched = data_to_string(struct_get(cfg, "scheduler"));
+ if (zonecfg_set_sched(handle, (char *)sched) != Z_OK)
+ goto err;
+
+ shares = data_to_string(struct_get(cfg, "cpuShares"));
+ errno = 0;
+ val = strtoull(shares, NULL, 10);
+ if (errno == 0)
+ if (zonecfg_set_aliased_rctl(handle, ALIAS_SHARES, val)
+ != Z_OK)
+ goto err;
+
+ /* Set the iptype */
+ iptype = enum_tostring(struct_get(cfg, "iptype"));
+ if (strcmp(iptype, "EXCLUSIVE") == 0)
+ ziptype = ZS_EXCLUSIVE;
+ else
+ ziptype = ZS_SHARED;
+ if (zonecfg_set_iptype(handle, ziptype) != Z_OK)
+ goto err;
+
+ delete_configured_interfaces(handle);
+
+ if (set_configured_interfaces(handle, cfg, ziptype, error) != 0) {
+ goto err;
+ }
+ if (zonecfg_save(handle) != Z_OK) {
+ goto err;
+ }
+
+ return (0);
+err:
+ return (-1);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneConfig(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ zone_dochandle_t handle = NULL;
+ zone_state_t state;
+ const char *zonename;
+ data_t *cfg;
+ data_t *eo = NULL;
+ int res;
+
+ zonename = data_to_string(args[0]);
+ cfg = args[1];
+
+ /* Make sure zone exists. */
+ /* XXX Need some atomicity here for check and modify */
+ res = zone_get_state((char *)zonename, &state);
+ if (res != Z_OK) {
+ eo = zone_create_error("ZONENOTEXISTS");
+ goto err;
+ }
+
+ /* get new handle for new zone */
+ handle = zonecfg_init_handle();
+ if (handle == NULL)
+ goto err;
+
+ /* Create a new zone document */
+ res = zonecfg_get_handle(zonename, handle);
+ if (res != Z_OK)
+ goto err;
+
+ /* Set configuration and save */
+ if (set_zone_config(handle, cfg, zonename, state, B_FALSE, &eo) != 0)
+ goto err;
+
+ zonecfg_fini_handle(handle);
+ return (ce_ok);
+
+err:
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
+
+ if (eo != NULL) {
+ *error = eo;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneConfigure(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ zone_dochandle_t handle = NULL;
+ zone_state_t state;
+ char template[ZONENAME_MAX];
+ const char *zonename;
+ data_t *cfg = args[0];
+ data_t *eo = NULL;
+ int res;
+
+ zonename = data_to_string(struct_get(cfg, "zoneName"));
+
+ /* Make sure zone does not exist */
+ /* XXX Need some atomicity here for check and create */
+ res = zone_get_state((char *)zonename, &state);
+ if (res == Z_OK) {
+ eo = zone_create_error("ZONEEXISTS");
+ goto err;
+ }
+
+ /* get new handle for new zone */
+ handle = zonecfg_init_handle();
+ if (handle == NULL)
+ goto err;
+
+ /* Create a new zone document */
+ (void) strlcpy(template, "SUNWdefault", sizeof (template));
+ res = zonecfg_get_template_handle(template, zonename, handle);
+ if (res != Z_OK)
+ goto err;
+
+ /* Set configuration and save */
+ if (set_zone_config(handle, cfg, zonename, state, B_TRUE, &eo) != 0)
+ goto err;
+
+ zonecfg_fini_handle(handle);
+ return (ce_ok);
+
+err:
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
+
+ if (eo != NULL) {
+ *error = eo;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneUnconfigure(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ zone_dochandle_t handle = NULL;
+ zone_state_t state;
+ const char *zonename;
+ data_t *cfg;
+ data_t *eo = NULL;
+ int res;
+
+ zonename = data_to_string(args[0]);
+ cfg = args[1];
+
+ /* Make sure zone exists */
+ /* XXX Need some atomicity here for check and create */
+ res = zone_get_state((char *)zonename, &state);
+ if (res != Z_OK) {
+ eo = zone_create_error("ZONENOTEXISTS");
+ goto err;
+ }
+
+ /* Zone must be in the configured state to destroy it */
+ if (state != ZONE_STATE_CONFIGURED) {
+ eo = zone_create_error("ZONENOTCONFIGURED");
+ goto err;
+ }
+
+ /* XXX Need some atomicity here for check and destroy */
+ if (zonecfg_destroy(zonename, B_FALSE) != Z_OK)
+ goto err;
+
+ return (0);
+err:
+ if (eo != NULL) {
+ *error = eo;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+static int
+get_exclusive_interfaces(zoneid_t zid, data_t *networks)
+{
+ int nlinks, new_nlinks, i, res;
+ datalink_id_t *linkids;
+ dladm_status_t dlres;
+ dladm_handle_t dlh = NULL;
+ char linkname[MAXLINKNAMELEN];
+ data_t *network = NULL;
+ data_t *string;
+
+link_again:
+
+ /* Get the datalinks for the zone */
+ nlinks = 0;
+ linkids = NULL;
+ res = zone_list_datalink(zid, &nlinks, NULL);
+ if (res != 0)
+ goto err;
+
+ if (nlinks == 0)
+ return (0);
+
+ linkids = malloc(nlinks *
+ sizeof (datalink_id_t));
+
+ res = zone_list_datalink(zid, &new_nlinks,
+ linkids);
+ if (res != 0)
+ goto err;
+
+ if (new_nlinks > nlinks)
+ goto link_again;
+
+ if (new_nlinks == 0) {
+ free(linkids);
+ return (0);
+ }
+
+ if (dladm_open(&dlh) != DLADM_STATUS_OK)
+ goto err;
+
+ /* create a network for each datalink */
+ for (i = 0; i < new_nlinks; i++) {
+
+
+ dlres = dladm_datalink_id2info(dlh,
+ linkids[i], NULL, NULL, NULL,
+ linkname, sizeof (linkname));
+
+ if (dlres != DLADM_STATUS_OK)
+ goto err;
+
+ network = data_new_struct(&t__Network);
+ if (network == NULL)
+ goto err;
+ res = array_add(networks, network);
+ if (res != 0) {
+ data_free(network);
+ goto err;
+ }
+ string = data_new_string(linkname,
+ lt_copy);
+ if (string == NULL)
+ goto err;
+
+ struct_set(network, "physical",
+ string);
+ }
+ free(linkids);
+ linkids = NULL;
+ dladm_close(dlh);
+ dlh = NULL;
+
+ return (0);
+err:
+ if (linkids != NULL)
+ free(linkids);
+ if (dlh != NULL)
+ dladm_close(dlh);
+
+ return (-1);
+}
+
+static int
+get_shared_interfaces(zoneid_t zid, data_t *networks)
+{
+ struct lifnum lifn;
+ struct lifconf lifc;
+ struct lifreq *lifrp, lifrl;
+ int64_t lifc_flags = LIFC_NOXMIT | LIFC_ALLZONES;
+ int num_ifs, s = -1, i, ret_code = 0;
+ uint_t bufsize;
+ char *buf = NULL;
+ data_t *string;
+ data_t *network;
+ int res;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
+ char addrstr[INET6_ADDRSTRLEN];
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (-1);
+ /* Get the number of logical interfaces */
+if_again:
+ lifn.lifn_family = AF_UNSPEC;
+ lifn.lifn_flags = (int)lifc_flags;
+ if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0)
+ goto err;
+
+ num_ifs = lifn.lifn_count;
+ bufsize = num_ifs * sizeof (struct lifreq);
+ if ((buf = malloc(bufsize)) == NULL)
+ goto err;
+
+ /* Get the list of logical interfaces */
+ lifc.lifc_family = AF_UNSPEC;
+ lifc.lifc_flags = (int)lifc_flags;
+ lifc.lifc_len = bufsize;
+ lifc.lifc_buf = buf;
+ if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
+ /* Try again if interfaces no longer fit in buf */
+ if (errno == EINVAL) {
+ free(buf);
+ buf = NULL;
+ goto if_again;
+ } else {
+ goto err;
+ }
+ }
+ close(s);
+ s = -1;
+ /* Walk the list of logical interfaces */
+ lifrp = lifc.lifc_req;
+ for (i = lifc.lifc_len / sizeof (struct lifreq); i > 0; i--, lifrp++) {
+
+ if ((s = socket(lifrp->lifr_addr.ss_family, SOCK_DGRAM, 0)) <
+ 0)
+ goto err;
+
+ (void) memset(&lifrl, 0, sizeof (lifrl));
+ (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
+ sizeof (lifrl.lifr_name));
+
+ /* Check the flags for loopback interfaces */
+ if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) {
+ if (errno == ENXIO) {
+ /*
+ * Interface may have been removed by admin or
+ * another zone halting.
+ */
+ close(s);
+ s = -1;
+ continue;
+ } else {
+ goto err;
+ }
+ }
+ /* Skip loopback interfaces */
+ if (lifrl.lifr_flags & IFF_LOOPBACK) {
+ close(s);
+ s = -1;
+ continue;
+ }
+ /* get zone of interface */
+ if (ioctl(s, SIOCGLIFZONE, (caddr_t)&lifrl) < 0) {
+ if (errno == ENXIO) {
+ /*
+ * Interface may have been removed by admin or
+ * another zone halting.
+ */
+ close(s);
+ s = -1;
+ continue;
+ } else {
+ goto err;
+ }
+ }
+ /* skip interfaces not for this zone */
+ if (lifrl.lifr_zoneid != zid) {
+ close(s);
+ s = -1;
+ continue;
+ }
+ /* get the address of the interface */
+ if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifrl) < 0) {
+ if (errno == ENXIO) {
+ /*
+ * Interface may have been removed by admin or
+ * another zone halting.
+ */
+ close(s);
+ s = -1;
+ continue;
+ } else {
+ goto err;
+ }
+ }
+ if (lifrl.lifr_addr.ss_family == AF_INET) {
+ ipv4 = (struct sockaddr_in *)&lifrl.lifr_addr;
+ if (inet_ntop(AF_INET, &ipv4->sin_addr, addrstr,
+ sizeof (addrstr)) == NULL)
+ goto err;
+
+ } else if (lifrl.lifr_addr.ss_family = AF_INET6) {
+ ipv6 = (struct sockaddr_in6 *)&lifrl.lifr_addr;
+ if (inet_ntop(AF_INET6, &ipv6->sin6_addr, addrstr,
+ sizeof (addrstr)) == NULL)
+ goto err;
+ } else {
+ close(s);
+ s = -1;
+ continue;
+ }
+
+ network = data_new_struct(&t__Network);
+ if (network == NULL)
+ goto err;
+ res = array_add(networks, network);
+ if (res != 0) {
+ data_free(network);
+ goto err;
+ }
+ string = data_new_string(lifrl.lifr_name, lt_copy);
+ if (string == NULL)
+ goto err;
+
+ struct_set(network, "physical",
+ string);
+
+ string = data_new_string(addrstr, lt_copy);
+ if (string == NULL)
+ goto err;
+
+ struct_set(network, "address", string);
+
+ close(s);
+ }
+
+ free(buf);
+ return (0);
+
+err:
+ if (s >= 0)
+ close(s);
+ if (buf != NULL)
+ free(buf);
+
+ return (-1);
+}
+
+conerr_t
+api_zonesManagement_invoke_getSystemState(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ data_t *systemState = NULL;
+ data_t *zoneState = NULL;
+ data_t *zoneNames = NULL;
+ data_t *zonesConfigured = NULL;
+ data_t *zonesInstalled = NULL;
+ data_t *zonesRunning = NULL;
+ data_t *zoneStates = NULL;
+ data_t *installedState = NULL;
+ data_t *runningState = NULL;
+ data_t *networks = NULL;
+
+ data_t *string;
+ conerr_t err;
+ int numzones;
+
+ FILE *cookie;
+ char *name;
+ zone_state_t zstate;
+ zone_iptype_t ziptype;
+ ushort_t zflags;
+ zoneid_t zid;
+ uuid_t uuid;
+
+ char path[MAXPATHLEN];
+ char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
+ int res;
+
+ /* Top level structure for system State */
+ systemState = data_new_struct(&t__SystemState);
+ if (systemState == NULL)
+ goto err;
+
+ /* Create list of zone state structs */
+ zoneStates = data_new_array(&t_array__ZoneState, 0);
+ if (zoneStates == NULL)
+ goto err;
+ struct_set(systemState, "zones", zoneStates);
+
+ /* Create lists of zone names */
+ zoneNames = data_new_array(&t_array_string, 0);
+ if (zoneNames == NULL)
+ goto err;
+ struct_set(systemState, "zoneNames", zoneNames);
+
+ zonesConfigured = data_new_array(&t_array_string, 0);
+ if (zonesConfigured == NULL)
+ goto err;
+ struct_set(systemState, "zonesConfigured", zonesConfigured);
+
+ zonesInstalled = data_new_array(&t_array_string, 0);
+ if (zonesInstalled == NULL)
+ goto err;
+ struct_set(systemState, "zonesInstalled", zonesInstalled);
+
+ zonesRunning = data_new_array(&t_array_string, 0);
+ if (zonesRunning == NULL)
+ goto err;
+ struct_set(systemState, "zonesRunning", zonesRunning);
+
+ /* Walk each zone and set state */
+ if ((cookie = setzoneent()) == NULL)
+ goto err;
+
+ while ((name = getzoneent(cookie)) != NULL) {
+
+ /* Get the zone's state */
+ /*
+ * XXX need to interact with zone lock to ensure that
+ * no zones are configured or configured while this
+ * look is running, and in general, the index file does
+ * not change.
+ */
+ res = zone_get_state(name, &zstate);
+ if (res != Z_OK)
+ goto err;
+
+ /* Add the zone to the name list */
+ string = data_new_string(name, lt_copy);
+ if (string == NULL)
+ goto err;
+ res = array_add(zoneNames, string);
+ if (res != 0) {
+ data_free(string);
+ goto err;
+ }
+
+ /* Create a state object for zone */
+ zoneState = data_new_struct(&t__ZoneState);
+ if (zoneState == NULL)
+ goto err;
+ res = array_add(zoneStates, zoneState);
+ if (res != 0) {
+ data_free(zoneState);
+ goto err;
+ }
+ string = data_new_string(name, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(zoneState, "name", string);
+
+ /* Set the state for each zone */
+ switch (zstate) {
+ case ZONE_STATE_CONFIGURED:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "CONFIGURED"));
+ break;
+ case ZONE_STATE_INCOMPLETE:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "INCOMPLETE"));
+ break;
+ case ZONE_STATE_INSTALLED:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "INSTALLED"));
+ break;
+ case ZONE_STATE_READY:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "READY"));
+ break;
+ case ZONE_STATE_MOUNTED:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "MOUNTED"));
+ break;
+ case ZONE_STATE_RUNNING:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "RUNNING"));
+ break;
+ case ZONE_STATE_SHUTTING_DOWN:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "HALTING"));
+ break;
+ case ZONE_STATE_DOWN:
+ struct_set(zoneState, "state",
+ data_new_enum_byname(&t__ZoneStateCode,
+ "DOWN"));
+ break;
+ default:
+ goto err;
+ }
+
+ /* add the state details for each zone */
+ switch (zstate) {
+ case ZONE_STATE_RUNNING:
+ case ZONE_STATE_SHUTTING_DOWN:
+ case ZONE_STATE_DOWN:
+ string = data_new_string(name, lt_copy);
+ if (string == NULL)
+ goto err;
+ res = array_add(zonesRunning, string);
+ if (res != 0) {
+ data_free(string);
+ goto err;
+ }
+
+ /* Create the running state object for the zone */
+ runningState =
+ data_new_struct(&t__ZoneRunningState);
+ if (runningState == NULL)
+ goto err;
+ struct_set(zoneState, "runningState",
+ runningState);
+
+ networks = data_new_array(&t_array__Network, 0);
+ if (networks == NULL)
+ goto err;
+ struct_set(runningState, "networks", networks);
+
+ zid = getzoneidbyname(name);
+ if (zid < 0)
+ goto err;
+
+ res = zone_getattr(zid, ZONE_ATTR_FLAGS, &zflags,
+ sizeof (zflags));
+ if (res != sizeof (zflags))
+ goto err;
+
+ if (zflags & ZF_NET_EXCL) {
+ ziptype = ZS_EXCLUSIVE;
+ res = get_exclusive_interfaces(zid, networks);
+ if (res != 0)
+ goto err;
+ struct_set(runningState, "iptype",
+ data_new_enum_byname(&t__IpType,
+ "EXCLUSIVE"));
+ } else {
+ ziptype = ZS_SHARED;
+
+ res = get_shared_interfaces(zid, networks);
+ if (res != 0)
+ goto err;
+ struct_set(runningState, "iptype",
+ data_new_enum_byname(&t__IpType,
+ "SHARED"));
+ }
+ /* FALLTHROUGH */
+ case ZONE_STATE_INSTALLED:
+ case ZONE_STATE_MOUNTED:
+ case ZONE_STATE_READY:
+ string = data_new_string(name, lt_copy);
+ if (string == NULL)
+ goto err;
+ res = array_add(zonesInstalled, string);
+ if (res != 0) {
+ data_free(string);
+ goto err;
+ }
+
+ /* Add the details about the installed zone */
+ installedState =
+ data_new_struct(&t__ZoneInstalledState);
+ if (installedState == NULL)
+ goto err;
+ struct_set(zoneState, "installedState",
+ installedState);
+
+ res = zone_get_zonepath(name, path, sizeof (path));
+ if (res != 0)
+ goto err;
+ string = data_new_string(path, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(installedState, "zonepath", string);
+
+ res = zonecfg_get_uuid(name, uuid);
+ if (res != 0)
+ goto err;
+ uuid_unparse(uuid, uuidstr);
+ string = data_new_string(uuidstr, lt_copy);
+ if (string == NULL)
+ goto err;
+ struct_set(installedState, "uuid", string);
+
+ /* FALLTHROUGH */
+ case ZONE_STATE_INCOMPLETE:
+ case ZONE_STATE_CONFIGURED:
+ string = data_new_string(name, lt_copy);
+ if (string == NULL)
+ goto err;
+ res = array_add(zonesConfigured, string);
+ if (res != 0) {
+ data_free(string);
+ goto err;
+ }
+ break;
+ default:
+ goto err;
+ }
+
+ }
+ endzoneent(cookie);
+ *ret = systemState;
+ return (ce_ok);
+err:
+
+ if (cookie != NULL)
+ endzoneent(cookie);
+
+ /* Rely on recursive data_free to free everything */
+ if (systemState != NULL)
+ data_free(systemState);
+
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_getZoneState(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED:"
+ " api_zonesManagement_invoke_getZoneState\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_GetCpuState(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_GetCpuState\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZonePool(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZonePool\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneScheduler(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZoneScheduler\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneCpuShares(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZoneCpuShares\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneCappedCpu(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZoneCappedCpu\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneDedicatedCpu(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZoneDedicatedCpu\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_setZoneCappedMemory(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_setZoneCappedMemory\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneMove(struct instance *inst, struct method *meth,
+ data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED:"
+ " api_zonesManagement_invoke_zoneMove\n");
+ return (ce_system);
+}
+
+static int
+forkexec(const char *path, const char **argv, int *status)
+{
+ pid_t p = forkx(FORK_WAITPID);
+ if (p == 0) {
+ (void) dup2(2, 1);
+ (void) execv(path, (char **)argv);
+ _exit(1);
+ }
+ if (p > 0) {
+ siginfo_t si;
+ if (waitid(P_PID, p, &si, WEXITED) == -1) {
+ return (1);
+ }
+ if (status != NULL)
+ *status = si.si_status;
+ return (0);
+ }
+ return (1);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneInstall(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ const char *zonename = data_to_string(args[0]);
+ data_t *pkgs = args[1];
+ data_t *eo = NULL;
+ int res, i;
+ const char **argv = NULL;
+ int argc = 0;
+ int nargs = 5;
+ int npkgs = 0;
+ int status;
+ zone_state_t state;
+
+ /* Make sure zone exists */
+ /* XXX Need some atomicity here for check and install */
+ res = zone_get_state((char *)zonename, &state);
+ if (res != Z_OK) {
+ eo = zone_create_error("ZONENOTEXISTS");
+ goto err;
+ }
+
+ /* Zone must be in the configured state to install it */
+ if (state != ZONE_STATE_CONFIGURED) {
+ eo = zone_create_error("ZONENOTCONFIGURED");
+ goto err;
+ }
+
+ if (pkgs != NULL && array_size(pkgs) > 0) {
+ npkgs = array_size(pkgs);
+ }
+ /* Allocate argv for zoneadm options, including extra packages */
+ argv = malloc(sizeof (char *) * (nargs + (npkgs * 2)));
+ if (argv == NULL)
+ goto err;
+
+ /* add cli options for install */
+ argv[argc++] = "zoneadm";
+ argv[argc++] = "-z";
+ argv[argc++] = (char *)zonename;
+ argv[argc++] = "install";
+ argv[argc] = NULL;
+
+ /* add cli options for packages */
+ for (i = 0; i < npkgs; i++) {
+ argv[argc++] = "-e";
+ argv[argc++] = (char *)data_to_string(array_get(pkgs, i));
+ argv[argc] == NULL;
+ }
+
+ res = forkexec("/usr/sbin/zoneadm", argv, &status);
+ if (res != 0 || status != 0) {
+ eo = zone_create_error("UNKNOWN");
+ goto err;
+ }
+
+ free(argv);
+ return (ce_ok);
+err:
+ if (argv != NULL)
+ free(argv);
+
+ if (eo != NULL) {
+ *error = eo;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneUninstall(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ const char *zonename = data_to_string(args[0]);
+ data_t *eo = NULL;
+ int res;
+ const char **argv = NULL;
+ int argc = 0;
+ int nargs = 6;
+ int status;
+ zone_state_t state;
+
+ /* Make sure zone exists */
+ /* XXX Need some atomicity here for check and install */
+ res = zone_get_state((char *)zonename, &state);
+ if (res != Z_OK) {
+ eo = zone_create_error("ZONENOTEXISTS");
+ goto err;
+ }
+
+ /* Zone must be in the configured state to install it */
+ if (state != ZONE_STATE_INSTALLED) {
+ eo = zone_create_error("ZONENOTINSTALLED");
+ goto err;
+ }
+
+ /* Allocate argv for zoneadm options, including extra packages */
+ argv = malloc(sizeof (char *) * nargs);
+ if (argv == NULL)
+ goto err;
+
+ /* add cli options for install */
+ argv[argc++] = "zoneadm";
+ argv[argc++] = "-z";
+ argv[argc++] = (char *)zonename;
+ argv[argc++] = "uninstall";
+ argv[argc++] = "-F";
+ argv[argc] = NULL;
+
+ res = forkexec("/usr/sbin/zoneadm", argv, &status);
+ if (res != 0 || status != 0) {
+ eo = zone_create_error("UNKNOWN");
+ goto err;
+ }
+
+ free(argv);
+ return (ce_ok);
+err:
+ if (argv != NULL)
+ free(argv);
+
+ if (eo != NULL) {
+ *error = eo;
+ return (ce_object);
+ }
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneInstallP2V(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneInstallP2V\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneClone(struct instance *inst, struct method *meth,
+ data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneClone\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneAttach(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneAttach\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneDetach(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneDetach\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneVerify(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneVerify\n");
+ return (ce_system);
+}
+
+/*
+ * Adds a warning to an array of warnings. If "warnings" is NULL,
+ * the warning list will be created.
+ */
+static data_t *
+zone_add_warning(data_t *warnings, char *string)
+{
+ data_t *warning = NULL;
+ data_t *wcode = NULL;
+ data_t *msg = NULL;
+
+ if (warnings == NULL) {
+ if (data_new_array(&t_array__ZonesWarning, 0) != 0)
+ goto err;
+ }
+ if ((warning = data_new_struct(&t__ZonesWarning)) == NULL)
+ goto err;
+ if (array_add(warnings, warning) != 0)
+ goto err;
+ if ((wcode = data_new_enum_byname(&t__ZonesWarningCode, string))
+ == NULL)
+ goto err;
+ struct_set(warning, "warning", wcode);
+ if ((msg = data_new_string(string, lt_copy)) == NULL)
+ goto err;
+ struct_set(warning, "message", msg);
+
+ return (warnings);
+err:
+ if (warnings != NULL)
+ data_free(warnings);
+
+ return (NULL);
+}
+
+conerr_t
+do_zoneadmd_cmd(struct instance *inst, struct method *meth,
+ data_t **ret, data_t **args, int count, data_t **error, int cmd)
+{
+ zone_cmd_arg_t zarg;
+ char *locale;
+ zarg.cmd = Z_BOOT;
+ const char *zonename;
+ data_t *warnings;
+ data_t *err;
+ int i, res;
+ char *zone_lock_env;
+ zone_state_t zstate;
+ char path[MAXPATHLEN];
+
+ /* We can trust that there is one arg which is a string */
+ zonename = data_to_string(args[0]);
+
+ /* Make sure zone exists */
+ res = zone_get_state((char *)zonename, &zstate);
+ if (res != Z_OK) {
+ if (res == Z_NO_ZONE) {
+ if ((err = zone_create_error("ZONENOTCONFIGURED"))
+ == NULL)
+ return (ce_system);
+ goto err;
+ } else {
+ return (ce_system);
+ }
+ }
+ if ((locale = setlocale(LC_ALL, "")) == NULL)
+ locale = "C";
+
+ zonecfg_init_lock_file(zonename, &zone_lock_env);
+
+ zarg.bootbuf[0] = '\0';
+ zarg.cmd = cmd;
+ /*
+ * XXX lacks sanity checks done my zoneadm. Will succeed if zone
+ * is already booted.
+ */
+ /*
+ * XXX libzonecfg should use forkx(FORK_WAITPID)
+ */
+ sigset(SIGCHLD, SIG_DFL);
+ res = zonecfg_call_zoneadmd(zonename, &zarg, locale, B_TRUE);
+ sigset(SIGCHLD, SIG_IGN);
+
+ if (res != Z_OK) {
+ if ((err = zone_create_error("UNKNOWN")) == NULL)
+ return (ce_system);
+ goto err;
+ } else {
+ return (ce_ok);
+ }
+
+err:
+ if (data_purify(err) == NULL) {
+ return (ce_system);
+ }
+ *error = err;
+ return (ce_object);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneBoot(struct instance *inst, struct method *meth,
+ data_t **ret, data_t **args, int count, data_t **error)
+{
+
+ return (do_zoneadmd_cmd(inst, meth, ret, args, count, error, Z_BOOT));
+}
+
+
+conerr_t
+api_zonesManagement_invoke_zoneReboot(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ return (do_zoneadmd_cmd(inst, meth, ret, args, count, error, Z_REBOOT));
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneHalt(struct instance *inst, struct method *meth,
+ data_t **ret, data_t **args, int count, data_t **error)
+{
+ return (do_zoneadmd_cmd(inst, meth, ret, args, count, error, Z_HALT));
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneIsConfigured(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneIsConfigured\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneIsInstalled(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneIsInstalled\n");
+ return (ce_system);
+}
+
+conerr_t
+api_zonesManagement_invoke_zoneIsRunning(struct instance *inst,
+ struct method *meth, data_t **ret, data_t **args, int count, data_t **error)
+{
+ (void) fprintf(stderr, "NOT IMPLEMENTED: "
+ "api_zonesManagement_invoke_zoneIsRunning\n");
+ return (ce_system);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/zmgr/zmgr.py Wed May 12 16:54:43 2010 -0700
@@ -0,0 +1,539 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+import socket
+import rad.client as rad
+import sys
+import getopt
+
+
+def usage():
+ print >> sys.stderr, "Usage: zmgr help"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> create -p <zonepath>"
+ print >> sys.stderr, " zmgr -z <zonename> delete"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> config list"
+ print >> sys.stderr, " zmgr -z <zonename> config info"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> config set iptype [shared | exclusive ] "
+ print >> sys.stderr, " zmgr -z <zonename> config set scheduler <sched>"
+ print >> sys.stderr, " zmgr -z <zonename> config set cpu-shares <shares>"
+ print >> sys.stderr, " zmgr -z <zonename> config add net -p <physical> -a <address>"
+ print >> sys.stderr, " zmgr -z <zonename> config remove net -p <physical> -a <address>"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> state list"
+ print >> sys.stderr, " zmgr -z <zonename> state info"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> install <pkgs> ..."
+ print >> sys.stderr, " zmgr -z <zonename> uninstall"
+ print >> sys.stderr, ""
+ print >> sys.stderr, " zmgr -z <zonename> boot"
+ print >> sys.stderr, " zmgr -z <zonename> halt"
+ print >> sys.stderr, " zmgr -z <zonename> reboot"
+ print >> sys.stderr, ""
+ sys.exit(2);
+
+def state_info_func(zones):
+
+ for zone in zones:
+
+ print ""
+ print zone.name
+
+ print " state :", zone.state
+ if zone.installedState:
+ print " zonepath:", zone.installedState.zonepath
+ print " uuid :", zone.installedState.uuid
+ if zone.runningState:
+ print " iptype :", zone.runningState.iptype
+ for net in zone.runningState.networks:
+ print " network :", net.physical
+ if (zone.runningState.iptype == "SHARED"):
+ print " addr :", net.address
+
+ return (0);
+
+def state_list_func(zones):
+
+ format = "%-15s%-15s%-20s%-10s%-20s"
+ print format %("NAME", "STATUS", "PATH", "IPTYPE", "NETS")
+ for zone in zones:
+
+ path = "-";
+ iptype = "-"
+ nets = {};
+
+ if (zone.installedState):
+ path = zone.installedState.zonepath
+
+ if (zone.runningState):
+ iptype = zone.runningState.iptype;
+ for net in zone.runningState.networks:
+ nets[net.physical] = 1;
+
+ print format % (zone.name, zone.state, path, iptype, nets.keys())
+ return(0);
+
+def state_func(args):
+
+ if (len(args) == 0):
+ usage();
+
+ try:
+ state = obj.getSystemState(1, 0, 0, 0, None);
+ except rad.RadException, ex:
+ print ex.message;
+ return 1;
+
+ if (zonename != ""):
+ for zone in state.zones:
+ if (zone.name == zonename):
+ zones = [ zone ];
+ break;
+ else:
+ zones = state.zones
+
+ if (args[0] == "list"):
+ return state_list_func(zones);
+ elif (args[0] == "info"):
+ return state_info_func(zones);
+ else:
+ usage();
+
+# Configure a new zone
+def create_func(args):
+ try:
+ opts, args = getopt.getopt(args, "p:");
+ except getopt.GetoptError, err:
+ print >> sys.stderr, str(err)
+ usage();
+ sys.exit(2);
+
+ found=0
+ for o,a in opts:
+ if o == "-p":
+ zonepath = a
+ found=1
+
+ if (found == 0):
+ usage();
+
+ argtype = obj._object.get_type("ZoneConfig");
+ cfg = argtype.makev(zonename, zonepath, "", "1", "SHARED",
+ None, None, None, None)
+
+ try:
+ obj.zoneConfigure(cfg);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+ return 0;
+
+def delete_func(args):
+ try:
+ obj.zoneUnconfigure(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 0;
+
+def config_list_func(args):
+ try:
+ state = obj.getSystemState(1, 0, 0, 0, None);
+ except rad.RadException, ex:
+ print ex.message;
+ return 1;
+
+ if (zonename != ""):
+ for zone in state.zoneNames:
+ if (zone.name == zonename):
+ zones = [ zonename ];
+ break;
+ else:
+ zones = state.zoneNames
+
+ format = "%-15s%-25s%-10s%-10s%-15s"
+ print format %("NAME", "PATH", "IPTYPE", "SHARES", "NETS")
+
+ for zone in zones:
+ try:
+ cfg = obj.getZoneConfig(zone);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+
+ if (cfg.cpuShares != ""):
+ if cfg.scheduler == "FSS":
+ shares = cfg.cpuShares
+ else:
+ shares = "*%s" % (cfg.cpuShares)
+ else:
+ shares="-"
+ nets = {};
+ for net in cfg.networks:
+ nets[net.physical] = 1;
+
+ print format % (zone, cfg.zonePath, cfg.iptype, shares, nets.keys())
+ return(0);
+
+def config_info_func(args):
+ try:
+ state = obj.getSystemState(1, 0, 0, 0, None);
+ except rad.RadException, ex:
+ print ex.message;
+ return 1;
+
+ if (zonename != ""):
+ for zone in state.zoneNames:
+ if (zone == zonename):
+ zones = [ zonename ];
+ break;
+ else:
+ zones = state.zoneNames
+
+
+ for zone in zones:
+ try:
+ cfg = obj.getZoneConfig(zone);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+
+ if (cfg.cpuShares != ""):
+ if cfg.scheduler == "FSS":
+ shares = cfg.cpuShares
+ else:
+ shares = "*%s" % (cfg.cpuShares)
+ else:
+ shares=""
+ nets = {};
+ for net in cfg.networks:
+ nets[net.physical] = 1;
+
+ print ""
+ print zone
+ print " zonepath :", cfg.zonePath
+ print " ipytpe :", cfg.iptype
+ print " scheduler:", cfg.scheduler
+ print " cpu-share:", shares
+ for net in cfg.networks:
+ print " network :", net.physical
+ if (cfg.iptype == "SHARED"):
+ print " addr :", net.address
+
+ return(0);
+
+def config_set_func(args):
+
+ if (zonename == ""):
+ usage()
+
+ if (len(args) != 2):
+ usage;
+ try:
+ cfg = obj.getZoneConfig(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+
+ prop = args[0];
+ value = args[1];
+
+ if prop == "iptype":
+ if value == "shared":
+ cfg.iptype = "SHARED";
+ elif value == "exclusive":
+ cfg.iptype = "EXCLUSIVE";
+ else:
+ usage();
+ elif prop == "scheduler":
+ cfg.scheduler = value;
+ elif prop == "cpu-shares":
+ cfg.cpuShares = value;
+ else:
+ usage()
+
+ try:
+ obj.setZoneConfig(zonename, cfg);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1;
+ return 0;
+
+def config_add_func(args):
+ if (zonename == ""):
+ usage()
+
+ if args[0] != "net":
+ usage();
+
+ args = args[1:];
+
+ physical=""
+ address=""
+
+ try:
+ opts, args = getopt.getopt(args, "p:a:");
+ except getopt.GetoptError, err:
+ print >> sys.stderr, str(err)
+ usage();
+
+ for o, a in opts:
+ if o == "-p":
+ physical = a
+ if o == "-a":
+ address = a;
+
+ if physical == "":
+ print >> sys.stderr, "-p <physical> required"
+ usage()
+ try:
+ cfg = obj.getZoneConfig(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+
+
+ if (cfg.iptype == "EXCLUSIVE"):
+
+ if address != "":
+ print >> sys.stderr, "-a not invalid for exclusive stack"
+ usage();
+
+ found = 0;
+ for net in cfg.networks:
+ if net.physical == physical:
+ found = 1;
+
+ if found == 0:
+ argtype = obj._object.get_type("Network");
+ net = argtype.makev(physical, "", "");
+ cfg.networks.append(net);
+ else:
+ if address == "":
+ print >> sys.stderr, "-a not required for shared stack"
+ usage();
+
+ found = 0;
+ for net in cfg.networks:
+ if net.physical == physical and net.address == address:
+ found = 1;
+ net.address = address;
+ if found == 0:
+ argtype = obj._object.get_type("Network");
+ net = argtype.makev(physical, address, "");
+ cfg.networks.append(net);
+
+ try:
+ obj.setZoneConfig(zonename, cfg);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1;
+ return 0;
+
+def config_remove_func(args):
+
+ if (zonename == ""):
+ usage()
+
+ if args[0] != "net":
+ usage();
+
+ args = args[1:];
+
+ physical=""
+ address=""
+
+ try:
+ opts, args = getopt.getopt(args, "p:a:");
+ except getopt.GetoptError, err:
+ print >> sys.stderr, str(err)
+ usage();
+
+ for o, a in opts:
+ if o == "-p":
+ physical = a
+ if o == "-a":
+ address = a;
+
+ if physical == "":
+ print >> sys.stderr, "-p <physical> required"
+ usage()
+ try:
+ cfg = obj.getZoneConfig(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+
+ newnets = [];
+ if (cfg.iptype == "EXCLUSIVE"):
+
+ if address != "":
+ print >> sys.stderr, "-a not invalid for exclusive stack"
+ usage();
+
+ found = 0;
+ for net in cfg.networks:
+ if net.physical == physical:
+ found = 1;
+ else:
+ newnets.append(net);
+ if found == 0:
+ print >> sys.stderr, "Network not found!"
+ else:
+ if address == "":
+ print >> sys.stderr, "-a not required for shared stack"
+ usage();
+
+ found = 0;
+ for net in cfg.networks:
+ if net.physical == physical and net.address == address:
+ found = 1;
+ else:
+ newnets.append(net)
+ if found == 0:
+ print >> sys.stderr, "Network not found!"
+
+ cfg.networks = newnets;
+ try:
+ obj.setZoneConfig(zonename, cfg);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1;
+ return 0;
+
+def config_func(args):
+
+ config_funcs = {
+ "list" : config_list_func,
+ "info" : config_info_func,
+ "set" : config_set_func,
+ "add" : config_add_func,
+ "remove" : config_remove_func }
+
+ cmd = args[0];
+ args = args[1:];
+
+ if cmd not in config_funcs:
+ usage();
+
+ return config_funcs[cmd](args);
+
+def install_func(args):
+ try:
+ obj.zoneinstall(zonename, []);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+ return 0;
+
+def uninstall_func(args):
+ try:
+ obj.zoneUninstall(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+ return 0;
+
+def boot_func(args):
+ try:
+ obj.zoneBoot(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+ return 0;
+
+def halt_func(args):
+ try:
+ obj.zoneHalt(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+
+ return 0;
+
+def reboot_func(args):
+ try:
+ obj.zoneReboot(zonename);
+ except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ return 1
+ return 0;
+
+def list_func(args):
+ return ();
+
+# set up some dispatch
+do_funcs = {
+ "state" : state_func,
+ "create" : create_func,
+ "delete" : delete_func,
+ "config" : config_func,
+ "install" : install_func,
+ "uninstall" : uninstall_func,
+ "boot" : boot_func,
+ "halt" : halt_func,
+ "reboot" : reboot_func }
+
+# process args
+argv = sys.argv[1:]
+try:
+ opts, args = getopt.getopt(argv, "z:");
+except getopt.GetoptError, err:
+ print >> sys.stderr, str(err)
+ usage();
+
+zonename=""
+for o,a in opts:
+ if o == "-z":
+ zonename = a
+
+cmd = args[0];
+args = args[1:];
+
+if (cmd == "help"):
+ usage();
+
+if cmd not in do_funcs:
+ usage();
+
+# Inital args look ok. Connect to rad
+s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM);
+s.connect("/var/run/radsocket");
+rc = rad.RadConnection(s)
+obj = rc.get_object_s("com.oracle.solaris.zonesManagement", [("type", "zonesManager")])
+
+res = do_funcs[cmd](args)
+
+sys.exit(res);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/zmgr/ztest.py Wed May 12 16:54:43 2010 -0700
@@ -0,0 +1,188 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+import socket
+import rad.client as rad
+import sys
+
+# Make connection (AF_UNIX socket lets us bypass authentication)
+s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM);
+s.connect("/var/run/radsocket");
+
+#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
+#s.connect(("localhost", 1234))
+
+rc = rad.RadConnection(s)
+
+# Get an authorization token from authenticated session
+#auth = rc.get_object_s("org.opensolaris.os.rad", [("type", "authentication")])
+#block = auth.login("C", "root");
+#print block.type
+#for m in block.messages:
+# print m.style
+# print m.message
+#block = auth.submit(["l1admin"])
+#print block.type
+
+# Continue using newly authenticated session
+# Obtain service object for application/pkg/server:default
+obj = rc.get_object_s("com.oracle.solaris.zonesManagement", [("type", "zonesManager")])
+
+print ""
+print "Test getSystemState"
+try:
+ systemState = obj.getSystemState(0, 0, 0, 0, None)
+ print "\tPASS"
+except:
+ print "\tFAIL"
+
+print ""
+print "Test zone name lists"
+try:
+
+ print "\tzones :", systemState.zoneNames
+ print "\tconfigured:", systemState.zonesConfigured
+ print "\tinstalled :", systemState.zonesInstalled
+ print "\trunning :", systemState.zonesRunning
+ print "\tPASS"
+except:
+ print "\tFAIL"
+
+print ""
+print "Test print zone states"
+try:
+ for state in systemState.zones:
+
+ cfg = obj.getZoneConfig(state.name)
+
+
+ print ""
+ print "\t", state.name
+ print "\tstate: ", state.state
+
+ print "\tconfigured:"
+
+ print "\tzonepath: ", cfg.zonePath
+ print "\tiptype : ", cfg.iptype
+ print "\tscheduler: ", cfg.scheduler
+ for network in cfg.networks:
+ print "\tnetwork : ", network.physical
+ if network.address:
+ print "\t ", network.address
+
+ print " installed:"
+ if state.name in systemState.zonesInstalled:
+ print "\tzonepath: ", state.installedState.zonepath
+ print "\tuuid : ", state.installedState.uuid
+ print " running:"
+ if state.name in systemState.zonesRunning:
+ print "\tiptype : ", state.runningState.iptype
+ for network in state.runningState.networks:
+ print "\tnetwork : ", network.physical
+ if network.address:
+ print "\t ", network.address
+except:
+ print "\tFAIL"
+
+print ""
+print "Test configure and unconfigure zone"
+try:
+ cfgtype = obj._object.get_type("ZoneConfig");
+ cfg = cfgtype.makev("test-unconfig", "/export/test-unconfig",
+ "FSS", "1", "SHARED", None, None, None, None)
+ obj.zoneConfigure(cfg);
+ cfg = obj.getZoneConfig("test-unconfig");
+ obj.zoneUnconfigure("test-unconfig");
+ try:
+ obj.getZoneConfig("test-unconfig");
+ print "\tFAIL"
+ except rad.RadException, ex:
+ print "\tPASS"
+except rad.RadException, ex:
+ print "\tFAIL"
+ print ex.get_payload()
+
+print ""
+print "Test configure, install, boot, reboot, halt, uninstall, unconfigure"
+try:
+ cfgtype = obj._object.get_type("ZoneConfig");
+ cfg = cfgtype.makev("test-install", "/export/test-install",
+ "FSS", "1", "SHARED", None, None, None, None)
+ obj.zoneConfigure(cfg);
+ obj.zoneInstall("test-install", []);
+ obj.zoneBoot("test-install")
+ obj.zoneReboot("test-install")
+ obj.zoneHalt("test-install")
+ obj.zoneUninstall("test-install");
+ obj.zoneUnconfigure("test-install");
+ print "\tPASS"
+except rad.RadException, ex:
+ print "\tFAIL"
+ err = ex.get_payload()
+ print err;
+
+print ""
+print "Test boot non-existent zone:"
+try:
+ res = obj.zoneBoot("nosuchzone")
+ print "\tFAILED"
+except rad.RadException, ex:
+ error = ex.get_payload();
+ print "\t", error.message
+ print "\tPASS"
+
+
+print ""
+print "Test setZoneConfig"
+argtype = obj._object.get_type("ZoneConfig");
+
+try:
+ # Configure zone
+ zoneConfig = argtype.makev("test", "/export/oldpath", "", "",
+ "SHARED", None, None, None, None)
+ obj.zoneConfigure(zoneConfig);
+
+ # Change zonepath
+ newConfig = argtype.makev("test", "/export/newpath", "", "",
+ "SHARED", None, None, None, None)
+ obj.setZoneConfig("test", newConfig);
+
+ # Change zonename
+ newConfig = argtype.makev("test-new", "/export/newpath", "", "",
+ "SHARED", None, None, None, None)
+ obj.setZoneConfig("test", newConfig);
+
+ # Change scheduler and cpu shares
+ newConfig = argtype.makev("test-new", "/export/newpath", "FSS", "10",
+ "SHARED", None, None, None, None)
+ obj.setZoneConfig("test-new", newConfig);
+
+ # Unconfigure zones
+ obj.zoneUnconfigure("test-new");
+ print "\tPASS"
+except rad.RadException, ex:
+ error = ex.get_payload();
+ print error.message
+ print "\tFAILED"
+
+s.close()