def _get_access_entries_according_to_mapping(self, access_mapping): access_list = [] for access_type, protocols in access_mapping.items(): if access_type.lower() == 'cert': access_to = CONF.data_node_access_cert elif access_type.lower() == 'ip': access_to = CONF.data_node_access_ip elif access_type.lower() == 'user': access_to = CONF.data_node_access_admin_user else: msg = _("Unsupported access type provided: %s.") % access_type raise exception.ShareDataCopyFailed(reason=msg) if not access_to: msg = _("Configuration for Data node mounting access type %s " "has not been set.") % access_type raise exception.ShareDataCopyFailed(reason=msg) access = { 'access_type': access_type, 'access_level': constants.ACCESS_LEVEL_RW, 'access_to': access_to, } access_list.append(access) return access_list
def _validate_item(src_item, dest_item): src_sum, err = utils.execute( "sha256sum", "%s" % src_item, run_as_root=True) dest_sum, err = utils.execute( "sha256sum", "%s" % dest_item, run_as_root=True) if src_sum.split()[0] != dest_sum.split()[0]: msg = _("Data corrupted while copying. Aborting data copy.") raise exception.ShareDataCopyFailed(reason=msg)
def test_copy_data(self): values = [("folder1/\nitem/\nfile1\nitem", ""), "", ("", ""), ("10000", ""), "", ""] def get_output(*args, **kwargs): return values.pop(0) # mocks self.mock_object( data_utils, '_validate_item', mock.Mock(side_effect=[ exception.ShareDataCopyFailed(reason='fake'), None ])) self.mock_object(utils, 'execute', mock.Mock(side_effect=get_output)) self.mock_object(self._copy, 'get_progress') # run self._copy.copy_data(self._copy.src) # asserts self._copy.get_progress.assert_called_once_with() utils.execute.assert_has_calls([ mock.call("ls", "-pA1", "--group-directories-first", self._copy.src, run_as_root=True), mock.call("mkdir", "-p", os.path.join(self._copy.dest, "folder1/"), run_as_root=True), mock.call("ls", "-pA1", "--group-directories-first", os.path.join(self._copy.src, "folder1/"), run_as_root=True), mock.call("stat", "-c", "%s", os.path.join(self._copy.src, "file1"), run_as_root=True), mock.call("cp", "-P", "--preserve=all", os.path.join(self._copy.src, "file1"), os.path.join(self._copy.dest, "file1"), run_as_root=True), mock.call("cp", "-P", "--preserve=all", os.path.join(self._copy.src, "file1"), os.path.join(self._copy.dest, "file1"), run_as_root=True) ])
def migration_start(self, context, ignore_list, share_id, share_instance_id, dest_share_instance_id, connection_info_src, connection_info_dest): LOG.debug( "Received request to migrate share content from share instance " "%(instance_id)s to instance %(dest_instance_id)s.", { 'instance_id': share_instance_id, 'dest_instance_id': dest_share_instance_id }) share_ref = self.db.share_get(context, share_id) share_instance_ref = self.db.share_instance_get(context, share_instance_id, with_share_data=True) share_rpcapi = share_rpc.ShareAPI() mount_path = CONF.mount_tmp_location try: copy = data_utils.Copy( os.path.join(mount_path, share_instance_id), os.path.join(mount_path, dest_share_instance_id), ignore_list, CONF.check_hash) self._copy_share_data(context, copy, share_ref, share_instance_id, dest_share_instance_id, connection_info_src, connection_info_dest) except exception.ShareDataCopyCancelled: share_rpcapi.migration_complete(context, share_instance_ref, dest_share_instance_id) return except Exception: self.db.share_update( context, share_id, {'task_state': constants.TASK_STATE_DATA_COPYING_ERROR}) msg = _("Failed to copy contents from instance %(src)s to " "instance %(dest)s.") % { 'src': share_instance_id, 'dest': dest_share_instance_id } LOG.exception(msg) share_rpcapi.migration_complete(context, share_instance_ref, dest_share_instance_id) raise exception.ShareDataCopyFailed(reason=msg) finally: self.busy_tasks_shares.pop(share_id, None) LOG.info( "Completed copy operation of migrating share content from share " "instance %(instance_id)s to instance %(dest_instance_id)s.", { 'instance_id': share_instance_id, 'dest_instance_id': dest_share_instance_id })
def allow_access_to_data_service(self, share, share_instance_id, dest_share_instance_id): if share['share_proto'].upper() == 'GLUSTERFS': access_to = CONF.data_node_access_cert access_type = 'cert' if not access_to: msg = _("Data Node Certificate not specified. Cannot mount " "instances for data copy of share %(share_id)s. " "Aborting.") % { 'share_id': share['id'] } raise exception.ShareDataCopyFailed(reason=msg) else: access_to = CONF.data_node_access_ip access_type = 'ip' if not access_to: msg = _("Data Node Admin Network IP not specified. Cannot " "mount instances for data copy of share %(share_id)s. " "Aborting.") % { 'share_id': share['id'] } raise exception.ShareDataCopyFailed(reason=msg) access = { 'access_type': access_type, 'access_level': constants.ACCESS_LEVEL_RW, 'access_to': access_to } access_ref = self._allow_data_access(access, share_instance_id, dest_share_instance_id) return access_ref
def _get_access_entries_according_to_mapping(self, access_mapping): access_list = [] # NOTE(ganso): protocol is not relevant here because we previously # used it to filter the access types we are interested in for access_type, protocols in access_mapping.items(): access_to_list = [] if access_type.lower() == 'cert' and CONF.data_node_access_cert: access_to_list.append(CONF.data_node_access_cert) elif access_type.lower() == 'ip': ips = CONF.data_node_access_ips if ips: if not isinstance(ips, list): ips = [ips] access_to_list.extend(ips) elif (access_type.lower() == 'user' and CONF.data_node_access_admin_user): access_to_list.append(CONF.data_node_access_admin_user) else: msg = _("Unsupported access type provided: %s.") % access_type raise exception.ShareDataCopyFailed(reason=msg) if not access_to_list: msg = _("Configuration for Data node mounting access type %s " "has not been set.") % access_type raise exception.ShareDataCopyFailed(reason=msg) for access_to in access_to_list: access = { 'access_type': access_type, 'access_level': constants.ACCESS_LEVEL_RW, 'access_to': access_to, } access_list.append(access) return access_list
def test__copy_share_data_exception_access(self): connection_info_src = { 'mount': 'mount_cmd_src', 'unmount': 'unmount_cmd_src' } connection_info_dest = { 'mount': 'mount_cmd_src', 'unmount': 'unmount_cmd_src' } fake_copy = mock.MagicMock(cancelled=False) # mocks self.mock_object(db, 'share_update') self.mock_object( db, 'share_instance_get', mock.Mock( side_effect=[self.share['instance'], self.share['instance']])) self.mock_object( helper.DataServiceHelper, 'allow_access_to_data_service', mock.Mock(side_effect=exception.ShareDataCopyFailed( reason='fake'))) self.mock_object(helper.DataServiceHelper, 'cleanup_data_access') # run self.assertRaises(exception.ShareDataCopyFailed, self.manager._copy_share_data, self.context, fake_copy, self.share, 'ins1_id', 'ins2_id', connection_info_src, connection_info_dest) # asserts db.share_update.assert_called_once_with( self.context, self.share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING}) (helper.DataServiceHelper.allow_access_to_data_service. assert_called_once_with(self.share['instance'], connection_info_src, self.share['instance'], connection_info_dest))
def _copy_share_data(self, context, copy, src_share, share_instance_id, dest_share_instance_id, connection_info_src, connection_info_dest): copied = False mount_path = CONF.mount_tmp_location share_instance = self.db.share_instance_get(context, share_instance_id, with_share_data=True) dest_share_instance = self.db.share_instance_get( context, dest_share_instance_id, with_share_data=True) self.db.share_update( context, src_share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING}) helper_src = helper.DataServiceHelper(context, self.db, src_share) helper_dest = helper_src access_ref_list_src = helper_src.allow_access_to_data_service( share_instance, connection_info_src, dest_share_instance, connection_info_dest) access_ref_list_dest = access_ref_list_src def _call_cleanups(items): for item in items: if 'unmount_src' == item: helper_src.cleanup_unmount_temp_folder( connection_info_src['unmount'], mount_path, share_instance_id) elif 'temp_folder_src' == item: helper_src.cleanup_temp_folder(share_instance_id, mount_path) elif 'temp_folder_dest' == item: helper_dest.cleanup_temp_folder(dest_share_instance_id, mount_path) elif 'access_src' == item: helper_src.cleanup_data_access(access_ref_list_src, share_instance_id) elif 'access_dest' == item: helper_dest.cleanup_data_access(access_ref_list_dest, dest_share_instance_id) try: helper_src.mount_share_instance(connection_info_src['mount'], mount_path, share_instance) except Exception: msg = _("Data copy failed attempting to mount " "share instance %s.") % share_instance_id LOG.exception(msg) _call_cleanups(['temp_folder_src', 'access_dest', 'access_src']) raise exception.ShareDataCopyFailed(reason=msg) try: helper_dest.mount_share_instance(connection_info_dest['mount'], mount_path, dest_share_instance) except Exception: msg = _("Data copy failed attempting to mount " "share instance %s.") % dest_share_instance_id LOG.exception(msg) _call_cleanups([ 'temp_folder_dest', 'unmount_src', 'temp_folder_src', 'access_dest', 'access_src' ]) raise exception.ShareDataCopyFailed(reason=msg) self.busy_tasks_shares[src_share['id']] = copy self.db.share_update( context, src_share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_IN_PROGRESS}) try: copy.run() self.db.share_update( context, src_share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_COMPLETING}) if copy.get_progress()['total_progress'] == 100: copied = True except Exception: LOG.exception( "Failed to copy data from share instance " "%(share_instance_id)s to " "%(dest_share_instance_id)s.", { 'share_instance_id': share_instance_id, 'dest_share_instance_id': dest_share_instance_id }) try: helper_src.unmount_share_instance(connection_info_src['unmount'], mount_path, share_instance_id) except Exception: LOG.exception( "Could not unmount folder of instance" " %s after its data copy.", share_instance_id) try: helper_dest.unmount_share_instance(connection_info_dest['unmount'], mount_path, dest_share_instance_id) except Exception: LOG.exception( "Could not unmount folder of instance" " %s after its data copy.", dest_share_instance_id) try: helper_src.deny_access_to_data_service(access_ref_list_src, share_instance) except Exception: LOG.exception( "Could not deny access to instance" " %s after its data copy.", share_instance_id) try: helper_dest.deny_access_to_data_service(access_ref_list_dest, dest_share_instance) except Exception: LOG.exception( "Could not deny access to instance" " %s after its data copy.", dest_share_instance_id) if copy and copy.cancelled: self.db.share_update( context, src_share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_CANCELLED}) LOG.warning( "Copy of data from share instance " "%(src_instance)s to share instance " "%(dest_instance)s was cancelled.", { 'src_instance': share_instance_id, 'dest_instance': dest_share_instance_id }) raise exception.ShareDataCopyCancelled( src_instance=share_instance_id, dest_instance=dest_share_instance_id) elif not copied: msg = _("Copying data from share instance %(instance_id)s " "to %(dest_instance_id)s did not succeed.") % ( { 'instance_id': share_instance_id, 'dest_instance_id': dest_share_instance_id }) raise exception.ShareDataCopyFailed(reason=msg) self.db.share_update( context, src_share['id'], {'task_state': constants.TASK_STATE_DATA_COPYING_COMPLETED}) LOG.debug( "Copy of data from share instance %(src_instance)s to " "share instance %(dest_instance)s was successful.", { 'src_instance': share_instance_id, 'dest_instance': dest_share_instance_id })