]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/List.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / tools / rbd / action / List.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "tools/rbd/ArgumentTypes.h"
5#include "tools/rbd/Shell.h"
6#include "tools/rbd/Utils.h"
7#include "include/stringify.h"
8#include "include/types.h"
9#include "common/errno.h"
10#include "common/Formatter.h"
11#include "common/TextTable.h"
12#include <iostream>
13#include <boost/program_options.hpp>
14
15namespace rbd {
16namespace action {
17namespace list {
18
19namespace at = argument_types;
20namespace po = boost::program_options;
21
22int do_list(librbd::RBD &rbd, librados::IoCtx& io_ctx, bool lflag,
23 Formatter *f) {
24 std::vector<std::string> names;
25 int r = rbd.list(io_ctx, names);
26 if (r == -ENOENT)
27 r = 0;
28 if (r < 0)
29 return r;
30
31 if (!lflag) {
32 if (f)
33 f->open_array_section("images");
34 for (std::vector<std::string>::const_iterator i = names.begin();
35 i != names.end(); ++i) {
36 if (f)
37 f->dump_string("name", *i);
38 else
39 std::cout << *i << std::endl;
40 }
41 if (f) {
42 f->close_section();
43 f->flush(std::cout);
44 }
45 return 0;
46 }
47
48 TextTable tbl;
49
50 if (f) {
51 f->open_array_section("images");
52 } else {
53 tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
54 tbl.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT);
55 tbl.define_column("PARENT", TextTable::LEFT, TextTable::LEFT);
56 tbl.define_column("FMT", TextTable::RIGHT, TextTable::RIGHT);
57 tbl.define_column("PROT", TextTable::LEFT, TextTable::LEFT);
58 tbl.define_column("LOCK", TextTable::LEFT, TextTable::LEFT);
59 }
60
61 std::string pool, image, snap, parent;
62
63 for (std::vector<std::string>::const_iterator i = names.begin();
64 i != names.end(); ++i) {
65 librbd::image_info_t info;
66 librbd::Image im;
67
68 r = rbd.open_read_only(io_ctx, im, i->c_str(), NULL);
69 // image might disappear between rbd.list() and rbd.open(); ignore
70 // that, warn about other possible errors (EPERM, say, for opening
71 // an old-format image, because you need execute permission for the
72 // class method)
73 if (r < 0) {
74 if (r != -ENOENT) {
75 std::cerr << "rbd: error opening " << *i << ": " << cpp_strerror(r)
76 << std::endl;
77 }
78 // in any event, continue to next image
79 continue;
80 }
81
82 // handle second-nth trips through loop
83 parent.clear();
84 r = im.parent_info(&pool, &image, &snap);
85 if (r < 0 && r != -ENOENT)
86 goto out;
87 bool has_parent = false;
88 if (r != -ENOENT) {
89 parent = pool + "/" + image + "@" + snap;
90 has_parent = true;
91 }
92
93 if (im.stat(info, sizeof(info)) < 0) {
94 r = -EINVAL;
95 goto out;
96 }
97
98 uint8_t old_format;
99 im.old_format(&old_format);
100
101 std::list<librbd::locker_t> lockers;
102 bool exclusive;
103 r = im.list_lockers(&lockers, &exclusive, NULL);
104 if (r < 0)
105 goto out;
106 std::string lockstr;
107 if (!lockers.empty()) {
108 lockstr = (exclusive) ? "excl" : "shr";
109 }
110
111 if (f) {
112 f->open_object_section("image");
113 f->dump_string("image", *i);
114 f->dump_unsigned("size", info.size);
115 if (has_parent) {
116 f->open_object_section("parent");
117 f->dump_string("pool", pool);
118 f->dump_string("image", image);
119 f->dump_string("snapshot", snap);
120 f->close_section();
121 }
122 f->dump_int("format", old_format ? 1 : 2);
123 if (!lockers.empty())
124 f->dump_string("lock_type", exclusive ? "exclusive" : "shared");
125 f->close_section();
126 } else {
127 tbl << *i
128 << stringify(si_t(info.size))
129 << parent
130 << ((old_format) ? '1' : '2')
131 << "" // protect doesn't apply to images
132 << lockstr
133 << TextTable::endrow;
134 }
135
136 std::vector<librbd::snap_info_t> snaplist;
137 if (im.snap_list(snaplist) >= 0 && !snaplist.empty()) {
138 for (std::vector<librbd::snap_info_t>::iterator s = snaplist.begin();
139 s != snaplist.end(); ++s) {
140 bool is_protected;
141 bool has_parent = false;
142 parent.clear();
143 im.snap_set(s->name.c_str());
144 r = im.snap_is_protected(s->name.c_str(), &is_protected);
145 if (r < 0)
146 goto out;
147 if (im.parent_info(&pool, &image, &snap) >= 0) {
148 parent = pool + "/" + image + "@" + snap;
149 has_parent = true;
150 }
151 if (f) {
152 f->open_object_section("snapshot");
153 f->dump_string("image", *i);
154 f->dump_string("snapshot", s->name);
155 f->dump_unsigned("size", s->size);
156 if (has_parent) {
157 f->open_object_section("parent");
158 f->dump_string("pool", pool);
159 f->dump_string("image", image);
160 f->dump_string("snapshot", snap);
161 f->close_section();
162 }
163 f->dump_int("format", old_format ? 1 : 2);
164 f->dump_string("protected", is_protected ? "true" : "false");
165 f->close_section();
166 } else {
167 tbl << *i + "@" + s->name
168 << stringify(si_t(s->size))
169 << parent
170 << ((old_format) ? '1' : '2')
171 << (is_protected ? "yes" : "")
172 << "" // locks don't apply to snaps
173 << TextTable::endrow;
174 }
175 }
176 }
177 }
178
179out:
180 if (f) {
181 f->close_section();
182 f->flush(std::cout);
183 } else if (!names.empty()) {
184 std::cout << tbl;
185 }
186
187 return r < 0 ? r : 0;
188}
189
190void get_arguments(po::options_description *positional,
191 po::options_description *options) {
192 options->add_options()
193 ("long,l", po::bool_switch(), "long listing format");
194 at::add_pool_options(positional, options);
195 at::add_format_options(options);
196}
197
198int execute(const po::variables_map &vm) {
199 size_t arg_index = 0;
200 std::string pool_name = utils::get_pool_name(vm, &arg_index);
201
202 at::Format::Formatter formatter;
203 int r = utils::get_formatter(vm, &formatter);
204 if (r < 0) {
205 return r;
206 }
207
208 librados::Rados rados;
209 librados::IoCtx io_ctx;
210 r = utils::init(pool_name, &rados, &io_ctx);
211 if (r < 0) {
212 return r;
213 }
214
215 librbd::RBD rbd;
216 r = do_list(rbd, io_ctx, vm["long"].as<bool>(), formatter.get());
217 if (r < 0) {
218 std::cerr << "rbd: list: " << cpp_strerror(r) << std::endl;
219 return r;
220 }
221
222 return 0;
223}
224
225Shell::SwitchArguments switched_arguments({"long", "l"});
226Shell::Action action(
227 {"list"}, {"ls"}, "List rbd images.", "", &get_arguments, &execute);
228
229} // namespace list
230} // namespace action
231} // namespace rbd