From 937f0572ea82373beb3965e7e1b45046e0f4366f Mon Sep 17 00:00:00 2001 From: John Coyle Date: Fri, 1 Apr 2016 01:58:39 -0400 Subject: [PATCH] common/util: add support for distro info from /etc/os-release file 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 (cherry picked from commit a9487e2ad09546f8cd06a371cfed9e4ba992c679) --- src/common/util.cc | 96 +++++++++++++++++++++++++++--------- src/test/common/test_util.cc | 15 ++++++ 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/common/util.cc b/src/common/util.cc index 2c60cb263f8bf..124b9b9c39e07 100644 --- a/src/common/util.cc +++ b/src/common/util.cc @@ -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 *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 *m, CephContext *cct) +static void file_values_parse(const map& kvm, FILE *fp, map *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 *m, CephContext *cct) { + static const map 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 *m, CephContext *cct) +{ + static const map 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 *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 *m, CephContext *cct) } // distro info - lsb_release_parse(m, cct); + distro_detect(m, cct); } void dump_services(Formatter* f, const map >& services, const char* type) diff --git a/src/test/common/test_util.cc b/src/test/common/test_util.cc index cb22047c600d7..2ea40b3f1c528 100644 --- a/src/test/common/test_util.cc +++ b/src/test/common/test_util.cc @@ -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 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(); +} -- 2.39.5