Add event table in node detail

Partially implements blueprint senlin-dashboard-event

Change-Id: I901ef6ea76e223bb94df3fc11bc68fcbc30465b4
This commit is contained in:
jing.liuqing 2016-01-19 06:48:00 -05:00 committed by Liuqing Jing
parent d4a87777d2
commit 666020fd90
6 changed files with 113 additions and 5 deletions

View File

@ -45,8 +45,8 @@ class Node(base.APIResourceWrapper):
class Event(base.APIResourceWrapper):
_attrs = ['id', 'obj_id', 'timestamp', 'status', 'status_reason',
'action']
_attrs = ['id', 'obj_id', 'obj_name', 'timestamp', 'status',
'status_reason', 'action']
@memoized.memoized

View File

@ -0,0 +1,62 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import tables
from horizon.utils import filters
class EventsTable(tables.DataTable):
STATUS_CHOICES = (
("INIT", None),
("ACTIVE", True),
("ERROR", False),
("DELETED", False),
("WARNING", None),
("CREATING", None),
("UPDATING", None),
("DELETING", None),
)
STATUS_DISPLAY_CHOICES = (
("INIT", pgettext_lazy("Current status of the event", u"INIT")),
("ACTIVE", pgettext_lazy("Current status of the event", u"ACTIVE")),
("ERROR", pgettext_lazy("Current status of the event", u"ERROR")),
("DELETED", pgettext_lazy("Current status of the event", u"DELETED")),
("WARNING", pgettext_lazy("Current status of the event", u"WARNING")),
("CREATING",
pgettext_lazy("Current status of the event", u"CREATING")),
("UPDATING",
pgettext_lazy("Current status of the event", u"UPDATING")),
("DELETING",
pgettext_lazy("Current status of the event", u"DELETING")),
)
obj_id = tables.Column("obj_id", verbose_name=_("Object ID"))
obj_name = tables.Column("obj_name", verbose_name=_("Object Name"))
status = tables.Column("status",
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES,
display_choices=STATUS_DISPLAY_CHOICES)
status_reason = tables.Column("status_reason",
verbose_name=_("Status Reason"))
action = tables.Column("action", verbose_name=_("Action"))
timestamp = tables.Column("timestamp",
verbose_name=_("Timestamp"),
filters=(filters.parse_isotime,))
class Meta(object):
name = "event"
verbose_name = _("Event")

View File

@ -12,8 +12,12 @@
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tabs
from senlin_dashboard.api import senlin
from senlin_dashboard.cluster.nodes import event_tables
class OverviewTab(tabs.Tab):
name = _("Overview")
@ -24,6 +28,25 @@ class OverviewTab(tabs.Tab):
return {"node": self.tab_group.kwargs['node']}
class EventTab(tabs.TableTab):
name = _("Event")
slug = "event"
table_classes = (event_tables.EventsTable,)
template_name = "cluster/nodes/_detail_event.html"
preload = False
def get_event_data(self):
node_id = self.tab_group.kwargs['node_id']
try:
params = {"obj_id": node_id}
events = senlin.event_list(self.request, params)
except Exception:
events = []
exceptions.handle(self.request,
_('Unable to retrieve node event list.'))
return sorted(events, reverse=True, key=lambda y: y.timestamp)
class NodeDetailTabs(tabs.TabGroup):
slug = "node_details"
tabs = (OverviewTab,)
tabs = (OverviewTab, EventTab)

View File

@ -0,0 +1,5 @@
<div class="row-fluid">
<div class="span12">
{{ table.render }}
</div>
</div>

View File

@ -22,7 +22,8 @@ from senlin_dashboard.test import helpers as test
NODE_INDEX_URL = reverse('horizon:cluster:nodes:index')
NODE_CREATE_URL = reverse('horizon:cluster:nodes:create')
NODE_DETAIL_URL = reverse('horizon:cluster:nodes:detail', args=[u'1'])
NODE_DETAIL_URL = reverse('horizon:cluster:nodes:detail',
args=[u'123456'])
class NodesTest(test.TestCase):
@ -94,9 +95,25 @@ class NodesTest(test.TestCase):
def test_node_detail(self):
node = self.nodes.list()[0]
api.senlin.node_get(
IsA(http.HttpRequest), u'1').AndReturn(node)
IsA(http.HttpRequest), u'123456').AndReturn(node)
self.mox.ReplayAll()
res = self.client.get(NODE_DETAIL_URL)
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
self.assertContains(res, 'test-node')
@test.create_stubs({api.senlin: ('event_list',
'node_get')})
def test_node_event(self):
events = self.events.list()
node = self.nodes.list()[0]
api.senlin.node_get(
IsA(http.HttpRequest), u'123456').AndReturn(node)
api.senlin.event_list(
IsA(http.HttpRequest),
params={'obj_id': u'123456'}).AndReturn(events)
self.mox.ReplayAll()
res = self.client.get(NODE_DETAIL_URL + '?tab=node_details__event')
self.assertTemplateUsed(res, 'cluster/nodes/_detail_event.html')
self.assertContains(res, '123456')

View File

@ -63,6 +63,7 @@ def data(TEST):
# Nodes
TEST.nodes = test_data_utils.TestDataContainer()
node_1 = mock.Mock()
node_1.id = "123456"
node_1.name = "test-node"
TEST.nodes.add(node_1)