#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);
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.");
#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_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;
* 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)
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);