Use baremetal node id for node detail page
Currently, the node detail page is keyed off the tuskar node id. However, a tuskar node merely maps a rack to a baremetal node, and does not persist if the rack is deleted (while the baremetal node does). This means that the detail page for an unracked node will error out. This patch updates the node detail page (and relevant links) to use the baremetal node id. Change-Id: I69a32226b3848b45b1a58417ea4e209c28c3e43a Closes-Bug: #1252813
This commit is contained in:
parent
f4f51b2421
commit
1219999177
@ -233,6 +233,14 @@ class BaremetalNode(StringIdAPIResourceWrapper):
|
||||
except requests.ConnectionError:
|
||||
return []
|
||||
|
||||
@cached_property
|
||||
def tuskar_node(self):
|
||||
node = next((tuskar_node
|
||||
for tuskar_node in TuskarNode.list(self.request)
|
||||
if tuskar_node.nova_baremetal_node_id == self.id),
|
||||
None)
|
||||
return node
|
||||
|
||||
@property
|
||||
def mac_address(self):
|
||||
try:
|
||||
|
@ -29,8 +29,8 @@ class DeleteNodes(tables.DeleteAction):
|
||||
|
||||
def delete(self, request, obj_id):
|
||||
try:
|
||||
tuskar_node = tuskar.TuskarNode.get(request, obj_id)
|
||||
tuskar_node.remove_from_rack(request)
|
||||
baremetal_node = tuskar.BaremetalNode.get(request, obj_id)
|
||||
baremetal_node.tuskar_node.remove_from_rack(request)
|
||||
except Exception:
|
||||
exceptions.handle(request, _("Error deleting node."))
|
||||
return False
|
||||
|
@ -16,6 +16,7 @@ from django.utils.translation import ugettext_lazy as _ # noqa
|
||||
|
||||
from horizon import messages
|
||||
from horizon import tabs
|
||||
import novaclient
|
||||
import requests
|
||||
|
||||
|
||||
@ -27,15 +28,23 @@ class OverviewTab(tabs.Tab):
|
||||
preload = False
|
||||
|
||||
def get_context_data(self, request):
|
||||
tuskar_node = self.tab_group.kwargs['tuskar_node']
|
||||
try:
|
||||
running_instances = len(tuskar_node.running_virtual_machines)
|
||||
except requests.exceptions.ConnectionError:
|
||||
running_instances = _("Unknown")
|
||||
messages.warning(
|
||||
request,
|
||||
_("Can't retrieve the running instances from the overcloud."))
|
||||
baremetal_node = self.tab_group.kwargs['baremetal_node']
|
||||
tuskar_node = baremetal_node.tuskar_node
|
||||
if tuskar_node:
|
||||
try:
|
||||
running_instances = len(tuskar_node.running_virtual_machines)
|
||||
except (requests.exceptions.ConnectionError,
|
||||
novaclient.exceptions.Unauthorized):
|
||||
running_instances = _("Unknown")
|
||||
messages.warning(
|
||||
request,
|
||||
_("Can't retrieve the running instances"
|
||||
"from the overcloud."))
|
||||
else:
|
||||
running_instances = _("None")
|
||||
|
||||
return {
|
||||
'baremetal_node': baremetal_node,
|
||||
'tuskar_node': tuskar_node,
|
||||
'running_instances': running_instances,
|
||||
}
|
||||
|
@ -42,22 +42,22 @@ class NodeViewTests(test.BaseAdminViewTests):
|
||||
self.assertItemsEqual(unracked_nodes_table, unracked_baremetal_nodes)
|
||||
|
||||
@test.create_stubs({
|
||||
tuskar.TuskarNode: ('get', 'running_virtual_machines', 'list_flavors'),
|
||||
tuskar.Rack: ('get',),
|
||||
tuskar.BaremetalNode: ('get',),
|
||||
tuskar.TuskarNode: ('list', 'running_virtual_machines',
|
||||
'list_flavors'),
|
||||
tuskar.Rack: ('get',),
|
||||
})
|
||||
def test_detail_node(self):
|
||||
tuskar_node = self.tuskar_nodes.first()
|
||||
tuskar_node.request = self.request
|
||||
rack = self.tuskar_racks.first()
|
||||
baremetal_node = self.baremetal_nodes.first()
|
||||
tuskar_nodes = self.tuskar_nodes.list()
|
||||
rack = self.tuskar_racks.first()
|
||||
|
||||
tuskar.TuskarNode.get(mox.IsA(http.HttpRequest),
|
||||
tuskar_node.id).AndReturn(tuskar_node)
|
||||
tuskar.Rack.get(mox.IsA(http.HttpRequest),
|
||||
rack.id).AndReturn(rack)
|
||||
tuskar.BaremetalNode.get(mox.IsA(http.HttpRequest),
|
||||
baremetal_node.id).AndReturn(baremetal_node)
|
||||
tuskar.TuskarNode.list(None).AndReturn(tuskar_nodes)
|
||||
tuskar.Rack.get(None, rack.id).AndReturn(rack)
|
||||
tuskar.BaremetalNode.get(None,
|
||||
baremetal_node.id).AndReturn(baremetal_node)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
tuskar.TuskarNode.running_virtual_machines = []
|
||||
@ -65,23 +65,24 @@ class NodeViewTests(test.BaseAdminViewTests):
|
||||
|
||||
url = urlresolvers.reverse(
|
||||
'horizon:infrastructure:resource_management:nodes:detail',
|
||||
args=[tuskar_node.id])
|
||||
args=[baremetal_node.id])
|
||||
res = self.client.get(url)
|
||||
self.assertTemplateUsed(
|
||||
res, 'infrastructure/resource_management/nodes/detail.html')
|
||||
|
||||
@test.create_stubs({tuskar.TuskarNode: ('get',)})
|
||||
@test.create_stubs({tuskar.BaremetalNode: ('get',)})
|
||||
def test_detail_node_exception(self):
|
||||
tuskar_node = self.tuskar_nodes.first()
|
||||
baremetal_node = self.baremetal_nodes.first()
|
||||
|
||||
tuskar.TuskarNode.get(mox.IsA(http.HttpRequest),
|
||||
tuskar_node.id).AndRaise(self.exceptions.tuskar)
|
||||
tuskar.BaremetalNode.get(
|
||||
mox.IsA(http.HttpRequest),
|
||||
baremetal_node.id).AndRaise(self.exceptions.tuskar)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = urlresolvers.reverse(
|
||||
'horizon:infrastructure:resource_management:nodes:detail',
|
||||
args=[tuskar_node.id])
|
||||
args=[baremetal_node.id])
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertRedirectsNoFollow(
|
||||
|
@ -44,25 +44,27 @@ class DetailView(horizon_tabs.TabView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
context["tuskar_node"] = self.get_data()
|
||||
context["baremetal_node"] = self.get_data()
|
||||
context["tuskar_node"] = self.get_data().tuskar_node
|
||||
return context
|
||||
|
||||
def get_data(self):
|
||||
if not hasattr(self, "_tuskar_node"):
|
||||
tuskar_node_id = self.kwargs['node_id']
|
||||
if not hasattr(self, "_baremetal_node"):
|
||||
baremetal_node_id = self.kwargs['node_id']
|
||||
try:
|
||||
tuskar_node = tuskar.TuskarNode.get(self.request,
|
||||
tuskar_node_id)
|
||||
baremetal_node = tuskar.BaremetalNode.get(self.request,
|
||||
baremetal_node_id)
|
||||
except Exception:
|
||||
redirect = urlresolvers.reverse(
|
||||
'horizon:infrastructure:resource_management:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve details for '
|
||||
'node "%s".') % tuskar_node_id,
|
||||
'node "%s".') % baremetal_node_id,
|
||||
redirect=redirect)
|
||||
self._tuskar_node = tuskar_node
|
||||
return self._tuskar_node
|
||||
self._baremetal_node = baremetal_node
|
||||
return self._baremetal_node
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
tuskar_node = self.get_data()
|
||||
return self.tab_group_class(request, tuskar_node=tuskar_node, **kwargs)
|
||||
baremetal_node = self.get_data()
|
||||
return self.tab_group_class(
|
||||
request, baremetal_node=baremetal_node, **kwargs)
|
||||
|
@ -39,12 +39,12 @@ class NodesTab(tabs.TableTab):
|
||||
def get_nodes_table_data(self):
|
||||
try:
|
||||
rack = self.tab_group.kwargs['rack']
|
||||
tuskar_nodes = rack.list_tuskar_nodes
|
||||
baremetal_nodes = rack.list_baremetal_nodes
|
||||
except Exception:
|
||||
tuskar_nodes = []
|
||||
baremetal_nodes = []
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve node list.'))
|
||||
return tuskar_nodes
|
||||
return baremetal_nodes
|
||||
|
||||
|
||||
class RackDetailTabs(tabs.TabGroup):
|
||||
|
@ -372,41 +372,39 @@ class RackViewTests(test.BaseAdminViewTests):
|
||||
self.assertEquals(res.content, state_json)
|
||||
|
||||
@test.create_stubs({
|
||||
tuskar.Rack: ('get', 'list_baremetal_nodes', 'list_flavors', 'update',
|
||||
'tuskar_node_ids', 'list_tuskar_nodes'),
|
||||
tuskar.TuskarNode: ('get',),
|
||||
tuskar.Rack: ('get', 'list_baremetal_nodes', 'update',
|
||||
'list_tuskar_nodes'),
|
||||
tuskar.BaremetalNode: ('get',),
|
||||
tuskar.TuskarNode: ('list',),
|
||||
})
|
||||
def test_node_delete(self):
|
||||
rack = self.tuskar_racks.first()
|
||||
rack.request = self.request
|
||||
baremetal_nodes = self.baremetal_nodes.list()
|
||||
baremetal_node = baremetal_nodes[0]
|
||||
baremetal_node.request = self.request
|
||||
tuskar_nodes = self.tuskar_nodes.list()
|
||||
tuskar_node = tuskar_nodes[0]
|
||||
|
||||
tuskar.Rack.get(mox.IsA(http.HttpRequest), rack.id).AndReturn(rack)
|
||||
tuskar.BaremetalNode.get(mox.IsA(http.HttpRequest),
|
||||
baremetal_node.id).AndReturn(baremetal_node)
|
||||
tuskar.TuskarNode.list(
|
||||
mox.IsA(http.HttpRequest)).AndReturn(tuskar_nodes)
|
||||
tuskar.Rack.get(None, rack.id).AndReturn(rack) # called by node.rack
|
||||
tuskar.Rack.update(mox.IsA(http.HttpRequest), rack.id, {
|
||||
'baremetal_nodes': [{'id': node.id}
|
||||
for node in baremetal_nodes
|
||||
if node.id != baremetal_node.id],
|
||||
}).AndReturn(rack)
|
||||
|
||||
tuskar.Rack.list_baremetal_nodes = baremetal_nodes
|
||||
tuskar.Rack.list_tuskar_nodes = tuskar_nodes
|
||||
tuskar.Rack.tuskar_node_ids = [t_node.id for t_node in tuskar_nodes]
|
||||
tuskar.Rack.list_flavors = []
|
||||
|
||||
tuskar.Rack.get(mox.IsA(http.HttpRequest), rack.id).AndReturn(rack)
|
||||
tuskar.TuskarNode.get(mox.IsA(http.HttpRequest),
|
||||
tuskar_node.id).AndReturn(tuskar_node)
|
||||
tuskar.BaremetalNode.get(None,
|
||||
baremetal_node.id).AndReturn(baremetal_node)
|
||||
tuskar.Rack.get(None, rack.id).AndReturn(rack) # called by node.rack
|
||||
tuskar.Rack.update(mox.IsA(http.HttpRequest), rack.id, {
|
||||
'baremetal_nodes': [{'id': bm_node.id}
|
||||
for bm_node in baremetal_nodes
|
||||
if bm_node.id != baremetal_node.id],
|
||||
}).AndReturn(rack)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = urlresolvers.reverse(
|
||||
'horizon:infrastructure:resource_management:racks:detail',
|
||||
args=[rack.id])
|
||||
form_data = {'action': 'nodes_table__delete__%s' % tuskar_node.id}
|
||||
form_data = {'action': 'nodes_table__delete__%s' % baremetal_node.id}
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertNoFormErrors(response)
|
||||
self.assertMessageCount(success=1)
|
||||
|
@ -8,15 +8,15 @@
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "MAC Address" %}</dt>
|
||||
<dd>{{ tuskar_node.mac_address|default:_("None") }}</dd>
|
||||
<dd>{{ baremetal_node.mac_address|default:_("None") }}</dd>
|
||||
<dt>{% trans "IPs" %}</dt>
|
||||
<dd>{{ tuskar_node.ip_address_other|default:_("None") }}</dd>
|
||||
<dd>{{ baremetal_node.ip_address_other|default:_("None") }}</dd>
|
||||
<dt>{% trans "Management IP" %}</dt>
|
||||
<dd>{{ tuskar_node.pm_address|default:_("None") }}</dd>
|
||||
<dd>{{ baremetal_node.pm_address|default:_("None") }}</dd>
|
||||
<dt>{% trans "Power Management" %}</dt>
|
||||
<dd>{{ tuskar_node.rack.power_management|default:_("-") }}</dd>
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>{{ tuskar_node.status|default:_("None") }}</dd>
|
||||
<dd>{{ baremetal_node.status|default:_("None") }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="span4">
|
||||
|
@ -13,7 +13,7 @@
|
||||
<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 tuskar_node.rack %}
|
||||
{% if tuskar_node %}
|
||||
<a href="{% url 'horizon:infrastructure:resource_management:racks:detail' tuskar_node.rack_id %}">{{ tuskar_node.rack.name }}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'horizon:infrastructure:resource_management:nodes:unracked' %}" >Unracked Nodes</a>
|
||||
@ -22,4 +22,4 @@
|
||||
</div>
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block name %}{{ tuskar_node.name }}{% endblock %}
|
||||
{% block name %}{{ baremetal_node.mac_address }}{% endblock %}
|
||||
|
@ -174,7 +174,7 @@
|
||||
{% for tuskar_node in rack.aggregated_alerts %}
|
||||
<li>
|
||||
<i class="icon-warning-sign"></i>
|
||||
Node <a href="{% url 'horizon:infrastructure:resource_management:nodes:detail' tuskar_node.id %}">{{ tuskar_node.name }}</a> has some problems
|
||||
Node <a href="{% url 'horizon:infrastructure:resource_management:nodes:detail' tuskar_node.nova_baremetal_node_id %}">{{ tuskar_node.name }}</a> has some problems
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
Loading…
x
Reference in New Issue
Block a user