
According to DSP1097, Virtual switch is modeled similar to virtual computer system. This patch consider two device as switch system: pyhical network card and bridge. Signed-off-by: Wayne Xia <xiawenc@linux.vnet.ibm.com> --- schema/VirtualEthernetSwitchSystem.mof | 10 + schema/VirtualEthernetSwitchSystem.registration | 3 + src/Virt_VirtualEthernetSwitchSystem.c | 477 +++++++++++++++++++++++ src/Virt_VirtualEthernetSwitchSystem.h | 52 +++ 4 files changed, 542 insertions(+), 0 deletions(-) create mode 100644 schema/VirtualEthernetSwitchSystem.mof create mode 100644 schema/VirtualEthernetSwitchSystem.registration create mode 100644 src/Virt_VirtualEthernetSwitchSystem.c create mode 100644 src/Virt_VirtualEthernetSwitchSystem.h diff --git a/schema/VirtualEthernetSwitchSystem.mof b/schema/VirtualEthernetSwitchSystem.mof new file mode 100644 index 0000000..5c016fd --- /dev/null +++ b/schema/VirtualEthernetSwitchSystem.mof @@ -0,0 +1,10 @@ +// Copyright IBM Corp. 2011 +[Description ( + "A class derived from CIM_ComputerSystem to represent " + "the Virtual Bridge on the host."), + Provider("cmpi::Virt_VirtualEthernetSwitchSystem") +] +class Net_VirtualEthernetSwitchSystem : CIM_ComputerSystem +{ + +}; diff --git a/schema/VirtualEthernetSwitchSystem.registration b/schema/VirtualEthernetSwitchSystem.registration new file mode 100644 index 0000000..4cd6bf4 --- /dev/null +++ b/schema/VirtualEthernetSwitchSystem.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2007 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_VirtualEthernetSwitchSystem root/virt Virt_VirtualEthernetSwitchSystem Virt_VirtualEthernetSwitchSystem instance method diff --git a/src/Virt_VirtualEthernetSwitchSystem.c b/src/Virt_VirtualEthernetSwitchSystem.c new file mode 100644 index 0000000..1816771 --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystem.c @@ -0,0 +1,477 @@ +/* + * 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 <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include <cmpidt.h> +#include <cmpift.h> +#include <cmpimacs.h> + +#include <libcmpiutil/libcmpiutil.h> +#include <libcmpiutil/std_invokemethod.h> +#include <libcmpiutil/std_instance.h> +#include <libcmpiutil/std_indication.h> + +#include "Virt_VirtualEthernetSwitchSystem.h" +#include "device_parsing.h" +#include "network_model_helper.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_switch(const CMPIBroker *broker, EthIface *piface, + CMPIInstance *instance) +{ + char *name; + uint16_t dedicated; + CMPIArray *array; + CMPIStatus s = {CMPI_RC_OK, NULL}; + + if (piface->name == NULL) { + return 0; + } + + name = get_switch_name_from_iface(piface->name); + CMSetProperty(instance, "Name", + (CMPIValue *)name, CMPI_chars); + CMSetProperty(instance, "ElementName", + (CMPIValue *)name, CMPI_chars); + SAFE_FREE(name); + + array = CMNewArray(broker, 1, CMPI_uint16, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) { + return 0; + } + dedicated = CIM_NUM_SWITCH_DEDICATED; + CMSetArrayElementAt(array, 0, &dedicated, CMPI_uint16); + CMSetProperty(instance, "Dedicated", + (CMPIValue *)&array, CMPI_uint16A); + + return 1; +} + +static int set_secondary_for_switch(const CMPIBroker *broker, EthIface *piface, + CMPIInstance *instance) +{ + int state; + if (piface->run_prop.state == ETH_STATE_DOWN) { + state = CIM_STATE_DISABLED; + } else if (piface->run_prop.state == ETH_STATE_UP) { + state = CIM_STATE_ENABLED; + } else { + state = CIM_STATE_UNKNOWN; + } + CMSetProperty(instance, "EnabledState", + (CMPIValue *)&state, CMPI_uint16); + CMSetProperty(instance, "RequestedState", + (CMPIValue *)&state, CMPI_uint16); + + return 1; +} + +/* Populate an instance with information from a switch */ +static CMPIStatus set_properties(const CMPIBroker *broker, + EthIface *piface, + const char *prefix, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr; + + if (!set_primary_for_switch(broker, piface, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (!set_secondary_for_switch(broker, piface, instance)) { + errstr = "failed to set secondary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + +static CMPIStatus instance_from_switch(const CMPIBroker *broker, + const CMPIObjectPath *reference, + EthIface *piface, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "VirtualEthernetSwitchSystem", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init VirtualEthernetSwitchSystem instance"); + goto out; + } + + s = set_properties(broker, + piface, + NETWORK_CLASS_PREFIX, + inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + *_inst = inst; + + out: + return s; +} + +CMPIStatus enum_switches(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + inst_list_init(&list); + eth_ifaceslist_init(&ifaces_list); +CU_DEBUG("##enum switch before"); + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch, NULL); +CU_DEBUG("##enum switch after"); + 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; + } + + i = 0; + while (i < ifaces_list.count) { + CMPIInstance *inst = NULL; + + s = instance_from_switch(broker, + reference, + ifaces_list.pifaces[i], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(&list, inst); + i++; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + + out: + inst_list_free(&list); + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +CMPIStatus get_switch_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *errstr; + int ret; + EthIfacesList ifaces_list; + + eth_ifaceslist_init(&ifaces_list); + + eth_name = get_iface_name_from_switch(name); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert switch_name"); + CU_DEBUG("switch name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch_for_name, eth_name); + 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; + } + if (ifaces_list.count != 1) { + errstr = "expected switch not found."; + CU_DEBUG("%s\n", errstr); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + s = instance_from_switch(broker, + reference, + ifaces_list.pifaces[0], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + eth_ifaceslist_uninit(&ifaces_list); + SAFE_FREE(eth_name); + return s; +} + +CMPIStatus get_switch_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + const char *name = NULL; + + if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "No domain name specified"); + goto out; + } + + s = get_switch_by_name(broker, name, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + + return s; +} + +static CMPIStatus __state_change(const CMPIBroker *broker, + const char *name, + uint16_t state, + const CMPIObjectPath *ref) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + EthIface iface; + int iface_state; + int ret; + char *errstr; + + eth_iface_init(&iface); + iface.name = get_iface_name_from_switch(name); + if (iface.name == NULL) { + errstr = "failed to get iface name."; + CU_DEBUG("for %s, %s.", name, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (state == CIM_STATE_ENABLED) { + iface_state = ETH_STATE_UP; + } else if (state == CIM_STATE_DISABLED) { + iface_state = ETH_STATE_DOWN; + } else { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_SUPPORTED, + "State not supported"); + goto out; + } + + /* TBD in next patch + ret = change_state_host_iface(&iface, iface_state); */ + 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); + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return enum_switches(_BROKER, reference, results, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + return enum_switches(_BROKER, reference, results, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + s = get_switch_by_ref(_BROKER, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_EQ(); +DEFAULT_INST_CLEANUP(); + +static CMPIStatus state_change(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIStatus s; + CMPIInstance *prev_inst = NULL; + uint16_t state; + int ret; + const char *name = NULL; + uint32_t rc = 1; + + ret = cu_get_u16_arg(argsin, "RequestedState", &state); + if (ret != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Invalid RequestedState"); + goto out; + } + + if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Name key not specified"); + goto out; + } + + s = get_switch_by_name(_BROKER, name, reference, &prev_inst); + if (s.rc != CMPI_RC_OK || prev_inst == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Unable to get instance for guest '%s'", + name); + goto out; + } + + s = __state_change(_BROKER, name, state, reference); + + if (s.rc == CMPI_RC_OK) { + rc = 0; + } + out: + CMReturnData(results, &rc, CMPI_uint32); + + return s; +} + +STD_InstanceMIStub(, + Virt_VirtualEthernetSwitchSystem, + _BROKER, + libvirt_cim_init()); + +static struct method_handler RequestStateChange = { + .name = "RequestStateChange", + .handler = state_change, + .args = {{"RequestedState", CMPI_uint16, false}, + {"TimeoutPeriod", CMPI_dateTime, true}, + ARG_END + } +}; + +static struct method_handler *my_handlers[] = { + &RequestStateChange, + NULL +}; + +STDIM_MethodMIStub(, + Virt_VirtualEthernetSwitchSystem, + _BROKER, + libvirt_cim_init(), + my_handlers); + +/* + * 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_VirtualEthernetSwitchSystem.h b/src/Virt_VirtualEthernetSwitchSystem.h new file mode 100644 index 0000000..de8587b --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystem.h @@ -0,0 +1,52 @@ +/* + * 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 __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H +#define __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H + +#include "misc_util.h" + +CMPIStatus enum_switches(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool names_only); + +CMPIStatus get_switch_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + + +CMPIStatus get_switch_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + + +#endif + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ -- 1.7.6