import cephfs
from .metadata_manager import MetadataManager
-from .subvolume_base import SubvolumeBase
+from .subvolume_base import SubvolumeBase, SubvolumeFeatures
from ..op_sm import OpSm
from ..template import SubvolumeTemplate
from ..snapshot_util import mksnap, rmsnap
except MetadataMgrException as me:
raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
+ @property
+ def features(self):
+ return [SubvolumeFeatures.FEATURE_SNAPSHOT_CLONE.value, SubvolumeFeatures.FEATURE_SNAPSHOT_AUTOPROTECT.value]
+
def create(self, size, isolate_nspace, pool, mode, uid, gid):
subvolume_type = SubvolumeBase.SUBVOLUME_TYPE_NORMAL
try:
snappath = self.snapshot_path(snapname)
mksnap(self.fs, snappath)
- def is_snapshot_protected(self, snapname):
- try:
- self.metadata_mgr.get_option('protected snaps', snapname)
- except MetadataMgrException as me:
- if me.errno == -errno.ENOENT:
- return False
- else:
- log.warning("error checking protected snap {0} ({1})".format(snapname, me))
- raise VolumeException(-errno.EINVAL, "snapshot protection check failed")
- else:
- return True
-
def has_pending_clones(self, snapname):
try:
return self.metadata_mgr.section_has_item('clone snaps', snapname)
raise
def remove_snapshot(self, snapname):
- if self.is_snapshot_protected(snapname):
- raise VolumeException(-errno.EINVAL, "snapshot '{0}' is protected".format(snapname))
+ if self.has_pending_clones(snapname):
+ raise VolumeException(-errno.EAGAIN, "snapshot '{0}' has pending clones".format(snapname))
snappath = self.snapshot_path(snapname)
rmsnap(self.fs, snappath)
return {'size': int(snap_info['size']),
'created_at': str(datetime.fromtimestamp(float(snap_info['created_at']))),
'data_pool': snap_info['data_pool'].decode('utf-8'),
- 'protected': "yes" if self.is_snapshot_protected(snapname) else "no",
'has_pending_clones': "yes" if self.has_pending_clones(snapname) else "no"}
except cephfs.Error as e:
if e.errno == errno.ENOENT:
return []
raise
- def _protect_snapshot(self, snapname):
- try:
- self.metadata_mgr.add_section("protected snaps")
- self.metadata_mgr.update_section("protected snaps", snapname, "1")
- self.metadata_mgr.flush()
- except MetadataMgrException as me:
- log.warning("error updating protected snap list ({0})".format(me))
- raise VolumeException(-errno.EINVAL, "error protecting snapshot")
-
- def _unprotect_snapshot(self, snapname):
- try:
- self.metadata_mgr.remove_option("protected snaps", snapname)
- self.metadata_mgr.flush()
- except MetadataMgrException as me:
- log.warning("error updating protected snap list ({0})".format(me))
- raise VolumeException(-errno.EINVAL, "error unprotecting snapshot")
-
- def protect_snapshot(self, snapname):
- if not snapname.encode('utf-8') in self.list_snapshots():
- raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
- if self.is_snapshot_protected(snapname):
- raise VolumeException(-errno.EEXIST, "snapshot '{0}' is already protected".format(snapname))
- self._protect_snapshot(snapname)
-
- def unprotect_snapshot(self, snapname):
- if not snapname.encode('utf-8') in self.list_snapshots():
- raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
- if not self.is_snapshot_protected(snapname):
- raise VolumeException(-errno.EEXIST, "snapshot '{0}' is not protected".format(snapname))
- if self.has_pending_clones(snapname):
- raise VolumeException(-errno.EEXIST, "snapshot '{0}' has pending clones".format(snapname))
- self._unprotect_snapshot(snapname)
-
def _add_snap_clone(self, track_id, snapname):
self.metadata_mgr.add_section("clone snaps")
self.metadata_mgr.update_section("clone snaps", track_id, snapname)
def attach_snapshot(self, snapname, tgt_subvolume):
if not snapname.encode('utf-8') in self.list_snapshots():
raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
- if not self.is_snapshot_protected(snapname):
- raise VolumeException(-errno.EINVAL, "snapshot '{0}' is not protected".format(snapname))
try:
create_clone_index(self.fs, self.vol_spec)
with open_clone_index(self.fs, self.vol_spec) as index: