예제 #1
0
    def switch_over(self, replica_pair_id):
        pair_info = self._get_replication_pair_info(replica_pair_id)

        if strutils.bool_from_string(pair_info['ISPRIMARY']):
            LOG.warning('The replica to promote is already primary, '
                        'no need to switch over.')
            return

        replica_state = self._check_replica_state(pair_info)
        if replica_state != common_constants.REPLICA_STATE_IN_SYNC:
            # replica is not in SYNC state, can't be promoted
            msg = _('Data of replica %s is not sync, cannot promote.'
                    ) % replica_pair_id
            raise exception.ReplicationException(reason=msg)

        try:
            self.helper.split_replication_pair(replica_pair_id)
        except Exception as err:
            # split failed
            # means replication pair is in an abnormal status,
            # ignore this exception, continue to cancel secondary write lock,
            # let secondary share accessible for disaster recovery.
            LOG.exception(
                'Failed to split replication pair %(pair)s while '
                'switching over. Reason: %(err)s', {
                    "pair": replica_pair_id,
                    "err": err
                })

        try:
            self.helper.cancel_pair_secondary_write_lock(replica_pair_id)
        except Exception:
            LOG.exception(
                'Failed to cancel replication pair %s '
                'secondary write lock.', replica_pair_id)
            raise

        def _rollback_done():
            _pair_info = self._get_replication_pair_info(replica_pair_id)
            return _pair_info.get('ISROLLBACK', 'false') != 'true'

        huawei_utils.wait_for_condition(_rollback_done, 3, 3600 * 24)

        try:
            self.helper.switch_replication_pair(replica_pair_id)
            self.helper.set_pair_secondary_write_lock(replica_pair_id)
            self.helper.sync_replication_pair(replica_pair_id)
        except Exception as err:
            LOG.exception(
                'Failed to completely switch over replication pair'
                ' %(pair)s. Reason: %(err)s', {
                    "pair": replica_pair_id,
                    "err": err
                })

            # for all the rest steps,
            # because secondary share is accessible now,
            # the upper business may access the secondary share,
            # return success to tell replica is primary.
            return
예제 #2
0
    def create(self, local_share_info, remote_device_wwn, remote_fs_id):
        local_share_name = local_share_info.get('name')

        try:
            local_fs_id = self.helper.get_fsid_by_name(local_share_name)
            if not local_fs_id:
                msg = _("Local fs was not found by name %s.")
                LOG.error(msg, local_share_name)
                raise exception.ReplicationException(reason=msg %
                                                     local_share_name)

            remote_device = self.helper.get_remote_device_by_wwn(
                remote_device_wwn)
            pair_params = {
                "LOCALRESID": local_fs_id,
                "LOCALRESTYPE": constants.FILE_SYSTEM_TYPE,
                "REMOTEDEVICEID": remote_device.get('ID'),
                "REMOTEDEVICENAME": remote_device.get('NAME'),
                "REMOTERESID": remote_fs_id,
                "REPLICATIONMODEL": constants.REPLICA_ASYNC_MODEL,
                "RECOVERYPOLICY": '2',
                "SYNCHRONIZETYPE": '1',
                "SPEED": constants.REPLICA_SPEED_MEDIUM,
            }

            pair_info = self.helper.create_replication_pair(pair_params)
        except Exception:
            msg = _LE("Failed to create replication pair for share %s.")
            LOG.exception(msg, local_share_name)
            raise

        self._sync_replication_pair(pair_info['ID'])

        return pair_info['ID']
예제 #3
0
 def wait_for_quiesced():
     snapmirror = dest_client.get_snapmirrors_svm(
         source_vserver=source_vserver,
         dest_vserver=dest_vserver,
         desired_attributes=['relationship-status', 'mirror-state'])[0]
     if snapmirror.get('relationship-status') != 'quiesced':
         raise exception.ReplicationException(
             reason="Snapmirror relationship is not quiesced.")
예제 #4
0
    def create(self, local_share_info, remote_device_wwn, remote_fs_id,
               local_replication):
        local_share_name = local_share_info.get('name')

        try:
            local_fs_info = self.helper.get_fs_info_by_name(local_share_name)
            if not local_fs_info:
                msg = _("Local fs was not found by name %s." %
                        local_share_name)
                LOG.error(msg)
                raise exception.ReplicationException(reason=msg)
            local_fs_id = local_fs_info['ID']
            pair_params = {
                "LOCALRESID": local_fs_id,
                "LOCALRESTYPE": constants.FILE_SYSTEM_TYPE,
                "REMOTERESID": remote_fs_id,
                "REPLICATIONMODEL": constants.REPLICA_ASYNC_MODEL,
                "RECOVERYPOLICY": '2',
                "SYNCHRONIZETYPE": '1',
                "SPEED": constants.REPLICA_SPEED_HIGHEST,
            }

            if local_replication:
                pair_params["PAIRTYPE"] = constants.LOCAL_REPLICATION
            else:
                remote_device = self.helper.get_remote_device_by_wwn(
                    remote_device_wwn)
                pair_params["REMOTEDEVICEID"] = remote_device.get('ID')

            support_sync_snapshot = huawei_utils.is_dorado_v6(self.helper)
            if support_sync_snapshot:
                pair_params["syncSnapPolicy"] = "1"

            pair_info = self.helper.create_replication_pair(pair_params)
            local_pair_id = pair_info['ID']

            if local_replication:
                remote_fs = self.helper.get_fs_info_by_id(remote_fs_id)
                if not remote_fs:
                    msg = _('Remote filesystem %s is not exist.' %
                            remote_fs_id)
                    LOG.error(msg)
                    raise exception.StorageResourceNotFound(name=remote_fs_id)
                replication_ids = json.loads(remote_fs['REMOTEREPLICATIONIDS'])
                # Here must have a replication id.
                remote_pair_id = replication_ids[0]
            else:
                remote_pair_id = local_pair_id

        except Exception:
            LOG.exception("Failed to create replication pair for share %s.",
                          local_share_name)
            raise

        self._sync_replication_pair(local_pair_id, need_sync=False)

        return local_pair_id, remote_pair_id
예제 #5
0
 def wait_for_quiesced():
     snapmirror = dest_client.get_snapmirrors(
         src_vserver, src_volume_name, dest_vserver,
         dest_volume_name, desired_attributes=['relationship-status',
                                               'mirror-state']
     )[0]
     if snapmirror.get('relationship-status') != 'quiesced':
         raise exception.ReplicationException(
             reason=_LE("Snapmirror relationship is not quiesced."))
예제 #6
0
    def switch_over(self, replica_pair_id):
        pair_info = self._get_replication_pair_info(replica_pair_id)

        if strutils.bool_from_string(pair_info['ISPRIMARY']):
            LOG.warning(
                _LW('The replica to promote is already primary, '
                    'no need to switch over.'))
            return

        replica_state = self._check_replica_state(pair_info)
        if replica_state != common_constants.REPLICA_STATE_IN_SYNC:
            # replica is not in SYNC state, can't be promoted
            msg = _('Data of replica %s is not synchronized, '
                    'can not promote.')
            raise exception.ReplicationException(reason=msg % replica_pair_id)

        try:
            self.helper.split_replication_pair(replica_pair_id)
        except Exception:
            # split failed
            # means replication pair is in an abnormal status,
            # ignore this exception, continue to cancel secondary write lock,
            # let secondary share accessible for disaster recovery.
            LOG.exception(
                _LE('Failed to split replication pair %s while '
                    'switching over.'), replica_pair_id)

        try:
            self.helper.cancel_pair_secondary_write_lock(replica_pair_id)
        except Exception:
            LOG.exception(
                _LE('Failed to cancel replication pair %s '
                    'secondary write lock.'), replica_pair_id)
            raise

        try:
            self.helper.switch_replication_pair(replica_pair_id)
            self.helper.set_pair_secondary_write_lock(replica_pair_id)
            self.helper.sync_replication_pair(replica_pair_id)
        except Exception:
            LOG.exception(
                _LE('Failed to completely switch over '
                    'replication pair %s.'), replica_pair_id)

            # for all the rest steps,
            # because secondary share is accessible now,
            # the upper business may access the secondary share,
            # return success to tell replica is primary.
            return
예제 #7
0
    def create(self, local_share_info, remote_device_wwn, remote_fs_id,
               local_replication):
        local_share_name = local_share_info.get('name')

        try:
            local_fs_id = self.helper.get_fsid_by_name(local_share_name)
            if not local_fs_id:
                msg = _("Local fs was not found by name %s.")
                LOG.error(msg, local_share_name)
                raise exception.ReplicationException(
                    reason=msg % local_share_name)

            pair_params = {
                "LOCALRESID": local_fs_id,
                "LOCALRESTYPE": constants.FILE_SYSTEM_TYPE,
                "REMOTERESID": remote_fs_id,
                "REPLICATIONMODEL": constants.REPLICA_ASYNC_MODEL,
                "RECOVERYPOLICY": '2',
                "SYNCHRONIZETYPE": '1',
                "SPEED": constants.REPLICA_SPEED_MEDIUM,
            }

            if local_replication:
                pair_params["PAIRTYPE"] = constants.LOCAL_REPLICATION
            else:
                remote_device = self.helper.get_remote_device_by_wwn(
                    remote_device_wwn)
                pair_params["REMOTEDEVICEID"] = remote_device.get('ID')

            pair_info = self.helper.create_replication_pair(pair_params)
            local_pair_id = pair_info['ID']

            if local_replication:
                remote_fs = self.helper._get_fs_info_by_id(remote_fs_id)
                replication_ids = json.loads(remote_fs['REMOTEREPLICATIONIDS'])
                # Here must have a replication id.
                remote_pair_id = replication_ids[0]
            else:
                remote_pair_id = local_pair_id

        except Exception:
            LOG.exception("Failed to create replication pair for share %s.",
                          local_share_name)
            raise

        self._sync_replication_pair(local_pair_id)

        return local_pair_id, remote_pair_id
예제 #8
0
    def test_promote_replication_exception(self):
        body = {'promote': None}
        replica, expected_replica = self._get_fake_replica(
            replica_state=constants.REPLICA_STATE_IN_SYNC)
        exception_type = exception.ReplicationException(reason='xyz')
        self.mock_object(share_replicas.db, 'share_replica_get',
                         mock.Mock(return_value=replica))
        mock_api_promote_replica_call = self.mock_object(
            share.API, 'promote_share_replica',
            mock.Mock(side_effect=exception_type))

        self.assertRaises(exc.HTTPBadRequest, self.controller.promote,
                          self.replicas_req, replica['id'], body)
        self.assertTrue(mock_api_promote_replica_call.called)
        self.mock_policy_check.assert_called_once_with(self.member_context,
                                                       self.resource_name,
                                                       'promote')
예제 #9
0
    def test_delete_exception(self):
        fake_replica_1 = self._get_fake_replica(
            share_id='FAKE_SHARE_ID',
            replica_state=constants.REPLICA_STATE_ACTIVE)[0]
        fake_replica_2 = self._get_fake_replica(
            share_id='FAKE_SHARE_ID',
            replica_state=constants.REPLICA_STATE_ACTIVE)[0]
        exception_type = exception.ReplicationException(reason='xyz')
        self.mock_object(share_replicas.db, 'share_replica_get',
                         mock.Mock(return_value=fake_replica_1))
        self.mock_object(
            share_replicas.db, 'share_replicas_get_all_by_share',
            mock.Mock(return_value=[fake_replica_1, fake_replica_2]))
        self.mock_object(share.API, 'delete_share_replica',
                         mock.Mock(side_effect=exception_type))

        self.assertRaises(exc.HTTPBadRequest, self.controller.delete,
                          self.replicas_req, 'FAKE_REPLICA_ID')
        self.mock_policy_check.assert_called_once_with(
            self.member_context, self.resource_name, 'delete')
예제 #10
0
 def test_replication_exception(self):
     # Verify response code for exception.ReplicationException
     reason = "Something bad happened."
     e = exception.ReplicationException(reason=reason)
     self.assertEqual(500, e.code)
     self.assertIn(reason, e.msg)