
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@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@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@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