]>
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>
37 int64_t unit_to_bytesize(string val
, ostream
*pss
)
41 *pss
<< "value is empty!";
45 char c
= val
[val
.length()-1];
48 if (val
.length() < 2) {
50 *pss
<< "invalid value: " << val
;
53 val
= val
.substr(0,val
.length()-1);
78 *pss
<< "unrecognized modifier '" << c
<< "'" << std::endl
;
83 if (val
[0] == '+' || val
[0] == '-') {
85 *pss
<< "expected numerical value, got: " << val
;
90 int64_t r
= strict_strtoll(val
.c_str(), 10, &err
);
91 if ((r
== 0) && !err
.empty()) {
98 *pss
<< "unable to parse positive integer '" << val
<< "'";
101 return (r
* (1LL << modifier
));
104 int get_fs_stats(ceph_data_stats_t
&stats
, const char *path
)
110 int err
= ::statfs(path
, &stbuf
);
115 stats
.byte_total
= stbuf
.f_blocks
* stbuf
.f_bsize
;
116 stats
.byte_used
= (stbuf
.f_blocks
- stbuf
.f_bfree
) * stbuf
.f_bsize
;
117 stats
.byte_avail
= stbuf
.f_bavail
* stbuf
.f_bsize
;
118 stats
.avail_percent
= (((float)stats
.byte_avail
/stats
.byte_total
)*100);
122 static char* value_sanitize(char *value
)
124 while (isspace(*value
) || *value
== '"')
127 char* end
= value
+ strlen(value
) - 1;
128 while (end
> value
&& (isspace(*end
) || *end
== '"'))
136 static bool value_set(char *buf
, const char *prefix
,
137 map
<string
, string
> *pm
, const char *key
)
139 if (strncmp(buf
, prefix
, strlen(prefix
))) {
143 (*pm
)[key
] = value_sanitize(buf
+ strlen(prefix
));
147 static void file_values_parse(const map
<string
, string
>& kvm
, FILE *fp
, map
<string
, string
> *m
, CephContext
*cct
) {
149 while (fgets(buf
, sizeof(buf
) - 1, fp
) != NULL
) {
150 for (auto& kv
: kvm
) {
151 if (value_set(buf
, kv
.second
.c_str(), m
, kv
.first
.c_str()))
157 static bool os_release_parse(map
<string
, string
> *m
, CephContext
*cct
)
159 static const map
<string
, string
> kvm
= {
161 { "distro_description", "PRETTY_NAME=" },
162 { "distro_version", "VERSION_ID=" }
165 FILE *fp
= fopen("/etc/os-release", "r");
168 lderr(cct
) << "os_release_parse - failed to open /etc/os-release: " << cpp_strerror(ret
) << dendl
;
172 file_values_parse(kvm
, fp
, m
, cct
);
179 static void distro_detect(map
<string
, string
> *m
, CephContext
*cct
)
181 if (!os_release_parse(m
, cct
)) {
182 lderr(cct
) << "distro_detect - /etc/os-release is required" << dendl
;
185 for (const char* rk
: {"distro", "distro_version"}) {
186 if (m
->find(rk
) == m
->end())
187 lderr(cct
) << "distro_detect - can't detect " << rk
<< dendl
;
191 void collect_sys_info(map
<string
, string
> *m
, CephContext
*cct
)
194 (*m
)["ceph_version"] = pretty_version_to_str();
200 (*m
)["os"] = u
.sysname
;
201 (*m
)["kernel_version"] = u
.release
;
202 (*m
)["kernel_description"] = u
.version
;
203 (*m
)["hostname"] = u
.nodename
;
204 (*m
)["arch"] = u
.machine
;
208 FILE *f
= fopen(PROCPREFIX
"/proc/meminfo", "r");
212 char *line
= fgets(buf
, sizeof(buf
), f
);
217 int r
= sscanf(line
, "%s %lld", key
, &value
);
219 if (strcmp(key
, "MemTotal:") == 0)
220 (*m
)["mem_total_kb"] = boost::lexical_cast
<string
>(value
);
221 else if (strcmp(key
, "SwapTotal:") == 0)
222 (*m
)["mem_swap_kb"] = boost::lexical_cast
<string
>(value
);
229 f
= fopen(PROCPREFIX
"/proc/cpuinfo", "r");
233 char *line
= fgets(buf
, sizeof(buf
), f
);
236 if (strncmp(line
, "model name", 10) == 0) {
237 char *c
= strchr(buf
, ':');
253 distro_detect(m
, cct
);
256 void dump_services(Formatter
* f
, const map
<string
, list
<int> >& services
, const char* type
)
260 f
->open_object_section(type
);
261 for (map
<string
, list
<int> >::const_iterator host
= services
.begin();
262 host
!= services
.end(); ++host
) {
263 f
->open_array_section(host
->first
.c_str());
264 const list
<int>& hosted
= host
->second
;
265 for (list
<int>::const_iterator s
= hosted
.begin();
266 s
!= hosted
.end(); ++s
) {
267 f
->dump_int(type
, *s
);
275 // If non-printable characters found then convert bufferlist to
276 // base64 encoded string indicating whether it did.
277 string
cleanbin(bufferlist
&bl
, bool &base64
)
279 bufferlist::iterator it
;
280 for (it
= bl
.begin(); it
!= bl
.end(); ++it
) {
284 if (it
== bl
.end()) {
286 string
result(bl
.c_str(), bl
.length());
291 bl
.encode_base64(b64
);
292 string
encoded(b64
.c_str(), b64
.length());
297 // If non-printable characters found then convert to "Base64:" followed by
299 string
cleanbin(string
&str
)
304 string result
= cleanbin(bl
, base64
);
306 result
= "Base64:" + result
;
310 std::string
bytes2str(uint64_t count
) {
311 static char s
[][2] = {"\0", "k", "M", "G", "T", "P", "E", "\0"};
313 while (count
>= 1024 && *s
[i
+1]) {
318 snprintf(str
, sizeof str
, "%" PRIu64
"%sB", count
, s
[i
]);
319 return std::string(str
);