#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)
#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*/
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:
"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",
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;
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);
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);
}
}
char flush_type_instance[DATA_MAX_NAME_LEN];
- snprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
- type_instance);
+ ssnprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
+ type_instance);
if ((bstats->bi.rd_req != -1) && (bstats->bi.wr_req != -1))
submit_derive2("disk_ops", (derive_t)bstats->bi.rd_req,
const char *reason_str = "N/A";
#endif
- snprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
- reason_str);
+ ssnprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
+ reason_str);
int severity;
switch (state) {
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 */
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.");
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);
}
}
#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;
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
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;
}
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;
* 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
}
}
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;
}
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? */
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)
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);
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);
goto done;
}
- snprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
- METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
+ 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) {
ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) failed on domain %s",
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;
}
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);
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;