- free_block_devices ();
- free_interface_devices ();
- free_domains ();
-
- /* Fetch each domain and add it to the list, unless ignore. */
- for (i = 0; i < n; ++i) {
- virDomainPtr dom = NULL;
- const char *name;
- char *xml = NULL;
- xmlDocPtr xml_doc = NULL;
- xmlXPathContextPtr xpath_ctx = NULL;
- xmlXPathObjectPtr xpath_obj = NULL;
- int j;
-
- dom = virDomainLookupByID (conn, domids[i]);
- if (dom == NULL) {
- VIRT_ERROR (conn, "virDomainLookupByID");
- /* Could be that the domain went away -- ignore it anyway. */
- continue;
- }
-
- name = virDomainGetName (dom);
- if (name == NULL) {
- VIRT_ERROR (conn, "virDomainGetName");
- goto cont;
- }
-
- if (il_domains && ignorelist_match (il_domains, name) != 0)
- goto cont;
-
- if (add_domain (dom) < 0) {
- ERROR (PLUGIN_NAME " plugin: malloc failed.");
- goto cont;
- }
-
- /* Get a list of devices for this domain. */
- xml = virDomainGetXMLDesc (dom, 0);
- if (!xml) {
- VIRT_ERROR (conn, "virDomainGetXMLDesc");
- goto cont;
- }
-
- /* Yuck, XML. Parse out the devices. */
- xml_doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, XML_PARSE_NONET);
- if (xml_doc == NULL) {
- VIRT_ERROR (conn, "xmlReadDoc");
- goto cont;
- }
-
- xpath_ctx = xmlXPathNewContext (xml_doc);
-
- /* Block devices. */
- xpath_obj = xmlXPathEval
- ((xmlChar *) "/domain/devices/disk/target[@dev]",
- xpath_ctx);
- if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET ||
- xpath_obj->nodesetval == NULL)
- goto cont;
-
- for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
- xmlNodePtr node;
- char *path = NULL;
-
- node = xpath_obj->nodesetval->nodeTab[j];
- if (!node) continue;
- path = (char *) xmlGetProp (node, (xmlChar *) "dev");
- if (!path) continue;
-
- if (il_block_devices &&
- ignore_device_match (il_block_devices, name, path) != 0)
- goto cont2;
-
- add_block_device (dom, path);
- cont2:
- if (path) xmlFree (path);
- }
- xmlXPathFreeObject (xpath_obj);
-
- /* Network interfaces. */
- xpath_obj = xmlXPathEval
- ((xmlChar *) "/domain/devices/interface[target[@dev]]",
- xpath_ctx);
- if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET ||
- xpath_obj->nodesetval == NULL)
- goto cont;
-
- xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
-
- for (j = 0; j < xml_interfaces->nodeNr; ++j) {
- char *path = NULL;
- char *address = NULL;
- xmlNodePtr xml_interface;
-
- xml_interface = xml_interfaces->nodeTab[j];
- if (!xml_interface) continue;
- xmlNodePtr child = NULL;
-
- for (child = xml_interface->children; child; child = child->next) {
- if (child->type != XML_ELEMENT_NODE) continue;
-
- if (xmlStrEqual(child->name, (const xmlChar *) "target")) {
- path = (char *) xmlGetProp (child, (const xmlChar *) "dev");
- if (!path) continue;
- } else if (xmlStrEqual(child->name, (const xmlChar *) "mac")) {
- address = (char *) xmlGetProp (child, (const xmlChar *) "address");
- if (!address) continue;
- }
- }
-
- if (il_interface_devices &&
- (ignore_device_match (il_interface_devices, name, path) != 0 ||
- ignore_device_match (il_interface_devices, name, address) != 0))
- goto cont3;
-
- add_interface_device (dom, path, address, j+1);
- cont3:
- if (path) xmlFree (path);
- if (address) xmlFree (address);
- }
-
- cont:
- if (xpath_obj) xmlXPathFreeObject (xpath_obj);
- if (xpath_ctx) xmlXPathFreeContext (xpath_ctx);
- if (xml_doc) xmlFreeDoc (xml_doc);
- sfree (xml);
- }
+/*
+ * returns 0 on success and <0 on error
+ */
+static int lv_domain_get_tag(xmlXPathContextPtr xpath_ctx, const char *dom_name,
+ char *dom_tag) {
+ char xpath_str[BUFFER_MAX_LEN] = {'\0'};
+ xmlXPathObjectPtr xpath_obj = NULL;
+ xmlNodePtr xml_node = NULL;
+ int ret = -1;
+ int err;
+
+ err = xmlXPathRegisterNs(xpath_ctx,
+ (const xmlChar *)METADATA_VM_PARTITION_PREFIX,
+ (const xmlChar *)METADATA_VM_PARTITION_URI);
+ if (err) {
+ ERROR(PLUGIN_NAME " plugin: xmlXpathRegisterNs(%s, %s) failed on domain %s",
+ METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_URI, dom_name);
+ goto done;
+ }
+
+ ssnprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
+ METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
+ xpath_obj = xmlXPathEvalExpression((xmlChar *)xpath_str, xpath_ctx);
+ if (xpath_obj == NULL) {
+ ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) failed on domain %s",
+ xpath_str, dom_name);
+ goto done;
+ }
+
+ if (xpath_obj->type != XPATH_NODESET) {
+ ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) unexpected return type %d "
+ "(wanted %d) on domain %s",
+ xpath_str, xpath_obj->type, XPATH_NODESET, dom_name);
+ goto done;
+ }
+
+ /*
+ * from now on there is no real error, it's ok if a domain
+ * doesn't have the metadata partition tag.
+ */
+ ret = 0;
+ if (xpath_obj->nodesetval == NULL || xpath_obj->nodesetval->nodeNr != 1) {
+ DEBUG(PLUGIN_NAME " plugin: xmlXPathEval(%s) return nodeset size=%i "
+ "expected=1 on domain %s",
+ xpath_str,
+ (xpath_obj->nodesetval == NULL) ? 0 : xpath_obj->nodesetval->nodeNr,
+ dom_name);
+ } else {
+ xml_node = xpath_obj->nodesetval->nodeTab[0];
+ sstrncpy(dom_tag, (const char *)xml_node->content, PARTITION_TAG_MAX_LEN);
+ }
+
+done:
+ /* deregister to clean up */
+ err = xmlXPathRegisterNs(xpath_ctx,
+ (const xmlChar *)METADATA_VM_PARTITION_PREFIX, NULL);
+ if (err) {
+ /* we can't really recover here */
+ ERROR(PLUGIN_NAME
+ " plugin: deregistration of namespace %s failed for domain %s",
+ METADATA_VM_PARTITION_PREFIX, dom_name);
+ }
+ if (xpath_obj)
+ xmlXPathFreeObject(xpath_obj);
+
+ return ret;
+}
+
+static int is_known_tag(const char *dom_tag) {
+ for (int i = 0; i < nr_instances; ++i)
+ if (!strcmp(dom_tag, lv_read_user_data[i].inst.tag))
+ return 1;
+ return 0;
+}