mirror of
https://github.com/ceph/ceph
synced 2025-01-29 22:43:40 +00:00
Merge pull request #24830 from dillaman/wip-rbd-pool-stats
rbd: expose pool stats summary tool Reviewed-by: Mykola Golub <mgolub@suse.com>
This commit is contained in:
commit
56412bf6d2
@ -59,6 +59,7 @@ extern "C" {
|
||||
|
||||
typedef void *rbd_image_t;
|
||||
typedef void *rbd_image_options_t;
|
||||
typedef void *rbd_pool_stats_t;
|
||||
|
||||
typedef void *rbd_completion_t;
|
||||
typedef void (*rbd_callback_t)(rbd_completion_t cb, void *arg);
|
||||
@ -264,6 +265,17 @@ typedef struct {
|
||||
rbd_config_source_t source;
|
||||
} rbd_config_option_t;
|
||||
|
||||
typedef enum {
|
||||
RBD_POOL_STAT_OPTION_IMAGES,
|
||||
RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES,
|
||||
RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
|
||||
RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS,
|
||||
RBD_POOL_STAT_OPTION_TRASH_IMAGES,
|
||||
RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES,
|
||||
RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
|
||||
RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS
|
||||
} rbd_pool_stat_option_t;
|
||||
|
||||
CEPH_RBD_API void rbd_image_options_create(rbd_image_options_t* opts);
|
||||
CEPH_RBD_API void rbd_image_options_destroy(rbd_image_options_t opts);
|
||||
CEPH_RBD_API int rbd_image_options_set_string(rbd_image_options_t opts,
|
||||
@ -1103,9 +1115,19 @@ CEPH_RBD_API int rbd_namespace_remove(rados_ioctx_t io,
|
||||
const char *namespace_name);
|
||||
CEPH_RBD_API int rbd_namespace_list(rados_ioctx_t io, char *namespace_names,
|
||||
size_t *size);
|
||||
CEPH_RBD_API int rbd_namespace_exists(rados_ioctx_t io, const char *namespace_name,
|
||||
CEPH_RBD_API int rbd_namespace_exists(rados_ioctx_t io,
|
||||
const char *namespace_name,
|
||||
bool *exists);
|
||||
|
||||
CEPH_RBD_API int rbd_pool_init(rados_ioctx_t io, bool force);
|
||||
|
||||
CEPH_RBD_API void rbd_pool_stats_create(rbd_pool_stats_t *stats);
|
||||
CEPH_RBD_API void rbd_pool_stats_destroy(rbd_pool_stats_t stats);
|
||||
CEPH_RBD_API int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
|
||||
int stat_option,
|
||||
uint64_t* stat_val);
|
||||
CEPH_RBD_API int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@ namespace librbd {
|
||||
|
||||
class Image;
|
||||
class ImageOptions;
|
||||
class PoolStats;
|
||||
typedef void *image_ctx_t;
|
||||
typedef void *completion_t;
|
||||
typedef void (*callback_t)(completion_t cb, void *arg);
|
||||
@ -290,6 +291,9 @@ public:
|
||||
int namespace_list(IoCtx& io_ctx, std::vector<std::string>* namespace_names);
|
||||
int namespace_exists(IoCtx& io_ctx, const char *namespace_name, bool *exists);
|
||||
|
||||
int pool_init(IoCtx& io_ctx, bool force);
|
||||
int pool_stats_get(IoCtx& io_ctx, PoolStats *pool_stats);
|
||||
|
||||
int pool_metadata_get(IoCtx &io_ctx, const std::string &key,
|
||||
std::string *value);
|
||||
int pool_metadata_set(IoCtx &io_ctx, const std::string &key,
|
||||
@ -329,6 +333,22 @@ private:
|
||||
rbd_image_options_t opts;
|
||||
};
|
||||
|
||||
class CEPH_RBD_API PoolStats {
|
||||
public:
|
||||
PoolStats();
|
||||
~PoolStats();
|
||||
|
||||
PoolStats(const PoolStats&) = delete;
|
||||
PoolStats& operator=(const PoolStats&) = delete;
|
||||
|
||||
int add(rbd_pool_stat_option_t option, uint64_t* opt_val);
|
||||
|
||||
private:
|
||||
friend class RBD;
|
||||
|
||||
rbd_pool_stats_t pool_stats;
|
||||
};
|
||||
|
||||
class CEPH_RBD_API UpdateWatchCtx {
|
||||
public:
|
||||
virtual ~UpdateWatchCtx() {}
|
||||
|
@ -31,6 +31,7 @@ set(librbd_internal_srcs
|
||||
api/Migration.cc
|
||||
api/Mirror.cc
|
||||
api/Namespace.cc
|
||||
api/Pool.cc
|
||||
api/PoolMetadata.cc
|
||||
api/Snapshot.cc
|
||||
api/Trash.cc
|
||||
|
354
src/librbd/api/Pool.cc
Normal file
354
src/librbd/api/Pool.cc
Normal file
@ -0,0 +1,354 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#include "librbd/api/Pool.h"
|
||||
#include "include/rados/librados.hpp"
|
||||
#include "common/dout.h"
|
||||
#include "common/errno.h"
|
||||
#include "common/Throttle.h"
|
||||
#include "cls/rbd/cls_rbd_client.h"
|
||||
#include "osd/osd_types.h"
|
||||
#include "librbd/Utils.h"
|
||||
#include "librbd/api/Config.h"
|
||||
#include "librbd/api/Image.h"
|
||||
#include "librbd/api/Trash.h"
|
||||
|
||||
#define dout_subsys ceph_subsys_rbd
|
||||
|
||||
namespace librbd {
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
#undef dout_prefix
|
||||
#define dout_prefix *_dout << "librbd::api::Pool::ImageStatRequest: " \
|
||||
<< __func__ << " " << this << ": " \
|
||||
<< "(id=" << m_image_id << "): "
|
||||
|
||||
template <typename I>
|
||||
class ImageStatRequest {
|
||||
public:
|
||||
ImageStatRequest(librados::IoCtx& io_ctx, SimpleThrottle& throttle,
|
||||
const std::string& image_id, bool scan_snaps,
|
||||
std::atomic<uint64_t>* bytes,
|
||||
std::atomic<uint64_t>* max_bytes,
|
||||
std::atomic<uint64_t>* snaps)
|
||||
: m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())),
|
||||
m_io_ctx(io_ctx), m_throttle(throttle), m_image_id(image_id),
|
||||
m_scan_snaps(scan_snaps), m_bytes(bytes), m_max_bytes(max_bytes),
|
||||
m_snaps(snaps) {
|
||||
m_throttle.start_op();
|
||||
}
|
||||
|
||||
void send() {
|
||||
get_head();
|
||||
}
|
||||
|
||||
protected:
|
||||
void finish(int r) {
|
||||
(*m_max_bytes) += m_max_size;
|
||||
m_throttle.end_op(r);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
CephContext* m_cct;
|
||||
librados::IoCtx& m_io_ctx;
|
||||
SimpleThrottle& m_throttle;
|
||||
const std::string& m_image_id;
|
||||
bool m_scan_snaps;
|
||||
std::atomic<uint64_t>* m_bytes;
|
||||
std::atomic<uint64_t>* m_max_bytes;
|
||||
std::atomic<uint64_t>* m_snaps;
|
||||
bufferlist m_out_bl;
|
||||
|
||||
uint64_t m_max_size = 0;
|
||||
::SnapContext m_snapc;
|
||||
|
||||
void get_head() {
|
||||
ldout(m_cct, 15) << dendl;
|
||||
|
||||
librados::ObjectReadOperation op;
|
||||
cls_client::get_size_start(&op, CEPH_NOSNAP);
|
||||
if (m_scan_snaps) {
|
||||
cls_client::get_snapcontext_start(&op);
|
||||
}
|
||||
|
||||
m_out_bl.clear();
|
||||
auto aio_comp = util::create_rados_callback<
|
||||
ImageStatRequest<I>, &ImageStatRequest<I>::handle_get_head>(this);
|
||||
int r = m_io_ctx.aio_operate(util::header_name(m_image_id), aio_comp, &op,
|
||||
&m_out_bl);
|
||||
ceph_assert(r == 0);
|
||||
aio_comp->release();
|
||||
}
|
||||
|
||||
void handle_get_head(int r) {
|
||||
ldout(m_cct, 15) << "r=" << r << dendl;
|
||||
|
||||
auto it = m_out_bl.cbegin();
|
||||
if (r == 0) {
|
||||
uint8_t order;
|
||||
r = cls_client::get_size_finish(&it, &m_max_size, &order);
|
||||
if (r == 0) {
|
||||
(*m_bytes) += m_max_size;
|
||||
}
|
||||
}
|
||||
if (m_scan_snaps && r == 0) {
|
||||
r = cls_client::get_snapcontext_finish(&it, &m_snapc);
|
||||
if (r == 0) {
|
||||
(*m_snaps) += m_snapc.snaps.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (r == -ENOENT) {
|
||||
finish(r);
|
||||
return;
|
||||
} else if (r < 0) {
|
||||
lderr(m_cct) << "failed to stat image: " << cpp_strerror(r) << dendl;
|
||||
finish(r);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_snapc.is_valid()) {
|
||||
lderr(m_cct) << "snap context is invalid" << dendl;
|
||||
finish(-EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
get_snaps();
|
||||
}
|
||||
|
||||
void get_snaps() {
|
||||
if (!m_scan_snaps || m_snapc.snaps.empty()) {
|
||||
finish(0);
|
||||
return;
|
||||
}
|
||||
|
||||
ldout(m_cct, 15) << dendl;
|
||||
librados::ObjectReadOperation op;
|
||||
for (auto snap_seq : m_snapc.snaps) {
|
||||
cls_client::get_size_start(&op, snap_seq);
|
||||
}
|
||||
|
||||
m_out_bl.clear();
|
||||
auto aio_comp = util::create_rados_callback<
|
||||
ImageStatRequest<I>, &ImageStatRequest<I>::handle_get_snaps>(this);
|
||||
int r = m_io_ctx.aio_operate(util::header_name(m_image_id), aio_comp, &op,
|
||||
&m_out_bl);
|
||||
ceph_assert(r == 0);
|
||||
aio_comp->release();
|
||||
}
|
||||
|
||||
void handle_get_snaps(int r) {
|
||||
ldout(m_cct, 15) << "r=" << r << dendl;
|
||||
|
||||
auto it = m_out_bl.cbegin();
|
||||
for ([[maybe_unused]] auto snap_seq : m_snapc.snaps) {
|
||||
uint64_t size;
|
||||
if (r == 0) {
|
||||
uint8_t order;
|
||||
r = cls_client::get_size_finish(&it, &size, &order);
|
||||
}
|
||||
if (r == 0 && m_max_size < size) {
|
||||
m_max_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
if (r == -ENOENT) {
|
||||
ldout(m_cct, 15) << "out-of-sync metadata" << dendl;
|
||||
get_head();
|
||||
} else if (r < 0) {
|
||||
lderr(m_cct) << "failed to retrieve snap size: " << cpp_strerror(r)
|
||||
<< dendl;
|
||||
finish(r);
|
||||
} else {
|
||||
finish(0);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
void get_pool_stat_option_value(typename Pool<I>::StatOptions* stat_options,
|
||||
rbd_pool_stat_option_t option,
|
||||
uint64_t** value) {
|
||||
auto it = stat_options->find(option);
|
||||
if (it == stat_options->end()) {
|
||||
*value = nullptr;
|
||||
} else {
|
||||
*value = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
int get_pool_stats(librados::IoCtx& io_ctx, const ConfigProxy& config,
|
||||
const std::vector<std::string>& image_ids, uint64_t* image_count,
|
||||
uint64_t* provisioned_bytes, uint64_t* max_provisioned_bytes,
|
||||
uint64_t* snapshot_count) {
|
||||
|
||||
bool scan_snaps = ((max_provisioned_bytes != nullptr) ||
|
||||
(snapshot_count != nullptr));
|
||||
|
||||
SimpleThrottle throttle(
|
||||
config.template get_val<uint64_t>("rbd_concurrent_management_ops"), true);
|
||||
std::atomic<uint64_t> bytes{0};
|
||||
std::atomic<uint64_t> max_bytes{0};
|
||||
std::atomic<uint64_t> snaps{0};
|
||||
for (auto& image_id : image_ids) {
|
||||
if (throttle.pending_error()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto req = new ImageStatRequest<I>(io_ctx, throttle, image_id,
|
||||
scan_snaps, &bytes, &max_bytes, &snaps);
|
||||
req->send();
|
||||
}
|
||||
|
||||
int r = throttle.wait_for_ret();
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (image_count != nullptr) {
|
||||
*image_count = image_ids.size();
|
||||
}
|
||||
if (provisioned_bytes != nullptr) {
|
||||
*provisioned_bytes = bytes.load();
|
||||
}
|
||||
if (max_provisioned_bytes != nullptr) {
|
||||
*max_provisioned_bytes = max_bytes.load();
|
||||
}
|
||||
if (snapshot_count != nullptr) {
|
||||
*snapshot_count = snaps.load();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#undef dout_prefix
|
||||
#define dout_prefix *_dout << "librbd::api::Pool: " << __func__ << ": "
|
||||
|
||||
template <typename I>
|
||||
int Pool<I>::init(librados::IoCtx& io_ctx, bool force) {
|
||||
auto cct = reinterpret_cast<CephContext*>(io_ctx.cct());
|
||||
ldout(cct, 10) << dendl;
|
||||
|
||||
int r = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RBD, force);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
// TODO configure self-managed snapshots (and other one-time pool checks)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
int Pool<I>::add_stat_option(StatOptions* stat_options,
|
||||
rbd_pool_stat_option_t option,
|
||||
uint64_t* value) {
|
||||
switch (option) {
|
||||
case RBD_POOL_STAT_OPTION_IMAGES:
|
||||
case RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES:
|
||||
case RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES:
|
||||
case RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS:
|
||||
case RBD_POOL_STAT_OPTION_TRASH_IMAGES:
|
||||
case RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES:
|
||||
case RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES:
|
||||
case RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS:
|
||||
stat_options->emplace(option, value);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
int Pool<I>::get_stats(librados::IoCtx& io_ctx, StatOptions* stat_options) {
|
||||
auto cct = reinterpret_cast<CephContext*>(io_ctx.cct());
|
||||
ldout(cct, 10) << dendl;
|
||||
|
||||
ConfigProxy config{cct->_conf};
|
||||
api::Config<I>::apply_pool_overrides(io_ctx, &config);
|
||||
|
||||
uint64_t* image_count;
|
||||
uint64_t* provisioned_bytes;
|
||||
uint64_t* max_provisioned_bytes;
|
||||
uint64_t* snapshot_count;
|
||||
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_IMAGES, &image_count);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES,
|
||||
&provisioned_bytes);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
|
||||
&max_provisioned_bytes);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS, &snapshot_count);
|
||||
if (image_count != nullptr || provisioned_bytes != nullptr ||
|
||||
max_provisioned_bytes != nullptr || snapshot_count != nullptr) {
|
||||
typename Image<I>::ImageNameToIds images;
|
||||
int r = Image<I>::list_images(io_ctx, &images);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<std::string> image_ids;
|
||||
image_ids.reserve(images.size());
|
||||
for (auto& it : images) {
|
||||
image_ids.push_back(std::move(it.second));
|
||||
}
|
||||
|
||||
r = get_pool_stats<I>(io_ctx, config, image_ids, image_count,
|
||||
provisioned_bytes, max_provisioned_bytes,
|
||||
snapshot_count);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_TRASH_IMAGES, &image_count);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES,
|
||||
&provisioned_bytes);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
|
||||
&max_provisioned_bytes);
|
||||
get_pool_stat_option_value<I>(
|
||||
stat_options, RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS, &snapshot_count);
|
||||
if (image_count != nullptr || provisioned_bytes != nullptr ||
|
||||
max_provisioned_bytes != nullptr || snapshot_count != nullptr) {
|
||||
std::vector<trash_image_info_t> trash_entries;
|
||||
int r = Trash<I>::list(io_ctx, trash_entries);
|
||||
if (r < 0 && r != -EOPNOTSUPP) {
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<std::string> image_ids;
|
||||
image_ids.reserve(trash_entries.size());
|
||||
for (auto& it : trash_entries) {
|
||||
image_ids.push_back(std::move(it.id));
|
||||
}
|
||||
|
||||
r = get_pool_stats<I>(io_ctx, config, image_ids, image_count,
|
||||
provisioned_bytes, max_provisioned_bytes,
|
||||
snapshot_count);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace librbd
|
||||
|
||||
template class librbd::api::Pool<librbd::ImageCtx>;
|
39
src/librbd/api/Pool.h
Normal file
39
src/librbd/api/Pool.h
Normal file
@ -0,0 +1,39 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#ifndef CEPH_LIBRBD_API_POOL_H
|
||||
#define CEPH_LIBRBD_API_POOL_H
|
||||
|
||||
#include "include/int_types.h"
|
||||
#include "include/rbd/librbd.h"
|
||||
#include <map>
|
||||
|
||||
namespace librados { class IoCtx; }
|
||||
|
||||
namespace librbd {
|
||||
|
||||
struct ImageCtx;
|
||||
|
||||
namespace api {
|
||||
|
||||
template <typename ImageCtxT = librbd::ImageCtx>
|
||||
class Pool {
|
||||
public:
|
||||
typedef std::map<rbd_pool_stat_option_t, uint64_t*> StatOptions;
|
||||
|
||||
static int init(librados::IoCtx& io_ctx, bool force);
|
||||
|
||||
static int add_stat_option(StatOptions* stat_options,
|
||||
rbd_pool_stat_option_t option,
|
||||
uint64_t* value);
|
||||
|
||||
static int get_stats(librados::IoCtx& io_ctx, StatOptions* stat_options);
|
||||
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
} // namespace librbd
|
||||
|
||||
extern template class librbd::api::Pool<librbd::ImageCtx>;
|
||||
|
||||
#endif // CEPH_LIBRBD_API_POOL_H
|
@ -33,6 +33,7 @@
|
||||
#include "librbd/api/Migration.h"
|
||||
#include "librbd/api/Mirror.h"
|
||||
#include "librbd/api/Namespace.h"
|
||||
#include "librbd/api/Pool.h"
|
||||
#include "librbd/api/PoolMetadata.h"
|
||||
#include "librbd/api/Snapshot.h"
|
||||
#include "librbd/api/Trash.h"
|
||||
@ -284,8 +285,23 @@ namespace librbd {
|
||||
};
|
||||
|
||||
/*
|
||||
RBD
|
||||
*/
|
||||
* Pool stats
|
||||
*/
|
||||
PoolStats::PoolStats() {
|
||||
rbd_pool_stats_create(&pool_stats);
|
||||
}
|
||||
|
||||
PoolStats::~PoolStats() {
|
||||
rbd_pool_stats_destroy(pool_stats);
|
||||
}
|
||||
|
||||
int PoolStats::add(rbd_pool_stat_option_t option, uint64_t* opt_val) {
|
||||
return rbd_pool_stats_option_add_uint64(pool_stats, option, opt_val);
|
||||
}
|
||||
|
||||
/*
|
||||
* RBD
|
||||
*/
|
||||
RBD::RBD()
|
||||
{
|
||||
}
|
||||
@ -650,6 +666,16 @@ namespace librbd {
|
||||
return librbd::api::Namespace<>::exists(io_ctx, namespace_name, exists);
|
||||
}
|
||||
|
||||
int RBD::pool_init(IoCtx& io_ctx, bool force) {
|
||||
return librbd::api::Pool<>::init(io_ctx, force);
|
||||
}
|
||||
|
||||
int RBD::pool_stats_get(IoCtx& io_ctx, PoolStats* stats) {
|
||||
auto pool_stat_options =
|
||||
reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats->pool_stats);
|
||||
return librbd::api::Pool<>::get_stats(io_ctx, pool_stat_options);
|
||||
}
|
||||
|
||||
int RBD::list(IoCtx& io_ctx, vector<string>& names)
|
||||
{
|
||||
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
|
||||
@ -3036,6 +3062,44 @@ extern "C" int rbd_namespace_exists(rados_ioctx_t io,
|
||||
return librbd::api::Namespace<>::exists(io_ctx, namespace_name, exists);
|
||||
}
|
||||
|
||||
extern "C" int rbd_pool_init(rados_ioctx_t io, bool force) {
|
||||
librados::IoCtx io_ctx;
|
||||
librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
|
||||
|
||||
return librbd::api::Pool<>::init(io_ctx, force);
|
||||
}
|
||||
|
||||
extern "C" void rbd_pool_stats_create(rbd_pool_stats_t *stats) {
|
||||
*stats = reinterpret_cast<rbd_pool_stats_t>(
|
||||
new librbd::api::Pool<>::StatOptions{});
|
||||
}
|
||||
|
||||
extern "C" void rbd_pool_stats_destroy(rbd_pool_stats_t stats) {
|
||||
auto pool_stat_options =
|
||||
reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
|
||||
delete pool_stat_options;
|
||||
}
|
||||
|
||||
extern "C" int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
|
||||
int stat_option,
|
||||
uint64_t* stat_val) {
|
||||
auto pool_stat_options =
|
||||
reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
|
||||
return librbd::api::Pool<>::add_stat_option(
|
||||
pool_stat_options, static_cast<rbd_pool_stat_option_t>(stat_option),
|
||||
stat_val);
|
||||
}
|
||||
|
||||
extern "C" int rbd_pool_stats_get(
|
||||
rados_ioctx_t io, rbd_pool_stats_t pool_stats) {
|
||||
librados::IoCtx io_ctx;
|
||||
librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
|
||||
|
||||
auto pool_stat_options =
|
||||
reinterpret_cast<librbd::api::Pool<>::StatOptions*>(pool_stats);
|
||||
return librbd::api::Pool<>::get_stats(io_ctx, pool_stat_options);
|
||||
}
|
||||
|
||||
extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
|
||||
const char *destname)
|
||||
{
|
||||
|
@ -87,6 +87,7 @@ cdef extern from "rbd/librbd.h" nogil:
|
||||
ctypedef void* rados_ioctx_t
|
||||
ctypedef void* rbd_image_t
|
||||
ctypedef void* rbd_image_options_t
|
||||
ctypedef void* rbd_pool_stats_t
|
||||
ctypedef void *rbd_completion_t
|
||||
|
||||
ctypedef struct rbd_image_info_t:
|
||||
@ -228,6 +229,16 @@ cdef extern from "rbd/librbd.h" nogil:
|
||||
char *value
|
||||
rbd_config_source_t source
|
||||
|
||||
ctypedef enum rbd_pool_stat_option_t:
|
||||
_RBD_POOL_STAT_OPTION_IMAGES "RBD_POOL_STAT_OPTION_IMAGES"
|
||||
_RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES"
|
||||
_RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES"
|
||||
_RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS "RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS"
|
||||
_RBD_POOL_STAT_OPTION_TRASH_IMAGES "RBD_POOL_STAT_OPTION_TRASH_IMAGES"
|
||||
_RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES"
|
||||
_RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES"
|
||||
_RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS "RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS"
|
||||
|
||||
ctypedef void (*rbd_callback_t)(rbd_completion_t cb, void *arg)
|
||||
ctypedef int (*librbd_progress_fn_t)(uint64_t offset, uint64_t total, void* ptr)
|
||||
|
||||
@ -536,6 +547,14 @@ cdef extern from "rbd/librbd.h" nogil:
|
||||
void rbd_config_image_list_cleanup(rbd_config_option_t *options,
|
||||
int max_options)
|
||||
|
||||
int rbd_pool_init(rados_ioctx_t, bint force)
|
||||
|
||||
void rbd_pool_stats_create(rbd_pool_stats_t *stats)
|
||||
void rbd_pool_stats_destroy(rbd_pool_stats_t stats)
|
||||
int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
|
||||
int stat_option, uint64_t* stat_val)
|
||||
int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats)
|
||||
|
||||
RBD_FEATURE_LAYERING = _RBD_FEATURE_LAYERING
|
||||
RBD_FEATURE_STRIPINGV2 = _RBD_FEATURE_STRIPINGV2
|
||||
RBD_FEATURE_EXCLUSIVE_LOCK = _RBD_FEATURE_EXCLUSIVE_LOCK
|
||||
@ -607,6 +626,16 @@ RBD_CONFIG_SOURCE_CONFIG = _RBD_CONFIG_SOURCE_CONFIG
|
||||
RBD_CONFIG_SOURCE_POOL = _RBD_CONFIG_SOURCE_POOL
|
||||
RBD_CONFIG_SOURCE_IMAGE = _RBD_CONFIG_SOURCE_IMAGE
|
||||
|
||||
RBD_POOL_STAT_OPTION_IMAGES = _RBD_POOL_STAT_OPTION_IMAGES
|
||||
RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES
|
||||
RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES
|
||||
RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS = _RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS
|
||||
RBD_POOL_STAT_OPTION_TRASH_IMAGES = _RBD_POOL_STAT_OPTION_TRASH_IMAGES
|
||||
RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES
|
||||
RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES
|
||||
RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS = _RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
@ -1818,6 +1847,94 @@ class RBD(object):
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error renaming group')
|
||||
|
||||
def pool_init(self, ioctx, force):
|
||||
"""
|
||||
Initialize an RBD pool
|
||||
:param ioctx: determines which RADOS pool
|
||||
:type ioctx: :class:`rados.Ioctx`
|
||||
:param force: force init
|
||||
:type force: bool
|
||||
"""
|
||||
cdef:
|
||||
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
|
||||
bint _force = force
|
||||
with nogil:
|
||||
ret = rbd_pool_init(_ioctx, _force)
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error initializing pool')
|
||||
|
||||
def pool_stats_get(self, ioctx):
|
||||
"""
|
||||
Return RBD pool stats
|
||||
|
||||
:param ioctx: determines which RADOS pool
|
||||
:type ioctx: :class:`rados.Ioctx`
|
||||
:returns: dict - contains the following keys:
|
||||
|
||||
* ``image_count`` (int) - image count
|
||||
|
||||
* ``image_provisioned_bytes`` (int) - image total HEAD provisioned bytes
|
||||
|
||||
* ``image_max_provisioned_bytes`` (int) - image total max provisioned bytes
|
||||
|
||||
* ``image_snap_count`` (int) - image snap count
|
||||
|
||||
* ``trash_count`` (int) - trash image count
|
||||
|
||||
* ``trash_provisioned_bytes`` (int) - trash total HEAD provisioned bytes
|
||||
|
||||
* ``trash_max_provisioned_bytes`` (int) - trash total max provisioned bytes
|
||||
|
||||
* ``trash_snap_count`` (int) - trash snap count
|
||||
|
||||
"""
|
||||
cdef:
|
||||
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
|
||||
uint64_t _image_count = 0
|
||||
uint64_t _image_provisioned_bytes = 0
|
||||
uint64_t _image_max_provisioned_bytes = 0
|
||||
uint64_t _image_snap_count = 0
|
||||
uint64_t _trash_count = 0
|
||||
uint64_t _trash_provisioned_bytes = 0
|
||||
uint64_t _trash_max_provisioned_bytes = 0
|
||||
uint64_t _trash_snap_count = 0
|
||||
rbd_pool_stats_t _stats
|
||||
|
||||
rbd_pool_stats_create(&_stats)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGES,
|
||||
&_image_count)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES,
|
||||
&_image_provisioned_bytes)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
|
||||
&_image_max_provisioned_bytes)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS,
|
||||
&_image_snap_count)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_IMAGES,
|
||||
&_trash_count)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES,
|
||||
&_trash_provisioned_bytes)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
|
||||
&_trash_max_provisioned_bytes)
|
||||
rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS,
|
||||
&_trash_snap_count)
|
||||
try:
|
||||
with nogil:
|
||||
ret = rbd_pool_stats_get(_ioctx, _stats)
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error retrieving pool stats')
|
||||
else:
|
||||
return {'image_count': _image_count,
|
||||
'image_provisioned_bytes': _image_provisioned_bytes,
|
||||
'image_max_provisioned_bytes': _image_max_provisioned_bytes,
|
||||
'image_snap_count': _image_snap_count,
|
||||
'trash_count': _trash_count,
|
||||
'trash_provisioned_bytes': _trash_provisioned_bytes,
|
||||
'trash_max_provisioned_bytes': _trash_max_provisioned_bytes,
|
||||
'trash_snap_count': _trash_snap_count}
|
||||
finally:
|
||||
rbd_pool_stats_destroy(_stats)
|
||||
|
||||
|
||||
cdef class MirrorPeerIterator(object):
|
||||
"""
|
||||
Iterator over mirror peer info for a pool.
|
||||
|
@ -107,6 +107,7 @@
|
||||
object-map check Verify the object map is correct.
|
||||
object-map rebuild Rebuild an invalid object map.
|
||||
pool init Initialize pool for use by RBD.
|
||||
pool stats Display pool statistics.
|
||||
remove (rm) Delete an image.
|
||||
rename (mv) Rename image within pool.
|
||||
resize Resize (expand or shrink) image.
|
||||
@ -1837,6 +1838,23 @@
|
||||
--force force initialize pool for RBD use if registered by
|
||||
another application
|
||||
|
||||
rbd help pool stats
|
||||
usage: rbd pool stats [--pool <pool>] [--namespace <namespace>]
|
||||
[--format <format>] [--pretty-format]
|
||||
<pool-name>
|
||||
|
||||
Display pool statistics.
|
||||
|
||||
Positional arguments
|
||||
<pool-name> pool name
|
||||
|
||||
Optional arguments
|
||||
-p [ --pool ] arg pool name
|
||||
--namespace arg namespace name
|
||||
--format arg output format (plain, json, or xml) [default: plain]
|
||||
--pretty-format pretty formatting (json and xml)
|
||||
|
||||
Note: legacy v1 images are not included in stats
|
||||
rbd help remove
|
||||
usage: rbd remove [--pool <pool>] [--namespace <namespace>] [--image <image>]
|
||||
[--no-progress]
|
||||
|
@ -7363,6 +7363,82 @@ TEST_F(TestLibRBD, ConfigPP)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestLibRBD, PoolStatsPP)
|
||||
{
|
||||
REQUIRE_FORMAT_V2();
|
||||
|
||||
librados::IoCtx ioctx;
|
||||
ASSERT_EQ(0, _rados.ioctx_create(create_pool(true).c_str(), ioctx));
|
||||
|
||||
librbd::RBD rbd;
|
||||
std::string image_name;
|
||||
uint64_t size = 2 << 20;
|
||||
uint64_t expected_size = 0;
|
||||
for (size_t idx = 0; idx < 4; ++idx) {
|
||||
image_name = get_temp_image_name();
|
||||
|
||||
int order = 0;
|
||||
ASSERT_EQ(0, create_image_pp(rbd, ioctx, image_name.c_str(), size, &order));
|
||||
expected_size += size;
|
||||
}
|
||||
|
||||
librbd::Image image;
|
||||
ASSERT_EQ(0, rbd.open(ioctx, image, image_name.c_str(), NULL));
|
||||
ASSERT_EQ(0, image.snap_create("snap1"));
|
||||
ASSERT_EQ(0, image.resize(0));
|
||||
ASSERT_EQ(0, image.close());
|
||||
uint64_t expect_head_size = (expected_size - size);
|
||||
|
||||
uint64_t image_count;
|
||||
uint64_t provisioned_bytes;
|
||||
uint64_t max_provisioned_bytes;
|
||||
uint64_t snap_count;
|
||||
uint64_t trash_image_count;
|
||||
uint64_t trash_provisioned_bytes;
|
||||
uint64_t trash_max_provisioned_bytes;
|
||||
uint64_t trash_snap_count;
|
||||
|
||||
librbd::PoolStats pool_stats1;
|
||||
pool_stats1.add(RBD_POOL_STAT_OPTION_IMAGES, &image_count);
|
||||
pool_stats1.add(RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES,
|
||||
&provisioned_bytes);
|
||||
ASSERT_EQ(0, rbd.pool_stats_get(ioctx, &pool_stats1));
|
||||
|
||||
ASSERT_EQ(4U, image_count);
|
||||
ASSERT_EQ(expect_head_size, provisioned_bytes);
|
||||
|
||||
pool_stats1.add(RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
|
||||
&max_provisioned_bytes);
|
||||
ASSERT_EQ(0, rbd.pool_stats_get(ioctx, &pool_stats1));
|
||||
ASSERT_EQ(4U, image_count);
|
||||
ASSERT_EQ(expect_head_size, provisioned_bytes);
|
||||
ASSERT_EQ(expected_size, max_provisioned_bytes);
|
||||
|
||||
librbd::PoolStats pool_stats2;
|
||||
pool_stats2.add(RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS, &snap_count);
|
||||
pool_stats2.add(RBD_POOL_STAT_OPTION_TRASH_IMAGES, &trash_image_count);
|
||||
pool_stats2.add(RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS, &trash_snap_count);
|
||||
ASSERT_EQ(0, rbd.pool_stats_get(ioctx, &pool_stats2));
|
||||
ASSERT_EQ(1U, snap_count);
|
||||
ASSERT_EQ(0U, trash_image_count);
|
||||
ASSERT_EQ(0U, trash_snap_count);
|
||||
|
||||
ASSERT_EQ(0, rbd.trash_move(ioctx, image_name.c_str(), 0));
|
||||
|
||||
librbd::PoolStats pool_stats3;
|
||||
pool_stats3.add(RBD_POOL_STAT_OPTION_TRASH_IMAGES, &trash_image_count);
|
||||
pool_stats3.add(RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES,
|
||||
&trash_provisioned_bytes);
|
||||
pool_stats3.add(RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
|
||||
&trash_max_provisioned_bytes);
|
||||
pool_stats3.add(RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS, &trash_snap_count);
|
||||
ASSERT_EQ(0, rbd.pool_stats_get(ioctx, &pool_stats3));
|
||||
ASSERT_EQ(1U, trash_image_count);
|
||||
ASSERT_EQ(0U, trash_provisioned_bytes);
|
||||
ASSERT_EQ(size, trash_max_provisioned_bytes);
|
||||
ASSERT_EQ(1U, trash_snap_count);
|
||||
}
|
||||
|
||||
// poorman's ceph_assert()
|
||||
namespace ceph {
|
||||
void __ceph_assert_fail(const char *assertion, const char *file, int line,
|
||||
|
@ -115,9 +115,9 @@ int create_image_data_pool(librados::Rados &rados, std::string &data_pool, bool
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
ioctx.application_enable("rbd", true);
|
||||
|
||||
return r;
|
||||
librbd::RBD rbd;
|
||||
return rbd.pool_init(ioctx, true);
|
||||
}
|
||||
|
||||
bool is_librados_test_stub(librados::Rados &rados) {
|
||||
|
@ -51,7 +51,7 @@ def setup_module():
|
||||
rados.create_pool(pool_name)
|
||||
global ioctx
|
||||
ioctx = rados.open_ioctx(pool_name)
|
||||
ioctx.application_enable('rbd')
|
||||
RBD().pool_init(ioctx, True)
|
||||
global features
|
||||
features = os.getenv("RBD_FEATURES")
|
||||
features = int(features) if features is not None else 61
|
||||
@ -92,6 +92,7 @@ def create_image():
|
||||
features=int(features))
|
||||
else:
|
||||
RBD().create(ioctx, image_name, IMG_SIZE, IMG_ORDER, old_format=True)
|
||||
return image_name
|
||||
|
||||
def remove_image():
|
||||
if image_name is not None:
|
||||
@ -377,6 +378,36 @@ def test_config_list():
|
||||
for option in rbd.config_list(ioctx):
|
||||
eq(option['source'], RBD_CONFIG_SOURCE_CONFIG)
|
||||
|
||||
@require_new_format()
|
||||
def test_pool_stats():
|
||||
rbd = RBD()
|
||||
|
||||
try:
|
||||
image1 = create_image()
|
||||
image2 = create_image()
|
||||
image3 = create_image()
|
||||
image4 = create_image()
|
||||
with Image(ioctx, image4) as image:
|
||||
image.create_snap('snap')
|
||||
image.resize(0)
|
||||
|
||||
stats = rbd.pool_stats_get(ioctx)
|
||||
eq(stats['image_count'], 4)
|
||||
eq(stats['image_provisioned_bytes'], 3 * IMG_SIZE)
|
||||
eq(stats['image_max_provisioned_bytes'], 4 * IMG_SIZE)
|
||||
eq(stats['image_snap_count'], 1)
|
||||
eq(stats['trash_count'], 0)
|
||||
eq(stats['trash_provisioned_bytes'], 0)
|
||||
eq(stats['trash_max_provisioned_bytes'], 0)
|
||||
eq(stats['trash_snap_count'], 0)
|
||||
finally:
|
||||
rbd.remove(ioctx, image1)
|
||||
rbd.remove(ioctx, image2)
|
||||
rbd.remove(ioctx, image3)
|
||||
with Image(ioctx, image4) as image:
|
||||
image.remove_snap('snap')
|
||||
rbd.remove(ioctx, image4)
|
||||
|
||||
def rand_data(size):
|
||||
return os.urandom(size)
|
||||
|
||||
@ -1806,6 +1837,7 @@ class TestTrash(object):
|
||||
|
||||
RBD().trash_move(ioctx, image_name, 1000)
|
||||
assert_raises(PermissionError, RBD().trash_remove, ioctx, image_id)
|
||||
RBD().trash_remove(ioctx, image_id, True)
|
||||
|
||||
def test_remove(self):
|
||||
create_image()
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "tools/rbd/Utils.h"
|
||||
#include "include/stringify.h"
|
||||
#include "common/errno.h"
|
||||
#include "osd/osd_types.h"
|
||||
#include "common/Formatter.h"
|
||||
#include <iostream>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
@ -37,8 +37,8 @@ int execute_init(const po::variables_map &vm,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RBD,
|
||||
vm["force"].as<bool>());
|
||||
librbd::RBD rbd;
|
||||
r = rbd.pool_init(io_ctx, vm["force"].as<bool>());
|
||||
if (r == -EOPNOTSUPP) {
|
||||
std::cerr << "rbd: luminous or later release required." << std::endl;
|
||||
} else if (r == -EPERM) {
|
||||
@ -52,9 +52,101 @@ int execute_init(const po::variables_map &vm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
Shell::Action action(
|
||||
void get_arguments_stats(po::options_description *positional,
|
||||
po::options_description *options) {
|
||||
at::add_pool_options(positional, options);
|
||||
at::add_namespace_option(options, at::ARGUMENT_MODIFIER_NONE);
|
||||
at::add_format_options(options);
|
||||
}
|
||||
|
||||
int execute_stats(const po::variables_map &vm,
|
||||
const std::vector<std::string> &ceph_global_init_args) {
|
||||
size_t arg_index = 0;
|
||||
std::string pool_name = utils::get_pool_name(vm, &arg_index);
|
||||
std::string namespace_name = utils::get_namespace_name(vm, &arg_index);
|
||||
|
||||
at::Format::Formatter formatter;
|
||||
int r = utils::get_formatter(vm, &formatter);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
librados::Rados rados;
|
||||
librados::IoCtx io_ctx;
|
||||
r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
librbd::RBD rbd;
|
||||
uint64_t image_count;
|
||||
uint64_t provisioned_bytes;
|
||||
uint64_t snap_count;
|
||||
uint64_t trash_count;
|
||||
uint64_t trash_provisioned_bytes;
|
||||
uint64_t trash_snap_count;
|
||||
|
||||
librbd::PoolStats pool_stats;
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_IMAGES, &image_count);
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
|
||||
&provisioned_bytes);
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS, &snap_count);
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_TRASH_IMAGES, &trash_count);
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
|
||||
&trash_provisioned_bytes);
|
||||
pool_stats.add(RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS, &trash_snap_count);
|
||||
|
||||
r = rbd.pool_stats_get(io_ctx, &pool_stats);
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd: failed to query pool stats: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (formatter) {
|
||||
formatter->open_object_section("stats");
|
||||
formatter->open_object_section("images");
|
||||
formatter->dump_unsigned("count", image_count);
|
||||
formatter->dump_unsigned("provisioned_bytes", provisioned_bytes);
|
||||
formatter->dump_unsigned("snap_count", snap_count);
|
||||
formatter->close_section();
|
||||
formatter->open_object_section("trash");
|
||||
formatter->dump_unsigned("count", trash_count);
|
||||
formatter->dump_unsigned("provisioned_bytes", trash_provisioned_bytes);
|
||||
formatter->dump_unsigned("snap_count", trash_snap_count);
|
||||
formatter->close_section();
|
||||
formatter->close_section();
|
||||
formatter->flush(std::cout);
|
||||
} else {
|
||||
std::cout << "Total Images: " << image_count;
|
||||
if (trash_count > 0) {
|
||||
std::cout << " (" << trash_count << " in trash)";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Total Snapshots: " << snap_count;
|
||||
if (trash_count > 0) {
|
||||
std::cout << " (" << trash_snap_count << " in trash)";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Provisioned Size: " << byte_u_t(provisioned_bytes);
|
||||
if (trash_count > 0) {
|
||||
std::cout << " (" << byte_u_t(trash_provisioned_bytes) << " in trash)";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Shell::Action init_action(
|
||||
{"pool", "init"}, {}, "Initialize pool for use by RBD.", "",
|
||||
&get_arguments_init, &execute_init);
|
||||
&get_arguments_init, &execute_init);
|
||||
Shell::Action stat_action(
|
||||
{"pool", "stats"}, {}, "Display pool statistics.",
|
||||
"Note: legacy v1 images are not included in stats",
|
||||
&get_arguments_stats, &execute_stats);
|
||||
|
||||
} // namespace pool
|
||||
} // namespace action
|
||||
|
Loading…
Reference in New Issue
Block a user