+ const char *domname = virDomainGetName(dom);
+ if (domname == NULL) {
+ VIRT_ERROR(conn, "virDomainGetName");
+ continue;
+ }
+
+ virDomainInfo info;
+ int status = virDomainGetInfo(dom, &info);
+ if (status != 0) {
+ ERROR(PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.",
+ status);
+ continue;
+ }
+
+ if (info.state != VIR_DOMAIN_RUNNING) {
+ DEBUG(PLUGIN_NAME " plugin: skipping inactive domain %s", domname);
+ continue;
+ }
+
+ /* Get a list of devices for this domain. */
+ xmlDocPtr xml_doc = NULL;
+ xmlXPathContextPtr xpath_ctx = NULL;
+
+ char *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);
+
+ char tag[PARTITION_TAG_MAX_LEN] = {'\0'};
+ if (lv_domain_get_tag(xpath_ctx, domname, tag) < 0) {
+ ERROR(PLUGIN_NAME " plugin: lv_domain_get_tag failed.");
+ goto cont;
+ }
+
+ if (!lv_instance_include_domain(inst, domname, tag))
+ goto cont;
+
+ /* Block devices. */
+ if (report_block_devices)
+ lv_add_block_devices(state, dom, domname, xpath_ctx);
+
+ /* Network interfaces. */
+ if (report_network_interfaces)
+ lv_add_network_interfaces(state, dom, domname, xpath_ctx);
+
+ cont:
+ if (xpath_ctx)
+ xmlXPathFreeContext(xpath_ctx);
+ if (xml_doc)
+ xmlFreeDoc(xml_doc);
+ sfree(xml);
+ }
+
+#ifdef HAVE_LIST_ALL_DOMAINS
+ /* NOTE: domains_active and domains_inactive data will be cleared during
+ refresh of all domains (inside lv_clean_read_state function) so we need
+ to free here only allocated arrays */
+ sfree(domains);
+ sfree(domains_inactive);
+#else
+ sfree(domids);
+
+end:
+#endif
+
+ DEBUG(PLUGIN_NAME " plugin#%s: refreshing"
+ " domains=%i block_devices=%i iface_devices=%i",
+ inst->tag, state->nr_domains, state->nr_block_devices,
+ state->nr_interface_devices);
+
+ return 0;
+}
+
+static void free_domains(struct lv_read_state *state) {
+ if (state->domains) {
+ for (int i = 0; i < state->nr_domains; ++i)
+ virDomainFree(state->domains[i].ptr);
+ sfree(state->domains);
+ }
+ state->domains = NULL;
+ state->nr_domains = 0;
+}
+
+static int add_domain(struct lv_read_state *state, virDomainPtr dom,
+ bool active) {
+ int new_size = sizeof(state->domains[0]) * (state->nr_domains + 1);
+
+ domain_t *new_ptr = realloc(state->domains, new_size);
+ if (new_ptr == NULL) {
+ ERROR(PLUGIN_NAME " plugin: realloc failed in add_domain()");
+ return -1;
+ }
+
+ state->domains = new_ptr;
+ state->domains[state->nr_domains].ptr = dom;
+ state->domains[state->nr_domains].active = active;
+ memset(&state->domains[state->nr_domains].info, 0,
+ sizeof(state->domains[state->nr_domains].info));
+
+ return state->nr_domains++;
+}
+
+static void free_block_devices(struct lv_read_state *state) {
+ if (state->block_devices) {
+ for (int i = 0; i < state->nr_block_devices; ++i)
+ sfree(state->block_devices[i].path);
+ sfree(state->block_devices);
+ }
+ state->block_devices = NULL;
+ state->nr_block_devices = 0;
+}
+
+static int add_block_device(struct lv_read_state *state, virDomainPtr dom,
+ const char *path, bool has_source) {
+
+ char *path_copy = strdup(path);
+ if (!path_copy)
+ return -1;
+
+ int new_size =
+ sizeof(state->block_devices[0]) * (state->nr_block_devices + 1);
+
+ struct block_device *new_ptr = realloc(state->block_devices, new_size);
+ if (new_ptr == NULL) {
+ sfree(path_copy);
+ return -1;
+ }
+ state->block_devices = new_ptr;
+ state->block_devices[state->nr_block_devices].dom = dom;
+ state->block_devices[state->nr_block_devices].path = path_copy;
+ state->block_devices[state->nr_block_devices].has_source = has_source;
+ return state->nr_block_devices++;
+}
+
+static void free_interface_devices(struct lv_read_state *state) {
+ if (state->interface_devices) {
+ for (int i = 0; i < state->nr_interface_devices; ++i) {
+ sfree(state->interface_devices[i].path);
+ sfree(state->interface_devices[i].address);
+ sfree(state->interface_devices[i].number);
+ }
+ sfree(state->interface_devices);
+ }
+ state->interface_devices = NULL;
+ state->nr_interface_devices = 0;
+}
+
+static int add_interface_device(struct lv_read_state *state, virDomainPtr dom,
+ const char *path, const char *address,
+ unsigned int number) {
+
+ if ((path == NULL) || (address == NULL))
+ return EINVAL;
+
+ char *path_copy = strdup(path);
+ if (!path_copy)
+ return -1;
+
+ char *address_copy = strdup(address);
+ if (!address_copy) {
+ sfree(path_copy);
+ return -1;
+ }
+
+ char number_string[21];
+ snprintf(number_string, sizeof(number_string), "interface-%u", number);
+ char *number_copy = strdup(number_string);
+ if (!number_copy) {
+ sfree(path_copy);
+ sfree(address_copy);
+ return -1;
+ }
+
+ int new_size =
+ sizeof(state->interface_devices[0]) * (state->nr_interface_devices + 1);
+
+ struct interface_device *new_ptr =
+ realloc(state->interface_devices, new_size);
+ if (new_ptr == NULL) {
+ sfree(path_copy);
+ sfree(address_copy);
+ sfree(number_copy);
+ return -1;
+ }
+
+ state->interface_devices = new_ptr;
+ state->interface_devices[state->nr_interface_devices].dom = dom;
+ state->interface_devices[state->nr_interface_devices].path = path_copy;
+ state->interface_devices[state->nr_interface_devices].address = address_copy;
+ state->interface_devices[state->nr_interface_devices].number = number_copy;
+ return state->nr_interface_devices++;
+}
+
+static int ignore_device_match(ignorelist_t *il, const char *domname,
+ const char *devpath) {
+ if ((domname == NULL) || (devpath == NULL))
+ return 0;
+
+ size_t n = strlen(domname) + strlen(devpath) + 2;
+ char *name = malloc(n);
+ if (name == NULL) {
+ ERROR(PLUGIN_NAME " plugin: malloc failed.");