diff --git a/openstack_dashboard/api/tuskar.py b/openstack_dashboard/api/tuskar.py index 1c86a4620..31ad2e015 100644 --- a/openstack_dashboard/api/tuskar.py +++ b/openstack_dashboard/api/tuskar.py @@ -17,14 +17,25 @@ import logging from datetime import timedelta from random import randint +from django.conf import settings from django.db.models import Sum, Max from django.utils.translation import ugettext_lazy as _ +from tuskarclient.v1 import client as tuskar_client + from openstack_dashboard.api import base import openstack_dashboard.dashboards.infrastructure.models as dummymodels LOG = logging.getLogger(__name__) +TUSKAR_ENDPOINT_URL = getattr(settings, 'TUSKAR_ENDPOINT_URL') + + +# FIXME: request isn't used right in the tuskar client right now, but looking +# at other clients, it seems like it will be in the future +def tuskarclient(request): + c = tuskar_client.Client(TUSKAR_ENDPOINT_URL) + return c class StringIdAPIResourceWrapper(base.APIResourceWrapper): @@ -207,27 +218,64 @@ class Rack(StringIdAPIResourceWrapper): """Wrapper for the Rack object returned by the dummy model. """ - _attrs = ['name', 'resource_class_id', 'location', 'subnet'] + _attrs = ['id', 'name', 'location', 'subnet', 'nodes'] @classmethod def create(cls, request, name, resource_class_id, location, subnet): - rack = dummymodels.Rack(name=name, - resource_class_id=resource_class_id, - location=location, subnet=subnet) - rack.save() - return rack + ## FIXME: Where is the location attribute?? Also, set nodes + ## here + rack = tuskarclient(request).racks.create( + name=name, + #location=location, + subnet=subnet, + nodes=[], + slots=0) + + ## FIXME: it would be optimal if we didn't have to make a separate + ## call for this. racks= also needs to be fixed + ## ALSO it doesn't seem to work, I can't get it to work using curl + ## from the command line + #rc = ResourceClass.get(request, resource_class_id) + #ResourceClass.update(request, resource_class_id, + # name=rc.name, + # service_type=rc.service_type, + # racks={"id": rack.id}) + + return cls(rack) + + @classmethod + def update(cls, request, rack_id, kwargs): + return cls(tuskarclient(request).racks.update(rack_id, + name=kwargs['name'], + #location=location, + subnet=kwargs['subnet'], + nodes=[], + slots=0)) @classmethod def list(cls, request, only_free_racks=False): + ## FIXME: currently resource_class is not an attribute of a rack; can + ## that be changed? If so, we can do free_racks much more easily if only_free_racks: - return [cls(r) for r in dummymodels.Rack.objects.all() if ( - r.resource_class is None)] + return [Rack(r) for r in + tuskarclient(request).racks.list()] else: - return [cls(r) for r in dummymodels.Rack.objects.all()] + return [Rack(r) for r in + tuskarclient(request).racks.list()] @classmethod def get(cls, request, rack_id): - return cls(dummymodels.Rack.objects.get(id=rack_id)) + return cls(tuskarclient(request).racks.get(rack_id)) + + ## FIXME: this is temporary + @property + def resource_class_id(self): + return 1 + + ## FIXME: as is this + @property + def location(self): + return "somewhere" @property def capacities(self): @@ -330,16 +378,19 @@ class Rack(StringIdAPIResourceWrapper): @classmethod def delete(cls, request, rack_id): - dummymodels.Rack.objects.get(id=rack_id).delete() + tuskarclient(request).racks.delete(rack_id) + ## FIXME: this will have to be rewritten to ultimately + ## fetch nodes from nova baremetal @property - def nodes(self): - if not hasattr(self, '_nodes'): - self._nodes = [Node(h) for h in self._apiresource.node_set.all()] - return self._nodes + def list_nodes(self): + return [] + #if not hasattr(self, '_nodes'): + # self._nodes = [Node(h) for h in self._apiresource.node_set.all()] + #return self._nodes def nodes_count(self): - return len(self.nodes) + return len(self.list_nodes) # The idea here is to take a list of MAC addresses and assign them to # our rack. I'm attaching this here so that we can take one list, versus @@ -369,16 +420,6 @@ class Rack(StringIdAPIResourceWrapper): self._resource_class = self._apiresource.resource_class return self._resource_class - @classmethod - def update(cls, rack_id, kwargs): - rack = dummymodels.Rack.objects.get(id=rack_id) - rack.name = kwargs['name'] - rack.location = kwargs['location'] - rack.subnet = kwargs['subnet'] - rack.resource_class_id = kwargs['resource_class_id'] - rack.save() - return cls(rack) - ########################################################################## # ResourceClass @@ -387,44 +428,37 @@ class ResourceClass(StringIdAPIResourceWrapper): """Wrapper for the ResourceClass object returned by the dummy model. """ - _attrs = ['name', 'service_type', 'status'] + _attrs = ['name', 'service_type', 'racks'] ########################################################################## # ResourceClass Class methods ########################################################################## @classmethod def get(cls, request, resource_class_id): - obj = cls(dummymodels.ResourceClass.objects.get( - id=resource_class_id)) - obj.set_request(request) - return obj + rc = cls(tuskarclient(request).resource_classes.get(resource_class_id)) + rc.set_request(request) + return rc @classmethod def create(self, request, name, service_type): - rc = dummymodels.ResourceClass( - name=name, - service_type=service_type) - - rc.save() - return ResourceClass(rc) + return ResourceClass( + tuskarclient(request).resource_classes.create( + name=name, + service_type=service_type)) @classmethod def list(self, request): - return [ - ResourceClass(rc) for rc in ( - dummymodels.ResourceClass.objects.all())] + return [ResourceClass(rc) for rc in + tuskarclient(request).resource_classes.list()] @classmethod def update(cls, request, resource_class_id, **kwargs): - rc = dummymodels.ResourceClass.objects.get(id=resource_class_id) - rc.name = kwargs['name'] - rc.service_type = kwargs['service_type'] - rc.save() - return cls(rc) + return cls(tuskarclient(request).resource_classes.update( + resource_class_id, **kwargs)) @classmethod def delete(cls, request, resource_class_id): - dummymodels.ResourceClass.objects.get(id=resource_class_id).delete() + tuskarclient(request).resource_classes.delete(resource_class_id) ########################################################################## # ResourceClass Properties @@ -437,12 +471,10 @@ class ResourceClass(StringIdAPIResourceWrapper): self.racks)] @property - def racks(self): + def list_racks(self): """ List of racks added to ResourceClass """ if not hasattr(self, '_racks'): - self._racks =\ - [Rack(r) for r in ( - self._apiresource.rack_set.all())] + self._racks = [Rack(r) for r in self.racks] return self._racks @property @@ -454,7 +486,7 @@ class ResourceClass(StringIdAPIResourceWrapper): [r for r in ( Rack.list(self.request)) if ( r.resource_class_id is None or - r._apiresource.resource_class == self._apiresource)] + r.resource_class_id == self.id)] return self._all_racks @property @@ -465,47 +497,55 @@ class ResourceClass(StringIdAPIResourceWrapper): self._apiresource.resourceclassflavor_set.all())] return self._resource_class_flavors + ## FIXME: this isn't currently supported by the client library, so would + ## have to be done through curl @property def flavors_ids(self): """ List of unicode ids of flavors added to resource class """ - return [ - unicode(flavor.flavor.id) for flavor in ( - self.resource_class_flavors)] + #return [ + # unicode(flavor.flavor.id) for flavor in ( + # self.resource_class_flavors)] + return [] + ## FIXME: this isn't currently supported by the client library, so would + ## have to be done through curl @property - def flavors(self): + def list_flavors(self): """ Joined relation table resourceclassflavor and flavor together """ - if not hasattr(self, '_flavors'): - added_flavors = self.resource_class_flavors - self._flavors = [] - for f in added_flavors: - flavor_obj = Flavor.get(self.request, f.flavor.id) - flavor_obj.set_max_vms(f.max_vms) - self._flavors.append(flavor_obj) - - return self._flavors + #if not hasattr(self, '_flavors'): + # added_flavors = self.resource_class_flavors + # self._flavors = [] + # for f in added_flavors: + # flavor_obj = Flavor.get(self.request, f.flavor.id) + # flavor_obj.set_max_vms(f.max_vms) + # self._flavors.append(flavor_obj) + #return self._flavors + return [] + ## FIXME: this isn't currently supported by the client library, so would + ## have to be done through curl @property def all_flavors(self): """ Joined relation table resourceclassflavor with all global flavors """ - if not hasattr(self, '_all_flavors'): - all_flavors = Flavor.list(self.request) + #if not hasattr(self, '_all_flavors'): + # all_flavors = Flavor.list(self.request) - added_resourceclassflavors = \ - self._apiresource.resourceclassflavor_set.all() - added_flavors = {} - for added_flavor in added_resourceclassflavors: - added_flavors[str(added_flavor.flavor_id)] = added_flavor + # added_resourceclassflavors = \ + # self._apiresource.resourceclassflavor_set.all() + # added_flavors = {} + # for added_flavor in added_resourceclassflavors: + # added_flavors[str(added_flavor.flavor_id)] = added_flavor - self._all_flavors = [] - for f in all_flavors: - added_flavor = added_flavors.get(f.id) - if added_flavor: - f.set_max_vms(added_flavor.max_vms) - self._all_flavors.append(f) + # self._all_flavors = [] + # for f in all_flavors: + # added_flavor = added_flavors.get(f.id) + # if added_flavor: + # f.set_max_vms(added_flavor.max_vms) + # self._all_flavors.append(f) - return self._all_flavors + #return self._all_flavors + return [] @property def nodes(self): @@ -626,35 +666,40 @@ class ResourceClass(StringIdAPIResourceWrapper): ########################################################################## # ResourceClass Instance methods ########################################################################## + + ## FIXME: this will have to be done some other way def set_flavors(self, request, flavors_ids, max_vms=None): + return # simply delete all and create new flavors, that'is # how the horizon flavors work - max_vms = max_vms or {} + #max_vms = max_vms or {} - for flavor_id in self.flavors_ids: - ResourceClassFlavor.delete(request, - self.id, - flavor_id) + #for flavor_id in self.flavors_ids: + # ResourceClassFlavor.delete(request, + # self.id, + # flavor_id) - for flavor_id in flavors_ids: - flavor = Flavor.get(request, flavor_id) - ResourceClassFlavor.create( - request, - max_vms=max_vms.get(flavor.id), - flavor=flavor._apiresource, - resource_class=self._apiresource) + #for flavor_id in flavors_ids: + # flavor = Flavor.get(request, flavor_id) + # ResourceClassFlavor.create( + # request, + # max_vms=max_vms.get(flavor.id), + # flavor=flavor._apiresource, + # resource_class=self._apiresource) + ## FIXME: this will have to be done some other way def set_racks(self, request, racks_ids): + return # simply delete all and create new racks - for rack_id in self.racks_ids: - rack = Rack.get(request, rack_id) - rack._apiresource.resource_class = None - rack._apiresource.save() + #for rack_id in self.racks_ids: + # rack = Rack.get(request, rack_id) + # rack._apiresource.resource_class = None + # rack._apiresource.save() - for rack_id in racks_ids: - rack = Rack.get(request, rack_id) - rack._apiresource.resource_class = self._apiresource - rack._apiresource.save() + #for rack_id in racks_ids: + # rack = Rack.get(request, rack_id) + # rack._apiresource.resource_class = self._apiresource + # rack._apiresource.save() class Flavor(StringIdAPIResourceWrapper): diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tabs.py b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tabs.py index 029b03b29..06b6ff8e4 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tabs.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tabs.py @@ -40,7 +40,7 @@ class NodesTab(tabs.TableTab): def get_nodes_data(self): try: rack = self.tab_group.kwargs['rack'] - nodes = rack.nodes + nodes = rack.list_nodes except: nodes = [] exceptions.handle(self.tab_group.request, diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tests.py b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tests.py index 7ad2f1a80..8f96856ba 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tests.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/tests.py @@ -23,7 +23,14 @@ from django.core.files.uploadedfile import InMemoryUploadedFile class RackViewTests(test.BaseAdminViewTests): index_page = reverse('horizon:infrastructure:resource_management:index') + @test.create_stubs({api.tuskar.ResourceClass: ('list',)}) def test_create_rack_get(self): + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) + + self.mox.ReplayAll() + url = reverse('horizon:infrastructure:resource_management:' 'racks:create') rack = self.client.get(url) @@ -35,10 +42,18 @@ class RackViewTests(test.BaseAdminViewTests): # FIXME (mawagner) - After moving EditRack to use workflows, we need # to circle back and fix these tests. # - @test.create_stubs({api.tuskar.Rack: ('create',)}) + @test.create_stubs({api.tuskar.Rack: ('list', 'create',), + api.tuskar.ResourceClass: ('list',)}) def test_create_rack_post(self): + api.tuskar.Rack.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_racks.list()) api.tuskar.Rack.create(IsA(http.request.HttpRequest), 'New Rack', u'2', 'Tokyo', '1.2.3.4').AndReturn(None) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) + self.mox.ReplayAll() data = {'name': 'New Rack', 'resource_class_id': u'2', @@ -48,35 +63,66 @@ class RackViewTests(test.BaseAdminViewTests): resp = self.client.post(url, data) self.assertRedirectsNoFollow(resp, self.index_page) + @test.create_stubs({api.tuskar.Rack: ('get',), + api.tuskar.ResourceClass: ('list',)}) def test_edit_rack_get(self): - url = reverse('horizon:infrastructure:resource_management:' + - 'racks:edit', args=[1]) - rack = self.client.get(url) - self.assertEqual(rack.status_code, 200) - self.assertTemplateUsed(rack, - 'horizon/common/_workflow_base.html') + rack = self.tuskar_racks.first() - @test.create_stubs({api.tuskar.Rack: ('update',)}) - def test_edit_rack_post(self): - data = {'name': 'Updated Rack', 'resource_class_id': u'1', - 'rack_id': u'1', 'location': 'New Location', - 'subnet': '127.10.10.0/24', 'node_macs': 'foo'} + api.tuskar.Rack.\ + get(IsA(http.HttpRequest), rack.id).\ + AndReturn(rack) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) - api.tuskar.Rack.update(u'1', data) self.mox.ReplayAll() url = reverse('horizon:infrastructure:resource_management:' + 'racks:edit', args=[1]) + res = self.client.get(url) + self.assertEqual(res.status_code, 200) + self.assertTemplateUsed(res, + 'horizon/common/_workflow_base.html') + + @test.create_stubs({api.tuskar.Rack: ('get', 'list', 'update',), + api.tuskar.ResourceClass: ('list',)}) + def test_edit_rack_post(self): + rack = self.tuskar_racks.first() + + data = {'name': 'Updated Rack', 'resource_class_id': u'1', + 'rack_id': u'1', 'location': 'New Location', + 'subnet': '127.10.10.0/24', 'node_macs': 'foo'} + + api.tuskar.Rack.get( + IsA(http.HttpRequest), + rack.id).\ + AndReturn(rack) + api.tuskar.Rack.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_racks.list()) + api.tuskar.Rack.update(IsA(http.HttpRequest), rack.id, data) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) + + self.mox.ReplayAll() + + url = reverse('horizon:infrastructure:resource_management:' + + 'racks:edit', args=[rack.id]) response = self.client.post(url, data) self.assertNoFormErrors(response) self.assertMessageCount(success=1) self.assertRedirectsNoFollow(response, self.index_page) - @test.create_stubs({api.tuskar.Rack: ('delete',)}) + @test.create_stubs({api.tuskar.Rack: ('delete', 'list')}) def test_delete_rack(self): rack_id = u'1' api.tuskar.Rack.delete(IsA(http.request.HttpRequest), rack_id) \ .AndReturn(None) + api.tuskar.Rack.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_racks.list()) + self.mox.ReplayAll() data = {'action': 'racks__delete__%s' % rack_id} url = reverse('horizon:infrastructure:resource_management:index') diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/views.py b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/views.py index 2cccd98b3..d1bdafc3b 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/views.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/views.py @@ -66,9 +66,8 @@ class EditView(workflows.WorkflowView): workflow_class = EditRack def get_initial(self): - obj = api.tuskar.Rack.get(None, - rack_id=self.kwargs['rack_id']) - mac_str = "\n".join([x.mac_address for x in obj.nodes]) + obj = api.tuskar.Rack.get(self.request, self.kwargs['rack_id']) + mac_str = "\n".join([x.mac_address for x in obj.list_nodes]) return {'name': obj.name, 'resource_class_id': obj.resource_class_id, 'location': obj.location, 'subnet': obj.subnet, 'node_macs': mac_str, 'rack_id': self.kwargs['rack_id']} diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/workflows.py b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/workflows.py index 1fceb7f10..f4d0f7ebc 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/racks/workflows.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/racks/workflows.py @@ -169,8 +169,8 @@ class EditRack(CreateRack): def handle(self, request, data): try: rack_id = self.context['rack_id'] - rack = api.tuskar.Rack.update(rack_id, data) + rack = api.tuskar.Rack.update(request, rack_id, data) return True except: - exceptions.handle(request, _("Unable to create rack.")) + exceptions.handle(request, _("Unable to edit rack.")) diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tabs.py b/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tabs.py index 0ab53376c..650d77613 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tabs.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tabs.py @@ -42,7 +42,7 @@ class RacksTab(tabs.TableTab): def get_racks_data(self): try: resource_class = self.tab_group.kwargs['resource_class'] - racks = resource_class.racks + racks = resource_class.list_racks except: racks = [] exceptions.handle(self.tab_group.request, @@ -60,7 +60,7 @@ class FlavorsTab(tabs.TableTab): def get_flavors_data(self): try: resource_class = self.tab_group.kwargs['resource_class'] - racks = resource_class.flavors + racks = resource_class.list_flavors except: racks = [] exceptions.handle(self.tab_group.request, diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tests.py b/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tests.py index c50ff569b..8cf0ebab1 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tests.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/resource_classes/tests.py @@ -42,10 +42,8 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertEqual(res.status_code, 200) @test.create_stubs({ - api.tuskar.ResourceClass: ('create', 'set_flavors', - 'set_racks'), - api.tuskar.Flavor: ('list',), - api.tuskar.Rack: ('list',) + api.tuskar.ResourceClass: ('list', 'create', + 'set_flavors', 'set_racks'), }) def test_create_resource_class_post(self): new_resource_class = self.tuskar_resource_classes.first() @@ -55,6 +53,9 @@ class ResourceClassViewTests(test.BaseAdminViewTests): add_max_vms = {} add_racks_ids = [] + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) api.tuskar.ResourceClass.\ create(IsA(http.HttpRequest), name=new_unique_name, service_type=new_resource_class.service_type).\ @@ -76,7 +77,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): ("%s?tab=resource_management_tabs__resource_classes_tab" % reverse("horizon:infrastructure:resource_management:index"))) - @test.create_stubs({api.tuskar.ResourceClass: ('get',)}) + @test.create_stubs({api.tuskar.ResourceClass: ('get', 'racks_ids')}) def test_edit_resource_class_get(self): resource_class = self.tuskar_resource_classes.first() all_flavors = [] @@ -85,6 +86,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): api.tuskar.ResourceClass.\ get(IsA(http.HttpRequest), resource_class.id).MultipleTimes().\ AndReturn(resource_class) + self.mox.ReplayAll() # FIXME I should probably track the racks and flavors methods @@ -101,7 +103,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertEqual(res.status_code, 200) @test.create_stubs({ - api.tuskar.ResourceClass: ('update', 'set_racks', + api.tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', 'set_flavors') }) def test_edit_resource_class_post(self): @@ -111,6 +113,13 @@ class ResourceClassViewTests(test.BaseAdminViewTests): add_max_vms = {} add_racks_ids = [] + api.tuskar.ResourceClass.get( + IsA(http.HttpRequest), + resource_class.id).\ + AndReturn(resource_class) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) api.tuskar.ResourceClass.\ update(IsA(http.HttpRequest), resource_class.id, name=resource_class.name, @@ -156,7 +165,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): res, reverse('horizon:infrastructure:resource_management:index')) @test.create_stubs({ - api.tuskar.ResourceClass: ('get', 'flavors', 'racks') + api.tuskar.ResourceClass: ('get', 'list_flavors', 'list_racks') }) def test_detail_get(self): resource_class = self.tuskar_resource_classes.first() @@ -169,8 +178,8 @@ class ResourceClassViewTests(test.BaseAdminViewTests): MultipleTimes().AndReturn(resource_class) self.mox.ReplayAll() - api.tuskar.ResourceClass.flavors = flavors - api.tuskar.ResourceClass.racks = racks + api.tuskar.ResourceClass.list_flavors = flavors + api.tuskar.ResourceClass.list_racks = racks url = reverse('horizon:infrastructure:resource_management:' 'resource_classes:detail', args=[resource_class.id]) @@ -183,7 +192,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertTemplateUsed(res, 'infrastructure/resource_management/resource_classes/detail.html') - @test.create_stubs({api.tuskar.ResourceClass: ('get',)}) + @test.create_stubs({api.tuskar.ResourceClass: ('get', 'racks_ids')}) def test_detail_edit_racks_get(self): resource_class = self.tuskar_resource_classes.first() all_flavors = [] @@ -208,7 +217,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertEqual(res.status_code, 200) @test.create_stubs({ - api.tuskar.ResourceClass: ('update', 'set_racks', + api.tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', 'set_flavors') }) def test_detail_edit_racks_post(self): @@ -218,6 +227,13 @@ class ResourceClassViewTests(test.BaseAdminViewTests): add_max_vms = {} add_racks_ids = [] + api.tuskar.ResourceClass.get( + IsA(http.HttpRequest), + resource_class.id).\ + AndReturn(resource_class) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) api.tuskar.ResourceClass.\ update(IsA(http.HttpRequest), resource_class.id, name=resource_class.name, @@ -245,7 +261,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): reverse(detail_url, args=(resource_class.id,))) self.assertRedirectsNoFollow(res, redirect_url) - @test.create_stubs({api.tuskar.ResourceClass: ('get',)}) + @test.create_stubs({api.tuskar.ResourceClass: ('get', 'racks_ids')}) def test_detail_edit_flavors_get(self): resource_class = self.tuskar_resource_classes.first() all_flavors = [] @@ -270,7 +286,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): self.assertEqual(res.status_code, 200) @test.create_stubs({ - api.tuskar.ResourceClass: ('update', 'set_racks', + api.tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', 'set_flavors') }) def test_detail_edit_flavors_post(self): @@ -280,6 +296,13 @@ class ResourceClassViewTests(test.BaseAdminViewTests): add_max_vms = {} add_racks_ids = [] + api.tuskar.ResourceClass.get( + IsA(http.HttpRequest), + resource_class.id).\ + AndReturn(resource_class) + api.tuskar.ResourceClass.list( + IsA(http.request.HttpRequest)).AndReturn( + self.tuskar_resource_classes.list()) api.tuskar.ResourceClass.\ update(IsA(http.HttpRequest), resource_class.id, name=resource_class.name, diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/tests.py b/openstack_dashboard/dashboards/infrastructure/resource_management/tests.py index 8fd65ae66..a5ed94558 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/tests.py +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/tests.py @@ -30,7 +30,7 @@ class ResourceManagementTests(test.BaseAdminViewTests): @test.create_stubs({ api.tuskar.ResourceClass: ( 'list', - 'racks', + 'list_racks', 'nodes'), api.tuskar.Flavor: ( 'list',), @@ -49,7 +49,7 @@ class ResourceManagementTests(test.BaseAdminViewTests): racks = [] api.tuskar.ResourceClass.nodes = nodes - api.tuskar.ResourceClass.racks = racks + api.tuskar.ResourceClass.list_racks = racks api.tuskar.ResourceClass.list( IsA(http.HttpRequest)).\ diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index 4494b695e..f0a2f1428 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -352,3 +352,7 @@ SECURITY_GROUP_RULES = { 'to_port': '3389', }, } + +# FIXME: this will eventually be unneeded, as it will be retrieved from Keystone +#TUSKAR_ENDPOINT_URL = "http://127.0.0.1:6385" + diff --git a/openstack_dashboard/test/api_tests/tuskar_tests.py b/openstack_dashboard/test/api_tests/tuskar_tests.py index 6fd9fd8ea..d3bf96146 100644 --- a/openstack_dashboard/test/api_tests/tuskar_tests.py +++ b/openstack_dashboard/test/api_tests/tuskar_tests.py @@ -30,20 +30,33 @@ import openstack_dashboard.dashboards.infrastructure.models as dummymodels class TuskarApiTests(test.APITestCase): def setUp(self): super(TuskarApiTests, self).setUp() + # FIXME: I'm not sure this is sustainable # dummy data are seeded from fixtures self.rclass1 = dummymodels.ResourceClass.objects.get(name='rclass1') self.flavor1 = dummymodels.Flavor.objects.get(name='flavor1') def test_resource_class_list(self): - rc_list = api.tuskar.ResourceClass.list(self.request) - self.assertEquals(3, len(rc_list)) - for rc in rc_list: + rcs = self.tuskar_resource_classes.list() + + tuskarclient = self.stub_tuskarclient() + tuskarclient.resource_classes = self.mox.CreateMockAnything() + tuskarclient.resource_classes.list().AndReturn(rcs) + self.mox.ReplayAll() + + ret_val = api.tuskar.ResourceClass.list(self.request) + for rc in ret_val: self.assertIsInstance(rc, api.tuskar.ResourceClass) def test_resource_class_get(self): - rc = api.tuskar.ResourceClass.get(self.request, self.rclass1.id) - self.assertIsInstance(rc, api.tuskar.ResourceClass) - self.assertEquals(rc.name, self.rclass1.name) + rc = self.tuskar_resource_classes.first() + + tuskarclient = self.stub_tuskarclient() + tuskarclient.resource_classes = self.mox.CreateMockAnything() + tuskarclient.resource_classes.get(rc.id).AndReturn(rc) + self.mox.ReplayAll() + + ret_val = api.tuskar.ResourceClass.get(self.request, rc.id) + self.assertIsInstance(ret_val, api.tuskar.ResourceClass) def test_resource_class_flavor_counts(self): rc = api.tuskar.ResourceClass.get(self.request, self.rclass1.id) diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index 79d201fd8..1a6ad8704 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -37,6 +37,7 @@ from keystoneclient.v2_0 import client as keystone_client from neutronclient.v2_0 import client as neutron_client from novaclient.v1_1 import client as nova_client from swiftclient import client as swift_client +from tuskarclient.v1 import client as tuskar_client import httplib2 import mox @@ -261,6 +262,7 @@ class APITestCase(TestCase): self._original_neutronclient = api.neutron.neutronclient self._original_cinderclient = api.cinder.cinderclient self._original_heatclient = api.heat.heatclient + self._original_tuskarclient = api.tuskar.tuskarclient # Replace the clients with our stubs. api.glance.glanceclient = lambda request: self.stub_glanceclient() @@ -269,6 +271,7 @@ class APITestCase(TestCase): api.neutron.neutronclient = lambda request: self.stub_neutronclient() api.cinder.cinderclient = lambda request: self.stub_cinderclient() api.heat.heatclient = lambda request: self.stub_heatclient() + api.tuskar.tuskarclient = lambda request: self.stub_tuskarclient() def tearDown(self): super(APITestCase, self).tearDown() @@ -278,6 +281,7 @@ class APITestCase(TestCase): api.neutron.neutronclient = self._original_neutronclient api.cinder.cinderclient = self._original_cinderclient api.heat.heatclient = self._original_heatclient + api.tuskar.tuskarclient = self._original_tuskarclient def stub_novaclient(self): if not hasattr(self, "novaclient"): @@ -335,6 +339,12 @@ class APITestCase(TestCase): self.heatclient = self.mox.CreateMock(heat_client.Client) return self.heatclient + def stub_tuskarclient(self): + if not hasattr(self, "tuskarclient"): + self.mox.StubOutWithMock(tuskar_client, 'Client') + self.tuskarclient = self.mox.CreateMock(tuskar_client.Client) + return self.tuskarclient + @unittest.skipUnless(os.environ.get('WITH_SELENIUM', False), "The WITH_SELENIUM env variable is not set.") diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index 1ccd920a3..3878d9d43 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -122,3 +122,7 @@ NOSE_ARGS = ['--nocapture', '--cover-package=openstack_dashboard', '--cover-inclusive', '--all-modules'] + +# FIXME: this will eventually be unneeded when the parameter is removed +# from local settings and api/tuskar.py +TUSKAR_ENDPOINT_URL = "http://127.0.0.1:6385" diff --git a/requirements.txt b/requirements.txt index b5ef7e678..66f184717 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,3 +20,5 @@ pytz>=2010h # Horizon Utility Requirements # for SECURE_KEY generation lockfile>=0.8 + +-e git://github.com/tuskar/python-tuskarclient.git#egg=python-tuskarclient