]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/util.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2012 Inktank Storage, Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include <sys/utsname.h>
16 #include <boost/lexical_cast.hpp>
18 #include "include/compat.h"
19 #include "include/util.h"
20 #include "common/debug.h"
21 #include "common/errno.h"
22 #include "common/version.h"
28 #if defined(DARWIN) || defined(__FreeBSD__)
29 #include <sys/param.h>
30 #include <sys/mount.h>
33 int64_t unit_to_bytesize(string val
, ostream
*pss
)
37 *pss
<< "value is empty!";
41 char c
= val
[val
.length()-1];
44 if (val
.length() < 2) {
46 *pss
<< "invalid value: " << val
;
49 val
= val
.substr(0,val
.length()-1);
74 *pss
<< "unrecognized modifier '" << c
<< "'" << std::endl
;
79 if (val
[0] == '+' || val
[0] == '-') {
81 *pss
<< "expected numerical value, got: " << val
;
86 int64_t r
= strict_strtoll(val
.c_str(), 10, &err
);
87 if ((r
== 0) && !err
.empty()) {
94 *pss
<< "unable to parse positive integer '" << val
<< "'";
97 return (r
* (1LL << modifier
));
100 int get_fs_stats(ceph_data_stats_t
&stats
, const char *path
)
106 int err
= ::statfs(path
, &stbuf
);
111 stats
.byte_total
= stbuf
.f_blocks
* stbuf
.f_bsize
;
112 stats
.byte_used
= (stbuf
.f_blocks
- stbuf
.f_bfree
) * stbuf
.f_bsize
;
113 stats
.byte_avail
= stbuf
.f_bavail
* stbuf
.f_bsize
;
114 stats
.avail_percent
= (((float)stats
.byte_avail
/stats
.byte_total
)*100);
118 static char* value_sanitize(char *value
)
120 while (isspace(*value
) || *value
== '"')
123 char* end
= value
+ strlen(value
) - 1;
124 while (end
> value
&& (isspace(*end
) || *end
== '"'))
132 static bool value_set(char *buf
, const char *prefix
,
133 map
<string
, string
> *pm
, const char *key
)
135 if (strncmp(buf
, prefix
, strlen(prefix
))) {
139 (*pm
)[key
] = value_sanitize(buf
+ strlen(prefix
));
143 static void file_values_parse(const map
<string
, string
>& kvm
, FILE *fp
, map
<string
, string
> *m
, CephContext
*cct
) {
145 while (fgets(buf
, sizeof(buf
) - 1, fp
) != NULL
) {
146 for (auto& kv
: kvm
) {
147 if (value_set(buf
, kv
.second
.c_str(), m
, kv
.first
.c_str()))
153 static bool os_release_parse(map
<string
, string
> *m
, CephContext
*cct
)
155 static const map
<string
, string
> kvm
= {
157 { "distro_description", "PRETTY_NAME=" },
158 { "distro_version", "VERSION_ID=" }
161 FILE *fp
= fopen("/etc/os-release", "r");
164 lderr(cct
) << "os_release_parse - failed to open /etc/os-release: " << cpp_strerror(ret
) << dendl
;
168 file_values_parse(kvm
, fp
, m
, cct
);
175 static void distro_detect(map
<string
, string
> *m
, CephContext
*cct
)
177 if (!os_release_parse(m
, cct
)) {
178 lderr(cct
) << "distro_detect - /etc/os-release is required" << dendl
;
181 for (const char* rk
: {"distro", "distro_version"}) {
182 if (m
->find(rk
) == m
->end())
183 lderr(cct
) << "distro_detect - can't detect " << rk
<< dendl
;
187 void collect_sys_info(map
<string
, string
> *m
, CephContext
*cct
)
190 (*m
)["ceph_version"] = pretty_version_to_str();
196 (*m
)["os"] = u
.sysname
;
197 (*m
)["kernel_version"] = u
.release
;
198 (*m
)["kernel_description"] = u
.version
;
199 (*m
)["hostname"] = u
.nodename
;
200 (*m
)["arch"] = u
.machine
;
204 FILE *f
= fopen(PROCPREFIX
"/proc/meminfo", "r");
208 char *line
= fgets(buf
, sizeof(buf
), f
);
213 int r
= sscanf(line
, "%s %lld", key
, &value
);
215 if (strcmp(key
, "MemTotal:") == 0)
216 (*m
)["mem_total_kb"] = boost::lexical_cast
<string
>(value
);
217 else if (strcmp(key
, "SwapTotal:") == 0)
218 (*m
)["mem_swap_kb"] = boost::lexical_cast
<string
>(value
);
225 f
= fopen(PROCPREFIX
"/proc/cpuinfo", "r");
229 char *line
= fgets(buf
, sizeof(buf
), f
);
232 if (strncmp(line
, "model name", 10) == 0) {
233 char *c
= strchr(buf
, ':');
249 distro_detect(m
, cct
);
252 void dump_services(Formatter
* f
, const map
<string
, list
<int> >& services
, const char* type
)
256 f
->open_object_section(type
);
257 for (map
<string
, list
<int> >::const_iterator host
= services
.begin();
258 host
!= services
.end(); ++host
) {
259 f
->open_array_section(host
->first
.c_str());
260 const list
<int>& hosted
= host
->second
;
261 for (list
<int>::const_iterator s
= hosted
.begin();
262 s
!= hosted
.end(); ++s
) {
263 f
->dump_int(type
, *s
);
271 // If non-printable characters found then convert bufferlist to
272 // base64 encoded string indicating whether it did.
273 string
cleanbin(bufferlist
&bl
, bool &base64
)
275 bufferlist::iterator it
;
276 for (it
= bl
.begin(); it
!= bl
.end(); ++it
) {
280 if (it
== bl
.end()) {
282 string
result(bl
.c_str(), bl
.length());
287 bl
.encode_base64(b64
);
288 string
encoded(b64
.c_str(), b64
.length());
293 // If non-printable characters found then convert to "Base64:" followed by
295 string
cleanbin(string
&str
)
300 string result
= cleanbin(bl
, base64
);
302 result
= "Base64:" + result
;