def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id): if 'volumes' not in 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) if is_m1_user_admin(request): volumes = get_volume_list(request, opts) snapshots = get_volume_snapshot_list(request, opts) else: 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) if is_m1_user_admin(request): volumes = get_volume_list(request) snapshots = get_volume_snapshot_list(request) 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)) except cinder.ClientException: msg = _("Unable to retrieve volume limit information.") exceptions.handle(request, msg)
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)
def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id, region=None): if 'volumes' not in disabled_quotas: if tenant_id: opts = {'all_tenants': 1} volumes = cinder.volume_list(request, opts, region=region) snapshots = cinder.volume_snapshot_list(request, opts, region=region) volumes = filter( lambda v: v.to_dict()['os-vol-tenant-attr:tenant_id'] == tenant_id, volumes) snapshots = filter( lambda s: s.to_dict()[ 'os-extended-snapshot-attributes:project_id'] == tenant_id, snapshots) else: volumes = cinder.volume_list(request) snapshots = cinder.volume_snapshot_list(request) # all_size = sum([int(v.size) for v in volumes]) + sum([int(s.size) for s in snapshots]) volume_size = sum([int(v.size) for v in volumes]) snapshot_size = sum([int(s.size) for s in snapshots]) usages.tally('volume_gigabytes', volume_size) usages.tally('snapshot_gigabytes', snapshot_size) usages.tally('volumes', len(volumes)) usages.tally('snapshots', len(snapshots))
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)
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.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.assertEquals(quota_usages.usages, expected_output)
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")
def test_create_volume_number_over_alloted_quota(self): usage_limit = {'maxTotalVolumeGigabytes': 100, 'gigabytesUsed': 20, 'volumesUsed': len(self.volumes.list()), 'maxTotalVolumes': len(self.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.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]) quotas.tenant_limit_usages(IsA(http.HttpRequest)).\ AndReturn(usage_limit) self.mox.ReplayAll() url = reverse('horizon:project: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)
def test_create_volume_gb_used_over_alloted_quota(self): usage_limit = {'maxTotalVolumeGigabytes': 100, 'gigabytesUsed': 80, 'volumesUsed': len(self.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.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]) quotas.tenant_limit_usages(IsA(http.HttpRequest)).\ AndReturn(usage_limit) 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)
def test_create_volume_from_image_dropdown(self): volume = self.volumes.first() usage_limit = { 'maxTotalVolumeGigabytes': 200, 'gigabytesUsed': 20, 'volumesUsed': len(self.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.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.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]) 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).AndReturn(volume) self.mox.ReplayAll() # get image from dropdown list url = reverse('horizon:project:volumes:create') res = self.client.post(url, formData) redirect_url = reverse('horizon:project:volumes:index') self.assertRedirectsNoFollow(res, redirect_url)
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)
def test_delete_volume(self): volumes = self.cinder_volumes.list() volume = self.cinder_volumes.first() formData = {'action': 'volumes__delete__%s' % volume.id} 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_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.cinder_volume_snapshots.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_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.assertIn("Scheduled deletion of Volume: Volume name", [m.message for m in res.context['messages']])
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)
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")
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())
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')
def _test_index(self, instanceless_volumes=False): volumes = self.cinder_volumes.list() if instanceless_volumes: for volume in volumes: volume.attachments = [] cinder.volume_list_paged(IsA(http.HttpRequest), sort_dir="desc", marker=None, paginate=True, search_opts={'all_tenants': True})\ .AndReturn([volumes, False, False]) cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={ 'all_tenants': True }).AndReturn([]) if not instanceless_volumes: 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(INDEX_URL) self.assertTemplateUsed(res, 'admin/volumes/index.html') volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, self.cinder_volumes.list())
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)
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)
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")
def test_create_volume_gb_used_over_alloted_quota(self): usage = {'gigabytes': {'available': 100, 'used': 20}} 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_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) cinder.volume_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_snapshots.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) 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 100GB of your quota available.' ] self.assertEqual(res.context['form'].errors['__all__'], expected_error)
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.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ .AndReturn(False) api.nova.server_list(IsA(http.HttpRequest)).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)
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)
def test_create_volume_number_over_alloted_quota(self): usage = { 'gigabytes': { 'available': 100, 'used': 20 }, 'volumes': { 'available': 0 } } 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_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) cinder.volume_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_snapshots.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) self.mox.ReplayAll() url = reverse('horizon:project: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)
def test_create_volume(self): volume = self.volumes.first() volume_type = self.volume_types.first() usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 6}} formData = { 'name': u'A Volume I Am Making', 'description': u'This is a volume I am making for a test.', 'method': u'CreateForm', 'type': volume_type.name, 'size': 50, 'snapshot_source': '' } cinder.volume_type_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_types.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) cinder.volume_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_snapshots.list()) cinder.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], formData['type'], metadata={}, snapshot_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)
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)
def test_create_volume(self): volume = self.volumes.first() volume_type = self.volume_types.first() usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 6}} formData = {'name': u'A Volume I Am Making', 'description': u'This is a volume I am making for a test.', 'method': u'CreateForm', 'type': volume_type.name, 'size': 50, 'snapshot_source': ''} cinder.volume_type_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_types.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) cinder.volume_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_snapshots.list()) cinder.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], formData['type'], metadata={}, snapshot_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)
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.", )
def _test_index(self, instanceless_volumes=False): volumes = self.cinder_volumes.list() if instanceless_volumes: for volume in volumes: volume.attachments = [] cinder.volume_list_paged(IsA(http.HttpRequest), sort_dir="desc", marker=None, paginate=True, search_opts={'all_tenants': True})\ .AndReturn([volumes, False, False]) cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={ 'all_tenants': True}).AndReturn([]) if not instanceless_volumes: 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(INDEX_URL) self.assertTemplateUsed(res, 'admin/volumes/index.html') volumes = res.context['volumes_table'].data self.assertItemsEqual(volumes, self.cinder_volumes.list())
def test_create_volume_from_snapshot(self): volume = self.volumes.first() usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 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': 50, 'type': '', 'snapshot_source': snapshot.id} # first call- with url param cinder.volume_type_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_types.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) 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.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], '', snapshot_id=snapshot.id).\ AndReturn(volume) # second call- with dropdown cinder.volume_type_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_types.list()) quotas.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage) cinder.volume_snapshot_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_snapshots.list()) cinder.volume_snapshot_get(IsA(http.HttpRequest), str(snapshot.id)).AndReturn(snapshot) cinder.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], '', snapshot_id=snapshot.id).\ AndReturn(volume) self.mox.ReplayAll() # get snapshot from url url = reverse('horizon:project:volumes:create') res = self.client.post("?".join([url, "snapshot_id=" + str(snapshot.id)]), formData) redirect_url = reverse('horizon:project:volumes:index') self.assertRedirectsNoFollow(res, redirect_url) # get snapshot from dropdown list url = reverse('horizon:project:volumes:create') res = self.client.post(url, formData) redirect_url = reverse('horizon:project:volumes:index') self.assertRedirectsNoFollow(res, redirect_url)
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)
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
def _test_tenant_quota_usages(self, nova_quotas_enabled=True, with_compute=True, with_volume=True): cinder.is_volume_service_enabled(IsA( http.HttpRequest)).AndReturn(with_volume) api.base.is_service_enabled(IsA(http.HttpRequest), 'network').AndReturn(False) api.base.is_service_enabled( IsA(http.HttpRequest), 'compute').MultipleTimes().AndReturn(with_compute) if with_compute: servers = [ s for s in self.servers.list() if s.tenant_id == self.request.user.tenant_id ] api.nova.flavor_list(IsA(http.HttpRequest)) \ .AndReturn(self.flavors.list()) 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]) if nova_quotas_enabled: api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \ .AndReturn(self.quotas.first()) if with_volume: 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( nova_quotas_enabled=nova_quotas_enabled, with_volume=with_volume, with_compute=with_compute) # Compare internal structure of usages to expected. self.assertItemsEqual(expected_output, quota_usages.usages) # Compare available resources self.assertAvailableQuotasEqual(expected_output, quota_usages.usages)
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)
def test_create_volume(self): volume = self.cinder_volumes.first() volume_type = self.volume_types.first() az = self.cinder_availability_zones.first().zoneName usage_limit = {'maxTotalVolumeGigabytes': 250, 'gigabytesUsed': 20, 'volumesUsed': len(self.cinder_volumes.list()), 'maxTotalVolumes': 6} formData = {'name': u'A Volume I Am Making', 'description': u'This is a volume I am making for a test.', 'method': u'CreateForm', 'type': volume_type.name, 'size': 50, 'snapshot_source': '', 'availability_zone': az} 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]) api.glance.image_list_detailed(IsA(http.HttpRequest), filters={'property-owner_id': self.tenant.id, 'status': 'active'}) \ .AndReturn([[], False]) cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn( self.cinder_availability_zones.list()) cinder.extension_supported(IsA(http.HttpRequest), 'AvailabilityZones')\ .AndReturn(True) cinder.volume_list(IsA( http.HttpRequest)).AndReturn(self.cinder_volumes.list()) cinder.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], formData['type'], metadata={}, snapshot_id=None, image_id=None, availability_zone=formData['availability_zone'], source_volid=None)\ .AndReturn(volume) self.mox.ReplayAll() url = reverse('horizon:project:volumes:volumes:create') res = self.client.post(url, formData) redirect_url = VOLUME_VOLUMES_TAB_URL self.assertRedirectsNoFollow(res, redirect_url)
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)
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")
def test_create_volume_cannot_encrypt(self): volume = self.volumes.first() volume_type = self.volume_types.first() usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 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 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 volume = self.volumes.first() volume_type = self.volume_types.first() 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
def get_context_data(self, **kwargs): context = super(ExtendView, self).get_context_data(**kwargs) context['volume'] = self.get_object() args = (self.kwargs['volume_id'], ) context['submit_url'] = reverse(self.submit_url, args=args) 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) print "#" * 120 print context return context
def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id): if 'volumes' not in disabled_quotas: if tenant_id: opts = {'alltenants': 1, 'tenant_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))
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))
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>'])
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
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")
def test_create_volume_cannot_encrypt(self): volume = self.volumes.first() volume_type = self.volume_types.first() usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 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 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 volume = self.volumes.first() volume_type = self.volume_types.first() 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
def _test_tenant_quota_usages(self, nova_quotas_enabled=True, with_compute=True, with_volume=True): cinder.is_volume_service_enabled(IsA(http.HttpRequest)).AndReturn( with_volume) api.base.is_service_enabled(IsA(http.HttpRequest), 'network').AndReturn(False) api.base.is_service_enabled( IsA(http.HttpRequest), 'compute' ).MultipleTimes().AndReturn(with_compute) if with_compute: servers = [s for s in self.servers.list() if s.tenant_id == self.request.user.tenant_id] api.nova.flavor_list(IsA(http.HttpRequest)) \ .AndReturn(self.flavors.list()) 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]) if nova_quotas_enabled: api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \ .AndReturn(self.quotas.first()) if with_volume: 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( nova_quotas_enabled=nova_quotas_enabled, with_volume=with_volume, with_compute=with_compute) # Compare internal structure of usages to expected. self.assertItemsEqual(expected_output, quota_usages.usages) # Compare available resources self.assertAvailableQuotasEqual(expected_output, quota_usages.usages)
def _test_tenant_quota_usages_with_target(self, targets, use_compute_call=True, use_flavor_list=False, use_cinder_call=False): 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) if use_compute_call: servers = [ s for s in self.servers.list() if s.tenant_id == self.request.user.tenant_id ] if use_flavor_list: api.nova.flavor_list(IsA(http.HttpRequest)) \ .AndReturn(self.flavors.list()) search_opts = {'tenant_id': self.request.user.tenant_id} api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ .AndReturn([servers, False]) api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \ .AndReturn(self.quotas.first()) if use_cinder_call: 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, targets=targets) expected = self.get_usages() expected = dict((k, v) for k, v in expected.items() if k in targets) # Compare internal structure of usages to expected. self.assertItemsEqual(expected, quota_usages.usages) # Compare available resources self.assertAvailableQuotasEqual(expected, quota_usages.usages)
def test_create_volume_from_snapshot_dropdown(self): volume = self.volumes.first() usage_limit = {'maxTotalVolumeGigabytes': 250, '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': 50, 'type': '', 'volume_source_type': 'snapshot_source', 'snapshot_source': snapshot.id } cinder.volume_type_list(IsA(http.HttpRequest)).\ AndReturn(self.volume_types.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()) cinder.volume_snapshot_get(IsA(http.HttpRequest), str(snapshot.id)).AndReturn(snapshot) cinder.volume_create(IsA(http.HttpRequest), formData['size'], formData['name'], formData['description'], '', metadata={}, snapshot_id=snapshot.id, image_id=None).\ AndReturn(volume) self.mox.ReplayAll() # get snapshot from dropdown list url = reverse('horizon:project:volumes:create') res = self.client.post(url, formData) redirect_url = reverse('horizon:project:volumes:index') self.assertRedirectsNoFollow(res, redirect_url)
def tenant_limit_usages(request): # TODO(licostan): This method shall be removed from Quota module. # ProjectUsage/BaseUsage maybe used instead on volume/image dashboards. limits = {} try: limits.update(nova.tenant_absolute_limits(request)) except Exception: msg = _("Unable to retrieve compute limit information.") exceptions.handle(request, msg) if base.is_service_enabled(request, 'volume'): try: limits.update(cinder.tenant_absolute_limits(request)) volumes = cinder.volume_list(request) snapshots = cinder.volume_snapshot_list(request) total_size = sum([getattr(volume, 'size', 0) for volume in volumes]) limits['gigabytesUsed'] = total_size limits['volumesUsed'] = len(volumes) limits['snapshotsUsed'] = len(snapshots) except Exception: msg = _("Unable to retrieve volume limit information.") exceptions.handle(request, msg) return limits
def update(self, request, **kwargs): """This widget allows selection of Volumes and Volume Snapshots""" available = {'status': cinder.VOLUME_STATE_AVAILABLE} try: choices = [(volume.id, volume.name) for volume in cinder.volume_list(request, search_opts=available)] except Exception: choices = [] exceptions.handle(request, _("Unable to retrieve volume list.")) if self.include_snapshots: try: choices.extend((snap.id, snap.name) for snap in cinder.volume_snapshot_list( request, search_opts=available)) except Exception: exceptions.handle(request, _("Unable to retrieve snapshot list.")) if choices: choices.sort(key=lambda e: e[1]) choices.insert(0, ("", _("Select volume"))) else: choices.insert(0, ("", _("No volumes available"))) self.choices = choices
def populate_volume_snapshot_id_choices(self, request, context): snapshots = [] try: if cinder.is_volume_service_enabled(request): available = api.cinder.VOLUME_STATE_AVAILABLE volumes = [ v.id for v in cinder.volume_list( self.request, search_opts=dict(bootable=True)) ] snapshots = [ self._get_volume_display_name(s) for s in cinder.volume_snapshot_list( self.request, search_opts=dict(status=available)) if s.volume_id in volumes ] except Exception: exceptions.handle( self.request, _('Unable to retrieve list of volume ' 'snapshots.')) if snapshots: snapshots.insert(0, ("", _("Select Volume Snapshot"))) else: snapshots.insert(0, ("", _("No volume snapshots available"))) return snapshots