+static void lv_add_block_devices(struct lv_read_state *state, virDomainPtr dom,
+ const char *domname,
+ xmlXPathContextPtr xpath_ctx) {
+ xmlXPathObjectPtr xpath_obj =
+ xmlXPathEval((const xmlChar *)"/domain/devices/disk", xpath_ctx);
+
+ if (xpath_obj == NULL) {
+ DEBUG(PLUGIN_NAME " plugin: no disk xpath-object found for domain %s",
+ domname);
+ return;
+ }
+
+ if (xpath_obj->type != XPATH_NODESET || xpath_obj->nodesetval == NULL) {
+ DEBUG(PLUGIN_NAME " plugin: no disk node found for domain %s", domname);
+ goto cleanup;
+ }
+
+ xmlNodeSetPtr xml_block_devices = xpath_obj->nodesetval;
+ for (int i = 0; i < xml_block_devices->nodeNr; ++i) {
+ xmlNodePtr xml_device = xpath_obj->nodesetval->nodeTab[i];
+ char *path_str = NULL;
+ char *source_str = NULL;
+
+ if (!xml_device)
+ continue;
+
+ /* Fetching path and source for block device */
+ for (xmlNodePtr child = xml_device->children; child; child = child->next) {
+ if (child->type != XML_ELEMENT_NODE)
+ continue;
+
+ /* we are interested only in either "target" or "source" elements */
+ if (xmlStrEqual(child->name, (const xmlChar *)"target"))
+ path_str = (char *)xmlGetProp(child, (const xmlChar *)"dev");
+ else if (xmlStrEqual(child->name, (const xmlChar *)"source")) {
+ /* name of the source is located in "dev" or "file" element (it depends
+ * on type of source). Trying "dev" at first*/
+ source_str = (char *)xmlGetProp(child, (const xmlChar *)"dev");
+ if (!source_str)
+ source_str = (char *)xmlGetProp(child, (const xmlChar *)"file");
+ }
+ /* ignoring any other element*/
+ }
+
+ /* source_str will be interpreted as a device path if blockdevice_format
+ * param is set to 'source'. */
+ const char *device_path =
+ (blockdevice_format == source) ? source_str : path_str;
+
+ if (!device_path) {
+ /* no path found and we can't add block_device without it */
+ WARNING(PLUGIN_NAME " plugin: could not generate device path for disk in "
+ "domain %s - disk device will be ignored in reports",
+ domname);
+ goto cont;
+ }
+
+ if (ignore_device_match(il_block_devices, domname, device_path) == 0) {
+ /* we only have to store information whether 'source' exists or not */
+ bool has_source = (source_str != NULL) ? true : false;
+
+ add_block_device(state, dom, device_path, has_source);
+ }
+
+ cont:
+ if (path_str)
+ xmlFree(path_str);
+
+ if (source_str)
+ xmlFree(source_str);
+ }
+
+cleanup:
+ xmlXPathFreeObject(xpath_obj);
+}
+
+static void lv_add_network_interfaces(struct lv_read_state *state,
+ virDomainPtr dom, const char *domname,
+ xmlXPathContextPtr xpath_ctx) {
+ xmlXPathObjectPtr xpath_obj = xmlXPathEval(
+ (xmlChar *)"/domain/devices/interface[target[@dev]]", xpath_ctx);
+
+ if (xpath_obj == NULL)
+ return;
+
+ if (xpath_obj->type != XPATH_NODESET || xpath_obj->nodesetval == NULL) {
+ xmlXPathFreeObject(xpath_obj);
+ return;
+ }
+
+ xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
+
+ for (int j = 0; j < xml_interfaces->nodeNr; ++j) {
+ char *path = NULL;
+ char *address = NULL;
+
+ xmlNodePtr xml_interface = xml_interfaces->nodeTab[j];
+ if (!xml_interface)
+ continue;
+
+ for (xmlNodePtr 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 ((ignore_device_match(il_interface_devices, domname, path) == 0 &&
+ ignore_device_match(il_interface_devices, domname, address) == 0)) {
+ add_interface_device(state, dom, path, address, j + 1);
+ }
+
+ if (path)
+ xmlFree(path);
+ if (address)
+ xmlFree(address);
+ }
+ xmlXPathFreeObject(xpath_obj);
+}
+