Skip to content

Commit

Permalink
Merge "Added a new attribute - display_choices to Column class, for s…
Browse files Browse the repository at this point in the history
…ubstituting the display value of the statuses provided by Nova to some more meaningful ones in the instance table." into stable/essex
  • Loading branch information
Jenkins authored and openstack-gerrit committed Jun 21, 2012
2 parents c1ac606 + 102cf10 commit 3be6dce
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 14 deletions.
Expand Up @@ -23,6 +23,7 @@
from horizon import api
from horizon import tables
from horizon.templatetags import sizeformat
from horizon.utils.filters import replace_underscores

from .tabs import InstanceDetailTabs, LogTab, VNCTab

Expand Down Expand Up @@ -216,10 +217,6 @@ def get_power_state(instance):
return POWER_STATES.get(getattr(instance, "OS-EXT-STS:power_state", 0), '')


def replace_underscores(string):
return string.replace("_", " ")


class InstancesTable(tables.DataTable):
TASK_STATUS_CHOICES = (
(None, True),
Expand All @@ -231,6 +228,9 @@ class InstancesTable(tables.DataTable):
("paused", True),
("error", False),
)
TASK_DISPLAY_CHOICES = (
("image_snapshot", "Snapshotting"),
)
name = tables.Column("name", link="horizon:nova:instances_and_volumes:" \
"instances:detail",
verbose_name=_("Instance Name"))
Expand All @@ -245,7 +245,8 @@ class InstancesTable(tables.DataTable):
verbose_name=_("Task"),
filters=(title, replace_underscores),
status=True,
status_choices=TASK_STATUS_CHOICES)
status_choices=TASK_STATUS_CHOICES,
display_choices=TASK_DISPLAY_CHOICES)
state = tables.Column(get_power_state,
filters=(title, replace_underscores),
verbose_name=_("Power State"))
Expand Down
42 changes: 42 additions & 0 deletions horizon/dashboards/nova/instances_and_volumes/instances/tests.py
Expand Up @@ -22,6 +22,7 @@
from django.core.urlresolvers import reverse
from mox import IsA, IgnoreArg
from novaclient import exceptions as nova_exceptions
from copy import deepcopy

from horizon import api
from horizon import test
Expand Down Expand Up @@ -267,6 +268,47 @@ def test_instance_vnc_exception(self):
res = self.client.get(url)
self.assertRedirectsNoFollow(res, INDEX_URL)

def test_create_instance_snapshot(self):
server = self.servers.first()
snapshot_server = deepcopy(server)
setattr(snapshot_server, 'OS-EXT-STS:task_state',
"IMAGE_SNAPSHOT")
self.mox.StubOutWithMock(api, 'server_get')
self.mox.StubOutWithMock(api, 'snapshot_create')
self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
self.mox.StubOutWithMock(api, 'image_list_detailed')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'server_delete')
self.mox.StubOutWithMock(api, 'volume_list')
api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
api.snapshot_create(IsA(http.HttpRequest),
server.id,
"snapshot1")
api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
api.snapshot_list_detailed(IsA(http.HttpRequest)).AndReturn([])
api.image_list_detailed(IsA(http.HttpRequest)).AndReturn([])
api.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])

api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn([snapshot_server])
api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
self.mox.ReplayAll()

formData = {'instance_id': server.id,
'method': 'CreateSnapshot',
'tenant_id': server.tenant_id,
'name': 'snapshot1'}
url = reverse('horizon:nova:images_and_snapshots:snapshots:create',
args=[server.id])
redir_url = reverse('horizon:nova:images_and_snapshots:index')
res = self.client.post(url, formData)
self.assertRedirects(res, redir_url)
res = self.client.get(INDEX_URL)
self.assertContains(res, "<td class=\"status_unknown\">"
"Snapshotting</td>", 1)

def test_instance_update_get(self):
server = self.servers.first()

Expand Down
14 changes: 9 additions & 5 deletions horizon/dashboards/syspanel/instances/tables.py
Expand Up @@ -26,7 +26,7 @@
TerminateInstance, EditInstance, ConsoleLink, LogLink, SnapshotLink,
TogglePause, ToggleSuspend, RebootInstance, get_size, UpdateRow,
get_ips, get_power_state)

from horizon.utils.filters import replace_underscores

LOG = logging.getLogger(__name__)

Expand All @@ -50,6 +50,9 @@ class SyspanelInstancesTable(tables.DataTable):
("active", True),
("error", False),
)
TASK_DISPLAY_CHOICES = (
("image_snapshot", "Snapshotting"),
)
tenant = tables.Column("tenant_name", verbose_name=_("Tenant"))
# NOTE(gabriel): Commenting out the user column because all we have
# is an ID, and correlating that at production scale using our current
Expand All @@ -67,17 +70,18 @@ class SyspanelInstancesTable(tables.DataTable):
verbose_name=_("Size"),
classes=('nowrap-col',))
status = tables.Column("status",
filters=(title,),
filters=(title, replace_underscores),
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES)
task = tables.Column("OS-EXT-STS:task_state",
verbose_name=_("Task"),
filters=(title,),
filters=(title, replace_underscores),
status=True,
status_choices=TASK_STATUS_CHOICES)
status_choices=TASK_STATUS_CHOICES,
display_choices=TASK_DISPLAY_CHOICES)
state = tables.Column(get_power_state,
filters=(title,),
filters=(title, replace_underscores),
verbose_name=_("Power State"))

class Meta:
Expand Down
22 changes: 18 additions & 4 deletions horizon/tables/base.py
Expand Up @@ -110,6 +110,11 @@ class Column(html.HTMLElement):
('off', False),
)
.. attribute:: display_choices
A tuple of tuples representing the possible values to substitute
the data when displayed in the column cell.
.. attribute:: empty_value
A string to be used for cells which have no data. Defaults to an
Expand Down Expand Up @@ -157,8 +162,8 @@ class Column(html.HTMLElement):

def __init__(self, transform, verbose_name=None, sortable=False,
link=None, hidden=False, attrs=None, status=False,
status_choices=None, empty_value=None, filters=None,
classes=None):
status_choices=None, display_choices=None,
empty_value=None, filters=None, classes=None):
self.classes = classes or getattr(self, "classes", [])
super(Column, self).__init__()
self.attrs.update(attrs or {})
Expand All @@ -183,6 +188,7 @@ def __init__(self, transform, verbose_name=None, sortable=False,
self.filters = filters or []
if status_choices:
self.status_choices = status_choices
self.display_choices = display_choices

self.creation_counter = Column.creation_counter
Column.creation_counter += 1
Expand Down Expand Up @@ -227,8 +233,16 @@ def get_data(self, datum):
msg = termcolors.colorize(msg, **PALETTE['ERROR'])
LOG.warning(msg)
data = None
for filter_func in self.filters:
data = filter_func(data)
display_value = None
if self.display_choices:
display_value = [display for (value, display) in
self.display_choices
if value.lower() == (data or '').lower()]
if display_value:
data = display_value[0]
else:
for filter_func in self.filters:
data = filter_func(data)
self.table._data_cache[self][datum_id] = data
return self.table._data_cache[self][datum_id]

Expand Down
19 changes: 19 additions & 0 deletions horizon/utils/filters.py
@@ -0,0 +1,19 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 Nebula, Inc.
#
# 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.


def replace_underscores(string):
return string.replace("_", " ")

0 comments on commit 3be6dce

Please sign in to comment.