Disable Floating IP features if Neutron router is disabled
If the config option 'enable_router' is set to False, Floating IP features are disabled when Neutron is enabled. It does not affect when Neutron is disabled. It also adds unit tests for api.network.servers_update_addresses which is affected by this change. Completes blueprint hide-router-panel-by-config Closes-Bug: #1292022 Change-Id: Ib63c6a0e7bb5661d4a60d10a1722fdad978b50bb
This commit is contained in:
parent
1100169130
commit
936fc59aa8
@ -514,10 +514,11 @@ available.
|
||||
|
||||
Default: ``True``
|
||||
|
||||
Enable (True) or disable (False) the router panel. If your neutron
|
||||
has no support for Layer-3 router features, or you do no not wish to
|
||||
provide the Layer-3 features through the Dashboard, this should be set to
|
||||
``False``.
|
||||
Enable (True) or disable (False) the panels and menus related
|
||||
to router and Floating IP features. This option only affects
|
||||
when Neutron is enabled. If your neutron has no support for
|
||||
Layer-3 features, or you do no not wish to provide the Layer-3
|
||||
features through the Dashboard, this should be set to ``False``.
|
||||
|
||||
``enable_distributed_router``:
|
||||
|
||||
|
@ -88,6 +88,10 @@ def floating_ip_simple_associate_supported(request):
|
||||
return NetworkClient(request).floating_ips.is_simple_associate_supported()
|
||||
|
||||
|
||||
def floating_ip_supported(request):
|
||||
return NetworkClient(request).floating_ips.is_supported()
|
||||
|
||||
|
||||
def security_group_list(request):
|
||||
return NetworkClient(request).secgroups.list()
|
||||
|
||||
|
@ -131,6 +131,11 @@ class FloatingIpManager(object):
|
||||
"""Returns True if the default floating IP pool is enabled."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_supported(self):
|
||||
"""Returns True if floating IP feature is supported."""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class SecurityGroupManager(object):
|
||||
|
@ -427,6 +427,10 @@ class FloatingIpManager(network_base.FloatingIpManager):
|
||||
# to enable simple association support.
|
||||
return False
|
||||
|
||||
def is_supported(self):
|
||||
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||
return network_config.get('enable_router', True)
|
||||
|
||||
|
||||
def get_ipver_str(ip_version):
|
||||
"""Convert an ip version number to a human-friendly string."""
|
||||
@ -784,8 +788,11 @@ def servers_update_addresses(request, servers):
|
||||
try:
|
||||
ports = port_list(request,
|
||||
device_id=[instance.id for instance in servers])
|
||||
floating_ips = FloatingIpManager(request).list(
|
||||
port_id=[port.id for port in ports])
|
||||
fips = FloatingIpManager(request)
|
||||
if fips.is_supported():
|
||||
floating_ips = fips.list(port_id=[port.id for port in ports])
|
||||
else:
|
||||
floating_ips = []
|
||||
networks = network_list(request,
|
||||
id=[port.network_id for port in ports])
|
||||
except Exception:
|
||||
|
@ -389,6 +389,9 @@ class FloatingIpManager(network_base.FloatingIpManager):
|
||||
def is_simple_associate_supported(self):
|
||||
return conf.HORIZON_CONFIG["simple_ip_management"]
|
||||
|
||||
def is_supported(self):
|
||||
return True
|
||||
|
||||
|
||||
def novaclient(request):
|
||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||
|
@ -37,12 +37,13 @@ INDEX_URL = reverse('horizon:project:overview:index')
|
||||
|
||||
class UsageViewTests(test.BaseAdminViewTests):
|
||||
|
||||
def _stub_nova_api_calls(self, nova_stu_enabled):
|
||||
def _stub_api_calls(self, nova_stu_enabled):
|
||||
self.mox.StubOutWithMock(api.nova, 'usage_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_absolute_limits')
|
||||
self.mox.StubOutWithMock(api.nova, 'extension_supported')
|
||||
self.mox.StubOutWithMock(api.keystone, 'tenant_list')
|
||||
self.mox.StubOutWithMock(api.neutron, 'is_extension_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.cinder, 'tenant_absolute_limits')
|
||||
@ -61,7 +62,7 @@ class UsageViewTests(test.BaseAdminViewTests):
|
||||
self._test_usage(tenant_deleted=True)
|
||||
|
||||
def _test_usage(self, nova_stu_enabled=True, tenant_deleted=False):
|
||||
self._stub_nova_api_calls(nova_stu_enabled)
|
||||
self._stub_api_calls(nova_stu_enabled)
|
||||
api.nova.extension_supported(
|
||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||
.AndReturn(nova_stu_enabled)
|
||||
@ -87,6 +88,8 @@ class UsageViewTests(test.BaseAdminViewTests):
|
||||
.AndReturn(self.limits['absolute'])
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'security-group').AndReturn(True)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
@ -150,7 +153,7 @@ class UsageViewTests(test.BaseAdminViewTests):
|
||||
self._test_usage_csv(nova_stu_enabled=False)
|
||||
|
||||
def _test_usage_csv(self, nova_stu_enabled=True):
|
||||
self._stub_nova_api_calls(nova_stu_enabled)
|
||||
self._stub_api_calls(nova_stu_enabled)
|
||||
api.nova.extension_supported(
|
||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||
.AndReturn(nova_stu_enabled)
|
||||
@ -171,6 +174,8 @@ class UsageViewTests(test.BaseAdminViewTests):
|
||||
.AndReturn(self.limits['absolute'])
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'security-group').AndReturn(True)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
|
@ -1565,12 +1565,15 @@ class UsageViewTests(test.BaseAdminViewTests):
|
||||
|
||||
def _stub_neutron_api_calls(self, neutron_sg_enabled=True):
|
||||
self.mox.StubOutWithMock(api.neutron, 'is_extension_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
if neutron_sg_enabled:
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest),
|
||||
'security-group').AndReturn(neutron_sg_enabled)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
if neutron_sg_enabled:
|
||||
|
@ -122,6 +122,7 @@ class FloatingIpViewTests(test.TestCase):
|
||||
def test_disassociate_post(self):
|
||||
floating_ip = self.floating_ips.first()
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||
@ -129,6 +130,8 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.network.floating_ip_disassociate(IsA(http.HttpRequest),
|
||||
@ -144,6 +147,7 @@ class FloatingIpViewTests(test.TestCase):
|
||||
def test_disassociate_post_with_exception(self):
|
||||
floating_ip = self.floating_ips.first()
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||
@ -151,6 +155,8 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
|
||||
@ -180,6 +186,7 @@ class FloatingIpNeutronViewTests(FloatingIpViewTests):
|
||||
api.cinder: ('tenant_quota_get', 'volume_list',
|
||||
'volume_snapshot_list',),
|
||||
api.network: ('floating_ip_pools_list',
|
||||
'floating_ip_supported',
|
||||
'tenant_floating_ip_list'),
|
||||
api.neutron: ('is_extension_supported',
|
||||
'tenant_quota_get')})
|
||||
@ -206,6 +213,8 @@ class FloatingIpNeutronViewTests(FloatingIpViewTests):
|
||||
.AndReturn(True)
|
||||
api.neutron.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
|
||||
.AndReturn(self.neutron_quotas.first())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(self.floating_ips.list())
|
||||
api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
|
||||
|
@ -34,9 +34,13 @@ class KeyPairViewTests(test.TestCase):
|
||||
def test_delete_keypair(self):
|
||||
keypair = self.keypairs.first()
|
||||
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||
|
||||
# floating_ip_supported is called in Floating IP tab allowed().
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name)
|
||||
@ -48,9 +52,13 @@ class KeyPairViewTests(test.TestCase):
|
||||
|
||||
def test_delete_keypair_exception(self):
|
||||
keypair = self.keypairs.first()
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||
|
||||
# floating_ip_supported is called in Floating IP tab allowed().
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \
|
||||
|
@ -108,6 +108,9 @@ class FloatingIPsTab(tabs.TableTab):
|
||||
|
||||
return floating_ips
|
||||
|
||||
def allowed(self, request):
|
||||
return network.floating_ip_supported(request)
|
||||
|
||||
|
||||
class APIAccessTab(tabs.TableTab):
|
||||
table_classes = (EndpointsTable,)
|
||||
|
@ -39,6 +39,7 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
sec_groups = self.security_groups.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
@ -49,6 +50,8 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
@ -82,6 +85,7 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
sec_groups = self.security_groups.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
@ -92,6 +96,8 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
|
@ -491,6 +491,8 @@ class AssociateIP(tables.LinkAction):
|
||||
return {"project_id": project_id}
|
||||
|
||||
def allowed(self, request, instance):
|
||||
if not api.network.floating_ip_supported(request):
|
||||
return False
|
||||
if api.network.floating_ip_simple_associate_supported(request):
|
||||
return False
|
||||
return not is_deleting(instance)
|
||||
@ -552,6 +554,8 @@ class SimpleDisassociateIP(tables.Action):
|
||||
return {"project_id": project_id}
|
||||
|
||||
def allowed(self, request, instance):
|
||||
if not api.network.floating_ip_supported(request):
|
||||
return False
|
||||
if not conf.HORIZON_CONFIG["simple_ip_management"]:
|
||||
return False
|
||||
return not is_deleting(instance)
|
||||
|
@ -57,6 +57,7 @@ class InstanceTests(helpers.TestCase):
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: (
|
||||
'floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',
|
||||
),
|
||||
})
|
||||
@ -75,6 +76,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -111,6 +114,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'tenant_absolute_limits', 'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_index_flavor_list_exception(self):
|
||||
@ -133,6 +137,8 @@ class InstanceTests(helpers.TestCase):
|
||||
AndReturn(full_flavors[server.flavor["id"]])
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -150,6 +156,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'tenant_absolute_limits', 'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_index_flavor_get_exception(self):
|
||||
@ -175,6 +182,8 @@ class InstanceTests(helpers.TestCase):
|
||||
AndRaise(self.exceptions.nova)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -193,6 +202,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_index_with_instance_booted_from_volume(self):
|
||||
@ -215,6 +225,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -972,6 +984,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def _test_instances_index_retrieve_password_action(self):
|
||||
@ -989,6 +1002,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -2559,6 +2574,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_launch_button_disabled_when_quota_exceeded(self):
|
||||
@ -2579,6 +2595,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(limits)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -2607,6 +2625,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_index_options_after_migrate(self):
|
||||
@ -2626,6 +2645,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
@ -3102,6 +3123,7 @@ class InstanceTests(helpers.TestCase):
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_index_form_action_with_pagination(self):
|
||||
@ -3132,6 +3154,8 @@ class InstanceTests(helpers.TestCase):
|
||||
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(self.limits['absolute'])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
|
@ -50,12 +50,15 @@ class UsageViewTests(test.TestCase):
|
||||
|
||||
def _stub_neutron_api_calls(self, neutron_sg_enabled=True):
|
||||
self.mox.StubOutWithMock(api.neutron, 'is_extension_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
if neutron_sg_enabled:
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest),
|
||||
'security-group').AndReturn(neutron_sg_enabled)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
if neutron_sg_enabled:
|
||||
@ -278,6 +281,10 @@ class UsageViewTests(test.TestCase):
|
||||
def test_usage_with_neutron_nova_security_group(self):
|
||||
self._test_usage_with_neutron(neutron_sg_enabled=False)
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
def test_usage_with_neutron_floating_ip_disabled(self):
|
||||
self._test_usage_with_neutron(neutron_fip_enabled=False)
|
||||
|
||||
def _test_usage_with_neutron_prepare(self):
|
||||
now = timezone.now()
|
||||
usage_obj = api.nova.NovaUsage(self.usages.first())
|
||||
@ -288,6 +295,7 @@ class UsageViewTests(test.TestCase):
|
||||
.AndReturn(True)
|
||||
self.mox.StubOutWithMock(api.neutron, 'tenant_quota_get')
|
||||
self.mox.StubOutWithMock(api.neutron, 'is_extension_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_supported')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'security_group_list')
|
||||
start = datetime.datetime(now.year, now.month, 1, 0, 0, 0, 0)
|
||||
@ -298,15 +306,19 @@ class UsageViewTests(test.TestCase):
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest))\
|
||||
.AndReturn(self.limits['absolute'])
|
||||
|
||||
def _test_usage_with_neutron(self, neutron_sg_enabled=True):
|
||||
def _test_usage_with_neutron(self, neutron_sg_enabled=True,
|
||||
neutron_fip_enabled=True):
|
||||
self._test_usage_with_neutron_prepare()
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest), 'quotas').AndReturn(True)
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest),
|
||||
'security-group').AndReturn(neutron_sg_enabled)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(neutron_fip_enabled)
|
||||
if neutron_fip_enabled:
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
if neutron_sg_enabled:
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.q_secgroups.list())
|
||||
|
@ -12,11 +12,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import itertools
|
||||
import uuid
|
||||
|
||||
from django import http
|
||||
from django.test.utils import override_settings
|
||||
from mox import IsA # noqa
|
||||
|
||||
from novaclient.v1_1 import floating_ip_pools
|
||||
@ -218,14 +220,120 @@ class NetworkApiNeutronTestBase(test.APITestCase):
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest), 'network') \
|
||||
.AndReturn(True)
|
||||
self.qclient = self.stub_neutronclient()
|
||||
self.qclient.list_extensions() \
|
||||
.AndReturn({'extensions': self.api_extensions.list()})
|
||||
|
||||
|
||||
class NetworkApiNeutronTests(NetworkApiNeutronTestBase):
|
||||
|
||||
def _get_expected_addresses(self, server, no_fip_expected=True):
|
||||
server_ports = self.ports.filter(device_id=server.id)
|
||||
addresses = collections.defaultdict(list)
|
||||
for p in server_ports:
|
||||
net_name = self.networks.get(id=p['network_id']).name
|
||||
for ip in p.fixed_ips:
|
||||
addresses[net_name].append(
|
||||
{'version': 4,
|
||||
'addr': ip['ip_address'],
|
||||
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
||||
'OS-EXT-IPS:type': 'fixed'})
|
||||
if no_fip_expected:
|
||||
continue
|
||||
fips = self.q_floating_ips.filter(port_id=p['id'])
|
||||
if not fips:
|
||||
continue
|
||||
# Only one FIP should match.
|
||||
fip = fips[0]
|
||||
addresses[net_name].append(
|
||||
{'version': 4,
|
||||
'addr': fip.floating_ip_address,
|
||||
'OS-EXT-IPS-MAC:mac_addr': p.mac_address,
|
||||
'OS-EXT-IPS:type': 'floating'})
|
||||
return addresses
|
||||
|
||||
def _check_server_address(self, res_server_data, no_fip_expected=False):
|
||||
expected_addresses = self._get_expected_addresses(res_server_data,
|
||||
no_fip_expected)
|
||||
self.assertEqual(len(expected_addresses),
|
||||
len(res_server_data.addresses))
|
||||
for net, addresses in expected_addresses.items():
|
||||
self.assertIn(net, res_server_data.addresses)
|
||||
self.assertEqual(addresses, res_server_data.addresses[net])
|
||||
|
||||
def _test_servers_update_addresses(self, router_enabled=True):
|
||||
tenant_id = self.request.user.tenant_id
|
||||
|
||||
servers = copy.deepcopy(self.servers.list())
|
||||
server_ids = [server.id for server in servers]
|
||||
server_ports = [p for p in self.api_ports.list()
|
||||
if p['device_id'] in server_ids]
|
||||
server_port_ids = [p['id'] for p in server_ports]
|
||||
if router_enabled:
|
||||
assoc_fips = [fip for fip in self.api_q_floating_ips.list()
|
||||
if fip['port_id'] in server_port_ids]
|
||||
server_network_ids = [p['network_id'] for p in server_ports]
|
||||
server_networks = [net for net in self.api_networks.list()
|
||||
if net['id'] in server_network_ids]
|
||||
|
||||
self.qclient.list_ports(device_id=server_ids) \
|
||||
.AndReturn({'ports': server_ports})
|
||||
if router_enabled:
|
||||
self.qclient.list_floatingips(tenant_id=tenant_id,
|
||||
port_id=server_port_ids) \
|
||||
.AndReturn({'floatingips': assoc_fips})
|
||||
self.qclient.list_ports(tenant_id=tenant_id) \
|
||||
.AndReturn({'ports': self.api_ports.list()})
|
||||
self.qclient.list_networks(id=server_network_ids) \
|
||||
.AndReturn({'networks': server_networks})
|
||||
self.qclient.list_subnets() \
|
||||
.AndReturn({'subnets': self.api_subnets.list()})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.servers_update_addresses(self.request, servers)
|
||||
|
||||
self.assertEqual(self.servers.count(), len(servers))
|
||||
self.assertEqual([server.id for server in self.servers.list()],
|
||||
[server.id for server in servers])
|
||||
|
||||
no_fip_expected = not router_enabled
|
||||
|
||||
# server[0] has one fixed IP and one floating IP
|
||||
# if router ext isenabled.
|
||||
self._check_server_address(servers[0], no_fip_expected)
|
||||
# The expected is also calculated, we examine the result manually once.
|
||||
addrs = servers[0].addresses['net1']
|
||||
if router_enabled:
|
||||
self.assertEqual(2, len(addrs))
|
||||
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
||||
self.assertEqual('floating', addrs[1]['OS-EXT-IPS:type'])
|
||||
else:
|
||||
self.assertEqual(1, len(addrs))
|
||||
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
||||
|
||||
# server[1] has one fixed IP.
|
||||
self._check_server_address(servers[1], no_fip_expected)
|
||||
# manual check.
|
||||
addrs = servers[1].addresses['net2']
|
||||
self.assertEqual(1, len(addrs))
|
||||
self.assertEqual('fixed', addrs[0]['OS-EXT-IPS:type'])
|
||||
|
||||
# server[2] has no corresponding ports in neutron_data,
|
||||
# so it should be an empty dict.
|
||||
self.assertFalse(servers[2].addresses)
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_router': True})
|
||||
def test_servers_update_addresses(self):
|
||||
self._test_servers_update_addresses()
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_router': False})
|
||||
def test_servers_update_addresses_router_disabled(self):
|
||||
self._test_servers_update_addresses(router_enabled=False)
|
||||
|
||||
|
||||
class NetworkApiNeutronSecurityGroupTests(NetworkApiNeutronTestBase):
|
||||
|
||||
def setUp(self):
|
||||
super(NetworkApiNeutronSecurityGroupTests, self).setUp()
|
||||
self.qclient.list_extensions() \
|
||||
.AndReturn({'extensions': self.api_extensions.list()})
|
||||
self.sg_dict = dict([(sg['id'], sg['name']) for sg
|
||||
in self.api_q_secgroups.list()])
|
||||
|
||||
@ -398,6 +506,22 @@ class NetworkApiNeutronSecurityGroupTests(NetworkApiNeutronTestBase):
|
||||
|
||||
|
||||
class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
|
||||
|
||||
def setUp(self):
|
||||
super(NetworkApiNeutronFloatingIpTests, self).setUp()
|
||||
self.qclient.list_extensions() \
|
||||
.AndReturn({'extensions': self.api_extensions.list()})
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_router': True})
|
||||
def test_floating_ip_supported(self):
|
||||
self.mox.ReplayAll()
|
||||
self.assertTrue(api.network.floating_ip_supported(self.request))
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_router': False})
|
||||
def test_floating_ip_supported_false(self):
|
||||
self.mox.ReplayAll()
|
||||
self.assertFalse(api.network.floating_ip_supported(self.request))
|
||||
|
||||
def test_floating_ip_pools_list(self):
|
||||
search_opts = {'router:external': True}
|
||||
ext_nets = [n for n in self.api_networks.list()
|
||||
|
@ -52,7 +52,8 @@ class QuotaTests(test.APITestCase):
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_supported'),
|
||||
api.base: ('is_service_enabled',),
|
||||
cinder: ('volume_list', 'volume_snapshot_list',
|
||||
'tenant_quota_get',)})
|
||||
@ -68,6 +69,8 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
@ -90,7 +93,8 @@ class QuotaTests(test.APITestCase):
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_supported'),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def test_tenant_quota_usages_without_volume(self):
|
||||
servers = [s for s in self.servers.list()
|
||||
@ -104,6 +108,8 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
@ -125,7 +131,8 @@ class QuotaTests(test.APITestCase):
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_supported'),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def test_tenant_quota_usages_no_instances_running(self):
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
@ -136,6 +143,8 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([])
|
||||
api.nova.server_list(IsA(http.HttpRequest)).AndReturn([[], False])
|
||||
@ -157,7 +166,8 @@ class QuotaTests(test.APITestCase):
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_supported'),
|
||||
api.base: ('is_service_enabled',),
|
||||
cinder: ('volume_list', 'volume_snapshot_list',
|
||||
'tenant_quota_get',)})
|
||||
@ -175,6 +185,8 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(inf_quota)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
@ -196,3 +208,44 @@ class QuotaTests(test.APITestCase):
|
||||
|
||||
# Compare internal structure of usages to expected.
|
||||
self.assertEqual(quota_usages.usages, expected_output)
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_supported'),
|
||||
api.base: ('is_service_enabled',),
|
||||
cinder: ('volume_list', 'volume_snapshot_list',
|
||||
'tenant_quota_get',)})
|
||||
def test_tenant_quota_usages_neutron_fip_disabled(self):
|
||||
servers = [s for s in self.servers.list()
|
||||
if s.tenant_id == self.request.user.tenant_id]
|
||||
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'volume').AndReturn(True)
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest),
|
||||
'network').AndReturn(False)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(False)
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([servers, False])
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.snapshots.list())
|
||||
cinder.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.cinder_quotas.first())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
quota_usages = quotas.tenant_quota_usages(self.request)
|
||||
expected_output = self.get_usages()
|
||||
expected_output['floating_ips']['used'] = 0
|
||||
expected_output['floating_ips']['available'] = 1
|
||||
|
||||
# Compare internal structure of usages to expected.
|
||||
self.assertEqual(quota_usages.usages, expected_output)
|
||||
|
@ -145,7 +145,8 @@ class BaseUsage(object):
|
||||
neutron_sg_used = (
|
||||
api.neutron.is_extension_supported(self.request,
|
||||
'security-group'))
|
||||
self._get_neutron_usage(self.limits, 'floatingip')
|
||||
if api.network.floating_ip_supported(self.request):
|
||||
self._get_neutron_usage(self.limits, 'floatingip')
|
||||
if neutron_sg_used:
|
||||
self._get_neutron_usage(self.limits, 'security_group')
|
||||
# Quotas are an optional extension in Neutron. If it isn't
|
||||
|
@ -200,7 +200,12 @@ def tenant_quota_usages(request):
|
||||
usages.add_quota(quota)
|
||||
|
||||
# Get our usages.
|
||||
floating_ips = network.tenant_floating_ip_list(request)
|
||||
floating_ips = []
|
||||
try:
|
||||
if network.floating_ip_supported(request):
|
||||
floating_ips = network.tenant_floating_ip_list(request)
|
||||
except Exception:
|
||||
pass
|
||||
flavors = dict([(f.id, f) for f in nova.flavor_list(request)])
|
||||
instances, has_more = nova.server_list(request)
|
||||
# Fetch deleted flavors if necessary.
|
||||
|
Loading…
x
Reference in New Issue
Block a user