Update node detail page for Juno
Node detail page updated for Juno wireframes. Data on page uses correct API calls. Additional work needed: * styling * graphs * mapping from status to a 'pretty status' (for example, from ACTIVE to Provisioned As part of this work, the node api is corrected to pull the correct Nova server mock data. Partial-Implements: blueprint node-details-attribute-update Change-Id: I38d8bae44a9af0bbc1b598be5c5c58940d6c9b1c
This commit is contained in:
@@ -127,7 +127,7 @@ class Stack(base.APIResourceWrapper):
|
||||
r.stack_id == self.id]
|
||||
|
||||
if not with_joins:
|
||||
return [Resource(r, request=self._request)
|
||||
return [Resource(r, request=self._request, stack=self)
|
||||
for r in resources]
|
||||
|
||||
nodes_dict = utils.list_to_dict(node.Node.list(self._request,
|
||||
@@ -137,7 +137,7 @@ class Stack(base.APIResourceWrapper):
|
||||
for r in resources:
|
||||
joined_resources.append(
|
||||
Resource(r, node=nodes_dict.get(r.physical_resource_id, None),
|
||||
request=self._request))
|
||||
request=self._request, stack=self))
|
||||
# TODO(lsmola) I want just resources with nova instance
|
||||
# this could be probably filtered a better way, investigate
|
||||
return [r for r in joined_resources if r.node is not None]
|
||||
@@ -329,6 +329,8 @@ class Resource(base.APIResourceWrapper):
|
||||
self._request = request
|
||||
if 'node' in kwargs:
|
||||
self._node = kwargs['node']
|
||||
if 'stack' in kwargs:
|
||||
self._stack = kwargs['stack']
|
||||
|
||||
@classmethod
|
||||
def get(cls, request, stack, resource_name):
|
||||
@@ -349,7 +351,7 @@ class Resource(base.APIResourceWrapper):
|
||||
"""
|
||||
for r in TEST_DATA.heatclient_resources.list():
|
||||
if r.stack_id == stack.id and r.resource_name == resource_name:
|
||||
return cls(stack, request=request)
|
||||
return cls(r, request=request, stack=stack)
|
||||
|
||||
@classmethod
|
||||
def get_by_node(cls, request, node):
|
||||
@@ -416,3 +418,14 @@ class Resource(base.APIResourceWrapper):
|
||||
return node.Node.get_by_instance_uuid(self._request,
|
||||
self.physical_resource_id)
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def stack(self):
|
||||
"""Return the Stack associated with this Resource
|
||||
|
||||
:return: Stack associated with this Resource, or None if no
|
||||
Stack is associated
|
||||
:rtype: tuskar_ui.api.heat.Stack
|
||||
"""
|
||||
if hasattr(self, '_stack'):
|
||||
return self._stack
|
||||
|
||||
@@ -339,6 +339,12 @@ class BareMetalNode(base.APIResourceWrapper):
|
||||
'local_disk': self.local_gb * 1024.0 * 1024.0 * 1024.0
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def driver(self):
|
||||
"""Return driver for this BareMetalNode
|
||||
"""
|
||||
return "IPMI + PXE"
|
||||
|
||||
@cached_property
|
||||
def driver_info(self):
|
||||
"""Return driver_info for this BareMetalNode
|
||||
@@ -419,7 +425,11 @@ class Node(base.APIResourceWrapper):
|
||||
def get(cls, request, uuid):
|
||||
node = NodeClient(request).node_class.get(request, uuid)
|
||||
if node.instance_uuid is not None:
|
||||
server = TEST_DATA.novaclient_servers.first()
|
||||
for server in TEST_DATA.novaclient_servers.list():
|
||||
if server.id == node.instance_uuid:
|
||||
break
|
||||
else:
|
||||
server = None
|
||||
return cls(node, instance=server, request=request)
|
||||
|
||||
return cls(node)
|
||||
@@ -429,7 +439,11 @@ class Node(base.APIResourceWrapper):
|
||||
def get_by_instance_uuid(cls, request, instance_uuid):
|
||||
node = NodeClient(request).node_class.get_by_instance_uuid(
|
||||
request, instance_uuid)
|
||||
server = TEST_DATA.novaclient_servers.first()
|
||||
for server in TEST_DATA.novaclient_servers.list():
|
||||
if server.id == node.instance_uuid:
|
||||
break
|
||||
else:
|
||||
server = None
|
||||
return cls(node, instance=server, request=request)
|
||||
|
||||
@classmethod
|
||||
@@ -467,10 +481,9 @@ class Node(base.APIResourceWrapper):
|
||||
return self._instance
|
||||
|
||||
if self.instance_uuid:
|
||||
server = TEST_DATA.novaclient_servers.first()
|
||||
return server
|
||||
|
||||
return None
|
||||
for server in TEST_DATA.novaclient_servers.list():
|
||||
if server.id == self.instance_uuid:
|
||||
return server
|
||||
|
||||
@cached_property
|
||||
def image_name(self):
|
||||
@@ -483,13 +496,21 @@ class Node(base.APIResourceWrapper):
|
||||
"""
|
||||
if self.instance is None:
|
||||
return
|
||||
return image_get(self._request, self.instance.image['id']).name
|
||||
for image in TEST_DATA.glanceclient_images.list():
|
||||
if image.id == self.instance.image['id']:
|
||||
return image.name
|
||||
|
||||
@cached_property
|
||||
def instance_status(self):
|
||||
return getattr(getattr(self, 'instance', None),
|
||||
'status', None)
|
||||
|
||||
@cached_property
|
||||
def provisioning_status(self):
|
||||
if self.instance_uuid:
|
||||
return _("Provisioned")
|
||||
return _("Free")
|
||||
|
||||
|
||||
def filter_nodes(nodes, healthy=None):
|
||||
"""Filters the list of Nodes and returns the filtered list.
|
||||
|
||||
@@ -9,16 +9,7 @@
|
||||
{% block main %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>{% trans "Info" %}</h4>
|
||||
<dl class="clearfix">
|
||||
<dt>{% trans "MAC Addresses" %}</dt>
|
||||
<dd>{{ node.addresses|join:", "|default:"—" }}</dd>
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ node.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Instance UUID" %}</dt>
|
||||
<dd>{{ node.instance_uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Driver" %}</dt>
|
||||
<dd>{{ node.driver|default:"—" }}</dd>
|
||||
<dt>{% trans "Power state" %}</dt>
|
||||
<dd>{{ node.power_state|default:"—" }}</dd>
|
||||
</dl>
|
||||
@@ -26,23 +17,42 @@
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<h4>{% trans "Driver Info" %}</h4>
|
||||
<h4>{% trans "Inventory" %}</h4>
|
||||
<dl class="clearfix">
|
||||
<dt>{% trans "IPMI address" %}</dt>
|
||||
<dd>{{ node.driver_info.ipmi_address|default:"—" }}</dd>
|
||||
<dt>{% trans "IPMI username" %}</dt>
|
||||
<dd>{{ node.driver_info.ipmi_username|default:"—" }}</dd>
|
||||
<dt>{% trans "Node UUID" %}</dt>
|
||||
<dd>{{ node.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Driver" %}</dt>
|
||||
<dd>{{ node.driver|default:"—" }}</dd>
|
||||
<dt>{% trans "Network Cards" %}</dt>
|
||||
<dd>{{ node.addresses|length }}</dd>
|
||||
<dt>{% trans "Registered HW" %}</dt>
|
||||
<dd>
|
||||
{{ node.properties.cpu|default:"—" }} {% trans "CPU" %}<br />
|
||||
{{ node.properties.ram|filesizeformat|default:"—" }} {% trans "RAM" %}<br />
|
||||
{{ node.properties.local_disk|filesizeformat|default:"—" }} {% trans "HDD" %}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<h4>{% trans "Properties" %}</h4>
|
||||
<h4>{% trans "Deployment" %}</h4>
|
||||
<dl class="clearfix">
|
||||
<dt>{% trans "Local disk" %}</dt>
|
||||
<dd>{{ node.properties.local_disk|filesizeformat|default:"—" }}</dd>
|
||||
<dt>{% trans "RAM" %}</dt>
|
||||
<dd>{{ node.properties.ram|filesizeformat|default:"—" }}</dd>
|
||||
<dt>{% trans "CPU" %}</dt>
|
||||
<dd>{{ node.properties.cpu|default:"—" }}</dd>
|
||||
<dt>{% trans "Deployment Role" %}</dt>
|
||||
{% if stack and role %}
|
||||
<dd><a href="{% url 'horizon:infrastructure:overcloud:role' stack.id role.id %}">{{ role.name }}</a></dd>
|
||||
{% else %}
|
||||
<dd>—</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Provisioning" %}</dt>
|
||||
<dd>
|
||||
{{ node.provisioning_status|default:"—" }}
|
||||
{% if node.instance_uuid %}
|
||||
<br />{{ node.instance.created }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{% trans "Image" %}</dt>
|
||||
<dd>{{ node.image_name|default:"—" }}</dd>
|
||||
<dt>{% trans "Instance UUID" %}</dt>
|
||||
<dd>{{ node.instance_uuid|default:"—" }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,7 @@ from django import http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import base
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms as horizon_forms
|
||||
from horizon import tabs as horizon_tabs
|
||||
from horizon import views as horizon_views
|
||||
@@ -79,6 +80,12 @@ class DetailView(horizon_views.APIView):
|
||||
redirect = reverse_lazy('horizon:infrastructure:nodes:index')
|
||||
node = api.node.Node.get(request, node_uuid, _error_redirect=redirect)
|
||||
context['node'] = node
|
||||
try:
|
||||
resource = api.heat.Resource.get_by_node(request, node)
|
||||
context['role'] = resource.role
|
||||
context['stack'] = resource.stack
|
||||
except exceptions.NotFound:
|
||||
pass
|
||||
if api_base.is_service_enabled(request, 'metering'):
|
||||
context['meters'] = (
|
||||
('cpu', _('CPU')),
|
||||
|
||||
@@ -113,7 +113,7 @@ class NodeAPITests(test.APITestCase):
|
||||
with patch('openstack_dashboard.api.glance.image_get',
|
||||
return_value=image):
|
||||
ret_val = api.node.Node(node).image_name
|
||||
self.assertEqual(ret_val, 'overcloud-control')
|
||||
self.assertEqual(ret_val, 'overcloud-compute')
|
||||
|
||||
def test_node_addresses_no_ironic(self):
|
||||
node = self.baremetalclient_nodes.first()
|
||||
|
||||
@@ -157,7 +157,8 @@ def data(TEST):
|
||||
servers.ServerManager(None),
|
||||
{'id': 'aa',
|
||||
'name': 'Compute',
|
||||
'image': {'id': 1},
|
||||
'created': '2014-06-26T20:38:06Z',
|
||||
'image': {'id': '1'},
|
||||
'flavor': {
|
||||
'id': '1',
|
||||
},
|
||||
@@ -166,7 +167,8 @@ def data(TEST):
|
||||
servers.ServerManager(None),
|
||||
{'id': 'bb',
|
||||
'name': 'Controller',
|
||||
'image': {'id': 2},
|
||||
'created': '2014-06-27T20:38:06Z',
|
||||
'image': {'id': '2'},
|
||||
'flavor': {
|
||||
'id': '2',
|
||||
},
|
||||
@@ -175,7 +177,8 @@ def data(TEST):
|
||||
servers.ServerManager(None),
|
||||
{'id': 'cc',
|
||||
'name': 'Compute',
|
||||
'image': {'id': 1},
|
||||
'created': '2014-06-28T20:38:06Z',
|
||||
'image': {'id': '1'},
|
||||
'flavor': {
|
||||
'id': '1',
|
||||
},
|
||||
@@ -184,7 +187,8 @@ def data(TEST):
|
||||
servers.ServerManager(None),
|
||||
{'id': 'dd',
|
||||
'name': 'Compute',
|
||||
'image': {'id': 1},
|
||||
'created': '2014-06-29T20:38:06Z',
|
||||
'image': {'id': '1'},
|
||||
'flavor': {
|
||||
'id': '1',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user