Skip to content

Commit

Permalink
Translate status in network topology
Browse files Browse the repository at this point in the history
Enables the translation of the status on
network topology.
Provides a json decoder that will resolve
lazy objects like translations.
Moves STATUS_DISPLAY_CHOICES and
ADMIN_STATE_DISPLAY_CHOICES out of the RoutersTable
for easy access to their status from other parts
of the code.
All network objects have their status translated
and a new item called original_status which provides
the untranslated status so the javascript code
is able to display the proper image (green/red)
based on the original status instead of doing it
on the translation.

Change-Id: Ic8cebafe7fbc291fa8933e8d1c2a244be20128e3
Closes-Bug: #1323599
Closes-Bug: #1484113
  • Loading branch information
Itxaka authored and Doug Fish committed Jan 18, 2016
1 parent eb2554a commit 031aed5
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 24 deletions.
4 changes: 2 additions & 2 deletions horizon/static/horizon/js/horizon.networktopology.js
Expand Up @@ -918,7 +918,7 @@ horizon.network_topology = {
object.router_id = port.device_id;
object.url = port.url;
object.port_status = port.status;
object.port_status_css = (port.status === 'ACTIVE') ? 'active' : 'down';
object.port_status_css = (port.original_status === 'ACTIVE') ? 'active' : 'down';
var ipAddress = '';
try {
for (var ip in port.fixed_ips) {
Expand Down Expand Up @@ -962,7 +962,7 @@ horizon.network_topology = {
type:d.type,
delete_label: gettext('Delete'),
status:d.status,
status_class: (d.status === 'ACTIVE') ? 'active' : 'down',
status_class: (d.original_status === 'ACTIVE') ? 'active' : 'down',
status_label: gettext('STATUS'),
id_label: gettext('ID'),
interfaces_label: gettext('Interfaces'),
Expand Down
25 changes: 25 additions & 0 deletions horizon/utils/lazy_encoder.py
@@ -0,0 +1,25 @@
# Copyright 2016 Red Hat, 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.

from django.core.serializers.json import DjangoJSONEncoder
from django.utils.encoding import force_text
from django.utils.functional import Promise


class LazyTranslationEncoder(DjangoJSONEncoder):
"""JSON encoder that resolves lazy objects like translations"""
def default(self, obj):
if isinstance(obj, Promise):
return force_text(obj)
return super(LazyTranslationEncoder, self).default(obj)
18 changes: 13 additions & 5 deletions openstack_dashboard/dashboards/project/network_topology/tests.py
Expand Up @@ -20,6 +20,8 @@
from oslo_serialization import jsonutils

from openstack_dashboard import api
from openstack_dashboard.dashboards.project.network_topology.views import \
TranslationHelper
from openstack_dashboard.test import helpers as test
from openstack_dashboard.usage import quotas

Expand All @@ -28,6 +30,7 @@


class NetworkTopologyTests(test.TestCase):
trans = TranslationHelper()

@test.create_stubs({api.nova: ('server_list',),
api.neutron: ('network_list_for_tenant',
Expand Down Expand Up @@ -83,7 +86,8 @@ def _test_json_view(self, router_enable=True):
expect_server_urls = [
{'id': server.id,
'name': server.name,
'status': server.status,
'status': self.trans.instance[server.status],
'original_status': server.status,
'task': None,
'url': '/project/instances/%s/' % server.id}
for server in self.servers.list()]
Expand All @@ -98,7 +102,8 @@ def _test_json_view(self, router_enable=True):
'external_gateway_info':
router.external_gateway_info,
'name': router.name,
'status': router.status,
'status': self.trans.router[router.status],
'original_status': router.status,
'url': '/project/routers/%s/' % router.id}
for router in routers]
self.assertEqual(expect_router_urls, data['routers'])
Expand All @@ -112,14 +117,16 @@ def _test_json_view(self, router_enable=True):
'url': '/project/networks/%s/detail' % net.id,
'name': net.name,
'router:external': net.router__external,
'status': net.status,
'status': self.trans.network[net.status],
'original_status': net.status,
'subnets': []}
for net in external_networks]
expect_net_urls += [{'id': net.id,
'url': '/project/networks/%s/detail' % net.id,
'name': net.name,
'router:external': net.router__external,
'status': net.status,
'status': self.trans.network[net.status],
'original_status': net.status,
'subnets': [{'cidr': subnet.cidr,
'id': subnet.id,
'url':
Expand All @@ -139,7 +146,8 @@ def _test_json_view(self, router_enable=True):
'device_owner': port.device_owner,
'fixed_ips': port.fixed_ips,
'network_id': port.network_id,
'status': port.status,
'status': self.trans.port[port.status],
'original_status': port.status,
'url': '/project/networks/ports/%s/detail' % port.id}
for port in self.ports.list()]
if router_enable:
Expand Down
55 changes: 49 additions & 6 deletions openstack_dashboard/dashboards/project/network_topology/views.py
Expand Up @@ -17,6 +17,7 @@
# under the License.

import json
import six

from django.conf import settings
from django.core.urlresolvers import reverse
Expand All @@ -26,6 +27,7 @@
from django.views.generic import View # noqa

from horizon import exceptions
from horizon.utils.lazy_encoder import LazyTranslationEncoder
from horizon import views

from openstack_dashboard import api
Expand All @@ -44,6 +46,8 @@

from openstack_dashboard.dashboards.project.instances import\
console as i_console
from openstack_dashboard.dashboards.project.instances.tables import \
STATUS_DISPLAY_CHOICES as instance_choices
from openstack_dashboard.dashboards.project.instances import\
views as i_views
from openstack_dashboard.dashboards.project.instances.workflows import\
Expand All @@ -52,16 +56,48 @@
views as s_views
from openstack_dashboard.dashboards.project.networks.subnets import\
workflows as s_workflows
from openstack_dashboard.dashboards.project.networks.tables import \
DISPLAY_CHOICES as network_display_choices
from openstack_dashboard.dashboards.project.networks.tables import \
STATUS_DISPLAY_CHOICES as network_choices
from openstack_dashboard.dashboards.project.networks import\
views as n_views
from openstack_dashboard.dashboards.project.networks import\
workflows as n_workflows
from openstack_dashboard.dashboards.project.routers.ports.tables import \
DISPLAY_CHOICES as ports_choices
from openstack_dashboard.dashboards.project.routers.ports.tables import \
STATUS_DISPLAY_CHOICES as ports_status_choices
from openstack_dashboard.dashboards.project.routers.ports import\
views as p_views
from openstack_dashboard.dashboards.project.routers.tables import \
ADMIN_STATE_DISPLAY_CHOICES as routers_admin_choices
from openstack_dashboard.dashboards.project.routers.tables import \
STATUS_DISPLAY_CHOICES as routers_status_choices
from openstack_dashboard.dashboards.project.routers import\
views as r_views


class TranslationHelper(object):
"""Helper class to provide the translations of instances, networks,
routers and ports from other parts of the code to the network topology
"""
def __init__(self):
# turn translation tuples into dicts for easy access
self.instance = dict(instance_choices)
self.network = dict(network_choices)
self.network.update(dict(network_display_choices))
self.router = dict(routers_admin_choices)
self.router.update(dict(routers_status_choices))
self.port = dict(ports_choices)
self.port.update(dict(ports_status_choices))
# and turn all the keys into Uppercase for simple access
self.instance = {k.upper(): v for k, v in six.iteritems(self.instance)}
self.network = {k.upper(): v for k, v in six.iteritems(self.network)}
self.router = {k.upper(): v for k, v in six.iteritems(self.router)}
self.port = {k.upper(): v for k, v in six.iteritems(self.port)}


class NTAddInterfaceView(p_views.AddInterfaceView):
success_url = "horizon:project:network_topology:index"
failure_url = "horizon:project:network_topology:index"
Expand Down Expand Up @@ -183,6 +219,7 @@ def get_context_data(self, **kwargs):


class JSONView(View):
trans = TranslationHelper()

@property
def is_router_enabled(self):
Expand Down Expand Up @@ -221,7 +258,8 @@ def _get_servers(self, request):
console = None

server_data = {'name': server.name,
'status': server.status,
'status': self.trans.instance[server.status],
'original_status': server.status,
'task': getattr(server, 'OS-EXT-STS:task_state'),
'id': server.id}
if console:
Expand Down Expand Up @@ -249,7 +287,8 @@ def _get_networks(self, request):
'subnets': [{'id': subnet.id,
'cidr': subnet.cidr}
for subnet in network.subnets],
'status': network.status,
'status': self.trans.network[network.status],
'original_status': network.status,
'router:external': network['router:external']}
self.add_resource_url('horizon:project:networks:subnets:detail',
obj['subnets'])
Expand Down Expand Up @@ -281,7 +320,8 @@ def _get_networks(self, request):
'name': publicnet.name_or_id,
'id': publicnet.id,
'subnets': subnets,
'status': publicnet.status,
'status': self.trans.network[publicnet.status],
'original_status': publicnet.status,
'router:external': publicnet['router:external']})

self.add_resource_url('horizon:project:networks:detail',
Expand All @@ -303,7 +343,8 @@ def _get_routers(self, request):

routers = [{'id': router.id,
'name': router.name_or_id,
'status': router.status,
'status': self.trans.router[router.status],
'original_status': router.status,
'external_gateway_info': router.external_gateway_info}
for router in neutron_routers]
self.add_resource_url('horizon:project:routers:detail', routers)
Expand All @@ -320,7 +361,8 @@ def _get_ports(self, request):
'device_id': port.device_id,
'fixed_ips': port.fixed_ips,
'device_owner': port.device_owner,
'status': port.status}
'status': self.trans.port[port.status],
'original_status': port.status}
for port in neutron_ports
if port.device_owner != 'network:router_ha_interface']
self.add_resource_url('horizon:project:networks:ports:detail',
Expand Down Expand Up @@ -354,5 +396,6 @@ def get(self, request, *args, **kwargs):
'ports': self._get_ports(request),
'routers': self._get_routers(request)}
self._prepare_gateway_ports(data['routers'], data['ports'])
json_string = json.dumps(data, ensure_ascii=False)
json_string = json.dumps(data, cls=LazyTranslationEncoder,
ensure_ascii=False)
return HttpResponse(json_string, content_type='text/json')
19 changes: 10 additions & 9 deletions openstack_dashboard/dashboards/project/routers/tables.py
Expand Up @@ -197,16 +197,17 @@ def filter(self, table, routers, filter_string):
if query in router.name.lower()]


class RoutersTable(tables.DataTable):
STATUS_DISPLAY_CHOICES = (
("active", pgettext_lazy("current status of router", u"Active")),
("error", pgettext_lazy("current status of router", u"Error")),
)
ADMIN_STATE_DISPLAY_CHOICES = (
("up", pgettext_lazy("Admin state of a Router", u"UP")),
("down", pgettext_lazy("Admin state of a Router", u"DOWN")),
)
STATUS_DISPLAY_CHOICES = (
("active", pgettext_lazy("current status of router", u"Active")),
("error", pgettext_lazy("current status of router", u"Error")),
)
ADMIN_STATE_DISPLAY_CHOICES = (
("up", pgettext_lazy("Admin state of a Router", u"UP")),
("down", pgettext_lazy("Admin state of a Router", u"DOWN")),
)


class RoutersTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
link="horizon:project:routers:detail")
Expand Down
4 changes: 2 additions & 2 deletions openstack_dashboard/dashboards/project/routers/views.py
Expand Up @@ -155,9 +155,9 @@ def get_context_data(self, **kwargs):
self.request, "dvr", "get")
context['ha_supported'] = api.neutron.get_feature_permission(
self.request, "l3-ha", "get")
choices = table.STATUS_DISPLAY_CHOICES
choices = rtables.STATUS_DISPLAY_CHOICES
router.status_label = filters.get_display_label(choices, router.status)
choices = table.ADMIN_STATE_DISPLAY_CHOICES
choices = rtables.ADMIN_STATE_DISPLAY_CHOICES
router.admin_state_label = (
filters.get_display_label(choices, router.admin_state))
return context
Expand Down

0 comments on commit 031aed5

Please sign in to comment.