diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-23 16:45:17 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-23 16:45:44 +0000 |
commit | 17d6a993fc17d533460c5f40f3908c708e057c18 (patch) | |
tree | 1a3bd93e0ecd74fa02f93a528fe2f87e5314c4b5 /src/pybind/mgr/snap_schedule/module.py | |
parent | Releasing progress-linux version 18.2.2-0progress7.99u1. (diff) | |
download | ceph-17d6a993fc17d533460c5f40f3908c708e057c18.tar.xz ceph-17d6a993fc17d533460c5f40f3908c708e057c18.zip |
Merging upstream version 18.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/pybind/mgr/snap_schedule/module.py | 154 |
1 files changed, 125 insertions, 29 deletions
diff --git a/src/pybind/mgr/snap_schedule/module.py b/src/pybind/mgr/snap_schedule/module.py index b691572b6..d8f04a62b 100644 --- a/src/pybind/mgr/snap_schedule/module.py +++ b/src/pybind/mgr/snap_schedule/module.py @@ -6,7 +6,7 @@ LGPL2.1. See file COPYING. import errno import json import sqlite3 -from typing import Any, Dict, Optional, Tuple +from typing import Any, Dict, Optional, Tuple, Union from .fs.schedule_client import SnapSchedClient from mgr_module import MgrModule, CLIReadCommand, CLIWriteCommand, Option from mgr_util import CephfsConnectionException @@ -37,6 +37,44 @@ class Module(MgrModule): self._initialized = Event() self.client = SnapSchedClient(self) + def _subvolume_exist(self, fs: str, subvol: Union[str, None], group: Union[str, None]) -> bool: + rc, subvolumes, err = self.remote('volumes', 'subvolume_ls', fs, group) + if rc == 0: + for svj in json.loads(subvolumes): + if subvol == svj['name']: + return True + + return False + + def _subvolume_flavor(self, fs: str, subvol: Union[str, None], group: Union[str, None]) -> str: + rc, subvol_info, err = self.remote('volumes', 'subvolume_info', fs, subvol, group) + svi_json = json.loads(subvol_info) + return svi_json.get('flavor', 'bad_flavor') # 1 or 2 etc. + + def _resolve_subvolume_path(self, fs: str, path: str, subvol: Union[str, None], group: Union[str, None]) -> Tuple[int, str, str]: + if subvol is None and group is None: + return 0, path, '' + + rc = -1 + subvol_path = '' + if self._subvolume_exist(fs, subvol, group): + rc, subvol_path, err = self.remote('volumes', 'subvolume_getpath', fs, subvol, group) + if rc != 0: + return rc, '', f'Could not resolve subvol:{subvol} path in fs:{fs}' + else: + subvol_flavor = self._subvolume_flavor(fs, subvol, group) + if subvol_flavor == 1: # v1 + return 0, subvol_path, f'Ignoring user specified path:{path} for subvol' + if subvol_flavor == 2: # v2 + err = ''; + if path != "/..": + err = f'Ignoring user specified path:{path} for subvol' + return 0, subvol_path + "/..", err + + return -errno.EINVAL, '', f'Unhandled subvol flavor:{subvol_flavor}' + else: + return -errno.EINVAL, '', f'No such subvol: {group}::{subvol}' + @property def _default_fs(self) -> Tuple[int, str, str]: fs_map = self.get('fs_map') @@ -53,11 +91,11 @@ class Module(MgrModule): rc, fs, err = self._default_fs if rc < 0: return rc, fs, err - if not self.has_fs(fs): + if not self._has_fs(fs): return -errno.EINVAL, '', f"no such file system: {fs}" return 0, fs, 'Success' - def has_fs(self, fs_name: str) -> bool: + def _has_fs(self, fs_name: str) -> bool: return fs_name in self.client.get_all_filesystems() def serve(self) -> None: @@ -71,6 +109,8 @@ class Module(MgrModule): def snap_schedule_get(self, path: str = '/', fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None, format: Optional[str] = 'plain') -> Tuple[int, str, str]: ''' List current snapshot schedules @@ -78,19 +118,28 @@ class Module(MgrModule): rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + errstr = 'Success' try: - ret_scheds = self.client.get_snap_schedules(fs, path) + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr + ret_scheds = self.client.get_snap_schedules(fs, abs_path) except CephfsConnectionException as e: return e.to_tuple() + except Exception as e: + return -errno.EIO, '', str(e) if format == 'json': json_report = ','.join([ret_sched.report_json() for ret_sched in ret_scheds]) return 0, f'[{json_report}]', '' + self.log.info(errstr) return 0, '\n===\n'.join([ret_sched.report() for ret_sched in ret_scheds]), '' @CLIReadCommand('fs snap-schedule list') def snap_schedule_list(self, path: str, recursive: bool = False, fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None, format: Optional[str] = 'plain') -> Tuple[int, str, str]: ''' Get current snapshot schedule for <path> @@ -98,11 +147,17 @@ class Module(MgrModule): rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - scheds = self.client.list_snap_schedules(fs, path, recursive) + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr + scheds = self.client.list_snap_schedules(fs, abs_path, recursive) self.log.debug(f'recursive is {recursive}') except CephfsConnectionException as e: return e.to_tuple() + except Exception as e: + return -errno.EIO, '', str(e) if not scheds: if format == 'json': output: Dict[str, str] = {} @@ -112,7 +167,7 @@ class Module(MgrModule): # json_list = ','.join([sched.json_list() for sched in scheds]) schedule_list = [sched.schedule for sched in scheds] retention_list = [sched.retention for sched in scheds] - out = {'path': path, 'schedule': schedule_list, 'retention': retention_list} + out = {'path': abs_path, 'schedule': schedule_list, 'retention': retention_list} return 0, json.dumps(out), '' return 0, '\n'.join([str(sched) for sched in scheds]), '' @@ -121,23 +176,27 @@ class Module(MgrModule): path: str, snap_schedule: str, start: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Set a snapshot schedule for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path - subvol = None + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.store_snap_schedule(fs, abs_path, (abs_path, snap_schedule, - fs, path, start, subvol)) - suc_msg = f'Schedule set for path {path}' + fs, abs_path, start, subvol, group)) + suc_msg = f'Schedule set for path {abs_path}' except sqlite3.IntegrityError: - existing_scheds = self.client.get_snap_schedules(fs, path) + existing_scheds = self.client.get_snap_schedules(fs, abs_path) report = [s.report() for s in existing_scheds] error_msg = f'Found existing schedule {report}' self.log.error(error_msg) @@ -146,6 +205,8 @@ class Module(MgrModule): return -errno.ENOENT, '', str(e) except CephfsConnectionException as e: return e.to_tuple() + except Exception as e: + return -errno.EIO, '', str(e) return 0, suc_msg, '' @CLIWriteCommand('fs snap-schedule remove') @@ -153,36 +214,48 @@ class Module(MgrModule): path: str, repeat: Optional[str] = None, start: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Remove a snapshot schedule for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.rm_snap_schedule(fs, abs_path, repeat, start) except ValueError as e: return -errno.ENOENT, '', str(e) except CephfsConnectionException as e: return e.to_tuple() - return 0, 'Schedule removed for path {}'.format(path), '' + except Exception as e: + return -errno.EIO, '', str(e) + return 0, 'Schedule removed for path {}'.format(abs_path), '' @CLIWriteCommand('fs snap-schedule retention add') def snap_schedule_retention_add(self, path: str, retention_spec_or_period: str, retention_count: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Set a retention specification for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.add_retention_spec(fs, abs_path, retention_spec_or_period, retention_count) @@ -190,69 +263,92 @@ class Module(MgrModule): return -errno.ENOENT, '', str(e) except CephfsConnectionException as e: return e.to_tuple() - return 0, 'Retention added to path {}'.format(path), '' + except Exception as e: + return -errno.EIO, '', str(e) + return 0, 'Retention added to path {}'.format(abs_path), '' @CLIWriteCommand('fs snap-schedule retention remove') def snap_schedule_retention_rm(self, path: str, retention_spec_or_period: str, retention_count: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Remove a retention specification for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.rm_retention_spec(fs, abs_path, retention_spec_or_period, retention_count) - except CephfsConnectionException as e: - return e.to_tuple() except ValueError as e: return -errno.ENOENT, '', str(e) - return 0, 'Retention removed from path {}'.format(path), '' + except CephfsConnectionException as e: + return e.to_tuple() + except Exception as e: + return -errno.EIO, '', str(e) + return 0, 'Retention removed from path {}'.format(abs_path), '' @CLIWriteCommand('fs snap-schedule activate') def snap_schedule_activate(self, path: str, repeat: Optional[str] = None, start: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Activate a snapshot schedule for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.activate_snap_schedule(fs, abs_path, repeat, start) except ValueError as e: return -errno.ENOENT, '', str(e) except CephfsConnectionException as e: return e.to_tuple() - return 0, 'Schedule activated for path {}'.format(path), '' + except Exception as e: + return -errno.EIO, '', str(e) + return 0, 'Schedule activated for path {}'.format(abs_path), '' @CLIWriteCommand('fs snap-schedule deactivate') def snap_schedule_deactivate(self, path: str, repeat: Optional[str] = None, start: Optional[str] = None, - fs: Optional[str] = None) -> Tuple[int, str, str]: + fs: Optional[str] = None, + subvol: Optional[str] = None, + group: Optional[str] = None) -> Tuple[int, str, str]: ''' Deactivate a snapshot schedule for <path> ''' rc, fs, err = self._validate_fs(fs) if rc < 0: return rc, fs, err + abs_path = "" try: - abs_path = path + rc, abs_path, errstr = self._resolve_subvolume_path(fs, path, subvol, group) + if rc != 0: + return rc, '', errstr self.client.deactivate_snap_schedule(fs, abs_path, repeat, start) except ValueError as e: return -errno.ENOENT, '', str(e) except CephfsConnectionException as e: return e.to_tuple() - return 0, 'Schedule deactivated for path {}'.format(path), '' + except Exception as e: + return -errno.EIO, '', str(e) + return 0, 'Schedule deactivated for path {}'.format(abs_path), '' |