X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fvirt.c;h=d3d8c6a72823d1c5cf023a9d484ee00cbb7bd54f;hb=abaa1c8a24e8eff5632dd6052b1da5f6535caf19;hp=4ec76957ff11b852e228c90048b065565a8c46d9;hpb=a073b83ade22d475828889ed8c111d133b6f63f1;p=collectd.git diff --git a/src/virt.c b/src/virt.c index 4ec76957..d3d8c6a7 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) @@ -107,6 +108,9 @@ #define HAVE_DOM_REASON_POSTCOPY 1 #endif +#if LIBVIR_CHECK_VERSION(4, 10, 0) +#define HAVE_DOM_REASON_SHUTOFF_DAEMON 1 +#endif #endif /* LIBVIR_CHECK_VERSION */ /* structure used for aggregating notification-thread data*/ @@ -300,6 +304,16 @@ static int map_domain_event_detail_to_reason(int event, int detail) { switch (detail) { case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED: /* Guest finished shutdown sequence */ +#ifdef LIBVIR_CHECK_VERSION +#if LIBVIR_CHECK_VERSION(3, 4, 0) + case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST: /* Domain finished shutting down after + request from the guest itself (e.g. + hardware-specific action) */ + case VIR_DOMAIN_EVENT_SHUTDOWN_HOST: /* Domain finished shutting down after + request from the host (e.g. killed + by a signal) */ +#endif +#endif ret = VIR_DOMAIN_SHUTDOWN_USER; break; default: @@ -425,6 +439,10 @@ const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = { "domain failed to start", [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT] = "restored from a snapshot which was taken while domain was shutoff", +#ifdef HAVE_DOM_REASON_SHUTOFF_DAEMON + [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DAEMON] = + "daemon decides to kill domain during reconnection processing", +#endif [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_UNKNOWN] = "the reason is unknown", @@ -635,6 +653,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; @@ -916,20 +936,16 @@ 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); return; } - /* Skip 'last_update' reporting as that is not memory but timestamp */ - if (tag_index == 9) - return; - submit(dom, "memory", tags[tag_index], &(value_t){.gauge = value}, 1); } @@ -988,7 +1004,7 @@ static void vcpu_submit(derive_t value, virDomainPtr dom, int vcpu_nr, const char *type) { char type_instance[DATA_MAX_NAME_LEN]; - snprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr); + ssnprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr); submit(dom, type, type_instance, &(value_t){.derive = value}, 1); } @@ -1010,7 +1026,7 @@ static void disk_block_stats_submit(struct lv_block_stats *bstats, } char flush_type_instance[DATA_MAX_NAME_LEN]; - snprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s", + ssnprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s", type_instance); if ((bstats->bi.rd_req != -1) && (bstats->bi.wr_req != -1)) @@ -1114,7 +1130,7 @@ static void domain_state_submit_notif(virDomainPtr dom, int state, int reason) { const char *reason_str = "N/A"; #endif - snprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str, + ssnprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str, reason_str); int severity; @@ -1445,6 +1461,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 */ @@ -1462,8 +1483,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."); @@ -1548,7 +1578,7 @@ static void vcpu_pin_submit(virDomainPtr dom, int max_cpus, int vcpu, char type_instance[DATA_MAX_NAME_LEN]; bool is_set = VIR_CPU_USABLE(cpu_maps, cpu_map_len, vcpu, cpu); - snprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu, cpu); + ssnprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu, cpu); submit(dom, "cpu_affinity", type_instance, &(value_t){.gauge = is_set}, 1); } } @@ -1697,8 +1727,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_MAJOR_FAULT) + min_flt = minfo[i].val; + else if (minfo[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_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; @@ -2095,10 +2159,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; @@ -2234,33 +2297,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? */ @@ -2346,7 +2402,7 @@ static int lv_init_instance(size_t i, plugin_read_cb callback) { memset(lv_ud, 0, sizeof(*lv_ud)); - snprintf(inst->tag, sizeof(inst->tag), "%s-%" PRIsz, PLUGIN_NAME, i); + ssnprintf(inst->tag, sizeof(inst->tag), "%s-%" PRIsz, PLUGIN_NAME, i); inst->id = i; user_data_t *ud = &(lv_ud->ud); @@ -2381,19 +2437,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); @@ -2424,7 +2472,7 @@ static int lv_domain_get_tag(xmlXPathContextPtr xpath_ctx, const char *dom_name, goto done; } - snprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()", + 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) { @@ -2627,7 +2675,7 @@ static void lv_add_network_interfaces(struct lv_read_state *state, break; case if_number: { char number_string[4]; - snprintf(number_string, sizeof(number_string), "%d", itf_number); + ssnprintf(number_string, sizeof(number_string), "%d", itf_number); if (ignore_device_match(il_interface_devices, domname, number_string) != 0) device_ignored = true; @@ -2928,7 +2976,7 @@ static int add_interface_device(struct lv_read_state *state, virDomainPtr dom, } char number_string[21]; - snprintf(number_string, sizeof(number_string), "interface-%u", number); + ssnprintf(number_string, sizeof(number_string), "interface-%u", number); char *number_copy = strdup(number_string); if (!number_copy) { sfree(path_copy); @@ -2967,7 +3015,7 @@ static int ignore_device_match(ignorelist_t *il, const char *domname, ERROR(PLUGIN_NAME " plugin: malloc failed."); return 0; } - snprintf(name, n, "%s:%s", domname, devpath); + ssnprintf(name, n, "%s:%s", domname, devpath); int r = ignorelist_match(il, name); sfree(name); return r;