name = fs_config.pop('name')
temp = deepcopy(cephfs_config)
teuthology.deep_merge(temp, fs_config)
+ subvols = config.get('subvols', None)
+ if subvols:
+ teuthology.deep_merge(temp, {'subvols': subvols})
fs = Filesystem(ctx, fs_config=temp, name=name, create=True)
if set_allow_multifs:
fs.set_allow_multifs()
mount_timeout: 120 # default is 30, give up if /sys/ is not populated
- interactive:
+ Example that creates and mounts a subvol:
+
+ overrides:
+ ceph:
+ subvols:
+ create: 2
+ subvol_options: "--namespace-isolated --size 25000000000"
+ ceph-fuse:
+ client.0:
+ mount_subvol_num: 0
+ kclient:
+ client.1:
+ mount_subvol_num: 1
+
:param ctx: Context
:param config: Configuration
"""
yield
-
@contextlib.contextmanager
def ceph_monitoring(daemon_type, ctx, config):
"""
raise
if self.fs_config is not None:
+ log.debug(f"fs_config: {self.fs_config}")
max_mds = self.fs_config.get('max_mds', 1)
if max_mds > 1:
self.set_max_mds(max_mds)
if session_timeout != 60:
self.set_session_timeout(session_timeout)
+ if self.fs_config.get('subvols', None) is not None:
+ log.debug(f"Creating {self.fs_config.get('subvols')} subvols "
+ f"for filesystem '{self.name}'")
+ if not hasattr(self._ctx, "created_subvols"):
+ self._ctx.created_subvols = dict()
+
+ subvols = self.fs_config.get('subvols')
+ assert(isinstance(subvols, dict))
+ assert(isinstance(subvols['create'], int))
+ assert(subvols['create'] > 0)
+
+ for sv in range(0, subvols['create']):
+ sv_name = f'sv_{sv}'
+ self.mon_manager.raw_cluster_cmd(
+ 'fs', 'subvolume', 'create', self.name, sv_name,
+ self.fs_config.get('subvol_options', ''))
+
+ if self.name not in self._ctx.created_subvols:
+ self._ctx.created_subvols[self.name] = []
+
+ subvol_path = self.mon_manager.raw_cluster_cmd(
+ 'fs', 'subvolume', 'getpath', self.name, sv_name)
+ subvol_path = subvol_path.strip()
+ self._ctx.created_subvols[self.name].append(subvol_path)
+ else:
+ log.debug(f"Not Creating any subvols for filesystem '{self.name}'")
+
+
self.getinfo(refresh = True)
# wait pgs to be clean
fuse_cmd += ['--id', self.client_id]
if self.client_keyring_path and self.client_id is not None:
fuse_cmd += ['-k', self.client_keyring_path]
+ self.validate_subvol_options()
if self.cephfs_mntpt is not None:
fuse_cmd += ["--client_mountpoint=" + self.cephfs_mntpt]
if self.cephfs_name is not None:
if not self.cephfs_mntpt:
self.cephfs_mntpt = '/'
+ if not self.cephfs_name:
+ self.cephfs_name = 'cephfs'
stderr = StringIO()
try:
checksum_text = self.run_shell(cmd).stdout.getvalue().strip()
checksum_sorted = sorted(checksum_text.split('\n'), key=lambda v: v.split()[1])
return hashlib.md5(('\n'.join(checksum_sorted)).encode('utf-8')).hexdigest()
+
+ def validate_subvol_options(self):
+ mount_subvol_num = self.client_config.get('mount_subvol_num', None)
+ if self.cephfs_mntpt and mount_subvol_num is not None:
+ log.warning("You cannot specify both: cephfs_mntpt and mount_subvol_num")
+ log.info(f"Mounting subvol {mount_subvol_num} for now")
+
+ if mount_subvol_num is not None:
+ # mount_subvol must be an index into the subvol path array for the fs
+ if not self.cephfs_name:
+ self.cephfs_name = 'cephfs'
+ assert(hasattr(self.ctx, "created_subvols"))
+ # mount_subvol must be specified under client.[0-9] yaml section
+ subvol_paths = self.ctx.created_subvols[self.cephfs_name]
+ path_to_mount = subvol_paths[mount_subvol_num]
+ self.cephfs_mntpt = path_to_mount
+ elif not self.cephfs_mntpt:
+ # default to the "/" path
+ self.cephfs_mntpt = "/"