Пример #1
0
    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()
Пример #2
0
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')
Пример #3
0
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()
Пример #5
0
    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)
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
0
    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()
Пример #9
0
    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)
Пример #10
0
    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)
Пример #11
0
    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=[])
Пример #12
0
 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)
Пример #13
0
    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)
Пример #14
0
    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)
Пример #15
0
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)
Пример #16
0
    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
Пример #17
0
    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)
Пример #18
0
    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)
Пример #19
0
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)
Пример #20
0
def nova_server_resize_confirm(session, server_id):
    OpenStackBackend.create_nova_client(session).servers.confirm_resize(
        server_id)
Пример #21
0
def nova_wait_for_server_status(session, server_id, status):
    server = OpenStackBackend.create_nova_client(session).servers.get(
        server_id)
    return server.status == status
Пример #22
0
def openstack_create_session(**kwargs):
    return OpenStackBackend.create_session(**kwargs)
Пример #23
0
def nova_server_resize(session, server_id, flavor_id):
    OpenStackBackend.create_nova_client(session).servers.resize(
        server_id, flavor_id, 'MANUAL')
Пример #24
0
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))
Пример #25
0
 def wrapped(tracked_session, *args, **kwargs):
     session = OpenStackBackend.recover_session(tracked_session)
     session.validate()
     task_fn(session, *args, **kwargs)
     return session
Пример #26
0
 def setUp(self):
     self.backend = OpenStackBackend()
Пример #27
0
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')
Пример #28
0
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, )
Пример #29
0
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'])
Пример #30
0
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")