mirror of
https://github.com/ceph/ceph
synced 2025-02-21 09:57:26 +00:00
Merge remote-tracking branch 'gh/wip-rbd-tool'
This commit is contained in:
commit
cd6d70090d
@ -1,12 +1,12 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
TMP_FILES="/tmp/img1 /tmp/img1.new /tmp/img2 /tmp/img2.new /tmp/img3 /tmp/img3.new /tmp/img1.snap1"
|
||||
|
||||
rbd rm testimg1 || true
|
||||
rbd rm testimg2 || true
|
||||
rbd rm testimg3 || true
|
||||
|
||||
rm -f /tmp/img1 /tmp/img1.new
|
||||
rm -f /tmp/img2 /tmp/img2.new
|
||||
rm -f /tmp/img3 /tmp/img3.new
|
||||
rm -f $TMP_FILES
|
||||
|
||||
# create an image
|
||||
dd if=/bin/sh of=/tmp/img1 bs=1k count=1 seek=10
|
||||
@ -23,6 +23,10 @@ rbd snap create testimg1 --snap=snap1
|
||||
rbd resize testimg1 --size=128
|
||||
rbd export testimg1 /tmp/img3
|
||||
|
||||
# info
|
||||
rbd info testimg1 | grep 'size 128 MB'
|
||||
rbd info --snap=snap1 testimg1 | grep 'size 256 MB'
|
||||
|
||||
# make copies
|
||||
rbd copy testimg1 --snap=snap1 testimg2
|
||||
rbd copy testimg1 testimg3
|
||||
@ -38,6 +42,16 @@ rbd export testimg3 /tmp/img3.new
|
||||
cmp /tmp/img2 /tmp/img2.new
|
||||
cmp /tmp/img3 /tmp/img3.new
|
||||
|
||||
rm /tmp/img1 /tmp/img2 /tmp/img3 /tmp/img1.new /tmp/img2.new /tmp/img3.new
|
||||
# rollback
|
||||
rbd snap rollback --snap=snap1 testimg1
|
||||
rbd info testimg1 | grep 'size 256 MB'
|
||||
rbd export testimg1 /tmp/img1.snap1
|
||||
cmp /tmp/img2 /tmp/img1.snap1
|
||||
|
||||
# remove snapshots
|
||||
rbd snap rm --snap=snap1 testimg1
|
||||
rbd info --snap=snap1 testimg1 2>&1 | grep 'error setting snapshot context: error 2: No such file or directory'
|
||||
|
||||
rm -f $TMP_FILES
|
||||
|
||||
echo OK
|
||||
|
5
qa/workunits/rbd/test_librbd_python.sh
Executable file
5
qa/workunits/rbd/test_librbd_python.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
wget -q https://raw.github.com/NewDreamNetwork/ceph/master/src/test/pybind/test_rbd.py
|
||||
nosetests -v test_rbd
|
||||
exit 0
|
@ -1678,11 +1678,10 @@ int librados::RadosClient::clone_range(IoCtxImpl& io,
|
||||
bufferlist outbl;
|
||||
|
||||
lock.Lock();
|
||||
::SnapContext snapc;
|
||||
::ObjectOperation wr;
|
||||
prepare_assert_ops(&io, &wr);
|
||||
wr.clone_range(src_oid, src_offset, len, dst_offset);
|
||||
objecter->mutate(dst_oid, io.oloc, wr, snapc, ut, 0, onack, NULL, &ver);
|
||||
objecter->mutate(dst_oid, io.oloc, wr, io.snapc, ut, 0, onack, NULL, &ver);
|
||||
lock.Unlock();
|
||||
|
||||
mylock.Lock();
|
||||
@ -1906,7 +1905,6 @@ int librados::RadosClient::aio_write_full(IoCtxImpl& io, const object_t &oid,
|
||||
|
||||
int librados::RadosClient::remove(IoCtxImpl& io, const object_t& oid)
|
||||
{
|
||||
::SnapContext snapc;
|
||||
utime_t ut = ceph_clock_now(cct);
|
||||
|
||||
/* can't write to a snapshot */
|
||||
@ -1925,7 +1923,7 @@ int librados::RadosClient::remove(IoCtxImpl& io, const object_t& oid)
|
||||
|
||||
lock.Lock();
|
||||
objecter->remove(oid, io.oloc,
|
||||
snapc, ut, 0,
|
||||
io.snapc, ut, 0,
|
||||
onack, NULL, &ver, pop);
|
||||
lock.Unlock();
|
||||
|
||||
@ -1993,11 +1991,10 @@ int librados::RadosClient::tmap_update(IoCtxImpl& io, const object_t& oid, buffe
|
||||
bufferlist outbl;
|
||||
|
||||
lock.Lock();
|
||||
::SnapContext snapc;
|
||||
::ObjectOperation wr;
|
||||
prepare_assert_ops(&io, &wr);
|
||||
wr.tmap_update(cmdbl);
|
||||
objecter->mutate(oid, io.oloc, wr, snapc, ut, 0, onack, NULL, &ver);
|
||||
objecter->mutate(oid, io.oloc, wr, io.snapc, ut, 0, onack, NULL, &ver);
|
||||
lock.Unlock();
|
||||
|
||||
mylock.Lock();
|
||||
@ -2028,11 +2025,10 @@ int librados::RadosClient::tmap_put(IoCtxImpl& io, const object_t& oid, bufferli
|
||||
bufferlist outbl;
|
||||
|
||||
lock.Lock();
|
||||
::SnapContext snapc;
|
||||
::ObjectOperation wr;
|
||||
prepare_assert_ops(&io, &wr);
|
||||
wr.tmap_put(bl);
|
||||
objecter->mutate(oid, io.oloc, wr, snapc, ut, 0, onack, NULL, &ver);
|
||||
objecter->mutate(oid, io.oloc, wr, io.snapc, ut, 0, onack, NULL, &ver);
|
||||
lock.Unlock();
|
||||
|
||||
mylock.Lock();
|
||||
|
184
src/librbd.cc
184
src/librbd.cc
@ -137,6 +137,16 @@ namespace librbd {
|
||||
return CEPH_NOSNAP;
|
||||
}
|
||||
|
||||
int get_snap_size(std::string snap_name, uint64_t *size) const
|
||||
{
|
||||
std::map<std::string, struct SnapInfo>::const_iterator it = snaps_by_name.find(snap_name);
|
||||
if (it != snaps_by_name.end()) {
|
||||
*size = it->second.size;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
void add_snap(std::string snap_name, snap_t id, uint64_t size)
|
||||
{
|
||||
snapc.snaps.push_back(id);
|
||||
@ -150,11 +160,12 @@ namespace librbd {
|
||||
return name + RBD_SUFFIX;
|
||||
}
|
||||
|
||||
uint64_t get_image_size() {
|
||||
uint64_t get_image_size() const
|
||||
{
|
||||
if (snapname.length() == 0) {
|
||||
return header.image_size;
|
||||
} else {
|
||||
map<std::string,SnapInfo>::iterator p = snaps_by_name.find(snapname);
|
||||
map<std::string,SnapInfo>::const_iterator p = snaps_by_name.find(snapname);
|
||||
assert(p != snaps_by_name.end());
|
||||
return p->second.size;
|
||||
}
|
||||
@ -331,6 +342,7 @@ namespace librbd {
|
||||
int info(ImageCtx *ictx, image_info_t& info, size_t image_size);
|
||||
int remove(IoCtx& io_ctx, const char *imgname, ProgressContext& prog_ctx);
|
||||
int resize(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx);
|
||||
int resize_helper(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx);
|
||||
int snap_create(ImageCtx *ictx, const char *snap_name);
|
||||
int snap_list(ImageCtx *ictx, std::vector<snap_info_t>& snaps);
|
||||
int snap_rollback(ImageCtx *ictx, const char *snap_name, ProgressContext& prog_ctx);
|
||||
@ -357,7 +369,7 @@ namespace librbd {
|
||||
int tmap_set(IoCtx& io_ctx, const string& imgname);
|
||||
int tmap_rm(IoCtx& io_ctx, const string& imgname);
|
||||
int rollback_image(ImageCtx *ictx, uint64_t snapid, ProgressContext& prog_ctx);
|
||||
void image_info(const rbd_obj_header_ondisk& header, image_info_t& info, size_t info_size);
|
||||
void image_info(const ImageCtx& ictx, image_info_t& info, size_t info_size);
|
||||
string get_block_oid(const rbd_obj_header_ondisk &header, uint64_t num);
|
||||
uint64_t get_max_block(uint64_t size, int obj_order);
|
||||
uint64_t get_max_block(const rbd_obj_header_ondisk &header);
|
||||
@ -441,14 +453,14 @@ void init_rbd_header(struct rbd_obj_header_ondisk& ondisk,
|
||||
ondisk.snap_names_len = 0;
|
||||
}
|
||||
|
||||
void image_info(const rbd_obj_header_ondisk& header, image_info_t& info, size_t infosize)
|
||||
void image_info(const ImageCtx& ictx, image_info_t& info, size_t infosize)
|
||||
{
|
||||
int obj_order = header.options.order;
|
||||
info.size = header.image_size;
|
||||
int obj_order = ictx.header.options.order;
|
||||
info.size = ictx.get_image_size();
|
||||
info.obj_size = 1 << obj_order;
|
||||
info.num_objs = header.image_size >> obj_order;
|
||||
info.num_objs = ictx.get_image_size() >> obj_order;
|
||||
info.order = obj_order;
|
||||
memcpy(&info.block_name_prefix, &header.block_name, RBD_MAX_BLOCK_NAME_SIZE);
|
||||
memcpy(&info.block_name_prefix, &ictx.header.block_name, RBD_MAX_BLOCK_NAME_SIZE);
|
||||
info.parent_pool = -1;
|
||||
bzero(&info.parent_name, RBD_MAX_IMAGE_NAME_SIZE);
|
||||
}
|
||||
@ -828,7 +840,7 @@ int info(ImageCtx *ictx, image_info_t& info, size_t infosize)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
image_info(ictx->header, info, infosize);
|
||||
image_info(*ictx, info, infosize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -862,17 +874,9 @@ int remove(IoCtx& io_ctx, const char *imgname, ProgressContext& prog_ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resize(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx)
|
||||
int resize_helper(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx)
|
||||
{
|
||||
CephContext *cct = ictx->cct;
|
||||
ldout(cct, 20) << "resize " << ictx << " " << ictx->header.image_size << " -> " << size << dendl;
|
||||
|
||||
int r = ictx_check(ictx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
// trim
|
||||
if (size == ictx->header.image_size) {
|
||||
ldout(cct, 2) << "no change in size (" << size << " -> " << ictx->header.image_size << ")" << dendl;
|
||||
return 0;
|
||||
@ -890,7 +894,7 @@ int resize(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx)
|
||||
// rewrite header
|
||||
bufferlist bl;
|
||||
bl.append((const char *)&(ictx->header), sizeof(ictx->header));
|
||||
r = ictx->md_ctx.write(ictx->md_oid(), bl, bl.length(), 0);
|
||||
int r = ictx->md_ctx.write(ictx->md_oid(), bl, bl.length(), 0);
|
||||
|
||||
if (r == -ERANGE)
|
||||
lderr(cct) << "operation might have conflicted with another client!" << dendl;
|
||||
@ -901,6 +905,21 @@ int resize(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx)
|
||||
notify_change(ictx->md_ctx, ictx->md_oid(), NULL, ictx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resize(ImageCtx *ictx, uint64_t size, ProgressContext& prog_ctx)
|
||||
{
|
||||
CephContext *cct = ictx->cct;
|
||||
ldout(cct, 20) << "resize " << ictx << " " << ictx->header.image_size << " -> " << size << dendl;
|
||||
|
||||
int r = ictx_check(ictx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
resize_helper(ictx, size, prog_ctx);
|
||||
|
||||
ldout(cct, 2) << "done." << dendl;
|
||||
|
||||
return 0;
|
||||
@ -1062,59 +1081,6 @@ int ictx_refresh(ImageCtx *ictx, const char *snap_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snap_rollback(ImageCtx *ictx, const char *snap_name, ProgressContext& prog_ctx)
|
||||
{
|
||||
CephContext *cct = ictx->cct;
|
||||
ldout(cct, 20) << "snap_rollback " << ictx << " snap = " << snap_name << dendl;
|
||||
|
||||
int r = ictx_check(ictx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
snap_t snapid = ictx->get_snapid(snap_name);
|
||||
if (snapid == CEPH_NOSNAP) {
|
||||
lderr(cct) << "No such snapshot found." << dendl;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = rollback_image(ictx, snapid, prog_ctx);
|
||||
if (r < 0) {
|
||||
lderr(cct) << "Error rolling back image: " << cpp_strerror(-r) << dendl;
|
||||
return r;
|
||||
}
|
||||
|
||||
// refresh without setting the snapid we read from
|
||||
ictx_refresh(ictx, NULL);
|
||||
snap_t new_snapid = ictx->get_snapid(snap_name);
|
||||
ldout(ictx->cct, 20) << "snapid is " << ictx->snapid << " new snapid is " << new_snapid << dendl;
|
||||
|
||||
notify_change(ictx->md_ctx, ictx->md_oid(), NULL, ictx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CopyProgressCtx {
|
||||
CopyProgressCtx(ProgressContext &p)
|
||||
: prog_ctx(p)
|
||||
{
|
||||
}
|
||||
ImageCtx *destictx;
|
||||
uint64_t src_size;
|
||||
ProgressContext &prog_ctx;
|
||||
};
|
||||
|
||||
int do_copy_extent(uint64_t offset, size_t len, const char *buf, void *data)
|
||||
{
|
||||
CopyProgressCtx *cp = reinterpret_cast<CopyProgressCtx*>(data);
|
||||
cp->prog_ctx.update_progress(offset, cp->src_size);
|
||||
int ret = 0;
|
||||
if (buf) {
|
||||
ret = write(cp->destictx, offset, len, buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ProgressContext::~ProgressContext()
|
||||
{
|
||||
}
|
||||
@ -1147,6 +1113,70 @@ private:
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
int snap_rollback(ImageCtx *ictx, const char *snap_name, ProgressContext& prog_ctx)
|
||||
{
|
||||
CephContext *cct = ictx->cct;
|
||||
ldout(cct, 20) << "snap_rollback " << ictx << " snap = " << snap_name << dendl;
|
||||
|
||||
int r = ictx_check(ictx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
snap_t snapid = ictx->get_snapid(snap_name);
|
||||
if (snapid == CEPH_NOSNAP) {
|
||||
lderr(cct) << "No such snapshot found." << dendl;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
uint64_t new_size = ictx->get_image_size();
|
||||
ictx->get_snap_size(snap_name, &new_size);
|
||||
ldout(cct, 2) << "resizing to snapshot size..." << dendl;
|
||||
NoOpProgressContext no_op;
|
||||
r = resize_helper(ictx, new_size, no_op);
|
||||
if (r < 0) {
|
||||
lderr(cct) << "Error resizing to snapshot size: "
|
||||
<< cpp_strerror(-r) << dendl;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rollback_image(ictx, snapid, prog_ctx);
|
||||
if (r < 0) {
|
||||
lderr(cct) << "Error rolling back image: " << cpp_strerror(-r) << dendl;
|
||||
return r;
|
||||
}
|
||||
|
||||
// refresh without setting the snapid we read from
|
||||
ictx_refresh(ictx, NULL);
|
||||
snap_t new_snapid = ictx->get_snapid(snap_name);
|
||||
ldout(cct, 20) << "snapid is " << ictx->snapid << " new snapid is " << new_snapid << dendl;
|
||||
|
||||
notify_change(ictx->md_ctx, ictx->md_oid(), NULL, ictx);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
struct CopyProgressCtx {
|
||||
CopyProgressCtx(ProgressContext &p)
|
||||
: prog_ctx(p)
|
||||
{
|
||||
}
|
||||
ImageCtx *destictx;
|
||||
uint64_t src_size;
|
||||
ProgressContext &prog_ctx;
|
||||
};
|
||||
|
||||
int do_copy_extent(uint64_t offset, size_t len, const char *buf, void *data)
|
||||
{
|
||||
CopyProgressCtx *cp = reinterpret_cast<CopyProgressCtx*>(data);
|
||||
cp->prog_ctx.update_progress(offset, cp->src_size);
|
||||
int ret = 0;
|
||||
if (buf) {
|
||||
ret = write(cp->destictx, offset, len, buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int copy(ImageCtx& ictx, IoCtx& dest_md_ctx, const char *destname,
|
||||
ProgressContext &prog_ctx)
|
||||
{
|
||||
@ -1190,10 +1220,14 @@ int snap_set(ImageCtx *ictx, const char *snap_name)
|
||||
return r;
|
||||
|
||||
Mutex::Locker l(ictx->lock);
|
||||
if (snap_name)
|
||||
ictx->snap_set(snap_name);
|
||||
else
|
||||
if (snap_name) {
|
||||
r = ictx->snap_set(snap_name);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
ictx->snap_unset();
|
||||
}
|
||||
|
||||
ictx->data_ctx.snap_set_read(ictx->snapid);
|
||||
|
||||
|
@ -304,7 +304,6 @@ class Image(object):
|
||||
:type dest_ioctx: :class:`rados.Ioctx`
|
||||
:param dest_name: the name of the copy
|
||||
:type dest_name: str
|
||||
:returns: int - the number of bytes copied
|
||||
:raises: :class:`ImageExists`
|
||||
"""
|
||||
if not isinstance(dest_name, str):
|
||||
@ -312,7 +311,6 @@ class Image(object):
|
||||
ret = self.librbd.rbd_copy(self.image, dest_ioctx.io, c_char_p(dest_name))
|
||||
if ret < 0:
|
||||
raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
|
||||
return ret
|
||||
|
||||
def list_snaps(self):
|
||||
"""
|
||||
|
28
src/rbd.cc
28
src/rbd.cc
@ -56,18 +56,18 @@ 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"
|
||||
<< " info [image-name] show information about image size,\n"
|
||||
<< " info <--snap=name> [image-name] show information about image size,\n"
|
||||
<< " striping, etc.\n"
|
||||
<< " create [image-name] create an empty image (requires size\n"
|
||||
<< " param)\n"
|
||||
<< " resize [image-name] resize (expand or contract) image\n"
|
||||
<< " (requires size param)\n"
|
||||
<< " rm [image-name] delete an image\n"
|
||||
<< " export [image-name] [dest-path] export image to file\n"
|
||||
<< " export <--snap=name> [image-name] [path] export image to file\n"
|
||||
<< " import [path] [dst-image] import image from file (dest defaults\n"
|
||||
<< " as the filename part of file)\n"
|
||||
<< " <cp | copy> [src-image] [dest-image] copy image to dest\n"
|
||||
<< " <mv | rename> [src-image] [dest-image] copy image to dest\n"
|
||||
<< " <cp | copy> <--snap=name> [src] [dest] copy src image to dest\n"
|
||||
<< " <mv | rename> [src] [dest] rename src image to dest\n"
|
||||
<< " snap ls [image-name] dump list of image snapshots\n"
|
||||
<< " snap create <--snap=name> [image-name] create a snapshot\n"
|
||||
<< " snap rollback <--snap=name> [image-name] rollback image head to snapshot\n"
|
||||
@ -1003,12 +1003,13 @@ int main(int argc, const char **argv)
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
if (opt_cmd == OPT_INFO || opt_cmd == OPT_EXPORT || opt_cmd == OPT_COPY ||
|
||||
opt_cmd == OPT_SNAP_CREATE || opt_cmd == OPT_SNAP_ROLLBACK ||
|
||||
opt_cmd == OPT_SNAP_REMOVE ||
|
||||
opt_cmd == OPT_MAP || opt_cmd == OPT_UNMAP) {
|
||||
set_pool_image_name(poolname, imgname, (char **)&poolname, (char **)&imgname, (char **)&snapname);
|
||||
} else if (snapname) {
|
||||
// do this unconditionally so we can parse pool/image@snapshot into
|
||||
// the relevant parts
|
||||
set_pool_image_name(poolname, imgname, (char **)&poolname,
|
||||
(char **)&imgname, (char **)&snapname);
|
||||
if (snapname && opt_cmd != OPT_SNAP_CREATE && opt_cmd != OPT_SNAP_ROLLBACK &&
|
||||
opt_cmd != OPT_SNAP_REMOVE && opt_cmd != OPT_INFO &&
|
||||
opt_cmd != OPT_EXPORT && opt_cmd != OPT_COPY) {
|
||||
cerr << "error: snapname specified for a command that doesn't use it" << std::endl;
|
||||
usage_exit();
|
||||
}
|
||||
@ -1053,7 +1054,7 @@ int main(int argc, const char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (imgname &&
|
||||
if (imgname && talk_to_cluster &&
|
||||
(opt_cmd == OPT_RESIZE || opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST ||
|
||||
opt_cmd == OPT_SNAP_CREATE || opt_cmd == OPT_SNAP_ROLLBACK ||
|
||||
opt_cmd == OPT_SNAP_REMOVE || opt_cmd == OPT_EXPORT || opt_cmd == OPT_WATCH ||
|
||||
@ -1065,9 +1066,10 @@ int main(int argc, const char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (snapname) {
|
||||
if (snapname && talk_to_cluster &&
|
||||
(opt_cmd == OPT_INFO || opt_cmd == OPT_EXPORT || opt_cmd == OPT_COPY)) {
|
||||
r = image.snap_set(snapname);
|
||||
if (r < 0 && !(r == -ENOENT && opt_cmd == OPT_SNAP_CREATE)) {
|
||||
if (r < 0) {
|
||||
cerr << "error setting snapshot context: " << cpp_strerror(-r) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
38
src/test/cli/rbd/help.t
Normal file
38
src/test/cli/rbd/help.t
Normal file
@ -0,0 +1,38 @@
|
||||
$ 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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
360
src/test/cli/rbd/invalid-snap-usage.t
Normal file
360
src/test/cli/rbd/invalid-snap-usage.t
Normal file
@ -0,0 +1,360 @@
|
||||
$ rbd resize --snap=snap1 img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd resize img@snap
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd import --snap=snap1 /bin/ls ls
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd create --snap=snap img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd rm --snap=snap img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd rename --snap=snap img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd ls --snap=snap rbd
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd snap ls --snap=snap img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
||||
$ rbd watch --snap=snap img
|
||||
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
|
||||
info <--snap=name> [image-name] show information about image size,
|
||||
striping, etc.
|
||||
create [image-name] create an empty image (requires size
|
||||
param)
|
||||
resize [image-name] resize (expand or contract) image
|
||||
(requires size param)
|
||||
rm [image-name] delete an image
|
||||
export <--snap=name> [image-name] [path] export image to file
|
||||
import [path] [dst-image] import image from file (dest defaults
|
||||
as the filename part of file)
|
||||
<cp | copy> <--snap=name> [src] [dest] copy src image to dest
|
||||
<mv | rename> [src] [dest] rename src image to dest
|
||||
snap ls [image-name] dump list of image snapshots
|
||||
snap create <--snap=name> [image-name] create a snapshot
|
||||
snap rollback <--snap=name> [image-name] rollback image head to snapshot
|
||||
snap rm <--snap=name> [image-name] deletes a snapshot
|
||||
watch [image-name] watch events on image
|
||||
map [image-name] map the image to a block device
|
||||
using the kernel
|
||||
unmap [device] unmap a rbd device that was
|
||||
mapped by the kernel
|
||||
|
||||
Other input options:
|
||||
-p, --pool <pool> source pool name
|
||||
--image <image-name> image name
|
||||
--dest <name> destination [pool and] image name
|
||||
--snap <snapname> specify snapshot name
|
||||
--dest-pool <name> destination pool name
|
||||
--path <path-name> path name for import/export (if not specified)
|
||||
--size <size in MB> size parameter for create and resize commands
|
||||
|
||||
For the map command:
|
||||
--user <username> rados user to authenticate as
|
||||
--secret <path> file containing secret key for use with authx
|
||||
[1]
|
@ -4,7 +4,7 @@ import struct
|
||||
from nose import with_setup
|
||||
from nose.tools import eq_ as eq, assert_raises
|
||||
from rados import Rados
|
||||
from rbd import RBD, Image, ImageNotFound, InvalidArgument
|
||||
from rbd import RBD, Image, ImageNotFound, InvalidArgument, ImageExists
|
||||
|
||||
|
||||
rados = None
|
||||
@ -130,12 +130,12 @@ class TestImage(object):
|
||||
global ioctx
|
||||
data = rand_data(256)
|
||||
self.image.write(data, 256)
|
||||
bytes_copied = self.image.copy(ioctx, IMG_NAME + '2')
|
||||
self.image.copy(ioctx, IMG_NAME + '2')
|
||||
assert_raises(ImageExists, self.image.copy, ioctx, IMG_NAME + '2')
|
||||
copy = Image(ioctx, IMG_NAME + '2')
|
||||
copy_data = copy.read(256, 256)
|
||||
copy.close()
|
||||
self.rbd.remove(ioctx, IMG_NAME + '2')
|
||||
eq(bytes_copied, IMG_SIZE)
|
||||
eq(data, copy_data)
|
||||
|
||||
def test_create_snap(self):
|
||||
@ -191,6 +191,29 @@ class TestImage(object):
|
||||
read = self.image.read(0, 256)
|
||||
eq(read, '\0' * 256)
|
||||
|
||||
def test_rollback_with_resize(self):
|
||||
read = self.image.read(0, 256)
|
||||
eq(read, '\0' * 256)
|
||||
data = rand_data(256)
|
||||
self.image.write(data, 0)
|
||||
self.image.create_snap('snap1')
|
||||
read = self.image.read(0, 256)
|
||||
eq(read, data)
|
||||
new_size = IMG_SIZE * 2
|
||||
self.image.resize(new_size)
|
||||
check_stat(self.image.stat(), new_size, IMG_ORDER)
|
||||
self.image.write(data, new_size - 256)
|
||||
self.image.create_snap('snap2')
|
||||
read = self.image.read(new_size - 256, 256)
|
||||
eq(read, data)
|
||||
self.image.rollback_to_snap('snap1')
|
||||
check_stat(self.image.stat(), IMG_SIZE, IMG_ORDER)
|
||||
assert_raises(InvalidArgument, self.image.read, new_size - 256, 256)
|
||||
self.image.rollback_to_snap('snap2')
|
||||
check_stat(self.image.stat(), new_size, IMG_ORDER)
|
||||
read = self.image.read(new_size - 256, 256)
|
||||
eq(read, data)
|
||||
|
||||
def test_set_snap(self):
|
||||
self.image.write('\0' * 256, 0)
|
||||
self.image.create_snap('snap1')
|
||||
|
Loading…
Reference in New Issue
Block a user