def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.membership = factories.CloudProjectMembershipFactory() self.tenant = mock.Mock() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock( return_value=self.neutron_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.backend.push_security_group = mock.Mock() self.backend.create_security_group = mock.Mock() self.backend.update_security_group = mock.Mock() self.backend.delete_security_group = mock.Mock() self.backend.push_security_group_rules = mock.Mock()
class OpenStackBackendCloudAccountApiTest(unittest.TestCase): def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.cloud_account = mock.Mock() self.backend = OpenStackBackend() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) def test_push_cloud_account_does_not_call_openstack_api(self): self.backend.push_cloud_account(self.cloud_account) self.assertFalse(self.backend.create_keystone_client.called, 'Keystone client should not have been created') self.assertFalse(self.backend.create_nova_client.called, 'Nova client should not have been created') def test_push_cloud_account_does_not_update_cloud_account(self): self.backend.push_cloud_account(self.cloud_account) self.assertFalse(self.cloud_account.save.called, 'Cloud account should not have been updated')
class OpenStackBackendConversionTest(unittest.TestCase): def setUp(self): self.backend = OpenStackBackend() def test_get_backend_ram_size_leaves_value_intact(self): core_ram = 4 # in MiB backend_ram = self.backend.get_backend_ram_size(core_ram) self.assertEqual( backend_ram, core_ram, 'Core ram and Backend ram are supposed be in the same units') def test_get_core_ram_size_leaves_value_intact(self): backend_ram = 4 # in MiB core_ram = self.backend.get_core_ram_size(backend_ram) self.assertEqual( core_ram, backend_ram, 'Core ram and Backend ram are supposed be in the same units') def test_get_backend_disk_size_converts_from_mebibytes_to_gibibytes(self): core_disk = 4096 # in MiB backend_disk = self.backend.get_backend_disk_size(core_disk) self.assertEqual(backend_disk, 4) def test_get_core_disk_size_converts_from_gibibytes_to_mebibytes(self): backend_disk = 4 # in GiB core_disk = self.backend.get_core_disk_size(backend_disk) self.assertEqual(core_disk, 4096)
def populate_internal_network(apps, schema_editor): # check if such a network already exists, if so -- use it instead CloudProjectMembership = apps.get_model("iaas", "CloudProjectMembership") db_alias = schema_editor.connection.alias def get_tenant_name(membership): return '{0}-{1}'.format(membership.project.uuid.hex, membership.project.name) openstack = OpenStackBackend() for cpm in CloudProjectMembership.objects.using(db_alias).filter( internal_network_id='').iterator(): network_name = get_tenant_name(cpm) network_lookup = { 'name': network_name, 'tenant_id': cpm.tenant_id, } try: session = openstack.create_tenant_session(cpm) neutron = openstack.create_neutron_client(session) networks_by_name = neutron.list_networks( **network_lookup)['networks'] network_id = networks_by_name[0]['id'] except (ClientException, NeutronClientException, KeyError): network_id = 'ERROR-API' except IndexError: network_id = 'ERROR-NOT-FOUND' else: if len(networks_by_name) > 1: network_id = 'ERROR-TOO-MANY' cpm.internal_network_id = network_id cpm.save()
def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.membership = factories.CloudProjectMembershipFactory() self.tenant = mock.Mock() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock(return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock(return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock(return_value=self.neutron_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_internal_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.floating_ips = [ {'status': 'ACTIVE', 'floating_ip_address': '10.7.201.163', 'id': '063795b7-23ac-4a0d-82f0-4326e73ee1bc', 'port_id': 'fakeport', 'floating_network_id': 'd5e27df4-6754-46ac-903c-5b3fa25e21dd'}, {'status': 'DOWN', 'floating_ip_address': '10.7.201.114', 'id': '063795b7-23ac-4a0d-82f0-432as73asdas', 'port_id': 'fakeport', 'floating_network_id': '83353d4a-a2d2-4f24-a472-57578699a6b1'}, {'status': 'ACTIVE', 'floating_ip_address': '10.7.201.107', 'id': '063795b7-asds-aq34-3df4-23asdasddssc', 'port_id': 'fakeport', 'floating_network_id': '34918c99-de9f-4cd3-b56c-fc982429f481'}, ] self.backend.get_floating_ips = mock.Mock(return_value=self.floating_ips)
def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.cloud_account = mock.Mock() self.backend = OpenStackBackend() self.backend.create_keystone_client = mock.Mock(return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock(return_value=self.nova_client)
def setUp(self): self.membership = mock.Mock() self.session = mock.Mock() self.session.auth.auth_url = 'http://keystone.example.com:5000/v2.0' self.session.auth.username = '******' self.session.auth.password = '******' self.backend = OpenStackBackend(dummy=True) self.backend.create_session = mock.Mock(return_value=self.session)
def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.membership = mock.Mock() self.membership.project.uuid.hex = 'project_uuid' self.membership.project.name = 'project_name' self.membership.project.description = 'project_description' self.backend = OpenStackBackend()
def setUp(self): self.nova_client = mock.Mock() self.nova_client.servers.list.return_value = [] self.nova_client.servers.findall.return_value = [] self.membership = factories.CloudProjectMembershipFactory() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock(return_value=mock.Mock(dummy=False)) self.backend.create_nova_client = mock.Mock(return_value=self.nova_client)
def setUp(self): self.nova_client = mock.Mock() self.nova_client.flavors.findall.return_value = [] self.cloud_account = factories.CloudFactory() self.flavors = factories.FlavorFactory.create_batch(2, cloud=self.cloud_account) # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_nova_client = mock.Mock(return_value=self.nova_client)
def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.cinder_client = mock.Mock() self.membership = mock.Mock( ) # TODO: use real membership, not mocked and unite with test class below self.tenant = mock.Mock() # client methods: self.nova_quota = mock.Mock(cores=20, instances=10, ram=51200) self.nova_client.quotas.get = mock.Mock(return_value=self.nova_quota) self.cinder_quota = mock.Mock(gigabytes=1000) self.cinder_client.quotas.get = mock.Mock( return_value=self.cinder_quota) self.volumes = [mock.Mock(size=10 * i, id=i) for i in range(5)] self.snapshots = [mock.Mock(size=10 * i, id=i) for i in range(5)] self.flavors = [mock.Mock(ram=i, id=i, vcpus=i) for i in range(4)] self.instances = [mock.Mock(flavor={'id': i}) for i in range(2)] self.cinder_client.volume_snapshots.list = mock.Mock( return_value=self.snapshots) self.cinder_client.volumes.list = mock.Mock(return_value=self.volumes) self.nova_client.servers.list = mock.Mock(return_value=self.instances) self.nova_client.flavors.list = mock.Mock(return_value=self.flavors) # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock( return_value=self.neutron_client) self.backend.create_cinder_client = mock.Mock( return_value=self.cinder_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.backend.push_security_group = mock.Mock() self.backend.create_security_group = mock.Mock() self.backend.update_security_group = mock.Mock() self.backend.delete_security_group = mock.Mock() self.backend.push_security_group_rules = mock.Mock() self.backend.get_hypervisors_statistics = mock.Mock(return_value=[])
def setUp(self): settings, _ = OpenStackSettings.objects.update_or_create( auth_url='http://keystone.example.com:5000/v2.0', defaults={ 'username': '******', 'password': '******', 'tenant_name': 'test_tenant', }) self.auth_url = settings.auth_url self.tenant_id = '593af1f7b67b4d63b691fcabd2dad126' self.credentials = { 'auth_url': self.auth_url, 'username': '******', 'password': '******', 'tenant_id': uuid.uuid4().hex, } self.backend = OpenStackBackend(dummy=True)
def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.membership = factories.CloudProjectMembershipFactory() self.tenant = mock.Mock() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock( return_value=self.neutron_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.floating_ips = [ { 'status': 'ACTIVE', 'floating_ip_address': '10.7.201.163', 'id': '063795b7-23ac-4a0d-82f0-4326e73ee1bc', 'port_id': 'fakeport' }, { 'status': 'DOWN', 'floating_ip_address': '10.7.201.114', 'id': '063795b7-23ac-4a0d-82f0-432as73asdas', 'port_id': 'fakeport' }, { 'status': 'ACTIVE', 'floating_ip_address': '10.7.201.107', 'id': '063795b7-asds-aq34-3df4-23asdasddssc', 'port_id': 'fakeport' }, ] self.backend.get_floating_ips = mock.Mock( return_value=self.floating_ips)
def setUp(self): self.glance_client = mock.Mock() # C # ^ # | # (I0) # | # v # T0 T1 T2 # ^ ^ ^ # | \ | \ | # | \ | \ | # | \ | \ | # v v v v v # TM0 TM1 TM2 TM3 TM4 # self.cloud_account = factories.CloudFactory() self.templates = factories.TemplateFactory.create_batch(3) self.template_mappings = ( factories.TemplateMappingFactory.create_batch( 2, template=self.templates[0]) + factories.TemplateMappingFactory.create_batch( 2, template=self.templates[1]) + factories.TemplateMappingFactory.create_batch( 1, template=self.templates[2])) self.image = factories.ImageFactory( cloud=self.cloud_account, template=self.template_mappings[0].template, backend_id=self.template_mappings[0].backend_image_id, ) # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_glance_client = mock.Mock( return_value=self.glance_client)
class OpenStackBackendSecurityGroupsTest(TransactionTestCase): def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.membership = factories.CloudProjectMembershipFactory() self.tenant = mock.Mock() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock(return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock(return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock(return_value=self.neutron_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_internal_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.backend.push_security_group = mock.Mock() self.backend.create_security_group = mock.Mock() self.backend.update_security_group = mock.Mock() self.backend.delete_security_group = mock.Mock() self.backend.push_security_group_rules = mock.Mock() def test_push_security_groups_deletes_nonexisting_groups(self): group1 = mock.Mock() group1.name = 'group1' group1.id = 1 self.nova_client.security_groups.list = mock.Mock(return_value=[group1]) # when self.backend.push_security_groups(self.membership) # then self.backend.delete_security_group.assert_any_call(str(group1.id), nova=self.nova_client) def test_push_membership_security_groups_raises_cloud_backed_error_on_keystone_error(self): self.backend.create_session.side_effect = keystone_exceptions.AuthorizationFailure() with self.assertRaises(CloudBackendError): self.backend.push_security_groups(self.membership)
def test_do_not_push_ssh_public_key_dublicate(self): public_key = self._get_dummy_ssh_key() nova_client = mock.Mock() backend = OpenStackBackend(dummy=True) backend.create_session = mock.Mock(return_value=self.session) backend.create_nova_client = mock.Mock(return_value=nova_client) backend.push_ssh_public_key(self.membership, public_key) nova_client.keypairs.find.assert_called_once_with(fingerprint=public_key.fingerprint) assert not nova_client.keypairs.create.called
def test_session(self): session = self.backend.create_admin_session(self.auth_url) self.assertEqual(session.auth.tenant_id, self.tenant_id) session = self.backend.create_tenant_session(self.credentials) self.assertEqual(session.auth.tenant_id, self.credentials['tenant_id']) self.assertEqual(session.auth.username, self.credentials['username']) with self.assertRaises(keystone_exceptions.ConnectionRefused): crdts = self.credentials.copy() crdts['auth_url'] = 'another.example.com' self.backend.create_tenant_session(crdts) sess1 = dict(session.copy()) sess2 = OpenStackBackend.recover_session(sess1) self.assertTrue(sess2.dummy)
def get_backend(self): # TODO: Support different clouds instead of hard-coding # Importing here to avoid circular imports hell from nodeconductor.iaas.backend.openstack import OpenStackBackend return OpenStackBackend(dummy=self.dummy)
class OpenStackClientTest(TestCase): def setUp(self): settings, _ = OpenStackSettings.objects.update_or_create( auth_url='http://keystone.example.com:5000/v2.0', defaults={ 'username': '******', 'password': '******', 'tenant_name': 'test_tenant', }) self.auth_url = settings.auth_url self.tenant_id = '593af1f7b67b4d63b691fcabd2dad126' self.credentials = { 'auth_url': self.auth_url, 'username': '******', 'password': '******', 'tenant_id': uuid.uuid4().hex, } self.backend = OpenStackBackend(dummy=True) def test_session(self): session = self.backend.create_admin_session(self.auth_url) self.assertEqual(session.auth.tenant_id, self.tenant_id) session = self.backend.create_tenant_session(self.credentials) self.assertEqual(session.auth.tenant_id, self.credentials['tenant_id']) self.assertEqual(session.auth.username, self.credentials['username']) with self.assertRaises(keystone_exceptions.ConnectionRefused): crdts = self.credentials.copy() crdts['auth_url'] = 'another.example.com' self.backend.create_tenant_session(crdts) sess1 = dict(session.copy()) sess2 = OpenStackBackend.recover_session(sess1) self.assertTrue(sess2.dummy) def test_keystone(self): session = self.backend.create_tenant_session(self.credentials) keystone = self.backend.create_keystone_client(session) self.assertIsNotNone(keystone.tenants.get(self.tenant_id)) with self.assertRaises(keystone_exceptions.NotFound): keystone.tenants.find(name='some_tenant') self.assertIsNotNone( keystone.tenants.create(tenant_name='some_tenant')) self.assertIsNotNone(keystone.tenants.find(name='some_tenant')) with self.assertRaises(keystone_exceptions.Conflict): keystone.tenants.create(tenant_name='test_tenant') user = keystone.users.create(name='joe_doe') role = keystone.roles.find(name='admin') tenant = keystone.tenants.get(self.tenant_id) user_role = keystone.roles.add_user_role(user=user.id, role=role.id, tenant=tenant.id) self.assertIs(user_role, role) with self.assertRaises(keystone_exceptions.ClientException): keystone.roles.add_user_role(user=user.id, role=role.id, tenant='xyz') with self.assertRaises(keystone_exceptions.NotFound): keystone.roles.add_user_role(user=user.id, role='xyz', tenant=tenant.id) def test_nova_quotas(self): session = self.backend.create_tenant_session(self.credentials) nova = self.backend.create_nova_client(session) nova.quotas.update(self.credentials['tenant_id'], ram=6789, cores=34) quota = nova.quotas.get(tenant_id=self.credentials['tenant_id']) self.assertEqual(quota.ram, 6789) self.assertEqual(quota.cores, 34) def test_nova_keypairs(self): session = self.backend.create_tenant_session(self.credentials) nova = self.backend.create_nova_client(session) test_key = { 'name': 'some_key', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw2MaqOkQi4LUJXVnIgmgWKCUnVdDF3IFngm+YS4cTT+6Wvc6C0g3QZYnSCiQd3lJLWsizYUlCILVQRAH9JUAt+iyrcxrY68boc0aejuMGpPXXaZ0+RTC6gKw7IzNbvkgpbY7DzB0dNuMYERLVM83SPABudGELk/kxEPvDO1J0RY5Is5QziebU18gWWwK87jmjRQfphM6lcS08Bd17U+4MAe/vCJbIJnI9ctoHLRczrGN0w/DtNJDAfao4yLa+PdStPNAxkBTHY/OWycbdEJRL+Ile73FkpcoVfWbbJcdrvvVSKWIZATyHmlnUSBLQe5WQg8F3ZF17G5bDFMnSueoH [email protected]', 'fingerprint': '1b:a8:73:34:57:80:5e:c8:e0:36:6a:b1:a8:62:ad:a3', } key = nova.keypairs.create(name=test_key['name'], public_key=test_key['public_key']) self.assertEqual(key.fingerprint, test_key['fingerprint']) self.assertIsNotNone( nova.keypairs.findall(fingerprint=test_key['fingerprint'])) nova.keypairs.delete(test_key['name']) with self.assertRaises(nova_exceptions.NotFound): nova.keypairs.get(test_key['name']) with self.assertRaises(nova_exceptions.NotFound): nova.keypairs.delete('another_key') with self.assertRaises(nova_exceptions.BadRequest): nova.keypairs.create(name=test_key['name'], public_key='My Secret Key') with self.assertRaises(nova_exceptions.BadRequest): nova.keypairs.create(name='joe@example', public_key=test_key['public_key']) def test_nova_security_groups(self): session = self.backend.create_tenant_session(self.credentials) nova = self.backend.create_nova_client(session) sg = nova.security_groups.create(name='jedis', description='') nova.security_groups.update(sg, name='siths', description='') nova.security_groups.get(group_id=sg.id) sgr = nova.security_group_rules.create(parent_group_id=sg.id, ip_protocol='tcp', from_port=81, to_port=82) self.assertEqual(sgr.to_port, 82) with self.assertRaises(nova_exceptions.Conflict): nova.security_group_rules.create(parent_group_id=sg.id, ip_protocol='TCP', from_port=81, to_port=82) sg = nova.security_groups.find(id=sg.id) self.assertEqual(sg.name, 'siths') nova.security_group_rules.delete(sgr.id) nova.security_groups.delete(sg.id) def test_nova_flavors(self): session = self.backend.create_tenant_session(self.credentials) nova = self.backend.create_nova_client(session) flavors = nova.flavors.findall(is_public=True) self.assertEqual(len(flavors), 5) self.assertIsNotNone(nova.flavors.get('3')) def test_nova_servers(self): session = self.backend.create_tenant_session(self.credentials) neutron = self.backend.create_neutron_client(session) cinder = self.backend.create_cinder_client(session) glance = self.backend.create_glance_client(session) nova = self.backend.create_nova_client(session) create_response = neutron.create_network({ 'networks': [{ 'name': 'test-net', 'tenant_id': self.credentials['tenant_id'] }] }) network_id = create_response['networks'][0]['id'] image = next(glance.images.list()) system_volume = cinder.volumes.create( size=100, display_name='test-system', display_description='', imageRef=image.id, ) data_volume = cinder.volumes.create( size=200, display_name='test-data', display_description='', ) group = nova.security_groups.create(name='test-group', description='') flavor = nova.flavors.get('3') server = nova.servers.create( name='test-instance', image=None, flavor=flavor, block_device_mapping_v2=[ { 'boot_index': 0, 'destination_type': 'volume', 'device_type': 'disk', 'source_type': 'volume', 'uuid': system_volume.id, 'delete_on_termination': True, }, { 'destination_type': 'volume', 'device_type': 'disk', 'source_type': 'volume', 'uuid': data_volume.id, 'delete_on_termination': True, }, ], nics=[{ 'net-id': network_id }], key_name='example_key', security_groups=[group.id], ) self.assertEqual(server.status, 'ACTIVE') sg = nova.servers.list_security_group(server.id)[0] self.assertEqual(sg, group) nova.servers.stop(server.id) self.assertEqual(server.status, 'SHUTOFF') nova.servers.start(server.id) self.assertEqual(server.status, 'ACTIVE') nova.servers.delete(server.id) stats = nova.hypervisors.statistics()._info self.assertEqual(stats['free_ram_mb'], 477) def test_glance(self): session = self.backend.create_tenant_session(self.credentials) glance = self.backend.create_glance_client(session) images = glance.images.list() self.assertIsInstance(images, types.GeneratorType) def test_neutron(self): session = self.backend.create_tenant_session(self.credentials) neutron = self.backend.create_neutron_client(session) response = neutron.create_network({ 'networks': [{ 'name': 'nc-f38a1bee66a5494c99bd123525b8ceb8', 'tenant_id': '1' }] }) self.assertEqual(response['networks'][0]['status'], 'ACTIVE') network_id = response['networks'][0]['id'] response = neutron.create_subnet({ 'subnets': [{ 'network_id': network_id, 'tenant_id': '2', 'name': '{0}-sn01'.format(network_id), 'cidr': '192.168.42.0/24', 'allocation_pools': [{ 'start': '192.168.42.10', 'end': '192.168.42.250' }], 'ip_version': 4, 'enable_dhcp': True }] }) subnet_id = response['subnets'][0]['id'] self.assertEqual(response['subnets'][0]['gateway_ip'], '0.0.0.0') router = neutron.create_router({'router': {'name': 'nc-router'}}) self.assertEqual(router['router']['name'], 'nc-router') response = neutron.list_routers() self.assertEqual(response['routers'][0]['name'], 'nc-router') network = neutron.show_network(network_id) self.assertEqual(subnet_id, network['network']['subnets'][0]) def test_cinder(self): session = self.backend.create_tenant_session(self.credentials) cinder = self.backend.create_cinder_client(session) glance = self.backend.create_glance_client(session) image = next(glance.images.list()) with self.assertRaises(cinder_exceptions.OverLimit): cinder.volumes.create(size=1024, display_name='test', imageRef=image.id) with self.assertRaises(cinder_exceptions.BadRequest): cinder.volumes.create(size=1000, display_name='test', imageRef='NULL') cinder.quotas.update(self.credentials['tenant_id'], gigabytes=3072) quota = cinder.quotas.get(tenant_id=self.credentials['tenant_id']) self.assertEqual(quota.gigabytes, 3072) volume = cinder.volumes.create(size=1024, display_name='test-system', display_description='', imageRef=image.id) self.assertEqual(volume.status, 'available') backup = cinder.backups.create(volume.id, name='test-backup', description='') self.assertEqual(backup.status, 'available') cinder.volumes.extend(volume, 512) self.assertEqual(cinder.volumes.get(volume.id).size, 512) cinder.restores.restore(backup.id) snapshot = cinder.volume_snapshots.create( volume.id, force=True, display_name='snapshot_from_volume_%s' % volume.id) self.assertEqual(snapshot.status, 'available') volume2 = cinder.volumes.create(768, snapshot_id=snapshot.id, display_name='test-two') self.assertEqual(volume2.snapshot_id, snapshot.id) self.assertEqual(volume2.size, 768) cinder.volumes.delete(volume.id) with self.assertRaises(cinder_exceptions.NotFound): cinder.volume_snapshots.get(snapshot.id)
def nova_server_resize_confirm(session, server_id): OpenStackBackend.create_nova_client(session).servers.confirm_resize( server_id)
def nova_wait_for_server_status(session, server_id, status): server = OpenStackBackend.create_nova_client(session).servers.get( server_id) return server.status == status
def openstack_create_session(**kwargs): return OpenStackBackend.create_session(**kwargs)
def nova_server_resize(session, server_id, flavor_id): OpenStackBackend.create_nova_client(session).servers.resize( server_id, flavor_id, 'MANUAL')
class OpenStackBackendMembershipApiTest(unittest.TestCase): def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.cinder_client = mock.Mock() self.membership = mock.Mock( ) # TODO: use real membership, not mocked and unite with test class below self.tenant = mock.Mock() # client methods: self.nova_quota = mock.Mock(cores=20, instances=10, ram=51200) self.nova_client.quotas.get = mock.Mock(return_value=self.nova_quota) self.cinder_quota = mock.Mock(gigabytes=1000) self.cinder_client.quotas.get = mock.Mock( return_value=self.cinder_quota) self.volumes = [mock.Mock(size=10 * i, id=i) for i in range(5)] self.snapshots = [mock.Mock(size=10 * i, id=i) for i in range(5)] self.flavors = [mock.Mock(ram=i, id=i, vcpus=i) for i in range(4)] self.instances = [mock.Mock(flavor={'id': i}) for i in range(2)] self.cinder_client.volume_snapshots.list = mock.Mock( return_value=self.snapshots) self.cinder_client.volumes.list = mock.Mock(return_value=self.volumes) self.nova_client.servers.list = mock.Mock(return_value=self.instances) self.nova_client.flavors.list = mock.Mock(return_value=self.flavors) # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock( return_value=self.neutron_client) self.backend.create_cinder_client = mock.Mock( return_value=self.cinder_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.backend.push_security_group = mock.Mock() self.backend.create_security_group = mock.Mock() self.backend.update_security_group = mock.Mock() self.backend.delete_security_group = mock.Mock() self.backend.push_security_group_rules = mock.Mock() self.backend.get_hypervisors_statistics = mock.Mock(return_value=[]) def test_push_membership_synchronizes_user(self): self.backend.push_membership(self.membership) self.backend.get_or_create_user.assert_called_once_with( self.membership, self.keystone_client) def test_push_membership_synchronizes_tenant(self): self.backend.push_membership(self.membership) self.backend.get_or_create_tenant.assert_called_once_with( self.membership, self.keystone_client) def test_push_membership_synchronizes_network(self): self.backend.push_membership(self.membership) self.backend.get_or_create_network.assert_called_once_with( self.membership, self.neutron_client) def test_push_membership_synchronizes_users_role_in_tenant(self): self.backend.push_membership(self.membership) self.backend.get_or_create_user.ensure_user_is_tenant_admin( 'john', self.tenant, self.keystone_client) def test_push_membership_updates_membership_with_backend_data(self): self.backend.push_membership(self.membership) self.assertEquals(self.membership.username, 'john') self.assertEquals(self.membership.password, 'doe') self.assertEquals(self.membership.tenant_id, self.tenant.id) self.membership.save.assert_called_once_with() def test_push_membership_raises_on_openstack_api_error(self): self.backend.create_session.side_effect = keystone_exceptions.AuthorizationFailure with self.assertRaises(CloudBackendError): self.backend.push_membership(self.membership) def test_get_resource_stats_gets_credentials_with_given_auth_url(self): auth_url = 'http://example.com/' self.backend.get_resource_stats(auth_url) self.backend.create_session.assert_called_once_with( keystone_url=auth_url, dummy=False) def test_get_resource_stats_raises_openstack_api_error(self): self.backend.create_nova_client.side_effect = keystone_exceptions.AuthorizationFailure auth_url = 'http://example.com/' with self.assertRaises(CloudBackendError): self.backend.get_resource_stats(auth_url) def test_pull_quota_resource_initiates_quota_parameters(self): membership = factories.CloudProjectMembershipFactory( tenant_id='test_backend_id') # when self.backend.pull_resource_quota(membership) # then self.assertEqual( membership.quotas.get(name='ram').limit, self.nova_quota.ram) self.assertEqual( membership.quotas.get(name='max_instances').limit, self.nova_quota.instances) self.assertEqual( membership.quotas.get(name='vcpu').limit, self.nova_quota.cores) self.assertEqual( membership.quotas.get(name='storage').limit, self.cinder_quota.gigabytes * 1024) def test_pull_quota_resource_calls_clients_quotas_gets_methods_with_membership_tenant_id( self): membership = factories.CloudProjectMembershipFactory( tenant_id='test_backend_id') # when self.backend.pull_resource_quota(membership) # then self.nova_client.quotas.get.assert_called_once_with( tenant_id=membership.tenant_id) self.cinder_client.quotas.get.assert_called_once_with( tenant_id=membership.tenant_id) def test_pull_quota_resource_rewrite_old_resource_quota_data(self): membership = factories.CloudProjectMembershipFactory( tenant_id='test_backend_id') # when self.backend.pull_resource_quota(membership) # then self.assertEqual( membership.quotas.get(name='max_instances').limit, self.nova_quota.instances) def test_pull_quota_resource_usage_initiates_quota_parameters(self): membership = factories.CloudProjectMembershipFactory() # when self.backend.pull_resource_quota_usage(membership) # then instance_flavors = [ f for f in self.flavors if f.id in [i.flavor['id'] for i in self.instances] ] self.assertEqual( membership.quotas.get(name='ram').usage, sum([f.ram for f in instance_flavors])) self.assertEqual( membership.quotas.get(name='max_instances').usage, len(self.instances)) self.assertEqual( membership.quotas.get(name='vcpu').usage, sum([f.vcpus for f in instance_flavors])) self.assertEqual( membership.quotas.get(name='storage').usage, sum([int(v.size * 1024) for v in self.volumes + self.snapshots])) def test_pull_quota_resource_usage_rewrite_old_resource_quota_usage_data( self): membership = factories.CloudProjectMembershipFactory() # when self.backend.pull_resource_quota_usage(membership) # then self.assertEqual( membership.quotas.get(name='max_instances').usage, len(self.instances))
def wrapped(tracked_session, *args, **kwargs): session = OpenStackBackend.recover_session(tracked_session) session.validate() task_fn(session, *args, **kwargs) return session
def setUp(self): self.backend = OpenStackBackend()
class OpenStackBackendHelperApiTest(unittest.TestCase): def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.membership = mock.Mock() self.membership.project.uuid.hex = 'project_uuid' self.membership.project.name = 'project_name' self.membership.project.description = 'project_description' self.backend = OpenStackBackend() # get_or_create_tenant tests def test_get_or_create_tenant_creates_tenant_with_proper_arguments(self): created_tenant = object() self.keystone_client.tenants.create.return_value = created_tenant tenant = self.backend.get_or_create_tenant(self.membership, self.keystone_client) self.keystone_client.tenants.create.assert_called_once_with( tenant_name='nc-project_uuid', description='project_description', ) self.assertEquals(tenant, created_tenant, 'Created tenant not returned') def test_get_or_create_tenant_looks_up_existing_tenant_if_creation_fails_due_to_conflict( self): existing_tenant = object() self.keystone_client.tenants.create.side_effect = keystone_exceptions.Conflict self.keystone_client.tenants.find.return_value = existing_tenant tenant = self.backend.get_or_create_tenant(self.membership, self.keystone_client) self.keystone_client.tenants.find.assert_called_once_with( name='nc-project_uuid', ) self.assertEquals(tenant, existing_tenant, 'Looked up tenant not returned') def test_get_or_create_tenant_raises_if_both_creation_and_lookup_failed( self): self.keystone_client.tenants.create.side_effect = keystone_exceptions.Conflict self.keystone_client.tenants.find.side_effect = keystone_exceptions.NotFound with self.assertRaises(keystone_exceptions.ClientException): self.backend.get_or_create_tenant(self.membership, self.keystone_client) # get_or_create_user tests def test_get_or_create_user_creates_user_if_membership_was_never_synchronized_before( self): # This is a brand new membership that was never synchronized self.membership.username = '' username, password = self.backend.get_or_create_user( self.membership, self.keystone_client) self.assertEqual(self.keystone_client.users.create.call_count, 1, 'tenant.users.create() must be called exactly once') call_kwargs = self.keystone_client.users.create.call_args[1] call_username = call_kwargs.get('name') call_password = call_kwargs.get('password') # Check created username matches returned ones self.assertEqual((call_username, call_password), ( username, password ), 'Credentials used for account creation do not match the ones returned' ) self.assertTrue(username.endswith('-{0}'.format('project_name')), 'Username should contain project name') self.assertTrue(password, 'Password should not be empty') def test_get_or_create_user_returns_existing_credentials_if_they_are_valid( self): # This is a membership that was synchronized before self.membership.username = '******' self.membership.password = '******' # Pretend we can log in using existing credentials self.backend.create_session = mock.Mock() username, password = self.backend.get_or_create_user( self.membership, self.keystone_client) self.assertFalse(self.keystone_client.called, 'Keystone must not be accessed') self.assertEqual( ('my_user', 'my_pass'), (username, password), 'Credentials do not match the ones stored in membership') def test_get_or_create_user_creates_user_with_the_username_if_existing_credentials_are_invalid( self): # This is a membership that was synchronized before... self.membership.username = '******' self.membership.password = '******' # ... but they became stale self.backend.create_session = mock.Mock( side_effect=keystone_exceptions.AuthorizationFailure) username, password = self.backend.get_or_create_user( self.membership, self.keystone_client) self.assertEqual(self.keystone_client.users.create.call_count, 1, 'tenant.users.create() must be called exactly once') call_kwargs = self.keystone_client.users.create.call_args[1] call_username = call_kwargs.get('name') call_password = call_kwargs.get('password') # Check created username matches returned ones self.assertEqual(call_username, 'my_user-project_name', 'Existing username should have been used') self.assertEqual((call_username, call_password), ( username, password ), 'Credentials used for account creation do not match the ones returned' ) self.assertTrue(username.endswith('-{0}'.format('project_name')), 'Username should contain project name') self.assertTrue(password, 'Password should not be empty')
class OpenStackBackendInstanceApiTest(TransactionTestCase): def setUp(self): self.nova_client = mock.Mock() self.nova_client.servers.list.return_value = [] self.nova_client.servers.findall.return_value = [] self.membership = factories.CloudProjectMembershipFactory() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock(return_value=mock.Mock( dummy=False)) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) # XXX: import only the 1st data volume, sort by device name # Backend query tests def test_pull_instances_filters_out_instances_booted_from_image(self): self.when() self.nova_client.servers.findall.assert_called_once_with(image='', ) # Deletion tests def test_pull_instances_errs_stable_instances_missing_in_backend(self): # Given membership_params = self._get_membership_params() for state in Instance.States.STABLE_STATES: factories.InstanceFactory(state=state, **membership_params) self.when() # Then instances = Instance.objects.filter(**membership_params) self.assertTrue( all([i.state == Instance.States.ERRED for i in instances]), 'Instances should have been set to erred state') def test_pull_instances_doesnt_delete_unstable_instances_missing_in_backend( self): # Given membership_params = self._get_membership_params() for state in Instance.States.UNSTABLE_STATES: factories.InstanceFactory(state=state, **membership_params) # When self.when() # Then expected_instance_count = len(Instance.States.UNSTABLE_STATES) actual_instance_count = Instance.objects.filter( **membership_params).count() self.assertEqual( expected_instance_count, actual_instance_count, 'No instances should have been deleted from the database') def test_floating_ip_is_released_after_instance_deletion(self): instance = factories.InstanceFactory(state=Instance.States.OFFLINE) factories.FloatingIPFactory( cloud_project_membership=instance.cloud_project_membership, address=instance.external_ips, status='ACTIVE') self.backend._wait_for_instance_deletion = mock.Mock(return_value=True) self.backend.delete_instance(instance) floating_ip = FloatingIP.objects.get( cloud_project_membership=instance.cloud_project_membership, address=instance.external_ips) self.assertEqual(floating_ip.status, 'DOWN') # Helper methods def given_minimal_importable_instance(self): # Create a flavor flavor = NovaFlavor(next_unique_flavor_id(), 'id1', 3, 5, 8) # from novaclient.v1_1.servers import Server as NovaServer # Create a server # server = mock.Mock(spec_set=NovaServer) server = mock.Mock() server.id = 'server-uuid-1' server.name = 'name-1' server.flavor = { 'id': flavor.id, 'links': [{ 'href': 'http://example.com/TENANT-ID-1/flavors/%s' % flavor.id, 'rel': 'bookmark', }] } server.status = 'ACTIVE' server.image = '' # Mock volume fetches # Mock flavor fetches # Mock server fetches self.nova_client.servers.findall.return_value = [server] self.nova_client.servers.find.return_value = server def when(self): self.backend.pull_instances(self.membership) def _get_membership_params(self): return dict( # XXX: Should we introduce ProjectMember mixin? cloud_project_membership=self.membership, )
class OpenStackBackendFloatingIPTest(TransactionTestCase): def setUp(self): self.keystone_client = mock.Mock() self.nova_client = mock.Mock() self.neutron_client = mock.Mock() self.cloud_account = mock.Mock() self.membership = factories.CloudProjectMembershipFactory() self.tenant = mock.Mock() # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_keystone_client = mock.Mock( return_value=self.keystone_client) self.backend.create_nova_client = mock.Mock( return_value=self.nova_client) self.backend.create_neutron_client = mock.Mock( return_value=self.neutron_client) self.backend.get_or_create_tenant = mock.Mock(return_value=self.tenant) self.backend.get_or_create_user = mock.Mock(return_value=('john', 'doe')) self.backend.get_or_create_network = mock.Mock() self.backend.ensure_user_is_tenant_admin = mock.Mock() self.floating_ips = [ { 'status': 'ACTIVE', 'floating_ip_address': '10.7.201.163', 'id': '063795b7-23ac-4a0d-82f0-4326e73ee1bc', 'port_id': 'fakeport' }, { 'status': 'DOWN', 'floating_ip_address': '10.7.201.114', 'id': '063795b7-23ac-4a0d-82f0-432as73asdas', 'port_id': 'fakeport' }, { 'status': 'ACTIVE', 'floating_ip_address': '10.7.201.107', 'id': '063795b7-asds-aq34-3df4-23asdasddssc', 'port_id': 'fakeport' }, ] self.backend.get_floating_ips = mock.Mock( return_value=self.floating_ips) def test_pull_floating_ips_deletes_staled_ips(self): staled_ip = factories.FloatingIPFactory( backend_id='qqqq', cloud_project_membership=self.membership) # when self.backend.pull_floating_ips(self.membership) # then self.assertFalse( FloatingIP.objects.filter(id=staled_ip.id).exists(), 'Staled floating ip should be deleted') def test_pull_floating_ips_creates_new_ips(self): # when self.backend.pull_floating_ips(self.membership) # then for ip in self.floating_ips: self.assertTrue( FloatingIP.objects.filter(backend_id=ip['id']).exists(), 'Unexisted floating ip should be created') self.assertEqual def test_pull_floating_ips_updates_existing_ips(self): backend_ip = self.floating_ips[0] nc_floating_ip = factories.FloatingIPFactory( backend_id=backend_ip['id'], cloud_project_membership=self.membership) # when self.backend.pull_floating_ips(self.membership) # then reread_ip = FloatingIP.objects.get(id=nc_floating_ip.id) backend_ip = self.floating_ips[0] self.assertEqual(reread_ip.address, backend_ip['floating_ip_address']) self.assertEqual(reread_ip.status, backend_ip['status']) self.assertEqual(reread_ip.backend_id, backend_ip['id'])
class OpenStackBackendImageApiTest(TransactionTestCase): def setUp(self): self.glance_client = mock.Mock() # C # ^ # | # (I0) # | # v # T0 T1 T2 # ^ ^ ^ # | \ | \ | # | \ | \ | # | \ | \ | # v v v v v # TM0 TM1 TM2 TM3 TM4 # self.cloud_account = factories.CloudFactory() self.templates = factories.TemplateFactory.create_batch(3) self.template_mappings = ( factories.TemplateMappingFactory.create_batch( 2, template=self.templates[0]) + factories.TemplateMappingFactory.create_batch( 2, template=self.templates[1]) + factories.TemplateMappingFactory.create_batch( 1, template=self.templates[2])) self.image = factories.ImageFactory( cloud=self.cloud_account, template=self.template_mappings[0].template, backend_id=self.template_mappings[0].backend_image_id, ) # Mock low level non-AbstractCloudBackend api methods self.backend = OpenStackBackend() self.backend.create_session = mock.Mock() self.backend.create_glance_client = mock.Mock( return_value=self.glance_client) def test_pulling_creates_images_for_all_matching_template_mappings(self): # Given matching_mapping1 = self.template_mappings[2] image_id = matching_mapping1.backend_image_id new_image = GlanceImage(image_id, is_public=True, deleted=False) # Make another mapping use the same backend id matching_mapping2 = self.template_mappings[4] matching_mapping2.backend_image_id = image_id matching_mapping2.save() self.glance_client.images.list.return_value = iter([ new_image, ]) # When self.backend.pull_images(self.cloud_account) # Then image_count = self.cloud_account.images.filter( backend_id=new_image.id, ).count() self.assertEqual(2, image_count, 'Two images should have been created') try: self.cloud_account.images.get( backend_id=matching_mapping1.backend_image_id, template=matching_mapping1.template, ) except Image.DoesNotExist: self.fail('Image for the first matching template mapping' ' should have been created') try: self.cloud_account.images.get( backend_id=matching_mapping2.backend_image_id, template=matching_mapping2.template, ) except Image.DoesNotExist: self.fail('Image for the second matching template mapping' ' should have been created') def test_pulling_doesnt_create_images_missing_in_database_if_template_mapping_doesnt_exist( self): # Given non_matching_image = GlanceImage('not-mapped-id', is_public=True, deleted=False) self.glance_client.images.list.return_value = iter([ non_matching_image, ]) # When self.backend.pull_images(self.cloud_account) # Then image_exists = self.cloud_account.images.filter( backend_id=non_matching_image.id, ).exists() self.assertFalse(image_exists, 'Image should not have been created in the database') def test_pulling_doesnt_create_images_for_non_public_backend_images(self): # Given matching_mapping = self.template_mappings[2] image_id = matching_mapping.backend_image_id new_image = GlanceImage(image_id, is_public=False, deleted=False) self.glance_client.images.list.return_value = iter([ new_image, ]) # When self.backend.pull_images(self.cloud_account) # Then image_exists = self.cloud_account.images.filter( backend_id=new_image.id, ).exists() self.assertFalse(image_exists, 'Image should not have been created in the database') def test_pulling_doesnt_create_images_for_deleted_backend_images(self): # Given matching_mapping = self.template_mappings[2] image_id = matching_mapping.backend_image_id new_image = GlanceImage(image_id, is_public=True, deleted=True) self.glance_client.images.list.return_value = iter([ new_image, ]) # When self.backend.pull_images(self.cloud_account) # Then image_exists = self.cloud_account.images.filter( backend_id=new_image.id, ).exists() self.assertFalse(image_exists, 'Image should not have been created in the database') def test_pulling_does_not_create_image_if_backend_image_ids_collide(self): # Given matching_mapping1 = self.template_mappings[2] new_image1 = GlanceImage(matching_mapping1.backend_image_id, is_public=True, deleted=False) # Make another mapping use the same backend id matching_mapping2 = self.template_mappings[3] new_image2 = GlanceImage(matching_mapping2.backend_image_id, is_public=True, deleted=False) self.glance_client.images.list.return_value = iter([ new_image1, new_image2, ]) # When self.backend.pull_images(self.cloud_account) # Then images_exist = self.cloud_account.images.filter( template=self.templates[1]).exists() self.assertFalse(images_exist, 'No images should have been created') def test_pulling_deletes_existing_image_if_template_mapping_doesnt_exist( self): # Given non_matching_image = GlanceImage('not-mapped-id', is_public=True, deleted=False) self.glance_client.images.list.return_value = iter([ non_matching_image, ]) # When self.backend.pull_images(self.cloud_account) # Then matching_mapping = self.template_mappings[0] image_exists = self.cloud_account.images.filter( backend_id=matching_mapping.backend_image_id, template=matching_mapping.template, ).exists() self.assertFalse(image_exists, 'Image should have been deleted') def test_pulling_updates_existing_images_backend_id_if_template_mapping_changed( self): # Given # Simulate MO updating the mapping matching_mapping = self.template_mappings[0] image_id = 'new-id' matching_mapping.backend_image_id = image_id matching_mapping.save() existing_image = GlanceImage(image_id, is_public=True, deleted=False) self.glance_client.images.list.return_value = iter([ existing_image, ]) # When self.backend.pull_images(self.cloud_account) # Then try: self.cloud_account.images.get( backend_id=matching_mapping.backend_image_id, template=matching_mapping.template, ) except Image.DoesNotExist: self.fail("Image's backend_id should have been updated")