mirror of
https://github.com/ceph/ceph
synced 2025-02-19 08:57:27 +00:00
cephfs-shell: add snapshot management
Snapshots can be managed by: $ snap {create|delete} snap_name dir_name Fixes: http://tracker.ceph.com/issues/38681 Signed-off-by: Milind Changire <mchangir@redhat.com>
This commit is contained in:
parent
324f8781ca
commit
73597e94f1
@ -380,3 +380,17 @@ Usage :
|
||||
|
||||
Options :
|
||||
-h Shows the help message
|
||||
|
||||
snap
|
||||
----
|
||||
|
||||
Create or Delete Snapshot
|
||||
|
||||
Usage:
|
||||
|
||||
snap {create|delete} <snap_name> <dir_name>
|
||||
|
||||
* snap_name - Snapshot name to be created or deleted
|
||||
|
||||
* dir_name - directory under which snapshot should be created or deleted
|
||||
|
||||
|
@ -48,6 +48,11 @@ class TestCephFSShell(CephFSTestCase):
|
||||
return mount_x.client_remote.run(args=args, stdout=StringIO(),
|
||||
stdin=stdin)
|
||||
|
||||
def get_cephfs_shell_cmd_error(self, cmd, mount_x=None, opts=None,
|
||||
stdin=None):
|
||||
return self.run_cephfs_shell_cmd(cmd, mount_x, opts, stdin).stderr.\
|
||||
getvalue().strip()
|
||||
|
||||
def get_cephfs_shell_cmd_output(self, cmd, mount_x=None, opts=None,
|
||||
stdin=None):
|
||||
return self.run_cephfs_shell_cmd(cmd, mount_x, opts, stdin).stdout.\
|
||||
@ -293,6 +298,71 @@ class TestGetAndPut(TestCephFSShell):
|
||||
log.info("o_hash:{}".format(o_hash))
|
||||
assert(s_hash == o_hash)
|
||||
|
||||
class TestSnapshots(TestCephFSShell):
|
||||
def test_snap(self):
|
||||
"""
|
||||
Test that snapshot creation and deletion work
|
||||
"""
|
||||
sd = self.fs.get_config('client_snapdir')
|
||||
sdn = "data_dir/{}/snap1".format(sd)
|
||||
|
||||
# create a data dir and dump some files into it
|
||||
self.get_cephfs_shell_cmd_output("mkdir data_dir")
|
||||
s = 'A' * 10240
|
||||
o = self.get_cephfs_shell_cmd_output("put - data_dir/data_a", stdin=s)
|
||||
s = 'B' * 10240
|
||||
o = self.get_cephfs_shell_cmd_output("put - data_dir/data_b", stdin=s)
|
||||
s = 'C' * 10240
|
||||
o = self.get_cephfs_shell_cmd_output("put - data_dir/data_c", stdin=s)
|
||||
s = 'D' * 10240
|
||||
o = self.get_cephfs_shell_cmd_output("put - data_dir/data_d", stdin=s)
|
||||
s = 'E' * 10240
|
||||
o = self.get_cephfs_shell_cmd_output("put - data_dir/data_e", stdin=s)
|
||||
|
||||
o = self.get_cephfs_shell_cmd_output("ls -l /data_dir")
|
||||
log.info("cephfs-shell output:\n{}".format(o))
|
||||
|
||||
# create the snapshot - must pass
|
||||
o = self.get_cephfs_shell_cmd_output("snap create snap1 /data_dir")
|
||||
log.info("cephfs-shell output:\n{}".format(o))
|
||||
assert(o == "")
|
||||
o = self.mount_a.stat(sdn)
|
||||
log.info("mount_a output:\n{}".format(o))
|
||||
assert(('st_mode' in str(o)) == True)
|
||||
|
||||
# create the same snapshot again - must fail with an error message
|
||||
o = self.get_cephfs_shell_cmd_error("snap create snap1 /data_dir")
|
||||
log.info("cephfs-shell output:\n{}".format(o))
|
||||
o = o.split('\n')
|
||||
assert(o[0] == "ERROR: snapshot 'snap1' already exists")
|
||||
o = self.mount_a.stat(sdn)
|
||||
log.info("mount_a output:\n{}".format(o))
|
||||
assert(('st_mode' in str(o)) == True)
|
||||
|
||||
# delete the snapshot - must pass
|
||||
o = self.get_cephfs_shell_cmd_output("snap delete snap1 /data_dir")
|
||||
log.info("cephfs-shell output:\n{}".format(o))
|
||||
assert(o == "")
|
||||
try:
|
||||
o = self.mount_a.stat(sdn)
|
||||
except:
|
||||
# snap dir should not exist anymore
|
||||
pass
|
||||
log.info("mount_a output:\n{}".format(o))
|
||||
assert(('st_mode' in str(o)) == False)
|
||||
|
||||
# delete the same snapshot again - must fail with an error message
|
||||
o = self.get_cephfs_shell_cmd_error("snap delete snap1 /data_dir")
|
||||
o = o.strip()
|
||||
o = o.split('\n')
|
||||
assert(o[0] == "ERROR: 'snap1': no such snapshot")
|
||||
try:
|
||||
o = self.mount_a.stat(sdn)
|
||||
except:
|
||||
pass
|
||||
log.info("mount_a output:\n{}".format(o))
|
||||
assert(('st_mode' in str(o)) == False)
|
||||
|
||||
class TestCD(TestCephFSShell):
|
||||
CLIENTS_REQUIRED = 1
|
||||
|
||||
|
@ -172,8 +172,9 @@ def get_all_possible_paths(pattern):
|
||||
for pattern in patterns:
|
||||
for path in paths:
|
||||
paths.extend(glob(path, pattern))
|
||||
return [path for path in paths if fnmatch.fnmatch(path,
|
||||
os.path.join(cephfs.getcwd(), complete_pattern))]
|
||||
if is_rel_path:
|
||||
complete_pattern = os.path.join(cephfs.getcwd(), complete_pattern)
|
||||
return [path for path in paths if fnmatch.fnmatch(path, complete_pattern)]
|
||||
|
||||
|
||||
suffixes = ['B', 'K', 'M', 'G', 'T', 'P']
|
||||
@ -822,6 +823,9 @@ sub-directories, files')
|
||||
|
||||
@with_argparser(rmdir_parser)
|
||||
def do_rmdir(self, args):
|
||||
self.do_rmdir_helper(args)
|
||||
|
||||
def do_rmdir_helper(self, args):
|
||||
"""
|
||||
Remove a specific Directory
|
||||
"""
|
||||
@ -1245,6 +1249,50 @@ sub-directories, files')
|
||||
perror('max_files is not set')
|
||||
pass
|
||||
|
||||
snap_parser = argparse.ArgumentParser(description='Snapshot Management')
|
||||
snap_parser.add_argument('op', type=str,
|
||||
help='Snapshot operation: create or delete')
|
||||
snap_parser.add_argument('name', type=str, action=path_to_bytes,
|
||||
help='Name of snapshot')
|
||||
snap_parser.add_argument('dir', type=str, action=path_to_bytes,
|
||||
help='Directory for which snapshot '
|
||||
'needs to be created or deleted')
|
||||
|
||||
@with_argparser(snap_parser)
|
||||
def do_snap(self, args):
|
||||
"""
|
||||
Snapshot management for the volume
|
||||
"""
|
||||
# setting self.colors to None turns off colorizing and
|
||||
# perror emits plain text
|
||||
self.colors = None
|
||||
|
||||
snapdir = '.snap'
|
||||
conf_snapdir = cephfs.conf_get('client_snapdir')
|
||||
if conf_snapdir is not None:
|
||||
snapdir = conf_snapdir
|
||||
snapdir = to_bytes(snapdir)
|
||||
if args.op == 'create':
|
||||
try:
|
||||
if is_dir_exists(args.dir):
|
||||
cephfs.mkdir(os.path.join(args.dir, snapdir, args.name), 0o755)
|
||||
else:
|
||||
self.perror("'{}': no such directory".format(args.dir.decode('utf-8')))
|
||||
except libcephfs.Error:
|
||||
self.perror("snapshot '{}' already exists".format(args.name.decode('utf-8')))
|
||||
elif args.op == 'delete':
|
||||
snap_dir = os.path.join(args.dir, snapdir, args.name)
|
||||
try:
|
||||
if is_dir_exists(snap_dir):
|
||||
newargs = argparse.Namespace(paths=[snap_dir], parent=False)
|
||||
self.do_rmdir_helper(newargs)
|
||||
else:
|
||||
self.perror("'{}': no such snapshot".format(args.name.decode('utf-8')))
|
||||
except libcephfs.Error:
|
||||
self.perror("error while deleting '{}'".format(snap_dir.decode('utf-8')))
|
||||
else:
|
||||
self.perror("snapshot can only be created or deleted; check - help snap")
|
||||
|
||||
def do_help(self, line):
|
||||
"""
|
||||
Get details about a command.
|
||||
|
Loading…
Reference in New Issue
Block a user