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