next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
SubvolumeStates.STATE_PENDING,
SubvolumeActions.ACTION_CANCELLED)
+ update_clone_failure_status(fs_client, volspec, volname, groupname, subvolname,
+ VolumeException(-errno.EINTR, "user interrupted clone operation"))
else:
next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
SubvolumeStates.STATE_PENDING,
raise VolumeException(-e.args[0], e.args[1])
cptree(source_path, dst_path)
if should_cancel():
- raise VolumeException(-errno.EINTR, "clone operation interrupted")
+ raise VolumeException(-errno.EINTR, "user interrupted clone operation")
def set_quota_on_clone(fs_handle, clone_volumes_pair):
src_path = clone_volumes_pair[1].snapshot_data_path(clone_volumes_pair[2])
bulk_copy(fs_handle, src_path, dst_path, should_cancel)
set_quota_on_clone(fs_handle, clone_volumes)
+def update_clone_failure_status(fs_client, volspec, volname, groupname, subvolname, ve):
+ with open_volume_lockless(fs_client, volname) as fs_handle:
+ with open_clone_subvolume_pair(fs_client, fs_handle, volspec, volname, groupname, subvolname) as clone_volumes:
+ if ve.errno == -errno.EINTR:
+ clone_volumes[0].add_clone_failure(-ve.errno, "user interrupted clone operation")
+ else:
+ clone_volumes[0].add_clone_failure(-ve.errno, ve.error_str)
+
def log_clone_failure(volname, groupname, subvolname, ve):
if ve.errno == -errno.EINTR:
log.info("Clone cancelled: ({0}, {1}, {2})".format(volname, groupname, subvolname))
SubvolumeStates.STATE_INPROGRESS,
SubvolumeActions.ACTION_SUCCESS)
except VolumeException as ve:
+ update_clone_failure_status(fs_client, volspec, volname, groupname, subvolname, ve)
log_clone_failure(volname, groupname, subvolname, ve)
next_state = get_next_state_on_error(ve.errno)
except OpSmException as oe:
clone_state,
SubvolumeActions.ACTION_CANCELLED)
clone_subvolume.state = (next_state, True)
+ clone_subvolume.add_clone_failure(errno.EINTR, "user interrupted clone operation")
s_subvolume.detach_snapshot(s_snapname, track_idx.decode('utf-8'))
def cancel_job(self, volname, job):
if flush:
self.metadata_mgr.flush()
+ def add_clone_failure(self, errno, error_msg):
+ self.metadata_mgr.add_section(MetadataManager.CLONE_FAILURE_SECTION)
+ self.metadata_mgr.update_section(MetadataManager.CLONE_FAILURE_SECTION,
+ MetadataManager.CLONE_FAILURE_META_KEY_ERRNO, errno)
+ self.metadata_mgr.update_section(MetadataManager.CLONE_FAILURE_SECTION,
+ MetadataManager.CLONE_FAILURE_META_KEY_ERROR_MSG, error_msg)
+ self.metadata_mgr.flush()
+
def create_clone(self, pool, source_volname, source_subvolume, snapname):
subvolume_type = SubvolumeTypes.TYPE_CLONE
try:
raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
return clone_source
+ def _get_clone_failure(self):
+ clone_failure = {
+ 'errno' : self.metadata_mgr.get_option(MetadataManager.CLONE_FAILURE_SECTION, MetadataManager.CLONE_FAILURE_META_KEY_ERRNO),
+ 'error_msg' : self.metadata_mgr.get_option(MetadataManager.CLONE_FAILURE_SECTION, MetadataManager.CLONE_FAILURE_META_KEY_ERROR_MSG),
+ }
+ return clone_failure
+
@property
def status(self):
state = SubvolumeStates.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE))
}
if not SubvolumeOpSm.is_complete_state(state) and subvolume_type == SubvolumeTypes.TYPE_CLONE:
subvolume_status["source"] = self._get_clone_source()
+ if SubvolumeOpSm.is_failed_state(state) and subvolume_type == SubvolumeTypes.TYPE_CLONE:
+ try:
+ subvolume_status["failure"] = self._get_clone_failure()
+ except MetadataMgrException:
+ pass
+
return subvolume_status
@property