diff options
12 files changed, 301 insertions, 366 deletions
diff --git a/docs/index.rst b/docs/index.rst index 8960aa8b..195f5f1c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,7 @@ Tuskar-UI ========= -Tuskar-UI is a user interface for `Tuskar <https://github.com/stackforge/tuskar>`_, a management API for OpenStack deployments. It is a plugin for `OpenStack Horizon <https://wiki.openstack.org/wiki/Horizon>`_. +Tuskar-UI is a user interface for `Tuskar <https://github.com/openstack/tuskar>`_, a management API for OpenStack deployments. It is a plugin for `OpenStack Horizon <https://wiki.openstack.org/wiki/Horizon>`_. High-Level Overview ------------------- @@ -18,16 +18,16 @@ Developer Information Installation Guide ~~~~~~~~~~~~~~~~~~ -Follow the `Installation Guide <https://github.com/stackforge/tuskar-ui/blob/master/docs/install.rst>`_ to install Tuskar-UI. +Follow the `Installation Guide <https://github.com/openstack/tuskar-ui/blob/master/docs/install.rst>`_ to install Tuskar-UI. Contributing ~~~~~~~~~~~~ -We've moved the code to `stackforge <https://github.com/stackforge>`__ +We've moved the code to `openstack <https://github.com/openstack>`__ to be more familiar to the OpenStack developers. Please go there if you want to check it out: - git clone https://github.com/stackforge/tuskar-ui.git + git clone https://github.com/openstack/tuskar-ui.git The list of bugs and blueprints is on Launchpad: @@ -35,14 +35,14 @@ The list of bugs and blueprints is on Launchpad: We use OpenStack's Gerrit for the code contributions: -`<https://review.openstack.org/#/q/status:open+project:stackforge/tuskar-ui,n,z>`__ +`<https://review.openstack.org/#/q/status:open+project:openstack/tuskar-ui,n,z>`__ and we follow the `OpenStack Gerrit Workflow <https://wiki.openstack.org/wiki/Gerrit_Workflow>`__. If you're interested in the code, here are some key places to start: -* `tuskar_ui/api.py <https://github.com/stackforge/tuskar-ui/blob/master/tuskar_ui/api.py>`_ - This file contains all the API calls made to the Tuskar API (through python-tuskarclient). -* `tuskar_ui/infrastructure <https://github.com/stackforge/tuskar-ui/tree/master/tuskar_ui/infrastructure>`_ - The Tuskar UI code is contained within this directory. Up to this point, UI development has been focused within the resource_management/ subdirectory. +* `tuskar_ui/api.py <https://github.com/openstack/tuskar-ui/blob/master/tuskar_ui/api.py>`_ - This file contains all the API calls made to the Tuskar API (through python-tuskarclient). +* `tuskar_ui/infrastructure <https://github.com/openstack/tuskar-ui/tree/master/tuskar_ui/infrastructure>`_ - The Tuskar UI code is contained within this directory. Up to this point, UI development has been focused within the resource_management/ subdirectory. Future Work ----------- diff --git a/docs/install.rst b/docs/install.rst index 9e174a9d..1defc8d5 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -20,7 +20,7 @@ Installation prerequisites are: machine as tuskar-ui, but it must be network accessible. You may find -`the Tuskar install guide <https://github.com/stackforge/tuskar/blob/master/INSTALL.rst>`_ +`the Tuskar install guide <https://github.com/openstack/tuskar/blob/master/INSTALL.rst>`_ helpful. For baremetal provisioning, you will want a Nova Baremetal driver @@ -28,7 +28,7 @@ installed and registered in the Keystone services catalog. (You can `read more about setting up Nova Baremetal here <https://wiki.openstack.org/wiki/Baremetal>`_.) If you are using Devstack to run OpenStack, you can use -`Devstack Baremetal configuration <https://github.com/stackforge/tuskar-ui/blob/master/docs/devstack_baremetal.rst>`_. +`Devstack Baremetal configuration <https://github.com/openstack/tuskar-ui/blob/master/docs/devstack_baremetal.rst>`_. Installing the packages ----------------------- @@ -62,7 +62,7 @@ Begin by cloning the horizon and tuskar-ui repositories: :: git clone git://github.com/openstack/horizon.git - git clone git://github.com/stackforge/tuskar-ui.git + git clone git://github.com/openstack/tuskar-ui.git Go into horizon and create a symlink to the tuskar-ui code: @@ -137,7 +137,7 @@ tuskar-ui introduces one additional dependency - python-tuskarclient: :: - pip install git+http://github.com/stackforge/python-tuskarclient.git + pip install git+http://github.com/openstack/python-tuskarclient.git Starting the app ---------------- diff --git a/tuskar_ui/api.py b/tuskar_ui/api.py index 834b5b13..81a36ff2 100644 --- a/tuskar_ui/api.py +++ b/tuskar_ui/api.py @@ -21,7 +21,6 @@ import random import django.conf import django.db.models from django.utils.translation import ugettext_lazy as _ # noqa -from horizon import exceptions import requests from novaclient.v1_1.contrib import baremetal @@ -163,20 +162,36 @@ class Capacity(StringIdAPIResourceWrapper): return self._average -class Node(StringIdAPIResourceWrapper): - """Wrapper for the Node object returned by the - dummy model. - """ +class BaremetalNode(StringIdAPIResourceWrapper): _attrs = ['id', 'pm_address', 'cpus', 'memory_mb', 'service_host', 'local_gb', 'pm_user'] @classmethod + def create(cls, request, **kwargs): + # The pm_address, pm_user and terminal_port need to be None when + # empty for the baremetal vm to work. + # terminal_port needs separate handling because 0 is a valid value. + terminal_port = kwargs['terminal_port'] + if terminal_port == '': + terminal_port = None + node = baremetalclient(request).create(kwargs['name'], + kwargs['cpus'], + kwargs['memory_mb'], + kwargs['local_gb'], + kwargs['prov_mac_address'], + kwargs['pm_address'] or None, + kwargs['pm_user'] or None, + kwargs['pm_password'], + terminal_port) + return cls(node) + + @classmethod def get(cls, request, node_id): node = cls(baremetalclient(request).get(node_id)) node.request = request # FIXME ugly, fix after demo, make abstraction of instance details - # this is realy not optimal, but i dont have time do fix it now + # this is realy not optimal, but i dont hve time do fix it now instances, more = nova.server_list( request, search_opts={'paginate': True}, @@ -192,8 +207,8 @@ class Node(StringIdAPIResourceWrapper): if detail: addresses = detail._apiresource.addresses.get('ctlplane') if addresses: - node.ip_address_other = (", ".join([addr['addr'] - for addr in addresses])) + node.ip_address_other = (", " + .join([addr['addr'] for addr in addresses])) node.status = detail._apiresource._info['OS-EXT-STS:vm_state'] node.power_management = "" @@ -206,74 +221,24 @@ class Node(StringIdAPIResourceWrapper): @classmethod def list(cls, request): - return [Node(n, request) for n in baremetalclient(request).list()] + return [cls(n, request) for n in + baremetalclient(request).list()] @classmethod def list_unracked(cls, request): try: - return [n for n in Node.list(request) if (n.rack is None)] + racked_node_ids = [node.nova_baremetal_node_id + for node in Node.list(request)] + return [bn for bn in BaremetalNode.list(request) + if bn.id not in racked_node_ids] except requests.ConnectionError: return [] - @classmethod - def create(cls, request, **kwargs): - # The pm_address, pm_user and terminal_port need to be None when - # empty for the baremetal vm to work. - # terminal_port needs separate handling because 0 is a valid value. - terminal_port = kwargs['terminal_port'] - if terminal_port == '': - terminal_port = None - node = baremetalclient(request).create(kwargs['name'], - kwargs['cpus'], - kwargs['memory_mb'], - kwargs['local_gb'], - kwargs['prov_mac_address'], - kwargs['pm_address'] or None, - kwargs['pm_user'] or None, - kwargs['pm_password'], - terminal_port) - return cls(node) - - @property - def list_flavors(self): - if not hasattr(self, '_flavors'): - # FIXME: just a mock of used instances, add real values - used_instances = 0 - - if not self.rack or not self.rack.get_resource_class: - return [] - resource_class = self.rack.get_resource_class - - added_flavors = tuskarclient(self.request).flavors\ - .list(resource_class.id) - self._flavors = [] - if added_flavors: - for f in added_flavors: - flavor_obj = Flavor(f) - #flavor_obj.max_vms = f.max_vms - - # FIXME just a mock of used instances, add real values - used_instances += 5 - flavor_obj.used_instances = used_instances - self._flavors.append(flavor_obj) - - return self._flavors - @property - def rack(self): + def mac_address(self): try: - if not hasattr(self, '_rack'): - # FIXME the node.rack association should be stored somewhere - self._rack = None - for rack in Rack.list(self.request): - for node_obj in rack.list_nodes: - if node_obj.id == self.id: - self._rack = rack - - return self._rack + return self._apiresource.interfaces[0]['address'] except Exception: - msg = "Could not obtain Nodes's rack" - LOG.debug(exceptions.error_color(msg)) return None @property @@ -287,24 +252,6 @@ class Node(StringIdAPIResourceWrapper): return 100 - self.running_instances @property - # FIXME: just mock implementation, add proper one - def is_provisioned(self): - return self.status != "unprovisioned" and self.rack - - @property - def alerts(self): - if not hasattr(self, '_alerts'): - self._alerts = [] - return self._alerts - - @property - def mac_address(self): - try: - return self._apiresource.interfaces[0]['address'] - except Exception: - return None - - @property def running_virtual_machines(self): if not hasattr(self, '_running_virtual_machines'): if OVERCLOUD_CREDS: @@ -321,67 +268,115 @@ class Node(StringIdAPIResourceWrapper): return self._running_virtual_machines -class BaremetalNode(Node): - _attrs = ['id', 'pm_address', 'cpus', 'memory_mb', 'service_host', - 'local_gb', 'pm_user'] - - @classmethod - def create(cls, request, **kwargs): - # The pm_address, pm_user and terminal_port need to be None when - # empty for the baremetal vm to work. - # terminal_port needs separate handling because 0 is a valid value. - terminal_port = kwargs['terminal_port'] - if terminal_port == '': - terminal_port = None - node = baremetalclient(request).create(kwargs['name'], - kwargs['cpus'], - kwargs['memory_mb'], - kwargs['local_gb'], - kwargs['prov_mac_address'], - kwargs['pm_address'] or None, - kwargs['pm_user'] or None, - kwargs['pm_password'], - terminal_port) - return cls(node) +class Node(StringIdAPIResourceWrapper): + """ + Wrapper for the Node object returned by the + dummy model. + """ + _attrs = ['id', 'rack', 'nova_baremetal_node_id'] @classmethod def get(cls, request, node_id): - node = cls(baremetalclient(request).get(node_id)) + node = cls(tuskarclient(request).nodes.get(node_id)) node.request = request + return node - # FIXME ugly, fix after demo, make abstraction of instance details - # this is realy not optimal, but i dont hve time do fix it now - instances, more = nova.server_list( - request, - search_opts={'paginate': True}, - all_tenants=True) - - instance_details = {} - for instance in instances: - id = (instance. - _apiresource._info['OS-EXT-SRV-ATTR:hypervisor_hostname']) - instance_details[id] = instance + @classmethod + def list(cls, request): + return [cls(n, request) for n in (tuskarclient(request).nodes.list())] - detail = instance_details.get(node_id) - if detail: - addresses = detail._apiresource.addresses.get('ctlplane') - if addresses: - node.ip_address_other = (", " - .join([addr['addr'] for addr in addresses])) + @property + def get_rack(self): + if not hasattr(self, '_rack'): + if self.rack: + self._rack = Rack.get(self.request, self.rack['id']) + else: + self._rack = None + return self._rack - node.status = detail._apiresource._info['OS-EXT-STS:vm_state'] - node.power_management = "" - if node.pm_user: - node.power_management = node.pm_user + "/********" + @property + def rack_id(self): + if self.rack: + return unicode(self.rack['id']) else: - node.status = 'unprovisioned' + return None - return node + @property + def nova_baremetal_node(self): + if not hasattr(self, '_nova_baremetal_node'): + if self.nova_baremetal_node_id: + self._nova_baremetal_node = BaremetalNode.get( + self.request, + self.nova_baremetal_node_id) + else: + self._nova_baremetal_node = None + return self._nova_baremetal_node - @classmethod - def list(cls, request): - return [cls(n, request) for n in - baremetalclient(request).list()] + def nova_baremetal_node_attribute(self, attr_name): + key = "_%s" % attr_name + if not hasattr(self, key): + if self.nova_baremetal_node: + value = getattr(self.nova_baremetal_node, attr_name, None) + else: + value = None + setattr(self, key, value) + return getattr(self, key) + + @property + def service_host(self): + return self.nova_baremetal_node_attribute('service_host') + + @property + def mac_address(self): + return self.nova_baremetal_node_attribute('mac_address') + + @property + def pm_address(self): + return self.nova_baremetal_node_attribute('pm_address') + + @property + def status(self): + return self.nova_baremetal_node_attribute('status') + + @property + def running_virtual_machines(self): + return self.nova_baremetal_node_attribute('running_virtual_machines') + + @property + def list_flavors(self): + if not hasattr(self, '_flavors'): + # FIXME: just a mock of used instances, add real values + used_instances = 0 + + if not self.rack or not self.get_rack.get_resource_class: + return [] + resource_class = self.get_rack.get_resource_class + + added_flavors = tuskarclient(self.request).flavors\ + .list(resource_class.id) + self._flavors = [] + if added_flavors: + for f in added_flavors: + flavor_obj = Flavor(f) + #flavor_obj.max_vms = f.max_vms + + # FIXME just a mock of used instances, add real values + used_instances += 5 + flavor_obj.used_instances = used_instances + self._flavors.append(flavor_obj) + + return self._flavors + + @property + # FIXME: just mock implementation, add proper one + def is_provisioned(self): + return (self.status != "unprovisioned" and self.rack) + + @property + def alerts(self): + if not hasattr(self, '_alerts'): + self._alerts = [] + return self._alerts class Rack(StringIdAPIResourceWrapper): @@ -648,8 +643,8 @@ class ResourceClass(StringIdAPIResourceWrapper): @property def nodes(self): if not hasattr(self, '_nodes'): - nodes_lists = [rack.list_nodes for rack in self.list_racks] - self._nodes = [node for nodes in nodes_lists for node in nodes] + self._nodes = [n for n in Node.list(self.request) + if n.rack_id in self.racks_ids] return self._nodes @property diff --git a/tuskar_ui/infrastructure/resource_management/nodes/tests.py b/tuskar_ui/infrastructure/resource_management/nodes/tests.py index f1bd3758..045c267d 100644 --- a/tuskar_ui/infrastructure/resource_management/nodes/tests.py +++ b/tuskar_ui/infrastructure/resource_management/nodes/tests.py @@ -40,16 +40,26 @@ class NodeViewTests(test.BaseAdminViewTests): unracked_nodes_table = res.context['unracked_nodes_table'].data self.assertItemsEqual(unracked_nodes_table, unracked_nodes) - @test.create_stubs({tuskar.Node: ('get', 'running_virtual_machines')}) + @test.create_stubs({tuskar.Node: ('get', 'running_virtual_machines', + 'list_flavors'), + tuskar.Rack: ('get',), + tuskar.BaremetalNode: ('get',)}) def test_detail_node(self): node = self.tuskar_nodes.first() + node.request = self.request + rack = self.tuskar_racks.first() + bm_node = self.baremetal_nodes.first() tuskar.Node.get(mox.IsA(http.HttpRequest), node.id).AndReturn(node) - + tuskar.Rack.get(mox.IsA(http.HttpRequest), + rack.id).AndReturn(rack) + tuskar.BaremetalNode.get(mox.IsA(http.HttpRequest), + bm_node.id).AndReturn(bm_node) self.mox.ReplayAll() tuskar.Node.running_virtual_machines = [] + tuskar.Node.list_flavors = [] url = urlresolvers.reverse('horizon:infrastructure:' 'resource_management:nodes:' @@ -62,7 +72,7 @@ class NodeViewTests(test.BaseAdminViewTests): @test.create_stubs({tuskar.Node: ('get',)}) def test_detail_node_exception(self): - node = self.baremetal_nodes.first() + node = self.tuskar_nodes.first() tuskar.Node.get( mox.IsA(http.HttpRequest), diff --git a/tuskar_ui/infrastructure/resource_management/racks/tests.py b/tuskar_ui/infrastructure/resource_management/racks/tests.py index d0addcf7..62cdff95 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/tests.py +++ b/tuskar_ui/infrastructure/resource_management/racks/tests.py @@ -71,7 +71,7 @@ class RackViewTests(test.BaseAdminViewTests): resource_class_id=u'1', location='Tokyo', subnet='1.2.3.4', - nodes=[{'id': '1'}]).AndReturn(None) + nodes=[{'id': '11'}]).AndReturn(None) tuskar.ResourceClass.list( mox.IsA(http.HttpRequest)).AndReturn( self.tuskar_resource_classes.list()) @@ -262,21 +262,21 @@ class RackViewTests(test.BaseAdminViewTests): self.assertMessageCount(success=1) self.assertMessageCount(error=0) - @test.create_stubs({ - tuskar.Rack: ('get', 'list_nodes', 'list_flavors', - 'get_resource_class')}) + @test.create_stubs({tuskar.Rack: ('get', 'list_nodes', 'list_flavors'), + tuskar.ResourceClass: ('get',)}) def test_detail_rack(self): rack = self.tuskar_racks.first() + rack.request = self.request resource_class = self.tuskar_resource_classes.first() tuskar.Rack.get(mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - + tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), + resource_class.id).AndReturn(resource_class) self.mox.ReplayAll() tuskar.Rack.list_nodes = [] tuskar.Rack.list_flavors = [] - tuskar.Rack.get_resource_class = resource_class url = urlresolvers.reverse('horizon:infrastructure:' 'resource_management:racks:detail', diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py index 47d0b7c4..8ba274b7 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py @@ -297,7 +297,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): 'horizon:infrastructure:resource_management:index')) @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', 'list_racks') + tuskar.ResourceClass: ('get', 'list_flavors', 'list_racks', 'nodes') }) def test_detail_get(self): resource_class = self.tuskar_resource_classes.first() @@ -311,6 +311,7 @@ class ResourceClassViewTests(test.BaseAdminViewTests): tuskar.ResourceClass.list_flavors = flavors tuskar.ResourceClass.list_racks = racks + tuskar.ResourceClass.nodes = [] url = urlresolvers.reverse( 'horizon:infrastructure:resource_management:resource_classes:' diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py index 04f01bfc..e018ff5b 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py @@ -154,10 +154,6 @@ class CreateRacks(tuskar_ui.workflows.TableStep): 'resource_classes/_racks_step.html' def contribute(self, data, context): - request = self.workflow.request - context["racks_object_ids"] =\ - request.POST.getlist("racks_object_ids") - context.update(data) return context diff --git a/tuskar_ui/infrastructure/resource_management/tabs.py b/tuskar_ui/infrastructure/resource_management/tabs.py index b42bbe3d..b418fc9e 100644 --- a/tuskar_ui/infrastructure/resource_management/tabs.py +++ b/tuskar_ui/infrastructure/resource_management/tabs.py @@ -85,7 +85,7 @@ class RacksTab(ProvisioningInfoMixin, tabs.TableTab): def get_context_data(self, request): context = super(RacksTab, self).get_context_data(request) try: - context["nodes"] = tuskar.Node.list_unracked(self.request) + context["nodes"] = tuskar.BaremetalNode.list_unracked(self.request) except Exception: context["nodes"] = [] exceptions.handle(request, diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html index a6a4b9ae..e28c04a9 100644 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html +++ b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html @@ -14,7 +14,7 @@ <dt>{% trans "Management IP" %}</dt> <dd>{{ node.pm_address|default:_("None") }}</dd> <dt>{% trans "Power Management" %}</dt> - <dd>{{ node.rack.power_management|default:_("-") }}</dd> + <dd>{{ node.get_rack.power_management|default:_("-") }}</dd> <dt>{% trans "Status" %}</dt> <dd>{{ node.status|default:_("None") }}</dd> </dl> @@ -24,8 +24,8 @@ <hr class="header_rule"> <dl> <dt>{% trans "Rack" %}</dt> - {% if node.rack %} - <dd><a href="{% url 'horizon:infrastructure:resource_management:racks:detail' node.rack.id %}">{{ node.rack.name|default:_("None") }}</a></dd> + {% if node.get_rack %} + <dd><a href="{% url 'horizon:infrastructure:resource_management:racks:detail' node.rack_id %}">{{ node.get_rack.name|default:_("None") }}</a></dd> {% else %} <dd>{% trans "None" %}</dd> {% endif %} @@ -170,7 +170,7 @@ <tr> {% for flavor in node.list_flavors %} <td class="flavor_usage_label"> - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:flavors:detail' node.rack.resource_class.id flavor.id %}">{{ flavor.name }}</a> + <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:flavors:detail' node.get_rack.resource_class.id flavor.id %}">{{ flavor.name }}</a> </td> {% endfor %} </tr> @@ -234,7 +234,7 @@ <div id="most_contacting_racks" class="communication_chart" data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' node.rack.id %}?cond=from" + data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' node.rack_id %}?cond=from" data-time="now" data-size="22"> </div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html index efa0f280..6b9278f0 100644 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html +++ b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html @@ -12,8 +12,8 @@ <span class="separator"></span> <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__racks_tab" >Racks</a> <span class="separator"></span> - {% if node.rack %} - <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' node.rack.id %}">{{ node.rack.name }}</a> + {% if node.get_rack %} + <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' node.rack_id %}">{{ node.get_rack.name }}</a> {% else %} <a href="{% url 'horizon:infrastructure:resource_management:nodes:unracked' %}" >Unracked Nodes</a> {% endif %} diff --git a/tuskar_ui/test/api_tests/tuskar_tests.py b/tuskar_ui/test/api_tests/tuskar_tests.py index 627c316d..be098723 100644 --- a/tuskar_ui/test/api_tests/tuskar_tests.py +++ b/tuskar_ui/test/api_tests/tuskar_tests.py @@ -22,22 +22,6 @@ from tuskar_ui.test import helpers as test class TuskarApiTests(test.APITestCase): - def test_baremetal_node_get(self): - node = self.baremetalclient_nodes.first() - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - baremetal.BareMetalNodeManager.get(node.id).AndReturn(node) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).AndReturn([]) - self.mox.ReplayAll() - - ret_val = api.BaremetalNode.get(self.request, node.id) - self.assertIsInstance(ret_val, api.BaremetalNode) - def test_baremetal_node_create(self): node = self.baremetalclient_nodes.first() @@ -63,7 +47,7 @@ class TuskarApiTests(test.APITestCase): pm_user='user', pm_password='password', terminal_port=0) - self.assertIsInstance(ret_val, api.Node) + self.assertIsInstance(ret_val, api.BaremetalNode) def test_baremetal_node_create_with_empty_pm(self): """ @@ -82,7 +66,23 @@ class TuskarApiTests(test.APITestCase): self.request, name='node', cpus=1, memory_mb=1024, local_gb=10, prov_mac_address='aa:bb:cc:dd:ee', pm_address='', pm_user='', pm_password='', terminal_port='') - self.assertIsInstance(ret_val, api.Node) + self.assertIsInstance(ret_val, api.BaremetalNode) + + def test_baremetal_node_get(self): + node = self.baremetalclient_nodes.first() + + self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') + baremetal.BareMetalNodeManager.get(node.id).AndReturn(node) + + novaclient = self.stub_novaclient() + novaclient.servers = self.mox.CreateMockAnything() + novaclient.servers.list(True, + {'all_tenants': True, + 'limit': 21}).AndReturn([]) + self.mox.ReplayAll() + + ret_val = api.BaremetalNode.get(self.request, node.id) + self.assertIsInstance(ret_val, api.BaremetalNode) def test_baremetal_node_list(self): nodes = self.baremetalclient_nodes_all.list() @@ -93,102 +93,105 @@ class TuskarApiTests(test.APITestCase): ret_val = api.BaremetalNode.list(self.request) for node in ret_val: - self.assertIsInstance(node, api.Node) + self.assertIsInstance(node, api.BaremetalNode) - def test_node_get(self): - node = self.tuskarclient_nodes.first() + def test_baremetal_node_list_unracked(self): + tuskarclient_nodes = self.tuskarclient_nodes.list() + baremetal_nodes = self.baremetalclient_nodes_all.list() - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - baremetal.BareMetalNodeManager.get(node.id).AndReturn(node) + tuskarclient = self.stub_tuskarclient() + tuskarclient.nodes = self.mox.CreateMockAnything() + tuskarclient.nodes.list().AndReturn(tuskarclient_nodes) + + self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'list') + baremetal.BareMetalNodeManager.list().AndReturn(baremetal_nodes) - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).AndReturn([]) self.mox.ReplayAll() - ret_val = api.Node.get(self.request, node.id) - self.assertIsInstance(ret_val, api.Node) + ret_val = api.BaremetalNode.list_unracked(self.request) + for node in ret_val: + self.assertIsInstance(node, api.BaremetalNode) + self.assertEquals(1, len(ret_val)) + + def test_baremetal_node_running_instances(self): + node = self.baremetal_nodes.first() + + self.assertEquals(4, node.running_instances) + + def test_baremetal_node_remaining_capacity(self): + node = self.baremetal_nodes.first() - def test_node_create(self): + self.assertEquals(96, node.remaining_capacity) + + def test_node_get(self): node = self.tuskarclient_nodes.first() - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'create') - baremetal.BareMetalNodeManager.create('node', 1, 1024, 10, - 'aa:bb:cc:dd:ee', '0.0.0.0', 'user', 'password', 0).AndReturn(node) + tuskarclient = self.stub_tuskarclient() + tuskarclient.nodes = self.mox.CreateMockAnything() + tuskarclient.nodes.get(node.id).AndReturn(node) self.mox.ReplayAll() - ret_val = api.Node.create(self.request, name='node', cpus=1, - memory_mb=1024, local_gb=10, prov_mac_address='aa:bb:cc:dd:ee', - pm_address='0.0.0.0', pm_user='user', pm_password='password', - terminal_port=0) + ret_val = api.Node.get(self.request, node.id) self.assertIsInstance(ret_val, api.Node) def test_node_list(self): - nodes = self.tuskarclient_nodes_all.list() + nodes = self.tuskarclient_nodes.list() - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'list') - baremetal.BareMetalNodeManager.list().AndReturn(nodes) + tuskarclient = self.stub_tuskarclient() + tuskarclient.nodes = self.mox.CreateMockAnything() + tuskarclient.nodes.list().AndReturn(nodes) self.mox.ReplayAll() ret_val = api.Node.list(self.request) for node in ret_val: self.assertIsInstance(node, api.Node) - def test_node_list_unracked(self): - nodes = self.tuskarclient_nodes.list() - all_nodes = self.tuskarclient_nodes_all.list() - racks = self.tuskarclient_racks.list() - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'list') - baremetal.BareMetalNodeManager.list().AndReturn(all_nodes) + def test_node_rack(self): + node = self.tuskar_nodes.first() + rack = self.tuskarclient_racks.first() tuskarclient = self.stub_tuskarclient() tuskarclient.racks = self.mox.CreateMockAnything() - tuskarclient.racks.list().MultipleTimes().AndReturn(racks) + tuskarclient.racks.get(rack.id).AndReturn(rack) + self.mox.ReplayAll() + + node.request = self.request + self.assertIsInstance(node.get_rack, api.Rack) + self.assertEquals('1', node.rack_id) + + def test_node_nova_baremetal_node(self): + node = self.tuskar_nodes.first() + bm_node = self.baremetalclient_nodes.first() + + self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') + baremetal.BareMetalNodeManager.get( + node.nova_baremetal_node_id).AndReturn(bm_node) novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() novaclient.servers.list(True, {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).\ - MultipleTimes().AndReturn(n) + 'limit': 21}).AndReturn([]) self.mox.ReplayAll() - ret_val = api.Node.list_unracked(self.request) - for node in ret_val: - self.assertIsInstance(node, api.Node) - self.assertEquals(1, len(ret_val)) + node.request = self.request + n = node.nova_baremetal_node + self.assertIsInstance(n, api.BaremetalNode) + self.assertEquals('11', n.id) def test_node_flavors(self): node = self.tuskar_nodes.first() - nodes = self.tuskarclient_nodes.list() - racks = self.tuskarclient_racks.list() + rack = self.tuskarclient_racks.first() rc = self.tuskarclient_resource_classes.first() flavors = self.tuskarclient_flavors.list() tuskarclient = self.stub_tuskarclient() tuskarclient.racks = self.mox.CreateMockAnything() - tuskarclient.racks.list().AndReturn(racks) + tuskarclient.racks.get(rack.id).AndReturn(rack) tuskarclient.resource_classes = self.mox.CreateMockAnything() tuskarclient.resource_classes.get(rc.id).AndReturn(rc) tuskarclient.flavors = self.mox.CreateMockAnything() tuskarclient.flavors.list(rc.id).AndReturn(flavors) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) self.mox.ReplayAll() node.request = self.request @@ -197,64 +200,28 @@ class TuskarApiTests(test.APITestCase): self.assertIsInstance(flavor, api.Flavor) self.assertEquals(2, len(ret_val)) - def test_node_rack(self): + def test_node_is_provisioned(self): node = self.tuskar_nodes.first() - nodes = self.tuskarclient_nodes.list() - racks = self.tuskarclient_racks.list() + node.request = self.request + bm_node = self.baremetalclient_nodes.first() - tuskarclient = self.stub_tuskarclient() - tuskarclient.racks = self.mox.CreateMockAnything() - tuskarclient.racks.list().AndReturn(racks) + self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') + baremetal.BareMetalNodeManager.get( + node.nova_baremetal_node_id).AndReturn(bm_node) novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() novaclient.servers.list(True, {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) + 'limit': 21}).AndReturn([]) self.mox.ReplayAll() - node.request = self.request - rack = node.rack - self.assertIsInstance(rack, api.Rack) - self.assertEquals('1', rack.id) - - def test_node_running_instances(self): - node = self.tuskar_nodes.first() - - self.assertEquals(4, node.running_instances) - - def test_node_remaining_capacity(self): - node = self.tuskar_nodes.first() - - self.assertEquals(96, node.remaining_capacity) + self.assertFalse(node.is_provisioned) - def test_node_is_provisioned(self): + def test_node_alerts(self): node = self.tuskar_nodes.first() - nodes = self.tuskarclient_nodes.list() - racks = self.tuskarclient_racks.list() - - tuskarclient = self.stub_tuskarclient() - tuskarclient.racks = self.mox.CreateMockAnything() - tuskarclient.racks.list().AndReturn(racks) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) - self.mox.ReplayAll() - node.request = self.request - node.status = 'provisioned' - self.assertTrue(node.is_provisioned) + self.assertEquals([], node.alerts) def test_resource_class_list(self): rcs = self.tuskarclient_resource_classes.list() @@ -375,23 +342,11 @@ class TuskarApiTests(test.APITestCase): def test_resource_class_nodes(self): rc = self.tuskar_resource_classes.first() - racks = self.tuskarclient_racks.list() - nodes = self.baremetalclient_nodes.list() + nodes = self.tuskarclient_nodes.list() tuskarclient = self.stub_tuskarclient() - tuskarclient.racks = self.mox.CreateMockAnything() - tuskarclient.racks.get('1').AndReturn(racks[0]) - tuskarclient.racks.get('2').AndReturn(racks[1]) - - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) + tuskarclient.nodes = self.mox.CreateMockAnything() + tuskarclient.nodes.list().AndReturn(nodes) self.mox.ReplayAll() rc.request = self.request @@ -478,6 +433,7 @@ class TuskarApiTests(test.APITestCase): def test_resource_class_aggregated_alerts(self): rc = self.tuskar_resource_classes.list()[0] rc.request = self.request + nodes = self.tuskarclient_nodes.list() tuskarclient = self.stub_tuskarclient() tuskarclient.racks = self.mox.CreateMockAnything() @@ -485,16 +441,9 @@ class TuskarApiTests(test.APITestCase): tuskarclient.racks.get('1').AndReturn(racks[0]) tuskarclient.racks.get('2').AndReturn(racks[1]) - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - nodes = self.baremetalclient_nodes.list() + tuskarclient.nodes = self.mox.CreateMockAnything() for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) + tuskarclient.nodes.get(n.id).AndReturn(n) self.mox.ReplayAll() @@ -571,17 +520,12 @@ class TuskarApiTests(test.APITestCase): def test_rack_nodes(self): rack = self.tuskar_racks.first() - nodes = self.baremetalclient_nodes.list() + nodes = self.tuskarclient_nodes.list() - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') + tuskarclient = self.stub_tuskarclient() + tuskarclient.nodes = self.mox.CreateMockAnything() for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) + tuskarclient.nodes.get(n.id).AndReturn(n) self.mox.ReplayAll() rack.request = self.request @@ -695,18 +639,12 @@ class TuskarApiTests(test.APITestCase): def test_rack_aggregated_alerts(self): rack = self.tuskar_racks.first() rack.request = self.request + nodes = self.tuskarclient_nodes.list() - self.mox.StubOutWithMock(baremetal.BareMetalNodeManager, 'get') - nodes = self.baremetalclient_nodes.list() + tuskarclient = self.stub_tuskarclient() + tuskarclient.nodes = self.mox.CreateMockAnything() for n in nodes: - baremetal.BareMetalNodeManager.get(n.id).AndReturn(n) - - novaclient = self.stub_novaclient() - novaclient.servers = self.mox.CreateMockAnything() - novaclient.servers.list(True, - {'all_tenants': True, - 'limit': 21}).MultipleTimes().AndReturn([]) - + tuskarclient.nodes.get(n.id).AndReturn(n) self.mox.ReplayAll() for node in rack.aggregated_alerts: diff --git a/tuskar_ui/test/test_data/tuskar_data.py b/tuskar_ui/test/test_data/tuskar_data.py index 68b71fca..39d6c23a 100644 --- a/tuskar_ui/test/test_data/tuskar_data.py +++ b/tuskar_ui/test/test_data/tuskar_data.py @@ -16,6 +16,7 @@ from openstack_dashboard.test.test_data import utils as test_data_utils from novaclient.v1_1.contrib import baremetal from tuskarclient.v1 import flavors +from tuskarclient.v1 import nodes from tuskarclient.v1 import racks from tuskarclient.v1 import resource_classes @@ -129,42 +130,36 @@ def data(TEST): # Nodes TEST.tuskarclient_nodes = test_data_utils.TestDataContainer() TEST.tuskar_nodes = test_data_utils.TestDataContainer() - # FIXME this will be removed once Node/BaremetalNode separation is complete - TEST.tuskarclient_nodes_all = test_data_utils.TestDataContainer() - tuskar_node_1 = baremetal.BareMetalNode( - baremetal.BareMetalNodeManager(None), + tuskar_node_1 = nodes.Node( + nodes.NodeManager(None), {'id': '1', - 'name': 'node1', - 'prov_mac_address': '00-B0-D0-86-AB-F7'}) - tuskar_node_2 = baremetal.BareMetalNode( - baremetal.BareMetalNodeManager(None), + 'nova_baremetal_node_id': '11', + 'rack': {"id": "1"}}) + tuskar_node_2 = nodes.Node( + nodes.NodeManager(None), {'id': '2', - 'name': 'node2', - 'prov_mac_address': '00-B0-D0-86-AB-F8'}) - tuskar_node_3 = baremetal.BareMetalNode( - baremetal.BareMetalNodeManager(None), + 'nova_baremetal_node_id': '12', + 'rack': {"id": "1"}}) + tuskar_node_3 = nodes.Node( + nodes.NodeManager(None), {'id': '3', - 'name': 'node3', - 'prov_mac_address': '00-B0-D0-86-AB-F9'}) - tuskar_node_4 = baremetal.BareMetalNode( - baremetal.BareMetalNodeManager(None), + 'nova_baremetal_node_id': '13', + 'rack': {"id": "1"}}) + tuskar_node_4 = nodes.Node( + nodes.NodeManager(None), {'id': '4', - 'name': 'node4', - 'prov_mac_address': '00-B0-D0-86-AB-F0'}) - tuskar_node_5 = baremetal.BareMetalNode( - baremetal.BareMetalNodeManager(None), - {'id': '5', - 'name': 'node5', - 'prov_mac_address': '00-B0-D0-86-AB-F1'}) + 'nova_baremetal_node_id': '14', + 'rack': {"id": "1"}}) - TEST.tuskarclient_nodes.add(tuskar_node_1, tuskar_node_2, - tuskar_node_3, tuskar_node_4) - TEST.tuskarclient_nodes_all.add(tuskar_node_1, tuskar_node_2, - tuskar_node_3, tuskar_node_4, - tuskar_node_5) - TEST.tuskar_nodes.add(api.Node(tuskar_node_1), api.Node(tuskar_node_2), - api.Node(tuskar_node_3), api.Node(tuskar_node_4)) + TEST.tuskarclient_nodes.add(tuskar_node_1, + tuskar_node_2, + tuskar_node_3, + tuskar_node_4) + TEST.tuskar_nodes.add(api.Node(tuskar_node_1), + api.Node(tuskar_node_2), + api.Node(tuskar_node_3), + api.Node(tuskar_node_4)) TEST.baremetalclient_nodes = test_data_utils.TestDataContainer() TEST.baremetal_nodes = test_data_utils.TestDataContainer() @@ -175,27 +170,27 @@ def data(TEST): node_1 = baremetal.BareMetalNode( baremetal.BareMetalNodeManager(None), - {'id': '1', + {'id': '11', 'name': 'node1', 'prov_mac_address': '00-B0-D0-86-AB-F7'}) node_2 = baremetal.BareMetalNode( baremetal.BareMetalNodeManager(None), - {'id': '2', + {'id': '12', 'name': 'node2', 'prov_mac_address': '00-B0-D0-86-AB-F8'}) node_3 = baremetal.BareMetalNode( baremetal.BareMetalNodeManager(None), - {'id': '3', + {'id': '13', 'name': 'node3', 'prov_mac_address': '00-B0-D0-86-AB-F9'}) node_4 = baremetal.BareMetalNode( baremetal.BareMetalNodeManager(None), - {'id': '4', + {'id': '14', 'name': 'node4', 'prov_mac_address': '00-B0-D0-86-AB-F0'}) node_5 = baremetal.BareMetalNode( baremetal.BareMetalNodeManager(None), - {'id': '5', + {'id': '15', 'name': 'node5', 'prov_mac_address': '00-B0-D0-86-AB-F1'}) |