Пример #1
0
    def test_create_volume_number_over_alloted_quota(self):
        usage_limit = {
            "maxTotalVolumeGigabytes": 100,
            "gigabytesUsed": 20,
            "volumesUsed": len(self.cinder_volumes.list()),
            "maxTotalVolumes": len(self.cinder_volumes.list()),
        }
        formData = {
            "name": u"Too Many...",
            "description": u"We have no volumes left!",
            "method": u"CreateForm",
            "size": 10,
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).AndReturn(self.volume_types.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).AndReturn(usage_limit)
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volume_snapshots.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False, False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False, False])
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volumes.list())
        cinder.extension_supported(IsA(http.HttpRequest), "AvailabilityZones").AndReturn(True)
        cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(self.cinder_availability_zones.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).AndReturn(usage_limit)

        self.mox.ReplayAll()

        url = reverse("horizon:project:volumes:volumes:create")
        res = self.client.post(url, formData)

        expected_error = [u"You are already using all of your available" " volumes."]
        self.assertEqual(res.context["form"].errors["__all__"], expected_error)
Пример #2
0
    def test_index(self):
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).AndReturn(self.cinder_volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts={
                             'all_tenants': True}) \
                       .AndReturn([self.servers.list(), False])
        cinder.volume_type_list(IsA(http.HttpRequest)).\
                               AndReturn(self.volume_types.list())
        keystone.tenant_list(IsA(http.HttpRequest)) \
                .AndReturn([self.tenants.list(), False])

        cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volume_snapshots.list())
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volumes.list())
        keystone.tenant_list(IsA(http.HttpRequest)). \
            AndReturn([self.tenants.list(), False])

        self.mox.ReplayAll()

        res = self.client.get(reverse('horizon:admin:volumes:index'))

        self.assertTemplateUsed(res, 'admin/volumes/index.html')
        volumes = res.context['volumes_table'].data

        self.assertItemsEqual(volumes, self.cinder_volumes.list())
Пример #3
0
    def test_delete_volume(self):
        volumes = self.cinder_volumes.list()
        volume = self.cinder_volumes.first()
        formData = {'action':
                    'volumes__delete__%s' % volume.id}

        cinder.volume_backup_supported(IsA(http.HttpRequest)). \
            MultipleTimes().AndReturn(True)
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
            AndReturn(volumes)
        cinder.volume_delete(IsA(http.HttpRequest), volume.id)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
            AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
            AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
            AndReturn([self.servers.list(), False])
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).MultipleTimes().\
            AndReturn(self.cinder_limits['absolute'])

        self.mox.ReplayAll()

        url = VOLUME_INDEX_URL
        res = self.client.post(url, formData, follow=True)
        self.assertIn("Scheduled deletion of Volume: Volume name",
                      [m.message for m in res.context['messages']])
Пример #4
0
    def test_create_button_disabled_when_quota_exceeded(self):
        quota_usages = self.quota_usages.first()
        quota_usages['volumes']['available'] = 0
        volumes = self.cinder_volumes.list()

        cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn([self.servers.list(), False])
        cinder.volume_snapshot_list(IsA(http.HttpRequest))\
              .AndReturn(self.cinder_volume_snapshots.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
        quotas.tenant_quota_usages(IsA(http.HttpRequest))\
              .MultipleTimes().AndReturn(quota_usages)

        self.mox.ReplayAll()

        res = self.client.get(VOLUME_INDEX_URL)
        self.assertTemplateUsed(res, 'project/volumes/index.html')

        volumes = res.context['volumes_table'].data
        self.assertItemsEqual(volumes, self.cinder_volumes.list())

        create_link = tables.CreateVolume()
        url = create_link.get_link_url()
        classes = list(create_link.get_default_classes())\
                    + list(create_link.classes)
        link_name = "%s (%s)" % (unicode(create_link.verbose_name),
                                 "Quota exceeded")
        expected_string = "<a href='%s' title='%s'  class='%s disabled' "\
                          "id='volumes__action_create'>%s</a>" \
                            % (url, link_name, " ".join(classes), link_name)
        self.assertContains(res, expected_string, html=True,
                            msg_prefix="The create button is not disabled")
Пример #5
0
    def test_snapshot_tab(self):
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn([self.servers.list(), False])
        cinder.volume_type_list(IsA(http.HttpRequest)).\
            AndReturn(self.volume_types.list())
        keystone.tenant_list(IsA(http.HttpRequest)). \
            AndReturn([self.tenants.list(), False])

        cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}). \
            AndReturn(self.cinder_volume_snapshots.list())
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volumes.list())
        keystone.tenant_list(IsA(http.HttpRequest)). \
            AndReturn([self.tenants.list(), False])
        self.mox.ReplayAll()

        res = self.client.get(reverse('horizon:admin:volumes:snapshots_tab'))
        self.assertEqual(res.status_code, 200)
        self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
Пример #6
0
    def test_delete_volume_error_existing_snapshot(self):
        volume = self.volumes.first()
        formData = {'action':
                    'volumes__delete__%s' % volume.id}
        exc = self.exceptions.cinder.__class__(400,
                                               "error: dependent snapshots")

        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(self.volumes.list())
        cinder.volume_delete(IsA(http.HttpRequest), volume.id).\
                             AndRaise(exc)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(self.volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).MultipleTimes().\
                                   AndReturn(self.quota_usages.first())

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:index')
        res = self.client.post(url, formData, follow=True)
        self.assertMessageCount(res, error=1)
        self.assertEqual(list(res.context['messages'])[0].message,
                         u'Unable to delete volume "%s". '
                         u'One or more snapshots depend on it.' %
                         volume.display_name)
Пример #7
0
    def _test_encryption(self, encryption):
        volumes = self.volumes.list()
        for volume in volumes:
            volume.encrypted = encryption
        quota_usages = self.quota_usages.first()

        cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
            .MultipleTimes().AndReturn(self.volumes.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn([])
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
                .AndReturn([self.servers.list(), False])
        quotas.tenant_quota_usages(IsA(http.HttpRequest))\
              .MultipleTimes().AndReturn(quota_usages)

        self.mox.ReplayAll()

        res = self.client.get(VOLUME_INDEX_URL)
        rows = res.context['volumes_table'].get_rows()

        if encryption:
            column_value = 'Yes'
        else:
            column_value = 'No'

        for row in rows:
            self.assertEqual(row.cells['encryption'].data, column_value)
Пример #8
0
    def test_tenant_quota_usages(self):
        quotas.is_service_enabled(IsA(http.HttpRequest),
                                  'volume').AndReturn(True)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
                .AndReturn(self.quotas.first())
        api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
                .AndReturn(self.floating_ips.list())
        api.nova.server_list(IsA(http.HttpRequest)) \
                .AndReturn(self.servers.list())
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = {
            'injected_file_content_bytes': {'quota': 1},
            'metadata_items': {'quota': 1},
            'injected_files': {'quota': 1},
            'gigabytes': {'available': 920, 'used': 80, 'quota': 1000},
            'ram': {'available': 8976, 'used': 1024, 'quota': 10000},
            'floating_ips': {'available': 0, 'used': 2, 'quota': 1},
            'instances': {'available': 8, 'used': 2, 'quota': 10},
            'volumes': {'available': 0, 'used': 3, 'quota': 1},
            'cores': {'available': 8, 'used': 2, 'quota': 10}
        }

        # Compare internal structure of usages to expected.
        self.assertEquals(quota_usages.usages, expected_output)
Пример #9
0
    def test_launch_flavorlist_error(self):
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest), tenant_id=self.tenant.id, shared=False).AndReturn(
            self.networks.list()[:1]
        )
        api.quantum.network_list(IsA(http.HttpRequest), shared=True).AndReturn(self.networks.list()[1:])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(self.quota_usages.first())
        api.nova.flavor_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
        api.nova.flavor_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
        api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)).AndReturn(self.security_groups.list())

        self.mox.ReplayAll()

        url = reverse("horizon:project:instances:launch")
        res = self.client.get(url)

        self.assertTemplateUsed(res, "project/instances/launch.html")
Пример #10
0
    def test_launch_form_keystone_exception(self):
        flavor = self.flavors.first()
        image = self.images.first()
        keypair = self.keypairs.first()
        server = self.servers.first()
        sec_group = self.security_groups.first()
        customization_script = "userData"
        nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ""}]

        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
        api.nova.keypair_list(IgnoreArg()).AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)).AndReturn(self.security_groups.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest), tenant_id=self.tenant.id, shared=False).AndReturn(
            self.networks.list()[:1]
        )
        api.quantum.network_list(IsA(http.HttpRequest), shared=True).AndReturn(self.networks.list()[1:])
        cinder.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
        api.nova.server_create(
            IsA(http.HttpRequest),
            server.name,
            image.id,
            flavor.id,
            keypair.name,
            customization_script,
            [sec_group.name],
            None,
            nics=nics,
            instance_count=IsA(int),
            admin_pass="******",
        ).AndRaise(self.exceptions.keystone)

        self.mox.ReplayAll()

        form_data = {
            "flavor": flavor.id,
            "source_type": "image_id",
            "image_id": image.id,
            "keypair": keypair.name,
            "name": server.name,
            "customization_script": customization_script,
            "project_id": self.tenants.first().id,
            "user_id": self.user.id,
            "groups": sec_group.name,
            "volume_type": "",
            "network": self.networks.first().id,
            "count": 1,
            "admin_pass": "******",
            "confirm_admin_pass": "******",
        }
        url = reverse("horizon:project:instances:launch")
        res = self.client.post(url, form_data)

        self.assertRedirectsNoFollow(res, INDEX_URL)
Пример #11
0
    def test_delete_volume_error_existing_snapshot(self):
        volume = self.cinder_volumes.first()
        volumes = self.cinder_volumes.list()
        formData = {'action':
                    'volumes__delete__%s' % volume.id}
        exc = self.exceptions.cinder.__class__(400,
                                               "error: dependent snapshots")

        cinder.volume_backup_supported(IsA(http.HttpRequest)). \
            MultipleTimes().AndReturn(True)
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(volumes)
        cinder.volume_delete(IsA(http.HttpRequest), volume.id).\
                             AndRaise(exc)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).MultipleTimes().\
                                   AndReturn(self.cinder_limits['absolute'])
        self.mox.ReplayAll()

        url = VOLUME_INDEX_URL
        res = self.client.post(url, formData, follow=True)
        self.assertEqual(list(res.context['messages'])[0].message,
                         u'Unable to delete volume "%s". '
                         u'One or more snapshots depend on it.' %
                         volume.name)
Пример #12
0
    def test_tenant_quota_usages(self):
        quotas.is_service_enabled(IsA(http.HttpRequest), "volume").AndReturn(True)
        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), "1").AndReturn(self.quotas.first())
        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)).AndReturn(self.floating_ips.list())
        api.nova.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), "1").AndReturn(self.quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = {
            "injected_file_content_bytes": {"quota": 1},
            "metadata_items": {"quota": 1},
            "injected_files": {"quota": 1},
            "gigabytes": {"available": 920, "used": 80, "quota": 1000},
            "ram": {"available": 8976, "used": 1024, "quota": 10000},
            "floating_ips": {"available": 0, "used": 2, "quota": 1},
            "instances": {"available": 8, "used": 2, "quota": 10},
            "volumes": {"available": 0, "used": 3, "quota": 1},
            "cores": {"available": 8, "used": 2, "quota": 10},
        }

        # Compare internal structure of usages to expected.
        self.assertEquals(quota_usages.usages, expected_output)
Пример #13
0
    def test_tenant_quota_usages_neutron_fip_disabled(self):
        servers = [s for s in self.servers.list()
                   if s.tenant_id == self.request.user.tenant_id]

        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'volume').AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'network').AndReturn(False)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
            .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.quotas.first())
        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
            .AndReturn(False)
        search_opts = {'tenant_id': self.request.user.tenant_id}
        api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts,
                             all_tenants=True) \
            .AndReturn([servers, False])
        opts = {'all_tenants': 1, 'project_id': self.request.user.tenant_id}
        cinder.volume_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.cinder_volume_snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()
        expected_output['floating_ips']['used'] = 0
        expected_output['floating_ips']['available'] = 1

        # Compare internal structure of usages to expected.
        self.assertItemsEqual(expected_output, quota_usages.usages)
Пример #14
0
    def test_tenant_quota_usages_unlimited_quota(self):
        inf_quota = self.quotas.first()
        inf_quota['ram'] = -1
        servers = [s for s in self.servers.list()
                   if s.tenant_id == self.request.user.tenant_id]

        api.base.is_service_enabled(IsA(http.HttpRequest),
                                  'volume').AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                  'network').AndReturn(False)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
                .AndReturn(inf_quota)
        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
                .AndReturn(self.floating_ips.list())
        api.nova.server_list(IsA(http.HttpRequest)) \
                .AndReturn([servers, False])
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
                .AndReturn(self.snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()
        expected_output.update({'ram': {'available': float("inf"),
                                        'used': 1024,
                                        'quota': float("inf")}})

        # Compare internal structure of usages to expected.
        self.assertEquals(quota_usages.usages, expected_output)
Пример #15
0
    def _test_encryption(self, encryption):
        volumes = self.volumes.list()
        for volume in volumes:
            volume.encrypted = encryption
        limits = self.cinder_limits['absolute']

        cinder.volume_backup_supported(IsA(http.HttpRequest))\
            .MultipleTimes('backup_supported').AndReturn(False)
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
            .AndReturn(self.volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
            .AndReturn([self.servers.list(), False])
        cinder.tenant_absolute_limits(IsA(http.HttpRequest))\
            .MultipleTimes('limits').AndReturn(limits)

        self.mox.ReplayAll()

        res = self.client.get(VOLUME_INDEX_URL)
        rows = res.context['volumes_table'].get_rows()

        if encryption:
            column_value = 'Yes'
        else:
            column_value = 'No'

        for row in rows:
            self.assertEqual(row.cells['encryption'].data, column_value)
Пример #16
0
    def test_tenant_quota_usages(self):
        servers = [s for s in self.servers.list()
                   if s.tenant_id == self.request.user.tenant_id]

        api.base.is_service_enabled(IsA(http.HttpRequest),
                                  'volume').AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                  'network').AndReturn(False)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
                .AndReturn(self.quotas.first())
        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
                .AndReturn(True)
        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
                .AndReturn(self.floating_ips.list())
        api.nova.server_list(IsA(http.HttpRequest)) \
                .AndReturn([servers, False])
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
                .AndReturn(self.snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()

        # Compare internal structure of usages to expected.
        self.assertEqual(expected_output, quota_usages.usages)
Пример #17
0
    def test_create_button_disabled_when_quota_exceeded(self):
        limits = self.cinder_limits['absolute']
        limits['totalVolumesUsed'] = limits['maxTotalVolumes']
        volumes = self.cinder_volumes.list()

        api.cinder.volume_backup_supported(IsA(http.HttpRequest)). \
            MultipleTimes().AndReturn(True)
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn([self.servers.list(), False])
        cinder.tenant_absolute_limits(IsA(http.HttpRequest))\
              .MultipleTimes().AndReturn(limits)
        self.mox.ReplayAll()

        res = self.client.get(VOLUME_INDEX_URL)
        self.assertTemplateUsed(res, 'project/volumes/index.html')

        volumes = res.context['volumes_table'].data
        self.assertItemsEqual(volumes, self.cinder_volumes.list())

        create_link = tables.CreateVolume()
        url = create_link.get_link_url()
        classes = list(create_link.get_default_classes())\
                    + list(create_link.classes)
        link_name = "%s (%s)" % (unicode(create_link.verbose_name),
                                 "Quota exceeded")
        expected_string = "<a href='%s' title='%s'  class='%s disabled' "\
            "id='volumes__action_create'  data-update-url=" \
            "'/project/volumes/?action=create&amp;table=volumes'> "\
            "<span class='glyphicon glyphicon-plus'></span>%s</a>" \
            % (url, link_name, " ".join(classes), link_name)
        self.assertContains(res, expected_string, html=True,
                            msg_prefix="The create button is not disabled")
Пример #18
0
    def test_create_volume_from_image_invalid_size(self):
        usage_limit = {'maxTotalVolumeGigabytes': 100,
                 'maxTotalVolumes': 6}
        image = self.images.first()
        formData = {'name': u'A Volume I Am Making',
                    'description': u'This is a volume I am making for a test.',
                    'method': u'CreateForm',
                    'size': 1, 'image_source': image.id}

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())
        api.glance.image_get(IsA(http.HttpRequest),
                             str(image.id)).AndReturn(image)
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:create')
        res = self.client.post("?".join([url,
                                         "image_id=" + str(image.id)]),
                               formData, follow=True)
        self.assertEqual(res.redirect_chain, [])
        self.assertFormError(res, 'form', None,
                             "The volume size cannot be less than the "
                             "image size (20.0 GB)")
Пример #19
0
    def test_select_default_keypair_if_only_one(self):
        keypair = self.keypairs.first()
        quota_usages = self.quota_usages.first()
        image = self.images.first()

        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest), tenant_id=self.tenant.id, shared=False).AndReturn(
            self.networks.list()[:1]
        )
        api.quantum.network_list(IsA(http.HttpRequest), shared=True).AndReturn(self.networks.list()[1:])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quota_usages)
        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn([keypair])
        api.nova.security_group_list(IsA(http.HttpRequest)).AndReturn(self.security_groups.list())

        self.mox.ReplayAll()

        url = reverse("horizon:project:instances:launch")
        res = self.client.get(url)
        self.assertContains(
            res,
            "<option selected='selected' value='%(key)s'>" "%(key)s</option>" % {"key": keypair.name},
            html=True,
            msg_prefix="The default keypair was not selected.",
        )
Пример #20
0
    def test_create_volume_gb_used_over_alloted_quota(self):
        usage_limit = {
            "maxTotalVolumeGigabytes": 100,
            "gigabytesUsed": 80,
            "volumesUsed": len(self.cinder_volumes.list()),
            "maxTotalVolumes": 6,
        }
        formData = {
            "name": u"This Volume Is Huge!",
            "description": u"This is a volume that is just too big!",
            "method": u"CreateForm",
            "size": 5000,
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).AndReturn(self.volume_types.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).AndReturn(usage_limit)
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volume_snapshots.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False, False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False, False])
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volumes.list())
        cinder.extension_supported(IsA(http.HttpRequest), "AvailabilityZones").AndReturn(True)
        cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(self.cinder_availability_zones.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).AndReturn(usage_limit)

        self.mox.ReplayAll()

        url = reverse("horizon:project:volumes:volumes:create")
        res = self.client.post(url, formData)

        expected_error = [u"A volume of 5000GB cannot be created as you only" " have 20GB of your quota available."]
        self.assertEqual(res.context["form"].errors["__all__"], expected_error)
Пример #21
0
    def test_launch_form_instance_count_error(self):
        flavor = self.flavors.first()
        image = self.images.first()
        keypair = self.keypairs.first()
        server = self.servers.first()
        volume = self.volumes.first()
        sec_group = self.security_groups.first()
        customization_script = 'user data'
        device_name = u'vda'
        volume_choice = "%s:vol" % volume.id

        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.keypair_list(IsA(http.HttpRequest)) \
                .AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)) \
                .AndReturn(self.security_groups.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 tenant_id=self.tenant.id,
                                 shared=False) \
                .AndReturn(self.networks.list()[:1])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 shared=True) \
                .AndReturn(self.networks.list()[1:])
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])

        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
                .AndReturn(self.quota_usages.first())

        self.mox.ReplayAll()

        form_data = {'flavor': flavor.id,
                     'source_type': 'image_id',
                     'image_id': image.id,
                     'keypair': keypair.name,
                     'name': server.name,
                     'customization_script': customization_script,
                     'project_id': self.tenants.first().id,
                     'user_id': self.user.id,
                     'groups': sec_group.name,
                     'volume_type': 'volume_id',
                     'volume_id': volume_choice,
                     'device_name': device_name,
                     'count': 0}
        url = reverse('horizon:project:instances:launch')
        res = self.client.post(url, form_data)

        self.assertContains(res, "greater than or equal to 1")
Пример #22
0
    def test_create_volume_from_image_dropdown(self):
        volume = self.cinder_volumes.first()
        usage_limit = {'maxTotalVolumeGigabytes': 200,
                       'gigabytesUsed': 20,
                       'volumesUsed': len(self.cinder_volumes.list()),
                       'maxTotalVolumes': 6}
        image = self.images.first()
        formData = {'name': u'A Volume I Am Making',
                    'description': u'This is a volume I am making for a test.',
                    'method': u'CreateForm',
                    'size': 30,
                    'type': '',
                    'volume_source_type': 'image_source',
                    'snapshot_source': self.cinder_volume_snapshots.first().id,
                    'image_source': image.id}

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
                                 AndReturn(self.cinder_volume_snapshots.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])
        cinder.volume_list(IsA(
            http.HttpRequest)).AndReturn(self.cinder_volumes.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)) \
                  .AndReturn(usage_limit)
        api.glance.image_get(IsA(http.HttpRequest),
                             str(image.id)).AndReturn(image)

        cinder.extension_supported(IsA(http.HttpRequest), 'AvailabilityZones')\
            .AndReturn(True)
        cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
            self.cinder_availability_zones.list())

        cinder.volume_create(IsA(http.HttpRequest),
                             formData['size'],
                             formData['name'],
                             formData['description'],
                             '',
                             metadata={},
                             snapshot_id=None,
                             image_id=image.id,
                             availability_zone=None,
                             source_volid=None).AndReturn(volume)

        self.mox.ReplayAll()

        # get image from dropdown list
        url = reverse('horizon:project:volumes:volumes:create')
        res = self.client.post(url, formData)

        redirect_url = VOLUME_VOLUMES_TAB_URL
        self.assertRedirectsNoFollow(res, redirect_url)
Пример #23
0
    def test_get_tenant_volume_usages_cinder_exception(self):
        cinder.volume_list(IsA(http.HttpRequest)) \
            .AndRaise(cinder.cinder_exception.ClientException('test'))
        exceptions.handle(IsA(http.HttpRequest),
                          _("Unable to retrieve volume limit information."))
        self.mox.ReplayAll()

        quotas._get_tenant_volume_usages(self.request, {}, set(), None)
Пример #24
0
    def test_create_volume_from_volume(self):
        volume = self.volumes.first()
        usage_limit = {'maxTotalVolumeGigabytes': 250,
                       'gigabytesUsed': 20,
                       'volumesUsed': len(self.volumes.list()),
                       'maxTotalVolumes': 6}

        formData = {'name': u'A copy of a volume',
                    'description': u'This is a volume I am making for a test.',
                    'method': u'CreateForm',
                    'size': 50,
                    'type': '',
                    'volume_source_type': 'volume_source',
                    'volume_source': volume.id}

        cinder.volume_list(IsA(http.HttpRequest)).\
                AndReturn(self.volumes.list())
        cinder.volume_type_list(IsA(http.HttpRequest)).\
                AndReturn(self.volume_types.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
                AndReturn(self.volume_snapshots.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
                AndReturn(usage_limit)

        cinder.volume_get(IsA(http.HttpRequest),
                          volume.id).AndReturn(self.volumes.first())
        cinder.extension_supported(IsA(http.HttpRequest),
                                   'AvailabilityZones').AndReturn(True)
        cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
            self.cinder_availability_zones.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])

        cinder.volume_create(IsA(http.HttpRequest),
                             formData['size'],
                             formData['name'],
                             formData['description'],
                             '',
                             metadata={},
                             snapshot_id=None,
                             image_id=None,
                             availability_zone=None,
                             source_volid=volume.id).AndReturn(volume)
        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:volumes:create')
        redirect_url = reverse('horizon:project:volumes:index')
        res = self.client.post(url, formData)
        self.assertNoFormErrors(res)
        self.assertMessageCount(info=1)
        self.assertRedirectsNoFollow(res, redirect_url)
Пример #25
0
    def test_launch_instance_post_no_images_available(self):
        flavor = self.flavors.first()
        keypair = self.keypairs.first()
        server = self.servers.first()
        volume = self.volumes.first()
        sec_group = self.security_groups.first()
        customization_script = "user data"
        device_name = u"vda"
        volume_choice = "%s:vol" % volume.id

        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn({})
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([[], False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest), tenant_id=self.tenant.id, shared=False).AndReturn(
            self.networks.list()[:1]
        )
        api.quantum.network_list(IsA(http.HttpRequest), shared=True).AndReturn(self.networks.list()[1:])
        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)).AndReturn(self.security_groups.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])

        self.mox.ReplayAll()

        form_data = {
            "flavor": flavor.id,
            "source_type": "image_id",
            "image_id": "",
            "keypair": keypair.name,
            "name": server.name,
            "customization_script": customization_script,
            "project_id": self.tenants.first().id,
            "user_id": self.user.id,
            "groups": sec_group.name,
            "volume_type": "volume_id",
            "volume_id": volume_choice,
            "device_name": device_name,
            "count": 1,
        }
        url = reverse("horizon:project:instances:launch")
        res = self.client.post(url, form_data)

        self.assertFormErrors(
            res,
            1,
            "There are no image sources available; "
            "you must first create an image before "
            "attempting to launch an instance.",
        )
        self.assertTemplateUsed(res, "project/instances/launch.html")
Пример #26
0
    def test_create_volume_from_image_dropdown(self):
        volume = self.cinder_volumes.first()
        usage_limit = {
            "maxTotalVolumeGigabytes": 200,
            "gigabytesUsed": 20,
            "volumesUsed": len(self.cinder_volumes.list()),
            "maxTotalVolumes": 6,
        }
        image = self.images.first()
        formData = {
            "name": u"A Volume I Am Making",
            "description": u"This is a volume I am making for a test.",
            "method": u"CreateForm",
            "size": 30,
            "type": "",
            "volume_source_type": "image_source",
            "snapshot_source": self.cinder_volume_snapshots.first().id,
            "image_source": image.id,
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).AndReturn(self.volume_types.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volume_snapshots.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False, False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False, False])
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.cinder_volumes.list())
        quotas.tenant_limit_usages(IsA(http.HttpRequest)).AndReturn(usage_limit)
        api.glance.image_get(IsA(http.HttpRequest), str(image.id)).AndReturn(image)

        cinder.extension_supported(IsA(http.HttpRequest), "AvailabilityZones").AndReturn(True)
        cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(self.cinder_availability_zones.list())

        cinder.volume_create(
            IsA(http.HttpRequest),
            formData["size"],
            formData["name"],
            formData["description"],
            "",
            metadata={},
            snapshot_id=None,
            image_id=image.id,
            availability_zone=None,
            source_volid=None,
        ).AndReturn(volume)

        self.mox.ReplayAll()

        # get image from dropdown list
        url = reverse("horizon:project:volumes:volumes:create")
        res = self.client.post(url, formData)

        redirect_url = VOLUME_VOLUMES_TAB_URL
        self.assertRedirectsNoFollow(res, redirect_url)
Пример #27
0
    def test_launch_instance_get(self):
        quota_usages = self.quota_usages.first()
        image = self.images.first()

        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                .AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 tenant_id=self.tenant.id,
                                 shared=False) \
                .AndReturn(self.networks.list()[:1])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 shared=True) \
                .AndReturn(self.networks.list()[1:])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
                .AndReturn(quota_usages)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.keypair_list(IsA(http.HttpRequest)) \
                .AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)) \
                                .AndReturn(self.security_groups.list())

        self.mox.ReplayAll()

        url = reverse('horizon:project:instances:launch')
        params = urlencode({"source_type": "image_id",
                            "source_id": image.id})
        res = self.client.get("%s?%s" % (url, params))

        workflow = res.context['workflow']
        self.assertTemplateUsed(res,
                        'project/instances/launch.html')
        self.assertEqual(res.context['workflow'].name, LaunchInstance.name)
        step = workflow.get_step("setinstancedetailsaction")
        self.assertEqual(step.action.initial['image_id'], image.id)
        self.assertQuerysetEqual(workflow.steps,
                            ['<SetInstanceDetails: setinstancedetailsaction>',
                             '<SetAccessControls: setaccesscontrolsaction>',
                             '<SetNetwork: setnetworkaction>',
                             '<VolumeOptions: volumeoptionsaction>',
                             '<PostCreationStep: customizeaction>'])
Пример #28
0
def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id):
    if 'volumes' not in disabled_quotas:
        if tenant_id:
            opts = {'all_tenants': 1, 'project_id': tenant_id}
            volumes = cinder.volume_list(request, opts)
            snapshots = cinder.volume_snapshot_list(request, opts)
        else:
            volumes = cinder.volume_list(request)
            snapshots = cinder.volume_snapshot_list(request)
        usages.tally('gigabytes', sum([int(v.size) for v in volumes]))
        usages.tally('volumes', len(volumes))
        usages.tally('snapshots', len(snapshots))
Пример #29
0
    def test_create_volume_encrypted(self):
        volume = self.volumes.first()
        volume_type = self.volume_types.first()
        usage_limit = {'maxTotalVolumeGigabytes': 250,
                 'gigabytesUsed': 20,
                 'maxTotalVolumes': 6}
        formData = {'name': u'An Encrypted Volume',
                    'description': u'This volume has metadata for encryption.',
                    'method': u'CreateForm',
                    'type': volume_type.name,
                    'size': 50,
                    'snapshot_source': '',
                    'encryption': u'LUKS'}

        # check normal operation with can_encrypt_volumes = true
        PREV = settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes']
        settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes'] = True

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volume_snapshots.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])
        cinder.volume_create(IsA(http.HttpRequest),
                             formData['size'],
                             formData['name'],
                             formData['description'],
                             formData['type'],
                             metadata={'encryption': formData['encryption']},
                             snapshot_id=None,
                             image_id=None).AndReturn(volume)

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:create')
        res = self.client.post(url, formData)

        redirect_url = reverse('horizon:project:volumes:index')
        self.assertRedirectsNoFollow(res, redirect_url)

        settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes'] = PREV
Пример #30
0
    def test_launch_form_instance_count_error(self):
        flavor = self.flavors.first()
        image = self.images.first()
        keypair = self.keypairs.first()
        server = self.servers.first()
        volume = self.volumes.first()
        sec_group = self.security_groups.first()
        customization_script = "user data"
        device_name = u"vda"
        volume_choice = "%s:vol" % volume.id

        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)).AndReturn(self.security_groups.list())
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"is_public": True, "status": "active"}
        ).AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(
            IsA(http.HttpRequest), filters={"property-owner_id": self.tenant.id, "status": "active"}
        ).AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest), tenant_id=self.tenant.id, shared=False).AndReturn(
            self.networks.list()[:1]
        )
        api.quantum.network_list(IsA(http.HttpRequest), shared=True).AndReturn(self.networks.list()[1:])
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])

        api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(self.quota_usages.first())

        self.mox.ReplayAll()

        form_data = {
            "flavor": flavor.id,
            "source_type": "image_id",
            "image_id": image.id,
            "keypair": keypair.name,
            "name": server.name,
            "customization_script": customization_script,
            "project_id": self.tenants.first().id,
            "user_id": self.user.id,
            "groups": sec_group.name,
            "volume_type": "volume_id",
            "volume_id": volume_choice,
            "device_name": device_name,
            "count": 0,
        }
        url = reverse("horizon:project:instances:launch")
        res = self.client.post(url, form_data)

        self.assertContains(res, "greater than or equal to 1")
Пример #31
0
    def test_index(self):
        cinder.volume_list(IsA(http.HttpRequest),
                           search_opts={
                               'all_tenants': True
                           }).AndReturn(self.cinder_volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest),
                                    search_opts={
                                        'all_tenants': True
                                    }).AndReturn([])
        api.nova.server_list(IsA(http.HttpRequest), search_opts={
                             'all_tenants': True}) \
            .AndReturn([self.servers.list(), False])
        keystone.tenant_list(IsA(http.HttpRequest)) \
            .AndReturn([self.tenants.list(), False])

        self.mox.ReplayAll()
        res = self.client.get(reverse('horizon:admin:volumes:index'))

        self.assertTemplateUsed(res, 'admin/volumes/index.html')
        volumes = res.context['volumes_table'].data
        self.assertItemsEqual(volumes, self.cinder_volumes.list())
Пример #32
0
    def test_delete_volume(self):
        volume = self.volumes.first()
        formData = {'action': 'volumes__delete__%s' % volume.id}
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(self.volumes.list())
        cinder.volume_delete(IsA(http.HttpRequest), volume.id)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(self.volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).MultipleTimes().\
                                   AndReturn(self.quota_usages.first())

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:index')
        res = self.client.post(url, formData, follow=True)
        self.assertIn("Scheduled deletion of Volume: Volume name",
                      [m.message for m in res.context['messages']])
Пример #33
0
    def _test_snapshots_index_paginated(self, marker, sort_dir, snapshots, url,
                                        has_more, has_prev):
        cinder.volume_snapshot_list_paged(
            IsA(http.HttpRequest), paginate=True, marker=marker,
            sort_dir=sort_dir, search_opts={'all_tenants': True}) \
            .AndReturn([snapshots, has_more, has_prev])
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volumes.list())
        keystone.tenant_list(IsA(http.HttpRequest)) \
            .AndReturn([self.tenants.list(), False])

        self.mox.ReplayAll()

        res = self.client.get(url)

        self.assertTemplateUsed(res, 'admin/volumes/index.html')
        self.assertEqual(res.status_code, 200)

        self.mox.UnsetStubs()
        return res
Пример #34
0
    def test_tenant_quota_usages_unlimited_quota(self):
        inf_quota = self.quotas.first()
        inf_quota['ram'] = -1
        servers = [s for s in self.servers.list()
                   if s.tenant_id == self.request.user.tenant_id]

        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'volume').AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'network').AndReturn(False)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
            .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(inf_quota)
        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
            .AndReturn(True)
        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
            .AndReturn(self.floating_ips.list())
        search_opts = {'tenant_id': self.request.user.tenant_id}
        api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts,
                             all_tenants=True) \
            .AndReturn([servers, False])
        opts = {'alltenants': 1, 'tenant_id': self.request.user.tenant_id}
        cinder.volume_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.cinder_volume_snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()
        expected_output.update({'ram': {'available': float("inf"),
                                        'used': 1024,
                                        'quota': float("inf")}})

        # Compare internal structure of usages to expected.
        self.assertItemsEqual(expected_output, quota_usages.usages)
Пример #35
0
    def test_delete_volume_error_existing_snapshot(self):
        volume = self.cinder_volumes.first()
        volumes = self.cinder_volumes.list()
        formData = {'action':
                    'volumes__delete__%s' % volume.id}
        exc = self.exceptions.cinder.__class__(400,
                                               "error: dependent snapshots")

        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(volumes)
        cinder.volume_delete(IsA(http.HttpRequest), volume.id).\
                             AndRaise(exc)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts=None).\
                           AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
                             AndReturn([self.servers.list(), False])
        cinder.volume_snapshot_list(IsA(http.HttpRequest))\
              .AndReturn(self.cinder_volume_snapshots.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
        quotas.tenant_quota_usages(IsA(http.HttpRequest)).MultipleTimes().\
                                   AndReturn(self.quota_usages.first())

        self.mox.ReplayAll()

        url = VOLUME_INDEX_URL
        res = self.client.post(url, formData, follow=True)
        self.assertEqual(list(res.context['messages'])[0].message,
                         u'Unable to delete volume "%s". '
                         u'One or more snapshots depend on it.' %
                         volume.name)
Пример #36
0
    def test_create_volume_gb_used_over_alloted_quota(self):
        usage_limit = {'maxTotalVolumeGigabytes': 100, 'maxTotalVolumes': 6}
        formData = {
            'name': u'This Volume Is Huge!',
            'description': u'This is a volume that is just too big!',
            'method': u'CreateForm',
            'size': 5000
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volume_snapshots.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:create')
        res = self.client.post(url, formData)

        expected_error = [
            u'A volume of 5000GB cannot be created as you only'
            ' have 20GB of your quota available.'
        ]
        self.assertEqual(res.context['form'].errors['__all__'], expected_error)
Пример #37
0
    def test_create_volume_from_image(self):
        volume = self.volumes.first()
        usage_limit = {'maxTotalVolumeGigabytes': 200, 'maxTotalVolumes': 6}
        image = self.images.first()
        formData = {
            'name': u'A Volume I Am Making',
            'description': u'This is a volume I am making for a test.',
            'method': u'CreateForm',
            'size': 40,
            'type': '',
            'image_source': image.id
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volumes.list())
        api.glance.image_get(IsA(http.HttpRequest),
                             str(image.id)).AndReturn(image)
        cinder.volume_create(IsA(http.HttpRequest),
                             formData['size'],
                             formData['name'],
                             formData['description'],
                             '',
                             metadata={},
                             snapshot_id=None,
                             image_id=image.id).\
                             AndReturn(volume)

        self.mox.ReplayAll()

        # get image from url
        url = reverse('horizon:project:volumes:create')
        res = self.client.post("?".join([url, "image_id=" + str(image.id)]),
                               formData)

        redirect_url = reverse('horizon:project:volumes:index')
        self.assertRedirectsNoFollow(res, redirect_url)
Пример #38
0
def tenant_quota_usages(request):
    # Get our quotas and construct our usage object.
    disabled_quotas = get_disabled_quotas(request)

    usages = QuotaUsage()
    for quota in get_tenant_quota_data(request,
                                       disabled_quotas=disabled_quotas):
        usages.add_quota(quota)

    # Get our usages.
    floating_ips = []
    try:
        if network.floating_ip_supported(request):
            floating_ips = network.tenant_floating_ip_list(request)
    except Exception:
        pass
    flavors = dict([(f.id, f) for f in nova.flavor_list(request)])
    instances, has_more = nova.server_list(request)
    # Fetch deleted flavors if necessary.
    missing_flavors = [
        instance.flavor['id'] for instance in instances
        if instance.flavor['id'] not in flavors
    ]
    for missing in missing_flavors:
        if missing not in flavors:
            try:
                flavors[missing] = nova.flavor_get(request, missing)
            except Exception:
                flavors[missing] = {}
                exceptions.handle(request, ignore=True)

    usages.tally('instances', len(instances))
    usages.tally('floating_ips', len(floating_ips))

    if 'volumes' not in disabled_quotas:
        volumes = cinder.volume_list(request)
        snapshots = cinder.volume_snapshot_list(request)
        usages.tally('gigabytes', sum([int(v.size) for v in volumes]))
        usages.tally('volumes', len(volumes))
        usages.tally('snapshots', len(snapshots))

    # Sum our usage based on the flavors of the instances.
    for flavor in [flavors[instance.flavor['id']] for instance in instances]:
        usages.tally('cores', getattr(flavor, 'vcpus', None))
        usages.tally('ram', getattr(flavor, 'ram', None))

    # Initialise the tally if no instances have been launched yet
    if len(instances) == 0:
        usages.tally('cores', 0)
        usages.tally('ram', 0)

    return usages
Пример #39
0
    def get_context_data(self, **kwargs):
        context = super(CreateView, self).get_context_data(**kwargs)
        try:
            context['usages'] = cinder.tenant_absolute_limits(self.request)
            volumes = cinder.volume_list(self.request)
            total_size = sum(
                [getattr(volume, 'size', 0) for volume in volumes])
            context['usages']['gigabytesUsed'] = total_size
            context['usages']['volumesUsed'] = len(volumes)

        except:
            exceptions.handle(self.request)
        return context
Пример #40
0
    def test_create_volume_cannot_encrypt(self):
        # check that widget is hidden if can_encrypt_volumes = false
        PREV = settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes']
        settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes'] = False

        usage_limit = {
            'maxTotalVolumeGigabytes': 250,
            'gigabytesUsed': 20,
            'maxTotalVolumes': 6
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volume_snapshots.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:create')
        res = self.client.get(url)

        # Assert the encryption field is hidden.
        form = res.context['form']
        self.assertTrue(
            isinstance(form.fields['encryption'].widget, widgets.HiddenInput))

        settings.OPENSTACK_HYPERVISOR_FEATURES['can_encrypt_volumes'] = PREV
Пример #41
0
def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id):
    if CINDER_QUOTA_FIELDS - disabled_quotas:
        try:
            if tenant_id:
                opts = {'all_tenants': 1, 'project_id': tenant_id}
                volumes = cinder.volume_list(request, opts)
                snapshots = cinder.volume_snapshot_list(request, opts)
            else:
                volumes = cinder.volume_list(request)
                snapshots = cinder.volume_snapshot_list(request)
            volume_usage = sum([int(v.size) for v in volumes])
            snapshot_usage = sum([int(s.size) for s in snapshots])
            _add_usage_if_quota_enabled(usages, 'gigabytes',
                                        (snapshot_usage + volume_usage),
                                        disabled_quotas)
            _add_usage_if_quota_enabled(usages, 'volumes', len(volumes),
                                        disabled_quotas)
            _add_usage_if_quota_enabled(usages, 'snapshots', len(snapshots),
                                        disabled_quotas)
        except cinder.cinder_exception.ClientException:
            msg = _("Unable to retrieve volume limit information.")
            exceptions.handle(request, msg)
Пример #42
0
 def populate_volume_id_choices(self, request, context):
     volume_options = [("", _("Select Volume"))]
     try:
         volumes = [
             v for v in cinder.volume_list(self.request)
             if v.status == api.cinder.VOLUME_STATE_AVAILABLE
         ]
         volume_options.extend(
             [self._get_volume_display_name(vol) for vol in volumes])
     except Exception:
         exceptions.handle(self.request,
                           _('Unable to retrieve list of volumes.'))
     return volume_options
Пример #43
0
 def get_volumes(self, request):
     volumes = []
     try:
         volume_list = cinder.volume_list(self.request)
         if volume_list is not None:
             volumes = [
                 v for v in volume_list
                 if v.status == api.cinder.VOLUME_STATE_AVAILABLE
             ]
     except Exception:
         exceptions.handle(request,
                           _('Unable to retrieve list of volumes.'))
     return volumes
Пример #44
0
    def test_tenant_quota_usages_neutron_fip_disabled(self):
        servers = [
            s for s in self.servers.list()
            if s.tenant_id == self.request.user.tenant_id
        ]

        cinder.is_volume_service_enabled(IsA(http.HttpRequest)).AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'network').AndReturn(False)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'compute').MultipleTimes().AndReturn(True)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
            .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.quotas.first())
        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
            .AndReturn(False)
        search_opts = {'tenant_id': self.request.user.tenant_id}
        api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts,
                             all_tenants=True) \
            .AndReturn([servers, False])
        opts = {'all_tenants': 1, 'project_id': self.request.user.tenant_id}
        cinder.volume_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.cinder_volume_snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()
        expected_output['floating_ips']['used'] = 0
        expected_output['floating_ips']['available'] = 1

        # Compare internal structure of usages to expected.
        self.assertItemsEqual(expected_output, quota_usages.usages)
Пример #45
0
    def test_tenant_quota_usages_with_id(self):
        tenant_id = 3
        cinder.is_volume_service_enabled(IsA(http.HttpRequest)).AndReturn(True)
        api.base.is_service_enabled(IsA(http.HttpRequest),
                                    'network').AndReturn(False)
        api.base.is_service_enabled(IsA(http.HttpRequest), 'compute') \
            .MultipleTimes().AndReturn(True)
        servers = [s for s in self.servers.list() if s.tenant_id == tenant_id]
        api.nova.flavor_list(IsA(http.HttpRequest)) \
            .AndReturn(self.flavors.list())
        opts = {'tenant_id': tenant_id,
                'all_tenants': True}
        api.nova.server_list(IsA(http.HttpRequest), search_opts=opts) \
            .AndReturn([servers, False])
        api.nova.tenant_quota_get(IsA(http.HttpRequest), tenant_id) \
            .AndReturn(self.quotas.first())

        opts = {'all_tenants': 1,
                'project_id': tenant_id}
        cinder.volume_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest), opts) \
            .AndReturn(self.cinder_volume_snapshots.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), tenant_id) \
            .AndReturn(self.cinder_quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request,
                                                  tenant_id=tenant_id)
        expected_output = self.get_usages(
            nova_quotas_enabled=True, with_volume=True,
            with_compute=True, tenant_id=tenant_id)

        # Compare internal structure of usages to expected.
        self.assertItemsEqual(expected_output, quota_usages.usages)
        # Compare available resources
        self.assertAvailableQuotasEqual(expected_output, quota_usages.usages)
Пример #46
0
    def test_launch_flavorlist_error(self):
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                                       filters={'is_public': True,
                                                'status': 'active'}) \
                  .AndReturn([self.images.list(), False])
        api.glance.image_list_detailed(IsA(http.HttpRequest),
                            filters={'property-owner_id': self.tenant.id,
                                     'status': 'active'}) \
                  .AndReturn([[], False])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 tenant_id=self.tenant.id,
                                 shared=False) \
                .AndReturn(self.networks.list()[:1])
        api.quantum.network_list(IsA(http.HttpRequest),
                                 shared=True) \
                .AndReturn(self.networks.list()[1:])
        quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
                .AndReturn(self.quota_usages.first())
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndRaise(self.exceptions.nova)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndRaise(self.exceptions.nova)
        api.nova.keypair_list(IsA(http.HttpRequest)) \
                .AndReturn(self.keypairs.list())
        api.nova.security_group_list(IsA(http.HttpRequest)) \
                .AndReturn(self.security_groups.list())

        self.mox.ReplayAll()

        url = reverse('horizon:project:instances:launch')
        res = self.client.get(url)

        self.assertTemplateUsed(res,
                        'project/instances/launch.html')
Пример #47
0
    def test_delete_volume_type(self):
        volume_type = self.volume_types.first()
        formData = {'action': 'volume_types__delete__%s' % volume_type.id}

        cinder.volume_list(IsA(http.HttpRequest), search_opts={
                           'all_tenants': True}).AndReturn(self.volumes.list())
        api.nova.server_list(IsA(http.HttpRequest), search_opts={
                             'all_tenants': True}) \
                         .AndReturn([self.servers.list(), False])
        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.volume_type_delete(IsA(http.HttpRequest),
                                  str(volume_type.id))
        keystone.tenant_list(IsA(http.HttpRequest)) \
                .AndReturn([self.tenants.list(), False])
        self.mox.ReplayAll()

        res = self.client.post(reverse('horizon:admin:volumes:index'),
                               formData)

        redirect = reverse('horizon:admin:volumes:index')
        self.assertNoFormErrors(res)
        self.assertRedirectsNoFollow(res, redirect)
Пример #48
0
    def test_tenant_quota_usages(self):
        quotas.is_service_enabled(IsA(http.HttpRequest),
                                  'volume').AndReturn(True)
        api.nova.flavor_list(IsA(http.HttpRequest)) \
                .AndReturn(self.flavors.list())
        api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
                .AndReturn(self.quotas.first())
        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
                .AndReturn(self.floating_ips.list())
        api.nova.server_list(IsA(http.HttpRequest)) \
                .AndReturn([self.servers.list(), False])
        cinder.volume_list(IsA(http.HttpRequest)) \
                .AndReturn(self.volumes.list())
        cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
            .AndReturn(self.quotas.first())

        self.mox.ReplayAll()

        quota_usages = quotas.tenant_quota_usages(self.request)
        expected_output = self.get_usages()

        # Compare internal structure of usages to expected.
        self.assertEquals(quota_usages.usages, expected_output)
Пример #49
0
 def populate_volume_id_choices(self, request, context):
     try:
         volumes = [self._get_volume_display_name(v)
                    for v in cinder.volume_list(self.request)
                    if v.status == api.cinder.VOLUME_STATE_AVAILABLE]
     except Exception:
         volumes = []
         exceptions.handle(self.request,
                           _('Unable to retrieve list of volumes.'))
     if volumes:
         volumes.insert(0, ("", _("Select Volume")))
     else:
         volumes.insert(0, ("", _("No volumes available.")))
     return volumes
Пример #50
0
    def test_snapshots_tab(self):
        cinder.volume_snapshot_list_paged(
            IsA(http.HttpRequest),
            paginate=True,
            marker=None,
            sort_dir='desc',
            search_opts={
                'all_tenants': True
            },
        ).AndReturn([self.cinder_volume_snapshots.list(), False, False])
        cinder.volume_list(IsA(http.HttpRequest), search_opts={
            'all_tenants': True}).\
            AndReturn(self.cinder_volumes.list())
        keystone.tenant_list(IsA(http.HttpRequest)). \
            AndReturn([self.tenants.list(), False])

        self.mox.ReplayAll()
        res = self.client.get(reverse('horizon:admin:volumes:snapshots_tab'))

        self.assertEqual(res.status_code, 200)
        self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
        snapshots = res.context['volume_snapshots_table'].data
        self.assertItemsEqual(snapshots, self.cinder_volume_snapshots.list())
Пример #51
0
    def __init__(self, request, *args, **kwargs):
        super(CreateSnapshotAdvanced, self).__init__(request, *args, **kwargs)

        instance_id = kwargs.get('initial', {}).get('instance_id', [])
        search_opts = {'status': 'in-use'}
        volumes = cinder.volume_list(self.request, search_opts)
        volumes = getfileteredvolume(instance_id, volumes)

        VOL_CHOICES = getVolumeList(volumes)
        #self.fields['volume_radio'] = forms.ChoiceField(widget=forms.RadioSelect(),
        #                                           choices=VOL_CHOICES,label="cloud disk")
        self.fields['volume_select'] = forms.ChoiceField(widget=forms.Select(),
                                                         choices=VOL_CHOICES,
                                                         label=_("cloud disk"))
Пример #52
0
    def test_create_volume_from_snapshot_invalid_size(self):
        usage_limit = {'maxTotalVolumeGigabytes': 100, 'maxTotalVolumes': 6}
        snapshot = self.volume_snapshots.first()
        formData = {
            'name': u'A Volume I Am Making',
            'description': u'This is a volume I am making for a test.',
            'method': u'CreateForm',
            'size': 20,
            'snapshot_source': snapshot.id
        }

        cinder.volume_type_list(IsA(http.HttpRequest)).\
                                AndReturn(self.volume_types.list())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volumes.list())
        cinder.volume_snapshot_get(IsA(http.HttpRequest),
                                   str(snapshot.id)).AndReturn(snapshot)
        cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
                          AndReturn(self.volumes.first())
        cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
                                AndReturn(usage_limit)
        cinder.volume_list(IsA(http.HttpRequest)).\
                                    AndReturn(self.volumes.list())

        self.mox.ReplayAll()

        url = reverse('horizon:project:volumes:create')
        res = self.client.post("?".join(
            [url, "snapshot_id=" + str(snapshot.id)]),
                               formData,
                               follow=True)
        self.assertEqual(res.redirect_chain, [])
        self.assertFormError(
            res, 'form', None, "The volume size cannot be less than the "
            "snapshot size (40GB)")
Пример #53
0
    def get_context_data(self, **kwargs):
        context = super(CreateView, self).get_context_data(**kwargs)
        try:
            context['usages'] = quotas.tenant_limit_usages(self.request)
            _volume_types = self._get_volume_types()
            _volumes = cinder.volume_list(self.request)
            _snapshots = cinder.volume_snapshot_list(self.request)

            volume_types = {}
            volume_type_size = {}

            for volume_type in _volume_types:
                if volume_type['name'] == 'no_type':
                    continue
                volume_type_size[volume_type['name']] = 0

            for volume in _volumes:
                volume_types[volume.id] = volume.volume_type
                volume_type_size[volume.volume_type] = (volume_type_size.get(
                    volume.volume_type) or 0) + volume.size

            for snapshot in cinder.volume_snapshot_list(self.request):
                volume_type_size[volume_types[snapshot.volume_id]] = (
                    volume_type_size.get(volume_types.get(snapshot.volume_id))
                    or 0) + snapshot.size

            tenant_quotas = {}
            for quota in cinder.tenant_quota_get(self.request,
                                                 self.request.user.tenant_id):
                if quota.name.startswith('gigabytes_'):
                    tenant_quotas[quota.name[10:]] = quota.limit

            volume_type_usage = []
            for volume_type, total_size in volume_type_size.iteritems():
                volume_type_usage.append({
                    'name':
                    volume_type,
                    'usage':
                    total_size,
                    'quota':
                    tenant_quotas.get(volume_type) or -1
                })

            context['usages']['volume_type'] = volume_type_usage
            context['volume_types'] = json.dumps(_volume_types)

        except Exception:
            exceptions.handle(self.request)
        return context
Пример #54
0
    def test_create_button_disabled_when_quota_exceeded(self):
        quota_usages = self.quota_usages.first()
        quota_usages['volumes']['available'] = 0
        volumes = self.volumes.list()

        cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn(volumes)
        api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
              .AndReturn([self.servers.list(), False])
        cinder.volume_snapshot_list(IsA(http.HttpRequest))\
              .AndReturn(self.volume_snapshots.list())
        cinder.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
        quotas.tenant_quota_usages(IsA(http.HttpRequest))\
              .MultipleTimes().AndReturn(quota_usages)

        self.mox.ReplayAll()

        res = self.client.get(reverse('horizon:project:volumes:index'))
        self.assertTemplateUsed(res, 'project/volumes/index.html')

        volumes = res.context['volumes_table'].data
        self.assertItemsEqual(volumes, self.volumes.list())

        create_link = tables.CreateVolume()
        url = create_link.get_link_url()
        classes = list(create_link.get_default_classes())\
                    + list(create_link.classes)
        link_name = "%s (%s)" % (unicode(
            create_link.verbose_name), "Quota exceeded")
        expected_string = "<a href='%s' title='%s'  class='%s disabled' "\
                          "id='volumes__action_create'>%s</a>" \
                            % (url, link_name, " ".join(classes), link_name)
        self.assertContains(res,
                            expected_string,
                            html=True,
                            msg_prefix="The create button is not disabled")
Пример #55
0
    def test_detail_view(self):
        cg_snapshot = self.cinder_cg_snapshots.first()
        cgroup = self.cinder_consistencygroups.first()
        volume_type = self.cinder_volume_types.first()
        volumes = self.cinder_volumes.list()

        cinder.volume_cg_snapshot_get(IsA(http.HttpRequest), cg_snapshot.id).\
            AndReturn(cg_snapshot)
        cinder.volume_cgroup_get(IsA(http.HttpRequest), cgroup.id).\
            AndReturn(cgroup)
        cinder.volume_type_get(IsA(http.HttpRequest), volume_type.id).\
            MultipleTimes().AndReturn(volume_type)
        search_opts = {'consistencygroup_id': cgroup.id}
        cinder.volume_list(IsA(http.HttpRequest), search_opts=search_opts).\
            AndReturn(volumes)

        self.mox.ReplayAll()

        url = reverse(
            'horizon:project:cg_snapshots:cg_snapshot_detail',
            args=[cg_snapshot.id])
        res = self.client.get(url)
        self.assertNoFormErrors(res)
        self.assertEqual(res.status_code, 200)
Пример #56
0
    def handle(self, request, context):
        cgroup_id = context['cgroup_id']
        add_vols = []
        remove_vols = []
        try:
            selected_volumes = context['volumes']
            volumes = cinder.volume_list(request)

            # scan all volumes and make correct consistency group is set
            for volume in volumes:
                selected = False
                for selection in selected_volumes:
                    if selection == volume.id:
                        selected = True
                        break

                if selected:
                    # ensure this volume is in this consistency group
                    if hasattr(volume, 'consistencygroup_id'):
                        if volume.consistencygroup_id != cgroup_id:
                            add_vols.append(volume.id)
                    else:
                        add_vols.append(volume.id)
                else:
                    # ensure this volume is not in our consistency group
                    if hasattr(volume, 'consistencygroup_id'):
                        if volume.consistencygroup_id == cgroup_id:
                            # remove from this CG
                            remove_vols.append(volume.id)

            add_vols_str = ",".join(add_vols)
            remove_vols_str = ",".join(remove_vols)

            if not add_vols_str and not remove_vols_str:
                # nothing to change
                return True

            cinder.volume_cgroup_update(request,
                                        cgroup_id,
                                        name=context['name'],
                                        add_vols=add_vols_str,
                                        remove_vols=remove_vols_str)

        except Exception:
            # error message supplied by form
            return False

        return True
Пример #57
0
 def populate_volume_id_choices(self, request, context):
     volumes = []
     try:
         if cinder.is_volume_service_enabled(request):
             available = api.cinder.VOLUME_STATE_AVAILABLE
             volumes = [self._get_volume_display_name(v)
                        for v in cinder.volume_list(self.request,
                        search_opts=dict(status=available, bootable=True))]
     except Exception:
         exceptions.handle(self.request,
                           _('Unable to retrieve list of volumes.'))
     if volumes:
         volumes.insert(0, ("", _("Select Volume")))
     else:
         volumes.insert(0, ("", _("No volumes available")))
     return volumes
Пример #58
0
    def _verify_changes(self, request, cgroup_id, add_vols, remove_vols):
        search_opts = {'consistencygroup_id': cgroup_id}
        done = False
        while not done:
            done = True
            volumes = cinder.volume_list(request, search_opts=search_opts)
            assigned_vols = []
            for volume in volumes:
                assigned_vols.append(volume.id)

            for add_vol in add_vols:
                if add_vol not in assigned_vols:
                    done = False

            for remove_vol in remove_vols:
                if remove_vol in assigned_vols:
                    done = False
Пример #59
0
 def populate_volume_id_choices(self, request, context):
     volumes = []
     try:
         if base.is_service_enabled(request, 'volume'):
             volumes = [
                 self._get_volume_display_name(v)
                 for v in cinder.volume_list(self.request)
                 if (v.status == api.cinder.VOLUME_STATE_AVAILABLE
                     and v.bootable == 'true')
             ]
     except Exception:
         exceptions.handle(self.request,
                           _('Unable to retrieve list of volumes.'))
     if volumes:
         volumes.insert(0, ("", _("Select Volume")))
     else:
         volumes.insert(0, ("", _("No volumes available")))
     return volumes
Пример #60
0
    def get_data(self):
        snapshots = []
        volumes = {}
        needs_gs = False
        if cinder.is_volume_service_enabled(self.request):
            try:
                marker, sort_dir = self._get_marker()
                snapshots, self._has_more_data, self._has_prev_data = \
                    cinder.volume_snapshot_list_paged(
                        self.request, paginate=True, marker=marker,
                        sort_dir=sort_dir)
            except Exception:
                exceptions.handle(self.request,
                                  _("Unable to retrieve volume snapshots."))
            try:
                volumes = cinder.volume_list(self.request)
                volumes = dict((v.id, v) for v in volumes)
            except Exception:
                exceptions.handle(self.request,
                                  _("Unable to retrieve volumes."))
            needs_gs = any(
                getattr(snapshot, 'group_snapshot_id', None)
                for snapshot in snapshots)
            if needs_gs:
                try:
                    group_snapshots = cinder.group_snapshot_list(self.request)
                    group_snapshots = dict(
                        (gs.id, gs) for gs in group_snapshots)
                except Exception:
                    group_snapshots = {}
                    exceptions.handle(self.request,
                                      _("Unable to retrieve group snapshots."))

        for snapshot in snapshots:
            volume = volumes.get(snapshot.volume_id)
            setattr(snapshot, '_volume', volume)
            if needs_gs:
                group_snapshot = group_snapshots.get(
                    snapshot.group_snapshot_id)
                snapshot.group_snapshot = group_snapshot
            else:
                snapshot.group_snapshot = None

        return snapshots