コード例 #1
0
ファイル: test_replication.py プロジェクト: j-griffith/cinder
    def test_instorage_retype_from_mirror_to_none_replication(self):
        # Set replication target
        self.driver.configuration.set_override('replication_device',
                                               [self.rep_target])
        self.driver.do_setup(self.ctxt)
        host = {'host': 'openstack@mcs#openstack'}

        volume, model_update = self._create_test_volume(self.mm_type)
        self.assertEqual('enabled', model_update['replication_status'])

        diff, _equal = volume_types.volume_types_diff(
            self.ctxt, self.mm_type['id'], self.gm_type['id'])
        # Change the mirror type
        self.assertRaises(exception.VolumeDriverException,
                          self.driver.retype, self.ctxt,
                          volume, self.gm_type, diff, host)

        diff, _equal = volume_types.volume_types_diff(
            self.ctxt, self.non_replica_type['id'], self.mm_type['id'])
        # Disable replica
        retyped, model_update = self.driver.retype(
            self.ctxt, volume, self.non_replica_type, diff, host)
        self.assertEqual('disabled', model_update['replication_status'])
        self._assert_vol_exists(
            instorage_const.REPLICA_AUX_VOL_PREFIX + volume['name'], False)

        self.driver.delete_volume(volume)
        self._assert_vol_exists(volume['name'], False)
        rel_info = self.driver._assistant.get_relationship_info(volume['name'])
        self.assertIsNone(rel_info)
コード例 #2
0
    def test_retype(self):
        """Test that retype returns successfully."""

        self.driver.do_setup(None)

        # prepare parameters
        ctxt = context.get_admin_context()

        host = {"host": "foo", "capabilities": {"location_info": "xiv_ds8k_fake_1", "extent_size": "1024"}}

        key_specs_old = {"easytier": False, "warning": 2, "autoexpand": True}
        key_specs_new = {"easytier": True, "warning": 5, "autoexpand": False}
        old_type_ref = volume_types.create(ctxt, "old", key_specs_old)
        new_type_ref = volume_types.create(ctxt, "new", key_specs_new)

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref["id"], new_type_ref["id"])

        volume = copy.deepcopy(VOLUME)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref["id"])
        volume["volume_type"] = old_type
        volume["host"] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref["id"])

        self.driver.create_volume(volume)
        ret = self.driver.retype(ctxt, volume, new_type, diff, host)
        self.assertTrue(ret)
        self.assertTrue(volume["easytier"])
コード例 #3
0
ファイル: test_hplefthand.py プロジェクト: mshabdiz/cinder
    def test_retype_same_extra_specs(self):
        # setup drive with default configuration
        # and return the mock HTTP LeftHand client
        mock_client = self.setup_driver()
        mock_client.getVolumeByName.return_value = {'id': self.volume_id}

        ctxt = context.get_admin_context()

        host = {'host': self.serverName}
        key_specs_old = {'hplh:provisioning': 'full', 'hplh:ao': 'true'}
        key_specs_new = {'hplh:provisioning': 'full', 'hplh:ao': 'false'}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref['id'],
                                                     new_type_ref['id'])

        volume = dict.copy(self.volume)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        volume['volume_type'] = old_type
        volume['host'] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        self.driver.retype(ctxt, volume, new_type, diff, host)

        expected = self.driver_startup_call_stack + [
            mock.call.getVolumeByName('fakevolume'),
            mock.call.modifyVolume(
                1,
                {'isAdaptiveOptimizationEnabled': False})]

        # validate call chain
        mock_client.assert_has_calls(expected)
コード例 #4
0
ファイル: test_gpfs.py プロジェクト: corystone/cinder
    def test_retype_volume_different_backend(self):
        ctxt = self.context
        loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id
        cap = {'location_info': loc}
        host = {'host': 'foo', 'capabilities': cap}

        key_specs_old = {'capabilities:storage_pool': 'bronze',
                         'volume_backend_name': 'backend1'}
        key_specs_new = {'capabilities:storage_pool': 'gold',
                         'volume_backend_name': 'backend2'}

        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        diff, equal = volume_types.volume_types_diff(ctxt,
                                                     old_type_ref['id'],
                                                     new_type_ref['id'])
        # set volume host to match target host
        volume = test_utils.create_volume(ctxt, host=host['host'])
        volume['volume_type_id'] = old_type['id']

        with mock.patch('cinder.utils.execute'):
            LOG.debug('Retype different backends, cannot migrate. '
                      'Expected rv = False.')
            self.driver.create_volume(volume)
            rv = self.driver.retype(ctxt, volume, old_type, diff, host)
            self.assertFalse(rv)
            self.driver.delete_volume(volume)
            LOG.debug('Retype different backends, cannot migrate, '
                      'rv = %s.' % rv)
コード例 #5
0
ファイル: test_hplefthand.py プロジェクト: mshabdiz/cinder
    def test_retype_with_no_LH_extra_specs(self):
        # setup drive with default configuration
        # and return the mock HTTP LeftHand client
        mock_client = self.setup_driver()

        ctxt = context.get_admin_context()

        host = {'host': self.serverName}
        key_specs_old = {'foo': False, 'bar': 2, 'error': True}
        key_specs_new = {'foo': True, 'bar': 5, 'error': False}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref['id'],
                                                     new_type_ref['id'])

        volume = dict.copy(self.volume)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        volume['volume_type'] = old_type
        volume['host'] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        self.driver.retype(ctxt, volume, new_type, diff, host)

        expected = self.driver_startup_call_stack + [
            mock.call.getVolumeByName('fakevolume')]

        # validate call chain
        mock_client.assert_has_calls(expected)
コード例 #6
0
ファイル: test_gpfs.py プロジェクト: corystone/cinder
    def test_retype_volume_different_pool_and_host(self):
        ctxt = self.context
        loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id
        cap = {'location_info': loc}
        host = {'host': 'foo', 'capabilities': cap}

        key_specs_old = {'capabilities:storage_pool': 'bronze',
                         'volume_backend_name': 'backend1'}
        key_specs_new = {'capabilities:storage_pool': 'gold',
                         'volume_backend_name': 'backend1'}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        diff, equal = volume_types.volume_types_diff(ctxt,
                                                     old_type_ref['id'],
                                                     new_type_ref['id'])

        # set volume host to be different from target host
        volume = test_utils.create_volume(ctxt, host=CONF.host)
        volume['volume_type_id'] = old_type['id']

        with mock.patch('cinder.utils.execute'):
            # different host different pool
            LOG.debug('Retype different pools and hosts, expected rv = True.')
            self.driver.db = mock.Mock()
            self.driver.create_volume(volume)
            rv = self.driver.retype(ctxt, volume, new_type, diff, host)
            self.assertTrue(rv)
            self.driver.delete_volume(volume)
            LOG.debug('Retype different pools and hosts, rv = %s.' % rv)
コード例 #7
0
ファイル: test_replication.py プロジェクト: j-griffith/cinder
    def test_instorage_retype_from_none_to_mirror_replication(self):
        # Set replication target
        self.driver.configuration.set_override('replication_device',
                                               [self.rep_target])
        self.driver.do_setup(self.ctxt)
        host = {'host': 'openstack@mcs#openstack'}

        diff, _equal = volume_types.volume_types_diff(
            self.ctxt, self.non_replica_type['id'], self.mm_type['id'])

        volume, model_update = self._create_test_volume(self.non_replica_type)
        self.assertIsNone(model_update)

        # Enable replica
        retyped, model_update = self.driver.retype(
            self.ctxt, volume, self.mm_type, diff, host)
        volume['volume_type_id'] = self.mm_type['id']
        self.assertEqual(fields.ReplicationStatus.ENABLED,
                         model_update['replication_status'])
        self._validate_replic_vol_creation(volume)

        self.driver.delete_volume(volume)
コード例 #8
0
ファイル: test_ibm_xiv_ds8k.py プロジェクト: 10171121/cinder
    def test_retype_fail_on_exception(self):
        """Test that retype fails on exception."""

        self.driver.do_setup(None)

        # prepare parameters
        ctxt = context.get_admin_context()

        host = {
            'host': 'foo',
            'capabilities': {
                'location_info': 'xiv_ds8k_fake_1',
                'extent_size': '1024'
            }
        }

        key_specs_old = {'easytier': False, 'warning': 2, 'autoexpand': True}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new')

        diff, equal = volume_types.volume_types_diff(
            ctxt,
            old_type_ref['id'],
            new_type_ref['id'],
        )

        volume = copy.deepcopy(VOLUME)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        volume['volume_type'] = old_type
        volume['host'] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        self.driver.create_volume(volume)
        self.assertRaises(
            KeyError,
            self.driver.retype,
            ctxt, volume, new_type, diff, host
        )
コード例 #9
0
    def test_retype(self):
        """Test that retype returns successfully."""

        self.driver.do_setup(None)

        # prepare parameters
        ctxt = context.get_admin_context()

        host = {
            'host': 'foo',
            'capabilities': {
                'location_info': 'ibm_storage_fake_1',
                'extent_size': '1024'
            }
        }

        key_specs_old = {'easytier': False, 'warning': 2, 'autoexpand': True}
        key_specs_new = {'easytier': True, 'warning': 5, 'autoexpand': False}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        diff, equal = volume_types.volume_types_diff(
            ctxt,
            old_type_ref['id'],
            new_type_ref['id'],
        )

        volume = copy.deepcopy(VOLUME)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        volume['volume_type'] = old_type
        volume['host'] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        self.driver.create_volume(volume)
        ret = self.driver.retype(ctxt, volume, new_type, diff, host)
        self.assertTrue(ret)
        self.assertEqual('1', volume['easytier'])
コード例 #10
0
    def test_retype(self):
        """Test that retype returns successfully."""

        self.driver.do_setup(None)

        # prepare parameters
        ctxt = context.get_admin_context()

        host = {
            'host': 'foo',
            'capabilities': {
                'location_info': 'xiv_ds8k_fake_1',
                'extent_size': '1024'
            }
        }

        key_specs_old = {'easytier': False, 'warning': 2, 'autoexpand': True}
        key_specs_new = {'easytier': True, 'warning': 5, 'autoexpand': False}
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        diff, equal = volume_types.volume_types_diff(
            ctxt,
            old_type_ref['id'],
            new_type_ref['id'],
        )

        volume = copy.deepcopy(VOLUME)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        volume['volume_type'] = old_type
        volume['host'] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        self.driver.create_volume(volume)
        ret = self.driver.retype(ctxt, volume, new_type, diff, host)
        self.assertTrue(ret)
        self.assertTrue(volume['easytier'])
コード例 #11
0
    def test_retype_volume_different_pool_and_host(self):
        ctxt = self.context
        loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id
        cap = {'location_info': loc}
        host = {'host': 'foo', 'capabilities': cap}

        key_specs_old = {
            'capabilities:storage_pool': 'bronze',
            'volume_backend_name': 'backend1'
        }
        key_specs_new = {
            'capabilities:storage_pool': 'gold',
            'volume_backend_name': 'backend1'
        }
        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref['id'],
                                                     new_type_ref['id'])

        # set volume host to be different from target host
        volume = test_utils.create_volume(ctxt, host=CONF.host)
        volume['volume_type_id'] = old_type['id']

        with mock.patch('cinder.utils.execute'):
            # different host different pool
            LOG.debug('Retype different pools and hosts, expected rv = True.')
            self.driver.db = mock.Mock()
            self.driver.create_volume(volume)
            rv = self.driver.retype(ctxt, volume, new_type, diff, host)
            self.assertTrue(rv)
            self.driver.delete_volume(volume)
            LOG.debug('Retype different pools and hosts, rv = %s.' % rv)
コード例 #12
0
ファイル: test_ibm_storage.py プロジェクト: sebrandon1/cinder
    def test_retype_fail_on_exception(self):
        """Test that retype fails on exception."""

        self.driver.do_setup(None)

        # prepare parameters
        ctxt = context.get_admin_context()

        host = {"host": "foo", "capabilities": {"location_info": "ibm_storage_fake_1", "extent_size": "1024"}}

        key_specs_old = {"easytier": False, "warning": 2, "autoexpand": True}
        old_type_ref = volume_types.create(ctxt, "old", key_specs_old)
        new_type_ref = volume_types.create(ctxt, "new")

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref["id"], new_type_ref["id"])

        volume = copy.deepcopy(VOLUME)
        old_type = volume_types.get_volume_type(ctxt, old_type_ref["id"])
        volume["volume_type"] = old_type
        volume["host"] = host
        new_type = volume_types.get_volume_type(ctxt, new_type_ref["id"])

        self.driver.create_volume(volume)
        self.assertRaises(KeyError, self.driver.retype, ctxt, volume, new_type, diff, host)
コード例 #13
0
    def test_retype_volume_different_backend(self):
        ctxt = self.context
        loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id
        cap = {'location_info': loc}
        host = {'host': 'foo', 'capabilities': cap}

        key_specs_old = {
            'capabilities:storage_pool': 'bronze',
            'volume_backend_name': 'backend1'
        }
        key_specs_new = {
            'capabilities:storage_pool': 'gold',
            'volume_backend_name': 'backend2'
        }

        old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
        new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)

        old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
        new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])

        diff, equal = volume_types.volume_types_diff(ctxt, old_type_ref['id'],
                                                     new_type_ref['id'])
        # set volume host to match target host
        volume = test_utils.create_volume(ctxt, host=host['host'])
        volume['volume_type_id'] = old_type['id']

        with mock.patch('cinder.utils.execute'):
            LOG.debug('Retype different backends, cannot migrate. '
                      'Expected rv = False.')
            self.driver.create_volume(volume)
            rv = self.driver.retype(ctxt, volume, old_type, diff, host)
            self.assertFalse(rv)
            self.driver.delete_volume(volume)
            LOG.debug('Retype different backends, cannot migrate, '
                      'rv = %s.' % rv)
コード例 #14
0
    def test_volume_types_diff(self):
        # type_ref 1 and 2 have the same extra_specs, while 3 has different
        keyvals1 = {"key1": "val1", "key2": "val2"}
        keyvals2 = {"key1": "val0", "key2": "val2"}
        type_ref1 = volume_types.create(self.ctxt, "type1", keyvals1)
        type_ref2 = volume_types.create(self.ctxt, "type2", keyvals1)
        type_ref3 = volume_types.create(self.ctxt, "type3", keyvals2)

        # Check equality with only extra_specs
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertTrue(same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref3['id'])
        self.assertFalse(same)
        self.assertEqual(('val1', 'val0'), diff['extra_specs']['key1'])

        # qos_ref 1 and 2 have the same specs, while 3 has different
        qos_keyvals1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
        qos_keyvals2 = {'k1': 'v0', 'k2': 'v2', 'k3': 'v3'}
        qos_ref1 = qos_specs.create(self.ctxt, 'qos-specs-1', qos_keyvals1)
        qos_ref2 = qos_specs.create(self.ctxt, 'qos-specs-2', qos_keyvals1)
        qos_ref3 = qos_specs.create(self.ctxt, 'qos-specs-3', qos_keyvals2)

        # Check equality with qos specs too
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref1['id'],
                                          type_ref1['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2['id'],
                                          type_ref2['id'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertTrue(same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v1'), diff['qos_specs']['k1'])
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref2['id'],
                                         type_ref2['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref3['id'],
                                          type_ref2['id'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertFalse(same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v0'), diff['qos_specs']['k1'])
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref3['id'],
                                         type_ref2['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2['id'],
                                          type_ref2['id'])

        # And add encryption for good measure
        enc_keyvals1 = {'cipher': 'c1', 'key_size': 256, 'provider': 'p1',
                        'control_location': 'front-end',
                        'encryption_id': 'uuid1'}
        enc_keyvals2 = {'cipher': 'c1', 'key_size': 128, 'provider': 'p1',
                        'control_location': 'front-end',
                        'encryption_id': 'uuid2'}
        db.volume_type_encryption_create(self.ctxt, type_ref1['id'],
                                         enc_keyvals1)
        db.volume_type_encryption_create(self.ctxt, type_ref2['id'],
                                         enc_keyvals2)
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertFalse(same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v1'), diff['qos_specs']['k1'])
        self.assertEqual((256, 128), diff['encryption']['key_size'])

        # Check diff equals type specs when one type is None
        diff, same = volume_types.volume_types_diff(self.ctxt, None,
                                                    type_ref1['id'])
        self.assertFalse(same)
        self.assertEqual({'key1': (None, 'val1'), 'key2': (None, 'val2')},
                         diff['extra_specs'])
        self.assertEqual({'consumer': (None, 'back-end'),
                          'k1': (None, 'v1'),
                          'k2': (None, 'v2'),
                          'k3': (None, 'v3')}, diff['qos_specs'])
        self.assertEqual({'cipher': (None, 'c1'),
                          'control_location': (None, 'front-end'),
                          'deleted': (None, False),
                          'key_size': (None, 256),
                          'provider': (None, 'p1'),
                          'encryption_id': (None, 'uuid1')},
                         diff['encryption'])
コード例 #15
0
    def test_volume_types_diff(self):
        # type_ref 1 and 2 have the same extra_specs, while 3 has different
        keyvals1 = {"key1": "val1", "key2": "val2"}
        keyvals2 = {"key1": "val0", "key2": "val2"}
        type_ref1 = volume_types.create(self.ctxt, "type1", keyvals1)
        type_ref2 = volume_types.create(self.ctxt, "type2", keyvals1)
        type_ref3 = volume_types.create(self.ctxt, "type3", keyvals2)

        # Check equality with only extra_specs
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1["id"], type_ref2["id"])
        self.assertTrue(same)
        self.assertEqual(diff["extra_specs"]["key1"], ("val1", "val1"))
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1["id"], type_ref3["id"])
        self.assertFalse(same)
        self.assertEqual(diff["extra_specs"]["key1"], ("val1", "val0"))

        # qos_ref 1 and 2 have the same specs, while 3 has different
        qos_keyvals1 = {"k1": "v1", "k2": "v2", "k3": "v3"}
        qos_keyvals2 = {"k1": "v0", "k2": "v2", "k3": "v3"}
        qos_ref1 = qos_specs.create(self.ctxt, "qos-specs-1", qos_keyvals1)
        qos_ref2 = qos_specs.create(self.ctxt, "qos-specs-2", qos_keyvals1)
        qos_ref3 = qos_specs.create(self.ctxt, "qos-specs-3", qos_keyvals2)

        # Check equality with qos specs too
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref1["id"], type_ref1["id"])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2["id"], type_ref2["id"])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1["id"], type_ref2["id"])
        self.assertTrue(same)
        self.assertEqual(diff["extra_specs"]["key1"], ("val1", "val1"))
        self.assertEqual(diff["qos_specs"]["k1"], ("v1", "v1"))
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref2["id"], type_ref2["id"])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref3["id"], type_ref2["id"])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1["id"], type_ref2["id"])
        self.assertFalse(same)
        self.assertEqual(diff["extra_specs"]["key1"], ("val1", "val1"))
        self.assertEqual(diff["qos_specs"]["k1"], ("v1", "v0"))
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref3["id"], type_ref2["id"])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2["id"], type_ref2["id"])

        # And add encryption for good measure
        enc_keyvals1 = {
            "cipher": "c1",
            "key_size": 256,
            "provider": "p1",
            "control_location": "front-end",
            "encryption_id": "uuid1",
        }
        enc_keyvals2 = {
            "cipher": "c1",
            "key_size": 128,
            "provider": "p1",
            "control_location": "front-end",
            "encryption_id": "uuid2",
        }
        db.volume_type_encryption_create(self.ctxt, type_ref1["id"], enc_keyvals1)
        db.volume_type_encryption_create(self.ctxt, type_ref2["id"], enc_keyvals2)
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1["id"], type_ref2["id"])
        self.assertFalse(same)
        self.assertEqual(diff["extra_specs"]["key1"], ("val1", "val1"))
        self.assertEqual(diff["qos_specs"]["k1"], ("v1", "v1"))
        self.assertEqual(diff["encryption"]["key_size"], (256, 128))

        # Check diff equals type specs when one type is None
        diff, same = volume_types.volume_types_diff(self.ctxt, None, type_ref1["id"])
        self.assertFalse(same)
        self.assertEqual(diff["extra_specs"], {"key1": (None, "val1"), "key2": (None, "val2")})
        self.assertEqual(
            diff["qos_specs"],
            {"consumer": (None, "back-end"), "k1": (None, "v1"), "k2": (None, "v2"), "k3": (None, "v3")},
        )
        self.assertEqual(
            diff["encryption"],
            {
                "cipher": (None, "c1"),
                "control_location": (None, "front-end"),
                "deleted": (None, False),
                "key_size": (None, 256),
                "provider": (None, "p1"),
                "encryption_id": (None, "uuid1"),
            },
        )
コード例 #16
0
    def _clone_image_2_2(self, context, volume, image_location, image_meta,
                         image_service):
        # We're not going to fast image clone if the feature is not enabled
        # and/or we can't reach the image being requested
        if (not self.image_cache
                or not self._image_accessible(context, volume, image_meta)):
            return None, False
        # Check to make sure we're working with a valid volume type
        try:
            found = volume_types.get_volume_type(context, self.image_type)
        except (exception.VolumeTypeNotFound, exception.InvalidVolumeType):
            found = None
        if not found:
            msg = "Invalid volume type: %s"
            LOG.error(msg, self.image_type)
            raise ValueError(
                _("Option datera_image_cache_volume_type_id must"
                  " be set to a valid volume_type id"))
        # Check image format
        fmt = image_meta.get('disk_format', '')
        if fmt.lower() != 'raw':
            LOG.debug(
                "Image format is not RAW, image requires conversion "
                "before clone.  Image format: [%s]", fmt)
            return None, False

        LOG.debug("Starting fast image clone")
        # TODO(_alastor_): determine if Datera is already an image backend
        # for this request and direct clone instead of caching

        # Dummy volume, untracked by Cinder
        src_vol = {
            'id': image_meta['id'],
            'volume_type_id': self.image_type,
            'size': volume['size'],
            'project_id': volume['project_id']
        }

        # Determine if we have a cached version of the image
        cached = self._vol_exists_2_2(src_vol)

        if cached:
            tenant = self.get_tenant(src_vol['project_id'])
            ai = self.cvol_to_ai(src_vol, tenant=tenant)
            metadata = ai.metadata.get(tenant=tenant)
            # Check to see if the master image has changed since we created
            # The cached version
            ts = self._get_vol_timestamp_2_2(src_vol)
            mts = time.mktime(image_meta['updated_at'].timetuple())
            LOG.debug("Original image timestamp: %s, cache timestamp %s", mts,
                      ts)
            # If the image is created by Glance, we'll trust that even if the
            # timestamps don't match up, the data is ok to clone as it's not
            # managed by this driver
            if metadata.get('type') == 'image':
                LOG.debug("Found Glance volume-backed image for %s",
                          src_vol['id'])
            # If the master image time is greater than the volume creation
            # time, we invalidate the cache and delete the volume.  The
            # exception is if the cached volume was created by Glance.  We
            # NEVER want to delete this volume.  It's annotated with
            # 'type': 'image' in the metadata, so we'll check for that
            elif mts > ts and metadata.get('type') != 'image':
                LOG.debug("Cache is older than original image, deleting cache")
                cached = False
                self._delete_volume_2_2(src_vol)

        # If we don't have the image, we'll cache it
        if not cached:
            LOG.debug("No image cache found for: %s, caching image",
                      image_meta['id'])
            self._cache_vol_2_2(context, src_vol, image_meta, image_service)

        # Now perform the clone of the found image or newly cached image
        self._create_cloned_volume_2_2(volume, src_vol)
        # Force volume resize
        vol_size = volume['size']
        volume['size'] = 0
        self._extend_volume_2_2(volume, vol_size)
        volume['size'] = vol_size
        # Determine if we need to retype the newly created volume
        vtype_id = volume.get('volume_type_id')
        if vtype_id and self.image_type and vtype_id != self.image_type:
            vtype = volume_types.get_volume_type(context, vtype_id)
            LOG.debug("Retyping newly cloned volume from type: %s to type: %s",
                      self.image_type, vtype_id)
            diff, discard = volume_types.volume_types_diff(
                context, self.image_type, vtype_id)
            host = {'capabilities': {'vendor_name': self.backend_name}}
            self._retype_2_2(context, volume, vtype, diff, host)
        return None, True
コード例 #17
0
    def test_volume_types_diff(self):
        #type_ref 1 and 2 have the same extra_specs, while 3 has different
        keyvals1 = {"key1": "val1", "key2": "val2"}
        keyvals2 = {"key1": "val0", "key2": "val2"}
        type_ref1 = volume_types.create(self.ctxt, "type1", keyvals1)
        type_ref2 = volume_types.create(self.ctxt, "type2", keyvals1)
        type_ref3 = volume_types.create(self.ctxt, "type3", keyvals2)

        # Check equality with only extra_specs
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertEqual(True, same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref3['id'])
        self.assertEqual(False, same)
        self.assertEqual(('val1', 'val0'), diff['extra_specs']['key1'])

        #qos_ref 1 and 2 have the same specs, while 3 has different
        qos_keyvals1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
        qos_keyvals2 = {'k1': 'v0', 'k2': 'v2', 'k3': 'v3'}
        qos_ref1 = qos_specs.create(self.ctxt, 'qos-specs-1', qos_keyvals1)
        qos_ref2 = qos_specs.create(self.ctxt, 'qos-specs-2', qos_keyvals1)
        qos_ref3 = qos_specs.create(self.ctxt, 'qos-specs-3', qos_keyvals2)

        # Check equality with qos specs too
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref1['id'],
                                          type_ref1['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2['id'],
                                          type_ref2['id'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertEqual(True, same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v1'), diff['qos_specs']['k1'])
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref2['id'],
                                         type_ref2['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref3['id'],
                                          type_ref2['id'])
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertEqual(False, same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v0'), diff['qos_specs']['k1'])
        qos_specs.disassociate_qos_specs(self.ctxt, qos_ref3['id'],
                                         type_ref2['id'])
        qos_specs.associate_qos_with_type(self.ctxt, qos_ref2['id'],
                                          type_ref2['id'])

        # And add encryption for good measure
        enc_keyvals1 = {'cipher': 'c1', 'key_size': 256, 'provider': 'p1',
                        'control_location': 'front-end'}
        enc_keyvals2 = {'cipher': 'c1', 'key_size': 128, 'provider': 'p1',
                        'control_location': 'front-end'}
        db.volume_type_encryption_create(self.ctxt, type_ref1['id'],
                                         enc_keyvals1)
        db.volume_type_encryption_create(self.ctxt, type_ref2['id'],
                                         enc_keyvals2)
        diff, same = volume_types.volume_types_diff(self.ctxt, type_ref1['id'],
                                                    type_ref2['id'])
        self.assertEqual(False, same)
        self.assertEqual(('val1', 'val1'), diff['extra_specs']['key1'])
        self.assertEqual(('v1', 'v1'), diff['qos_specs']['k1'])
        self.assertEqual((256, 128), diff['encryption']['key_size'])
コード例 #18
0
ファイル: manager.py プロジェクト: japplewhite/cinder-1
    def retype(self, ctxt, volume_id, new_type_id, host, migration_policy="never", reservations=None):
        def _retype_error(context, volume_id, old_reservations, new_reservations, status_update):
            try:
                self.db.volume_update(context, volume_id, status_update)
            finally:
                QUOTAS.rollback(context, old_reservations)
                QUOTAS.rollback(context, new_reservations)

        context = ctxt.elevated()

        volume_ref = self.db.volume_get(ctxt, volume_id)
        status_update = {"status": self._get_original_status(volume_ref)}
        if context.project_id != volume_ref["project_id"]:
            project_id = volume_ref["project_id"]
        else:
            project_id = context.project_id

        try:
            # NOTE(flaper87): Verify the driver is enabled
            # before going forward. The exception will be caught
            # and the volume status updated.
            utils.require_driver_initialized(self.driver)
        except exception.DriverNotInitialized:
            with excutils.save_and_reraise_exception():
                # NOTE(flaper87): Other exceptions in this method don't
                # set the volume status to error. Should that be done
                # here? Setting the volume back to it's original status
                # for now.
                self.db.volume_update(context, volume_id, status_update)

        # Get old reservations
        try:
            reserve_opts = {"volumes": -1, "gigabytes": -volume_ref["size"]}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume_ref.get("volume_type_id"))
            old_reservations = QUOTAS.reserve(context, project_id=project_id, **reserve_opts)
        except Exception:
            old_reservations = None
            self.db.volume_update(context, volume_id, status_update)
            LOG.exception(_("Failed to update usages while retyping volume."))
            raise exception.CinderException(_("Failed to get old volume type" " quota reservations"))

        # We already got the new reservations
        new_reservations = reservations

        # If volume types have the same contents, no need to do anything
        retyped = False
        diff, all_equal = volume_types.volume_types_diff(context, volume_ref.get("volume_type_id"), new_type_id)
        if all_equal:
            retyped = True

        # Call driver to try and change the type
        if not retyped:
            try:
                new_type = volume_types.get_volume_type(context, new_type_id)
                retyped = self.driver.retype(context, volume_ref, new_type, diff, host)
                if retyped:
                    LOG.info(_("Volume %s: retyped succesfully"), volume_id)
            except Exception as ex:
                retyped = False
                LOG.error(
                    _("Volume %s: driver error when trying to retype, " "falling back to generic mechanism."),
                    volume_ref["id"],
                )
                LOG.exception(ex)

        # We could not change the type, so we need to migrate the volume, where
        # the destination volume will be of the new type
        if not retyped:
            if migration_policy == "never":
                _retype_error(context, volume_id, old_reservations, new_reservations, status_update)
                msg = _("Retype requires migration but is not allowed.")
                raise exception.VolumeMigrationFailed(reason=msg)

            snaps = self.db.snapshot_get_all_for_volume(context, volume_ref["id"])
            if snaps:
                _retype_error(context, volume_id, old_reservations, new_reservations, status_update)
                msg = _("Volume must not have snapshots.")
                LOG.error(msg)
                raise exception.InvalidVolume(reason=msg)
            self.db.volume_update(context, volume_ref["id"], {"migration_status": "starting"})

            try:
                self.migrate_volume(context, volume_id, host, new_type_id=new_type_id)
            except Exception:
                with excutils.save_and_reraise_exception():
                    _retype_error(context, volume_id, old_reservations, new_reservations, status_update)

        self.db.volume_update(
            context, volume_id, {"volume_type_id": new_type_id, "host": host["host"], "status": status_update["status"]}
        )

        if old_reservations:
            QUOTAS.commit(context, old_reservations, project_id=project_id)
        if new_reservations:
            QUOTAS.commit(context, new_reservations, project_id=project_id)
        self.publish_service_capabilities(context)