virt plugin: Added connection state check via virConnectIsAlive()
[collectd.git] / src / virt.c
index 1742026..7e7e057 100644 (file)
@@ -976,7 +976,7 @@ static double cpu_ns_to_percent(unsigned int node_cpus,
   }
 
   DEBUG(PLUGIN_NAME " plugin: node_cpus=%u cpu_time_old=%" PRIu64
-                    " cpu_time_new=%" PRIu64 "cpu_time_diff=%" PRIu64
+                    " cpu_time_new=%" PRIu64 " cpu_time_diff=%" PRIu64
                     " time_diff_sec=%f percent=%f",
         node_cpus, (uint64_t)cpu_time_old, (uint64_t)cpu_time_new,
         (uint64_t)cpu_time_diff, time_diff_sec, percent);
@@ -1523,8 +1523,8 @@ static int lv_domain_block_stats(virDomainPtr dom, const char *path,
 
   virTypedParameterPtr params = calloc(nparams, sizeof(*params));
   if (params == NULL) {
-    ERROR("virt plugin: alloc(%i) for block=%s parameters failed.", nparams,
-          path);
+    ERROR(PLUGIN_NAME " plugin: alloc(%i) for block=%s parameters failed.",
+          nparams, path);
     return -1;
   }
 
@@ -1564,8 +1564,17 @@ static int get_perf_events(virDomainPtr domain) {
   int status =
       virDomainListGetStats(domain_array, VIR_DOMAIN_STATS_PERF, &stats, 0);
   if (status == -1) {
-    ERROR("virt plugin: virDomainListGetStats failed with status %i.", status);
-    return status;
+    ERROR(PLUGIN_NAME " plugin: virDomainListGetStats failed with status %i.",
+          status);
+
+    virErrorPtr err = virConnGetLastError(conn);
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      ERROR(PLUGIN_NAME
+            " plugin: Disabled unsupported ExtraStats selector: perf");
+      extra_stats &= ~(ex_stats_perf);
+    }
+
+    return -1;
   }
 
   for (int i = 0; i < status; ++i)
@@ -1589,7 +1598,6 @@ static void vcpu_pin_submit(virDomainPtr dom, int max_cpus, int vcpu,
 
 static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) {
   int max_cpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
-  int cpu_map_len = VIR_CPU_MAPLEN(max_cpus);
 
   virVcpuInfoPtr vinfo = calloc(nr_virt_cpu, sizeof(*vinfo));
   if (vinfo == NULL) {
@@ -1597,11 +1605,17 @@ static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) {
     return -1;
   }
 
-  unsigned char *cpumaps = calloc(nr_virt_cpu, cpu_map_len);
-  if (cpumaps == NULL) {
-    ERROR(PLUGIN_NAME " plugin: calloc failed.");
-    sfree(vinfo);
-    return -1;
+  int cpu_map_len = 0;
+  unsigned char *cpumaps = NULL;
+  if (extra_stats & ex_stats_vcpupin) {
+    cpu_map_len = VIR_CPU_MAPLEN(max_cpus);
+    cpumaps = calloc(nr_virt_cpu, cpu_map_len);
+
+    if (cpumaps == NULL) {
+      ERROR(PLUGIN_NAME " plugin: calloc failed.");
+      sfree(vinfo);
+      return -1;
+    }
   }
 
   int status =
@@ -1609,9 +1623,21 @@ static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) {
   if (status < 0) {
     ERROR(PLUGIN_NAME " plugin: virDomainGetVcpus failed with status %i.",
           status);
+
+    virErrorPtr err = virConnGetLastError(conn);
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      if (extra_stats & ex_stats_vcpu)
+        ERROR(PLUGIN_NAME
+              " plugin: Disabled unsupported ExtraStats selector: vcpu");
+      if (extra_stats & ex_stats_vcpupin)
+        ERROR(PLUGIN_NAME
+              " plugin: Disabled unsupported ExtraStats selector: vcpupin");
+      extra_stats &= ~(ex_stats_vcpu | ex_stats_vcpupin);
+    }
+
     sfree(cpumaps);
     sfree(vinfo);
-    return status;
+    return -1;
   }
 
   for (int i = 0; i < nr_virt_cpu; ++i) {
@@ -1631,6 +1657,14 @@ static int get_pcpu_stats(virDomainPtr dom) {
   int nparams = virDomainGetCPUStats(dom, NULL, 0, -1, 1, 0);
   if (nparams < 0) {
     VIRT_ERROR(conn, "getting the CPU params count");
+
+    virErrorPtr err = virConnGetLastError(conn);
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      ERROR(PLUGIN_NAME
+            " plugin: Disabled unsupported ExtraStats selector: pcpu");
+      extra_stats &= ~(ex_stats_pcpu);
+    }
+
     return -1;
   }
 
@@ -1713,17 +1747,25 @@ static int get_memory_stats(virDomainPtr domain) {
   virDomainMemoryStatPtr minfo =
       calloc(VIR_DOMAIN_MEMORY_STAT_NR, sizeof(*minfo));
   if (minfo == NULL) {
-    ERROR("virt plugin: calloc failed.");
+    ERROR(PLUGIN_NAME " plugin: calloc failed.");
     return -1;
   }
 
   int mem_stats =
       virDomainMemoryStats(domain, minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
   if (mem_stats < 0) {
-    ERROR("virt plugin: virDomainMemoryStats failed with mem_stats %i.",
+    ERROR(PLUGIN_NAME " plugin: virDomainMemoryStats failed with mem_stats %i.",
           mem_stats);
     sfree(minfo);
-    return mem_stats;
+
+    virErrorPtr err = virConnGetLastError(conn);
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      ERROR(PLUGIN_NAME
+            " plugin: Disabled unsupported ExtraStats selector: memory");
+      extra_stats &= ~(ex_stats_memory);
+    }
+
+    return -1;
   }
 
   derive_t swap_in = -1;
@@ -1780,6 +1822,15 @@ static int get_disk_err(virDomainPtr domain) {
   if (disk_err_count == -1) {
     ERROR(PLUGIN_NAME
           " plugin: failed to get preferred size of disk errors array");
+
+    virErrorPtr err = virConnGetLastError(conn);
+
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      ERROR(PLUGIN_NAME
+            " plugin: Disabled unsupported ExtraStats selector: disk_err");
+      extra_stats &= ~(ex_stats_disk_err);
+    }
+
     return -1;
   }
 
@@ -1826,6 +1877,24 @@ static int get_block_device_stats(struct block_device *block_dev) {
           0) {
         ERROR(PLUGIN_NAME " plugin: virDomainGetBlockInfo failed for path: %s",
               block_dev->path);
+
+        virErrorPtr err = virConnGetLastError(conn);
+        if (err->code == VIR_ERR_NO_SUPPORT) {
+
+          if (extra_stats & ex_stats_disk_allocation)
+            ERROR(PLUGIN_NAME " plugin: Disabled unsupported ExtraStats "
+                              "selector: disk_allocation");
+          if (extra_stats & ex_stats_disk_capacity)
+            ERROR(PLUGIN_NAME " plugin: Disabled unsupported ExtraStats "
+                              "selector: disk_capacity");
+          if (extra_stats & ex_stats_disk_physical)
+            ERROR(PLUGIN_NAME " plugin: Disabled unsupported ExtraStats "
+                              "selector: disk_physical");
+
+          extra_stats &= ~(ex_stats_disk_allocation | ex_stats_disk_capacity |
+                           ex_stats_disk_physical);
+        }
+
         return -1;
       }
     }
@@ -1912,7 +1981,15 @@ static int get_fs_info(virDomainPtr domain) {
   if (mount_points_cnt == -1) {
     ERROR(PLUGIN_NAME " plugin: virDomainGetFSInfo failed: %d",
           mount_points_cnt);
-    return mount_points_cnt;
+
+    virErrorPtr err = virConnGetLastError(conn);
+    if (err->code == VIR_ERR_NO_SUPPORT) {
+      ERROR(PLUGIN_NAME
+            " plugin: Disabled unsupported ExtraStats selector: fs_info");
+      extra_stats &= ~(ex_stats_fs_info);
+    }
+
+    return -1;
   }
 
   for (int i = 0; i < mount_points_cnt; ++i) {
@@ -1959,7 +2036,6 @@ static void job_stats_submit(virDomainPtr domain, virTypedParameterPtr param) {
 }
 
 static int get_job_stats(virDomainPtr domain) {
-  int ret = 0;
   int job_type = 0;
   int nparams = 0;
   virTypedParameterPtr params = NULL;
@@ -1967,10 +2043,24 @@ static int get_job_stats(virDomainPtr domain) {
                   ? VIR_DOMAIN_JOB_STATS_COMPLETED
                   : 0;
 
-  ret = virDomainGetJobStats(domain, &job_type, &params, &nparams, flags);
+  int ret = virDomainGetJobStats(domain, &job_type, &params, &nparams, flags);
   if (ret != 0) {
     ERROR(PLUGIN_NAME " plugin: virDomainGetJobStats failed: %d", ret);
-    return ret;
+
+    virErrorPtr err = virConnGetLastError(conn);
+    // VIR_ERR_INVALID_ARG returned when VIR_DOMAIN_JOB_STATS_COMPLETED flag is
+    // not supported by driver
+    if (err->code == VIR_ERR_NO_SUPPORT || err->code == VIR_ERR_INVALID_ARG) {
+      if (extra_stats & ex_stats_job_stats_completed)
+        ERROR(PLUGIN_NAME " plugin: Disabled unsupported ExtraStats selector: "
+                          "job_stats_completed");
+      if (extra_stats & ex_stats_job_stats_background)
+        ERROR(PLUGIN_NAME " plugin: Disabled unsupported ExtraStats selector: "
+                          "job_stats_background");
+      extra_stats &=
+          ~(ex_stats_job_stats_completed | ex_stats_job_stats_background);
+    }
+    return -1;
   }
 
   DEBUG(PLUGIN_NAME " plugin: job_type=%d nparams=%d", job_type, nparams);
@@ -1982,7 +2072,7 @@ static int get_job_stats(virDomainPtr domain) {
   }
 
   virTypedParamsFree(params, nparams);
-  return ret;
+  return 0;
 }
 #endif /* HAVE_JOB_STATS */
 
@@ -2113,6 +2203,9 @@ static int domain_lifecycle_event_cb(__attribute__((unused)) virConnectPtr con_,
   return 0;
 }
 
+static void virt_eventloop_timeout_cb(int timer ATTRIBUTE_UNUSED,
+                                      void *timer_info) {}
+
 static int register_event_impl(void) {
   if (virEventRegisterDefaultImpl() < 0) {
     virErrorPtr err = virGetLastError();
@@ -2122,6 +2215,14 @@ static int register_event_impl(void) {
     return -1;
   }
 
+  if (virEventAddTimeout(CDTIME_T_TO_MS(plugin_get_interval()),
+                         virt_eventloop_timeout_cb, NULL, NULL) < 0) {
+    virErrorPtr err = virGetLastError();
+    ERROR(PLUGIN_NAME " plugin: virEventAddTimeout failed: %s",
+          err && err->message ? err->message : "Unknown error");
+    return -1;
+  }
+
   return 0;
 }
 
@@ -2317,6 +2418,21 @@ static int lv_read(user_data_t *ud) {
     return 0;
   }
 
+  int ret = virConnectIsAlive(conn);
+  if (ret == 0) { /* Connection lost */
+    if (inst->id == 0) {
+      c_complain(LOG_ERR, &conn_complain,
+                 PLUGIN_NAME " plugin: Lost connection.");
+
+      if (!persistent_notification)
+        stop_event_loop(&notif_thread);
+
+      lv_disconnect();
+      last_refresh = 0;
+    }
+    return -1;
+  }
+
   time_t t;
   time(&t);