diff --git a/tox.ini b/tox.ini index e91bd4cf7..bf8e8ec3f 100644 --- a/tox.ini +++ b/tox.ini @@ -32,11 +32,10 @@ downloadcache = ~/cache/pip [flake8] builtins = _ exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,panel_template,dash_template,local_settings.py -# E127 continuation line over-indented for visual indent # E128 continuation line under-indented for visual indent # F403 'from import *' used; unable to detect undefined names # F999 syntax error in doctest # H4xx docstrings # H701 empty localization string # H702 Formatting operation should be outside of localization method call -ignore = E127,E128,F403,F999,H4,H701,H702 +ignore = E128,F403,F999,H4,H701,H702 diff --git a/tuskar_ui/api.py b/tuskar_ui/api.py index 68b2a413f..0f553e322 100644 --- a/tuskar_ui/api.py +++ b/tuskar_ui/api.py @@ -519,8 +519,9 @@ class Rack(StringIdAPIResourceWrapper): if not self.resource_class: return [] - added_flavors = tuskarclient(self.request).flavors\ - .list(self.resource_class_id) + added_flavors = (tuskarclient(self.request) + .flavors + .list(self.resource_class_id)) self._flavors = [] if added_flavors: for f in added_flavors: @@ -589,7 +590,7 @@ class ResourceClass(StringIdAPIResourceWrapper): @classmethod def update(cls, request, resource_class_id, name, service_type, image_id, - flavors): + flavors): resource_class = cls(tuskarclient(request).resource_classes.update( resource_class_id, name=name, @@ -600,7 +601,7 @@ class ResourceClass(StringIdAPIResourceWrapper): ## FIXME: flavors have to be updated separately, seems less than ideal for flavor_id in resource_class.flavors_ids: Flavor.delete(request, resource_class_id=resource_class.id, - flavor_id=flavor_id) + flavor_id=flavor_id) for flavor in flavors: Flavor.create(request, resource_class_id=resource_class.id, diff --git a/tuskar_ui/infrastructure/resource_management/flavors/tests.py b/tuskar_ui/infrastructure/resource_management/flavors/tests.py index 3c07c365b..8e37cb46f 100644 --- a/tuskar_ui/infrastructure/resource_management/flavors/tests.py +++ b/tuskar_ui/infrastructure/resource_management/flavors/tests.py @@ -38,13 +38,13 @@ class FlavorsTests(test.BaseAdminViewTests): self.mox.ReplayAll() url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:resource_classes:' - 'flavors:detail', + 'resource_management:resource_classes:' + 'flavors:detail', args=[resource_class.id, flavor.id]) res = self.client.get(url) self.assertTemplateUsed(res, 'infrastructure/resource_management/' - 'flavors/detail.html') + 'flavors/detail.html') @test.create_stubs({tuskar.Flavor: ('get',)}) def test_detail_flavor_exception(self): @@ -52,17 +52,17 @@ class FlavorsTests(test.BaseAdminViewTests): resource_class = self.tuskar_resource_classes.first() tuskar.Flavor.get(mox.IsA(http.HttpRequest), - resource_class.id, - flavor.id).AndRaise(self.exceptions.tuskar) + resource_class.id, + flavor.id).AndRaise(self.exceptions.tuskar) self.mox.ReplayAll() url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:resource_classes:' - 'flavors:detail', + 'resource_management:resource_classes:' + 'flavors:detail', args=[resource_class.id, flavor.id]) res = self.client.get(url) self.assertRedirectsNoFollow(res, urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index')) + 'index')) diff --git a/tuskar_ui/infrastructure/resource_management/flavors/views.py b/tuskar_ui/infrastructure/resource_management/flavors/views.py index e3a9ac44b..8d0335448 100644 --- a/tuskar_ui/infrastructure/resource_management/flavors/views.py +++ b/tuskar_ui/infrastructure/resource_management/flavors/views.py @@ -62,7 +62,7 @@ class DetailView(horizon_tabs.TabView): exceptions.handle(self.request, _('Unable to retrieve details for resource ' 'class "%s".') % resource_class_id, - redirect=redirect) + redirect=redirect) self._resource_class = resource_class return self._resource_class diff --git a/tuskar_ui/infrastructure/resource_management/nodes/tests.py b/tuskar_ui/infrastructure/resource_management/nodes/tests.py index 045c267d2..433031d6e 100644 --- a/tuskar_ui/infrastructure/resource_management/nodes/tests.py +++ b/tuskar_ui/infrastructure/resource_management/nodes/tests.py @@ -88,4 +88,4 @@ class NodeViewTests(test.BaseAdminViewTests): self.assertRedirectsNoFollow(res, urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index')) + 'index')) diff --git a/tuskar_ui/infrastructure/resource_management/nodes/views.py b/tuskar_ui/infrastructure/resource_management/nodes/views.py index a4f79a8a6..68a7f1a39 100644 --- a/tuskar_ui/infrastructure/resource_management/nodes/views.py +++ b/tuskar_ui/infrastructure/resource_management/nodes/views.py @@ -58,8 +58,8 @@ class DetailView(horizon_tabs.TabView): exceptions.handle(self.request, _('Unable to retrieve details for ' 'node "%s".') - % node_id, - redirect=redirect) + % node_id, + redirect=redirect) self._node = node return self._node diff --git a/tuskar_ui/infrastructure/resource_management/racks/forms.py b/tuskar_ui/infrastructure/resource_management/racks/forms.py index 59a8e1989..0ad8e0bab 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/forms.py +++ b/tuskar_ui/infrastructure/resource_management/racks/forms.py @@ -80,11 +80,13 @@ class UploadRack(forms.SelfHandlingForm): tuskar.ResourceClass.list(request)) for rack in racks: try: - tuskar.Rack.create(request, name=rack.name, - resource_class_id= - rclass_ids[rack.resource_class], - location=rack.region, - subnet=rack.subnet) + tuskar.Rack.create( + request, + name=rack.name, + resource_class_id=rclass_ids[rack.resource_class], + location=rack.region, + subnet=rack.subnet, + ) # FIXME: will have to handle nodes once proper attributes # for nodes are added successes.append(rack.name) @@ -97,7 +99,7 @@ class UploadRack(forms.SelfHandlingForm): if fails: messages.error(request, _('Failed to add following racks: %s') % - (',').join(fails)) + (',').join(fails)) return True diff --git a/tuskar_ui/infrastructure/resource_management/racks/tables.py b/tuskar_ui/infrastructure/resource_management/racks/tables.py index 5891fbf90..36f3af59c 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/tables.py +++ b/tuskar_ui/infrastructure/resource_management/racks/tables.py @@ -70,6 +70,12 @@ class UpdateRow(tables.Row): return rack +def _usage_filter(vm_capacity): + if vm_capacity and vm_capacity.value: + return "{0:.0f} %".format( + round((100.0 / vm_capacity.value) * vm_capacity.usage)) + + class RacksTable(tables.DataTable): STATUS_CHOICES = ( ("unprovisioned", False), @@ -82,24 +88,22 @@ class RacksTable(tables.DataTable): ":racks:detail"), verbose_name=_("Rack Name")) subnet = tables.Column('subnet', verbose_name=_("IP Subnet")) - resource_class = tables.Column('resource_class', - verbose_name=_("Class"), - filters=(lambda resource_class: - (resource_class and - resource_class.name) - or None,)) + resource_class = tables.Column( + 'resource_class', + verbose_name=_("Class"), + filters=(lambda resource_class: getattr(resource_class, 'name', None),) + ) node_count = tables.Column('nodes_count', verbose_name=_("Nodes")) state = tables.Column('state', verbose_name=_("State"), status=True, status_choices=STATUS_CHOICES) + usage = tables.Column( 'vm_capacity', verbose_name=_("Usage"), - filters=(lambda vm_capacity: - (vm_capacity and vm_capacity.value and - "%s %%" % int(round((100 / float(vm_capacity.value)) * - vm_capacity.usage, 0))) or None,)) + filters=(_usage_filter,), + ) class Meta: name = "racks" diff --git a/tuskar_ui/infrastructure/resource_management/racks/tests.py b/tuskar_ui/infrastructure/resource_management/racks/tests.py index 475b95d9e..9c514d438 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/tests.py +++ b/tuskar_ui/infrastructure/resource_management/racks/tests.py @@ -39,7 +39,7 @@ class RackViewTests(test.BaseAdminViewTests): self.mox.ReplayAll() url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:create') + 'resource_management:racks:create') rack = self.client.get(url) self.assertEqual(rack.status_code, 200) @@ -97,7 +97,7 @@ class RackViewTests(test.BaseAdminViewTests): 'nodes-0-local_gb': u'10', } url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:create') + 'resource_management:racks:create') resp = self.client.post(url, data) self.assertRedirectsNoFollow(resp, self.index_page_racks_tab) @@ -222,13 +222,13 @@ class RackViewTests(test.BaseAdminViewTests): self.mox.ReplayAll() data = {'action': 'racks__delete__%s' % rack_id} url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') + 'resource_management:index') result = self.client.post(url, data) self.assertRedirectsNoFollow(result, self.index_page) def test_upload_rack_get(self): url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') + 'resource_management:racks:upload') rack = self.client.get(url) self.assertEqual(rack.status_code, 200) @@ -245,7 +245,7 @@ class RackViewTests(test.BaseAdminViewTests): data = {'csv_file': temp_file, 'upload': '1'} url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') + 'resource_management:racks:upload') resp = self.client.post(url, data) self.assertTemplateUsed(resp, 'infrastructure/resource_management/racks/upload.html') @@ -256,7 +256,7 @@ class RackViewTests(test.BaseAdminViewTests): def test_upload_rack_upload_with_error(self): data = {'upload': '1'} url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') + 'resource_management:racks:upload') resp = self.client.post(url, data) self.assertTemplateUsed(resp, 'infrastructure/resource_management/racks/upload.html') @@ -281,7 +281,7 @@ class RackViewTests(test.BaseAdminViewTests): data = {'uploaded_data': base64.b64encode(csv_data), 'add_racks': '1'} url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') + 'resource_management:racks:upload') resp = self.client.post(url, data) self.assertRedirectsNoFollow(resp, self.index_page) self.assertMessageCount(success=1) diff --git a/tuskar_ui/infrastructure/resource_management/racks/workflows.py b/tuskar_ui/infrastructure/resource_management/racks/workflows.py index 2e6791bc7..9dc3b05ff 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/workflows.py +++ b/tuskar_ui/infrastructure/resource_management/racks/workflows.py @@ -103,10 +103,10 @@ class NodeCreateAction(workflows.Action): formset = table.get_formset() if formset.is_valid(): cleaned_data['nodes'] = [form.cleaned_data - for form in formset - if form.cleaned_data - and not - form.cleaned_data.get('DELETE')] + for form in formset + if form.cleaned_data + and not + form.cleaned_data.get('DELETE')] else: raise forms.ValidationError(_("Errors in the nodes list.")) return cleaned_data @@ -157,7 +157,7 @@ class CreateRack(workflows.Workflow): """This url is used both as success and failure url""" return "%s?tab=resource_management_tabs__racks_tab" %\ urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index') + 'index') def get_success_url(self): return self.get_index_url() diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py index 695949243..e73723627 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py @@ -446,7 +446,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): @test.create_stubs({ tuskar.ResourceClass: ('get', 'list_flavors', - 'racks_ids', 'all_racks'), + 'racks_ids', 'all_racks'), glance: ('image_list_detailed',), }) def test_detail_edit_racks_get(self): @@ -457,8 +457,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( (self.images.list(), False)) tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).\ - AndReturn(resource_class) + resource_class.id).AndReturn(resource_class) # get_flavors_data in workflows.py tuskar.ResourceClass.get( @@ -551,7 +550,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): @test.create_stubs({ tuskar.ResourceClass: ('get', 'list_flavors', - 'racks_ids', 'all_racks'), + 'racks_ids', 'all_racks'), glance: ('image_list_detailed',), }) def test_detail_edit_flavors_get(self): @@ -562,8 +561,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( (self.images.list(), False)) tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).\ - AndReturn(resource_class) + resource_class.id).AndReturn(resource_class) # get_flavors_data in workflows.py tuskar.ResourceClass.get( @@ -649,7 +647,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertMessageCount(success=1) redirect_url = ('horizon:infrastructure:resource_management:' - 'resource_classes:detail') + 'resource_classes:detail') redirect_url = "%s?tab=resource_class_details__flavors" % ( urlresolvers.reverse(redirect_url, args=(resource_class.id,))) self.assertRedirectsNoFollow(res, redirect_url) diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/views.py b/tuskar_ui/infrastructure/resource_management/resource_classes/views.py index 3c66151f6..de451676e 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/views.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/views.py @@ -114,8 +114,7 @@ class DetailView(horizon_tabs.TabView): exceptions.handle(self.request, _('Unable to retrieve details for ' 'resource class "%s".') - % resource_class_id, - redirect=redirect) + % resource_class_id, redirect=redirect) self._resource_class = resource_class return self._resource_class diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py index 763b62ac6..66d6f04a2 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py @@ -224,13 +224,13 @@ class ResourceClassWorkflowMixin: resource_class_name = data['name'] for flavor in data.get('flavors') or []: capacities = [] - for name, (label, - unit, required) in flavors_forms.CAPACITIES.items(): + for name, info in flavors_forms.CAPACITIES.items(): + label, unit, required = info value = flavor.get(name, '') if value is None: value = '' capacities.append({'name': name, 'value': str(value), - 'unit': unit}) + 'unit': unit}) # FIXME: tuskar uses resource-class-name prefix for flavors, # e.g. m1.large, we add rc name to the template name: flavor_name = "%s.%s" % (resource_class_name, flavor['name']) diff --git a/tuskar_ui/infrastructure/resource_management/tabs.py b/tuskar_ui/infrastructure/resource_management/tabs.py index 08df0ac26..c5d5b9277 100644 --- a/tuskar_ui/infrastructure/resource_management/tabs.py +++ b/tuskar_ui/infrastructure/resource_management/tabs.py @@ -26,9 +26,9 @@ from tuskar_ui.infrastructure.resource_management.resource_classes\ def get_provision_racks_and_state(racks): unprovisioned_racks = [rack for rack in racks - if not rack.is_provisioned] + if not rack.is_provisioned] provisioning_racks = [rack for rack in racks - if rack.is_provisioning] + if rack.is_provisioning] if provisioning_racks: state = 'provisioning' elif unprovisioned_racks: diff --git a/tuskar_ui/infrastructure/resource_management/urls.py b/tuskar_ui/infrastructure/resource_management/urls.py index 4f6052e31..18e585d93 100644 --- a/tuskar_ui/infrastructure/resource_management/urls.py +++ b/tuskar_ui/infrastructure/resource_management/urls.py @@ -28,9 +28,9 @@ from tuskar_ui.test import urls as test_urls urlpatterns = defaults.patterns('', defaults.url(r'^$', views.IndexView.as_view(), name='index'), defaults.url(r'^provision$', views.ProvisionView.as_view(), - name='provision'), + name='provision'), defaults.url(r'^provisioning_state.json$', views.provisioning_state, - name='provisioning_state'), + name='provisioning_state'), defaults.url(r'^racks/', defaults.include(rack_urls, namespace='racks')), defaults.url(r'^resource_classes/', defaults.include(resource_classes_urls, diff --git a/tuskar_ui/tables.py b/tuskar_ui/tables.py index 8544759d2..7b129c989 100644 --- a/tuskar_ui/tables.py +++ b/tuskar_ui/tables.py @@ -35,7 +35,7 @@ class BaseCell(horizon_tables.Cell): """ Represents a single cell in the table. """ def __init__(self, datum, column, row, attrs=None, classes=None): super(BaseCell, self).__init__(datum, None, column, row, attrs, - classes) + classes) self.data = self.get_data(datum, column, row) def get_data(self, datum, column, row): @@ -214,7 +214,7 @@ class FormsetDataTableMixin(object): formset = self.get_formset() formset.is_valid() for datum, form in itertools.izip_longest(self.filtered_data, - formset): + formset): row = self._meta.row_class(self, datum, form) if self.get_object_id(datum) == self.current_item_id: self.selected = True diff --git a/tuskar_ui/test/helpers.py b/tuskar_ui/test/helpers.py index f86768ec2..6faa27b4b 100644 --- a/tuskar_ui/test/helpers.py +++ b/tuskar_ui/test/helpers.py @@ -34,7 +34,7 @@ def create_stubs(stubs_to_create={}): @unittest.skipIf(os.environ.get('SKIP_UNITTESTS', False), - "The SKIP_UNITTESTS env variable is set.") + "The SKIP_UNITTESTS env variable is set.") class TestCase(openstack_dashboard_helpers.TestCase): """ Specialized base test case class for Horizon which gives access to diff --git a/tuskar_ui/test/test_data/tuskar_data.py b/tuskar_ui/test/test_data/tuskar_data.py index b5e121262..df6bbebd9 100644 --- a/tuskar_ui/test/test_data/tuskar_data.py +++ b/tuskar_ui/test/test_data/tuskar_data.py @@ -29,22 +29,22 @@ def data(TEST): {'id': '1', 'name': 'nano', 'max_vms': 100, - 'capacities': - [{"name": "cpu", + 'capacities': [ + {"name": "cpu", "value": 64, "unit": "CPU"}, - {"name": "memory", - "value": 1024, - "unit": "MB"}, - {"name": "storage", - "value": 1, - "unit": "GB"}, - {"name": "ephemeral_disk", - "value": 0, - "unit": "GB"}, - {"name": "swap_disk", - "value": 2, - "unit": "GB"}]}) + {"name": "memory", + "value": 1024, + "unit": "MB"}, + {"name": "storage", + "value": 1, + "unit": "GB"}, + {"name": "ephemeral_disk", + "value": 0, + "unit": "GB"}, + {"name": "swap_disk", + "value": 2, + "unit": "GB"}]}) flavor_2 = flavors.Flavor(flavors.FlavorManager(None), {'id': '2', 'name': 'large', @@ -81,18 +81,18 @@ def data(TEST): 'location': 'location', 'subnet': '192.168.1.0/24', 'state': 'active', - 'nodes': - [{'id': '1'}, - {'id': '2'}, - {'id': '3'}, - {'id': '4'}], - 'capacities': - [{"name": "total_cpu", - "value": "64", - "unit": "CPU"}, - {"name": "total_memory", - "value": "1024", - "unit": "MB"}], + 'nodes': [ + {'id': '1'}, + {'id': '2'}, + {'id': '3'}, + {'id': '4'}], + 'capacities': [ + {"name": "total_cpu", + "value": "64", + "unit": "CPU"}, + {"name": "total_memory", + "value": "1024", + "unit": "MB"}], 'resource_class': {'id': '1'}}) rack_2 = racks.Rack(racks.RackManager(None), {'id': '2', @@ -101,13 +101,13 @@ def data(TEST): 'subnet': '192.168.1.0/25', 'state': 'provisioning', 'nodes': [], - 'capacities': - [{"name": "total_cpu", - "value": "1", - "unit": "CPU"}, - {"name": "total_memory", - "value": "4", - "unit": "MB"}], + 'capacities': [ + {"name": "total_cpu", + "value": "1", + "unit": "CPU"}, + {"name": "total_memory", + "value": "4", + "unit": "MB"}], 'resource_class': {'id': '1'}}) rack_3 = racks.Rack(racks.RackManager(None), {'id': '3', @@ -116,13 +116,13 @@ def data(TEST): 'subnet': '192.168.1.0/26', 'state': 'inactive', 'nodes': [], - 'capacities': - [{"name": "total_cpu", - "value": "1", - "unit": "CPU"}, - {"name": "total_memory", - "value": "2", - "unit": "MB"}], + 'capacities': [ + {"name": "total_cpu", + "value": "1", + "unit": "CPU"}, + {"name": "total_memory", + "value": "2", + "unit": "MB"}], }) TEST.tuskarclient_racks.add(rack_1, rack_2, rack_3) TEST.tuskar_racks.add(api.Rack(rack_1), api.Rack(rack_2), api.Rack(rack_3))