rbd: use TextTable to implement ls -l

Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
Dan Mick 2012-10-04 14:40:03 -07:00
parent fb88683cd1
commit 61b2e4d6ac
8 changed files with 138 additions and 36 deletions

View File

@ -97,8 +97,10 @@ Commands
.. TODO rst "option" directive seems to require --foo style options, parsing breaks on subcommands.. the args show up as bold too
:command:`ls` [*pool-name*]
Will list all rbd images listed in the rbd_directory object.
:command:`ls` [-l | --long] [pool-name]
Will list all rbd images listed in the rbd_directory object. With
-l, also show snapshots, and use longer-format output including
size, parent (if clone), format, etc.
:command:`info` [*image-name*]
Will dump information (such as size and order) about a specific rbd image.

View File

@ -1,4 +1,4 @@
.TH "RBD" "8" "September 27, 2012" "dev" "Ceph"
.TH "RBD" "8" "October 03, 2012" "dev" "Ceph"
.SH NAME
rbd \- manage rados block device (RBD) images
.
@ -124,8 +124,10 @@ a clustered filesystem.
.SH COMMANDS
.INDENT 0.0
.TP
.B \fBls\fP [\fIpool\-name\fP]
Will list all rbd images listed in the rbd_directory object.
.B \fBls\fP [\-l | \-\-long] [pool\-name]
Will list all rbd images listed in the rbd_directory object. With
\-l, also show snapshots, and use longer\-format output including
size, parent (if clone), format, etc.
.TP
.B \fBinfo\fP [\fIimage\-name\fP]
Will dump information (such as size and order) about a specific rbd image.

View File

@ -88,6 +88,9 @@ test_ls() {
rbd ls | grep test1
rbd ls | grep test2
rbd ls | wc -l | grep 2
# look for fields in output of ls -l without worrying about space
rbd ls -l | grep 'test1.*image.*1024 KB.*1'
rbd ls -l | grep 'test2.*image.*1024 KB.*1'
rbd rm test1
rbd rm test2
@ -97,6 +100,8 @@ test_ls() {
rbd ls | grep test1
rbd ls | grep test2
rbd ls | wc -l | grep 2
rbd ls -l | grep 'test1.*image.*1024 KB.*2'
rbd ls -l | grep 'test2.*image.*1024 KB.*2'
rbd rm test1
rbd rm test2
@ -106,6 +111,8 @@ test_ls() {
rbd ls | grep test1
rbd ls | grep test2
rbd ls | wc -l | grep 2
rbd ls -l | grep 'test1.*image.*1024 KB.*2'
rbd ls -l | grep 'test2.*image.*1024 KB.*1'
remove_images
}

View File

@ -411,7 +411,7 @@ radosacl_SOURCES = radosacl.cc
radosacl_LDADD = librados.la $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS)
bin_DEBUGPROGRAMS += scratchtool scratchtoolpp radosacl
rbd_SOURCES = rbd.cc common/fiemap.cc common/secret.c
rbd_SOURCES = rbd.cc common/fiemap.cc common/secret.c common/TextTable.cc
rbd_CXXFLAGS = ${AM_CXXFLAGS}
rbd_LDADD = libglobal.la librbd.la librados.la $(PTHREAD_LIBS) -lm -lkeyutils $(CRYPTO_LIBS) $(EXTRALIBS)
if LINUX

View File

@ -22,6 +22,7 @@
#include "global/global_init.h"
#include "common/safe_io.h"
#include "common/secret.h"
#include "include/stringify.h"
#include "include/rados/librados.hpp"
#include "include/rbd/librbd.hpp"
#include "include/byteorder.h"
@ -44,6 +45,7 @@
#include <sys/ioctl.h>
#include "include/rbd_types.h"
#include "common/TextTable.h"
#if defined(__linux__)
#include <linux/fs.h>
@ -66,7 +68,8 @@ void usage()
cout <<
"usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...\n"
"where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:\n"
" (ls | list) [pool-name] list rbd images\n"
" (ls | list) [-l | --long ] [pool-name] list rbd images\n"
" (-l includes snapshots/clones)\n"
" info <image-name> show information about image size,\n"
" striping, etc.\n"
" create [--order <bits>] --size <MB> <name> create an empty image\n"
@ -138,7 +141,7 @@ struct MyProgressContext : public librbd::ProgressContext {
MyProgressContext(const char *o) : operation(o), last_pc(0) {
}
int update_progress(uint64_t offset, uint64_t total) {
int pc = total ? (offset * 100ull / total) : 0;
if (pc != last_pc) {
@ -158,15 +161,78 @@ struct MyProgressContext : public librbd::ProgressContext {
}
};
static int do_list(librbd::RBD &rbd, librados::IoCtx& io_ctx)
static int do_list(librbd::RBD &rbd, librados::IoCtx& io_ctx, bool lflag)
{
std::vector<string> names;
int r = rbd.list(io_ctx, names);
if (r < 0)
if (r < 0 || (names.size() == 0))
return r;
for (std::vector<string>::const_iterator i = names.begin(); i != names.end(); i++)
cout << *i << std::endl;
if (!lflag) {
for (std::vector<string>::const_iterator i = names.begin();
i != names.end(); ++i) {
cout << *i << std::endl;
}
return 0;
}
TextTable tbl;
tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
tbl.define_column("TYPE", TextTable::LEFT, TextTable::LEFT);
tbl.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT);
tbl.define_column("PARENT", TextTable::LEFT, TextTable::LEFT);
tbl.define_column("FORMAT", TextTable::RIGHT, TextTable::RIGHT);
string pool, image, snap, parent;
for (std::vector<string>::const_iterator i = names.begin();
i != names.end(); ++i) {
librbd::image_info_t info;
librbd::Image im;
rbd.open(io_ctx, im, i->c_str());
// handle second-nth trips through loop
parent.clear();
r = im.parent_info(&pool, &image, &snap);
if (r < 0 && r != -ENOENT)
return r;
if (r != -ENOENT)
parent = pool + "/" + image + "@" + snap;
if (im.stat(info, sizeof(info)) < 0)
return -EINVAL;
uint8_t old_format;
im.old_format(&old_format);
tbl << *i
<< ((parent.length()) ? "clone" : "image")
<< stringify(prettybyte_t(info.size))
<< parent
<< ((old_format) ? '1' : '2')
<< TextTable::endrow;
vector<librbd::snap_info_t> snaplist;
if (im.snap_list(snaplist) >= 0 && !snaplist.empty()) {
for (std::vector<librbd::snap_info_t>::iterator s = snaplist.begin();
s != snaplist.end(); ++s) {
parent.clear();
im.snap_set(s->name.c_str());
if (im.parent_info(&pool, &image, &snap) >= 0) {
parent = pool + "/" + image + "@" + snap;
}
tbl << *i + "@" + s->name
<< "snap"
<< stringify(prettybyte_t(s->size))
<< parent
<< ((old_format) ? '1' : '2')
<< TextTable::endrow;
}
}
}
cout << tbl;
return 0;
}
@ -175,7 +241,7 @@ static int do_create(librbd::RBD &rbd, librados::IoCtx& io_ctx,
int format, uint64_t features)
{
int r;
if (features == 0)
if (features == 0)
features = RBD_FEATURES_ALL;
if (format == 1)
@ -188,7 +254,7 @@ static int do_create(librbd::RBD &rbd, librados::IoCtx& io_ctx,
}
static int do_clone(librbd::RBD &rbd, librados::IoCtx &p_ioctx,
const char *p_name, const char *p_snapname,
const char *p_name, const char *p_snapname,
librados::IoCtx &c_ioctx, const char *c_name,
uint64_t features, int *c_order)
{
@ -274,7 +340,7 @@ static int do_show_info(const char *imgname, librbd::Image& image,
<< std::endl;
}
// parent info, if present
// parent info, if present
if ((image.parent_info(&parent_pool, &parent_name, &parent_snapname) == 0) &&
parent_name.length() > 0) {
@ -313,13 +379,20 @@ static int do_list_snaps(librbd::Image& image)
{
std::vector<librbd::snap_info_t> snaps;
int r = image.snap_list(snaps);
if (r < 0)
if (r < 0 || snaps.empty())
return r;
cout << "ID\tNAME\t\tSIZE" << std::endl;
for (std::vector<librbd::snap_info_t>::iterator i = snaps.begin(); i != snaps.end(); ++i) {
cout << i->id << '\t' << i->name << '\t' << i->size << std::endl;
TextTable t;
t.define_column("SNAPID", TextTable::RIGHT, TextTable::RIGHT);
t.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
t.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT);
for (std::vector<librbd::snap_info_t>::iterator s = snaps.begin();
s != snaps.end(); ++s) {
t << s->id << s->name << stringify(prettybyte_t(s->size))
<< TextTable::endrow;
}
cout << t;
return 0;
}
@ -664,7 +737,7 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
extent++;
if (extent == fiemap->fm_mapped_extents)
break;
} while (end_ofs == (off_t)fiemap->fm_extents[extent].fe_logical);
//cerr << "rbd import file_pos=" << file_pos << " extent_len=" << extent_len << std::endl;
@ -1168,6 +1241,7 @@ int main(int argc, const char **argv)
*dest_poolname = NULL, *dest_snapname = NULL, *path = NULL,
*devpath = NULL, *lock_cookie = NULL, *lock_client = NULL,
*lock_tag = NULL;
bool lflag = false;
std::string val;
std::ostringstream err;
@ -1206,6 +1280,8 @@ int main(int argc, const char **argv)
return EXIT_FAILURE;
}
size = sizell << 20; // bytes to MB
} else if (ceph_argparse_flag(args, i, "-l", "--long", (char*)NULL)) {
lflag = true;
} else if (ceph_argparse_withint(args, i, &order, &err, "--order", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
@ -1508,7 +1584,7 @@ int main(int argc, const char **argv)
switch (opt_cmd) {
case OPT_LIST:
r = do_list(rbd, io_ctx);
r = do_list(rbd, io_ctx, lflag);
if (r < 0) {
switch (r) {
case -ENOENT:

View File

@ -2,7 +2,8 @@
error: image name was not specified
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -62,7 +63,8 @@
error: device path was not specified
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image

View File

@ -1,7 +1,8 @@
$ rbd --help
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image

View File

@ -2,7 +2,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -62,7 +63,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -122,7 +124,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -182,7 +185,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -242,7 +246,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -302,7 +307,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -362,7 +368,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -422,7 +429,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -482,7 +490,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -542,7 +551,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -602,7 +612,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image
@ -662,7 +673,8 @@
error: snapname specified for a command that doesn't use it
usage: rbd [-n <auth user>] [OPTIONS] <cmd> ...
where 'pool' is a rados pool name (default is 'rbd') and 'cmd' is one of:
(ls | list) [pool-name] list rbd images
(ls | list) [-l | --long ] [pool-name] list rbd images
(-l includes snapshots/clones)
info <image-name> show information about image size,
striping, etc.
create [--order <bits>] --size <MB> <name> create an empty image