]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/common/util.cc
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / common / util.cc
index fb67d7ca109ef486631ffdebf8ac6e5d1c0b099d..f816ff41db0bd9a3f023e12fc055825880bae9af 100644 (file)
@@ -13,7 +13,8 @@
  */
 
 #include <sys/utsname.h>
-#include <boost/lexical_cast.hpp>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
 
 #include "include/compat.h"
 #include "include/util.h"
 #include <sys/vfs.h>
 #endif
 
-#if defined(DARWIN) || defined(__FreeBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__)
 #include <sys/param.h>
 #include <sys/mount.h>
+#if defined(__APPLE__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
 #endif
 
 #include <string>
@@ -89,6 +94,7 @@ static void file_values_parse(const map<string, string>& kvm, FILE *fp, map<stri
 
 static bool os_release_parse(map<string, string> *m, CephContext *cct)
 {
+#if defined(__linux__)
   static const map<string, string> kvm = {
     { "distro", "ID=" },
     { "distro_description", "PRETTY_NAME=" },
@@ -105,6 +111,15 @@ static bool os_release_parse(map<string, string> *m, CephContext *cct)
   file_values_parse(kvm, fp, m, cct);
 
   fclose(fp);
+#elif defined(__FreeBSD__)
+  struct utsname u;
+  int r = uname(&u);
+  if (!r) {
+     m->insert(std::make_pair("distro", u.sysname));
+     m->insert(std::make_pair("distro_description", u.version));
+     m->insert(std::make_pair("distro_version", u.release));
+  }
+#endif
 
   return true;
 }
@@ -121,10 +136,44 @@ static void distro_detect(map<string, string> *m, CephContext *cct)
   }
 }
 
+int get_cgroup_memory_limit(uint64_t *limit)
+{
+  // /sys/fs/cgroup/memory/memory.limit_in_bytes
+
+  // the magic value 9223372036854771712 or 0x7ffffffffffff000
+  // appears to mean no limit.
+  FILE *f = fopen(PROCPREFIX "/sys/fs/cgroup/memory/memory.limit_in_bytes", "r");
+  if (!f) {
+    return -errno;
+  }
+  char buf[100];
+  int ret = 0;
+  long long value;
+  char *line = fgets(buf, sizeof(buf), f);
+  if (!line) {
+    ret = -EINVAL;
+    goto out;
+  }
+  if (sscanf(line, "%lld", &value) != 1) {
+    ret = -EINVAL;
+  }
+  if (value == 0x7ffffffffffff000) {
+    *limit = 0;  // no limit
+  } else {
+    *limit = value;
+  }
+out:
+  fclose(f);
+  return ret;
+}
+
+
 void collect_sys_info(map<string, string> *m, CephContext *cct)
 {
   // version
   (*m)["ceph_version"] = pretty_version_to_str();
+  (*m)["ceph_version_short"] = ceph_version_to_str();
+  (*m)["ceph_release"] = ceph_release_to_str();
 
   // kernel info
   struct utsname u;
@@ -137,58 +186,105 @@ void collect_sys_info(map<string, string> *m, CephContext *cct)
     (*m)["arch"] = u.machine;
   }
 
+  // but wait, am i in a container?
+  bool in_container = false;
+
+  if (const char *pod_name = getenv("POD_NAME")) {
+    (*m)["pod_name"] = pod_name;
+    in_container = true;
+  }
+  if (const char *container_name = getenv("CONTAINER_NAME")) {
+    (*m)["container_name"] = container_name;
+    in_container = true;
+  }
+  if (const char *container_image = getenv("CONTAINER_IMAGE")) {
+    (*m)["container_image"] = container_image;
+    in_container = true;
+  }
+  if (in_container) {
+    if (const char *node_name = getenv("NODE_NAME")) {
+      (*m)["container_hostname"] = u.nodename;
+      (*m)["hostname"] = node_name;
+    }
+    if (const char *ns = getenv("POD_NAMESPACE")) {
+      (*m)["pod_namespace"] = ns;
+    }
+  }
+
+#ifdef __APPLE__
   // memory
-  FILE *f = fopen(PROCPREFIX "/proc/meminfo", "r");
-  if (f) {
+  {
+    uint64_t size;
+    size_t len = sizeof(size);
+    r = sysctlbyname("hw.memsize", &size, &len, NULL, 0);
+    if (r == 0) {
+      (*m)["mem_total_kb"] = std::to_string(size);
+    }
+  }
+  {
+    xsw_usage vmusage;
+    size_t len = sizeof(vmusage);
+    r = sysctlbyname("vm.swapusage", &vmusage, &len, NULL, 0);
+    if (r == 0) {
+      (*m)["mem_swap_kb"] = std::to_string(vmusage.xsu_total);
+    }
+  }
+  // processor
+  {
     char buf[100];
-    while (!feof(f)) {
-      char *line = fgets(buf, sizeof(buf), f);
-      if (!line)
-       break;
-      char key[40];
-      long long value;
-      int r = sscanf(line, "%s %lld", key, &value);
-      if (r == 2) {
-       if (strcmp(key, "MemTotal:") == 0)
-         (*m)["mem_total_kb"] = boost::lexical_cast<string>(value);
-       else if (strcmp(key, "SwapTotal:") == 0)
-         (*m)["mem_swap_kb"] = boost::lexical_cast<string>(value);
+    size_t len = sizeof(buf);
+    r = sysctlbyname("machdep.cpu.brand_string", buf, &len, NULL, 0);
+    if (r == 0) {
+      buf[len - 1] = '\0';
+      (*m)["cpu"] = buf;
+    }
+  }
+#else
+  // memory
+  if (std::ifstream f{PROCPREFIX "/proc/meminfo"}; !f.fail()) {
+    for (std::string line; std::getline(f, line); ) {
+      std::vector<string> parts;
+      boost::split(parts, line, boost::is_any_of(":\t "), boost::token_compress_on);
+      if (parts.size() != 3) {
+       continue;
+      }
+      if (parts[0] == "MemTotal") {
+       (*m)["mem_total_kb"] = parts[1];
+      } else if (parts[0] == "SwapTotal") {
+       (*m)["mem_swap_kb"] = parts[1];
       }
     }
-    fclose(f);
+  }
+  uint64_t cgroup_limit;
+  if (get_cgroup_memory_limit(&cgroup_limit) == 0 &&
+      cgroup_limit > 0) {
+    (*m)["mem_cgroup_limit"] = std::to_string(cgroup_limit);
   }
 
   // processor
-  f = fopen(PROCPREFIX "/proc/cpuinfo", "r");
-  if (f) {
-    char buf[100];
-    while (!feof(f)) {
-      char *line = fgets(buf, sizeof(buf), f);
-      if (!line)
-       break;
-      if (strncmp(line, "model name", 10) == 0) {
-       char *c = strchr(buf, ':');
-       c++;
-       while (*c == ' ')
-         ++c;
-       char *nl = c;
-       while (*nl != '\n')
-         ++nl;
-       *nl = '\0';
-       (*m)["cpu"] = c;
+  if (std::ifstream f{PROCPREFIX "/proc/cpuinfo"}; !f.fail()) {
+    for (std::string line; std::getline(f, line); ) {
+      std::vector<string> parts;
+      boost::split(parts, line, boost::is_any_of(":"));
+      if (parts.size() != 2) {
+       continue;
+      }
+      boost::trim(parts[0]);
+      boost::trim(parts[1]);
+      if (parts[0] == "model name") {
+       (*m)["cpu"] = parts[1];
        break;
       }
     }
-    fclose(f);
   }
-
+#endif
   // distro info
   distro_detect(m, cct);
 }
 
 void dump_services(Formatter* f, const map<string, list<int> >& services, const char* type)
 {
-  assert(f);
+  ceph_assert(f);
 
   f->open_object_section(type);
   for (map<string, list<int> >::const_iterator host = services.begin();
@@ -204,10 +300,25 @@ void dump_services(Formatter* f, const map<string, list<int> >& services, const
   f->close_section();
 }
 
+void dump_services(Formatter* f, const map<string, list<string> >& services, const char* type)
+{
+  ceph_assert(f);
+
+  f->open_object_section(type);
+  for (const auto& host : services) {
+    f->open_array_section(host.first.c_str());
+    const auto& hosted = host.second;
+    for (const auto& s : hosted) {
+      f->dump_string(type, s);
+    }
+    f->close_section();
+  }
+  f->close_section();
+}
 
 // If non-printable characters found then convert bufferlist to
 // base64 encoded string indicating whether it did.
-string cleanbin(bufferlist &bl, bool &base64)
+string cleanbin(bufferlist &bl, bool &base64, bool show)
 {
   bufferlist::iterator it;
   for (it = bl.begin(); it != bl.end(); ++it) {
@@ -223,6 +334,8 @@ string cleanbin(bufferlist &bl, bool &base64)
   bufferlist b64;
   bl.encode_base64(b64);
   string encoded(b64.c_str(), b64.length());
+  if (show)
+    encoded = "Base64:" + encoded;
   base64 = true;
   return encoded;
 }
@@ -234,9 +347,7 @@ string cleanbin(string &str)
   bool base64;
   bufferlist bl;
   bl.append(str);
-  string result = cleanbin(bl, base64);
-  if (base64)
-    result = "Base64:" + result;
+  string result = cleanbin(bl, base64, true);
   return result;
 }