Translate status in network topology
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
This commit is contained in:
parent
eb2554ad9b
commit
031aed50a3
@ -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) {
|
||||
@ -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'),
|
||||
|
25
horizon/utils/lazy_encoder.py
Normal file
25
horizon/utils/lazy_encoder.py
Normal file
@ -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)
|
@ -20,6 +20,8 @@ from mox3.mox import IsA # noqa
|
||||
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
|
||||
|
||||
@ -28,6 +30,7 @@ INDEX_URL = reverse('horizon:project:network_topology:index')
|
||||
|
||||
|
||||
class NetworkTopologyTests(test.TestCase):
|
||||
trans = TranslationHelper()
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',),
|
||||
api.neutron: ('network_list_for_tenant',
|
||||
@ -83,7 +86,8 @@ class NetworkTopologyTests(test.TestCase):
|
||||
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()]
|
||||
@ -98,7 +102,8 @@ class NetworkTopologyTests(test.TestCase):
|
||||
'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'])
|
||||
@ -112,14 +117,16 @@ class NetworkTopologyTests(test.TestCase):
|
||||
'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':
|
||||
@ -139,7 +146,8 @@ class NetworkTopologyTests(test.TestCase):
|
||||
'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:
|
||||
|
@ -17,6 +17,7 @@
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import six
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
@ -26,6 +27,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
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
|
||||
@ -44,6 +46,8 @@ from openstack_dashboard.dashboards.project.network_topology.subnets \
|
||||
|
||||
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\
|
||||
@ -52,16 +56,48 @@ from openstack_dashboard.dashboards.project.networks.subnets import\
|
||||
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"
|
||||
@ -183,6 +219,7 @@ class NetworkTopologyView(views.HorizonTemplateView):
|
||||
|
||||
|
||||
class JSONView(View):
|
||||
trans = TranslationHelper()
|
||||
|
||||
@property
|
||||
def is_router_enabled(self):
|
||||
@ -221,7 +258,8 @@ class JSONView(View):
|
||||
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:
|
||||
@ -249,7 +287,8 @@ class JSONView(View):
|
||||
'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'])
|
||||
@ -281,7 +320,8 @@ class JSONView(View):
|
||||
'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',
|
||||
@ -303,7 +343,8 @@ class JSONView(View):
|
||||
|
||||
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)
|
||||
@ -320,7 +361,8 @@ class JSONView(View):
|
||||
'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',
|
||||
@ -354,5 +396,6 @@ class JSONView(View):
|
||||
'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')
|
||||
|
@ -197,16 +197,17 @@ class RoutersFilterAction(tables.FilterAction):
|
||||
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")
|
||||
|
@ -155,9 +155,9 @@ class DetailView(tabs.TabbedTableView):
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user