def test_lookup_timeout(self, lookup_mock, sleep_mock):
     lookup_mock.side_effect = loopingcall.LoopingCallTimeOut()
     self.assertRaises(errors.LookupNodeError,
                       self.api_client.lookup_node,
                       hardware_info=self.hardware_info,
                       timeout=300,
                       starting_interval=1)
Esempio n. 2
0
 def _idle_for(result, elapsed):
     delay = round(elapsed - interval, 2)
     if delay > 0:
         func_name = reflection.get_callable_name(self.f)
         LOG.warning('Function %(func_name)r run outlasted '
                     'interval by %(delay).2f sec',
                     {'func_name': func_name,
                      'delay': delay})
     elapsed_time = time.time() - start_time
     if timeout > 0 and elapsed_time > timeout:
         raise loopingcall.LoopingCallTimeOut(
             _('Looping call timed out after %.02f seconds') %
             elapsed_time)
     return -delay if delay < 0 else 0
Esempio n. 3
0
class TestMigrateVolume(vxflexos.TestVxFlexOSDriver):
    """Test cases for ``VxFlexOSDriver.migrate_volume()``"""
    def setUp(self):
        """Setup a test case environment.

        Creates a fake volume object and sets up the required API responses.
        """

        super(TestMigrateVolume, self).setUp()
        ctx = context.RequestContext('fake', 'fake', auth_token=True)
        host = 'host@backend#{}:{}'.format(self.PROT_DOMAIN_NAME,
                                           self.STORAGE_POOL_NAME)
        self.volume = fake_volume.fake_volume_obj(
            ctx, **{
                'provider_id': fake.PROVIDER_ID,
                'host': host,
                'volume_type_id': fake.VOLUME_TYPE_ID
            })
        self.dst_host = {'host': host}
        self.DST_STORAGE_POOL_NAME = 'SP2'
        self.DST_STORAGE_POOL_ID = six.text_type('2')
        self.fake_vtree_id = 'c075744900000001'
        self.migration_success = (True, {})
        self.migration_host_assisted = (False, None)

        self.HTTPS_MOCK_RESPONSES = {
            self.RESPONSE_MODE.Valid: {
                'types/Domain/instances/getByName::{}'.format(self.PROT_DOMAIN_NAME):
                '"{}"'.format(self.PROT_DOMAIN_ID),
                'types/Pool/instances/getByName::{},{}'.format(
                    self.PROT_DOMAIN_ID, self.STORAGE_POOL_NAME):
                '"{}"'.format(self.STORAGE_POOL_ID),
                'types/Pool/instances/getByName::{},{}'.format(
                    self.PROT_DOMAIN_ID, self.DST_STORAGE_POOL_NAME):
                '"{}"'.format(self.DST_STORAGE_POOL_ID),
                'instances/ProtectionDomain::{}'.format(self.PROT_DOMAIN_ID): {
                    'id': self.PROT_DOMAIN_ID
                },
                'instances/StoragePool::{}'.format(self.STORAGE_POOL_ID): {
                    'id': self.STORAGE_POOL_ID,
                    'zeroPaddingEnabled': True
                },
                'instances/StoragePool::{}'.format(self.DST_STORAGE_POOL_ID): {
                    'id': self.DST_STORAGE_POOL_ID,
                    'zeroPaddingEnabled': True
                },
                'instances/Volume::{}'.format(self.volume.provider_id): {
                    'volumeType': 'ThinProvisioned',
                    'vtreeId': self.fake_vtree_id
                },
                'instances/Volume::{}/action/migrateVTree'.format(self.volume.provider_id):
                {},
                'instances/VTree::{}'.format(self.fake_vtree_id): {
                    'vtreeMigrationInfo': {
                        'migrationStatus': 'NotInMigration',
                        'migrationPauseReason': None
                    }
                }
            },
            self.RESPONSE_MODE.Invalid: {
                'instances/Volume::{}'.format(self.volume.provider_id): {
                    'vtreeId': self.fake_vtree_id
                },
                'instances/VTree::{}'.format(self.fake_vtree_id): {
                    'vtreeMigrationInfo': {
                        'migrationPauseReason': None
                    }
                }
            },
            self.RESPONSE_MODE.BadStatus: {
                'instances/Volume::{}/action/migrateVTree'.format(self.volume.provider_id):
                self.BAD_STATUS_RESPONSE
            },
        }

        self.volumetype_extraspecs_mock = self.mock_object(
            self.driver,
            '_get_volumetype_extraspecs',
            return_value={'provisioning:type': 'thin'})

        self.volume_is_replicated_mock = self.mock_object(self.volume,
                                                          'is_replicated',
                                                          return_value=False)

    def test_migrate_volume(self):
        ret = self.driver.migrate_volume(None, self.volume, self.dst_host)
        self.assertEqual(self.migration_success, ret)

    def test_migrate_replicated_volume(self):
        self.volume_is_replicated_mock.return_value = True
        self.assertRaises(exception.InvalidVolume, self.driver.migrate_volume,
                          None, self.volume, self.dst_host)

    def test_migrate_volume_crossbackend_not_supported(self):
        dst_host = {'host': 'host@another_backend#PD1:P1'}
        ret = self.driver.migrate_volume(None, self.volume, dst_host)
        self.assertEqual(self.migration_host_assisted, ret)

    def test_migrate_volume_bad_status_response(self):
        with self.custom_response_mode(
                **
            {
                'instances/Volume::{}/action/migrateVTree'.format(self.volume.provider_id):
                self.RESPONSE_MODE.BadStatus
            }):
            self.assertRaises(exception.VolumeBackendAPIException,
                              self.driver.migrate_volume, None, self.volume,
                              self.dst_host)

    def test_migrate_volume_migration_in_progress(self):
        with self.custom_response_mode(
                **
            {
                'instances/Volume::{}/action/migrateVTree'.format(self.volume.provider_id):
                vxflexos.mocks.MockHTTPSResponse(
                    {
                        'errorCode': 717,
                        'message': 'Migration in progress',
                    }, 500)
            }):
            ret = self.driver.migrate_volume(None, self.volume, self.dst_host)
            self.assertEqual(self.migration_success, ret)

    @mock.patch(
        'cinder.volume.drivers.dell_emc.vxflexos.driver.VxFlexOSDriver.'
        '_wait_for_volume_migration_to_complete',
        side_effect=loopingcall.LoopingCallTimeOut())
    def test_migrate_volume_migration_in_progress_timeout_expired(self, m):
        _, upd = self.driver.migrate_volume(None, self.volume, self.dst_host)
        self.assertEqual('maintenance', upd['status'])

    def test_migrate_volume_migration_failed(self):
        with self.custom_response_mode(
                **{
                    'instances/VTree::{}'.format(self.fake_vtree_id):
                    vxflexos.mocks.MockHTTPSResponse(
                        {
                            'vtreeMigrationInfo': {
                                'migrationStatus': 'NotInMigration',
                                'migrationPauseReason': 'MigrationError'
                            }
                        }, 200)
                }):
            self.assertRaises(exception.VolumeMigrationFailed,
                              self.driver.migrate_volume, None, self.volume,
                              self.dst_host)

    def test_get_real_provisioning_and_vtree_malformed_response(self):
        self.set_https_response_mode(self.RESPONSE_MODE.Invalid)
        self.assertRaises(exception.MalformedResponse,
                          self.driver._get_real_provisioning_and_vtree,
                          self.volume.provider_id)

    def test_wait_for_volume_migration_to_complete_malformed_response(self):
        self.set_https_response_mode(self.RESPONSE_MODE.Invalid)
        self.assertRaises(exception.MalformedResponse,
                          self.driver._wait_for_volume_migration_to_complete,
                          self.fake_vtree_id, self.volume.provider_id)

    @ddt.data(*MIGRATE_VOLUME_PARAMS_CASES)
    def test_get_migrate_volume_params(self, data):
        (vol_type, real_prov, conversion, compression, sup_thick) = data
        self.mock_object(self.driver,
                         '_get_provisioning_and_compression',
                         return_value=(vol_type, compression))
        self.mock_object(self.driver,
                         '_check_pool_support_thick_vols',
                         return_value=sup_thick)
        domain_name, pool_name = (
            self.driver._extract_domain_and_pool_from_host(
                self.dst_host['host']))
        ret = self.driver._get_volume_migration_params(self.volume,
                                                       domain_name, pool_name,
                                                       real_prov)
        self.assertTrue(ret['volTypeConversion'] == conversion)
        self.assertTrue(ret['compressionMethod'] == compression)