From b3d9acd7091f9f48e1c35f7229c8fac405c75483 Mon Sep 17 00:00:00 2001 From: "Mozejko, MarcinX" Date: Mon, 6 Nov 2017 10:03:18 +0000 Subject: [PATCH] virt: Add domain state metrics dispatch MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Previously information about Virtual Machine domains state (e.g. VIR_DOMAIN_RUNNING, VIR_DOMAIN_PAUSED..) was not dispatched (e.g. file with domain states was not created by CSV plugin). Now current VM state information with corresponding reason is dispatched as ‘domain_state’. Change-Id: I781f11f53adb9ca0abcf6565d5717c6495f853b7 Signed-off-by: Mozejko, MarcinX --- src/virt.c | 347 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 194 insertions(+), 153 deletions(-) diff --git a/src/virt.c b/src/virt.c index 20336b41..1b70b22e 100644 --- a/src/virt.c +++ b/src/virt.c @@ -467,6 +467,7 @@ struct interface_device { typedef struct domain_s { virDomainPtr ptr; virDomainInfo info; + _Bool active; } domain_t; struct lv_read_state { @@ -482,7 +483,8 @@ struct lv_read_state { }; static void free_domains(struct lv_read_state *state); -static int add_domain(struct lv_read_state *state, virDomainPtr dom); +static int add_domain(struct lv_read_state *state, virDomainPtr dom, + _Bool active); static void free_block_devices(struct lv_read_state *state); static int add_block_device(struct lv_read_state *state, virDomainPtr dom, @@ -1416,6 +1418,15 @@ static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) { } #ifdef HAVE_DOM_REASON + +static void domain_state_submit(virDomainPtr dom, int state, int reason) { + value_t values[] = { + {.gauge = (gauge_t)state}, {.gauge = (gauge_t)reason}, + }; + + submit(dom, "domain_state", NULL, values, STATIC_ARRAY_SIZE(values)); +} + static int get_domain_state(virDomainPtr domain) { int domain_state = 0; int domain_reason = 0; @@ -1427,6 +1438,8 @@ static int get_domain_state(virDomainPtr domain) { return status; } + domain_state_submit(domain, domain_state, domain_reason); + return status; } @@ -1991,10 +2004,16 @@ static int lv_read(user_data_t *ud) { /* Get domains' metrics */ for (int i = 0; i < state->nr_domains; ++i) { - int status = get_domain_metrics(&state->domains[i]); + domain_t *dom = &state->domains[i]; + int status; + if (dom->active) + status = get_domain_metrics(dom); + else + status = get_domain_state(dom->ptr); + if (status != 0) ERROR(PLUGIN_NAME " failed to get metrics for domain=%s", - virDomainGetName(state->domains[i].ptr)); + virDomainGetName(dom->ptr)); } /* Get block device stats for each domain. */ @@ -2178,208 +2197,228 @@ static int refresh_lists(struct lv_read_instance *inst) { struct lv_read_state *state = &inst->read_state; int n; +#ifndef HAVE_LIST_ALL_DOMAINS n = virConnectNumOfDomains(conn); if (n < 0) { VIRT_ERROR(conn, "reading number of domains"); return -1; } +#endif lv_clean_read_state(state); - if (n > 0) { +#ifndef HAVE_LIST_ALL_DOMAINS + if (n == 0) + goto end; +#endif + #ifdef HAVE_LIST_ALL_DOMAINS - virDomainPtr *domains; - n = virConnectListAllDomains(conn, &domains, - VIR_CONNECT_LIST_DOMAINS_ACTIVE); + virDomainPtr *domains, *domains_inactive; + int m = virConnectListAllDomains(conn, &domains_inactive, + VIR_CONNECT_LIST_DOMAINS_INACTIVE); + n = virConnectListAllDomains(conn, &domains, + VIR_CONNECT_LIST_DOMAINS_ACTIVE); #else - int *domids; + int *domids; - /* Get list of domains. */ - domids = malloc(sizeof(*domids) * n); - if (domids == NULL) { - ERROR(PLUGIN_NAME " plugin: malloc failed."); - return -1; - } + /* Get list of domains. */ + domids = malloc(sizeof(*domids) * n); + if (domids == NULL) { + ERROR(PLUGIN_NAME " plugin: malloc failed."); + return -1; + } - n = virConnectListDomains(conn, domids, n); + n = virConnectListDomains(conn, domids, n); #endif - if (n < 0) { - VIRT_ERROR(conn, "reading list of domains"); + if (n < 0) { + VIRT_ERROR(conn, "reading list of domains"); #ifndef HAVE_LIST_ALL_DOMAINS - sfree(domids); + sfree(domids); +#else + sfree(domains_inactive); #endif - return -1; + return -1; + } + +#ifdef HAVE_LIST_ALL_DOMAINS + for (int i = 0; i < m; ++i) + if (add_domain(state, domains_inactive[i], 0) < 0) { + ERROR(PLUGIN_NAME " plugin: malloc failed."); + continue; } +#endif - /* Fetch each domain and add it to the list, unless ignore. */ - for (int i = 0; i < n; ++i) { - const char *name; - char *xml = NULL; - xmlDocPtr xml_doc = NULL; - xmlXPathContextPtr xpath_ctx = NULL; - xmlXPathObjectPtr xpath_obj = NULL; - char tag[PARTITION_TAG_MAX_LEN] = {'\0'}; - virDomainInfo info; - int status; + /* Fetch each domain and add it to the list, unless ignore. */ + for (int i = 0; i < n; ++i) { + const char *name; + char *xml = NULL; + xmlDocPtr xml_doc = NULL; + xmlXPathContextPtr xpath_ctx = NULL; + xmlXPathObjectPtr xpath_obj = NULL; + char tag[PARTITION_TAG_MAX_LEN] = {'\0'}; + virDomainInfo info; + int status; #ifdef HAVE_LIST_ALL_DOMAINS - virDomainPtr dom = domains[i]; + virDomainPtr dom = domains[i]; #else - virDomainPtr dom = NULL; - dom = virDomainLookupByID(conn, domids[i]); - if (dom == NULL) { - VIRT_ERROR(conn, "virDomainLookupByID"); - /* Could be that the domain went away -- ignore it anyway. */ - continue; - } + virDomainPtr dom = NULL; + dom = virDomainLookupByID(conn, domids[i]); + if (dom == NULL) { + VIRT_ERROR(conn, "virDomainLookupByID"); + /* Could be that the domain went away -- ignore it anyway. */ + continue; + } #endif - name = virDomainGetName(dom); - if (name == NULL) { - VIRT_ERROR(conn, "virDomainGetName"); - goto cont; - } + name = virDomainGetName(dom); + if (name == NULL) { + VIRT_ERROR(conn, "virDomainGetName"); + goto cont; + } - status = virDomainGetInfo(dom, &info); - if (status != 0) { - ERROR(PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", - status); - continue; - } + 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", name); - continue; - } + if (info.state != VIR_DOMAIN_RUNNING) { + DEBUG(PLUGIN_NAME " plugin: skipping inactive domain %s", name); + continue; + } - if (il_domains && ignorelist_match(il_domains, name) != 0) - goto cont; + if (il_domains && ignorelist_match(il_domains, name) != 0) + goto cont; - /* Get a list of devices for this domain. */ - xml = virDomainGetXMLDesc(dom, 0); - if (!xml) { - VIRT_ERROR(conn, "virDomainGetXMLDesc"); - 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; - } + /* 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); + xpath_ctx = xmlXPathNewContext(xml_doc); - if (lv_domain_get_tag(xpath_ctx, name, tag) < 0) { - ERROR(PLUGIN_NAME " plugin: lv_domain_get_tag failed."); - goto cont; - } + if (lv_domain_get_tag(xpath_ctx, name, tag) < 0) { + ERROR(PLUGIN_NAME " plugin: lv_domain_get_tag failed."); + goto cont; + } - if (!lv_instance_include_domain(inst, name, tag)) - goto cont; + if (!lv_instance_include_domain(inst, name, tag)) + goto cont; - if (add_domain(state, dom) < 0) { - ERROR(PLUGIN_NAME " plugin: malloc failed."); - goto cont; - } + if (add_domain(state, dom, 1) < 0) { + ERROR(PLUGIN_NAME " plugin: malloc failed."); + goto cont; + } - /* Block devices. */ - const char *bd_xmlpath = "/domain/devices/disk/target[@dev]"; - if (blockdevice_format == source) - bd_xmlpath = "/domain/devices/disk/source[@dev]"; - xpath_obj = xmlXPathEval((const xmlChar *)bd_xmlpath, xpath_ctx); + /* Block devices. */ + const char *bd_xmlpath = "/domain/devices/disk/target[@dev]"; + if (blockdevice_format == source) + bd_xmlpath = "/domain/devices/disk/source[@dev]"; + xpath_obj = xmlXPathEval((const xmlChar *)bd_xmlpath, xpath_ctx); - if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || - xpath_obj->nodesetval == NULL) - goto cont; + if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || + xpath_obj->nodesetval == NULL) + goto cont; - for (int j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) { - xmlNodePtr node; - char *path = NULL; + for (int 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; + 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; + if (il_block_devices && + ignore_device_match(il_block_devices, name, path) != 0) + goto cont2; - add_block_device(state, dom, path); - cont2: - if (path) - xmlFree(path); - } - xmlXPathFreeObject(xpath_obj); + add_block_device(state, 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; + /* 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; + xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval; - for (int j = 0; j < xml_interfaces->nodeNr; ++j) { - char *path = NULL; - char *address = NULL; - xmlNodePtr xml_interface; + for (int 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) + 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; - for (xmlNodePtr child = xml_interface->children; child; - child = child->next) { - if (child->type != XML_ELEMENT_NODE) + 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 (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(state, 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); + 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(state, 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); + } + #ifdef HAVE_LIST_ALL_DOMAINS - sfree(domains); + sfree(domains); + sfree(domains_inactive); #else - sfree(domids); + sfree(domids); + +end: #endif - } DEBUG(PLUGIN_NAME " plugin#%s: refreshing" " domains=%i block_devices=%i iface_devices=%i", @@ -2399,7 +2438,8 @@ static void free_domains(struct lv_read_state *state) { state->nr_domains = 0; } -static int add_domain(struct lv_read_state *state, virDomainPtr dom) { +static int add_domain(struct lv_read_state *state, virDomainPtr dom, + _Bool active) { domain_t *new_ptr; int new_size = sizeof(state->domains[0]) * (state->nr_domains + 1); @@ -2413,6 +2453,7 @@ static int add_domain(struct lv_read_state *state, virDomainPtr dom) { 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)); -- 2.11.0