X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fvirt.c;h=17420269ee06a34586ff7b43603c8f043ecf1095;hb=a620282e87a3f5ac7c976d4f1f0ce4d87a14b3ff;hp=1fa472766c54634e88a0a1a08add8da3c6b60f11;hpb=9815a4ed680871671c58d791b70a57c4b9866783;p=collectd.git diff --git a/src/virt.c b/src/virt.c index 1fa47276..17420269 100644 --- a/src/virt.c +++ b/src/virt.c @@ -69,9 +69,10 @@ #endif /* - virConnectListAllDomains() appeared in 0.10.2 - Note that LIBVIR_CHECK_VERSION appeared a year later, so - in some systems which actually have virConnectListAllDomains() + virConnectListAllDomains() appeared in 0.10.2 (Sep 2012) + Note that LIBVIR_CHECK_VERSION appeared a year later (Dec 2013, + libvirt-1.2.0), + so in some systems which actually have virConnectListAllDomains() we can't detect this. */ #if LIBVIR_CHECK_VERSION(0, 10, 2) @@ -609,7 +610,9 @@ enum ex_stats { #endif ex_stats_disk_allocation = 1 << 10, ex_stats_disk_capacity = 1 << 11, - ex_stats_disk_physical = 1 << 12 + ex_stats_disk_physical = 1 << 12, + ex_stats_memory = 1 << 13, + ex_stats_vcpu = 1 << 14 }; static unsigned int extra_stats = ex_stats_none; @@ -640,6 +643,8 @@ static const struct ex_stats_item ex_stats_table[] = { {"disk_allocation", ex_stats_disk_allocation}, {"disk_capacity", ex_stats_disk_capacity}, {"disk_physical", ex_stats_disk_physical}, + {"memory", ex_stats_memory}, + {"vcpu", ex_stats_vcpu}, {NULL, ex_stats_none}, }; @@ -652,6 +657,8 @@ static enum if_field interface_format = if_name; static time_t last_refresh = (time_t)0; static int refresh_lists(struct lv_read_instance *inst); +static int register_event_impl(void); +static int start_event_loop(virt_notif_thread_t *thread_data); struct lv_block_stats { virDomainBlockStatsStruct bi; @@ -933,10 +940,10 @@ static void memory_submit(virDomainPtr dom, gauge_t value) { static void memory_stats_submit(gauge_t value, virDomainPtr dom, int tag_index) { - static const char *tags[] = {"swap_in", "swap_out", "major_fault", - "minor_fault", "unused", "available", - "actual_balloon", "rss", "usable", - "last_update"}; + static const char *tags[] = {"swap_in", "swap_out", "major_fault", + "minor_fault", "unused", "available", + "actual_balloon", "rss", "usable", + "last_update", "disk_caches"}; if ((tag_index < 0) || (tag_index >= (int)STATIC_ARRAY_SIZE(tags))) { ERROR("virt plugin: Array index out of bounds: tag_index = %d", tag_index); @@ -1458,6 +1465,11 @@ static int lv_config(oconfig_item_t *ci) { static int lv_connect(void) { if (conn == NULL) { + /* event implementation must be registered before connection is opened */ + if (!persistent_notification) + if (register_event_impl() != 0) + return -1; + /* `conn_string == NULL' is acceptable */ #ifdef HAVE_FS_INFO /* virDomainGetFSInfo requires full read-write access connection */ @@ -1475,8 +1487,17 @@ static int lv_connect(void) { int status = virNodeGetInfo(conn, &nodeinfo); if (status != 0) { ERROR(PLUGIN_NAME " plugin: virNodeGetInfo failed"); + virConnectClose(conn); + conn = NULL; return -1; } + + if (!persistent_notification) + if (start_event_loop(¬if_thread) != 0) { + virConnectClose(conn); + conn = NULL; + return -1; + } } c_release(LOG_NOTICE, &conn_complain, PLUGIN_NAME " plugin: Connection established."); @@ -1594,7 +1615,8 @@ static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) { } for (int i = 0; i < nr_virt_cpu; ++i) { - vcpu_submit(vinfo[i].cpuTime, domain, vinfo[i].number, "virt_vcpu"); + if (extra_stats & ex_stats_vcpu) + vcpu_submit(vinfo[i].cpuTime, domain, vinfo[i].number, "virt_vcpu"); if (extra_stats & ex_stats_vcpupin) vcpu_pin_submit(domain, max_cpus, i, cpumaps, cpu_map_len); } @@ -1648,16 +1670,7 @@ static int get_pcpu_stats(virDomainPtr dom) { #endif /* HAVE_CPU_STATS */ #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) { +static int submit_domain_state(virDomainPtr domain) { int domain_state = 0; int domain_reason = 0; @@ -1668,9 +1681,13 @@ static int get_domain_state(virDomainPtr domain) { return status; } - domain_state_submit(domain, domain_state, domain_reason); + value_t values[] = { + {.gauge = (gauge_t)domain_state}, {.gauge = (gauge_t)domain_reason}, + }; - return status; + submit(domain, "domain_state", NULL, values, STATIC_ARRAY_SIZE(values)); + + return 0; } #ifdef HAVE_LIST_ALL_DOMAINS @@ -1685,8 +1702,7 @@ static int get_domain_state_notify(virDomainPtr domain) { return status; } - if (persistent_notification) - domain_state_submit_notif(domain, domain_state, domain_reason); + domain_state_submit_notif(domain, domain_state, domain_reason); return status; } @@ -1710,8 +1726,42 @@ static int get_memory_stats(virDomainPtr domain) { return mem_stats; } - for (int i = 0; i < mem_stats; i++) - memory_stats_submit((gauge_t)minfo[i].val * 1024, domain, minfo[i].tag); + derive_t swap_in = -1; + derive_t swap_out = -1; + derive_t min_flt = -1; + derive_t maj_flt = -1; + + for (int i = 0; i < mem_stats; i++) { + if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_IN) + swap_in = minfo[i].val; + else if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_OUT) + swap_out = minfo[i].val; + else if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT) + min_flt = minfo[i].val; + else if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT) + maj_flt = minfo[i].val; +#ifdef LIBVIR_CHECK_VERSION +#if LIBVIR_CHECK_VERSION(2, 1, 0) + else if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_LAST_UPDATE) + /* Skip 'last_update' reporting as that is not memory but timestamp */ + continue; +#endif +#endif + else + memory_stats_submit((gauge_t)minfo[i].val * 1024, domain, minfo[i].tag); + } + + if (swap_in > 0 || swap_out > 0) { + submit(domain, "swap_io", "in", &(value_t){.gauge = swap_in}, 1); + submit(domain, "swap_io", "out", &(value_t){.gauge = swap_out}, 1); + } + + if (min_flt > 0 || maj_flt > 0) { + value_t values[] = { + {.gauge = (gauge_t)min_flt}, {.gauge = (gauge_t)maj_flt}, + }; + submit(domain, "ps_pagefaults", NULL, values, STATIC_ARRAY_SIZE(values)); + } sfree(minfo); return 0; @@ -1956,7 +2006,7 @@ static int get_domain_metrics(domain_t *domain) { * however it doesn't provide a reason for entering particular state. * We need to get it from virDomainGetState. */ - GET_STATS(get_domain_state, "domain reason", domain->ptr); + GET_STATS(submit_domain_state, "domain reason", domain->ptr); #endif } @@ -1973,8 +2023,10 @@ static int get_domain_metrics(domain_t *domain) { memory_submit(domain->ptr, (gauge_t)info.memory * 1024); - GET_STATS(get_vcpu_stats, "vcpu stats", domain->ptr, info.nrVirtCpu); - GET_STATS(get_memory_stats, "memory stats", domain->ptr); + if (extra_stats & (ex_stats_vcpu | ex_stats_vcpupin)) + GET_STATS(get_vcpu_stats, "vcpu stats", domain->ptr, info.nrVirtCpu); + if (extra_stats & ex_stats_memory) + GET_STATS(get_memory_stats, "memory stats", domain->ptr); #ifdef HAVE_PERF_STATS if (extra_stats & ex_stats_perf) @@ -2108,10 +2160,9 @@ static void *event_loop_worker(void *arg) { } static int virt_notif_thread_init(virt_notif_thread_t *thread_data) { - int ret; - assert(thread_data != NULL); - ret = pthread_mutex_init(&thread_data->active_mutex, NULL); + + int ret = pthread_mutex_init(&thread_data->active_mutex, NULL); if (ret != 0) { ERROR(PLUGIN_NAME " plugin: Failed to initialize mutex, err %u", ret); return ret; @@ -2247,33 +2298,26 @@ static int persistent_domains_state_notification(void) { } static int lv_read(user_data_t *ud) { - time_t t; - struct lv_read_instance *inst = NULL; - struct lv_read_state *state = NULL; - if (ud->data == NULL) { ERROR(PLUGIN_NAME " plugin: NULL userdata"); return -1; } - inst = ud->data; - state = &inst->read_state; - - bool reconnect = conn == NULL ? true : false; - /* event implementation must be registered before connection is opened */ - if (inst->id == 0) { - if (!persistent_notification && reconnect) - if (register_event_impl() != 0) - return -1; + struct lv_read_instance *inst = ud->data; + struct lv_read_state *state = &inst->read_state; + if (inst->id == 0) if (lv_connect() < 0) return -1; - if (!persistent_notification && reconnect && conn != NULL) - if (start_event_loop(¬if_thread) != 0) - return -1; + /* Wait until inst#0 establish connection */ + if (conn == NULL) { + DEBUG(PLUGIN_NAME " plugin#%s: Wait until inst#0 establish connection", + inst->tag); + return 0; } + time_t t; time(&t); /* Need to refresh domain or device lists? */ @@ -2320,8 +2364,8 @@ static int lv_read(user_data_t *ud) { if (dom->active) status = get_domain_metrics(dom); #ifdef HAVE_DOM_REASON - else - status = get_domain_state(dom->ptr); + else if (extra_stats & ex_stats_domain_state) + status = submit_domain_state(dom->ptr); #endif if (status != 0) @@ -2394,19 +2438,11 @@ static int lv_init(void) { if (lv_init_ignorelists() != 0) return -1; - /* event implementation must be registered before connection is opened */ if (!persistent_notification) - if (register_event_impl() != 0) + if (virt_notif_thread_init(¬if_thread) != 0) return -1; - if (lv_connect() != 0) - return -1; - - if (!persistent_notification) { - virt_notif_thread_init(¬if_thread); - if (start_event_loop(¬if_thread) != 0) - return -1; - } + lv_connect(); DEBUG(PLUGIN_NAME " plugin: starting %i instances", nr_instances);