Implement network availability zone column in network list

If the 'network_availability_zone'-extension is enabled, this patch adds a
column in the Networks-table named 'Availability Zones'.

Change-Id: Iea2bac351b922a0d267c4a55e0d74f6c2639d967
Partial-Bug: #1725617
This commit is contained in:
Trygve Vea 2017-10-21 11:36:29 +00:00
parent cb6fcc1d7a
commit 2949a9800f
5 changed files with 138 additions and 10 deletions

View File

@ -428,6 +428,9 @@ class NetworkSubnetTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network-ip-availability').AndReturn(True)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'network_availability_zone')\
.MultipleTimes().AndReturn(True)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'dhcp_agent_scheduler')\
.MultipleTimes().AndReturn(True)

View File

@ -106,6 +106,13 @@ DISPLAY_CHOICES = (
)
def get_availability_zones(network):
if 'availability_zones' in network and network.availability_zones:
return ', '.join(network.availability_zones)
else:
return _("-")
class AdminNetworksFilterAction(project_tables.ProjectNetworksFilterAction):
name = "filter_admin_networks"
filter_choices = (('project', _("Project ="), True),) +\
@ -131,6 +138,8 @@ class NetworksTable(tables.DataTable):
admin_state = tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=DISPLAY_CHOICES)
availability_zones = tables.Column(get_availability_zones,
verbose_name=_("Availability Zones"))
def get_object_display(self, network):
return network.name_or_id
@ -147,6 +156,15 @@ class NetworksTable(tables.DataTable):
request, data=data,
needs_form_wrapper=needs_form_wrapper,
**kwargs)
try:
if not api.neutron.is_extension_supported(
request, "network_availability_zone"):
del self.columns["availability_zones"]
except Exception:
msg = _("Unable to check if network availability zone extension "
"is supported")
exceptions.handle(self.request, msg)
del self.columns['availability_zones']
try:
if not api.neutron.is_extension_supported(request,
'dhcp_agent_scheduler'):

View File

@ -43,6 +43,9 @@ class NetworkTests(test.BaseAdminViewTests):
.AndReturn(self.networks.list())
api.keystone.tenant_list(IsA(http.HttpRequest))\
.AndReturn([tenants, False])
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
for network in self.networks.list():
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
@ -70,6 +73,9 @@ class NetworkTests(test.BaseAdminViewTests):
def test_index_network_list_exception(self):
api.neutron.network_list(IsA(http.HttpRequest)) \
.AndRaise(self.exceptions.neutron)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -117,6 +123,9 @@ class NetworkTests(test.BaseAdminViewTests):
'mac-learning') \
.AndReturn(mac_learning)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -155,6 +164,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network-ip-availability').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -192,6 +204,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'mac-learning')\
.AndReturn(mac_learning)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -232,6 +247,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -333,6 +351,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -389,6 +410,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network-ip-availability').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'dhcp_agent_scheduler')\
.AndReturn(True)
@ -772,6 +796,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.list_dhcp_agent_hosting_networks(IsA(http.HttpRequest),
network.id).\
AndReturn(self.agents.list())
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -802,6 +829,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.list_dhcp_agent_hosting_networks(IsA(http.HttpRequest),
network.id).\
AndReturn(self.agents.list())
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -825,6 +855,9 @@ class NetworkTests(test.BaseAdminViewTests):
@test.create_stubs({api.neutron: ('is_extension_supported',)})
@test.update_settings(FILTER_DATA_FIRST={'admin.networks': True})
def test_networks_list_with_admin_filter_first(self):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network_availability_zone').AndReturn(True)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)

View File

@ -150,6 +150,13 @@ STATUS_DISPLAY_CHOICES = (
)
def get_availability_zones(network):
if 'availability_zones' in network and network.availability_zones:
return ', '.join(network.availability_zones)
else:
return _("-")
class ProjectNetworksFilterAction(tables.FilterAction):
name = "filter_project_networks"
filter_type = "server"
@ -178,6 +185,24 @@ class NetworksTable(tables.DataTable):
admin_state = tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=DISPLAY_CHOICES)
availability_zones = tables.Column(get_availability_zones,
verbose_name=_("Availability Zones"))
def __init__(self, request, data=None, needs_form_wrapper=None, **kwargs):
super(NetworksTable, self).__init__(
request,
data=data,
needs_form_wrapper=needs_form_wrapper,
**kwargs)
try:
if not api.neutron.is_extension_supported(
request, "network_availability_zone"):
del self.columns["availability_zones"]
except Exception:
msg = _("Unable to check if network availability zone extension "
"is supported")
exceptions.handle(self.request, msg)
del self.columns['availability_zones']
def get_object_display(self, network):
return network.name_or_id

View File

@ -123,7 +123,8 @@ class NetworkStubMixin(object):
class NetworkTests(test.TestCase, NetworkStubMixin):
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_index(self):
quota_data = self.quota_usages.first()
@ -136,6 +137,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
@ -144,7 +148,8 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
networks = res.context['networks_table'].data
self.assertItemsEqual(networks, self.networks.list())
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_index_network_list_exception(self):
quota_data = self.neutron_quota_usages.first()
@ -155,6 +160,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
res = self.client.get(INDEX_URL)
@ -194,6 +202,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:project:networks:detail',
@ -219,6 +230,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:project:networks:subnets_tab',
@ -290,6 +304,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:project:networks:subnets_tab',
@ -330,6 +347,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:project:networks:subnets_tab',
@ -911,7 +931,8 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
@test.create_stubs({api.neutron: ('network_get',
'network_list',
'network_delete')})
'network_delete',
'is_extension_supported')})
def test_delete_network_no_subnet(self):
network = self.networks.first()
network.subnets = []
@ -919,6 +940,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
network.id,
expand_subnet=False)\
.AndReturn(network)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self._stub_net_list()
api.neutron.network_delete(IsA(http.HttpRequest), network.id)
@ -931,7 +955,8 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
@test.create_stubs({api.neutron: ('network_get',
'network_list',
'network_delete',
'subnet_delete')})
'subnet_delete',
'is_extension_supported')})
def test_delete_network_with_subnet(self):
network = self.networks.first()
network.subnets = [subnet.id for subnet in network.subnets]
@ -941,6 +966,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
network.id,
expand_subnet=False)\
.AndReturn(network)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self._stub_net_list()
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id)
@ -956,7 +984,8 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
@test.create_stubs({api.neutron: ('network_get',
'network_list',
'network_delete',
'subnet_delete')})
'subnet_delete',
'is_extension_supported')})
def test_delete_network_exception(self):
network = self.networks.first()
network.subnets = [subnet.id for subnet in network.subnets]
@ -966,6 +995,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
network.id,
expand_subnet=False)\
.AndReturn(network)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self._stub_net_list()
api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id)
api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id)
@ -999,6 +1031,9 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
@ -1028,6 +1063,9 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
@ -1042,7 +1080,8 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
"The create button should be disabled")
return button
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_network_create_button_disabled_when_quota_exceeded_index(self):
networks_tables.CreateNetwork()
@ -1052,7 +1091,8 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
self._test_create_button_disabled_when_quota_exceeded(_find_net_button,
network_quota=0)
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_subnet_create_button_disabled_when_quota_exceeded_index(self):
network_id = self.networks.first().id
@ -1065,7 +1105,8 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
self._test_create_button_disabled_when_quota_exceeded(
_find_subnet_button, subnet_quota=0)
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_network_create_button_shown_when_quota_disabled_index(self):
# if quota_data doesnt contain a networks["available"] key its disabled
@ -1074,7 +1115,8 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
lambda res: self.getAndAssertTableAction(res, 'networks', 'create')
)
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_subnet_create_button_shown_when_quota_disabled_index(self):
# if quota_data doesnt contain a subnets["available"] key, its disabled
@ -1106,6 +1148,9 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
@ -1135,7 +1180,8 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
self.assertNotIn('disabled', create_action.classes,
'The create button should be enabled')
@test.create_stubs({api.neutron: ('network_list',),
@test.create_stubs({api.neutron: ('network_list',
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_create_button_attributes(self):
create_action = self._test_create_button_shown_when_quota_disabled(
@ -1184,6 +1230,9 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('ports',)) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
.MultipleTimes().AndReturn(True)
self.mox.ReplayAll()