This patch add the core functions in CIM model, which provided the capabilities
to configure the bridge and vlan child ports. It is based on DSP1050.
Signed-off-by: Wayne Xia <xiawenc(a)linux.vnet.ibm.com>
---
...irtualEthernetSwitchSystemManagementService.mof | 14 +
...ernetSwitchSystemManagementService.registration | 3 +
..._VirtualEthernetSwitchSystemManagementService.c | 1342 ++++++++++++++++++++
..._VirtualEthernetSwitchSystemManagementService.h | 31 +
4 files changed, 1390 insertions(+), 0 deletions(-)
create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.mof
create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.registration
create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.c
create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.h
diff --git a/schema/VirtualEthernetSwitchSystemManagementService.mof
b/schema/VirtualEthernetSwitchSystemManagementService.mof
new file mode 100644
index 0000000..5317305
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemManagementService.mof
@@ -0,0 +1,14 @@
+// Copyright IBM Corp. 2011
+
+[Provider("cmpi::Virt_VirtualEthernetSwitchSystemManagementService")]
+class Net_VirtualEthernetSwitchSystemManagementService :
CIM_VirtualSystemManagementService
+{
+ [Description("HG changeset id of the providers")]
+ string Changeset;
+
+ [Description("HG revision number of the providers")]
+ string Revision;
+
+ [Description("Package Version")]
+ string Release;
+};
diff --git a/schema/VirtualEthernetSwitchSystemManagementService.registration
b/schema/VirtualEthernetSwitchSystemManagementService.registration
new file mode 100644
index 0000000..ef2b4b1
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemManagementService.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_VirtualEthernetSwitchSystemManagementService root/virt
Virt_VirtualEthernetSwitchSystemManagementService
Virt_VirtualEthernetSwitchSystemManagementService method instance
diff --git a/src/Virt_VirtualEthernetSwitchSystemManagementService.c
b/src/Virt_VirtualEthernetSwitchSystemManagementService.c
new file mode 100644
index 0000000..c60068c
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystemManagementService.c
@@ -0,0 +1,1342 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc(a)cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <time.h>
+#include <sys/time.h>
+#include <libvirt/libvirt.h>
+
+#include "cmpidt.h"
+#include "cmpift.h"
+#include "cmpimacs.h"
+
+#include "cs_util.h"
+#include "misc_util.h"
+#include "device_parsing.h"
+#include "xmlgen.h"
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_invokemethod.h>
+#include <libcmpiutil/std_indication.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "misc_util.h"
+#include "infostore.h"
+
+#include "Virt_VirtualSystemManagementService.h"
+#include "Virt_VirtualEthernetSwitchSystemManagementService.h"
+#include "Virt_VirtualEthernetSwitchSystem.h"
+#include "Virt_HostSystem.h"
+#include "Virt_EASD.h"
+#include "network_model.h"
+#include "svpc_types.h"
+
+#include "config.h"
+
+
+static const CMPIBroker *_BROKER;
+
+typedef enum ResourceAction {
+ RESOURCE_ADD,
+ RESOURCE_DEL,
+ RESOURCE_MOD,
+} ResourceAction;
+
+static CMPIArray *set_result_res_vessms(struct inst_list *list,
+ const char *ns)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *op = NULL;
+ CMPIArray *res = NULL;
+ int i = 0;
+
+ if (list->cur == 0) {
+ CU_DEBUG("No resources were added or modified");
+ return res;
+ }
+
+ res = CMNewArray(_BROKER, list->cur, CMPI_ref, &s);
+ if ((s.rc != CMPI_RC_OK) || (res == NULL)) {
+ CU_DEBUG("Unable to create results array");
+ goto out;
+ }
+
+ for (i = 0; list->list[i] != NULL; i++) {
+ op = CMGetObjectPath(list->list[i], NULL);
+ if (op == NULL) {
+ CU_DEBUG("Unable to EASD reference");
+ goto out;
+ }
+ CMSetNameSpace(op, ns);
+
+ s = CMSetArrayElementAt(res, i, (CMPIValue *)&op, CMPI_ref);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("Error setting results array element");
+ goto out;
+ }
+ }
+
+ out:
+ if (s.rc != CMPI_RC_OK) {
+ res = NULL;
+ }
+
+ return res;
+}
+
+static CMPIStatus check_piface_for_easd_ea(const CMPIBroker *broker,
+ EthIface *piface)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ VLAN_Prop_8021q *pvlan_8021q;
+ if ((piface->eth_type != ETH_TYPE_VLAN) ||
+ (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "now only support opertaion for IEEE 802.1.q.");
+ CU_DEBUG("only support IEEE 802.1.q.");
+ eth_iface_print(piface);
+ goto out;
+ }
+
+ pvlan_8021q = &(piface->pvlan_prop->props.prop_8021q);
+ if ((pvlan_8021q->vlan_id < 0) || (pvlan_8021q->vlan_id > 4095)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "invalid vlan id set.");
+ CU_DEBUG("invalid vlan id %d set.", pvlan_8021q->vlan_id);
+ goto out;
+ }
+
+ out:
+ return s;
+}
+
+static CMPIStatus check_piface_for_easd_ec(const CMPIBroker *broker,
+ EthIface *piface_src,
+ EthIface *piface_dest)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ if ((piface_dest->eth_type != ETH_TYPE_BRIDGE) ||
+ (piface_dest->name == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "now only support connection between bridge and "
+ "port, but the dest is not a bridge or "
+ "dest name not got.");
+ CU_DEBUG("requested connectting device %s is not a bridge.",
+ piface_dest->name);
+ goto out;
+ }
+
+ if (piface_src->name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "connection src port was not got.");
+ CU_DEBUG("connection src port was not got.");
+ goto out;
+ }
+
+ out:
+ return s;
+}
+
+/* piface need to be created before calling the funtion */
+static CMPIStatus instance_to_vesssd(const CMPIBroker *broker,
+ EthIface *piface,
+ CMPIInstance *inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *opathp = NULL;
+ const char *brname = NULL;
+ const char *cn;
+ char *pfx = NULL;
+ uint16_t stp;
+ int ret;
+
+ opathp = CMGetObjectPath(inst, NULL);
+ if (opathp == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "failed to get object path.");
+ goto out;
+ }
+
+ cn = CLASSNAME(opathp);
+ pfx = class_prefix_name(cn);
+ if (pfx == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unknown prefix for the class.");
+ goto out;
+ }
+
+ ret = cu_get_str_prop(inst, "VirtualSystemIdentifier", &brname);
+ if (ret != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "property VirtualSystemIdentifier not set.");
+ CU_DEBUG("failed to get property VirtualSystemIdentifier.");
+ goto out;
+ }
+ piface->name = get_iface_name_from_switch(brname);
+ if (piface->name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to convert switch_name");
+ CU_DEBUG("switch name %s failed to convert.", brname);
+ goto out;
+ }
+
+ ret = cu_get_u16_prop(inst, "STP", &stp);
+ if (ret == CMPI_RC_OK) {
+ piface->pbr_prop->STP = stp;
+ }
+
+ out:
+ free(pfx);
+ return s;
+}
+
+static CMPIStatus instance_to_easd_ea(const CMPIBroker *broker,
+ EthIface *piface,
+ CMPIInstance *inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIStatus s_tmp;
+ int ret, temp;
+ uint16_t vlan_type = 0;
+ uint16_t hdr = 0;
+ char *charpvalues[8];
+ int charpcount = 0;
+ VLAN_Prop_8021q *pvlan_8021q = NULL;
+ VLAN_Qos_8021q qos;
+ const char *ingress;
+ const char *egress;
+
+ ret = cu_get_u16_prop(inst, "VLANType", &vlan_type);
+ if (ret == CMPI_RC_OK) {
+ if (vlan_type == 1) {
+ piface->eth_type = ETH_TYPE_VLAN;
+ piface->pvlan_prop->vlan_type = VLAN_TYPE_802_1_Q;
+ pvlan_8021q = &(piface->pvlan_prop->props.prop_8021q);
+ } else {
+ CU_DEBUG("unsupported VLANType "
+ "%d requested", vlan_type);
+ }
+ } else {
+ CU_DEBUG("VLANType is missing");
+ }
+
+ if ((pvlan_8021q == NULL) ||
+ (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q)) {
+ goto end_of_8021q;
+ }
+
+ pvlan_8021q->parent = SAFE_STRDUP(piface->dep_ifname);
+
+ s_tmp = get_array_string_from_instance(broker, inst, "Connection",
+ charpvalues, &charpcount, 8);
+ if ((s_tmp.rc == CMPI_RC_OK) && (charpcount == 1)) {
+ temp = vlanid_from_connection_name(charpvalues[0]);
+ if ((temp >= 0) && (temp < 4096)) {
+ pvlan_8021q->vlan_id = temp;
+ }
+ } else {
+ CU_DEBUG("Connnection property have %d settings.",
charpcount);
+ }
+
+ /* optional settings */
+ ret = cu_get_u16_prop(inst, "ReorderHdr", &hdr);
+ if (ret == CMPI_RC_OK) {
+ pvlan_8021q->reorder_hdr = hdr;
+ }
+
+ ret = cu_get_str_prop(inst, "VLANQosIngress", &ingress);
+ if (ret == CMPI_RC_OK) {
+ CU_DEBUG("vlan qos ingress was got.");
+ if (1 == vlan_8021q_qos_str_to_num(&qos, ingress)) {
+ pvlan_8021q->ingress = qos;
+ } else {
+ CU_DEBUG("invalid ingress string.")
+ }
+ }
+
+ ret = cu_get_str_prop(inst, "VLANQosEgress", &egress);
+ if (ret == CMPI_RC_OK) {
+ CU_DEBUG("vlan qos egress was got.");
+ if (1 == vlan_8021q_qos_str_to_num(&qos, egress)) {
+ pvlan_8021q->egress = qos;
+ } else {
+ CU_DEBUG("invalid ingress string.")
+ }
+ }
+
+ end_of_8021q:
+ return s;
+}
+
+static CMPIStatus instance_to_easd_ec(const CMPIBroker *broker,
+ EthIface *piface_src,
+ EthIface *piface_dest,
+ CMPIInstance *inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL}, s_tmp;
+ int ret, i;
+ char *charpvalues[8];
+ int charpcount = 0;
+ char *prefix = NULL, *portname = NULL;
+ const char *tmp;
+
+ s_tmp = get_array_string_from_instance(broker, inst, "HostResource",
+ charpvalues, &charpcount, 8);
+ if ((s_tmp.rc == CMPI_RC_OK) && (charpcount == 1)) {
+ piface_dest->name = get_iface_name_from_switch(charpvalues[0]);
+ if (piface_dest->name != NULL) {
+ piface_dest->eth_type = ETH_TYPE_BRIDGE;
+ }
+ } else {
+ CU_DEBUG("HostResource have %d settings.", charpcount);
+ }
+ i = 0;
+ while (i < charpcount) {
+ SAFE_FREE(charpvalues[i]);
+ i++;
+ }
+
+ ret = cu_get_str_prop(inst, "Parent", &tmp);
+ if (ret == CMPI_RC_OK) {
+ if (1 == parse_fq_devid(tmp, &prefix, &portname)) {
+ SAFE_FREE(piface_src->name);
+ piface_src->name = get_iface_name_from_ethportsd(portname,
+ NULL);
+ }
+ }
+
+ SAFE_FREE(prefix);
+ SAFE_FREE(portname);
+ return s;
+}
+
+/* pifaces need to be created before calling the funtion */
+static CMPIStatus instance_to_easd(const CMPIBroker *broker,
+ const char *preset_parent,
+ EthIface *piface_src,
+ EthIface *piface_dest,
+ CMPIInstance *inst,
+ int *type)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ char *prefix = NULL;
+ char *name = NULL;
+ char *port_name = NULL;
+ char *switch_name = NULL;
+ const char *tmp;
+ int request_type = 0;
+ int ret;
+
+ CU_DEBUG("enter inst to easd, preset_parent is %s.", preset_parent);
+ /* If a preset_parent is set by the user, then the code use it as
+ parent device. This parameter was used when user call the method
+ with parameter AffectedSystem was set. */
+ if (preset_parent == NULL) {
+ s = get_instanceid(inst, &prefix, &name);
+ if ((s.rc != CMPI_RC_OK) ||
+ (prefix == NULL) || (name == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "failed to translate InstanceId");
+ CU_DEBUG("failed to translate InstanceId, "
+ "prefix %s, name %s.", prefix, name);
+ goto out;
+ }
+ } else {
+ /*fix me, use value from Parent if ElementName was not set */
+ ret = cu_get_str_prop(inst, "ElementName", &tmp);
+ if (ret == CMPI_RC_OK) {
+ name = SAFE_STRDUP(tmp);
+ prefix = SAFE_STRDUP(preset_parent);
+ } else {
+ s = get_instanceid(inst, &prefix, &name);
+ if ((s.rc != CMPI_RC_OK) || (name == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "failed to get port name, "
+ "InstanceID or ElementName "
+ "need to be set correctly.");
+ CU_DEBUG("failed to geto port name, "
+ "prefix %s, name %s.", prefix, name);
+ goto out;
+ }
+ }
+ }
+
+ if (name == NULL) {
+ s = get_instanceid(inst, &prefix, &name);
+ if ((s.rc != CMPI_RC_OK) ||
+ (prefix == NULL) || (name == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "failed to translate InstanceId");
+ CU_DEBUG("failed to translate InstanceId, "
+ "prefix %s, name %s.", prefix, name);
+ goto out;
+ }
+ }
+
+ switch_name = get_iface_name_from_switch(prefix);
+ if (switch_name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to convert instance prefix name");
+ CU_DEBUG("switch name %s failed to convert.", prefix);
+ goto out;
+ }
+ port_name = get_iface_name_from_ethportsd(name, &request_type);
+ if (port_name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to convert instance suffix name");
+ CU_DEBUG("ethport name %s failed to convert.", name);
+ goto out;
+ }
+
+ if (request_type == EASD_TYPE_EA) {
+ piface_src->name = port_name;
+ piface_src->dep_ifname = switch_name;
+ port_name = NULL;
+ switch_name = NULL;
+ s = instance_to_easd_ea(broker, piface_src, inst);
+ } else {
+ piface_src->name = port_name;
+ port_name = NULL;
+ s = instance_to_easd_ec(broker, piface_src, piface_dest, inst);
+ }
+
+ out:
+ *type = request_type;
+ SAFE_FREE(prefix);
+ SAFE_FREE(name);
+ SAFE_FREE(port_name);
+ SAFE_FREE(switch_name);
+ return s;
+}
+
+static CMPIStatus find_merge_existing_easd(const CMPIBroker *broker,
+ EthIface *piface)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ EthIface iface_ref;
+ EthIfacesList ifaces_list;
+ int ret;
+
+ eth_ifaceslist_init(&ifaces_list);
+ eth_iface_init(&iface_ref);
+ if (piface->name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "switch name not set.");
+ goto out;
+ }
+ iface_ref.name = SAFE_STRDUP(piface->name);
+ iface_ref.eth_type = piface->eth_type;
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_by_ref, &iface_ref);
+ if ((ret != 1) || (ifaces_list.count != 1)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to get original easd settings,"
+ " maybe it do not exist.");
+ goto out;
+ }
+ eth_iface_merge(piface, ifaces_list.pifaces[0], 1);
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ eth_iface_uninit(&iface_ref);
+ return s;
+}
+
+static CMPIStatus _update_easd_for(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *ref,
+ const char *preset_parent,
+ CMPIInstance *rasd,
+ ResourceAction action)
+{
+ CMPIStatus s;
+ int type;
+ EthIface iface_src, iface_dest;
+ int ret;
+ char *errstr;
+
+ eth_iface_init(&iface_src);
+ eth_iface_init(&iface_dest);
+ eth_iface_add_br_prop(&iface_src);
+ eth_iface_add_vlan_prop(&iface_src, VLAN_TYPE_802_1_Q);
+ eth_iface_add_br_prop(&iface_dest);
+ eth_iface_add_vlan_prop(&iface_dest, VLAN_TYPE_802_1_Q);
+
+
+ CU_DEBUG("Enter _update_easd_for");
+ s = instance_to_easd(broker, preset_parent,
+ &iface_src, &iface_dest, rasd, &type);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (type == EASD_TYPE_EA) {
+ s = check_piface_for_easd_ea(broker, &iface_src);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ CU_DEBUG("easd-EA operation with request type %d,"
+ "iface settings is :", action);
+ eth_iface_print(&iface_src);
+ if (action == RESOURCE_ADD) {
+ ret = add_host_iface(&iface_src, 1);
+ } else if (action == RESOURCE_MOD) {
+ s = find_merge_existing_easd(broker, &iface_src);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ ret = mod_host_iface(&iface_src, 1);
+ } else if (action == RESOURCE_DEL) {
+ ret = del_host_iface(&iface_src, 1);
+ } else {
+ errstr = "requested an unsupported operation.";
+ CU_DEBUG("%s", errstr);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+ } else {
+ s = check_piface_for_easd_ec(broker, &iface_src, &iface_dest);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ CU_DEBUG("easd-EC operation with request type %d,"
+ "iface settings are :", action);
+ eth_iface_print(&iface_src);
+ eth_iface_print(&iface_dest);
+ if (action == RESOURCE_ADD) {
+ ret = connect_two_ifaces(&iface_src, &iface_dest, 1);
+ } else if (action == RESOURCE_DEL) {
+ ret = disconnect_two_ifaces(&iface_src, &iface_dest, 1);
+ } else {
+ errstr = "requested an unsupported operation.";
+ CU_DEBUG("%s", errstr);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+ }
+
+ if (ret != 1) {
+ errstr = get_host_iface_error_reason(ret);
+ CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ out:
+ eth_iface_uninit(&iface_src);
+ eth_iface_uninit(&iface_dest);
+ return s;
+}
+
+static CMPIStatus _update_easd_settings(const CMPIContext *context,
+ const CMPIObjectPath *ref,
+ const char *bridge,
+ CMPIArray *resources,
+ const CMPIResult *results,
+ ResourceAction action,
+ struct inst_list *list)
+{
+ int i;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ int count = 0;
+ uint32_t rc = CIM_SVPC_RETURN_FAILED;
+
+ CU_DEBUG("Enter _update_easd_settings");
+ if (resources == NULL) {
+ CU_DEBUG("No easd settings.");
+ goto out;
+ }
+
+ count = CMGetArrayCount(resources, &s);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("failed to get array size.");
+ goto out;
+ }
+
+ i = 0;
+ CU_DEBUG("Trying update %d easds.", count);
+ while (i < count) {
+ CMPIData item;
+ CMPIInstance *inst;
+ item = CMGetArrayElementAt(resources, i, NULL);
+ inst = item.value.inst;
+
+ s = _update_easd_for(_BROKER,
+ context,
+ ref,
+ bridge,
+ inst,
+ action);
+ if (s.rc != CMPI_RC_OK) {
+ break;
+ }
+ inst_list_add(list, inst);
+ i++;
+ }
+
+ out:
+ if (s.rc == CMPI_RC_OK) {
+ rc = CIM_SVPC_RETURN_COMPLETED;
+ }
+ if ((results != NULL) && (resources != NULL)) {
+ CMReturnData(results, &rc, CMPI_uint32);
+ }
+
+ return s;
+}
+
+static CMPIStatus easd_refs_to_insts(const CMPIBroker *broker,
+ const CMPIContext *ctx,
+ const CMPIObjectPath *reference,
+ CMPIArray *arr,
+ CMPIArray **ret_arr)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIArray *tmp_arr;
+ int i;
+ int c;
+
+ c = CMGetArrayCount(arr, &s);
+ if (s.rc != CMPI_RC_OK) {
+ return s;
+ }
+
+ tmp_arr = CMNewArray(broker,
+ c,
+ CMPI_instance,
+ &s);
+
+ for (i = 0; i < c; i++) {
+ CMPIData d;
+ CMPIObjectPath *ref;
+ CMPIInstance *inst = NULL;
+ const char *id;
+
+ d = CMGetArrayElementAt(arr, i, &s);
+ ref = d.value.ref;
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("Unable to get ResourceSettings[%i]", i);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get ResourceSettings");
+ goto out;
+ }
+
+ if (cu_get_str_path(ref, "InstanceID", &id) != CMPI_RC_OK)
{
+ CU_DEBUG("Unable to get InstanceID of `%s'",
+ REF2STR(ref));
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get InstanceID");
+ goto out;
+ }
+
+ s = get_easd_by_id(broker, id, reference, NULL, &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ CMSetArrayElementAt(tmp_arr, i,
+ &inst,
+ CMPI_instance);
+
+ }
+
+ *ret_arr = tmp_arr;
+
+ out:
+ return s;
+}
+
+static CMPIInstance *create_switch_system(const CMPIContext *context,
+ CMPIInstance *vsssd,
+ CMPIArray *resources,
+ const CMPIObjectPath *ref,
+ const CMPIObjectPath *refconf,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ EthIface iface_br;
+ int ret;
+ char *errstr;
+ char *br_name = NULL;
+ struct inst_list list;
+
+ inst_list_init(&list);
+ eth_iface_init(&iface_br);
+ eth_iface_add_br_prop(&iface_br);
+
+ CU_DEBUG("Enter create_switch_system");
+ if (refconf != NULL) {
+ cu_statusf(_BROKER, s,
+ CMPI_RC_ERR_FAILED,
+ "creating switch system with"
+ " reference is not supported now.");
+ goto out;
+ }
+
+ *s = instance_to_vesssd(_BROKER, &iface_br, vsssd);
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(_BROKER, s,
+ CMPI_RC_ERR_FAILED,
+ "failed to translate settings.");
+ goto out;
+ }
+ iface_br.eth_type = ETH_TYPE_BRIDGE;
+ CU_DEBUG("Creating Switch System as follow:");
+ eth_iface_print(&iface_br);
+
+ ret = add_host_iface(&iface_br, 1);
+ if (ret != 1) {
+ errstr = get_host_iface_error_reason(ret);
+ CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+ cu_statusf(_BROKER, s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ br_name = get_switch_name_from_iface(iface_br.name);
+ *s = _update_easd_settings(context,
+ ref,
+ br_name,
+ resources,
+ NULL,
+ RESOURCE_ADD,
+ &list);
+
+
+ *s = get_switch_by_name(_BROKER,
+ br_name,
+ ref,
+ &inst);
+
+ out:
+ inst_list_free(&list);
+ eth_iface_uninit(&iface_br);
+ free(br_name);
+
+ return inst;
+}
+
+static CMPIStatus update_switchsystem_settings(const CMPIContext *context,
+ const CMPIObjectPath *ref,
+ CMPIInstance *vsssd)
+{
+ CMPIStatus s;
+ EthIface iface_br, iface_ref;
+ EthIfacesList ifaces_list;
+ int ret;
+ char *errstr;
+
+ eth_ifaceslist_init(&ifaces_list);
+ eth_iface_init(&iface_br);
+ eth_iface_init(&iface_ref);
+ eth_iface_add_br_prop(&iface_br);
+
+ s = instance_to_vesssd(_BROKER, &iface_br, vsssd);
+ if (s.rc != CMPI_RC_OK || (iface_br.name == NULL)) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to translate settings.");
+ goto out;
+
+ }
+
+ iface_ref.name = SAFE_STRDUP(iface_br.name);
+ iface_ref.eth_type = iface_br.eth_type;
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_by_ref, &iface_ref);
+ if ((ret != 1) || (ifaces_list.count != 1)) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to get original vs settings,"
+ " maybe it do not exist.");
+ goto out;
+ }
+ eth_iface_merge(&iface_br, ifaces_list.pifaces[0], 1);
+ CU_DEBUG("update switch settings as following settings:");
+ eth_iface_print(&iface_br);
+ ret = mod_host_iface(&iface_br, 1);
+ if (ret != 1) {
+ errstr = get_host_iface_error_reason(ret);
+ CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ eth_iface_uninit(&iface_ref);
+ eth_iface_uninit(&iface_br);
+ return s;
+}
+
+static CMPIStatus define_switch_system_parse_args(const CMPIArgs *argsin,
+ CMPIInstance **sys,
+ const char *ns,
+ CMPIArray **res,
+ CMPIObjectPath **refconf)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ if (cu_get_inst_arg(argsin, "SystemSettings", sys) != CMPI_RC_OK) {
+ CU_DEBUG("No SystemSettings string argument");
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "Missing argument `SystemSettings'");
+ goto out;
+ }
+
+ if (cu_get_array_arg(argsin, "ResourceSettings", res) !=
+ CMPI_RC_OK) {
+ CU_DEBUG("Did not get ResourceSettings arg");
+ *res = NULL;
+ }
+
+ if (cu_get_ref_arg(argsin, "ReferenceConfiguration", refconf) !=
+ CMPI_RC_OK) {
+ CU_DEBUG("Did not get ReferenceConfiguration arg");
+ *refconf = NULL;
+ }
+ out:
+ return s;
+}
+
+static CMPIStatus define_system(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *vsssd;
+ CMPIArray *res;
+ CMPIObjectPath *refconf;
+ CMPIInstance *sys = NULL;
+ CMPIObjectPath *result;
+ uint32_t rc = CIM_SVPC_RETURN_FAILED;
+
+ CU_DEBUG("DefineSystem");
+
+ s = define_switch_system_parse_args(argsin,
+ &vsssd,
+ NAMESPACE(reference),
+ &res,
+ &refconf);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ sys = create_switch_system(context, vsssd, res, reference, refconf, &s);
+ if (sys == NULL) {
+ goto out;
+ }
+
+ result = CMGetObjectPath(sys, &s);
+ if ((result != NULL) && (s.rc == CMPI_RC_OK)) {
+ CMSetNameSpace(result, NAMESPACE(reference));
+ CMAddArg(argsout, "ResultingSystem", &result, CMPI_ref);
+ }
+
+
+ out:
+ if (s.rc == CMPI_RC_OK) {
+ rc = CIM_SVPC_RETURN_COMPLETED;
+ }
+ CMReturnData(results, &rc, CMPI_uint32);
+
+ return s;
+}
+
+static CMPIStatus destroy_system(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *br_name = NULL;
+ EthIface iface_br;
+ uint32_t rc = IM_RC_FAILED;
+ CMPIObjectPath *sys;
+ int ret;
+ char *errstr;
+
+ eth_iface_init(&iface_br);
+ CU_DEBUG("entering destroy switch system.");
+
+ if (cu_get_ref_arg(argsin, "AffectedSystem", &sys) != CMPI_RC_OK)
{
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "AffectedSystem not set");
+ goto out;
+ }
+
+ br_name = get_key_from_ref_arg(argsin, "AffectedSystem",
"Name");
+ if (br_name == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed get Name of AffectedSystem");
+ goto out;
+ }
+
+ iface_br.name = get_iface_name_from_switch(br_name);
+ if (iface_br.name == NULL) {
+ CU_DEBUG("failed to get iface name from %s.", br_name);
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to translate Name of AffectedSystem");
+ goto out;
+ }
+
+ iface_br.eth_type = ETH_TYPE_BRIDGE;
+ CU_DEBUG("Deleting Switch System as follow:");
+ eth_iface_print(&iface_br);
+
+ ret = del_host_iface(&iface_br, 1);
+ if (ret != 1) {
+ errstr = get_host_iface_error_reason(ret);
+ CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ rc = IM_RC_OK;
+
+ out:
+ eth_iface_uninit(&iface_br);
+ CMReturnData(results, &rc, CMPI_uint32);
+ return s;
+}
+
+
+static CMPIStatus mod_system_settings(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIInstance *inst;
+ CMPIStatus s;
+ uint32_t rc;
+
+ if (cu_get_inst_arg(argsin, "SystemSettings", &inst) != CMPI_RC_OK)
{
+
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Missing SystemSettings");
+ goto out;
+ }
+
+ s = update_switchsystem_settings(context, reference, inst);
+ out:
+ if (s.rc == CMPI_RC_OK) {
+ rc = CIM_SVPC_RETURN_COMPLETED;
+ } else {
+ rc = CIM_SVPC_RETURN_FAILED;
+ }
+
+ CMReturnData(results, &rc, CMPI_uint32);
+
+ return s;
+}
+
+static CMPIStatus add_resource_settings(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIArray *arr;
+ CMPIStatus s;
+ CMPIObjectPath *sys;
+ char *bridge = NULL;
+ CMPIArray *res = NULL;
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ if (cu_get_array_arg(argsin, "ResourceSettings", &arr) !=
CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Missing ResourceSettings");
+ return s;
+ }
+
+ if (cu_get_ref_arg(argsin,
+ "AffectedConfiguration",
+ &sys) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "Missing AffectedConfiguration parameter");
+ return s;
+ }
+
+ if (!parse_instanceid(sys, NULL, &bridge)) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "AffectedConfiguration has invalid InstanceID");
+ return s;
+ }
+
+ s = _update_easd_settings(context,
+ reference,
+ bridge,
+ arr,
+ results,
+ RESOURCE_ADD,
+ &list);
+
+ free(bridge);
+
+ res = set_result_res_vessms(&list, NAMESPACE(reference));
+ inst_list_free(&list);
+ CMAddArg(argsout, "ResultingResourceSettings", &res, CMPI_refA);
+
+
+ return s;
+}
+
+static CMPIStatus mod_resource_settings(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIArray *arr;
+ CMPIStatus s;
+ CMPIArray *res = NULL;
+ struct inst_list list;
+
+ CU_DEBUG("Enter mod_resource_settings");
+ inst_list_init(&list);
+
+ if (cu_get_array_arg(argsin, "ResourceSettings", &arr) !=
CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Missing ResourceSettings");
+ return s;
+ }
+
+ s = _update_easd_settings(context,
+ reference,
+ NULL,
+ arr,
+ results,
+ RESOURCE_MOD,
+ &list);
+
+ res = set_result_res_vessms(&list, NAMESPACE(reference));
+ CMAddArg(argsout, "ResultingResourceSettings", &res, CMPI_refA);
+ inst_list_free(&list);
+
+ return s;
+}
+
+static CMPIStatus rm_resource_settings(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ /* The RemoveResources case is different from either Add or
+ * Modify, because it takes references instead of instances
+ */
+
+ CMPIArray *arr;
+ CMPIArray *resource_arr = NULL;
+ CMPIStatus s;
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ if (cu_get_array_arg(argsin, "ResourceSettings", &arr) !=
CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Missing ResourceSettings");
+ goto out;
+ }
+
+ /* delete is simple, just specify the names */
+ s = easd_refs_to_insts(_BROKER, context, reference, arr,
+ &resource_arr);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ s = _update_easd_settings(context,
+ reference,
+ NULL,
+ resource_arr,
+ results,
+ RESOURCE_DEL,
+ &list);
+ out:
+ inst_list_free(&list);
+
+ return s;
+}
+
+static struct method_handler DefineSystem = {
+ .name = "DefineSystem",
+ .handler = define_system,
+ .args = {{"SystemSettings", CMPI_instance, false},
+ {"ResourceSettings", CMPI_instanceA, true},
+ {"ReferenceConfiguration", CMPI_ref, true},
+ ARG_END
+ }
+};
+
+static struct method_handler DestroySystem = {
+ .name = "DestroySystem",
+ .handler = destroy_system,
+ .args = {{"AffectedSystem", CMPI_ref, false},
+ ARG_END
+ }
+};
+
+static struct method_handler AddResourceSettings = {
+ .name = "AddResourceSettings",
+ .handler = add_resource_settings,
+ .args = {{"AffectedConfiguration", CMPI_ref, false},
+ {"ResourceSettings", CMPI_instanceA, false},
+ ARG_END
+ }
+};
+
+static struct method_handler ModifyResourceSettings = {
+ .name = "ModifyResourceSettings",
+ .handler = mod_resource_settings,
+ .args = {{"ResourceSettings", CMPI_instanceA, false},
+ ARG_END
+ }
+};
+
+static struct method_handler ModifySystemSettings = {
+ .name = "ModifySystemSettings",
+ .handler = mod_system_settings,
+ .args = {{"SystemSettings", CMPI_instance, false},
+ ARG_END
+ }
+};
+
+static struct method_handler RemoveResourceSettings = {
+ .name = "RemoveResourceSettings",
+ .handler = rm_resource_settings,
+ .args = {{"ResourceSettings", CMPI_refA, false},
+ ARG_END
+ }
+};
+
+static struct method_handler *my_handlers[] = {
+ &DefineSystem,
+ &DestroySystem,
+ &AddResourceSettings,
+ &ModifyResourceSettings,
+ &ModifySystemSettings,
+ &RemoveResourceSettings,
+ NULL,
+};
+
+STDIM_MethodMIStub(, Virt_VirtualEthernetSwitchSystemManagementService,
+ _BROKER, libvirt_cim_init(), my_handlers);
+
+
+CMPIStatus get_vessms(const CMPIObjectPath *reference,
+ CMPIInstance **_inst,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ bool is_get_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char host_name[256];
+ CMPIArray *array;
+ uint16_t op_status;
+
+ *_inst = NULL;
+
+ inst = get_typed_instance(broker,
+ NETWORK_CLASS_PREFIX,
+
"VirtualEthernetSwitchSystemManagementService",
+ NAMESPACE(reference));
+
+ if (inst == NULL) {
+ CU_DEBUG("Failed to get typed instance");
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to create instance");
+ goto out;
+ }
+
+ CMSetProperty(inst, "Caption",
+ (CMPIValue *)"VLAN and VBridge services", CMPI_chars);
+
+ CMSetProperty(inst, "Name",
+ (CMPIValue *)"Management Service", CMPI_chars);
+
+ if (0 == get_fqdn(host_name, sizeof(host_name))) {
+ CMSetProperty(inst, "SystemName",
+ (CMPIValue *)host_name, CMPI_chars);
+ }
+
+ CMSetProperty(inst, "SystemCreationClassName",
+ (CMPIValue *)"KVM_HostSystem", CMPI_chars);
+
+
+ CMSetProperty(inst, "Revision",
+ (CMPIValue *)LIBVIRT_CIM_RV, CMPI_chars);
+
+ CMSetProperty(inst, "Release",
+ (CMPIValue *)PACKAGE_VERSION, CMPI_chars);
+
+ array = CMNewArray(broker, 1, CMPI_uint16, &s);
+ if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) {
+ goto out;
+ }
+
+ op_status = CIM_OPERATIONAL_STATUS;
+ CMSetArrayElementAt(array, 0, &op_status, CMPI_uint16);
+
+ CMSetProperty(inst, "OperationalStatus",
+ (CMPIValue *)&array, CMPI_uint16A);
+
+ if (is_get_inst) {
+ s = cu_validate_ref(broker, reference, inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ }
+
+ cu_statusf(broker, &s,
+ CMPI_RC_OK,
+ "");
+ out:
+ *_inst = inst;
+
+ return s;
+}
+
+static CMPIStatus return_vessms(const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ const CMPIResult *results,
+ bool name_only,
+ bool is_get_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst;
+
+ s = get_vessms(reference, &inst, _BROKER, context, is_get_inst);
+ if ((s.rc != CMPI_RC_OK) || (inst == NULL)) {
+ goto out;
+ }
+
+ if (name_only) {
+ cu_return_instance_name(results, inst);
+ } else {
+ CMReturnInstance(results, inst);
+ }
+ out:
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ return return_vessms(context, reference, results, true, false);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+
+ return return_vessms(context, reference, results, false, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const char **properties)
+{
+ return return_vessms(context, ref, results, false, true);
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_VirtualEthernetSwitchSystemManagementService,
+ _BROKER,
+ libvirt_cim_init());
+
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_VirtualEthernetSwitchSystemManagementService.h
b/src/Virt_VirtualEthernetSwitchSystemManagementService.h
new file mode 100644
index 0000000..07c0f4e
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystemManagementService.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc(a)cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef VESSMS_H
+#define VESSMS_H
+
+CMPIStatus get_vessms(const CMPIObjectPath *reference,
+ CMPIInstance **_inst,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ bool is_get_inst);
+
+#endif
--
1.7.6