Exemplo n.º 1
0
 def test_retype_volume_not_capable_to_replica(self):
     elevated = context.get_admin_context()
     db.volume_type_create(elevated, {'name': 'old', 'extra_specs': {}})
     old_vol_type = db.volume_type_get_by_name(elevated, 'old')
     new_extra_specs = {'replication_enabled': '<is> True'}
     db.volume_type_create(elevated, {
         'name': 'new',
         'extra_specs': new_extra_specs
     })
     new_vol_type = db.volume_type_get_by_name(elevated, 'new')
     volume = tests_utils.create_volume(self.context,
                                        size=1,
                                        host=CONF.host,
                                        status='available',
                                        volume_type_id=old_vol_type['id'],
                                        replication_status='not-capable')
     host_obj = {'host': 'newhost', 'capabilities': {}}
     with mock.patch.object(self.volume,
                            'migrate_volume') as migrate_volume:
         migrate_volume.return_value = True
         self.volume.retype(self.context,
                            volume,
                            new_vol_type['id'],
                            host_obj,
                            migration_policy='on-demand')
Exemplo n.º 2
0
    def test_volume_type_get_by_name_with_extra_specs(self):
        volume_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 self.vol_type1['name'])
        self.assertEquals(volume_type['extra_specs'], self.vol_type1_specs)

        volume_type = db.volume_type_get_by_name(
            context.get_admin_context(), self.vol_type2_noextra['name'])
        self.assertEquals(volume_type['extra_specs'], {})
    def test_volume_type_get_by_name_with_extra_specs(self):
        volume_type = db.volume_type_get_by_name(
            context.get_admin_context(),
            self.vol_type1['name'])
        self.assertEqual(volume_type['extra_specs'], self.vol_type1_specs)

        volume_type = db.volume_type_get_by_name(
            context.get_admin_context(),
            self.vol_type2_noextra['name'])
        self.assertEqual(volume_type['extra_specs'], {})
Exemplo n.º 4
0
    def test_create_volume_with_volume_type(self):
        """Test volume creation with default volume type."""
        def fake_reserve(context, expire=None, project_id=None, **deltas):
            return ["RESERVATION"]

        def fake_commit(context, reservations, project_id=None):
            pass

        def fake_rollback(context, reservations, project_id=None):
            pass

        self.stubs.Set(QUOTAS, "reserve", fake_reserve)
        self.stubs.Set(QUOTAS, "commit", fake_commit)
        self.stubs.Set(QUOTAS, "rollback", fake_rollback)

        volume_api = cinder.volume.api.API()

        # Create volume with default volume type while default
        # volume type doesn't exist, volume_type_id should be NULL
        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description')
        self.assertEquals(volume['volume_type_id'], None)

        # Create default volume type
        vol_type = fake_flags.def_vol_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))

        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        # Create volume with default volume type
        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description')
        self.assertEquals(volume['volume_type_id'], db_vol_type.get('id'))

        # Create volume with specific volume type
        vol_type = 'test'
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description',
                                   volume_type=db_vol_type)
        self.assertEquals(volume['volume_type_id'], db_vol_type.get('id'))
Exemplo n.º 5
0
    def test_create_volume_with_volume_type(self):
        """Test volume creation with default volume type."""
        def fake_reserve(context, expire=None, project_id=None, **deltas):
            return ["RESERVATION"]

        def fake_commit(context, reservations, project_id=None):
            pass

        def fake_rollback(context, reservations, project_id=None):
            pass

        self.stubs.Set(QUOTAS, "reserve", fake_reserve)
        self.stubs.Set(QUOTAS, "commit", fake_commit)
        self.stubs.Set(QUOTAS, "rollback", fake_rollback)

        volume_api = cinder.volume.api.API()

        # Create volume with default volume type while default
        # volume type doesn't exist, volume_type_id should be NULL
        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description')
        self.assertEquals(volume['volume_type_id'], None)

        # Create default volume type
        vol_type = fake_flags.def_vol_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))

        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        # Create volume with default volume type
        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description')
        self.assertEquals(volume['volume_type_id'], db_vol_type.get('id'))

        # Create volume with specific volume type
        vol_type = 'test'
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        volume = volume_api.create(self.context,
                                   1,
                                   'name',
                                   'description',
                                   volume_type=db_vol_type)
        self.assertEquals(volume['volume_type_id'], db_vol_type.get('id'))
Exemplo n.º 6
0
        def _setup_volume_types():
            spec_dict = _create_min_max_size_dict(2, 4)
            sized_vol_type_dict = {
                'name': 'limit_type',
                'extra_specs': spec_dict
            }
            db.volume_type_create(self.context, sized_vol_type_dict)
            self.sized_vol_type = db.volume_type_get_by_name(
                self.context, sized_vol_type_dict['name'])

            unsized_vol_type_dict = {'name': 'unsized_type', 'extra_specs': {}}
            db.volume_type_create(context.get_admin_context(),
                                  unsized_vol_type_dict)
            self.unsized_vol_type = db.volume_type_get_by_name(
                self.context, unsized_vol_type_dict['name'])
Exemplo n.º 7
0
 def setUp(self):
     super(ImageVolumeTestCases, self).setUp()
     db.volume_type_create(self.context,
                           v2_fakes.fake_default_type_get(
                               fake.VOLUME_TYPE2_ID))
     self.vol_type = db.volume_type_get_by_name(self.context,
                                                'vol_type_name')
Exemplo n.º 8
0
 def setUp(self, *args, **kwargs):
     super(SnapshotTestCase, self).setUp()
     db.volume_type_create(self.context,
                           v2_fakes.fake_default_type_get(
                               fake.VOLUME_TYPE2_ID))
     self.vol_type = db.volume_type_get_by_name(self.context,
                                                'vol_type_name')
Exemplo n.º 9
0
    def test_volume_create_with_type(self):
        vol_type = CONF.default_volume_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        vol = {"size": 100,
               "display_name": "Volume Test Name",
               "display_description": "Volume Test Desc",
               "availability_zone": "zone1:host1",
               "volume_type": "FakeTypeName"}
        body = {"volume": vol}
        req = fakes.HTTPRequest.blank('/v1/volumes')
        # Raise 404 when type name isn't valid
        self.assertRaises(webob.exc.HTTPNotFound, self.controller.create,
                          req, body)
        # Use correct volume type name
        vol.update(dict(volume_type=CONF.default_volume_type))
        body.update(dict(volume=vol))
        res_dict = self.controller.create(req, body)
        self.assertIn('id', res_dict['volume'])
        self.assertEqual(len(res_dict), 1)
        self.assertEqual(res_dict['volume']['volume_type'],
                         db_vol_type['name'])

        # Use correct volume type id
        vol.update(dict(volume_type=db_vol_type['id']))
        body.update(dict(volume=vol))
        res_dict = self.controller.create(req, body)
        self.assertIn('id', res_dict['volume'])
        self.assertEqual(len(res_dict), 1)
        self.assertEqual(res_dict['volume']['volume_type'],
                         db_vol_type['name'])
Exemplo n.º 10
0
    def test_create_volume_with_group_invalid_type(self):
        """Test volume creation with group & invalid volume type."""
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 '__DEFAULT__')

        grp = tests_utils.create_group(
            self.context,
            availability_zone=CONF.storage_availability_zone,
            status=fields.GroupStatus.AVAILABLE,
            volume_type_ids=[db_vol_type['id']],
            group_type_id=fake.GROUP_TYPE_ID,
            host=CONF.host)

        fake_type = fake_volume.fake_volume_type_obj(
            self.context,
            id=fake.VOLUME_TYPE_ID,
            name='fake')

        # Volume type must be provided when creating a volume in a
        # group.
        self.assertRaises(exception.InvalidInput,
                          self.volume_api.create,
                          self.context, 1, 'vol1', 'volume 1',
                          group=grp)

        # Volume type must be valid.
        self.assertRaises(exception.InvalidInput,
                          self.volume_api.create,
                          self.context, 1, 'vol1', 'volume 1',
                          volume_type=fake_type,
                          group=grp)
Exemplo n.º 11
0
    def test_volume_create_with_type(self):
        vol_type = CONF.default_volume_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        vol = {"size": 100,
               "display_name": "Volume Test Name",
               "display_description": "Volume Test Desc",
               "availability_zone": "zone1:host1",
               "volume_type": "FakeTypeName"}
        body = {"volume": vol}
        req = fakes.HTTPRequest.blank('/v1/volumes')
        # Raise 404 when type name isn't valid
        self.assertRaises(webob.exc.HTTPNotFound, self.controller.create,
                          req, body)
        # Use correct volume type name
        vol.update(dict(volume_type=CONF.default_volume_type))
        body.update(dict(volume=vol))
        res_dict = self.controller.create(req, body)
        self.assertIn('id', res_dict['volume'])
        self.assertEqual(len(res_dict), 1)
        self.assertEqual(res_dict['volume']['volume_type'],
                         db_vol_type['name'])

        # Use correct volume type id
        vol.update(dict(volume_type=db_vol_type['id']))
        body.update(dict(volume=vol))
        res_dict = self.controller.create(req, body)
        self.assertIn('id', res_dict['volume'])
        self.assertEqual(len(res_dict), 1)
        self.assertEqual(res_dict['volume']['volume_type'],
                         db_vol_type['name'])
Exemplo n.º 12
0
def get_volume_type_by_name(context, name):
    """Retrieves single volume type by name."""
    if name is None:
        msg = _("name cannot be None")
        raise exception.InvalidVolumeType(reason=msg)

    return db.volume_type_get_by_name(context, name)
Exemplo n.º 13
0
def get_volume_type_by_name(context, name):
    """Retrieves single volume type by name."""
    if name is None:
        msg = _("name cannot be None")
        raise exception.InvalidVolumeType(reason=msg)

    return db.volume_type_get_by_name(context, name)
Exemplo n.º 14
0
    def test_volume_create_with_type(self):
        vol_type = FLAGS.default_volume_type
        db.volume_type_create(context.get_admin_context(), dict(name=vol_type, extra_specs={}))

        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(), vol_type)

        vol = {
            "size": 100,
            "name": "Volume Test Name",
            "display_description": "Volume Test Desc",
            "availability_zone": "zone1:host1",
            "volume_type": db_vol_type["name"],
        }
        body = {"volume": vol}
        req = fakes.HTTPRequest.blank("/v2/volumes")
        res_dict = self.controller.create(req, body)
        volume_id = res_dict["volume"]["id"]
        self.assertEquals(len(res_dict), 1)

        self.stubs.Set(
            volume_api.API,
            "get_all",
            lambda *args, **kwargs: [stubs.stub_volume(volume_id, volume_type={"name": vol_type})],
        )
        req = fakes.HTTPRequest.blank("/v2/volumes/detail")
        res_dict = self.controller.detail(req)
Exemplo n.º 15
0
def get_volume_type_by_name(context: context.RequestContext,
                            name: Optional[str]) -> dict[str, Any]:
    """Retrieves single volume type by name."""
    if name is None:
        msg = _("name cannot be None")
        raise exception.InvalidVolumeType(reason=msg)

    return db.volume_type_get_by_name(context, name)
Exemplo n.º 16
0
 def test_retype_volume_not_capable_to_replica(self):
     elevated = context.get_admin_context()
     db.volume_type_create(elevated, {'name': 'old', 'extra_specs': {}})
     old_vol_type = db.volume_type_get_by_name(elevated, 'old')
     new_extra_specs = {'replication_enabled': '<is> True'}
     db.volume_type_create(elevated, {'name': 'new',
                                      'extra_specs': new_extra_specs})
     new_vol_type = db.volume_type_get_by_name(elevated, 'new')
     volume = tests_utils.create_volume(self.context, size=1,
                                        host=CONF.host, status='available',
                                        volume_type_id=old_vol_type['id'],
                                        replication_status='not-capable')
     host_obj = {'host': 'newhost', 'capabilities': {}}
     with mock.patch.object(self.volume,
                            'migrate_volume') as migrate_volume:
         migrate_volume.return_value = True
         self.volume.retype(self.context, volume, new_vol_type['id'],
                            host_obj, migration_policy='on-demand')
Exemplo n.º 17
0
    def test_retype_setup_fail_volume_is_available(self, mock_notify):
        """Verify volume is still available if retype prepare failed."""
        elevated = context.get_admin_context()
        project_id = self.context.project_id

        db.volume_type_create(elevated, {'name': 'old', 'extra_specs': {}})
        old_vol_type = db.volume_type_get_by_name(elevated, 'old')
        db.volume_type_create(elevated, {'name': 'new', 'extra_specs': {}})
        new_vol_type = db.volume_type_get_by_name(elevated, 'new')
        db.quota_create(elevated, project_id, 'volumes_new', 0)

        volume = tests_utils.create_volume(self.context, size=1,
                                           host=CONF.host, status='available',
                                           volume_type_id=old_vol_type['id'])

        api = cinder.volume.api.API()
        self.assertRaises(exception.VolumeLimitExceeded, api.retype,
                          self.context, volume, new_vol_type['id'])

        volume = db.volume_get(elevated, volume.id)
        mock_notify.assert_not_called()
        self.assertEqual('available', volume['status'])
Exemplo n.º 18
0
    def test_retype_setup_fail_volume_is_available(self, mock_notify):
        """Verify volume is still available if retype prepare failed."""
        elevated = context.get_admin_context()
        project_id = self.context.project_id

        db.volume_type_create(elevated, {'name': 'old', 'extra_specs': {}})
        old_vol_type = db.volume_type_get_by_name(elevated, 'old')
        db.volume_type_create(elevated, {'name': 'new', 'extra_specs': {}})
        new_vol_type = db.volume_type_get_by_name(elevated, 'new')
        db.quota_create(elevated, project_id, 'volumes_new', 0)

        volume = tests_utils.create_volume(self.context, size=1,
                                           host=CONF.host, status='available',
                                           volume_type_id=old_vol_type['id'])

        api = cinder.volume.api.API()
        self.assertRaises(exception.VolumeLimitExceeded, api.retype,
                          self.context, volume, new_vol_type['id'])

        volume = db.volume_get(elevated, volume.id)
        mock_notify.assert_not_called()
        self.assertEqual('available', volume['status'])
Exemplo n.º 19
0
    def schedule_create_volume(self, context, request_spec, filter_properties):
        """Use volume type extra_specs to store tenant info for tenant isolation"""

        volume_id = request_spec.get('volume_id')
        snapshot_id = request_spec.get('snapshot_id')
        image_id = request_spec.get('image_id')
        volume_properties = request_spec.get('volume_properties')
        availability_zone = volume_properties.get('availability_zone')

        context_dict = context.to_dict()
        tenant_name = context_dict['project_name']

        # check if request has volume type and volume type matching tenant
        # if no volume type in request, search db for tenant's bind volume type
        # if no bind volume type, add default volume type to create volume
        volume_type = request_spec.get('volume_type')
        if volume_type:
            specs = volume_type.get('extra_specs')
            if 'tenant_name' in specs:
                if specs['tenant_name'] != tenant_name:
                    msg = _("Tenant cannot use volume type %s." %
                            volume_type['name'])
                    raise exception.InvalidVolumeType(reason=msg)
        else:
            #check db if user's tenant has been bond to a volume type
            bindType = False
            volume_types = db.volume_type_get_all(context)
            for key in volume_types:
                specs = volume_types[key].get('extra_specs')
                if 'tenant_name' in specs:
                    if specs['tenant_name'] == tenant_name:
                        bindType = True
                        request_spec['volume_type'] = volume_types[key]
                        break
            if not bindType:
                request_spec['volume_type'] = db.volume_type_get_by_name(
                    context, 'DEFAULT')

        LOG.debug(str(request_spec))

        host = 'MyHost'
        updated_volume = driver.volume_update_db(context, volume_id, host)
        self.volume_rpcapi.create_volume(context,
                                         updated_volume,
                                         host,
                                         request_spec,
                                         filter_properties,
                                         snapshot_id=snapshot_id,
                                         image_id=image_id)
        return None
Exemplo n.º 20
0
    def test_volume_create_with_type(self):
        vol_type = CONF.default_volume_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        vol = {"size": 100,
               "display_name": "Volume Test Name",
               "display_description": "Volume Test Desc",
               "availability_zone": "zone1:host1",
               "volume_type": db_vol_type['name'], }
        body = {"volume": vol}
        req = fakes.HTTPRequest.blank('/v1/volumes')
        res_dict = self.controller.create(req, body)
        self.assertEquals(res_dict['volume']['volume_type'],
                          db_vol_type['name'])
Exemplo n.º 21
0
    def test_volume_create_with_type(self):
        vol_type = CONF.default_volume_type
        db.volume_type_create(context.get_admin_context(),
                              dict(name=vol_type, extra_specs={}))
        db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
                                                 vol_type)

        vol = {"size": 100,
               "display_name": "Volume Test Name",
               "display_description": "Volume Test Desc",
               "availability_zone": "zone1:host1",
               "volume_type": db_vol_type['name'], }
        body = {"volume": vol}
        req = fakes.HTTPRequest.blank('/v1/volumes')
        res_dict = self.controller.create(req, body)
        self.assertEquals(res_dict['volume']['volume_type'],
                          db_vol_type['name'])
    def test_manage_volume_raise_driver_exception(self, mock_execute,
                                                  mock_driver_get_size):
        elevated = context.get_admin_context()
        project_id = self.context.project_id
        db.volume_type_create(elevated, {'name': 'type1', 'extra_specs': {}})
        vol_type = db.volume_type_get_by_name(elevated, 'type1')
        # create source volume
        self.volume_params['volume_type_id'] = vol_type['id']
        self.volume_params['status'] = 'managing'
        test_vol = tests_utils.create_volume(self.context,
                                             **self.volume_params)
        mock_execute.side_effect = exception.VolumeBackendAPIException(
            data="volume driver got exception")
        mock_driver_get_size.return_value = 1
        # Set quota usage
        reserve_opts = {'volumes': 1, 'gigabytes': 1}
        reservations = QUOTAS.reserve(self.context, project_id=project_id,
                                      **reserve_opts)
        QUOTAS.commit(self.context, reservations)
        usage = db.quota_usage_get(self.context, project_id, 'volumes')
        volumes_in_use = usage.in_use
        usage = db.quota_usage_get(self.context, project_id, 'gigabytes')
        gigabytes_in_use = usage.in_use

        self.assertRaises(exception.VolumeBackendAPIException,
                          self.volume.manage_existing,
                          self.context, test_vol,
                          'volume_ref')
        # check volume status
        volume = objects.Volume.get_by_id(context.get_admin_context(),
                                          test_vol.id)
        self.assertEqual('error_managing', volume.status)
        # Delete this volume with 'error_managing_deleting' status in c-vol.
        test_vol.status = 'error_managing_deleting'
        test_vol.save()
        self.volume.delete_volume(self.context, test_vol)
        ctxt = context.get_admin_context(read_deleted='yes')
        volume = objects.Volume.get_by_id(ctxt, test_vol.id)
        self.assertEqual('deleted', volume.status)
        # Get in_use number after deleting error_managing volume
        usage = db.quota_usage_get(self.context, project_id, 'volumes')
        volumes_in_use_new = usage.in_use
        self.assertEqual(volumes_in_use, volumes_in_use_new)
        usage = db.quota_usage_get(self.context, project_id, 'gigabytes')
        gigabytes_in_use_new = usage.in_use
        self.assertEqual(gigabytes_in_use, gigabytes_in_use_new)
    def test_volume_type_get_by_name_with_extra_specs(self):
        volume_type = db.volume_type_get_by_name(context.get_admin_context(), self.vol_type1["name"])
        self.assertEquals(volume_type["extra_specs"], self.vol_type1_specs)

        volume_type = db.volume_type_get_by_name(context.get_admin_context(), self.vol_type2_noextra["name"])
        self.assertEquals(volume_type["extra_specs"], {})
Exemplo n.º 24
0
    def _retype_volume_exec(self,
                            driver,
                            mock_notify,
                            snap=False,
                            policy='on-demand',
                            migrate_exc=False,
                            exc=None,
                            diff_equal=False,
                            replica=False,
                            reserve_vol_type_only=False,
                            encryption_changed=False,
                            replica_new=None):
        elevated = context.get_admin_context()
        project_id = self.context.project_id

        if replica:
            rep_status = 'enabled'
            extra_specs = {'replication_enabled': '<is> True'}
        else:
            rep_status = 'disabled'
            extra_specs = {}

        if replica_new is None:
            replica_new = replica
        new_specs = {'replication_enabled': '<is> True'} if replica_new else {}

        db.volume_type_create(elevated, {
            'name': 'old',
            'extra_specs': extra_specs
        })
        old_vol_type = db.volume_type_get_by_name(elevated, 'old')

        db.volume_type_create(elevated, {
            'name': 'new',
            'extra_specs': new_specs
        })
        vol_type = db.volume_type_get_by_name(elevated, 'new')
        db.quota_create(elevated, project_id, 'volumes_new', 10)

        volume = tests_utils.create_volume(self.context,
                                           size=1,
                                           host=CONF.host,
                                           status='retyping',
                                           volume_type_id=old_vol_type['id'],
                                           replication_status=rep_status)
        volume.previous_status = 'available'
        volume.save()
        if snap:
            create_snapshot(volume.id, size=volume.size)
        if driver or diff_equal:
            host_obj = {'host': CONF.host, 'capabilities': {}}
        else:
            host_obj = {'host': 'newhost', 'capabilities': {}}

        reserve_opts = {'volumes': 1, 'gigabytes': volume.size}
        QUOTAS.add_volume_type_opts(self.context, reserve_opts, vol_type['id'])
        if reserve_vol_type_only:
            reserve_opts.pop('volumes')
            reserve_opts.pop('gigabytes')
            try:
                usage = db.quota_usage_get(elevated, project_id, 'volumes')
                total_volumes_in_use = usage.in_use
                usage = db.quota_usage_get(elevated, project_id, 'gigabytes')
                total_gigabytes_in_use = usage.in_use
            except exception.QuotaUsageNotFound:
                total_volumes_in_use = 0
                total_gigabytes_in_use = 0
        reservations = QUOTAS.reserve(self.context,
                                      project_id=project_id,
                                      **reserve_opts)

        old_reserve_opts = {'volumes': -1, 'gigabytes': -volume.size}
        QUOTAS.add_volume_type_opts(self.context, old_reserve_opts,
                                    old_vol_type['id'])
        old_reservations = QUOTAS.reserve(self.context,
                                          project_id=project_id,
                                          **old_reserve_opts)

        with mock.patch.object(self.volume.driver, 'retype') as _retype,\
                mock.patch.object(volume_types, 'volume_types_diff') as _diff,\
                mock.patch.object(self.volume, 'migrate_volume') as _mig,\
                mock.patch.object(db.sqlalchemy.api, 'volume_get') as mock_get:
            mock_get.return_value = volume
            _retype.return_value = driver
            returned_diff = {
                'encryption': {},
                'qos_specs': {},
                'extra_specs': {},
            }
            if replica != replica_new:
                returned_diff['extra_specs']['replication_enabled'] = (
                    extra_specs.get('replication_enabled'),
                    new_specs.get('replication_enabled'))
            expected_replica_status = 'enabled' if replica_new else 'disabled'

            if encryption_changed:
                returned_diff['encryption'] = 'fake'
            _diff.return_value = (returned_diff, diff_equal)
            if migrate_exc:
                _mig.side_effect = KeyError
            else:
                _mig.return_value = True

            if not exc:
                self.volume.retype(self.context,
                                   volume,
                                   vol_type['id'],
                                   host_obj,
                                   migration_policy=policy,
                                   reservations=reservations,
                                   old_reservations=old_reservations)
            else:
                self.assertRaises(exc,
                                  self.volume.retype,
                                  self.context,
                                  volume,
                                  vol_type['id'],
                                  host_obj,
                                  migration_policy=policy,
                                  reservations=reservations,
                                  old_reservations=old_reservations)
            if host_obj['host'] != CONF.host:
                _retype.assert_not_called()

        # get volume/quota properties
        volume = objects.Volume.get_by_id(elevated, volume.id)
        try:
            usage = db.quota_usage_get(elevated, project_id, 'volumes_new')
            volumes_in_use = usage.in_use
        except exception.QuotaUsageNotFound:
            volumes_in_use = 0

        # Get new in_use after retype, it should not be changed.
        if reserve_vol_type_only:
            try:
                usage = db.quota_usage_get(elevated, project_id, 'volumes')
                new_total_volumes_in_use = usage.in_use
                usage = db.quota_usage_get(elevated, project_id, 'gigabytes')
                new_total_gigabytes_in_use = usage.in_use
            except exception.QuotaUsageNotFound:
                new_total_volumes_in_use = 0
                new_total_gigabytes_in_use = 0
            self.assertEqual(total_volumes_in_use, new_total_volumes_in_use)
            self.assertEqual(total_gigabytes_in_use,
                             new_total_gigabytes_in_use)

        # check properties
        if driver or diff_equal:
            self.assertEqual(vol_type['id'], volume.volume_type_id)
            self.assertEqual('available', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(1, volumes_in_use)
            self.assert_notify_called(mock_notify,
                                      (['INFO', 'volume.retype'], ))
        elif not exc:
            self.assertEqual(old_vol_type['id'], volume.volume_type_id)
            self.assertEqual('retyping', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(1, volumes_in_use)
            self.assert_notify_called(mock_notify,
                                      (['INFO', 'volume.retype'], ))
        else:
            self.assertEqual(old_vol_type['id'], volume.volume_type_id)
            self.assertEqual('available', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(0, volumes_in_use)
            mock_notify.assert_not_called()
        if encryption_changed:
            self.assertTrue(_mig.called)
        self.assertEqual(expected_replica_status, volume.replication_status)
Exemplo n.º 25
0
    def _retype_volume_exec(self, driver, mock_notify,
                            snap=False, policy='on-demand',
                            migrate_exc=False, exc=None, diff_equal=False,
                            replica=False, reserve_vol_type_only=False,
                            encryption_changed=False,
                            replica_new=None):
        elevated = context.get_admin_context()
        project_id = self.context.project_id

        if replica:
            rep_status = 'enabled'
            extra_specs = {'replication_enabled': '<is> True'}
        else:
            rep_status = 'disabled'
            extra_specs = {}

        if replica_new is None:
            replica_new = replica
        new_specs = {'replication_enabled': '<is> True'} if replica_new else {}

        db.volume_type_create(elevated, {'name': 'old',
                                         'extra_specs': extra_specs})
        old_vol_type = db.volume_type_get_by_name(elevated, 'old')

        db.volume_type_create(elevated, {'name': 'new',
                                         'extra_specs': new_specs})
        vol_type = db.volume_type_get_by_name(elevated, 'new')
        db.quota_create(elevated, project_id, 'volumes_new', 10)

        volume = tests_utils.create_volume(self.context, size=1,
                                           host=CONF.host, status='retyping',
                                           volume_type_id=old_vol_type['id'],
                                           replication_status=rep_status)
        volume.previous_status = 'available'
        volume.save()
        if snap:
            create_snapshot(volume.id, size=volume.size,
                            user_id=self.user_context.user_id,
                            project_id=self.user_context.project_id,
                            ctxt=self.user_context)
        if driver or diff_equal:
            host_obj = {'host': CONF.host, 'capabilities': {}}
        else:
            host_obj = {'host': 'newhost', 'capabilities': {}}

        reserve_opts = {'volumes': 1, 'gigabytes': volume.size}
        QUOTAS.add_volume_type_opts(self.context,
                                    reserve_opts,
                                    vol_type['id'])
        if reserve_vol_type_only:
            reserve_opts.pop('volumes')
            reserve_opts.pop('gigabytes')
            try:
                usage = db.quota_usage_get(elevated, project_id, 'volumes')
                total_volumes_in_use = usage.in_use
                usage = db.quota_usage_get(elevated, project_id, 'gigabytes')
                total_gigabytes_in_use = usage.in_use
            except exception.QuotaUsageNotFound:
                total_volumes_in_use = 0
                total_gigabytes_in_use = 0
        reservations = QUOTAS.reserve(self.context,
                                      project_id=project_id,
                                      **reserve_opts)

        old_reserve_opts = {'volumes': -1, 'gigabytes': -volume.size}
        QUOTAS.add_volume_type_opts(self.context,
                                    old_reserve_opts,
                                    old_vol_type['id'])
        old_reservations = QUOTAS.reserve(self.context,
                                          project_id=project_id,
                                          **old_reserve_opts)

        with mock.patch.object(self.volume.driver, 'retype') as _retype,\
                mock.patch.object(volume_types, 'volume_types_diff') as _diff,\
                mock.patch.object(self.volume, 'migrate_volume') as _mig,\
                mock.patch.object(db.sqlalchemy.api, 'volume_get') as _vget,\
                mock.patch.object(context.RequestContext, 'elevated') as _ctx:
            _vget.return_value = volume
            _retype.return_value = driver
            _ctx.return_value = self.context
            returned_diff = {
                'encryption': {},
                'qos_specs': {},
                'extra_specs': {},
            }
            if replica != replica_new:
                returned_diff['extra_specs']['replication_enabled'] = (
                    extra_specs.get('replication_enabled'),
                    new_specs.get('replication_enabled'))
            expected_replica_status = 'enabled' if replica_new else 'disabled'

            if encryption_changed:
                returned_diff['encryption'] = 'fake'
            _diff.return_value = (returned_diff, diff_equal)
            if migrate_exc:
                _mig.side_effect = KeyError
            else:
                _mig.return_value = True

            if not exc:
                self.volume.retype(self.context, volume,
                                   vol_type['id'], host_obj,
                                   migration_policy=policy,
                                   reservations=reservations,
                                   old_reservations=old_reservations)
            else:
                self.assertRaises(exc, self.volume.retype,
                                  self.context, volume,
                                  vol_type['id'], host_obj,
                                  migration_policy=policy,
                                  reservations=reservations,
                                  old_reservations=old_reservations)
            if host_obj['host'] != CONF.host:
                _retype.assert_not_called()

        # get volume/quota properties
        volume = objects.Volume.get_by_id(elevated, volume.id)
        try:
            usage = db.quota_usage_get(elevated, project_id, 'volumes_new')
            volumes_in_use = usage.in_use
        except exception.QuotaUsageNotFound:
            volumes_in_use = 0

        # Get new in_use after retype, it should not be changed.
        if reserve_vol_type_only:
            try:
                usage = db.quota_usage_get(elevated, project_id, 'volumes')
                new_total_volumes_in_use = usage.in_use
                usage = db.quota_usage_get(elevated, project_id, 'gigabytes')
                new_total_gigabytes_in_use = usage.in_use
            except exception.QuotaUsageNotFound:
                new_total_volumes_in_use = 0
                new_total_gigabytes_in_use = 0
            self.assertEqual(total_volumes_in_use, new_total_volumes_in_use)
            self.assertEqual(total_gigabytes_in_use,
                             new_total_gigabytes_in_use)

        # check properties
        if driver or diff_equal:
            self.assertEqual(vol_type['id'], volume.volume_type_id)
            self.assertEqual('available', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(1, volumes_in_use)
            self.assert_notify_called(mock_notify,
                                      (['INFO', 'volume.retype'],))
        elif not exc:
            self.assertEqual(old_vol_type['id'], volume.volume_type_id)
            self.assertEqual('retyping', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(1, volumes_in_use)
            self.assert_notify_called(mock_notify,
                                      (['INFO', 'volume.retype'],))
        else:
            self.assertEqual(old_vol_type['id'], volume.volume_type_id)
            self.assertEqual('available', volume.status)
            self.assertEqual(CONF.host, volume.host)
            self.assertEqual(0, volumes_in_use)
            mock_notify.assert_not_called()
        if encryption_changed:
            self.assertTrue(_mig.called)
        self.assertEqual(expected_replica_status, volume.replication_status)