def test_create_with_projects(self): context = self.context.elevated() flavor = flavor_obj.Flavor() flavor.name = 'm1.foo' flavor.extra_specs = fake_flavor['extra_specs'] flavor.projects = ['project-1', 'project-2'] db_flavor = dict(fake_flavor, projects=list(flavor.projects)) with mock.patch.multiple( db, flavor_create=mock.DEFAULT, flavor_access_get_by_flavor_id=mock.DEFAULT) as methods: methods['flavor_create'].return_value = db_flavor methods['flavor_access_get_by_flavor_id'].return_value = [{ 'project_id': 'project-1' }, { 'project_id': 'project-2' }] flavor.create(context) methods['flavor_create'].assert_called_once_with( context, { 'name': 'm1.foo', 'extra_specs': fake_flavor['extra_specs'] }, projects=['project-1', 'project-2']) self.assertEqual(context, flavor._context) # NOTE(danms): Orphan this to avoid lazy-loads flavor._context = None self._compare(self, fake_flavor, flavor) self.assertEqual(['project-1', 'project-2'], flavor.projects)
def test_disk_gb(self): # First test the project limit using the non-admin project. flavor = flavor_obj.Flavor( context=self.ctx, memory_mb=1, vcpus=1, root_gb=100, flavorid='9', name='m1.custom') flavor.create() self._create_server(api=self.api, flavor_id=flavor.flavorid) # Attempt to create another should fail as we are at quota. e = self.assertRaises( client.OpenStackApiException, self._create_server, api=self.api, flavor_id=flavor.flavorid) self.assertEqual(403, e.response.status_code) self.assertIn('class:DISK_GB', e.response.text) # Then test the default limit of 250 using the admin project. for i in range(2): self._create_server(api=self.admin_api, flavor_id=flavor.flavorid) # Attempt to create another server should fail because we are at quota. e = self.assertRaises( client.OpenStackApiException, self._create_server, api=self.admin_api, flavor_id=flavor.flavorid) self.assertEqual(403, e.response.status_code) self.assertIn('class:DISK_GB', e.response.text)
def test_create_with_projects(self, mock_create): context = self.context.elevated() flavor = flavor_obj.Flavor(context=context) flavor.name = 'm1.foo' flavor.extra_specs = fake_flavor['extra_specs'] flavor.projects = ['project-1', 'project-2'] db_flavor = dict(fake_flavor, projects=[{ 'project_id': pid } for pid in flavor.projects]) mock_create.return_value = db_flavor flavor.create() mock_create.assert_called_once_with( context, { 'name': 'm1.foo', 'extra_specs': fake_flavor['extra_specs'], 'projects': ['project-1', 'project-2'] }) self.assertEqual(context, flavor._context) # NOTE(danms): Orphan this to avoid lazy-loads flavor._context = None self._compare(self, fake_flavor, flavor) self.assertEqual(['project-1', 'project-2'], flavor.projects)
def test_load_projects(self): flavor = flavor_obj.Flavor(context=self.context, flavorid='foo') with mock.patch.object(db, 'flavor_access_get_by_flavor_id') as get: get.return_value = [{'project_id': 'project-1'}] projects = flavor.projects self.assertEqual(['project-1'], projects)
def get_flavor(self, namespace=None): prefix = ('%s_' % namespace) if namespace is not None else '' db_flavor = flavors.extract_flavor(self, prefix) flavor = flavor_obj.Flavor() for key in flavors.system_metadata_flavor_props: flavor[key] = db_flavor[key] return flavor
def test_activate_and_deactivate_bootloader(self): self._create_node() flavor = flavor_obj.Flavor(context=self.context, extra_specs={ 'baremetal:deploy_kernel_id': 'eeee', 'baremetal:deploy_ramdisk_id': 'ffff', }) self.instance['uuid'] = 'fake-uuid' self.mox.StubOutWithMock(flavor_obj.Flavor, 'get_by_id') self.mox.StubOutWithMock(bm_utils, 'write_to_file') self.mox.StubOutWithMock(bm_utils, 'create_link_without_raise') self.mox.StubOutWithMock(bm_utils, 'unlink_without_raise') self.mox.StubOutWithMock(bm_utils, 'rmtree_without_raise') flavor_obj.Flavor.get_by_id( self.context, self.instance['instance_type_id']).AndReturn(flavor) # create the config file bm_utils.write_to_file(mox.StrContains('fake-uuid'), mox.StrContains(CONF.baremetal.tftp_root)) # unlink and link the 2 interfaces for i in range(2): bm_utils.unlink_without_raise( mox.Or(mox.StrContains('fake-uuid'), mox.StrContains(CONF.baremetal.tftp_root))) bm_utils.create_link_without_raise( mox.StrContains('fake-uuid'), mox.StrContains(CONF.baremetal.tftp_root)) # unlink all 2 interfaces, 4 images, and the config file for i in range(7): bm_utils.unlink_without_raise( mox.Or(mox.StrContains('fake-uuid'), mox.StrContains(CONF.baremetal.tftp_root))) bm_utils.rmtree_without_raise(mox.StrContains('fake-uuid')) self.mox.ReplayAll() # activate and deactivate the bootloader # and check the deployment task_state in the database row = db.bm_node_get(self.context, 1) self.assertIsNone(row['deploy_key']) self.driver.activate_bootloader(self.context, self.node, self.instance, network_info=self.test_network_info) row = db.bm_node_get(self.context, 1) self.assertIsNotNone(row['deploy_key']) self.driver.deactivate_bootloader(self.context, self.node, self.instance) row = db.bm_node_get(self.context, 1) self.assertIsNone(row['deploy_key']) self.mox.VerifyAll()
def test_save_deleted_extra_specs(self, mock_add, mock_delete, mock_create): mock_create.return_value = dict(fake_flavor, extra_specs={'key1': 'value1'}) flavor = flavor_obj.Flavor(context=self.context) flavor.flavorid = 'test' flavor.extra_specs = {'key1': 'value1'} flavor.create() flavor.extra_specs = {} flavor.save() mock_delete.assert_called_once_with(self.context, flavor.id, 'key1') self.assertFalse(mock_add.called)
def test_create(self, mock_create): mock_create.return_value = fake_flavor flavor = flavor_obj.Flavor(context=self.context) flavor.name = 'm1.foo' flavor.extra_specs = fake_flavor['extra_specs'] flavor.create() self.assertEqual(self.context, flavor._context) # NOTE(danms): Orphan this to avoid lazy-loads flavor._context = None self._compare(self, fake_flavor, flavor)
def test_create(self): flavor = flavor_obj.Flavor() flavor.name = 'm1.foo' flavor.extra_specs = fake_flavor['extra_specs'] with mock.patch.object(db, 'flavor_create') as create: create.return_value = fake_flavor flavor.create(self.context) self.assertEqual(self.context, flavor._context) # NOTE(danms): Orphan this to avoid lazy-loads flavor._context = None self._compare(self, fake_flavor, flavor)
def fake_flavor_obj(**updates): flavor = flavor_obj.Flavor() flavor.id = 1 flavor.name = 'fakeflavor' flavor.memory_mb = 8000 flavor.vcpus = 3 flavor.root_gb = 11 flavor.ephemeral_gb = 4 flavor.swap = 0 flavor.rxtx_factor = 1.0 flavor.vcpu_weight = 1 if updates: flavor.update(updates) return flavor
def _remove_tenant_access(self, req, id, body): context = req.environ['nova.context'] authorize(context, action="remove_tenant_access") vals = body['remove_tenant_access'] tenant = vals['tenant_id'] flavor = flavor_obj.Flavor(context=context, flavorid=id) try: flavor.remove_access(tenant) except (exception.FlavorAccessNotFound, exception.FlavorNotFound) as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) except exception.AdminRequired as e: raise webob.exc.HTTPForbidden(explanation=e.format_message()) return _marshall_flavor_access(flavor)
def test_save(self, mock_update, mock_delete, mock_remove, mock_add, mock_notify): ctxt = self.context.elevated() extra_specs = {'key1': 'value1', 'key2': 'value2'} projects = ['project-1', 'project-2'] flavor = flavor_obj.Flavor(context=ctxt, flavorid='foo', id=123, extra_specs=extra_specs, projects=projects) flavor.obj_reset_changes() # Test deleting an extra_specs key and project del flavor.extra_specs['key1'] del flavor.projects[-1] self.assertEqual(set(['extra_specs', 'projects']), flavor.obj_what_changed()) flavor.save() self.assertEqual({'key2': 'value2'}, flavor.extra_specs) mock_delete.assert_called_once_with(ctxt, 'foo', 'key1') self.assertEqual(['project-1'], flavor.projects) mock_remove.assert_called_once_with(ctxt, 'foo', 'project-2') # Test updating an extra_specs key value flavor.extra_specs['key2'] = 'foobar' self.assertEqual(set(['extra_specs']), flavor.obj_what_changed()) flavor.save() self.assertEqual({'key2': 'foobar'}, flavor.extra_specs) mock_update.assert_called_with(ctxt, 'foo', {'key2': 'foobar'}) # Test adding an extra_specs and project flavor.extra_specs['key3'] = 'value3' flavor.projects.append('project-3') self.assertEqual(set(['extra_specs', 'projects']), flavor.obj_what_changed()) flavor.save() self.assertEqual({ 'key2': 'foobar', 'key3': 'value3' }, flavor.extra_specs) mock_update.assert_called_with(ctxt, 'foo', { 'key2': 'foobar', 'key3': 'value3' }) self.assertEqual(['project-1', 'project-3'], flavor.projects) mock_add.assert_called_once_with(ctxt, 'foo', 'project-3')
def _removeTenantAccess(self, req, id, body): context = req.environ['nova.context'] authorize(context, action="removeTenantAccess") self._check_body(body) vals = body['removeTenantAccess'] tenant = vals['tenant'] flavor = flavor_obj.Flavor(context=context, flavorid=id) try: flavor.remove_access(tenant) except (exception.FlavorNotFound, exception.FlavorAccessNotFound) as err: raise webob.exc.HTTPNotFound(explanation=err.format_message()) return _marshall_flavor_access(flavor)
def test_save(self): flavor = flavor_obj.Flavor._from_db_object(self.context, flavor_obj.Flavor(), fake_flavor) flavor.flavorid = 'foo' flavor.obj_reset_changes() flavor.extra_specs = {'foo': 'baz'} flavor.projects = ['project-1', 'project-3'] with contextlib.nested( mock.patch.object(db, 'flavor_extra_specs_update_or_create'), mock.patch.object(db, 'flavor_access_get_by_flavor_id'), mock.patch.object(db, 'flavor_access_add'), mock.patch.object( db, 'flavor_access_remove')) as (extra_specs_update, access_get, access_add, access_remove): access_get.return_value = [{ 'project_id': 'project-1' }, { 'project_id': 'project-2' }] flavor.save(self.context) extra_specs_update.assert_called_once_with(self.context, flavor.flavorid, {'foo': 'baz'}) access_get.assert_called_once_with(self.context, flavor.flavorid) access_add.assert_called_once_with(self.context, flavor.flavorid, 'project-3') access_remove.assert_called_once_with(self.context, flavor.flavorid, 'project-2') self.assertEqual(set(), flavor.obj_what_changed()) self.assertEqual(['project-1', 'project-3'], flavor.projects) flavor.projects = [] with contextlib.nested( mock.patch.object(db, 'flavor_access_get_by_flavor_id'), mock.patch.object(db, 'flavor_access_remove')) as (access_get, access_remove): access_get.return_value = [{'project_id': 'project-1'}] flavor.save(self.context) access_remove.assert_called_once_with(self.context, flavor.flavorid, 'project-1')
def test_description(self, mock_notify): # Create a flavor with a description. ctxt = nova_context.get_admin_context() flavorid = uuidutils.generate_uuid() dict_flavor = dict(fake_flavor, name=flavorid, flavorid=flavorid) del dict_flavor['id'] flavor = flavor_obj.Flavor(ctxt, **dict_flavor) flavor.description = 'rainbows and unicorns' flavor.create() mock_notify.assert_called_once_with('create') # Lookup the flavor to make sure the description is set. flavor = flavor_obj.Flavor.get_by_flavor_id(ctxt, flavorid) self.assertEqual('rainbows and unicorns', flavor.description) # Now reset the flavor.description since it's nullable=True. mock_notify.reset_mock() self.assertEqual(0, len(flavor.obj_what_changed()), flavor.obj_what_changed()) flavor.description = None self.assertEqual(['description'], list(flavor.obj_what_changed()), flavor.obj_what_changed()) old_updated_at = flavor.updated_at flavor.save() # Make sure we reloaded the flavor from the database. self.assertNotEqual(old_updated_at, flavor.updated_at) mock_notify.assert_called_once_with('update') self.assertEqual(0, len(flavor.obj_what_changed()), flavor.obj_what_changed()) # Lookup the flavor to make sure the description is gone. flavor = flavor_obj.Flavor.get_by_flavor_id(ctxt, flavorid) self.assertIsNone(flavor.description) # Test compatibility. flavor.description = 'flavor descriptions are not backward compatible' data = lambda x: x['nova_object.data'] flavor_primitive = data(flavor.obj_to_primitive()) self.assertIn('description', flavor_primitive) flavor.obj_make_compatible(flavor_primitive, '1.1') self.assertIn('name', flavor_primitive) self.assertNotIn('description', flavor_primitive)
def _remove_tenant_access(self, req, id, body): context = req.environ['nova.context'] authorize(context, action="remove_tenant_access") if not self.is_valid_body(body, 'remove_tenant_access'): raise webob.exc.HTTPBadRequest(explanation=_("Invalid request")) vals = body['remove_tenant_access'] try: tenant = vals['tenant_id'] except KeyError: raise webob.exc.HTTPBadRequest( explanation=_("tenant_id is required")) flavor = flavor_obj.Flavor(context=context, flavorid=id) try: flavor.remove_access(tenant) except (exception.FlavorAccessNotFound, exception.FlavorNotFound) as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) except exception.AdminRequired as e: raise webob.exc.HTTPForbidden(explanation=e.format_message()) return _marshall_flavor_access(flavor)
def test_destroy_api_by_flavorid(self, mock_destroy): mock_destroy.return_value = dict(fake_flavor, flavorid='foo') flavor = flavor_obj.Flavor(context=self.context, flavorid='foo') flavor.destroy() mock_destroy.assert_called_once_with(self.context, flavorid=flavor.flavorid)
def test_destroy_api_by_name(self, mock_destroy): flavor = flavor_obj.Flavor(context=self.context, name='foo') flavor.destroy() mock_destroy.assert_called_once_with(self.context, name=flavor.name)
def test_destroy_api_by_flavorid(self, mock_destroy): flavor = flavor_obj.Flavor(context=self.context, flavorid='foo') flavor.destroy() mock_destroy.assert_called_once_with(self.context, flavorid=flavor.flavorid)
def test_remove_access(self): elevated = self.context.elevated() flavor = flavor_obj.Flavor(context=elevated, flavorid='123') with mock.patch.object(db, 'flavor_access_remove') as remove: flavor.remove_access('456') remove.assert_called_once_with(elevated, '123', '456')
# under the License. from nova.compute import power_state from nova.compute import task_states from nova.compute import vm_states from nova.objects import flavor from nova.objects import image_meta from nova.objects import instance import os import sys TEST_FLAVOR = flavor.Flavor(memory_mb=2048, swap=0, vcpu_weight=None, root_gb=10, id=2, name=u'm1.small', ephemeral_gb=0, rxtx_factor=1.0, flavorid=u'1', vcpus=1) TEST_INSTANCE = { 'id': 1, 'uuid': '49629a5c-f4c4-4721-9511-9725786ff2e5', 'display_name': 'Fake Instance', 'root_gb': 10, 'ephemeral_gb': 0, 'instance_type_id': '5', 'system_metadata': { 'image_os_distro': 'rhel' },
def test_add_access(self): elevated = self.context.elevated() flavor = flavor_obj.Flavor(context=elevated, flavorid='123') with mock.patch.object(db, 'flavor_access_add') as add: flavor.add_access('456') add.assert_called_once_with(elevated, '123', '456')
def test_add_access_with_dirty_projects(self): flavor = flavor_obj.Flavor(context=self.context, projects=['1']) self.assertRaises(exception.ObjectActionError, flavor.add_access, '2')
def test_destroy(self): flavor = flavor_obj.Flavor(id=123, name='foo') with mock.patch.object(db, 'flavor_destroy') as destroy: flavor.destroy(self.context) destroy.assert_called_once_with(self.context, flavor.name)
def test_load_anything_else(self): flavor = flavor_obj.Flavor() self.assertRaises(exception.ObjectActionError, getattr, flavor, 'name')
def test_save_invalid_fields(self): flavor = flavor_obj.Flavor(id=123) self.assertRaises(exception.ObjectActionError, flavor.save)
def test_create_with_id(self): flavor = flavor_obj.Flavor(id=123) self.assertRaises(exception.ObjectActionError, flavor.create, self.context)
def test_add_access_api(self, mock_api_add, mock_main_add, mock_notify): elevated = self.context.elevated() flavor = flavor_obj.Flavor(context=elevated, id=12345, flavorid='123') flavor.add_access('456') mock_api_add.assert_called_once_with(elevated, 12345, '456') self.assertFalse(mock_main_add.called)
def test_destroy(self, mock_destroy): mock_destroy.side_effect = exception.FlavorNotFound(flavor_id='foo') flavor = flavor_obj.Flavor(context=self.context, flavorid='foo') with mock.patch.object(db, 'flavor_destroy') as destroy: flavor.destroy() destroy.assert_called_once_with(self.context, flavor.flavorid)
def test_remove_access_api(self, mock_api_del, mock_notify): elevated = self.context.elevated() flavor = flavor_obj.Flavor(context=elevated, id=12345, flavorid='123') flavor.remove_access('456') mock_api_del.assert_called_once_with(elevated, 12345, '456')