[Libvirt-cim] [PATCH] Add write support for FilterList and NestedFilterList
Chip Vincent
cvincent at linux.vnet.ibm.com
Tue Jun 28 14:26:19 UTC 2011
Disregard.. Found some issues. Will post a version shortly.
On 06/27/2011 06:35 PM, Chip Vincent wrote:
> # HG changeset patch
> # User Chip Vincent<cvincent at us.ibm.com>
> # Date 1309213800 14400
> # Node ID 03e3f95547078be19d8d22cac83ce38daf7510b9
> # Parent 75411f53df02159c3fa6ce5810c9446579e3d66d
> Add write support for FilterList and NestedFilterList
>
> This allows clients to create new filter lists and then associate them
> with other filter lists to create complex filters. This patch also has some
> minor bug fixes to AppliedFilterList so the new filters can be applied
> to existing NetworkPort instances. The new cimtests for the create/delete
> associations are still under construction, but you can easily test
> FilterList create/delete (foundation) with the following commands:
>
> # wbemcli ci 'http://localhost:5988/root/virt:KVM_FilterList.CreationClassName="",Name="",SystemCreationClassName="",SystemName=""' 'Name="test"'
>
> # wbemcli di 'http://localhost:5988/root/virt:KVM_FilterList.CreationClassName="KVM_FilterList",Name="test",SystemCreationClassName="KVM_HostSystem",SystemName="oc0840652111.ibm.com"'
>
> Signed-off-by: Chip Vincent<cvincent at us.ibm.com>
>
> diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c
> --- a/libxkutil/acl_parsing.c
> +++ b/libxkutil/acl_parsing.c
> @@ -551,6 +551,57 @@
> #endif
> }
>
> +int create_filter(virConnectPtr conn, struct acl_filter *filter)
> +{
> + virNWFilterPtr vfilter = NULL;
> + char *xml = NULL;
> +
> + if (filter == NULL)
> + return 0;
> +
> + xml = filter_to_xml(filter);
> + if (xml == NULL)
> + return 0;
> +
> + vfilter = virNWFilterDefineXML(conn, xml);
> +
> + free(xml);
> +
> + if (vfilter == NULL)
> + return 0;
> +
> + virNWFilterFree(vfilter);
> +
> + return 1;
> +}
> +
> +int update_filter(virConnectPtr conn, struct acl_filter *filter)
> +{
> + if (delete_filter(conn, filter) == 0 ||
> + create_filter(conn, filter) == 0)
> + return 0;
> +
> + return 1;
> +}
> +
> +int delete_filter(virConnectPtr conn, struct acl_filter *filter)
> +{
> + virNWFilterPtr vfilter = NULL;
> +
> + if (filter == NULL)
> + return 0;
> +
> + vfilter = virNWFilterLookupByUUIDString(conn, filter->uuid);
> + if (vfilter == NULL)
> + return 0;
> +
> + if (virNWFilterUndefine(vfilter) != 0) {
> + virNWFilterFree(vfilter);
> + return 0;
> + }
> +
> + return 1;
> +}
>
> int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule)
> {
> @@ -605,6 +656,28 @@
> return 1;
> }
>
> +int remove_filter_ref(struct acl_filter *filter, const char *name)
> +{
> + int i;
> + char **old_refs = NULL;
> +
> + if ((filter == NULL) || (name == NULL))
> + return 0;
> +
> + /* TODO: called infrequently, but needs optimization */
> + old_refs = filter->refs;
> +
> + for (i = 0; i< filter->ref_ct; i++) {
> + if (STREQC(old_refs[i], name)) {
> + free(old_refs[i]);
> + }
> + else
> + append_filter_ref(filter, old_refs[i]);
> + }
> +
> + return 1;
> +}
> +
> char *make_rule_id(const char *filter, int index)
> {
> int ret;
> diff --git a/libxkutil/acl_parsing.h b/libxkutil/acl_parsing.h
> --- a/libxkutil/acl_parsing.h
> +++ b/libxkutil/acl_parsing.h
> @@ -194,11 +194,17 @@
> char *make_rule_id(const char *filter, int index);
> int parse_rule_id(const char *rule_id, char **filter, int *index);
>
> +int create_filter(virConnectPtr conn, struct acl_filter *filter);
> +int update_filter(virConnectPtr conn, struct acl_filter *filter);
> +int delete_filter(virConnectPtr conn, struct acl_filter *filter);
> +
> /** NOTE: Both append functions take parameters allocated by caller and
> * freed by cleanup_filter(s)
> */
> int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule);
> int append_filter_ref(struct acl_filter *filter, char *name);
> +int remove_filter_ref(struct acl_filter *filter, const char *name);
> +
> #endif
>
> /*
> diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
> --- a/libxkutil/xmlgen.c
> +++ b/libxkutil/xmlgen.c
> @@ -1360,6 +1360,59 @@
> return xml;
> }
>
> +char *filter_to_xml(struct acl_filter *filter)
> +{
> + char *msg = XML_ERROR;
> + char *xml = NULL;
> + xmlNodePtr root = NULL;
> + xmlNodePtr tmp = NULL;
> + int i;
> +
> + root = xmlNewNode(NULL, BAD_CAST "filter");
> + if (root == NULL)
> + goto out;
> +
> + if (xmlNewProp(root, BAD_CAST "name", BAD_CAST filter->name) == NULL)
> + goto out;
> +
> + if (filter->chain != NULL)
> + if (xmlNewProp(root, BAD_CAST "chain",
> + BAD_CAST filter->chain) == NULL)
> + goto out;
> +
> + if (filter->uuid != NULL) {
> + tmp = xmlNewChild(root, NULL, BAD_CAST "uuid", NULL);
> + if (xmlNewProp(tmp, NULL, BAD_CAST filter->uuid) == NULL)
> + goto out;
> + }
> +
> + for (i = 0; i< filter->ref_ct; i++) {
> + tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL);
> + if (xmlNewProp(tmp, BAD_CAST "filter",
> + BAD_CAST filter->refs[i]) == NULL)
> + goto out;
> + }
> +
> + /* TODO: Not yet supported
> + for (i = 0; i< filter->rule_ct; i++) {
> + msg = rule_to_xml(root, filter->rules[i]);
> + if (msg != NULL)
> + goto out;
> + }
> + */
> +
> + xml = tree_to_xml(root);
> + if (xml != NULL)
> + msg = NULL; /* no errors */
> +
> + out:
> + CU_DEBUG("Filter XML: %s", msg);
> +
> + xmlFreeNode(root);
> +
> + return xml;
> +}
> +
> /*
> * Local Variables:
> * mode: C
> diff --git a/schema/NestedFilterList.registration b/schema/NestedFilterList.registration
> --- a/schema/NestedFilterList.registration
> +++ b/schema/NestedFilterList.registration
> @@ -1,3 +1,3 @@
> # Copyright IBM Corp. 2011
> # Classname Namespace ProviderName ProviderModule ProviderTypes
> -KVM_NestedFilterList root/virt Virt_NestedFilterList Virt_NestedFilterList association
> +KVM_NestedFilterList root/virt Virt_NestedFilterList Virt_NestedFilterList instance association
> diff --git a/src/Virt_AppliedFilterList.c b/src/Virt_AppliedFilterList.c
> --- a/src/Virt_AppliedFilterList.c
> +++ b/src/Virt_AppliedFilterList.c
> @@ -411,10 +411,6 @@
> libvirt_cim_init(),
> handlers);
>
> -DEFAULT_GI();
> -DEFAULT_EIN();
> -DEFAULT_EI();
> -
> static CMPIStatus CreateInstance(
> CMPIInstanceMI *self,
> const CMPIContext *context,
> @@ -434,6 +430,8 @@
> virConnectPtr conn = NULL;
> virDomainPtr dom = NULL;
>
> + CU_DEBUG("Reference = %s", REF2STR(reference));
> +
> if (cu_get_ref_prop(instance, "Antecedent",
> &antecedent) != CMPI_RC_OK) {
> cu_statusf(_BROKER,&s,
> @@ -473,6 +471,8 @@
> goto out;
> }
>
> + CU_DEBUG("DeviceID = %s", device_name);
> +
> if (parse_fq_devid(device_name,&domain_name,&net_name) == 0) {
> CU_DEBUG("Failed to parse devid");
> goto out;
> @@ -492,7 +492,11 @@
> goto out;
> }
>
> - free(device->dev.net.filter_ref);
> + if (device->dev.net.filter_ref != NULL) {
> + free(device->dev.net.filter_ref);
> + device->dev.net.filter_ref = NULL;
> + }
> +
> device->dev.net.filter_ref = strdup(filter_name);
>
> if (update_device(dom, device) == 0) {
> @@ -502,10 +506,10 @@
> goto out;
> }
>
> + CU_DEBUG("CreateInstance complete");
> +
> out:
> - free((char *)filter_name);
> free(domain_name);
> - free((char *)device_name);
> free(net_name);
>
> cleanup_filter(filter);
> @@ -535,6 +539,8 @@
> virConnectPtr conn = NULL;
> virDomainPtr dom = NULL;
>
> + CU_DEBUG("Reference = %s", REF2STR(reference));
> +
> if (cu_get_ref_path(reference, "Antecedent",
> &antecedent) != CMPI_RC_OK) {
> cu_statusf(_BROKER,&s,
> @@ -574,6 +580,8 @@
> goto out;
> }
>
> + CU_DEBUG("DeviceID = %s", device_name);
> +
> if (parse_fq_devid(device_name,&domain_name,&net_name) == 0) {
> CU_DEBUG("Failed to parse devid");
> goto out;
> @@ -593,8 +601,10 @@
> goto out;
> }
>
> - free(device->dev.net.filter_ref);
> - device->dev.net.filter_ref = NULL;
> + if (device->dev.net.filter_ref != NULL) {
> + free(device->dev.net.filter_ref);
> + device->dev.net.filter_ref = NULL;
> + }
>
> if (update_device(dom, device) == 0) {
> cu_statusf(_BROKER,&s,
> @@ -603,10 +613,10 @@
> goto out;
> }
>
> + CU_DEBUG("CreateInstance complete");
> +
> out:
> - free((char *)filter_name);
> free(domain_name);
> - free((char *)device_name);
> free(net_name);
>
> cleanup_filter(filter);
> @@ -618,12 +628,15 @@
> return s;
> }
>
> +DEFAULT_GI();
> +DEFAULT_EIN();
> +DEFAULT_EI();
> DEFAULT_MI();
> DEFAULT_EQ();
> DEFAULT_INST_CLEANUP();
>
> STD_InstanceMIStub(,
> - Virt_AppliedFilterEntry,
> + Virt_AppliedFilterList,
> _BROKER,
> libvirt_cim_init());
>
> diff --git a/src/Virt_FilterList.c b/src/Virt_FilterList.c
> --- a/src/Virt_FilterList.c
> +++ b/src/Virt_FilterList.c
> @@ -81,6 +81,32 @@
> return inst;
> }
>
> +static struct acl_filter *convert_instance_to_filter(
> + const CMPIInstance *instance,
> + const CMPIContext *context,
> + CMPIStatus *s)
> +{
> + struct acl_filter *filter = NULL;
> + const char *name = NULL;
> +
> + if (cu_get_str_prop(instance, "Name",&name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER, s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Name property");
> + goto out;
> + }
> +
> + filter = malloc(sizeof(*filter));
> + if (filter == NULL)
> + goto out;
> +
> + memset(filter, 0, sizeof(*filter));
> + filter->name = strdup(name);
> +
> + out:
> + return filter;
> +}
> +
> CMPIStatus enum_filter_lists(const CMPIBroker *broker,
> const CMPIContext *context,
> const CMPIObjectPath *reference,
> @@ -230,9 +256,114 @@
> return s;
> }
>
> -DEFAULT_CI();
> +static CMPIStatus CreateInstance(
> + CMPIInstanceMI *self,
> + const CMPIContext *context,
> + const CMPIResult *results,
> + const CMPIObjectPath *reference,
> + const CMPIInstance *instance)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + const char *name = NULL;
> + struct acl_filter *filter = NULL;
> + CMPIInstance *_instance = NULL;
> + virConnectPtr conn = NULL;
> +
> + /**Get Name from instance rather than reference since keys
> + * are set by this provider, not the client.
> + */
> + if (cu_get_str_prop(instance, "Name",&name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Name property");
> + goto out;
> + }
> +
> + conn = connect_by_classname(_BROKER, CLASSNAME(reference),&s);
> + if (conn == NULL)
> + goto out;
> +
> + get_filter_by_name(conn, name,&filter);
> + if (filter != NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_ALREADY_EXISTS,
> + "Instance already exists");
> + goto out;
> + }
> +
> + filter = convert_instance_to_filter(instance, context,&s);
> + if (filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to convert instance to filter");
> + goto out;
> + }
> +
> + if (create_filter(conn, filter) == 0) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to create filter");
> + goto out;
> + }
> +
> + _instance = convert_filter_to_instance(filter,
> + _BROKER,
> + context,
> + reference,
> +&s);
> +
> + if(_instance != NULL)
> + cu_return_instance_name(results, _instance);
> +
> + CU_DEBUG("CreateInstance complete");
> +
> + out:
> + cleanup_filter(filter);
> + virConnectClose(conn);
> +
> + return s;
> +}
> +
> +static CMPIStatus DeleteInstance(
> + CMPIInstanceMI *self,
> + const CMPIContext *context,
> + const CMPIResult *results,
> + const CMPIObjectPath *reference)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + const char *name = NULL;
> + struct acl_filter *filter = NULL;
> + virConnectPtr conn = NULL;
> +
> + if (cu_get_str_path(reference, "Name",&name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_NOT_FOUND,
> + "Unable to get Name from reference");
> + goto out;
> + }
> +
> + conn = connect_by_classname(_BROKER, CLASSNAME(reference),&s);
> + if (conn == NULL)
> + goto out;
> +
> + get_filter_by_name(conn, name,&filter);
> + if (filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_NOT_FOUND,
> + "Instance does not exist");
> + goto out;
> + }
> +
> + delete_filter(conn, filter);
> +
> + out:
> + cleanup_filter(filter);
> + virConnectClose(conn);
> +
> + return s;
> +}
> +
> DEFAULT_MI();
> -DEFAULT_DI();
> DEFAULT_EQ();
> DEFAULT_INST_CLEANUP();
>
> diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c
> --- a/src/Virt_NestedFilterList.c
> +++ b/src/Virt_NestedFilterList.c
> @@ -38,6 +38,71 @@
>
> static const CMPIBroker *_BROKER;
>
> +/* TODO: Port to libcmpiutil/args_util.c */
> +/**
> + * Get a reference property of an instance
> + *
> + * @param inst The instance
> + * @param prop The property name
> + * @param reference A pointer to a CMPIObjectPath* that will be set
> + * if successful
> + * @returns
> + * - CMPI_RC_OK on success
> + * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
> + * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
> + * - CMPI_RC_OK otherwise
> + */
> +static CMPIrc cu_get_ref_prop(const CMPIInstance *instance,
> + const char *prop,
> + CMPIObjectPath **reference)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + CMPIData value;
> +
> + /* REQUIRE_PROPERY_DEFINED(instance, prop, value,&s); */
> + value = CMGetProperty(instance, prop,&s);
> + if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
> + return CMPI_RC_ERR_NO_SUCH_PROPERTY;
> +
> + if ((value.type != CMPI_ref) || CMIsNullObject(value.value.ref))
> + return CMPI_RC_ERR_TYPE_MISMATCH;
> +
> + *reference = value.value.ref;
> +
> + return CMPI_RC_OK;
> +}
> +
> +/* TODO: Port to libcmpiutil/args_util.c */
> +/**
> + * Get a reference component of an object path
> + *
> + * @param _reference The reference
> + * @param key The key name
> + * @param reference A pointer to a CMPIObjectPath* that will be set
> + * if successful
> + * @returns
> + * - CMPI_RC_OK on success
> + * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
> + * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
> + * - CMPI_RC_OK otherwise
> + */
> +static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
> + const char *key,
> + CMPIObjectPath **_reference)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + CMPIData value;
> +
> + /* REQUIRE_PROPERY_DEFINED(instance, prop, value,&s); */
> + value = CMGetKey(reference, key,&s);
> + if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
> + return CMPI_RC_ERR_NO_SUCH_PROPERTY;
> +
> + /* how to parse and object path? */
> +
> + return CMPI_RC_OK;
> +}
> +
> /**
> * given a filter, find all *direct* filter_refs
> */
> @@ -224,6 +289,203 @@
> libvirt_cim_init(),
> handlers);
>
> +DEFAULT_GI();
> +DEFAULT_EIN();
> +DEFAULT_EI();
> +
> +static CMPIStatus CreateInstance(
> + CMPIInstanceMI *self,
> + const CMPIContext *context,
> + const CMPIResult *results,
> + const CMPIObjectPath *reference,
> + const CMPIInstance *instance)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + CMPIObjectPath *antecedent = NULL;
> + const char *parent_name = NULL;
> + struct acl_filter *parent_filter = NULL;
> + CMPIObjectPath *dependent = NULL;
> + const char *child_name = NULL;
> + struct acl_filter *child_filter = NULL;
> + virConnectPtr conn = NULL;
> +
> + CU_DEBUG("Reference = %s", REF2STR(reference));
> +
> + conn = connect_by_classname(_BROKER, CLASSNAME(reference),&s);
> + if (conn == NULL)
> + goto out;
> +
> + if (cu_get_ref_prop(instance, "Antecedent",
> +&antecedent) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Antecedent property");
> + goto out;
> + }
> +
> + if (cu_get_str_path(reference, "Name",&parent_name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Antecedent.Name property");
> + goto out;
> + }
> +
> + get_filter_by_name(conn, parent_name,&parent_filter);
> + if (parent_filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Antecedent.Name object does not exist");
> + goto out;
> + }
> +
> + if (cu_get_ref_prop(instance, "Dependent",
> +&dependent) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Dependent property");
> + goto out;
> + }
> +
> + if (cu_get_str_path(reference, "Name",&child_name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Dependent.Name property");
> + goto out;
> + }
> +
> + get_filter_by_name(conn, child_name,&child_filter);
> + if (child_filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Dependent.Name object does not exist");
> + goto out;
> + }
> +
> + if (append_filter_ref(parent_filter, strdup(child_name)) == 0) {
> + free(dup);
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to append filter reference");
> + goto out;
> + }
> +
> + if (update_filter(conn, parent_filter) == 0) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to update filter");
> + goto out;
> + }
> +
> + CU_DEBUG("CreateInstance completed");
> +
> + out:
> + cleanup_filter(parent_filter);
> + cleanup_filter(child_filter);
> + virConnectClose(conn);
> +
> + return s;
> +}
> +
> +static CMPIStatus DeleteInstance(
> + CMPIInstanceMI *self,
> + const CMPIContext *context,
> + const CMPIResult *results,
> + const CMPIObjectPath *reference)
> +{
> + CMPIStatus s = {CMPI_RC_OK, NULL};
> + CMPIObjectPath *antecedent = NULL;
> + const char *parent_name = NULL;
> + struct acl_filter *parent_filter = NULL;
> + CMPIObjectPath *dependent = NULL;
> + const char *child_name = NULL;
> + struct acl_filter *child_filter = NULL;
> + virConnectPtr conn = NULL;
> +
> + CU_DEBUG("Reference = %s", REF2STR(reference));
> +
> + conn = connect_by_classname(_BROKER, CLASSNAME(reference),&s);
> + if (conn == NULL)
> + goto out;
> +
> + if (cu_get_ref_path(reference, "Antecedent",
> +&antecedent) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Antecedent property");
> + goto out;
> + }
> +
> + if (cu_get_str_path(reference, "Name",&parent_name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Antecedent.Name property");
> + goto out;
> + }
> +
> + get_filter_by_name(conn, parent_name,&parent_filter);
> + if (parent_filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Antecedent.Name object does not exist");
> + goto out;
> + }
> +
> + if (cu_get_ref_path(reference, "Dependent",
> +&dependent) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Dependent property");
> + goto out;
> + }
> +
> + if (cu_get_str_path(reference, "Name",&child_name) != CMPI_RC_OK) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Unable to get Dependent.Name property");
> + goto out;
> + }
> +
> + get_filter_by_name(conn, child_name,&child_filter);
> + if (child_filter == NULL) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Dependent.Name object does not exist");
> + goto out;
> + }
> +
> + if (remove_filter_ref(parent_filter, child_name) == 0) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to remove filter reference");
> + goto out;
> + }
> +
> + if (update_filter(conn, parent_filter) == 0) {
> + cu_statusf(_BROKER,&s,
> + CMPI_RC_ERR_FAILED,
> + "Failed to update filter");
> + goto out;
> + }
> +
> + CU_DEBUG("CreateInstance completed");
> +
> + out:
> + cleanup_filter(parent_filter);
> + cleanup_filter(child_filter);
> + virConnectClose(conn);
> +
> + return s;
> +}
> +
> +DEFAULT_MI();
> +DEFAULT_EQ();
> +DEFAULT_INST_CLEANUP();
> +
> +STD_InstanceMIStub(,
> + Virt_NestedFilterList,
> + _BROKER,
> + libvirt_cim_init());
> +
> /*
> * Local Variables:
> * mode: C
>
> _______________________________________________
> Libvirt-cim mailing list
> Libvirt-cim at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim
--
Chip Vincent
Open Virtualization
IBM Linux Technology Center
cvincent at linux.vnet.ibm.com
More information about the Libvirt-cim
mailing list