mirror of
https://github.com/ceph/ceph
synced 2025-02-22 02:27:29 +00:00
Merge pull request #19679 from trociny/wip-ggate-list-unmap
rbd-ggate: small fixes and improvements Reviewed-by: Willem Jan Withagen <wjw@digiware.nl>
This commit is contained in:
commit
1a9a44247d
@ -92,18 +92,23 @@ expect_false _sudo rbd-ggate map INVALIDIMAGE
|
||||
|
||||
# map test using the first unused device
|
||||
DEV=`_sudo rbd-ggate map ${POOL}/${IMAGE}`
|
||||
_sudo rbd-ggate list | grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
|
||||
# map test specifying the device
|
||||
expect_false _sudo rbd-ggate --device ${DEV} map ${POOL}/${IMAGE}
|
||||
dev1=${DEV}
|
||||
_sudo rbd-ggate unmap ${DEV}
|
||||
_sudo rbd-ggate list | expect_false grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | expect_false grep " ${DEV} *$"
|
||||
DEV=
|
||||
# XXX: race possible when the device is reused by other process
|
||||
DEV=`_sudo rbd-ggate --device ${dev1} map ${POOL}/${IMAGE}`
|
||||
[ "${DEV}" = "${dev1}" ]
|
||||
_sudo rbd-ggate list | grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
|
||||
# list format test
|
||||
expect_false _sudo rbd-ggate --format INVALID list
|
||||
_sudo rbd-ggate --format json --pretty-format list
|
||||
_sudo rbd-ggate --format xml list
|
||||
|
||||
# read test
|
||||
[ "`dd if=${DATA} bs=1M | md5`" = "`_sudo dd if=${DEV} bs=1M | md5`" ]
|
||||
@ -137,9 +142,9 @@ rbd info ${POOL}/${IMAGE}
|
||||
if [ -z "$RBD_GGATE_RESIZE_SUPPORTED" ]; then
|
||||
# XXX: ggate device resize is not supported by vanila kernel.
|
||||
# rbd-ggate should terminate when detecting resize.
|
||||
_sudo rbd-ggate list | expect_false grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | expect_false grep " ${DEV} *$"
|
||||
else
|
||||
_sudo rbd-ggate list | grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
size2=$(geom gate list ${devname} | awk '$1 ~ /Mediasize:/ {print $2}')
|
||||
test -n "${size2}"
|
||||
test ${size2} -eq $((size * 2))
|
||||
@ -161,7 +166,7 @@ DEV=
|
||||
# read-only option test
|
||||
DEV=`_sudo rbd-ggate map --read-only ${POOL}/${IMAGE}`
|
||||
devname=$(basename ${DEV})
|
||||
_sudo rbd-ggate list | grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
access=$(geom gate list ${devname} | awk '$1 == "access:" {print $2}')
|
||||
test "${access}" = "read-only"
|
||||
_sudo dd if=${DEV} of=/dev/null bs=1M
|
||||
@ -170,7 +175,7 @@ _sudo rbd-ggate unmap ${DEV}
|
||||
|
||||
# exclusive option test
|
||||
DEV=`_sudo rbd-ggate map --exclusive ${POOL}/${IMAGE}`
|
||||
_sudo rbd-ggate list | grep "^${DEV}$"
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
_sudo dd if=${DATA} of=${DEV} bs=1M
|
||||
_sudo sync
|
||||
expect_false timeout 10 \
|
||||
@ -179,4 +184,19 @@ _sudo rbd-ggate unmap ${DEV}
|
||||
DEV=
|
||||
rbd bench -p ${POOL} ${IMAGE} --io-type=write --io-size=1024 --io-total=1024
|
||||
|
||||
# unmap by image name test
|
||||
DEV=`_sudo rbd-ggate map ${POOL}/${IMAGE}`
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
_sudo rbd-ggate unmap "${POOL}/${IMAGE}"
|
||||
rbd-ggate list-mapped | expect_false grep " ${DEV} *$"
|
||||
DEV=
|
||||
|
||||
# map/unmap snap test
|
||||
rbd snap create ${POOL}/${IMAGE}@snap
|
||||
DEV=`_sudo rbd-ggate map ${POOL}/${IMAGE}@snap`
|
||||
_sudo rbd-ggate list | grep " ${DEV} *$"
|
||||
_sudo rbd-ggate unmap "${POOL}/${IMAGE}@snap"
|
||||
rbd-ggate list-mapped | expect_false grep " ${DEV} *$"
|
||||
DEV=
|
||||
|
||||
echo OK
|
||||
|
@ -76,9 +76,34 @@ static int call_ggate_cmd(const po::variables_map &vm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_image_or_snap_spec(const po::variables_map &vm, std::string *spec) {
|
||||
size_t arg_index = 0;
|
||||
std::string pool_name;
|
||||
std::string image_name;
|
||||
std::string snap_name;
|
||||
int r = utils::get_pool_image_snapshot_names(
|
||||
vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
|
||||
&snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED,
|
||||
utils::SPEC_VALIDATION_NONE);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
spec->append(pool_name);
|
||||
spec->append("/");
|
||||
spec->append(image_name);
|
||||
if (!snap_name.empty()) {
|
||||
spec->append("@");
|
||||
spec->append(snap_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_list_arguments(po::options_description *positional,
|
||||
po::options_description *options)
|
||||
{ }
|
||||
po::options_description *options) {
|
||||
at::add_format_options(options);
|
||||
}
|
||||
|
||||
int execute_list(const po::variables_map &vm)
|
||||
{
|
||||
@ -86,6 +111,14 @@ int execute_list(const po::variables_map &vm)
|
||||
|
||||
args.push_back("list");
|
||||
|
||||
if (vm.count("format")) {
|
||||
args.push_back("--format");
|
||||
args.push_back(vm["format"].as<at::Format>().value.c_str());
|
||||
}
|
||||
if (vm["pretty-format"].as<bool>()) {
|
||||
args.push_back("--pretty-format");
|
||||
}
|
||||
|
||||
return call_ggate_cmd(vm, args);
|
||||
}
|
||||
|
||||
@ -102,28 +135,13 @@ void get_map_arguments(po::options_description *positional,
|
||||
|
||||
int execute_map(const po::variables_map &vm)
|
||||
{
|
||||
size_t arg_index = 0;
|
||||
std::string pool_name;
|
||||
std::string image_name;
|
||||
std::string snap_name;
|
||||
int r = utils::get_pool_image_snapshot_names(
|
||||
vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
|
||||
&snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED,
|
||||
utils::SPEC_VALIDATION_NONE);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<const char*> args;
|
||||
|
||||
args.push_back("map");
|
||||
std::string img;
|
||||
img.append(pool_name);
|
||||
img.append("/");
|
||||
img.append(image_name);
|
||||
if (!snap_name.empty()) {
|
||||
img.append("@");
|
||||
img.append(snap_name);
|
||||
int r = get_image_or_snap_spec(vm, &img);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
args.push_back(img.c_str());
|
||||
|
||||
@ -145,7 +163,12 @@ void get_unmap_arguments(po::options_description *positional,
|
||||
po::options_description *options)
|
||||
{
|
||||
positional->add_options()
|
||||
("device-spec", "specify ggate device");
|
||||
("image-or-snap-or-device-spec",
|
||||
"image, snapshot, or device specification\n"
|
||||
"[<pool-name>/]<image-name>[@<snapshot-name>] or <device-path>");
|
||||
at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
|
||||
at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
|
||||
at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
|
||||
}
|
||||
|
||||
int execute_unmap(const po::variables_map &vm)
|
||||
@ -155,15 +178,25 @@ int execute_unmap(const po::variables_map &vm)
|
||||
device_name.clear();
|
||||
}
|
||||
|
||||
std::string image_name;
|
||||
if (device_name.empty()) {
|
||||
std::cerr << "rbd: ggate unmap requires device path" << std::endl;
|
||||
int r = get_image_or_snap_spec(vm, &image_name);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (device_name.empty() && image_name.empty()) {
|
||||
std::cerr << "rbd: unmap requires either image name or device path"
|
||||
<< std::endl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
std::vector<const char*> args;
|
||||
|
||||
args.push_back("unmap");
|
||||
args.push_back(device_name.c_str());
|
||||
args.push_back(device_name.empty() ? image_name.c_str() :
|
||||
device_name.c_str());
|
||||
|
||||
return call_ggate_cmd(vm, args);
|
||||
}
|
||||
|
@ -29,32 +29,31 @@ int Driver::kill(const std::string &devname) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int Driver::list(std::list<std::string> &devs) {
|
||||
int Driver::list(std::map<std::string, DevInfo> *devices) {
|
||||
size_t size = 1024;
|
||||
char **devs_ = nullptr;
|
||||
ggate_drv_info *devs = nullptr;
|
||||
int r;
|
||||
|
||||
while (size <= 1024 * 1024) {
|
||||
devs_ = static_cast<char **>(
|
||||
realloc(static_cast<void *>(devs_), size * sizeof(*devs_)));
|
||||
r = ggate_drv_list(devs_, &size);
|
||||
devs = static_cast<ggate_drv_info *>(
|
||||
realloc(static_cast<void *>(devs), size * sizeof(*devs)));
|
||||
r = ggate_drv_list(devs, &size);
|
||||
if (r != -ERANGE) {
|
||||
break;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
if (r < 0) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
devs.clear();
|
||||
devices->clear();
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
devs.push_back(devs_[i]);
|
||||
auto &dev = devs[i];
|
||||
(*devices)[dev.id] = {dev.name, dev.info};
|
||||
}
|
||||
|
||||
ggate_drv_list_free(devs_, size);
|
||||
free:
|
||||
free(devs_);
|
||||
free(devs);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef CEPH_RBD_GGATE_DRIVER_H
|
||||
#define CEPH_RBD_GGATE_DRIVER_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "ggate_drv.h"
|
||||
@ -16,9 +16,10 @@ struct Request;
|
||||
|
||||
class Driver {
|
||||
public:
|
||||
typedef std::pair<std::string, std::string> DevInfo;
|
||||
static int load();
|
||||
static int kill(const std::string &devname);
|
||||
static int list(std::list<std::string> &devs);
|
||||
static int list(std::map<std::string, DevInfo> *devices);
|
||||
|
||||
Driver(const std::string &devname, size_t sectorsize, size_t mediasize,
|
||||
bool readonly, const std::string &info);
|
||||
|
@ -330,7 +330,17 @@ int ggate_drv_send(ggate_drv_t drv_, ggate_drv_req_t req) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int ggate_drv_list(char **devs, size_t *size) {
|
||||
static const char * get_conf(struct ggeom *gp, const char *name) {
|
||||
struct gconfig *conf;
|
||||
|
||||
LIST_FOREACH(conf, &gp->lg_config, lg_config) {
|
||||
if (strcmp(conf->lg_name, name) == 0)
|
||||
return (conf->lg_val);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int ggate_drv_list(struct ggate_drv_info *info, size_t *size) {
|
||||
struct gmesh mesh;
|
||||
struct gclass *class;
|
||||
struct ggeom *gp;
|
||||
@ -355,8 +365,10 @@ int ggate_drv_list(char **devs, size_t *size) {
|
||||
goto done;
|
||||
}
|
||||
LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
|
||||
*devs = strdup(gp->lg_name);
|
||||
devs++;
|
||||
strlcpy(info->id, get_conf(gp, "unit"), sizeof(info->id));
|
||||
strlcpy(info->name, gp->lg_name, sizeof(info->name));
|
||||
strlcpy(info->info, get_conf(gp, "info"), sizeof(info->info));
|
||||
info++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,11 +377,3 @@ done:
|
||||
geom_deletetree(&mesh);
|
||||
return r;
|
||||
}
|
||||
|
||||
void ggate_drv_list_free(char **devs, size_t size) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
free(devs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -25,6 +27,12 @@ enum {
|
||||
GGATE_DRV_CMD_DISCARD = 4,
|
||||
};
|
||||
|
||||
struct ggate_drv_info {
|
||||
char id[16];
|
||||
char name[NAME_MAX];
|
||||
char info[2048]; /* G_GATE_INFOSIZE */
|
||||
};
|
||||
|
||||
uint64_t ggate_drv_req_id(ggate_drv_req_t req);
|
||||
int ggate_drv_req_cmd(ggate_drv_req_t req);
|
||||
void *ggate_drv_req_buf(ggate_drv_req_t req);
|
||||
@ -47,8 +55,7 @@ int ggate_drv_send(ggate_drv_t drv, ggate_drv_req_t req);
|
||||
int ggate_drv_resize(ggate_drv_t drv, size_t newsize);
|
||||
|
||||
int ggate_drv_kill(const char *devname);
|
||||
int ggate_drv_list(char **devs, size_t *size);
|
||||
void ggate_drv_list_free(char **devs, size_t size);
|
||||
int ggate_drv_list(struct ggate_drv_info *info, size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include "common/Formatter.h"
|
||||
#include "common/Preforker.h"
|
||||
#include "common/TextTable.h"
|
||||
#include "common/ceph_argparse.h"
|
||||
#include "common/config.h"
|
||||
#include "common/debug.h"
|
||||
@ -25,6 +29,7 @@
|
||||
|
||||
#include "include/rados/librados.hpp"
|
||||
#include "include/rbd/librbd.hpp"
|
||||
#include "include/stringify.h"
|
||||
|
||||
#include "Driver.h"
|
||||
#include "Server.h"
|
||||
@ -39,15 +44,20 @@ static void usage() {
|
||||
std::cout << "Usage: rbd-ggate [options] map <image-or-snap-spec> Map an image to ggate device\n"
|
||||
<< " unmap <device path> Unmap ggate device\n"
|
||||
<< " list List mapped ggate devices\n"
|
||||
<< "Options:\n"
|
||||
<< "\n"
|
||||
<< "Map options:\n"
|
||||
<< " --device <device path> Specify ggate device path\n"
|
||||
<< " --read-only Map readonly\n"
|
||||
<< " --exclusive Forbid writes by other clients\n"
|
||||
<< "\n"
|
||||
<< "List options:\n"
|
||||
<< " --format plain|json|xml Output format (default: plain)\n"
|
||||
<< " --pretty-format Pretty formatting (json and xml)\n"
|
||||
<< std::endl;
|
||||
generic_server_usage();
|
||||
}
|
||||
|
||||
static std::string devpath, poolname("rbd"), imgname, snapname;
|
||||
static std::string devpath, poolname, imgname, snapname;
|
||||
static bool readonly = false;
|
||||
static bool exclusive = false;
|
||||
|
||||
@ -90,7 +100,7 @@ static int do_map(int argc, const char *argv[])
|
||||
std::string err;
|
||||
r = forker.prefork(err);
|
||||
if (r < 0) {
|
||||
cerr << err << std::endl;
|
||||
std::cerr << err << std::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -106,7 +116,11 @@ static int do_map(int argc, const char *argv[])
|
||||
common_init_finish(g_ceph_context);
|
||||
global_init_chdir(g_ceph_context);
|
||||
|
||||
std::string devname = (devpath.compare(0, 5, "/dev/") == 0) ?
|
||||
if (poolname.empty()) {
|
||||
poolname = g_ceph_context->_conf->get_val<std::string>("rbd_default_pool");
|
||||
}
|
||||
|
||||
std::string devname = boost::starts_with(devpath, "/dev/") ?
|
||||
devpath.substr(5) : devpath;
|
||||
std::unique_ptr<rbd::ggate::Watcher> watcher;
|
||||
uint64_t handle;
|
||||
@ -118,24 +132,30 @@ static int do_map(int argc, const char *argv[])
|
||||
|
||||
r = rados.connect();
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to connect to cluster: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = rados.ioctx_create(poolname.c_str(), io_ctx);
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to acces pool " << poolname << ": "
|
||||
<< cpp_strerror(r) << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = rbd.open(io_ctx, image, imgname.c_str());
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to open image " << imgname << ": "
|
||||
<< cpp_strerror(r) << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (exclusive) {
|
||||
r = image.lock_acquire(RBD_LOCK_MODE_EXCLUSIVE);
|
||||
if (r < 0) {
|
||||
cerr << "rbd-ggate: failed to acquire exclusive lock: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
std::cerr << "rbd-ggate: failed to acquire exclusive lock: "
|
||||
<< cpp_strerror(r) << std::endl;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -145,6 +165,8 @@ static int do_map(int argc, const char *argv[])
|
||||
if (!snapname.empty()) {
|
||||
r = image.snap_set(snapname.c_str());
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to set snapshot " << snapname << ": "
|
||||
<< cpp_strerror(r) << std::endl;
|
||||
goto done;
|
||||
}
|
||||
readonly = true;
|
||||
@ -153,6 +175,8 @@ static int do_map(int argc, const char *argv[])
|
||||
|
||||
r = image.stat(info, sizeof(info));
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: image stat failed: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -161,12 +185,16 @@ static int do_map(int argc, const char *argv[])
|
||||
r = drv->init();
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
std::cerr << "rbd-ggate: failed to create ggate device: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
watcher.reset(new rbd::ggate::Watcher(drv.get(), io_ctx, image, info.size));
|
||||
r = image.update_watch(watcher.get(), &handle);
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to set watcher: " << cpp_strerror(r)
|
||||
<< std::endl;
|
||||
drv->shut_down();
|
||||
goto done;
|
||||
}
|
||||
@ -199,6 +227,10 @@ done:
|
||||
io_ctx.close();
|
||||
rados.shutdown();
|
||||
|
||||
if (r < 0) {
|
||||
std::cerr << "rbd-ggate: failed to map: " << cpp_strerror(r) << std::endl;
|
||||
}
|
||||
|
||||
forker.exit(r < 0 ? EXIT_FAILURE : 0);
|
||||
// Unreachable;
|
||||
return r;
|
||||
@ -206,7 +238,7 @@ done:
|
||||
|
||||
static int do_unmap()
|
||||
{
|
||||
std::string devname = (devpath.compare(0, 5, "/dev/") == 0) ?
|
||||
std::string devname = boost::starts_with(devpath, "/dev/") ?
|
||||
devpath.substr(5) : devpath;
|
||||
|
||||
int r = rbd::ggate::Driver::kill(devname);
|
||||
@ -219,8 +251,8 @@ static int do_unmap()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_imgpath(const std::string &imgpath)
|
||||
{
|
||||
static int parse_imgpath(const std::string &imgpath, std::string *poolname,
|
||||
std::string *imgname, std::string *snapname) {
|
||||
boost::regex pattern("^(?:([^/@]+)/)?([^/@]+)(?:@([^/@]+))?$");
|
||||
boost::smatch match;
|
||||
if (!boost::regex_match(imgpath, match, pattern)) {
|
||||
@ -229,31 +261,126 @@ static int parse_imgpath(const std::string &imgpath)
|
||||
}
|
||||
|
||||
if (match[1].matched) {
|
||||
poolname = match[1];
|
||||
*poolname = match[1];
|
||||
}
|
||||
|
||||
imgname = match[2];
|
||||
*imgname = match[2];
|
||||
|
||||
if (match[3].matched) {
|
||||
snapname = match[3];
|
||||
*snapname = match[3];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_list()
|
||||
static bool find_mapped_dev_by_spec(const std::string &spec,
|
||||
std::string *devname) {
|
||||
std::string poolname, imgname, snapname;
|
||||
int r = parse_imgpath(spec, &poolname, &imgname, &snapname);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
if (poolname.empty()) {
|
||||
// We could use rbd_default_pool config to set pool name but then
|
||||
// we would need to initialize the global context. So right now it
|
||||
// is mandatory for the user to specify a pool. Fortunately the
|
||||
// preferred way for users to call rbd-ggate is via rbd, which
|
||||
// cares to set the pool name.
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<std::string, rbd::ggate::Driver::DevInfo> devs;
|
||||
r = rbd::ggate::Driver::list(&devs);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &it : devs) {
|
||||
auto &name = it.second.first;
|
||||
auto &info = it.second.second;
|
||||
if (!boost::starts_with(info, "RBD ")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string p, i, s;
|
||||
parse_imgpath(info.substr(4), &p, &i, &s);
|
||||
if (p == poolname && i == imgname && s == snapname) {
|
||||
*devname = name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int do_list(const std::string &format, bool pretty_format)
|
||||
{
|
||||
rbd::ggate::Driver::load();
|
||||
|
||||
std::list<std::string> devs;
|
||||
int r = rbd::ggate::Driver::list(devs);
|
||||
std::map<std::string, rbd::ggate::Driver::DevInfo> devs;
|
||||
int r = rbd::ggate::Driver::list(&devs);
|
||||
if (r < 0) {
|
||||
return -r;
|
||||
}
|
||||
|
||||
for (auto &devname : devs) {
|
||||
cout << "/dev/" << devname << std::endl;
|
||||
std::unique_ptr<ceph::Formatter> f;
|
||||
TextTable tbl;
|
||||
|
||||
if (format == "json") {
|
||||
f.reset(new JSONFormatter(pretty_format));
|
||||
} else if (format == "xml") {
|
||||
f.reset(new XMLFormatter(pretty_format));
|
||||
} else if (!format.empty() && format != "plain") {
|
||||
std::cerr << "rbd-ggate: invalid output format: " << format << std::endl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
f->open_object_section("devices");
|
||||
} else {
|
||||
tbl.define_column("id", TextTable::LEFT, TextTable::LEFT);
|
||||
tbl.define_column("pool", TextTable::LEFT, TextTable::LEFT);
|
||||
tbl.define_column("image", TextTable::LEFT, TextTable::LEFT);
|
||||
tbl.define_column("snap", TextTable::LEFT, TextTable::LEFT);
|
||||
tbl.define_column("device", TextTable::LEFT, TextTable::LEFT);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (auto &it : devs) {
|
||||
auto &id = it.first;
|
||||
auto &name = it.second.first;
|
||||
auto &info = it.second.second;
|
||||
if (!boost::starts_with(info, "RBD ")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string poolname;
|
||||
std::string imgname;
|
||||
std::string snapname(f ? "" : "-");
|
||||
parse_imgpath(info.substr(4), &poolname, &imgname, &snapname);
|
||||
|
||||
if (f) {
|
||||
f->open_object_section(stringify(id).c_str());
|
||||
f->dump_string("pool", poolname);
|
||||
f->dump_string("image", imgname);
|
||||
f->dump_string("snap", snapname);
|
||||
f->dump_string("device", "/dev/" + name);
|
||||
f->close_section();
|
||||
} else {
|
||||
tbl << id << poolname << imgname << snapname << "/dev/" + name
|
||||
<< TextTable::endrow;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
f->close_section(); // devices
|
||||
f->flush(std::cout);
|
||||
} else if (count > 0) {
|
||||
std::cout << tbl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -271,6 +398,8 @@ int main(int argc, const char *argv[]) {
|
||||
argv_to_vec(argc, argv, args);
|
||||
md_config_t().parse_argv(args);
|
||||
|
||||
std::string format;
|
||||
bool pretty_format = false;
|
||||
std::vector<const char*>::iterator i;
|
||||
|
||||
for (i = args.begin(); i != args.end(); ) {
|
||||
@ -283,6 +412,10 @@ int main(int argc, const char *argv[]) {
|
||||
readonly = true;
|
||||
} else if (ceph_argparse_flag(args, i, "--exclusive", (char *)NULL)) {
|
||||
exclusive = true;
|
||||
} else if (ceph_argparse_witharg(args, i, &format, "--format",
|
||||
(char *)NULL)) {
|
||||
} else if (ceph_argparse_flag(args, i, "--pretty-format", (char *)NULL)) {
|
||||
pretty_format = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
@ -313,16 +446,21 @@ int main(int argc, const char *argv[]) {
|
||||
cerr << "rbd-ggate: must specify image-or-snap-spec" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (parse_imgpath(string(*args.begin())) < 0)
|
||||
if (parse_imgpath(*args.begin(), &poolname, &imgname, &snapname) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
args.erase(args.begin());
|
||||
break;
|
||||
case Disconnect:
|
||||
if (args.begin() == args.end()) {
|
||||
cerr << "rbd-ggate: must specify ggate device path" << std::endl;
|
||||
std::cerr << "rbd-ggate: must specify ggate device or image-or-snap-spec"
|
||||
<< std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
devpath = *args.begin();
|
||||
if (boost::starts_with(*args.begin(), "/dev/") ||
|
||||
!find_mapped_dev_by_spec(*args.begin(), &devpath)) {
|
||||
devpath = *args.begin();
|
||||
}
|
||||
args.erase(args.begin());
|
||||
break;
|
||||
default:
|
||||
@ -351,7 +489,7 @@ int main(int argc, const char *argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case List:
|
||||
r = do_list();
|
||||
r = do_list(format, pretty_format);
|
||||
if (r < 0)
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user