rbd-nbd: provide a way to map snapshots by id

Currently we don't have a way to map arbitrary snapshots,
this commit provides --snap-id option to all such snapshots

$ rbd --cluster=site-a snap ls pool1/test_image --all --format=json --pretty-format
[
    {
        "id": 4,
        "name": ".mirror.primary.c6fe94fd-3f9b-4ce0-aecc-e9d07472fd46.528a3f48-1b5c-4abb-9089-5a454328aeb3",
        "size": 1073741824,
        "protected": "false",
        "timestamp": "Thu Oct 27 22:09:12 2022",
        "namespace": {
            "type": "mirror",
            "state": "primary",
            "mirror_peer_uuids": [
                "3e99dc15-78ca-46bd-8934-93d8063c0081"
            ],
            "complete": true
        }
    }
]

$ rbd-nbd --cluster=site-a map --snap-id=4 pool1/test_image
/dev/nbd0

$ rbd-nbd list-mapped
id      pool   namespace  image       snap  device     cookie
511989  pool1             test_image  @4    /dev/nbd0  68de2ef3-1d22-43b9-8318-03f3d31ec8b5
513439  pool1             test_image  @5    /dev/nbd1  f3222c04-4048-4c61-a0b1-28536c4a29a7

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
This commit is contained in:
Prasanna Kumar Kalever 2022-10-31 11:38:18 +05:30
parent 528a5fb617
commit 75226f1be2
2 changed files with 43 additions and 10 deletions

View File

@ -9,7 +9,7 @@
Synopsis
========
| **rbd-nbd** [-c conf] [--read-only] [--device *nbd device*] [--nbds_max *limit*] [--max_part *limit*] [--exclusive] [--notrim] [--encryption-format *format*] [--encryption-passphrase-file *passphrase-file*] [--io-timeout *seconds*] [--reattach-timeout *seconds*] map *image-spec* | *snap-spec*
| **rbd-nbd** [-c conf] [--read-only] [--device *nbd device*] [--snap-id *snap-id*] [--nbds_max *limit*] [--max_part *limit*] [--exclusive] [--notrim] [--encryption-format *format*] [--encryption-passphrase-file *passphrase-file*] [--io-timeout *seconds*] [--reattach-timeout *seconds*] map *image-spec* | *snap-spec*
| **rbd-nbd** unmap *nbd device* | *image-spec* | *snap-spec*
| **rbd-nbd** list-mapped
| **rbd-nbd** attach --device *nbd device* *image-spec* | *snap-spec*
@ -71,6 +71,10 @@ Options
attached after the old process is detached. The default is 30
second.
.. option:: --snap-id *snapid*
Specify a snapshot to map/unmap/attach/detach by ID instead of by name.
Image and snap specs
====================

View File

@ -125,6 +125,7 @@ struct Config {
Command command = None;
int pid = 0;
std::string cookie;
uint64_t snapid = CEPH_NOSNAP;
std::string image_spec() const {
std::string spec = poolname + "/";
@ -168,6 +169,11 @@ static void usage()
<< " --try-netlink Use the nbd netlink interface\n"
<< " --show-cookie Show device cookie\n"
<< " --cookie Specify device cookie\n"
<< " --snap-id <snap-id> Specify snapshot by ID instead of by name\n"
<< "\n"
<< "Unmap and detach options:\n"
<< " --device <device path> Specify nbd device path (/dev/nbd{num})\n"
<< " --snap-id <snap-id> Specify snapshot by ID instead of by name\n"
<< "\n"
<< "List options:\n"
<< " --format plain|json|xml Output format (default: plain)\n"
@ -1657,10 +1663,20 @@ static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect)
}
}
if (!cfg->snapname.empty()) {
r = image.snap_set(cfg->snapname.c_str());
if (r < 0)
if (cfg->snapid != CEPH_NOSNAP) {
r = image.snap_set_by_id(cfg->snapid);
if (r < 0) {
cerr << "rbd-nbd: failed to set snap id: " << cpp_strerror(r)
<< std::endl;
goto close_fd;
}
} else if (!cfg->snapname.empty()) {
r = image.snap_set(cfg->snapname.c_str());
if (r < 0) {
cerr << "rbd-nbd: failed to set snap name: " << cpp_strerror(r)
<< std::endl;
goto close_fd;
}
}
if (encryption_format_count > 0) {
@ -1958,23 +1974,23 @@ static int do_list_mapped_devices(const std::string &format, bool pretty_format)
Config cfg;
NBDListIterator it;
while (it.get(&cfg)) {
std::string snap = (cfg.snapid != CEPH_NOSNAP ?
"@" + std::to_string(cfg.snapid) : cfg.snapname);
if (f) {
f->open_object_section("device");
f->dump_int("id", cfg.pid);
f->dump_string("pool", cfg.poolname);
f->dump_string("namespace", cfg.nsname);
f->dump_string("image", cfg.imgname);
f->dump_string("snap", cfg.snapname);
f->dump_string("snap", snap);
f->dump_string("device", cfg.devpath);
f->dump_string("cookie", cfg.cookie);
f->close_section();
} else {
should_print = true;
if (cfg.snapname.empty()) {
cfg.snapname = "-";
}
tbl << cfg.pid << cfg.poolname << cfg.nsname << cfg.imgname
<< cfg.snapname << cfg.devpath << cfg.cookie << TextTable::endrow;
<< (snap.empty() ? "-" : snap) << cfg.devpath << cfg.cookie
<< TextTable::endrow;
}
}
@ -1995,7 +2011,8 @@ static bool find_mapped_dev_by_spec(Config *cfg, int skip_pid=-1) {
if (c.pid != skip_pid &&
c.poolname == cfg->poolname && c.nsname == cfg->nsname &&
c.imgname == cfg->imgname && c.snapname == cfg->snapname &&
(cfg->devpath.empty() || c.devpath == cfg->devpath)) {
(cfg->devpath.empty() || c.devpath == cfg->devpath) &&
c.snapid == cfg->snapid) {
*cfg = c;
return true;
}
@ -2038,6 +2055,7 @@ static int parse_args(vector<const char*>& args, std::ostream *err_msg,
std::vector<const char*>::iterator i;
std::ostringstream err;
std::string arg_value;
long long snapid;
for (i = args.begin(); i != args.end(); ) {
if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
@ -2114,6 +2132,17 @@ static int parse_args(vector<const char*>& args, std::ostream *err_msg,
} else if (ceph_argparse_flag(args, i, "--show-cookie", (char *)NULL)) {
cfg->show_cookie = true;
} else if (ceph_argparse_witharg(args, i, &cfg->cookie, "--cookie", (char *)NULL)) {
} else if (ceph_argparse_witharg(args, i, &snapid, err,
"--snap-id", (char *)NULL)) {
if (!err.str().empty()) {
*err_msg << "rbd-nbd: " << err.str();
return -EINVAL;
}
if (snapid < 0) {
*err_msg << "rbd-nbd: Invalid argument for snap-id!";
return -EINVAL;
}
cfg->snapid = snapid;
} else if (ceph_argparse_witharg(args, i, &arg_value,
"--encryption-format", (char *)NULL)) {
if (arg_value == "luks1") {