[PATCH V7 7/7] vlan extention - CIM Model - VESSMS
by Wenchao Xia
This patch added a new service class VESSMS which can modify host network
about adding, modifying, deleting 802.1.q vlan and bridge.
The model of bridge modification is according to VSMS model, and on DSP1097
it says virtual switch should be managed similar to ComputerSystem.
The model of allocation of vlan port, is on chapter 9.1.2 of DSP1050_1.0.
Difference is that, this patch did not use Parent propety to identify which
switch it should belongs to, but use property InstanceID to say it, such as
VS_eth0/EA_eth0.10, because using Parent for port allocation needs to implement
EC_POOL making things more complicate.
The model of connecting of vlan port with bridge, is on chapter 9.1.4 of
DSP1050_1.0. The patch matches it despite of that EA_POOL and EC_POOL are not
implemented.
V7: Some host network checking such as checking of existence for an EthIface
before modify it, are moved to function library. Code style changed to fit
libvirt-cim. Added properties AutoStart, DHCP, Delay. Other things are same
with V2.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
...irtualEthernetSwitchSystemManagementService.mof | 14 +
...ernetSwitchSystemManagementService.registration | 3 +
src/Virt_HostSystem.c | 2 +-
src/Virt_HostSystem.h | 2 +
..._VirtualEthernetSwitchSystemManagementService.c | 1289 ++++++++++++++++++++
..._VirtualEthernetSwitchSystemManagementService.h | 31 +
src/Virt_VirtualSystemManagementService.c | 2 +-
src/Virt_VirtualSystemManagementService.h | 4 +
8 files changed, 1345 insertions(+), 2 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_HostSystem.c b/src/Virt_HostSystem.c
index 724a5ea..de8ec13 100644
--- a/src/Virt_HostSystem.c
+++ b/src/Virt_HostSystem.c
@@ -76,7 +76,7 @@ static int resolve_host(char *host, char *buf, int size)
return 0;
}
-static int get_fqdn(char *buf, int size)
+int get_fqdn(char *buf, int size)
{
char host[256];
int ret = 0;
diff --git a/src/Virt_HostSystem.h b/src/Virt_HostSystem.h
index 53ebf1c..3b988c1 100644
--- a/src/Virt_HostSystem.h
+++ b/src/Virt_HostSystem.h
@@ -21,6 +21,8 @@
#ifndef __VIRT_HOSTSYSTEM_H
#define __VIRT_HOSTSYSTEM_H
+int get_fqdn(char *buf, int size);
+
CMPIStatus get_host(const CMPIBroker *broker,
const CMPIContext *context,
const CMPIObjectPath *reference,
diff --git a/src/Virt_VirtualEthernetSwitchSystemManagementService.c b/src/Virt_VirtualEthernetSwitchSystemManagementService.c
new file mode 100644
index 0000000..1048676
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystemManagementService.c
@@ -0,0 +1,1289 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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_helper.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,
+ struct EthIface *piface)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct VLAN_Prop_8021q *pvlan_8021q;
+ if ((piface->eth_type != ETH_TYPE_ETHER_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, request is:");
+ 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,
+ struct EthIface *piface_src,
+ struct EthIface *piface_dest)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ if ((piface_dest->eth_type != ETH_TYPE_ETHER_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,
+ struct EthIface *piface,
+ CMPIInstance *inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *opathp = NULL;
+ const char *brname = NULL;
+ const char *cn = NULL;
+ char *pfx = NULL;
+ uint16_t stp, delay, dhcp, boot_mode;
+ 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;
+ }
+
+ ret = cu_get_u16_prop(inst, "Delay", &delay);
+ if (ret == CMPI_RC_OK) {
+ piface->pbr_prop->delay = delay;
+ }
+
+ ret = cu_get_u16_prop(inst, "DHCP", &dhcp);
+ if (ret == CMPI_RC_OK) {
+ piface->protocol_prop.ipv4_prop.DHCP = dhcp;
+ }
+
+ ret = cu_get_u16_prop(inst, "AutoStart", &boot_mode);
+ if (ret == CMPI_RC_OK) {
+ piface->run_prop.boot_mode = boot_mode;
+ }
+
+ out:
+ free(pfx);
+ return s;
+}
+
+static CMPIStatus instance_to_easd_ea(const CMPIBroker *broker,
+ struct EthIface *piface,
+ CMPIInstance *inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIStatus s_tmp;
+ int ret, temp;
+ uint16_t vlan_type = 0;
+ uint16_t dhcp, boot_mode;
+ char *charpvalues[8];
+ int charpcount = 0;
+ struct VLAN_Prop_8021q *pvlan_8021q = NULL;
+
+ ret = cu_get_u16_prop(inst, "VLANType", &vlan_type);
+ if (ret == CMPI_RC_OK) {
+ if (vlan_type == 1) {
+ piface->eth_type = ETH_TYPE_ETHER_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 = CU_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);
+ }
+
+ end_of_8021q:
+
+ ret = cu_get_u16_prop(inst, "DHCP", &dhcp);
+ if (ret == CMPI_RC_OK) {
+ piface->protocol_prop.ipv4_prop.DHCP = dhcp;
+ }
+
+ ret = cu_get_u16_prop(inst, "AutoStart", &boot_mode);
+ if (ret == CMPI_RC_OK) {
+ piface->run_prop.boot_mode = boot_mode;
+ }
+
+ return s;
+}
+
+static CMPIStatus instance_to_easd_ec(const CMPIBroker *broker,
+ struct EthIface *piface_src,
+ struct 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_ETHER_BRIDGE;
+ }
+ } else {
+ CU_DEBUG("HostResource have %d settings.", charpcount);
+ }
+ i = 0;
+ while (i < charpcount) {
+ CU_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)) {
+ CU_FREE(piface_src->name);
+ piface_src->name = get_iface_name_from_ethportsd(portname,
+ NULL);
+ }
+ }
+ piface_src->eth_type = ETH_TYPE_ETHER_ANY;
+
+ CU_FREE(prefix);
+ CU_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,
+ struct EthIface *piface_src,
+ struct 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. */
+ 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 = CU_STRDUP(tmp);
+ prefix = CU_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;
+ CU_FREE(prefix);
+ CU_FREE(name);
+ CU_FREE(port_name);
+ CU_FREE(switch_name);
+ 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;
+ struct 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);
+ } else if (action == RESOURCE_MOD) {
+ ret = mod_host_iface(&iface_src);
+ } else if (action == RESOURCE_DEL) {
+ ret = del_host_iface(&iface_src);
+ } 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);
+ } else if (action == RESOURCE_DEL) {
+ ret = disconnect_two_ifaces(&iface_src, &iface_dest);
+ } 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;
+ struct 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_ETHER_BRIDGE;
+ CU_DEBUG("Creating Switch System as follow:");
+ eth_iface_print(&iface_br);
+
+ ret = add_host_iface(&iface_br);
+ 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;
+ struct EthIface iface_br;
+ struct EthIfacesList ifaces_list;
+ int ret;
+ char *errstr;
+
+ eth_ifaceslist_init(&ifaces_list);
+ eth_iface_init(&iface_br);
+
+ 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;
+
+ }
+
+ CU_DEBUG("update switch settings as following settings:");
+ eth_iface_print(&iface_br);
+ ret = mod_host_iface(&iface_br);
+ 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_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;
+ struct 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_ETHER_BRIDGE;
+ CU_DEBUG("Deleting Switch System as follow:");
+ eth_iface_print(&iface_br);
+
+ ret = del_host_iface(&iface_br);
+ 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
diff --git a/src/Virt_VirtualSystemManagementService.c b/src/Virt_VirtualSystemManagementService.c
index 6f42c42..761263b 100644
--- a/src/Virt_VirtualSystemManagementService.c
+++ b/src/Virt_VirtualSystemManagementService.c
@@ -2836,7 +2836,7 @@ static CMPIStatus _update_resources_for(const CMPIContext *context,
return s;
}
-static CMPIStatus get_instanceid(CMPIInstance *rasd,
+CMPIStatus get_instanceid(CMPIInstance *rasd,
char **domain,
char **devid)
{
diff --git a/src/Virt_VirtualSystemManagementService.h b/src/Virt_VirtualSystemManagementService.h
index dbf17cb..d5ee4e4 100644
--- a/src/Virt_VirtualSystemManagementService.h
+++ b/src/Virt_VirtualSystemManagementService.h
@@ -34,3 +34,7 @@ CMPIStatus get_vsms(const CMPIObjectPath *reference,
const CMPIBroker *broker,
const CMPIContext *context,
bool is_get_inst);
+
+CMPIStatus get_instanceid(CMPIInstance *rasd,
+ char **domain,
+ char **devid);
--
1.7.1
12 years, 10 months
[PATCH V7 6/7] vlan extention - CIM Model - EASD
by Wenchao Xia
Add EASD for EthernetPort. According DSP1050, There are two kinds of EASD:
EA stands for Settings of EthernetPort, EC stands for Settings for Connection
between EthernetPort. EA_POOL and EC_POOL are not implemented, the model
standard is described with more details in next patch.
V7: add CIM properties AutoStart, DHCP.
V6: almost the same with V2.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
schema/EthernetPortAllocationSettingData.mof | 22 +
.../EthernetPortAllocationSettingData.registration | 3 +
src/Virt_EASD.c | 711 ++++++++++++++++++++
src/Virt_EASD.h | 59 ++
4 files changed, 795 insertions(+), 0 deletions(-)
create mode 100644 schema/EthernetPortAllocationSettingData.mof
create mode 100644 schema/EthernetPortAllocationSettingData.registration
create mode 100644 src/Virt_EASD.c
create mode 100644 src/Virt_EASD.h
diff --git a/schema/EthernetPortAllocationSettingData.mof b/schema/EthernetPortAllocationSettingData.mof
new file mode 100644
index 0000000..726bb1f
--- /dev/null
+++ b/schema/EthernetPortAllocationSettingData.mof
@@ -0,0 +1,22 @@
+// Copyright IBM Corp. 2012
+
+[Description ("Virtutal EthernetPort Setting Data"),
+ Provider("cmpi::Virt_EASD")
+]
+
+class Net_EthernetPortAllocationSettingData : CIM_EthernetPortAllocationSettingData
+{
+ uint16 PortVID;
+ uint16 DesiredEndPointMode;
+
+ [Description("VLAN type of the port, "
+ "Now only support IEEE 802.1.q."),
+ ValueMap { "0", "1", "2", "3" },
+ Values { "Not VLAN", "IEEE 802.1.q", "IEEE 802.1.qbg", "IEEE 802.1.qbh" }]
+ uint16 VLANType;
+
+ uint16 AutoStart;
+
+ uint16 DHCP;
+
+};
diff --git a/schema/EthernetPortAllocationSettingData.registration b/schema/EthernetPortAllocationSettingData.registration
new file mode 100644
index 0000000..8925739
--- /dev/null
+++ b/schema/EthernetPortAllocationSettingData.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_EthernetPortAllocationSettingData root/virt Virt_EASD Virt_EASD instance
diff --git a/src/Virt_EASD.c b/src/Virt_EASD.c
new file mode 100644
index 0000000..81243cd
--- /dev/null
+++ b/src/Virt_EASD.c
@@ -0,0 +1,711 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "misc_util.h"
+#include "cs_util.h"
+#include "device_parsing.h"
+#include "network_model_helper.h"
+
+#include "Virt_EASD.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_easd(const CMPIBroker *broker, const char* prefix,
+ struct EthIface *piface, int type, CMPIInstance *instance)
+{
+ char *eth_name, *easd_name;
+ int asret;
+ uint16_t res_type = CIM_NUM_SWITCHPORT;
+ uint16_t vlan_mode;
+
+ if (piface->name == NULL) {
+ return 0;
+ }
+
+ eth_name = get_ethportsd_name_from_iface(piface->name, type);
+ asret = asprintf(&easd_name, "%s/%s", prefix, eth_name);
+
+ CMSetProperty(instance, "InstanceID",
+ (CMPIValue *)easd_name, CMPI_chars);
+ CMSetProperty(instance, "ElementName",
+ (CMPIValue *)eth_name, CMPI_chars);
+ CU_FREE(easd_name);
+ CU_FREE(eth_name);
+
+ CMSetProperty(instance, "ResourceType",
+ (CMPIValue *)&res_type, CMPI_uint16);
+
+ if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) {
+ vlan_mode = CIM_NUM_VLAN_MODE_TRUNK;
+ CMSetProperty(instance, "DesiredEndPointMode",
+ (CMPIValue *)&vlan_mode, CMPI_uint16);
+ }
+
+
+ if (piface->mac != NULL) {
+ CMSetProperty(instance, "Address",
+ (CMPIValue *)piface->mac, CMPI_chars);
+ }
+
+ return 1;
+}
+
+static int set_secondary_for_easd(const CMPIBroker *broker,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ struct VLAN_Prop *pvlan;
+ struct VLAN_Prop_8021q *pvlan8021q;
+ uint16_t vid, dhcp;
+ CMPIArray *conn_array;
+ CMPIString *cm_str;
+ char *str = NULL;
+ CMPIStatus s;
+ uint16_t vlantype = 0;
+ uint16_t visibility = CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED;
+
+ if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) {
+ visibility = CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH;
+ }
+ CMSetProperty(instance, "ConsumerVisibility",
+ (CMPIValue *)&visibility, CMPI_uint16);
+
+ if (piface->protocol_prop.ipv4_prop.DHCP == 1) {
+ dhcp = 1;
+ } else {
+ /* dhcp would be -1 because in xml of
+ in netcf it would never be 0. */
+ dhcp = 0;
+ }
+ CMSetProperty(instance, "DHCP", (CMPIValue *)&dhcp, CMPI_uint16);
+
+ if (piface->run_prop.boot_mode >= 0) {
+ CMSetProperty(instance, "AutoStart",
+ (CMPIValue *)&piface->run_prop.boot_mode,
+ CMPI_uint16);
+ }
+
+ if ((piface->eth_type != ETH_TYPE_ETHER_VLAN) ||
+ (piface->pvlan_prop == NULL)) {
+ goto out;
+ }
+ pvlan = piface->pvlan_prop;
+
+ if (pvlan->vlan_type == VLAN_TYPE_802_1_Q) {
+ pvlan8021q = &(pvlan->props.prop_8021q);
+ vid = pvlan8021q->vlan_id;
+ CMSetProperty(instance, "PortVID",
+ (CMPIValue *)&vid, CMPI_uint16);
+
+ str = vlanid_to_connection_name(vid);
+ conn_array = CMNewArray(broker, 1, CMPI_string, &s);
+ if ((s.rc != CMPI_RC_OK) || (str == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Error creating Connection "
+ "list and its string");
+ CU_DEBUG("CMNewArray or string creation failed");
+ goto out;
+ }
+ cm_str = CMNewString(broker, str, &s);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("Error creating CMPIString");
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Error creating CMPIString for "
+ "BootDevices item");
+
+ goto out;
+ }
+ CMSetArrayElementAt(conn_array, 0, (CMPIValue *)&cm_str,
+ CMPI_string);
+ CMSetProperty(instance, "Connection",
+ (CMPIValue *)&conn_array, CMPI_stringA);
+
+ vlantype = 1;
+ }
+ CMSetProperty(instance, "VLANType",
+ (CMPIValue *)&vlantype, CMPI_uint16);
+
+out:
+ CU_FREE(str);
+ return 1;
+}
+
+static CMPIStatus add_conn_properties(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ const char *dest,
+ CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+ char *eth_name, *easd_name;
+ int asret;
+ CMPIArray *array;
+ CMPIString *tmp;
+
+ if (piface->name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "device name not set");
+ goto out;
+ }
+ if (dest == NULL) {
+ CU_DEBUG("warn: connection dest is NULL.");
+ }
+
+ eth_name = get_ethportsd_name_from_iface(piface->name, EASD_TYPE_EA);
+ asret = asprintf(&easd_name, "%s:%s", prefix, eth_name);
+ CMSetProperty(instance, "Parent",
+ (CMPIValue *)easd_name, CMPI_chars);
+ CU_FREE(easd_name);
+ CU_FREE(eth_name);
+
+ array = CMNewArray(broker, 1, CMPI_string, &s);
+ tmp = CMNewString(broker, dest, NULL);
+ CMSetArrayElementAt(array, 0, &(tmp), CMPI_string);
+ CMSetProperty(instance, "HostResource",
+ (CMPIValue *)&array, CMPI_stringA);
+
+
+ out:
+ return s;
+}
+
+static CMPIStatus set_properties(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ const char *dest,
+ int type,
+ CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+ char *errstr;
+
+ if (!set_primary_for_easd(broker, prefix, piface, type, 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 (type == EASD_TYPE_EA) {
+ if (!set_secondary_for_easd(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;
+ }
+ } else {
+ s = add_conn_properties(broker,
+ piface,
+ prefix,
+ dest,
+ instance);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ }
+
+ cu_statusf(broker, &s,
+ CMPI_RC_OK,
+ "");
+
+ out:
+ return s;
+}
+
+static CMPIStatus instance_from_easd_build(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ const char *dest,
+ int type,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIInstance *inst = NULL;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *keys[] = {"InstanceID", NULL};
+
+ inst = get_typed_instance(broker,
+ NETWORK_CLASS_PREFIX,
+ "EthernetPortAllocationSettingData",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to init SwitchSystem instance");
+ goto out;
+ }
+
+
+ s = CMSetPropertyFilter(inst, properties, keys);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("Unable to set property filter: %d", s.rc);
+ }
+
+ s = set_properties(broker,
+ piface,
+ prefix,
+ dest,
+ type,
+ inst);
+
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ *_inst = inst;
+
+ out:
+ return s;
+}
+
+/* vsname and req_type are filter conditions */
+static CMPIStatus instance_from_easd(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *vsname,
+ int req_type,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist)
+{
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *br1_name = NULL, *br2_name = NULL;
+
+ CU_DEBUG("enter instance_for_easd with vsname %s, type %d.",
+ vsname, req_type);
+ get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name);
+ if (br1_name == NULL) {
+ CU_DEBUG("failed to find any bridge for the port %s.",
+ piface->name);
+ }
+
+ /* building the EA instance */
+ if (!(req_type&EASD_TYPE_EA)) {
+ goto ea_build_end;
+ }
+ if ((vsname == NULL) || (br1_name == NULL) ||
+ (0 == strcmp(vsname, br1_name))) {
+ inst = NULL;
+ s = instance_from_easd_build(broker,
+ piface,
+ br1_name,
+ NULL,
+ EASD_TYPE_EA,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+
+ /* following is to make it comform to CIM profile which require two
+ ethports connectted to pNIC and vswitch, but we have only one piface
+ on linux indicating it is connected to pNIC and bridge at sametime */
+ if (br2_name == NULL) {
+ goto out;
+ }
+
+ if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) {
+ inst = NULL;
+ s = instance_from_easd_build(broker,
+ piface,
+ br2_name,
+ NULL,
+ EASD_TYPE_EA,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+ ea_build_end:
+
+ /* building the EC instance */
+ if (!(req_type&EASD_TYPE_EC)) {
+ goto ec_build_end;
+ }
+ if ((br1_name == NULL) || (br2_name == NULL)) {
+ goto ec_build_end;
+ }
+ /* connection exist, so a EC_easd should be added for each bridge */
+ if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) {
+ inst = NULL;
+ s = instance_from_easd_build(broker,
+ piface,
+ br1_name,
+ br2_name,
+ EASD_TYPE_EC,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+ if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) {
+ inst = NULL;
+ s = instance_from_easd_build(broker,
+ piface,
+ br2_name,
+ br1_name,
+ EASD_TYPE_EC,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+ ec_build_end:
+
+ out:
+ CU_FREE(br1_name);
+ CU_FREE(br2_name);
+ return s;
+}
+
+CMPIStatus get_easd_by_name(const CMPIBroker *broker,
+ const char *prefix,
+ const char *name,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *eth_name = NULL;
+ char *dest = NULL;
+ char *errstr;
+ int ret;
+ int type;
+ struct EthIfacesList ifaces_list;
+ struct inst_list list;
+
+ eth_ifaceslist_init(&ifaces_list);
+ inst_list_init(&list);
+
+ eth_name = get_iface_name_from_ethportsd(name, &type);
+ if (eth_name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to convert instance name");
+ CU_DEBUG("ethport name %s failed to convert.", name);
+ goto out;
+ }
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_ethport_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 ethport not found.";
+ CU_DEBUG("%d ethportd found.", ifaces_list.count);
+ eth_ifaceslist_print(&ifaces_list);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ inst = NULL;
+ s = instance_from_easd(broker,
+ ifaces_list.pifaces[0],
+ prefix,
+ type,
+ reference,
+ properties,
+ &list);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (list.cur == 0) {
+ CU_DEBUG("%d instance found, expect is 1.", list.cur);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "no such instance.");
+ goto out;
+ }
+
+ if (list.cur > 1) {
+ CU_DEBUG("%d instance found, expect is 1.", list.cur);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "instance found do not match expectation");
+ goto out;
+ }
+
+ *_inst = list.list[0];
+ list.list[0] = NULL;
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ inst_list_free(&list);
+ CU_FREE(eth_name);
+ CU_FREE(dest);
+ return s;
+}
+
+CMPIStatus get_easd_by_id(const CMPIBroker *broker,
+ const char *id,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ char *prefix = NULL;
+ char *suffix = NULL;
+ if (id == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "ID is NULL'", id);
+ }
+ if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) ||
+ (suffix == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "Invalid InstanceID `%s'", id);
+ goto out;
+ }
+ s = get_easd_by_name(broker, prefix, suffix, reference,
+ properties, _inst);
+
+ out:
+ CU_FREE(prefix);
+ CU_FREE(suffix);
+ return s;
+}
+
+CMPIStatus get_easd_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *name = NULL;
+ char *prefix = NULL;
+ const char *id;
+
+ if (cu_get_str_path(reference, "InstanceID", &id) != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "No such instance (InstanceID)");
+ goto out;
+ }
+ if ((!parse_fq_devid(id, &prefix, &name)) ||
+ (name == NULL) || (prefix == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to translate (InstanceID)");
+ goto out;
+ }
+
+ s = get_easd_by_name(broker, prefix, name, reference,
+ properties, &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:
+ free(name);
+ free(prefix);
+
+ return s;
+}
+
+
+CMPIStatus enum_easds(const CMPIBroker *broker,
+ const char *ref_vsname,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct EthIfacesList ifaces_list;
+ int ret, i;
+ char *errstr;
+
+ eth_ifaceslist_init(&ifaces_list);
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_ethport, NULL);
+ 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;
+ }
+ CU_DEBUG("enum easd, found following devices.")
+ eth_ifaceslist_print(&ifaces_list);
+
+ i = 0;
+ while (i < ifaces_list.count) {
+ s = instance_from_easd(broker,
+ ifaces_list.pifaces[i],
+ ref_vsname,
+ EASD_TYPE_EA|EASD_TYPE_EC,
+ reference,
+ properties,
+ plist);
+ i++;
+ /* this should never fail */
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("unexpected fail.");
+ break;
+ }
+ }
+
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+
+ return s;
+}
+
+static CMPIStatus return_enum_easds(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const CMPIResult *results,
+ const char **properties,
+ const bool names_only)
+{
+ struct inst_list list;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ inst_list_init(&list);
+ s = enum_easds(broker, NULL, reference, properties, &list);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (names_only) {
+ cu_return_instance_names(results, &list);
+ } else {
+ cu_return_instances(results, &list);
+ }
+
+ out:
+ inst_list_free(&list);
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ return return_enum_easds(_BROKER, reference, results,
+ NULL, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+
+ return return_enum_easds(_BROKER, reference, results,
+ properties, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+
+ s = get_easd_by_ref(_BROKER, ref, properties, &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ CMReturnInstance(results, inst);
+
+ out:
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_INST_CLEANUP();
+DEFAULT_EQ();
+
+STD_InstanceMIStub(,
+ Virt_EASD,
+ _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_EASD.h b/src/Virt_EASD.h
new file mode 100644
index 0000000..f9d13ec
--- /dev/null
+++ b/src/Virt_EASD.h
@@ -0,0 +1,59 @@
+/*
+ * 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 __VIRT_EASD_H
+#define __VIRT_EASD_H
+
+CMPIStatus enum_easds(const CMPIBroker *broker,
+ const char *ref_vsname,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist);
+
+CMPIStatus get_easd_by_name(const CMPIBroker *broker,
+ const char *prefix,
+ const char *name,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst);
+
+CMPIStatus get_easd_by_id(const CMPIBroker *broker,
+ const char *id,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst);
+
+CMPIStatus get_easd_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ 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.1
12 years, 10 months
[PATCH V7 5/7] vlan extention - CIM Model - EthernetPort
by Wenchao Xia
This patch add EthernetPort. EthernetPort is always a port on a switch,
So eth0.10 is modeled as VS_eth0/EP_eth0.10, and eth0 is modeled as
VS_eth0/EP_Eth0.
To make things simple enough, EtherPort belongs to VMs, are excluded from
the patch and still be modeled as NetworkPort. This means the patch only
concern about network on host side.
V7: no change.
V6: minior change according to comments.
V5: almost the same with V2.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
schema/EthernetPort.mof | 4 +
schema/EthernetPort.registration | 3 +
src/Virt_EthernetPort.c | 561 ++++++++++++++++++++++++++++++++++++++
src/Virt_EthernetPort.h | 58 ++++
4 files changed, 626 insertions(+), 0 deletions(-)
create mode 100644 schema/EthernetPort.mof
create mode 100644 schema/EthernetPort.registration
create mode 100644 src/Virt_EthernetPort.c
create mode 100644 src/Virt_EthernetPort.h
diff --git a/schema/EthernetPort.mof b/schema/EthernetPort.mof
new file mode 100644
index 0000000..9d5e23e
--- /dev/null
+++ b/schema/EthernetPort.mof
@@ -0,0 +1,4 @@
+// Copyright IBM Corp. 2012
+class Net_EthernetPort : CIM_EthernetPort
+{
+};
diff --git a/schema/EthernetPort.registration b/schema/EthernetPort.registration
new file mode 100644
index 0000000..e0e0f0c
--- /dev/null
+++ b/schema/EthernetPort.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_EthernetPort root/virt Virt_EthernetPort Virt_EthernetPort instance
diff --git a/src/Virt_EthernetPort.c b/src/Virt_EthernetPort.c
new file mode 100644
index 0000000..cdef910
--- /dev/null
+++ b/src/Virt_EthernetPort.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright IBM Corp. 2007
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "misc_util.h"
+#include "cs_util.h"
+#include "device_parsing.h"
+#include "network_model_helper.h"
+
+#include "Virt_EthernetPort.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_ep(const CMPIBroker *broker, const char* prefix,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ char *eth_name, *ep_name;
+ const char *syscls_name = "Virt_VirtualEthernetSwitchSystem";
+ int asret;
+
+ if (piface->name == NULL) {
+ return 0;
+ }
+
+ eth_name = get_ethport_name_from_iface(piface->name);
+ asret = asprintf(&ep_name, "%s/%s", prefix, eth_name);
+
+ CMSetProperty(instance, "DeviceID",
+ (CMPIValue *)ep_name, CMPI_chars);
+
+ CMSetProperty(instance, "InstanceID",
+ (CMPIValue *)ep_name, CMPI_chars);
+
+ CMSetProperty(instance, "ElementName",
+ (CMPIValue *)eth_name, CMPI_chars);
+ CU_FREE(ep_name);
+ CU_FREE(eth_name);
+
+ CMSetProperty(instance, "SystemCreationClassName",
+ (CMPIValue *)syscls_name, CMPI_chars);
+
+ CMSetProperty(instance, "SystemName",
+ (CMPIValue *)prefix, CMPI_chars);
+
+ return 1;
+}
+
+static int set_secondary_for_ep(const CMPIBroker *broker,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ int state;
+ uint16_t cim_type;
+ CMPIArray *array;
+ CMPIStatus s;
+ CMPIString *str;
+
+ if (piface->run_prop.status == ETH_STATE_INACTIVE) {
+ state = CIM_STATE_DISABLED;
+ } else if (piface->run_prop.status == ETH_STATE_ACTIVE) {
+ state = CIM_STATE_ENABLED;
+ } else {
+ state = CIM_STATE_UNKNOWN;
+ }
+ CMSetProperty(instance, "EnabledState",
+ (CMPIValue *)&state, CMPI_uint16);
+ CMSetProperty(instance, "RequestedState",
+ (CMPIValue *)&state, CMPI_uint16);
+
+ cim_type = CIM_NUM_NET_ETHERNET;
+ CMSetProperty(instance, "LinkTechnology",
+ (CMPIValue *)&cim_type, CMPI_uint16);
+
+ if (piface->mac != NULL) {
+ array = CMNewArray(broker, 1, CMPI_string, &s);
+ if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) {
+ CU_DEBUG("failed to create array.");
+ return 0;
+ }
+ str = CMNewString(broker, piface->mac, &s);
+ if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(str))) {
+ CU_DEBUG("failed to create array.");
+ return 0;
+ }
+
+ CMSetArrayElementAt(array, 0, &str, CMPI_string);
+
+ CMSetProperty(instance, "NetworkAddresses",
+ (CMPIValue *)&array, CMPI_stringA);
+ }
+
+ return 1;
+}
+
+static CMPIStatus set_properties(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+ char *errstr = NULL;
+
+ if (!set_primary_for_ep(broker, prefix, 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_ep(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_ep_build(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIInstance *inst = NULL;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *keys[] = {"InstanceID", NULL};
+
+ inst = get_typed_instance(broker,
+ NETWORK_CLASS_PREFIX,
+ "EthernetPort",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to init ep instance");
+ goto out;
+ }
+
+ s = CMSetPropertyFilter(inst, properties, keys);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("Unable to set property filter: %d", s.rc);
+ }
+
+ s = set_properties(broker,
+ piface,
+ prefix,
+ inst);
+
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ *_inst = inst;
+
+ out:
+ return s;
+}
+
+
+static CMPIStatus instance_from_ep(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *vsname,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist)
+{
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *br1_name = NULL, *br2_name = NULL;
+
+ get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name);
+ if (br1_name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to find any bridge for the port.");
+ CU_DEBUG("failed to find any bridge for the port %s.",
+ piface->name);
+ goto out;
+ }
+
+ /* building up the instance */
+ if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) {
+ inst = NULL;
+ s = instance_from_ep_build(broker,
+ piface,
+ br1_name,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+
+ /* following is to make it comform to CIM profile which require two
+ ethports connectted to pNIC and vswitch, but we have only one piface
+ on linux indicating it is connected to pNIC and bridge at sametime */
+ if (br2_name == NULL) {
+ goto out;
+ }
+
+ if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) {
+ inst = NULL;
+ s = instance_from_ep_build(broker,
+ piface,
+ br2_name,
+ reference,
+ properties,
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+ inst_list_add(plist, inst);
+ }
+
+
+ out:
+ CU_FREE(br1_name);
+ CU_FREE(br2_name);
+ return s;
+}
+
+CMPIStatus get_ep_by_name(const CMPIBroker *broker,
+ const char *prefix,
+ const char *name,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *eth_name = NULL;
+ char *dest = NULL;
+ char *errstr;
+ int ret;
+ struct EthIfacesList ifaces_list;
+ struct inst_list list;
+
+ eth_ifaceslist_init(&ifaces_list);
+ inst_list_init(&list);
+
+ eth_name = get_iface_name_from_ethport(name);
+ if (eth_name == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to convert instance name");
+ CU_DEBUG("ethport name %s failed to convert.", name);
+ goto out;
+ }
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_ethport_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 ethport not found.";
+ CU_DEBUG("%s\n", errstr);
+ eth_ifaceslist_print(&ifaces_list);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ errstr);
+ goto out;
+ }
+
+ inst = NULL;
+ s = instance_from_ep(broker,
+ ifaces_list.pifaces[0],
+ prefix,
+ reference,
+ properties,
+ &list);
+
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (list.cur == 0) {
+ CU_DEBUG("%d instance found, expect is 1.", list.cur);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "no such instance.");
+ goto out;
+ }
+
+ if (list.cur > 1) {
+ CU_DEBUG("%d instance found, expect is 1.", list.cur);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "instance found do not match expectation");
+ goto out;
+ }
+
+ *_inst = list.list[0];
+ list.list[0] = NULL;
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ inst_list_free(&list);
+ CU_FREE(eth_name);
+ CU_FREE(dest);
+ return s;
+}
+
+CMPIStatus get_ep_by_id(const CMPIBroker *broker,
+ const char *id,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ char *prefix = NULL;
+ char *suffix = NULL;
+ if (id == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "ID is NULL'", id);
+ }
+ if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) ||
+ (suffix == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "Invalid InstanceID `%s'", id);
+ goto out;
+ }
+ s = get_ep_by_name(broker, prefix, suffix, reference,
+ properties, _inst);
+
+ out:
+ CU_FREE(prefix);
+ CU_FREE(suffix);
+ return s;
+}
+
+CMPIStatus get_ep_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *name = NULL;
+ char *prefix = NULL;
+ const char *id;
+
+ if (cu_get_str_path(reference, "DeviceID", &id) != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "No such instance (InstanceID)");
+ goto out;
+ }
+ if ((!parse_fq_devid(id, &prefix, &name)) ||
+ (name == NULL) || (prefix == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to translate (InstanceID)");
+ goto out;
+ }
+
+ s = get_ep_by_name(broker, prefix, name, reference,
+ properties, &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:
+ free(name);
+ free(prefix);
+
+ return s;
+}
+
+
+CMPIStatus enum_eps(const CMPIBroker *broker,
+ const char *ref_vsname,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct EthIfacesList ifaces_list;
+ int ret, i;
+ char *errstr;
+
+ eth_ifaceslist_init(&ifaces_list);
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_ethport, NULL);
+ 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;
+ }
+ CU_DEBUG("enum ep, found following devices.")
+ eth_ifaceslist_print(&ifaces_list);
+
+ i = 0;
+ while (i < ifaces_list.count) {
+ s = instance_from_ep(broker,
+ ifaces_list.pifaces[i],
+ ref_vsname,
+ reference,
+ properties,
+ plist);
+ i++;
+ /* this should never fail */
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("unexpected fail.");
+ break;
+ }
+ }
+
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+
+ return s;
+}
+
+static CMPIStatus return_enum_eps(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const CMPIResult *results,
+ const char **properties,
+ const bool names_only)
+{
+ struct inst_list list;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ inst_list_init(&list);
+ s = enum_eps(broker, NULL, reference, properties, &list);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (names_only) {
+ cu_return_instance_names(results, &list);
+ } else {
+ cu_return_instances(results, &list);
+ }
+
+ out:
+ inst_list_free(&list);
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ return return_enum_eps(_BROKER, reference, results, NULL, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+
+ return return_enum_eps(_BROKER, reference, results, properties, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+
+ s = get_ep_by_ref(_BROKER, ref, properties, &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ CMReturnInstance(results, inst);
+
+ out:
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_INST_CLEANUP();
+DEFAULT_EQ();
+
+STD_InstanceMIStub(,
+ Virt_EthernetPort,
+ _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_EthernetPort.h b/src/Virt_EthernetPort.h
new file mode 100644
index 0000000..f474af2
--- /dev/null
+++ b/src/Virt_EthernetPort.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Wencao 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 __VIRT_ETHERNETPORT_H
+#define __VIRT_ETHERNETPORT_H
+
+CMPIStatus enum_eps(const CMPIBroker *broker,
+ const char *ref_vsname,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ struct inst_list *plist);
+
+CMPIStatus get_ep_by_name(const CMPIBroker *broker,
+ const char *prefix,
+ const char *name,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst);
+
+CMPIStatus get_ep_by_id(const CMPIBroker *broker,
+ const char *id,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ CMPIInstance **_inst);
+
+CMPIStatus get_ep_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const char **properties,
+ 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.1
12 years, 10 months
[PATCH V7 4/7] vlan extention - CIM Model - VESSSD
by Wenchao Xia
This patch add VESSSD, VirtualSwitch are bridge and pNIC on host.
V7: added Delay, AutoStart, DHCP properties which exist in libvirtAPI.
V6: same with V2.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
schema/VirtualEthernetSwitchSystemSettingData.mof | 33 ++
...ualEthernetSwitchSystemSettingData.registration | 3 +
src/Virt_VESSSD.c | 392 ++++++++++++++++++++
src/Virt_VESSSD.h | 39 ++
4 files changed, 467 insertions(+), 0 deletions(-)
create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.mof
create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.registration
create mode 100644 src/Virt_VESSSD.c
create mode 100644 src/Virt_VESSSD.h
diff --git a/schema/VirtualEthernetSwitchSystemSettingData.mof b/schema/VirtualEthernetSwitchSystemSettingData.mof
new file mode 100644
index 0000000..9dea980
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemSettingData.mof
@@ -0,0 +1,33 @@
+// Copyright IBM Corp. 2012
+
+
+/* fix me: the libvirt-cim lacks parent class
+ "VirtualEthernetSwitchSettingData" defined in DSP1050 */
+[Description (
+ "A class derived from Virt_VirtualEthernetSystemSettingData to represent "
+ "the config of ."),
+ Provider("cmpi::Virt_VESSSD")
+]
+class Net_VirtualEthernetSwitchSystemSettingData : CIM_VirtualSystemSettingData
+{
+
+ [Description ("Virtual Switch System type number")]
+ string VirtualSystemType;
+
+ string AssociatedResourcePool;
+
+ uint16 VLAN_Connection[];
+
+ uint16 MaxNumAddress;
+
+ uint16 EVBMode;
+
+ uint16 STP;
+
+ uint16 Delay;
+
+ uint16 AutoStart;
+
+ uint16 DHCP;
+
+};
diff --git a/schema/VirtualEthernetSwitchSystemSettingData.registration b/schema/VirtualEthernetSwitchSystemSettingData.registration
new file mode 100644
index 0000000..1ba7e0c
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemSettingData.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_VirtualEthernetSwitchSystemSettingData root/virt Virt_VESSSD Virt_VESSSD instance
diff --git a/src/Virt_VESSSD.c b/src/Virt_VESSSD.c
new file mode 100644
index 0000000..724d3b8
--- /dev/null
+++ b/src/Virt_VESSSD.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "cs_util.h"
+#include "misc_util.h"
+#include "device_parsing.h"
+
+#include "Virt_VESSSD.h"
+#include "network_model_helper.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_vesssd(const char *prefix, const CMPIBroker *broker,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ char *name, *vesssd_name;
+ int asret;
+
+ if (piface->name == NULL) {
+ return 0;
+ }
+
+ CMSetProperty(instance, "VirtualSystemType",
+ (CMPIValue *)"DMTF:VirtualEthernetSwitch", CMPI_chars);
+
+ name = get_switch_name_from_iface(piface->name);
+ asret = asprintf(&vesssd_name, "%s:%s", prefix, name);
+
+ CMSetProperty(instance, "InstanceID",
+ (CMPIValue *)vesssd_name, CMPI_chars);
+ CMSetProperty(instance, "ElementName",
+ (CMPIValue *)name, CMPI_chars);
+ CMSetProperty(instance, "VirtualSystemIdentifier",
+ (CMPIValue *)name, CMPI_chars);
+ CMSetProperty(instance, "VirtualSystemType",
+ (CMPIValue *)prefix, CMPI_chars);
+
+
+
+ free(vesssd_name);
+ CU_FREE(name);
+
+ return 1;
+}
+
+static int set_secondary_for_vesssd(const CMPIBroker *broker,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ uint16_t dhcp;
+ if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) {
+ if (piface->pbr_prop->STP >= 0) {
+ CMSetProperty(instance, "STP",
+ (CMPIValue *)&piface->pbr_prop->STP, CMPI_uint16);
+ }
+ if (piface->pbr_prop->delay >= 0) {
+ CMSetProperty(instance, "Delay",
+ (CMPIValue *)&piface->pbr_prop->delay, CMPI_uint16);
+ }
+ }
+
+ if (piface->protocol_prop.ipv4_prop.DHCP == 1) {
+ dhcp = 1;
+ } else {
+ /* dhcp would be -1 because in xml of
+ in netcf it would never be 0. */
+ dhcp = 0;
+ }
+ CMSetProperty(instance, "DHCP", (CMPIValue *)&dhcp, CMPI_uint16);
+
+ if (piface->run_prop.boot_mode >= 0) {
+ CMSetProperty(instance, "AutoStart",
+ (CMPIValue *)&piface->run_prop.boot_mode,
+ CMPI_uint16);
+ }
+
+ return 1;
+}
+
+/* Populate an instance with information from a switch */
+static CMPIStatus set_properties(const CMPIBroker *broker,
+ struct EthIface *piface,
+ const char *prefix,
+ CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+ char *errstr;
+
+ if (!set_primary_for_vesssd(prefix, 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_vesssd(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_vesssd(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ struct EthIface *piface,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+
+ inst = get_typed_instance(broker,
+ NETWORK_CLASS_PREFIX,
+ "VirtualEthernetSwitchSystemSettingData",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to init SwitchSystem instance");
+ goto out;
+ }
+
+ s = set_properties(broker,
+ piface,
+ VESSD_SYSTEM_PREFIX,
+ inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ *_inst = inst;
+
+ out:
+ return s;
+}
+
+CMPIStatus enum_vesssd(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ struct inst_list *plist)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct EthIfacesList ifaces_list;
+ int ret, i;
+ char *errstr;
+
+ eth_ifaceslist_init(&ifaces_list);
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_switch, NULL);
+
+ 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_vesssd(broker,
+ reference,
+ ifaces_list.pifaces[i],
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ inst_list_add(plist, inst);
+ i++;
+ }
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+
+ return s;
+}
+
+static CMPIStatus return_enum_vesssd(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ const CMPIResult *results,
+ bool names_only)
+{
+ struct inst_list list;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ inst_list_init(&list);
+
+ s = enum_vesssd(broker, reference, &list);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ if (names_only) {
+ cu_return_instance_names(results, &list);
+ } else {
+ cu_return_instances(results, &list);
+ }
+ out:
+ inst_list_free(&list);
+ return s;
+}
+
+CMPIStatus get_vesssd_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;
+ struct 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_vesssd(broker,
+ reference,
+ ifaces_list.pifaces[0],
+ &inst);
+ if (s.rc != CMPI_RC_OK) {
+ goto out;
+ }
+
+ *_inst = inst;
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ CU_FREE(eth_name);
+ return s;
+}
+
+CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ CMPIInstance **_inst)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *name = NULL;
+
+ if ((!parse_instanceid(reference, NULL, &name)) || (name == NULL)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "No such instance (InstanceID)");
+ goto out;
+ }
+
+ s = get_vesssd_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:
+ free(name);
+
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ return return_enum_vesssd(_BROKER, reference, results, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ return return_enum_vesssd(_BROKER, reference, results, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s;
+ CMPIInstance *inst = NULL;
+
+ s = get_vesssd_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();
+
+STD_InstanceMIStub(,
+ Virt_VESSSD,
+ _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_VESSSD.h b/src/Virt_VESSSD.h
new file mode 100644
index 0000000..5105057
--- /dev/null
+++ b/src/Virt_VESSSD.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __VIRT_VESSSD_H
+#define __VIRT_VESSSD_H
+
+
+CMPIStatus enum_vesssd(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ struct inst_list *plist);
+
+CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ CMPIInstance **_inst);
+
+CMPIStatus get_vesssd_by_name(const CMPIBroker *broker,
+ const char *name,
+ const CMPIObjectPath *reference,
+ CMPIInstance **_inst);
+
+
+#endif
--
1.7.1
12 years, 10 months
[PATCH V7 3/7] vlan extention - CIM Model - VESS
by Wenchao Xia
This patch add VESS according DSP1097. VESS is modeled similar to
ComputerSystem.
V7: added state change code which bring up or down ethiface.
V6: little change about style.
V5: Almost no change from V2, just removed one parameter when calling function
library.
Signed-off-by: Wenchao Xia <xiawenc(a)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..6c43719
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystem.mof
@@ -0,0 +1,10 @@
+// Copyright IBM Corp. 2012
+[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..ac94e7c
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystem.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# 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..d6de84c
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystem.c
@@ -0,0 +1,477 @@
+/*
+ * 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 <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,
+ const struct 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);
+ CU_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,
+ struct EthIface *piface, CMPIInstance *instance)
+{
+ int state;
+ if (piface->run_prop.status == ETH_STATE_INACTIVE) {
+ state = CIM_STATE_DISABLED;
+ } else if (piface->run_prop.status == ETH_STATE_ACTIVE) {
+ 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,
+ struct 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,
+ struct 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};
+ struct EthIfacesList ifaces_list;
+ int ret, i;
+ char *errstr;
+
+ inst_list_init(&list);
+ eth_ifaceslist_init(&ifaces_list);
+
+ ret = get_host_ifaces(&ifaces_list,
+ eth_iface_filter_cim_switch, NULL);
+
+ 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;
+ }
+ eth_ifaceslist_print(&ifaces_list);
+
+ 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;
+ struct 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);
+ CU_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};
+ struct 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_ACTIVE;
+ } else if (state == CIM_STATE_DISABLED) {
+ iface_state = ETH_STATE_INACTIVE;
+ } else {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_SUPPORTED,
+ "State not supported");
+ goto out;
+ }
+
+ 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(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 __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.1
12 years, 10 months
[PATCH V7 2/7] vlan extention - CIM Model - helper and Makefile
by Wenchao Xia
This patch change the Makefile, and add helper functions for CIM model such
as string parsing and generation.
V7: add VESSMS in Makefile.
V6: no change from V2.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
Makefile.am | 16 ++-
libxkutil/network_model_helper.c | 473 ++++++++++++++++++++++++++++++++++++++
libxkutil/network_model_helper.h | 101 ++++++++
src/Makefile.am | 29 ++-
4 files changed, 614 insertions(+), 5 deletions(-)
create mode 100644 libxkutil/network_model_helper.c
create mode 100644 libxkutil/network_model_helper.h
diff --git a/Makefile.am b/Makefile.am
index 94dc5f3..0ecca54 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -63,7 +63,13 @@ MOFS = \
$(top_srcdir)/schema/EntriesInFilterList.mof \
$(top_srcdir)/schema/NestedFilterList.mof \
$(top_srcdir)/schema/AppliedFilterList.mof \
- $(top_srcdir)/schema/HostedFilterList.mof
+ $(top_srcdir)/schema/HostedFilterList.mof \
+ $(top_srcdir)/schema/HostedFilterList.mof \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystem.mof \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.mof \
+ $(top_srcdir)/schema/EthernetPort.mof \
+ $(top_srcdir)/schema/EthernetPortAllocationSettingData.mof \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystemManagementService.mof
INTEROP_MOFS = \
$(top_srcdir)/schema/ComputerSystem.mof \
@@ -150,7 +156,13 @@ REGS = \
$(top_srcdir)/schema/EntriesInFilterList.registration \
$(top_srcdir)/schema/NestedFilterList.registration \
$(top_srcdir)/schema/AppliedFilterList.registration \
- $(top_srcdir)/schema/HostedFilterList.registration
+ $(top_srcdir)/schema/HostedFilterList.registration \
+ $(top_srcdir)/schema/HostedFilterList.registration \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystem.registration \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.registration \
+ $(top_srcdir)/schema/EthernetPort.registration \
+ $(top_srcdir)/schema/EthernetPortAllocationSettingData.registration \
+ $(top_srcdir)/schema/VirtualEthernetSwitchSystemManagementService.registration
INTEROP_REGS = \
$(top_srcdir)/schema/RegisteredProfile.registration \
diff --git a/libxkutil/network_model_helper.c b/libxkutil/network_model_helper.c
new file mode 100644
index 0000000..9bb3e83
--- /dev/null
+++ b/libxkutil/network_model_helper.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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 <string.h>
+
+#include "network_model_helper.h"
+#include "device_parsing.h"
+
+#include "cmpidt.h"
+#include "cmpift.h"
+#include "cmpimacs.h"
+
+/* this function would return a new allocated string or NULL */
+char *compare_and_switch_prefix(const char *orig_str,
+ const char *orig_prefix,
+ const char *dest_prefix)
+{
+ int orig_prefix_len, dest_prefix_len, asret;
+ char *retstr = NULL;
+ const char *suffix;
+ if (orig_str == NULL) {
+ goto out;
+ }
+ orig_prefix_len = strlen(orig_prefix);
+ dest_prefix_len = strlen(dest_prefix);
+ if (0 != strncmp(orig_str, orig_prefix, orig_prefix_len)) {
+ goto out;
+ }
+ suffix = orig_str + orig_prefix_len;
+ asret = asprintf(&retstr, "%s%s", dest_prefix, suffix);
+ if (asret == -1) {
+ free(retstr);
+ retstr = NULL;
+ }
+ out:
+ return retstr;
+}
+
+char *switch_device_id_prefix(const char *whole_id,
+ const char *orig_prefix,
+ const char *dest_prefix)
+{
+ char *system = NULL;
+ char *device = NULL;
+ char *new_id = NULL;
+ char *retstr = NULL;
+ int asret;
+
+
+ if (0 == parse_fq_devid(whole_id, &system, &device)) {
+ goto out;
+ }
+
+ new_id = compare_and_switch_prefix(device,
+ orig_prefix, dest_prefix);
+
+ if (new_id == NULL) {
+ goto out;
+ }
+ asret = asprintf(&retstr, "%s/%s", system, new_id);
+ if (asret == -1) {
+ free(retstr);
+ retstr = NULL;
+ }
+
+ out:
+ free(system);
+ free(device);
+ free(new_id);
+ return retstr;
+}
+
+char *ep_id_to_easdea_id(const char *epid)
+{
+ return switch_device_id_prefix(epid,
+ ETHPORT_PREFIX, ETHPORT_ALLOCATION_SD_PREFIX);
+}
+
+char *easdea_id_to_ep_id(const char *epid)
+{
+ return switch_device_id_prefix(epid,
+ ETHPORT_ALLOCATION_SD_PREFIX, ETHPORT_PREFIX);
+}
+
+char *ep_id_to_easdec_id(const char *epid)
+{
+ return switch_device_id_prefix(epid,
+ ETHPORT_PREFIX, ETHPORT_CONNECTION_SD_PREFIX);
+}
+
+char *easdec_id_to_ep_id(const char *epid)
+{
+ return switch_device_id_prefix(epid,
+ ETHPORT_CONNECTION_SD_PREFIX, ETHPORT_PREFIX);
+}
+
+char *vlanid_to_connection_name(const int id)
+{
+ int asret;
+ char *str = NULL;
+ char *prefix = CONNECTION_VLAN_PREFIX;
+ asret = asprintf(&str, "%s%d", prefix, id);
+ if (asret == -1) {
+ return NULL;
+ }
+ return str;
+}
+
+int vlanid_from_connection_name(const char *name)
+{
+ int id = -1;
+ int temp = -1;
+ char *prefix = CONNECTION_VLAN_PREFIX;
+ char *dig_start, *dig_end;
+ if (name == NULL) {
+ goto out;
+ }
+ dig_start = strstr(name, prefix);
+ if (dig_start == NULL) {
+ goto out;
+ }
+ dig_start += strlen(prefix);
+ temp = strtol(dig_start, &dig_end, 10);
+ if ((dig_start == dig_end) || (temp < 0) || (temp > 4095)) {
+ goto out;
+ }
+ id = temp;
+ out:
+ return id;
+}
+
+int eth_iface_filter_cim_ethport(const struct EthIface *piface,
+ void *nouse)
+{
+ if ((piface->eth_type != ETH_TYPE_NOT_GOT) &&
+ (piface->eth_type != ETH_TYPE_ETHER_BRIDGE)) {
+ return 1;
+ }
+ return 0;
+}
+
+int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface,
+ void *name)
+{
+ int cim_ethport_flag;
+ cim_ethport_flag = eth_iface_filter_cim_ethport(piface, NULL);
+ if (cim_ethport_flag == 1) {
+ if (0 == strcmp(piface->name, name)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* returned value need to be freed */
+char *get_ethportsd_name_from_iface(const char *iface_name, const int type)
+{
+ char *prefix;
+ char *name;
+ int size;
+
+ if (iface_name == NULL) {
+ return NULL;
+ }
+
+ if (type == EASD_TYPE_EA) {
+ prefix = ETHPORT_ALLOCATION_SD_PREFIX;
+ } else {
+ prefix = ETHPORT_CONNECTION_SD_PREFIX;
+ }
+
+ size = strlen(iface_name)+strlen(prefix)+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s%s", prefix, iface_name);
+ return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype)
+{
+ char *prefix;
+ char *name = NULL;
+ int size;
+ int prefix_len;
+ int t = -1;
+
+ if (ethport_name == NULL) {
+ goto out;
+ }
+
+ prefix = ETHPORT_ALLOCATION_SD_PREFIX;
+ prefix_len = strlen(prefix);
+ if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+ prefix = ETHPORT_CONNECTION_SD_PREFIX;
+ prefix_len = strlen(prefix);
+ if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+ goto out;
+ } else {
+ t = EASD_TYPE_EC;
+ }
+ } else {
+ t = EASD_TYPE_EA;
+ }
+ size = strlen(ethport_name)-strlen(prefix)+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s", ethport_name+prefix_len);
+
+ out:
+ if (ptype != NULL) {
+ *ptype = t;
+ }
+ return name;
+}
+
+int eth_iface_filter_cim_switch(const struct EthIface *piface,
+ void *nouse)
+{
+ if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) {
+ return 1;
+ }
+ return eth_iface_filter_peths(piface, nouse);
+}
+
+int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface,
+ void *name)
+{
+ int cim_switch_flag;
+ cim_switch_flag = eth_iface_filter_cim_switch(piface, NULL);
+ if (cim_switch_flag == 1) {
+ if (0 == strcmp(piface->name, name)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* returned value need to be freed */
+char *get_switch_name_from_iface(const char *iface_name)
+{
+ char *prefix = SWITCH_PREFIX;
+ char *name;
+ int size;
+
+ size = strlen(iface_name)+strlen(prefix)+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s%s", prefix, iface_name);
+ return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_switch(const char *switch_name)
+{
+ char *prefix = SWITCH_PREFIX;
+ char *name;
+ int size;
+ int prefix_len;
+
+ prefix_len = strlen(prefix);
+ if (0 != strncmp(switch_name, prefix, prefix_len)) {
+ return NULL;
+ }
+ size = strlen(switch_name)-strlen(prefix)+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s", switch_name+prefix_len);
+ return name;
+}
+
+/* returned value need to be freed */
+char *get_ethport_name_from_iface(const char *iface_name)
+{
+ char *prefix;
+ char *name;
+ int size;
+
+ if (iface_name == NULL) {
+ return NULL;
+ }
+
+ prefix = ETHPORT_PREFIX;
+ size = strlen(iface_name)+strlen(prefix)+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s%s", prefix, iface_name);
+ return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_ethport(const char *ethport_name)
+{
+ char *prefix = ETHPORT_PREFIX;
+ char *name = NULL;
+ int size;
+ int prefix_len;
+
+ if (ethport_name == NULL) {
+ goto out;
+ }
+
+ prefix = ETHPORT_PREFIX;
+ prefix_len = strlen(prefix);
+ if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+ goto out;
+ }
+ size = strlen(ethport_name)-prefix_len+1;
+ CU_MALLOC(name, size);
+ snprintf(name, size, "%s", ethport_name+prefix_len);
+
+ out:
+ return name;
+}
+
+/* determine the CIM switch from the piface */
+int get_possible_bridge_name_for_cim_model(struct EthIface *piface,
+ char **pbr1name, char **pbr2name)
+{
+ char *br1_name;
+ char *br2_name;
+ if (piface->attach_bridge != NULL) {
+ br1_name = get_switch_name_from_iface(piface->attach_bridge);
+ } else if (piface->dep_ifname != NULL) {
+ br1_name = get_switch_name_from_iface(piface->dep_ifname);
+ } else if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) {
+ br1_name = get_switch_name_from_iface(piface->name);
+ } else {
+ br1_name = NULL;
+ }
+
+ if ((piface->attach_bridge != NULL) && (piface->dep_ifname != NULL)) {
+ br2_name = get_switch_name_from_iface(piface->dep_ifname);
+ } else if ((piface->attach_bridge != NULL) &&
+ (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL)) {
+ br2_name = get_switch_name_from_iface(piface->name);
+ } else {
+ br2_name = NULL;
+ }
+
+ /* incase some pifaces such as "lo" have no parent nor attaching
+ bridge */
+ if (br1_name == NULL) {
+ br1_name = get_switch_name_from_iface(piface->name);
+ }
+ *pbr1name = br1_name;
+ *pbr2name = br2_name;
+ return 1;
+}
+
+CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker,
+ CMPIInstance *inst,
+ char *array_name,
+ int *ret_result,
+ int *ret_size,
+ int max_size)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIArray *array;
+ CMPICount array_size;
+ CMPIData elem;
+ int i, ret, count = 0;
+
+ ret = cu_get_array_prop(inst, array_name, &array);
+ if (ret != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "array property not found.");
+ CU_DEBUG("Failed to get array property %s.", array_name);
+ goto out;
+ }
+ array_size = CMGetArrayCount(array, &s);
+ if ((s.rc != CMPI_RC_OK) || (array_size > max_size) ||
+ (array_size <= 0)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to get size of array property,"
+ " or its size is 0 or too big.");
+ CU_DEBUG("failed in getting size of %s property.", array_name);
+ goto out;
+ }
+ for (i = 0; i < array_size; i++) {
+ elem = CMGetArrayElementAt(array, i, NULL);
+ if (CMIsNullValue(elem)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "NULL content of array property.");
+ CU_DEBUG("NULL content of %s property.", array_name);
+ goto out;
+ }
+ if (!(elem.type & CMPI_INTEGER)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "wrong type of array property.");
+ CU_DEBUG("wrong type of %s property.", array_name);
+ goto out;
+ }
+ ret_result[count] = elem.value.uint16;
+ count++;
+ }
+ out:
+ *ret_size = count;
+ return s;
+}
+
+CMPIStatus get_array_string_from_instance(const CMPIBroker *broker,
+ CMPIInstance *inst,
+ char *array_name,
+ char **ret_result,
+ int *ret_size,
+ int max_size)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIArray *array;
+ CMPICount array_size;
+ CMPIData elem;
+ const char *str;
+ int i, ret, count = 0;
+
+ ret = cu_get_array_prop(inst, array_name, &array);
+ if (ret != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "array property not found.");
+ CU_DEBUG("Failed to get array property %s.", array_name);
+ goto out;
+ }
+ array_size = CMGetArrayCount(array, &s);
+ if ((s.rc != CMPI_RC_OK) || (array_size > max_size) ||
+ (array_size <= 0)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "failed to get size of array property,"
+ " or its size is 0 or too big.");
+ CU_DEBUG("failed in getting size of %s property.", array_name);
+ goto out;
+ }
+ for (i = 0; i < array_size; i++) {
+ elem = CMGetArrayElementAt(array, i, NULL);
+ if (CMIsNullValue(elem)) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "NULL content of array property.");
+ CU_DEBUG("NULL content of %s property.", array_name);
+ goto out;
+ }
+ str = NULL;
+ str = CMGetCharPtr(elem.value.string);
+ if (str == NULL) {
+ CU_DEBUG("Could not extract char pointer from "
+ "CMPIArray %s.", array_name);
+ goto out;
+ }
+ ret_result[count] = CU_STRDUP(str);
+ count++;
+ }
+ out:
+ *ret_size = count;
+ return s;
+}
diff --git a/libxkutil/network_model_helper.h b/libxkutil/network_model_helper.h
new file mode 100644
index 0000000..6b3f151
--- /dev/null
+++ b/libxkutil/network_model_helper.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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 NETWORK_MODEL_HELPER_H
+#define NETWORK_MODEL_HELPER_H
+
+#include "network_parsing.h"
+
+#define EASD_TYPE_EA 1
+#define EASD_TYPE_EC 2
+
+#define NETWORK_CLASS_PREFIX "Net"
+
+#define SWITCH_PREFIX "VS_"
+#define VESSD_SYSTEM_PREFIX "Virt"
+#define ETHPORT_PREFIX "EP_"
+#define ETHPORT_ALLOCATION_SD_PREFIX "EA_"
+#define ETHPORT_CONNECTION_SD_PREFIX "EC_"
+
+#define CONNECTION_VLAN_PREFIX "VLAN"
+
+#define CIM_NUM_NET_ETHERNET 2
+#define CIM_NUM_SWITCH_DEDICATED 38
+#define CIM_NUM_SWITCHPORT 30
+#define CIM_NUM_VLAN_MODE_TRUNK 5
+#define CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH 2
+#define CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED 3
+
+char *get_switch_name_from_iface(const char *iface_name);
+char *get_iface_name_from_switch(const char *switch_name);
+
+char *get_ethport_name_from_iface(const char *iface_name);
+char *get_iface_name_from_ethport(const char *ethport_name);
+
+char *get_ethportsd_name_from_iface(const char *iface_name, const int type);
+char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype);
+
+char *ep_id_to_easdea_id(const char *epid);
+char *easdea_id_to_ep_id(const char *epid);
+char *ep_id_to_easdec_id(const char *epid);
+char *easdec_id_to_ep_id(const char *epid);
+
+char *vlanid_to_connection_name(const int id);
+int vlanid_from_connection_name(const char *name);
+
+int eth_iface_filter_cim_switch(const struct EthIface *piface,
+ void *nouse);
+int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface,
+ void *name);
+int eth_iface_filter_cim_ethport(const struct EthIface *piface,
+ void *nouse);
+int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface,
+ void *name);
+
+int get_possible_bridge_name_for_cim_model(struct EthIface *piface,
+ char **pbr1name, char **pbr2name);
+
+
+char *compare_and_switch_prefix(const char *orig_str,
+ const char *orig_prefix,
+ const char *dest_prefix);
+
+char *switch_device_id_prefix(const char *whole_id,
+ const char *orig_prefix,
+ const char *dest_prefix);
+
+/* other help function related to CIM */
+CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker,
+ CMPIInstance *inst,
+ char *array_name,
+ int *ret_result,
+ int *ret_size,
+ int max_size);
+
+CMPIStatus get_array_string_from_instance(const CMPIBroker *broker,
+ CMPIInstance *inst,
+ char *array_name,
+ char **ret_result,
+ int *ret_size,
+ int max_size);
+
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f90926..18afbb1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,11 +24,17 @@ noinst_HEADERS = profiles.h svpc_types.h \
Virt_ConsoleRedirectionServiceCapabilities.h \
Virt_KVMRedirectionSAP.h \
Virt_FilterList.h \
- Virt_FilterEntry.h
+ Virt_FilterEntry.h \
+ Virt_VirtualEthernetSwitchSystem.h \
+ Virt_VESSSD.h \
+ Virt_EthernetPort.h \
+ Virt_EASD.h \
+ Virt_VirtualEthernetSwitchSystemManagementService.h
XKUADD = $(top_builddir)/libxkutil/libxkutil.la
+NTWADD = $(top_builddir)/libnetwork/libnetwork.la
-CFLAGS += -I$(top_srcdir)/libxkutil $(CFLAGS_STRICT)
+CFLAGS += -I$(top_srcdir)/libxkutil -I$(top_srcdir)/libnetwork $(CFLAGS_STRICT)
AM_LDFLAGS = $(XKUADD) \
-version-info @VERSION_INFO@
@@ -85,7 +91,12 @@ provider_LTLIBRARIES = libVirt_ComputerSystem.la \
libVirt_EntriesInFilterList.la \
libVirt_NestedFilterList.la \
libVirt_HostedFilterList.la \
- libVirt_AppliedFilterList.la
+ libVirt_AppliedFilterList.la \
+ libVirt_VirtualEthernetSwitchSystem.la \
+ libVirt_VESSSD.la \
+ libVirt_EthernetPort.la \
+ libVirt_EASD.la \
+ libVirt_VirtualEthernetSwitchSystemManagementService.la
libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c
libVirt_ComputerSystem_la_DEPENDENCIES = libVirt_VirtualSystemSnapshotService.la
@@ -274,3 +285,15 @@ libVirt_HostedFilterList_la_LIBADD = -lVirt_HostSystem -lVirt_FilterList
libVirt_AppliedFilterList_la_DEPENDENCIES = libVirt_Device.la libVirt_FilterList.la
libVirt_AppliedFilterList_la_SOURCES = Virt_AppliedFilterList.c
libVirt_AppliedFilterList_la_LIBADD = -lVirt_Device -lVirt_FilterList
+
+libVirt_VirtualEthernetSwitchSystem_la_SOURCES = Virt_VirtualEthernetSwitchSystem.c
+
+libVirt_VESSSD_la_SOURCES = Virt_VESSSD.c
+
+libVirt_EthernetPort_la_SOURCES = Virt_EthernetPort.c
+
+libVirt_EASD_la_SOURCES = Virt_EASD.c
+
+libVirt_VirtualEthernetSwitchSystemManagementService_la_DEPENDENCIES = libVirt_VirtualSystemManagementService.la libVirt_HostSystem.la libVirt_EASD.la libVirt_VirtualEthernetSwitchSystem.la
+libVirt_VirtualEthernetSwitchSystemManagementService_la_SOURCES = Virt_VirtualEthernetSwitchSystemManagementService.c
+libVirt_VirtualEthernetSwitchSystemManagementService_la_LIBADD = -lVirt_VirtualSystemManagementService -lVirt_HostSystem -lVirt_EASD -lVirt_VirtualEthernetSwitchSystem
--
1.7.1
12 years, 10 months
[PATCH V7 1/7] vlan extention - function libarary
by Wenchao Xia
This patch add function libarary and test program with libvirt API.
Limit:
It have only DHCP property about IP settings. Other settings such IP
and mask are ignored, in most cases ip are got by DHCP.
V7: Add codes of writing about network configuration. Codes such as iface
comparing and duplication are removed comparing to V2, which brings some
limit to the usage of API and structure, but make things more simple.
V6: Code changes according to comments.
V5: Calling libvirt API instead of implement my own.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
libxkutil/Makefile.am | 14 +-
libxkutil/misc_util.c | 48 ++
libxkutil/misc_util.h | 3 +
libxkutil/network_parsing.c | 1309 ++++++++++++++++++++++++++++++++++++++
libxkutil/network_parsing.h | 217 +++++++
libxkutil/network_parsing_test.c | 184 ++++++
libxkutil/xmlgen.c | 4 +-
libxkutil/xmlgen.h | 4 +
8 files changed, 1778 insertions(+), 5 deletions(-)
create mode 100644 libxkutil/network_parsing.c
create mode 100644 libxkutil/network_parsing.h
create mode 100644 libxkutil/network_parsing_test.c
diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
index 8d436ad..d154ef6 100644
--- a/libxkutil/Makefile.am
+++ b/libxkutil/Makefile.am
@@ -11,7 +11,9 @@ noinst_HEADERS = \
infostore.h \
pool_parsing.h \
acl_parsing.h \
- list_util.h
+ list_util.h \
+ network_parsing.h \
+ network_model_helper.h
lib_LTLIBRARIES = \
libxkutil.la
@@ -24,7 +26,9 @@ libxkutil_la_SOURCES = \
infostore.c \
pool_parsing.c \
acl_parsing.c \
- list_util.c
+ list_util.c \
+ network_parsing.c \
+ network_model_helper.c
libxkutil_la_LDFLAGS = \
-version-info @VERSION_INFO@
@@ -42,3 +46,9 @@ xml_parse_test_SOURCES = \
xml_parse_test_LDADD = \
libxkutil.la \
@LIBVIRT_LIBS@
+
+noinst_PROGRAMS += network_parsing_test
+
+network_parsing_test_SOURCES = network_parsing_test.c
+network_parsing_test_LDADD = libxkutil.la \
+ @LIBVIRT_LIBS@
diff --git a/libxkutil/misc_util.c b/libxkutil/misc_util.c
index 61893c3..564c6f2 100644
--- a/libxkutil/misc_util.c
+++ b/libxkutil/misc_util.c
@@ -184,6 +184,54 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
return conn;
}
+virConnectPtr connect_any(void)
+{
+ const char *uri = NULL;
+ virConnectPtr conn = NULL;
+ hypervisor_status_t *h = NULL;
+ const char *classname = NULL;
+
+ for (h = &hypervisor_list[0]; h != NULL; h++) {
+ if (h->enabled) {
+
+ classname = h->name;
+
+ uri = cn_to_uri(classname);
+ if (!uri) {
+ CU_DEBUG("Unable to gen URI from classname,"
+ " uri is %s.", uri);
+ return NULL;
+ }
+ CU_DEBUG("Connecting to libvirt with uri `%s'", uri);
+
+ pthread_mutex_lock(&libvirt_mutex);
+
+ if (is_read_only())
+ conn = virConnectOpenReadOnly(uri);
+ else
+ conn = virConnectOpen(uri);
+
+ pthread_mutex_unlock(&libvirt_mutex);
+
+ if (!conn) {
+ virErrorPtr error = virGetLastError();
+ if (error->code == VIR_ERR_NO_CONNECT)
+ set_hypervisor_disabled(classname);
+
+ CU_DEBUG("Unable to connect to `%s'", uri);
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (classname == NULL) {
+ CU_DEBUG("Failed to find any hypervisor.");
+ }
+ return conn;
+}
+
void free_domain_list(virDomainPtr *list, int count)
{
int i;
diff --git a/libxkutil/misc_util.h b/libxkutil/misc_util.h
index c7a2122..d1cc081 100644
--- a/libxkutil/misc_util.h
+++ b/libxkutil/misc_util.h
@@ -57,6 +57,9 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
const char *classname,
CMPIStatus *s);
+/* Try connect to any hypervisor available */
+virConnectPtr connect_any(void);
+
/* Establish a libvirt connection to the appropriate hypervisor,
* as determined by the state of the system, or the value of the
* HYPURI environment variable, if set.
diff --git a/libxkutil/network_parsing.c b/libxkutil/network_parsing.c
new file mode 100644
index 0000000..b043b40
--- /dev/null
+++ b/libxkutil/network_parsing.c
@@ -0,0 +1,1309 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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 <sys/stat.h>
+
+#include <libvirt/libvirt.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libcmpiutil/libcmpiutil.h>
+
+#include "misc_util.h"
+#include "xmlgen.h"
+#include "device_parsing.h"
+#include "network_parsing.h"
+
+#define LIST_INACTIVE_IFACE 1
+#define LIST_ACTIVE_IFACE 2
+
+static void vlan_prop_print(struct VLAN_Prop *pvlan_prop)
+{
+ struct VLAN_Prop_8021q *p_8021q;
+ CU_DEBUG_OP(1, "--VLAN props: type %d.\n",
+ pvlan_prop->vlan_type);
+ if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
+ p_8021q = &(pvlan_prop->props.prop_8021q);
+ CU_DEBUG_OP(1, "----IEEE802.1.Q: id %d, parent %s.\n",
+ p_8021q->vlan_id, p_8021q->parent);
+ }
+}
+
+static void br_prop_print(struct BR_Prop *pbr_prop)
+{
+ int i = 0;
+ CU_DEBUG_OP(1, "--Bridge props: stp %d, delay %d, port_num %d.\n",
+ pbr_prop->STP, pbr_prop->delay, pbr_prop->port_num);
+ if (pbr_prop->port_names != NULL) {
+ CU_DEBUG_OP(1, "----Ports attached: ");
+ while (i < pbr_prop->port_num) {
+ CU_DEBUG_OP(1, " %s,", *(pbr_prop->port_names+i));
+ i++;
+ }
+ CU_DEBUG_OP(1, "\n");
+ }
+}
+
+void eth_iface_print(struct EthIface *piface)
+{
+ CU_DEBUG_OP(1, "Iface device: name %s.\n"
+ "--Main props: parent %s, attach to %s, mac %s, iface type %d,"
+ " status %d, boot_mode %d,"
+ " protocol ipv4 dhcp %d.\n",
+ piface->name,
+ piface->dep_ifname, piface->attach_bridge, piface->mac, piface->eth_type,
+ piface->run_prop.status, piface->run_prop.boot_mode,
+ piface->protocol_prop.ipv4_prop.DHCP);
+ if (piface->pbr_prop != NULL) {
+ br_prop_print(piface->pbr_prop);
+ }
+ if (piface->pvlan_prop != NULL) {
+ vlan_prop_print(piface->pvlan_prop);
+ }
+ return;
+}
+
+void eth_ifaceslist_print(struct EthIfacesList *plist)
+{
+ int i = 0;
+ CU_DEBUG_OP(1, "Have %d ifaces in the list:\n", plist->count);
+ while (i < plist->count) {
+ CU_DEBUG_OP(1, "%04d ", i);
+ eth_iface_print(plist->pifaces[i]);
+ i++;
+ }
+}
+
+static void vlan_prop_init(struct VLAN_Prop *pvlan_prop, int vlan_type)
+{
+ struct VLAN_Prop_8021q *p_8021q;
+ memset(pvlan_prop, 0, sizeof(struct VLAN_Prop));
+ pvlan_prop->vlan_type = vlan_type;
+ if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
+ p_8021q = &(pvlan_prop->props.prop_8021q);
+ p_8021q->vlan_id = NUM_NONE;
+ }
+}
+
+static void br_prop_init(struct BR_Prop *pbr_prop)
+{
+ memset(pbr_prop, 0, sizeof(struct BR_Prop));
+ pbr_prop->STP = NUM_NONE;
+ pbr_prop->delay = NUM_NONE;
+ pbr_prop->port_num = NUM_NONE;
+}
+
+void eth_iface_init(struct EthIface *piface)
+{
+ memset(piface, 0, sizeof(struct EthIface));
+ piface->eth_type = ETH_TYPE_NOT_GOT;
+ piface->run_prop.status = NUM_NONE;
+ piface->run_prop.boot_mode = BOOT_MODE_NOT_GOT;
+ piface->protocol_prop.ipv4_prop.DHCP = NUM_NONE;
+ return;
+}
+
+void eth_iface_add_br_prop(struct EthIface *piface)
+{
+ if (piface->pbr_prop != NULL) {
+ return;
+ }
+ CU_MALLOC(piface->pbr_prop, sizeof(struct BR_Prop));
+ br_prop_init(piface->pbr_prop);
+}
+
+static void eth_iface_add_br_prop_attached_iface(struct EthIface *pbridge,
+ const char *iface_name)
+{
+ char **ppchar = NULL;
+
+ if (pbridge->pbr_prop->port_names == NULL) {
+ CU_CALLOC(pbridge->pbr_prop->port_names,
+ MAX_IFACE_NUM, sizeof(char *));
+ pbridge->pbr_prop->port_num = 0;
+ }
+
+ ppchar = pbridge->pbr_prop->port_names +
+ (pbridge->pbr_prop->port_num)++;
+ *ppchar = CU_STRDUP(iface_name);
+}
+
+void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type)
+{
+ if (piface->pvlan_prop != NULL) {
+ return;
+ }
+ CU_MALLOC(piface->pvlan_prop, sizeof(struct VLAN_Prop));
+ vlan_prop_init(piface->pvlan_prop, vlan_type);
+}
+
+static void vlan_prop_uninit(struct VLAN_Prop *pvlan_prop)
+{
+ struct VLAN_Prop_8021q *p_8021q;
+ if (pvlan_prop == NULL) {
+ return;
+ }
+ if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
+ p_8021q = &(pvlan_prop->props.prop_8021q);
+ CU_FREE(p_8021q->parent);
+ }
+}
+
+static void br_prop_uninit(struct BR_Prop *pbr_prop)
+{
+ int i = 0;
+ if (pbr_prop == NULL) {
+ return;
+ }
+ if (pbr_prop->port_names != NULL) {
+ while (i < pbr_prop->port_num) {
+ CU_FREE(pbr_prop->port_names[i]);
+ i++;
+ }
+ CU_FREE(pbr_prop->port_names);
+ }
+}
+
+void eth_iface_uninit(struct EthIface *piface)
+{
+ if (piface == NULL) {
+ return;
+ }
+ CU_FREE(piface->name);
+ CU_FREE(piface->dep_ifname);
+ CU_FREE(piface->attach_bridge);
+ CU_FREE(piface->mac);
+ br_prop_uninit(piface->pbr_prop);
+ CU_FREE(piface->pbr_prop);
+ vlan_prop_uninit(piface->pvlan_prop);
+ CU_FREE(piface->pvlan_prop);
+ return;
+}
+
+void eth_ifaceslist_init(struct EthIfacesList *plist)
+{
+ plist->count = 0;
+}
+
+void eth_ifaceslist_uninit(struct EthIfacesList *plist)
+{
+ struct EthIface **t = NULL;
+ int i = 0;
+ if (plist->count <= 0) {
+ return;
+ }
+ t = plist->pifaces;
+ while (i < plist->count) {
+ if (*t != NULL) {
+ eth_iface_uninit(*t);
+ CU_FREE(*t);
+ }
+ t++;
+ i++;
+ }
+ return;
+}
+
+int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface)
+{
+ if (plist->count >= MAX_IFACE_NUM) {
+ CU_DEBUG("Too much device found.");
+ return 0;
+ }
+ plist->pifaces[plist->count] = *ppiface;
+ *ppiface = NULL;
+ plist->count++;
+ return 1;
+}
+
+struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
+ char *name)
+{
+ int i = 0;
+ struct EthIface *piface = NULL;
+
+ while (i < plist->count) {
+ piface = plist->pifaces[i];
+ i++;
+ if (piface != NULL) {
+ if (strcmp(piface->name, name) == 0) {
+ return piface;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void vlan_prop_merge(struct VLAN_Prop *pdest, struct VLAN_Prop *psrc)
+{
+ struct VLAN_Prop_8021q *pd_8021q, *ps_8021q;
+
+ NUM_MERGE(pdest->vlan_type, psrc->vlan_type, VLAN_TYPE_NOT_GOT);
+
+ if (psrc->vlan_type == VLAN_TYPE_802_1_Q) {
+ pd_8021q = &(pdest->props.prop_8021q);
+ ps_8021q = &(psrc->props.prop_8021q);
+ NUM_MERGE(pd_8021q->vlan_id, ps_8021q->vlan_id, NUM_NONE);
+ CHARS_MERGE(pd_8021q->parent, ps_8021q->parent);
+ }
+}
+
+static void br_prop_merge(struct BR_Prop *pdest, struct BR_Prop *psrc)
+{
+ int i;
+
+ /*merge it when dest have not been set */
+ if ((pdest->port_names == NULL) && (psrc->port_names != NULL)){
+ CU_PSTR_ARRAY_DUP(pdest->port_names, pdest->port_num,
+ psrc->port_names, psrc->port_num, i);
+ }
+
+ NUM_MERGE(pdest->STP, psrc->STP, NUM_NONE);
+ NUM_MERGE(pdest->delay, psrc->delay, NUM_NONE);
+}
+
+static void eth_iface_merge(struct EthIface *dest, struct EthIface *src)
+{
+ CHARS_MERGE(dest->name, src->name);
+ CHARS_MERGE(dest->dep_ifname, src->dep_ifname);
+ CHARS_MERGE(dest->attach_bridge, src->attach_bridge);
+ CHARS_MERGE(dest->mac, src->mac);
+ NUM_MERGE(dest->eth_type, src->eth_type, NUM_NONE);
+
+ NUM_MERGE(dest->run_prop.status, src->run_prop.status,
+ NUM_NONE);
+ NUM_MERGE(dest->run_prop.boot_mode, src->run_prop.boot_mode,
+ BOOT_MODE_NOT_GOT);
+ NUM_MERGE(dest->protocol_prop.ipv4_prop.DHCP,
+ src->protocol_prop.ipv4_prop.DHCP,
+ NUM_NONE);
+ if (src->pbr_prop != NULL) {
+ if (dest->pbr_prop == NULL) {
+ CU_MALLOC(dest->pbr_prop, sizeof(struct BR_Prop));
+ br_prop_init(dest->pbr_prop);
+ }
+ br_prop_merge(dest->pbr_prop, src->pbr_prop);
+ }
+
+ if (src->pvlan_prop != NULL) {
+ if (dest->pvlan_prop == NULL) {
+ CU_MALLOC(dest->pvlan_prop, sizeof(struct VLAN_Prop));
+ vlan_prop_init(dest->pvlan_prop, src->pvlan_prop->vlan_type);
+ }
+ vlan_prop_merge(dest->pvlan_prop, src->pvlan_prop);
+ }
+
+}
+
+/* the judgement condition is weak, but I can't find a better way */
+int eth_iface_filter_peths(const struct EthIface *piface, void *nouse)
+{
+ if ((piface->eth_type != ETH_TYPE_ETHER_ANY) &&
+ (piface->eth_type != ETH_TYPE_ETHER_PHYSICAL)) {
+ return 0;
+ }
+ if (piface->dep_ifname != NULL) {
+ return 0;
+ }
+ if (NULL != strstr(piface->name, ".")) {
+ return 0;
+ }
+ /* this filter NetUSB etc */
+ if (NULL == strstr(piface->name, "eth")) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int eth_iface_filter_by_name(const struct EthIface *piface, void *name)
+{
+ int comp_ret;
+ comp_ret = strcmp(piface->name, (char *)name);
+ if (comp_ret == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+char *get_host_iface_error_reason(int errno)
+{
+ char *ret = NULL;
+ switch (errno) {
+ case ERR_CONNECT:
+ ret = "Error in connect to hypervisor.";
+ break;
+
+ case ERR_LIST_INTERFACE:
+ ret = "Error in listing the interfaces.";
+ break;
+
+ case ERR_GENXML_INTERFACE:
+ ret = "Error in generating xml for interfaces.";
+ break;
+
+ case ERR_CALL_LIBVIRT:
+ ret = "Libvirt API returns failure.";
+ break;
+
+ case ERR_DEVICE_EXIST:
+ ret = "Interface already exist.";
+ break;
+
+ case ERR_DEVICE_NOT_EXIST:
+ ret = "Interface do not exist.";
+ break;
+
+ case ERR_NOT_SUPPORT:
+ ret = "Request for interfaces not supported.";
+ break;
+
+ default:
+ ret = "Internal error in calling libvirt API for interfaces.";
+ break;
+ }
+ return ret;
+}
+
+/* Dummy function to suppress error message from libxml2 */
+static void swallow_err_msg(void *ctx, const char *msg, ...)
+{
+ /* do nothing, just swallow the message. */
+}
+
+
+static const char *gen_eth_xmlnode_iface(xmlNodePtr root,
+ struct EthIface *piface,
+ struct EthIfacesList *plist,
+ int bridge_port_flag)
+{
+ const char *msg = NULL;
+ xmlNodePtr temp_node1 = NULL, temp_node2 = NULL, temp_node3 = NULL;
+ char *str = NULL, buf[16] = {0,};
+ int i = 0;
+ struct EthIface *pifaceport;
+
+ if (piface->name == NULL) {
+ msg = "Iface have no name.\n";
+ goto out;
+ }
+ /* netcfg have no xml for iface attatched to bridge */
+ if ((piface->attach_bridge != NULL) && (bridge_port_flag != 1)) {
+ goto out;
+ }
+
+ temp_node1 = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
+ if (temp_node1 == NULL) {
+ msg = XML_ERROR;
+ goto out;
+ }
+ xmlNewProp(temp_node1, BAD_CAST "name", BAD_CAST piface->name);
+
+ if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) {
+ str = "bridge";
+ } else if (piface->eth_type == ETH_TYPE_ETHER_VLAN) {
+ str = "vlan";
+ } else {
+ str = "ethernet";
+ }
+ xmlNewProp(temp_node1, BAD_CAST "type", BAD_CAST str);
+
+ if ((piface->pvlan_prop != NULL) &&
+ (piface->pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q)) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "vlan", NULL);
+ snprintf(buf, sizeof(buf),
+ "%d", piface->pvlan_prop->props.prop_8021q.vlan_id);
+ xmlNewProp(temp_node2, BAD_CAST "tag", BAD_CAST buf);
+ temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "interface", NULL);
+ xmlNewProp(temp_node3, BAD_CAST "name",
+ BAD_CAST piface->pvlan_prop->props.prop_8021q.parent);
+ }
+
+ /* if it is attached to bridge, only above properties could be set */
+ if (bridge_port_flag == 1) {
+ goto out;
+ }
+
+ if (piface->protocol_prop.ipv4_prop.DHCP == 1) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "protocol", NULL);
+ xmlNewProp(temp_node2, BAD_CAST "family", BAD_CAST "ipv4");
+ temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "dhcp", NULL);
+ }
+
+ if (piface->pbr_prop != NULL) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "bridge", NULL);
+ if (piface->pbr_prop->STP == 1) {
+ snprintf(buf, sizeof(buf), "on");
+ } else {
+ snprintf(buf, sizeof(buf), "off");
+ }
+ xmlNewProp(temp_node2, BAD_CAST "stp", BAD_CAST buf);
+ if (piface->pbr_prop->delay >= 0) {
+ snprintf(buf, sizeof(buf), "%d", piface->pbr_prop->delay);
+ xmlNewProp(temp_node2, BAD_CAST "delay", BAD_CAST buf);
+ }
+ if ((piface->pbr_prop->port_names != NULL) &&
+ (piface->pbr_prop->port_num > 0)) {
+ for (i = 0; i < piface->pbr_prop->port_num; i++) {
+ pifaceport = eth_ifaceslist_search(plist,
+ piface->pbr_prop->port_names[i]);
+ if (pifaceport == NULL) {
+ CU_DEBUG("failed to find port %s of bridge %s in list.",
+ piface->pbr_prop->port_names[i], piface->name);
+ } else {
+ gen_eth_xmlnode_iface(temp_node2, pifaceport, plist, 1);
+ }
+ }
+ }
+ }
+
+ if (piface->run_prop.boot_mode == BOOT_MODE_AUTOSTART) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
+ xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "onboot");
+ } else if (piface->run_prop.boot_mode == BOOT_MODE_NONE) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
+ xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "none");
+ }
+ if (piface->mac != NULL) {
+ temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "mac", NULL);
+ xmlNewProp(temp_node2, BAD_CAST "address", BAD_CAST piface->mac);
+ }
+
+ out:
+ return msg;
+}
+
+static const char *gen_eth_xmlnode(xmlNodePtr root,
+ struct EthIfacesList *plist)
+{
+ const char *msg = NULL;
+ int i = 0;
+ struct EthIface *piface = NULL;
+
+ while (i < plist->count) {
+ piface = plist->pifaces[i];
+ i++;
+ msg = gen_eth_xmlnode_iface(root, piface, plist, 0);
+ if (msg != NULL) {
+ goto out;
+ }
+ }
+
+ out:
+ return msg;
+}
+
+static const char *EthIfaceListTOXML(char **ppxml,
+ struct EthIfacesList *plist,
+ int dump_all_flag)
+{
+ const char *msg = NULL;
+ xmlNodePtr root = NULL;
+
+ root = xmlNewNode(NULL, BAD_CAST "tmp");
+ if (root == NULL) {
+ msg = "Failed to create root node.";
+ goto out;
+ }
+ msg = gen_eth_xmlnode(root, plist);
+ if (msg == NULL) {
+ if (dump_all_flag == 1) {
+ *ppxml = tree_to_xml(root);
+ } else {
+ *ppxml = tree_to_xml(root->children);
+ }
+ }
+
+ out:
+ xmlFreeNode(root);
+ return msg;
+}
+
+static int host_iface_adjust(struct EthIface *piface)
+{
+ if (1 == eth_iface_filter_peths(piface, NULL)) {
+ piface->eth_type = ETH_TYPE_ETHER_PHYSICAL;
+ }
+ return 1;
+}
+
+static int parse_eth_xmlnode(struct EthIfacesList *plist, xmlNode *inode,
+ int status, char *attached,
+ eth_iface_filter_func filter_func,
+ void *filter_opaque)
+{
+ struct EthIface *piface = NULL;
+ xmlNode *child1 = NULL, *child2 = NULL;
+ char *temp = NULL;
+ int filter_ret = 0;
+
+ CU_MALLOC(piface, sizeof(struct EthIface));
+ eth_iface_init(piface);
+
+ piface->name = get_attr_value(inode, "name");
+ piface->run_prop.status = status;
+ if (attached != NULL) {
+ piface->attach_bridge = strdup(attached);
+ }
+ temp = get_attr_value(inode, "type");
+ if (temp != NULL) {
+ if (strcmp(temp, "ethernet") == 0) {
+ piface->eth_type = ETH_TYPE_ETHER_ANY;
+ }
+ if (strcmp(temp, "bridge") == 0) {
+ piface->eth_type = ETH_TYPE_ETHER_BRIDGE;
+ }
+ if (strcmp(temp, "vlan") == 0) {
+ piface->eth_type = ETH_TYPE_ETHER_VLAN;
+ }
+ CU_FREE(temp);
+ }
+
+ for (child1 = inode->children; child1 != NULL; child1 = child1->next) {
+ if (XSTREQ(child1->name, "start")) {
+ temp = get_attr_value(child1, "mode");
+ if (strcmp(temp, "onboot") == 0) {
+ piface->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
+ }
+ if (strcmp(temp, "none") == 0) {
+ piface->run_prop.boot_mode = BOOT_MODE_NONE;
+ }
+ CU_FREE(temp);
+ }
+ if (XSTREQ(child1->name, "mac")) {
+ piface->mac = get_attr_value(child1, "address");
+ }
+ if (XSTREQ(child1->name, "protocol")) {
+ temp = get_attr_value(child1, "family");
+ if (strcmp(temp, "ipv4") == 0) {
+ for (child2 = child1->children; child2 != NULL;
+ child2 = child2->next) {
+ if (XSTREQ(child2->name, "dhcp")) {
+ piface->protocol_prop.ipv4_prop.DHCP = 1;
+ break;
+ }
+ }
+ }
+ CU_FREE(temp);
+ }
+ if (XSTREQ(child1->name, "bridge")) {
+ eth_iface_add_br_prop(piface);
+ temp = get_attr_value(child1, "stp");
+ if (strcmp(temp, "on") == 0) {
+ piface->pbr_prop->STP = 1;
+ }
+ if (strcmp(temp, "off") == 0) {
+ piface->pbr_prop->STP = 0;
+ }
+ CU_FREE(temp);
+ temp = get_attr_value(child1, "delay");
+ piface->pbr_prop->delay = strtol(temp, NULL, 10);
+ CU_FREE(temp);
+ }
+ if (XSTREQ(child1->name, "bridge")) {
+ eth_iface_add_br_prop(piface);
+ temp = get_attr_value(child1, "stp");
+ if (strcmp(temp, "on") == 0) {
+ piface->pbr_prop->STP = 1;
+ }
+ if (strcmp(temp, "off") == 0) {
+ piface->pbr_prop->STP = 0;
+ }
+ CU_FREE(temp);
+ temp = get_attr_value(child1, "delay");
+ piface->pbr_prop->delay = strtol(temp, NULL, 10);
+ CU_FREE(temp);
+ for (child2 = child1->children; child2 != NULL;
+ child2 = child2->next) {
+ if (XSTREQ(child2->name, "interface")) {
+ temp = get_attr_value(child2, "name");
+ eth_iface_add_br_prop_attached_iface(piface, temp);
+ CU_FREE(temp);
+ parse_eth_xmlnode(plist, child2, status, piface->name,
+ filter_func, filter_opaque);
+ }
+ }
+ }
+ if (XSTREQ(child1->name, "vlan")) {
+ eth_iface_add_vlan_prop(piface, VLAN_TYPE_802_1_Q);
+ temp = get_attr_value(child1, "tag");
+ piface->pvlan_prop->props.prop_8021q.vlan_id =
+ strtol(temp, NULL, 10);
+ CU_FREE(temp);
+ for (child2 = child1->children; child2 != NULL;
+ child2 = child2->next) {
+ if (XSTREQ(child2->name, "interface")) {
+ piface->pvlan_prop->props.prop_8021q.parent =
+ get_attr_value(child2, "name");
+ piface->dep_ifname =
+ get_attr_value(child2, "name");
+ }
+ }
+ }
+ }
+
+ host_iface_adjust(piface);
+
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(piface, filter_opaque);
+ }
+ if (filter_ret == 1) {
+ eth_ifaceslist_add(plist, &piface);
+ }
+ return 1;
+}
+
+static const char *XMLToEthIfaceList(struct EthIfacesList *plist,
+ const char *xml,
+ int status,
+ eth_iface_filter_func filter_func,
+ void *filter_opaque)
+{
+ xmlDoc *xmldoc = NULL;
+ xmlXPathContext *xpathCtx = NULL;
+ xmlXPathObject *xpathObj = NULL;
+ xmlChar *xpathstr = NULL;
+ xmlNode **dev_nodes = NULL;
+ xmlNodeSet *nsv = NULL;
+ int count = 0;
+ int len = 0, devidx = 0;
+ const char *msg = NULL;
+
+ len = strlen(xml) + 1;
+ xpathstr = (xmlChar *)"/interface";
+
+ xmlSetGenericErrorFunc(NULL, swallow_err_msg);
+ if ((xmldoc = xmlParseMemory(xml, len)) == NULL) {
+ msg = "Failed to get xmldoc.";
+ goto err1;
+ }
+
+ if ((xpathCtx = xmlXPathNewContext(xmldoc)) == NULL) {
+ msg = "Failed to get pathCtx";
+ goto err2;
+ }
+
+ if ((xpathObj = xmlXPathEvalExpression(xpathstr, xpathCtx))
+ == NULL) {
+ msg = "Failed to get xpathObj";
+ goto err3;
+ }
+
+ nsv = xpathObj->nodesetval;
+ if (nsv == NULL) {
+ msg = "Failed to get nodesetval.";
+ goto out;
+ }
+
+ dev_nodes = nsv->nodeTab;
+ count = nsv->nodeNr;
+
+ if (count <= 0) {
+ msg = "Nodesetval have less that 1 values.";
+ goto out;
+ }
+
+ for (devidx = 0; devidx < count; devidx++) {
+ parse_eth_xmlnode(plist, dev_nodes[devidx], status, NULL,
+ filter_func, filter_opaque);
+ }
+
+ out:
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlXPathFreeObject(xpathObj);
+
+ err3:
+ xmlXPathFreeContext(xpathCtx);
+ err2:
+ xmlFreeDoc(xmldoc);
+ err1:
+ return msg;
+}
+
+int get_host_ifaces(struct EthIfacesList *plist,
+ eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+ int ret = 0;
+ int num = 0, listnum = 0, i = 0;
+ char **names = NULL;
+ char *xml = NULL;
+ int flags = 0;
+ const char *msg = NULL;
+ int list_flag = LIST_INACTIVE_IFACE | LIST_ACTIVE_IFACE;
+ int xml_flag = VIR_INTERFACE_XML_INACTIVE;
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ /* list defined interfaces*/
+ if ((list_flag & LIST_INACTIVE_IFACE) == 0) {
+ goto list_active;
+ }
+ num = virConnectNumOfDefinedInterfaces(conn);
+ if (num < 0) {
+ CU_DEBUG("Failed to find number of defined interfaces.");
+ ret = ERR_LIST_INTERFACE;
+ goto out;
+ }
+ names = malloc(num * sizeof(char *));
+ listnum = virConnectListDefinedInterfaces(conn, names, num);
+ if (listnum < 0) {
+ CU_DEBUG("Failed to list names of defined interfaces.");
+ ret = ERR_LIST_INTERFACE;
+ goto out;
+ }
+ CU_DEBUG("%d defined ifaces found from libvirt API.\n", listnum);
+
+ flags = xml_flag;
+ for (i = 0; i < listnum; i++) {
+ iface = virInterfaceLookupByName(conn, names[i]);
+ if (!iface) {
+ CU_DEBUG("Failed to look up %s.\n", names[i]);
+ CU_FREE(names[i]);
+ continue;
+ }
+ CU_FREE(names[i]);
+ xml = virInterfaceGetXMLDesc(iface, flags);
+ CU_DEBUG_OP(3, "Defined interface %d xml:\n%s", i, xml);
+ msg = XMLToEthIfaceList(plist, xml, ETH_STATE_INACTIVE,
+ filter_func, filter_opaque);
+ if (msg != NULL) {
+ CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg);
+ }
+ CU_FREE(xml);
+ virInterfaceFree(iface);
+ }
+ CU_FREE(names);
+
+ list_active:
+ /* list active interfaces*/
+ if ((list_flag & LIST_ACTIVE_IFACE) == 0) {
+ goto out;
+ }
+ num = virConnectNumOfInterfaces(conn);
+ if (num < 0) {
+ CU_DEBUG("Failed to find number of active interfaces.");
+ ret = ERR_LIST_INTERFACE;
+ goto out;
+ }
+ names = malloc(num * sizeof(char *));
+
+ listnum = virConnectListInterfaces(conn, names, num);
+ if (listnum < 0) {
+ CU_DEBUG("Failed to list names of active interfacess.");
+ ret = ERR_LIST_INTERFACE;
+ goto out;
+ }
+ CU_DEBUG("%d active ifaces found from libvirt API.\n", listnum);
+
+ flags = xml_flag;
+ for (i = 0; i < listnum; i++) {
+ iface = virInterfaceLookupByName(conn, names[i]);
+ if (!iface) {
+ CU_DEBUG("Failed to look up %s.\n", names[i]);
+ CU_FREE(names[i]);
+ continue;
+ }
+ CU_FREE(names[i]);
+ xml = virInterfaceGetXMLDesc(iface, flags);
+ CU_DEBUG_OP(3, "Active interface %d xml:\n%s", i, xml);
+ msg = XMLToEthIfaceList(plist, xml, ETH_STATE_ACTIVE,
+ filter_func, filter_opaque);
+ if (msg != NULL) {
+ CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg);
+ }
+ CU_FREE(xml);
+ virInterfaceFree(iface);
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ CU_FREE(names);
+ return ret;
+}
+
+int add_host_iface(struct EthIface *piface)
+{
+ struct EthIfacesList list;
+ const char *msg = NULL;
+ char *genxml = NULL;
+ int ret = 0;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+
+ /* the list do not need to be uninitilized to keep untouch of piface,
+ because now eth_ifaceslist_add function simply add piface to the
+ list instead of duplication. */
+ eth_ifaceslist_init(&list);
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ /* Fix me: now virInterfaceLookupByName sometimes return a valid pointer
+ even thought iface with name piface->name is deleted. So here a check
+ for it is skipped. */
+ /*
+ iface = virInterfaceLookupByName(conn, piface->name);
+ if (iface != NULL) {
+ CU_DEBUG("iface %s already exist.", piface->name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+ */
+
+ eth_ifaceslist_add(&list, &piface);
+ msg = EthIfaceListTOXML(&genxml, &list, 0);
+ if (msg != NULL) {
+ CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg);
+ ret = ERR_GENXML_INTERFACE;
+ goto out;
+ }
+
+ CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml);
+ iface = virInterfaceDefineXML(conn, genxml, 0);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ CU_FREE(genxml);
+ return ret;
+}
+
+int del_host_iface(struct EthIface *piface)
+{
+ int call_ret = 0;
+ int ret = 0;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ iface = virInterfaceLookupByName(conn, piface->name);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in find iface %s.", piface->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ call_ret = virInterfaceUndefine(iface);
+ if (call_ret != 0) {
+ CU_DEBUG("Failed in undefine iface %s, ret is %d.",
+ piface->name, call_ret);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ return ret;
+}
+
+/* piface would be changed because of internel merge, in order to save code of
+ struct EthIface duplication */
+int mod_host_iface(struct EthIface *piface)
+{
+ struct EthIfacesList list, list_new;
+ struct EthIface *pprev_iface = NULL;
+ int ret = 0;
+ const char *msg = NULL;
+ char *genxml = NULL;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+
+ eth_ifaceslist_init(&list);
+ ret = get_host_ifaces(&list, NULL, NULL);
+ if (ret != 1) {
+ CU_DEBUG("Failed in list host device.");
+ goto out;
+ }
+
+ pprev_iface = eth_ifaceslist_search(&list, piface->name);
+ if (pprev_iface == NULL) {
+ CU_DEBUG("Failed in searching for iface %s",
+ piface->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ eth_iface_merge(piface, pprev_iface);
+
+ /* list_new do not need to be uninited */
+ eth_ifaceslist_init(&list_new);
+ eth_ifaceslist_add(&list_new, &piface);
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ msg = EthIfaceListTOXML(&genxml, &list_new, 0);
+ if (msg != NULL) {
+ CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg);
+ ret = ERR_GENXML_INTERFACE;
+ goto out;
+ }
+
+ CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml);
+ iface = virInterfaceDefineXML(conn, genxml, 0);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ CU_FREE(genxml);
+ eth_ifaceslist_uninit(&list);
+ return ret;
+}
+
+/* assuming that pbridge have not added piface in its bridge property,
+ and piface have not set pbridge'name in its attach_bridge property. */
+int connect_two_ifaces(struct EthIface *p1, struct EthIface *p2)
+{
+ struct EthIface *pbridge = NULL, *piface = NULL;
+ struct EthIfacesList list, list_new;
+ struct EthIface *pprev_iface1 = NULL, *pprev_iface2 = NULL,
+ *pexist_port = NULL;
+ int ret = 0;
+ const char* msg = NULL;
+ char *genxml = NULL;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+ int i;
+
+ eth_ifaceslist_init(&list);
+ eth_ifaceslist_init(&list_new);
+
+ ret = get_host_ifaces(&list, NULL, NULL);
+ if (ret != 1) {
+ CU_DEBUG("Failed in list host device.");
+ goto out;
+ }
+
+ pprev_iface1 = eth_ifaceslist_search(&list, p1->name);
+ if (pprev_iface1 == NULL) {
+ CU_DEBUG("Failed in searching for iface %s",
+ p1->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ pprev_iface2 = eth_ifaceslist_search(&list, p2->name);
+ if (pprev_iface2 == NULL) {
+ CU_DEBUG("Failed in searching for iface %s",
+ p2->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ if ((pprev_iface1->eth_type == ETH_TYPE_ETHER_BRIDGE) &&
+ ((pprev_iface2->eth_type == ETH_TYPE_ETHER_VLAN) ||
+ (pprev_iface2->eth_type == ETH_TYPE_ETHER_PHYSICAL))) {
+ pbridge = pprev_iface1;
+ piface = pprev_iface2;
+ }
+ if ((pprev_iface2->eth_type == ETH_TYPE_ETHER_BRIDGE) &&
+ ((pprev_iface1->eth_type == ETH_TYPE_ETHER_VLAN) ||
+ (pprev_iface1->eth_type == ETH_TYPE_ETHER_PHYSICAL))) {
+ pbridge = pprev_iface2;
+ piface = pprev_iface1;
+ }
+
+ if ((pbridge == NULL) || (piface == NULL)) {
+ CU_DEBUG("Cannot connect these devices, one must be bridge.");
+ ret = ERR_NOT_SUPPORT;
+ goto out;
+ }
+
+ if (pbridge->pbr_prop == NULL) {
+ CU_DEBUG("pbridge %s have no bridge props added.", pbridge->name);
+ ret = ERR_NOT_SUPPORT;
+ goto out;
+ }
+
+ /* adding piface to pbridge, list_new do not need uninitlized */
+ eth_iface_add_br_prop_attached_iface(pbridge, piface->name);
+ eth_ifaceslist_add(&list_new, &pbridge);
+ pbridge = list_new.pifaces[0];
+ /* adding existing port to list_new, despite new added port */
+ if (pbridge->pbr_prop->port_num > 1) {
+ for (i = 0;i < (pbridge->pbr_prop->port_num - 1); i++) {
+ pexist_port = eth_ifaceslist_search(&list,
+ pbridge->pbr_prop->port_names[i]);
+ if (pexist_port == NULL) {
+ CU_DEBUG("Fail to find %s.", pbridge->pbr_prop->port_names[i]);
+ continue;
+ }
+ eth_ifaceslist_add(&list_new, &pexist_port);
+ }
+ }
+ piface->attach_bridge = CU_STRDUP(pbridge->name);
+ eth_ifaceslist_add(&list_new, &piface);
+
+ msg = EthIfaceListTOXML(&genxml, &list_new, 0);
+ if (msg != NULL) {
+ CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg);
+ ret = ERR_GENXML_INTERFACE;
+ goto out;
+ }
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml);
+ iface = virInterfaceDefineXML(conn, genxml, 0);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ eth_ifaceslist_uninit(&list);
+ CU_FREE(genxml);
+ return ret;
+}
+
+int disconnect_two_ifaces(struct EthIface *p1, struct EthIface *p2)
+{
+ struct EthIface *pbridge = NULL, *piface = NULL;
+ struct EthIfacesList list, list_new;
+ struct EthIface *pprev_iface1 = NULL, *pprev_iface2 = NULL;
+ int ret = 0;
+ const char* msg = NULL;
+ char *genxml = NULL;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+
+ eth_ifaceslist_init(&list);
+ eth_ifaceslist_init(&list_new);
+
+ ret = get_host_ifaces(&list, NULL, NULL);
+ if (ret != 1) {
+ CU_DEBUG("Failed in list host device.");
+ goto out;
+ }
+
+ pprev_iface1 = eth_ifaceslist_search(&list, p1->name);
+ if (pprev_iface1 == NULL) {
+ CU_DEBUG("Failed in searching for iface %s",
+ p1->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ pprev_iface2 = eth_ifaceslist_search(&list, p2->name);
+ if (pprev_iface2 == NULL) {
+ CU_DEBUG("Failed in searching for iface %s",
+ p2->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ if ((pprev_iface1->eth_type == ETH_TYPE_ETHER_BRIDGE) &&
+ ((pprev_iface2->eth_type == ETH_TYPE_ETHER_VLAN) ||
+ (pprev_iface2->eth_type == ETH_TYPE_ETHER_PHYSICAL))) {
+ pbridge = pprev_iface1;
+ piface = pprev_iface2;
+ }
+ if ((pprev_iface2->eth_type == ETH_TYPE_ETHER_BRIDGE) &&
+ ((pprev_iface1->eth_type == ETH_TYPE_ETHER_VLAN) ||
+ (pprev_iface1->eth_type == ETH_TYPE_ETHER_PHYSICAL))) {
+ pbridge = pprev_iface2;
+ piface = pprev_iface1;
+ }
+
+ if ((pbridge == NULL) || (piface == NULL)) {
+ CU_DEBUG("Cannot disconnect these devices, one must be bridge.");
+ ret = ERR_NOT_SUPPORT;
+ goto out;
+ }
+
+ /* for libvirt, just remove the attached bridge in piface and redefine it*/
+ CU_FREE(piface->attach_bridge);
+ piface->attach_bridge = NULL;
+ /* for a stand alone piface, libvirt/netcf require it have boot_mode set */
+ if (piface->run_prop.boot_mode == BOOT_MODE_NOT_GOT) {
+ piface->run_prop.boot_mode = BOOT_MODE_NONE;
+ }
+ eth_ifaceslist_add(&list_new, &piface);
+
+ msg = EthIfaceListTOXML(&genxml, &list_new, 0);
+ if (msg != NULL) {
+ CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg);
+ ret = ERR_GENXML_INTERFACE;
+ goto out;
+ }
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml);
+ iface = virInterfaceDefineXML(conn, genxml, 0);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ eth_ifaceslist_uninit(&list);
+ CU_FREE(genxml);
+ return ret;
+}
+
+int change_state_host_iface(struct EthIface *piface, int state)
+{
+ int ret = 0, call_ret = 0;
+ int prev_state = 0;
+ virConnectPtr conn = NULL;
+ virInterfacePtr iface = NULL;
+
+ conn = connect_any();
+ if (conn == NULL) {
+ CU_DEBUG("Connect for network failed.");
+ ret = ERR_CONNECT;
+ goto out;
+ }
+
+ iface = virInterfaceLookupByName(conn, piface->name);
+ if (iface == NULL) {
+ CU_DEBUG("Failed in finding %s.", piface->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ prev_state = virInterfaceIsActive(iface);
+ if (prev_state == state) {
+ CU_DEBUG("iface %s already in state %d, request is %d.", piface->name,
+ prev_state, state);
+ ret = 1;
+ goto out;
+ }
+
+ CU_DEBUG("Calling libvirt API to change state to %d.", state);
+ if (state == 1) {
+ call_ret = virInterfaceCreate(iface, 0);
+ if (call_ret != 0) {
+ CU_DEBUG("Failed to activate %s in libvirt.", piface->name);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ } else if (state == 0) {
+ call_ret = virInterfaceDestroy(iface, 0);
+ if (call_ret != 0) {
+ CU_DEBUG("Failed to destroy %s in libvirt.", piface->name);
+ ret = ERR_CALL_LIBVIRT;
+ goto out;
+ }
+ }
+
+ ret = 1;
+
+ out:
+ if (conn != NULL) {
+ virConnectClose(conn);
+ }
+ if (iface != NULL) {
+ virInterfaceFree(iface);
+ }
+ return ret;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/libxkutil/network_parsing.h b/libxkutil/network_parsing.h
new file mode 100644
index 0000000..c8121a5
--- /dev/null
+++ b/libxkutil/network_parsing.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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.
+ */
+
+#ifndef NETWORK_PARSING_H
+#define NETWORK_PARSING_H
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+/* value defines */
+#define MAX_IFACE_NUM 4096
+
+#define NUM_NONE -1
+
+#define CU_DEBUG_LEVEL 2
+
+#define ERR_CONNECT -1
+#define ERR_LIST_INTERFACE -2
+#define ERR_GENXML_INTERFACE -3
+#define ERR_CALL_LIBVIRT -4
+#define ERR_DEVICE_EXIST -5
+#define ERR_DEVICE_NOT_EXIST -6
+#define ERR_NOT_SUPPORT -7
+
+/* macro functions */
+#define CU_DEBUG_OP(lvl, fmt, args...) do { \
+ if (CU_DEBUG_LEVEL && (lvl) <= CU_DEBUG_LEVEL) { \
+ debug_print(fmt, ##args); \
+ } \
+} while (0)
+
+#define CU_MALLOC(p, size) \
+{ \
+ (p) = malloc((size)); \
+ if ((p) == NULL) { \
+ CU_DEBUG("malloc failed."); \
+ } \
+}
+
+#define CU_CALLOC(p, nmen, size) \
+{ \
+ (p) = calloc((nmen), (size)); \
+ if ((p) == NULL) { \
+ CU_DEBUG("calloc failed."); \
+ } \
+}
+
+#define CU_FREE(p) {free(p); (p) = NULL; }
+
+/* duplicate char* */
+#define CU_STRDUP(p) (p) == NULL ? NULL : strdup(p);
+
+/* duplicate char* array */
+#define CU_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter) do { \
+ (dest_num) = (src_num); \
+ (ppdest) = NULL; \
+ if (((ppsrc) != NULL) && ((src_num) > 0)) { \
+ CU_CALLOC((ppdest), (src_num), sizeof(char *)); \
+ (iter) = 0; \
+ while ((iter) < (src_num)) { \
+ *((ppdest)+(iter)) = CU_STRDUP(*((ppsrc)+(iter))); \
+ (iter)++; \
+ } \
+ } \
+} while (0)
+
+/* merge integer if dest == default */
+#define NUM_MERGE(dest, src, default) do { \
+ if ((dest) == (default)) { \
+ (dest) = (src); \
+ } \
+} while (0)
+
+/* merge char* if dest == NULL */
+#define CHARS_MERGE(dest, src) do { \
+ if (((dest) == NULL) && ((src) != NULL)) { \
+ (dest) = strdup((src)); \
+ } \
+} while (0)
+
+typedef enum {
+ ETH_TYPE_NOT_GOT = NUM_NONE,
+ ETH_TYPE_ETHER_ANY = 0x0001,
+ ETH_TYPE_ETHER_PHYSICAL = 0x0002,
+ ETH_TYPE_ETHER_BRIDGE = 0x0004,
+ ETH_TYPE_ETHER_VLAN = 0x0008
+} EthType;
+
+typedef enum {
+ VLAN_TYPE_NOT_GOT = NUM_NONE,
+ VLAN_TYPE_802_1_Q = 1,
+ VLAN_TYPE_802_1_QBG = 2,
+ VLAN_TYPE_802_1_QBH = 4
+} VLANType;
+
+typedef enum {
+ BOOT_MODE_NOT_GOT = NUM_NONE,
+ BOOT_MODE_NONE = 0,
+ BOOT_MODE_AUTOSTART = 1
+} BootMode;
+
+typedef enum {
+ ETH_STATE_INACTIVE = 0,
+ ETH_STATE_ACTIVE = 1
+} Status;
+
+struct IPV4_Prop {
+ int DHCP;
+} ;
+
+struct Protocol_Prop {
+ struct IPV4_Prop ipv4_prop;
+} ;
+
+struct BR_Prop {
+ int STP;
+ int delay;
+ char **port_names;
+ int port_num;
+} ;
+
+struct Run_Prop {
+ Status status;
+ BootMode boot_mode;
+} ;
+
+struct VLAN_Prop_8021q {
+ int vlan_id;
+ char *parent;
+} ;
+
+/* HP vlan standard, TBD */
+struct VLAN_Prop_8021qbg {
+ int invalid;
+} ;
+
+/* Cisco and VMware vlan standard, TBD */
+struct VLAN_Prop_8021qbh {
+ int invalid;
+} ;
+
+struct VLAN_Prop {
+ VLANType vlan_type;
+ union {
+ struct VLAN_Prop_8021q prop_8021q;
+ struct VLAN_Prop_8021qbg prop_8021qbg;
+ struct VLAN_Prop_8021qbh prop_8021qbh;
+ } props;
+} ;
+
+/* EthIface is logical devices include eth ports and bridges */
+struct EthIface {
+ char *name;
+ char *dep_ifname; /* parent dev name */
+ char *attach_bridge; /* bridge the iface is attached to */
+ char *mac;
+ EthType eth_type;
+ struct Run_Prop run_prop;
+ struct Protocol_Prop protocol_prop;
+ /* optional properties */
+ struct BR_Prop *pbr_prop;
+ struct VLAN_Prop *pvlan_prop;
+} ;
+
+struct EthIfacesList {
+ struct EthIface *pifaces[MAX_IFACE_NUM];
+ int count;
+} ;
+
+void eth_iface_init(struct EthIface *piface);
+void eth_iface_add_br_prop(struct EthIface *piface);
+void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type);
+void eth_iface_uninit(struct EthIface *piface);
+
+void eth_ifaceslist_init(struct EthIfacesList *plist);
+void eth_ifaceslist_uninit(struct EthIfacesList *plist);
+/* ppiface must be allocated from heap and it is directly added to list,
+ to save code of struct duplication */
+int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface);
+/* returned pointer is direct reference to a member in plist */
+struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
+ char *name);
+
+void eth_iface_print(struct EthIface *piface);
+void eth_ifaceslist_print(struct EthIfacesList *plist);
+
+typedef int (*eth_iface_filter_func)(const struct EthIface *piface,
+ void *opaque);
+
+int eth_iface_filter_peths(const struct EthIface *piface, void *nouse);
+int eth_iface_filter_by_name(const struct EthIface *piface, void *name);
+
+int get_host_ifaces(struct EthIfacesList *plist,
+ eth_iface_filter_func filter_func, void *filter_opaque);
+
+int add_host_iface(struct EthIface *piface);
+int del_host_iface(struct EthIface *piface);
+int mod_host_iface(struct EthIface *piface);
+
+int connect_two_ifaces(struct EthIface *p1, struct EthIface *p2);
+int disconnect_two_ifaces(struct EthIface *p1, struct EthIface *p2);
+
+int change_state_host_iface(struct EthIface *piface, int state);
+
+char *get_host_iface_error_reason(int errno);
+
+#endif
diff --git a/libxkutil/network_parsing_test.c b/libxkutil/network_parsing_test.c
new file mode 100644
index 0000000..4531364
--- /dev/null
+++ b/libxkutil/network_parsing_test.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <time.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <libvirt/libvirt.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include "misc_util.h"
+#include "device_parsing.h"
+#include "network_parsing.h"
+
+static long print_and_ret_time_stamp(void)
+{
+ struct timeval tv;
+ long ret;
+ gettimeofday(&tv, NULL);
+ ret = tv.tv_sec*1000 + tv.tv_usec/1000;
+ CU_DEBUG("time is [%ld] ms.", ret);
+ return ret;
+}
+
+static void check_iface_state(struct EthIface *piface, int expect_state)
+{
+ struct EthIfacesList list;
+ struct EthIface *piface_search;
+
+ eth_ifaceslist_init(&list);
+ get_host_ifaces(&list, NULL, NULL);
+ piface_search = eth_ifaceslist_search(&list, piface->name);
+ if (piface_search != NULL) {
+ if (expect_state == 1) {
+ CU_DEBUG("piface exist, result is:\n");
+ eth_iface_print(piface_search);
+ } else {
+ CU_DEBUG("Error!! piface %s still exist.", piface->name);
+ exit(1);
+ }
+ } else {
+ if (expect_state == 1) {
+ CU_DEBUG("Error!! piface %s do not exist.", piface->name);
+ exit(1);
+ } else {
+ CU_DEBUG("piface %s not exist.", piface->name);
+ }
+ }
+ eth_ifaceslist_uninit(&list);
+}
+
+/* It is a simple test case, autocheck only covers if device exist, other
+ properties need to be checked manually, otherwise more code need to be
+ introduced about property comparation. Output of eth_iface_print() in
+ function check_iface_state() could be used to check the properties. */
+int main(int argc, char **argv)
+{
+ libvirt_cim_init();
+ struct EthIfacesList *plist = NULL;
+ long start_time, end_time;
+ struct EthIface *piface_vlan, *piface_br;
+
+ CU_MALLOC(plist, sizeof(struct EthIfacesList));
+ eth_ifaceslist_init(plist);
+
+ /* test listing the pifaces */
+ start_time = print_and_ret_time_stamp();
+ get_host_ifaces(plist, NULL, NULL);
+ end_time = print_and_ret_time_stamp();
+ CU_DEBUG("cost [%d]ms in discovering host network. Result:\n"
+ "--------------------------------------------------",
+ end_time - start_time);
+ eth_ifaceslist_print(plist);
+ CU_DEBUG("---------------------------------------------");
+ eth_ifaceslist_uninit(plist);
+
+ /* test 802.1.q vlan */
+ CU_MALLOC(piface_vlan, sizeof(struct EthIface));
+ eth_iface_init(piface_vlan);
+ eth_iface_add_vlan_prop(piface_vlan, VLAN_TYPE_802_1_Q);
+
+ piface_vlan->name = CU_STRDUP("eth0.100");
+ piface_vlan->dep_ifname = CU_STRDUP("eth0");
+ piface_vlan->eth_type = ETH_TYPE_ETHER_VLAN;
+ piface_vlan->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
+ piface_vlan->protocol_prop.ipv4_prop.DHCP = 1;
+ piface_vlan->pvlan_prop->vlan_type = VLAN_TYPE_802_1_Q;
+ piface_vlan->pvlan_prop->props.prop_8021q.vlan_id = 100;
+ piface_vlan->pvlan_prop->props.prop_8021q.parent = CU_STRDUP("eth0");
+ CU_DEBUG("********Adding vlan.");
+ add_host_iface(piface_vlan);
+ check_iface_state(piface_vlan, 1);
+
+ eth_iface_uninit(piface_vlan);
+ eth_iface_init(piface_vlan);
+ piface_vlan->name = CU_STRDUP("eth0.100");
+ piface_vlan->protocol_prop.ipv4_prop.DHCP = 0;
+ piface_vlan->run_prop.boot_mode = BOOT_MODE_NONE;
+ CU_DEBUG("********Modifying vlan.");
+ mod_host_iface(piface_vlan);
+ check_iface_state(piface_vlan, 1);
+
+ /* test bridge */
+ CU_MALLOC(piface_br, sizeof(struct EthIface));
+ eth_iface_init(piface_br);
+ eth_iface_add_br_prop(piface_br);
+ piface_br->name = CU_STRDUP("testbr0");
+ piface_br->eth_type = ETH_TYPE_ETHER_BRIDGE;
+ piface_br->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
+ piface_br->protocol_prop.ipv4_prop.DHCP = 0;
+ piface_br->pbr_prop->STP = 1;
+ piface_br->pbr_prop->delay = 20;
+ CU_DEBUG("********Adding bridge.");
+ add_host_iface(piface_br);
+ check_iface_state(piface_br, 1);
+
+ eth_iface_uninit(piface_br);
+ eth_iface_init(piface_br);
+ eth_iface_add_br_prop(piface_br);
+ piface_br->name = CU_STRDUP("testbr0");
+ piface_br->pbr_prop->STP = 0;
+ piface_br->pbr_prop->delay = 0;
+ CU_DEBUG("********Modifying bridge.");
+ mod_host_iface(piface_br);
+ check_iface_state(piface_br, 1);
+
+ /* test connection */
+ CU_DEBUG("********Connect bridge.");
+ connect_two_ifaces(piface_br, piface_vlan);
+ check_iface_state(piface_br, 1);
+
+ CU_DEBUG("********Disconnect bridge.");
+ disconnect_two_ifaces(piface_br, piface_vlan);
+ check_iface_state(piface_br, 1);
+ check_iface_state(piface_vlan, 1);
+
+ /* test activation */
+ CU_DEBUG("********Activate bridge and vlan");
+ change_state_host_iface(piface_br, 1);
+ change_state_host_iface(piface_vlan, 1);
+ check_iface_state(piface_br, 1);
+ check_iface_state(piface_vlan, 1);
+
+ CU_DEBUG("********Deactivate bridge and vlan");
+ change_state_host_iface(piface_br, 0);
+ change_state_host_iface(piface_vlan, 0);
+ check_iface_state(piface_br, 1);
+ check_iface_state(piface_vlan, 1);
+
+ /* delete them */
+ CU_DEBUG("********Deleting vlan.");
+ del_host_iface(piface_vlan);
+ check_iface_state(piface_vlan, 0);
+ eth_iface_uninit(piface_vlan);
+
+ CU_DEBUG("********Deleting bridge.");
+ del_host_iface(piface_br);
+ check_iface_state(piface_br, 0);
+ eth_iface_uninit(piface_br);
+
+ CU_FREE(piface_br);
+ CU_FREE(piface_vlan);
+ CU_FREE(plist);
+ return 0;
+}
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
index 5c16ebe..23d6cc5 100644
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -36,8 +36,6 @@
#include "cmpimacs.h"
#endif
-#define XML_ERROR "Failed to allocate XML memory"
-
typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo);
typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool);
typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res);
@@ -831,7 +829,7 @@ static char *features_xml(xmlNodePtr root, struct domain *domain)
return NULL;
}
-static char *tree_to_xml(xmlNodePtr root)
+char *tree_to_xml(xmlNodePtr root)
{
xmlBufferPtr buffer = NULL;
xmlSaveCtxtPtr savectx = NULL;
diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h
index 743fc82..9c88986 100644
--- a/libxkutil/xmlgen.h
+++ b/libxkutil/xmlgen.h
@@ -27,11 +27,15 @@
#include "cmpidt.h"
+#define XML_ERROR "Failed to allocate XML memory"
+
struct kv {
const char *key;
const char *val;
};
+char *tree_to_xml(xmlNodePtr root);
+
char *system_to_xml(struct domain *dominfo);
char *device_to_xml(struct virt_device *dev);
--
1.7.1
12 years, 10 months
[PATCH V7 0/7] vlan 802.1.q extention
by Wenchao Xia
These patches add vlan extention of host network. Many code are used to
build up the network model, which is very similar to ComputerSystem.
Patch 1 contains function library codes and C test program.
From Patch 2 to 6, it is almost readonly codes, except VESS state change.
Patch 7 are CIM model codes of writing network configuration.
Limit:
Now only DHCP on/off are supported about IP settings, mannually setting of
address and netmask are not considered.
v7: added portion of code about writing.
v6: added CIM model for readonly usage. Code changes according to comments.
v5: switched to libvirt API about to enable readonly library.
v4: using netlink 1.0 as implemention to avoid runtime errors.
v3: using netlink 3.0 and libbridge as implemention.
v2: code fix and bug fix.
v1: using string parsing and direct accessing with host configuration file,
which require some utilities installed, such as IP, VCONFIG.
git repository:
git://gitorious.org/libvirt-cim_develop/libvirt-cim_develop.git
branch vlan_v7
Wenchao Xia (7):
vlan extention - function libarary
vlan extention - CIM Model - helper and Makefile
vlan extention - CIM Model - VESS
vlan extention - CIM Model - VESSSD
vlan extention - CIM Model - EthernetPort
vlan extention - CIM Model - EASD
vlan extention - CIM Model - VESSMS
Makefile.am | 16 +-
libxkutil/Makefile.am | 14 +-
libxkutil/misc_util.c | 48 +
libxkutil/misc_util.h | 3 +
libxkutil/network_model_helper.c | 473 +++++++
libxkutil/network_model_helper.h | 101 ++
libxkutil/network_parsing.c | 1309 ++++++++++++++++++++
libxkutil/network_parsing.h | 217 ++++
libxkutil/network_parsing_test.c | 184 +++
libxkutil/xmlgen.c | 4 +-
libxkutil/xmlgen.h | 4 +
schema/EthernetPort.mof | 4 +
schema/EthernetPort.registration | 3 +
schema/EthernetPortAllocationSettingData.mof | 22 +
.../EthernetPortAllocationSettingData.registration | 3 +
schema/VirtualEthernetSwitchSystem.mof | 10 +
schema/VirtualEthernetSwitchSystem.registration | 3 +
...irtualEthernetSwitchSystemManagementService.mof | 14 +
...ernetSwitchSystemManagementService.registration | 3 +
schema/VirtualEthernetSwitchSystemSettingData.mof | 33 +
...ualEthernetSwitchSystemSettingData.registration | 3 +
src/Makefile.am | 29 +-
src/Virt_EASD.c | 711 +++++++++++
src/Virt_EASD.h | 59 +
src/Virt_EthernetPort.c | 561 +++++++++
src/Virt_EthernetPort.h | 58 +
src/Virt_HostSystem.c | 2 +-
src/Virt_HostSystem.h | 2 +
src/Virt_VESSSD.c | 392 ++++++
src/Virt_VESSSD.h | 39 +
src/Virt_VirtualEthernetSwitchSystem.c | 477 +++++++
src/Virt_VirtualEthernetSwitchSystem.h | 52 +
..._VirtualEthernetSwitchSystemManagementService.c | 1289 +++++++++++++++++++
..._VirtualEthernetSwitchSystemManagementService.h | 31 +
src/Virt_VirtualSystemManagementService.c | 2 +-
src/Virt_VirtualSystemManagementService.h | 4 +
36 files changed, 6167 insertions(+), 12 deletions(-)
create mode 100644 libxkutil/network_model_helper.c
create mode 100644 libxkutil/network_model_helper.h
create mode 100644 libxkutil/network_parsing.c
create mode 100644 libxkutil/network_parsing.h
create mode 100644 libxkutil/network_parsing_test.c
create mode 100644 schema/EthernetPort.mof
create mode 100644 schema/EthernetPort.registration
create mode 100644 schema/EthernetPortAllocationSettingData.mof
create mode 100644 schema/EthernetPortAllocationSettingData.registration
create mode 100644 schema/VirtualEthernetSwitchSystem.mof
create mode 100644 schema/VirtualEthernetSwitchSystem.registration
create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.mof
create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.registration
create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.mof
create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.registration
create mode 100644 src/Virt_EASD.c
create mode 100644 src/Virt_EASD.h
create mode 100644 src/Virt_EthernetPort.c
create mode 100644 src/Virt_EthernetPort.h
create mode 100644 src/Virt_VESSSD.c
create mode 100644 src/Virt_VESSSD.h
create mode 100644 src/Virt_VirtualEthernetSwitchSystem.c
create mode 100644 src/Virt_VirtualEthernetSwitchSystem.h
create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.c
create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.h
12 years, 10 months
Release of libvirt-cim-0.6.1
by Chip Vincent
I'm happy announce the release of libvirt-cim-0.6.1.
The new release is available at:
ftp://libvirt.org/libvirt-cim/libvirt-cim-0.6.1.tar.gz
libvirt-cim-0.6.1:
* ACL: Use linked list helper for filter refs (Eduardo Lima (Etrunko))
* CSI: Use list helper implementation (Eduardo Lima (Etrunko))
* libxkutil: Linked list helper (Eduardo Lima (Etrunko))
* FilterEntry: Accept protocol id string values (Eduardo Lima (Etrunko))
* FilterEntry: Update action property (Eduardo Lima (Etrunko))
* FilterList: Add 'Priority' property (Eduardo Lima (Etrunko))
* FilterEntry: Change 'Priority' property type (Eduardo Lima (Etrunko))
* Fix AppliedFilterList creation and deletion (Chip Vincent)
* autoconfiscate.sh: Use proper command for revision count (Eduardo Lima (Etr
* libxkutil: Fix possible NULL dereferences (Eduardo Lima (Etrunko))
* Fix possible use of unitialized variables (Eduardo Lima (Etrunko))
* xml_parse_test: Fix invalid dereference (Eduardo Lima (Etrunko))
* Fix possible memory leaks (Eduardo Lima (Etrunko))
* Fix a problem with multi-arch (Daniel Veillard)
* Remove compilation warnings (Eduardo Lima (Etrunko))
* VirtualSystemManagementService: Remove dead code (Eduardo Lima (Etrunko))
--
Chip Vincent
Open Virtualization
IBM Linux Technology Center
cvincent(a)linux.vnet.ibm.com
12 years, 10 months
[PATCH v6 0/3] Implementation of a linked list helper
by Eduardo Lima (Etrunko)
From: "Eduardo Lima (Etrunko)" <eblima(a)br.ibm.com>
This series provides a generic linked list implementation for libxkutil that is
based on the one originally developed for the libvirt domain events support
recently integrated upstream.
As test case I ported the ComputerSystemIndication provider code to use this
list implementation. In the near future it will be also used by the event loop
that I am currently working on to allow systems with libvirt older than 0.9.0
to make use of the same feature.
Other possible use cases would be to port the code of libxkutil/*_parsing* to
also use the list implementation instead of static arrays.
Changes from v5:
- Fix possible NULL dereference in list_first()
Changes from v4:
- Fix possible NULL dereference in list_last_node()
- Fix possible leak in acl_parsing.c
Changes from v3:
- Fix crashes in list_free(), list_first_node() and list_count()
- Include patch that ports the acl filter ref code to use the linked list
implementation
Changes from v2:
- Make list struct private
Changes from v1:
- Fix version iformation in Makefile.am
Eduardo Lima (Etrunko) (3):
libxkutil: Linked list helper
CSI: Use list helper implementation
ACL: Use linked list helper for filter refs
libxkutil/Makefile.am | 51 +++++--
libxkutil/acl_parsing.c | 58 +++------
libxkutil/acl_parsing.h | 5 +-
libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++
libxkutil/list_util.h | 73 ++++++++++
libxkutil/xmlgen.c | 30 +++-
src/Virt_ComputerSystemIndication.c | 95 ++++----------
src/Virt_NestedFilterList.c | 73 ++++++-----
8 files changed, 472 insertions(+), 167 deletions(-)
create mode 100644 libxkutil/list_util.c
create mode 100644 libxkutil/list_util.h
--
1.7.7.6
12 years, 11 months