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
+
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.\
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
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']
@with_argparser(rmdir_parser)
def do_rmdir(self, args):
+ self.do_rmdir_helper(args)
+
+ def do_rmdir_helper(self, args):
"""
Remove a specific Directory
"""
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.