]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/util: add support for distro info from /etc/os-release file
authorJohn Coyle <dx9err@gmail.com>
Fri, 1 Apr 2016 05:58:39 +0000 (01:58 -0400)
committerLoic Dachary <ldachary@redhat.com>
Wed, 9 Nov 2016 15:17:36 +0000 (16:17 +0100)
test/cephtool-test-mon.sh tests osd metadata for distro info. This fails on Alpine because lsb_release is not supported.

Updated collect_sys_info() to detect distro info in /etc/os-release as a fallback to lsb_release.

Added unit test for distro info detection.

Signed-off-by: John Coyle <dx9err@gmail.com>
(cherry picked from commit a9487e2ad09546f8cd06a371cfed9e4ba992c679)

src/common/util.cc
src/test/common/test_util.cc

index 2c60cb263f8bfd502917f23957ec7a34a1969c55..124b9b9c39e073a8c97ab510c3bdfa7b356a645d 100644 (file)
@@ -115,47 +115,99 @@ int get_fs_stats(ceph_data_stats_t &stats, const char *path)
   return 0;
 }
 
-static bool lsb_release_set(char *buf, const char *prefix,
+static char* value_sanitize(char *value)
+{
+  while (isspace(*value) || *value == '"')
+    value++;
+
+  char* end = value + strlen(value) - 1;
+  while (end > value && (isspace(*end) || *end == '"'))
+    end--;
+
+  *(end + 1) = '\0';
+
+  return value;
+}
+
+static bool value_set(char *buf, const char *prefix,
                            map<string, string> *pm, const char *key)
 {
   if (strncmp(buf, prefix, strlen(prefix))) {
     return false;
   }
 
-  if (buf[strlen(buf)-1] == '\n')
-    buf[strlen(buf)-1] = '\0';
-
-  char *value = buf + strlen(prefix) + 1;
-  (*pm)[key] = value;
+  (*pm)[key] = value_sanitize(buf + strlen(prefix));
   return true;
 }
 
-static void lsb_release_parse(map<string, string> *m, CephContext *cct)
+static void file_values_parse(const map<string, string>& kvm, FILE *fp, map<string, string> *m, CephContext *cct) {
+  char buf[512];
+  while (fgets(buf, sizeof(buf) - 1, fp) != NULL) {
+    for (auto& kv : kvm) {
+      if (value_set(buf, kv.second.c_str(), m, kv.first.c_str()))
+        continue;
+    }
+  }
+}
+
+static bool lsb_release_parse(map<string, string> *m, CephContext *cct)
 {
+  static const map<string, string> kvm = {
+      { "distro", "Distributor ID:" },
+      { "distro_description", "Description:" },
+      { "distro_codename", "Codename:", },
+      { "distro_version", "Release:" }
+  };
+
   FILE *fp = popen("lsb_release -idrc", "r");
   if (!fp) {
     int ret = -errno;
     lderr(cct) << "lsb_release_parse - failed to call lsb_release binary with error: " << cpp_strerror(ret) << dendl;
-    return;
+    return false;
   }
 
-  char buf[512];
-  while (fgets(buf, sizeof(buf) - 1, fp) != NULL) {
-    if (lsb_release_set(buf, "Distributor ID:", m, "distro"))
-      continue;
-    if (lsb_release_set(buf, "Description:", m, "distro_description"))
-      continue;
-    if (lsb_release_set(buf, "Release:", m, "distro_version"))
-      continue;
-    if (lsb_release_set(buf, "Codename:", m, "distro_codename"))
-      continue;
-
-    lderr(cct) << "unhandled output: " << buf << dendl;
-  }
+  file_values_parse(kvm, fp, m, cct);
 
   if (pclose(fp)) {
     int ret = -errno;
     lderr(cct) << "lsb_release_parse - pclose failed: " << cpp_strerror(ret) << dendl;
+    return false;
+  }
+
+  return true;
+}
+
+static bool os_release_parse(map<string, string> *m, CephContext *cct)
+{
+  static const map<string, string> kvm = {
+    { "distro", "ID=" },
+    { "distro_description", "PRETTY_NAME=" },
+    { "distro_version", "VERSION_ID=" }
+  };
+
+  FILE *fp = fopen("/etc/os-release", "r");
+  if (!fp) {
+    int ret = -errno;
+    lderr(cct) << "os_release_parse - failed to open /etc/os-release: " << cpp_strerror(ret) << dendl;
+    return false;
+  }
+
+  file_values_parse(kvm, fp, m, cct);
+
+  fclose(fp);
+
+  return true;
+}
+
+static void distro_detect(map<string, string> *m, CephContext *cct)
+{
+  if (!lsb_release_parse(m, cct) && !os_release_parse(m, cct)) {
+    lderr(cct) << "distro_detect - lsb_release or /etc/os-release is required" << dendl;
+  }
+
+  for (const char* rk: {"distro", "distro_version"}) {
+    if (m->find(rk) == m->end())
+      lderr(cct) << "distro_detect - can't detect " << rk << dendl;
   }
 }
 
@@ -218,7 +270,7 @@ void collect_sys_info(map<string, string> *m, CephContext *cct)
   }
 
   // distro info
-  lsb_release_parse(m, cct);
+  distro_detect(m, cct);
 }
 
 void dump_services(Formatter* f, const map<string, list<int> >& services, const char* type)
index cb22047c600d78f3687eedf873f50b8f03e7adab..2ea40b3f1c5287d3686a7fae60023f86c7ae8665 100644 (file)
@@ -12,6 +12,7 @@
  *
  */
 
+#include "common/ceph_context.h"
 #include "include/util.h"
 #include "gtest/gtest.h"
 
@@ -30,3 +31,17 @@ TEST(util, unit_to_bytesize)
 
   ASSERT_EQ(65536ll, unit_to_bytesize(" 64K", &cerr));
 }
+
+TEST(util, collect_sys_info)
+{
+  map<string, string> sys_info;
+
+  CephContext *cct = (new CephContext(CEPH_ENTITY_TYPE_CLIENT))->get();
+  collect_sys_info(&sys_info, cct);
+
+  ASSERT_TRUE(sys_info.find("distro") != sys_info.end());
+  ASSERT_TRUE(sys_info.find("distro_version") != sys_info.end());
+  ASSERT_TRUE(sys_info.find("distro_description") != sys_info.end());
+
+  cct->put();
+}