Merge "Show security groups in Port detail page"
This commit is contained in:
commit
4a882c14b9
@ -289,13 +289,13 @@ class SecurityGroupManager(object):
|
||||
return [SecurityGroup(sg) for sg in secgroups.get('security_groups')]
|
||||
|
||||
@profiler.trace
|
||||
def list(self):
|
||||
def list(self, **params):
|
||||
"""Fetches a list all security groups.
|
||||
|
||||
:returns: List of SecurityGroup objects
|
||||
"""
|
||||
tenant_id = self.request.user.tenant_id
|
||||
return self._list(tenant_id=tenant_id)
|
||||
tenant_id = params.pop('tenant_id', self.request.user.tenant_id)
|
||||
return self._list(tenant_id=tenant_id, **params)
|
||||
|
||||
def _sg_name_dict(self, sg_id, rules):
|
||||
"""Create a mapping dict from secgroup id to its name."""
|
||||
@ -1316,8 +1316,8 @@ def floating_ip_supported(request):
|
||||
|
||||
|
||||
@memoized
|
||||
def security_group_list(request):
|
||||
return SecurityGroupManager(request).list()
|
||||
def security_group_list(request, **params):
|
||||
return SecurityGroupManager(request).list(**params)
|
||||
|
||||
|
||||
def security_group_get(request, sg_id):
|
||||
|
@ -31,23 +31,27 @@ NETWORKS_DETAIL_URL = 'horizon:project:networks:detail'
|
||||
|
||||
class NetworkPortTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_get',
|
||||
'port_get',
|
||||
'is_extension_supported',)})
|
||||
def test_port_detail(self):
|
||||
self._test_port_detail()
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_get',
|
||||
'port_get',
|
||||
'is_extension_supported',)})
|
||||
def test_port_detail_with_mac_learning(self):
|
||||
self._test_port_detail(mac_learning=True)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_get',
|
||||
'port_get',
|
||||
'is_extension_supported',
|
||||
'security_group_list',)})
|
||||
def _test_port_detail(self, mac_learning=False):
|
||||
port = self.ports.first()
|
||||
# Use a port associated with security group
|
||||
port = [p for p in self.ports.list() if p.security_groups][0]
|
||||
sgs = [sg for sg in self.security_groups.list()
|
||||
if sg.id in port.security_groups]
|
||||
network_id = self.networks.first().id
|
||||
api.neutron.port_get(IsA(http.HttpRequest), port.id)\
|
||||
.AndReturn(self.ports.first())
|
||||
.AndReturn(port)
|
||||
api.neutron.security_group_list(IsA(http.HttpRequest),
|
||||
ids=port.security_groups)\
|
||||
.AndReturn(sgs)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'mac-learning')\
|
||||
.MultipleTimes().AndReturn(mac_learning)
|
||||
|
@ -114,6 +114,20 @@ class DetailView(tabs.TabbedTableView):
|
||||
|
||||
return network
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_security_groups(self, sg_ids):
|
||||
# Avoid extra API calls if no security group is associated.
|
||||
if not sg_ids:
|
||||
return []
|
||||
try:
|
||||
security_groups = api.neutron.security_group_list(self.request,
|
||||
id=sg_ids)
|
||||
except Exception:
|
||||
security_groups = []
|
||||
msg = _("Unable to retrieve security groups for the port.")
|
||||
exceptions.handle(self.request, msg)
|
||||
return security_groups
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
port = self.get_data()
|
||||
@ -124,6 +138,7 @@ class DetailView(tabs.TabbedTableView):
|
||||
port.network_url = reverse(network_url, args=[port.network_id])
|
||||
for ip in port.fixed_ips:
|
||||
ip['subnet_url'] = reverse(subnet_url, args=[ip['subnet_id']])
|
||||
port.security_groups = self.get_security_groups(port.security_groups)
|
||||
table = project_tables.PortsTable(self.request,
|
||||
network_id=port.network_id)
|
||||
# TODO(robcresswell) Add URL for "Ports" crumb after bug/1416838
|
||||
|
@ -83,6 +83,23 @@
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
<h4>{% trans "Security Groups" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
{% for group in port.security_groups %}
|
||||
<dt>{{ group.name }}</dt>
|
||||
<dd>
|
||||
<ul class="list-unstyled">
|
||||
{% for rule in group.rules %}
|
||||
<li>{{ rule }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</dd>
|
||||
{% empty %}
|
||||
<dd>{% trans "No security group is associated" %}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
<h4>{% trans "Binding" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
|
@ -776,19 +776,30 @@ class NeutronApiSecurityGroupTests(NeutronApiTestBase):
|
||||
for (exprule, retrule) in six.moves.zip(exp_rules, ret_sg.rules):
|
||||
self._cmp_sg_rule(exprule, retrule)
|
||||
|
||||
def test_security_group_list(self):
|
||||
def _test_security_group_list(self, **params):
|
||||
sgs = self.api_security_groups.list()
|
||||
tenant_id = self.request.user.tenant_id
|
||||
q_params = {'tenant_id': self.request.user.tenant_id}
|
||||
# if tenant_id is specified, the passed tenant_id should be sent.
|
||||
q_params.update(params)
|
||||
# use deepcopy to ensure self.api_security_groups is not modified.
|
||||
self.qclient.list_security_groups(tenant_id=tenant_id) \
|
||||
self.qclient.list_security_groups(**q_params) \
|
||||
.AndReturn({'security_groups': copy.deepcopy(sgs)})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rets = api.neutron.security_group_list(self.request)
|
||||
rets = api.neutron.security_group_list(self.request, **params)
|
||||
self.assertEqual(len(sgs), len(rets))
|
||||
for (exp, ret) in six.moves.zip(sgs, rets):
|
||||
self._cmp_sg(exp, ret)
|
||||
|
||||
def test_security_group_list(self):
|
||||
self._test_security_group_list()
|
||||
|
||||
def test_security_group_list_with_params(self):
|
||||
self._test_security_group_list(name='sg1')
|
||||
|
||||
def test_security_group_list_with_tenant_id(self):
|
||||
self._test_security_group_list(tenant_id='tenant1', name='sg1')
|
||||
|
||||
def test_security_group_get(self):
|
||||
secgroup = self.api_security_groups.first()
|
||||
sg_ids = set([secgroup['id']] +
|
||||
|
@ -114,56 +114,71 @@ def data(TEST):
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
# Ports on 1st network.
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
||||
'device_owner': 'network:dhcp',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '063cf7f3-ded1-4297-bc4c-31eae876cc91',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7e',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'allowed_address_pairs': [{'ip_address': '174.0.0.201',
|
||||
'mac_address': 'fa:16:3e:7a:7b:18'}]
|
||||
}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
||||
'device_owner': 'network:dhcp',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '063cf7f3-ded1-4297-bc4c-31eae876cc91',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7e',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'allowed_address_pairs': [
|
||||
{'ip_address': '174.0.0.201',
|
||||
'mac_address': 'fa:16:3e:7a:7b:18'}
|
||||
],
|
||||
'security_groups': [],
|
||||
}
|
||||
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '1',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.4',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
||||
'mac_address': 'fa:16:3e:9d:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host'}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': '1',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.4',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
||||
'mac_address': 'fa:16:3e:9d:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [
|
||||
# sec_group_1 ID below
|
||||
'faad7c80-3b62-4440-967c-13808c37131d',
|
||||
# sec_group_2 ID below
|
||||
'27a5c9a1-bdbb-48ac-833a-2e4b5f54b31d'
|
||||
],
|
||||
}
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
assoc_port = port_dict
|
||||
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '279989f7-54bb-41d9-ba42-0d61f12fda61',
|
||||
'device_owner': 'network:router_interface',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.1',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '9036eedb-e7fa-458e-bc6e-d9d06d9d1bc4',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host'}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': '279989f7-54bb-41d9-ba42-0d61f12fda61',
|
||||
'device_owner': 'network:router_interface',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.1',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '9036eedb-e7fa-458e-bc6e-d9d06d9d1bc4',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [],
|
||||
}
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
|
||||
@ -201,19 +216,25 @@ def data(TEST):
|
||||
TEST.networks.add(neutron.Network(network))
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '2',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '172.16.88.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '1db2cc37-3553-43fa-b7e2-3fc4eb4f9905',
|
||||
'mac_address': 'fa:16:3e:56:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host'}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': '2',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '172.16.88.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '1db2cc37-3553-43fa-b7e2-3fc4eb4f9905',
|
||||
'mac_address': 'fa:16:3e:56:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [
|
||||
# sec_group_1 ID below
|
||||
'faad7c80-3b62-4440-967c-13808c37131d',
|
||||
],
|
||||
}
|
||||
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
@ -315,19 +336,22 @@ def data(TEST):
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
# Set up router data.
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
||||
'device_owner': 'network:router_gateway',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '44ec6726-4bdc-48c5-94d4-df8d1fbf613b',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7e',
|
||||
'name': '',
|
||||
'network_id': TEST.networks.get(name="ext_net")['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '1',
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host'}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
||||
'device_owner': 'network:router_gateway',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '44ec6726-4bdc-48c5-94d4-df8d1fbf613b',
|
||||
'mac_address': 'fa:16:3e:9c:d5:7e',
|
||||
'name': '',
|
||||
'network_id': TEST.networks.get(name="ext_net")['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '1',
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [],
|
||||
}
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
|
||||
@ -923,20 +947,23 @@ def data(TEST):
|
||||
TEST.firewalls.add(fw2)
|
||||
|
||||
# ports on 4th network
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '9872faaa-b2b2-eeee-9911-21332eedaa77',
|
||||
'device_owner': 'network:dhcp',
|
||||
'fixed_ips': [{'ip_address': '11.10.0.3',
|
||||
'subnet_id':
|
||||
TEST.subnets.first().id}],
|
||||
'id': 'a21dcd22-6733-cccc-aa32-22adafaf16a2',
|
||||
'mac_address': '78:22:ff:1a:ba:23',
|
||||
'name': 'port5',
|
||||
'network_id': TEST.networks.first().id,
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': TEST.networks.first().tenant_id,
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host'}
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': '9872faaa-b2b2-eeee-9911-21332eedaa77',
|
||||
'device_owner': 'network:dhcp',
|
||||
'fixed_ips': [{'ip_address': '11.10.0.3',
|
||||
'subnet_id':
|
||||
TEST.subnets.first().id}],
|
||||
'id': 'a21dcd22-6733-cccc-aa32-22adafaf16a2',
|
||||
'mac_address': '78:22:ff:1a:ba:23',
|
||||
'name': 'port5',
|
||||
'network_id': TEST.networks.first().id,
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': TEST.networks.first().tenant_id,
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [],
|
||||
}
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(neutron.Port(port_dict))
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Security group association per port is now shown in the port detail page.
|
||||
In Neutron different security groups can be associated on different ports
|
||||
of a same server instance, but previously it cannot be referred in Horizon.
|
Loading…
Reference in New Issue
Block a user