diff --git a/releasenotes/notes/toggle-port-security-f5bc606e82141feb.yaml b/releasenotes/notes/toggle-port-security-f5bc606e82141feb.yaml new file mode 100644 index 000000000..821a20fb6 --- /dev/null +++ b/releasenotes/notes/toggle-port-security-f5bc606e82141feb.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Added a new property, 'port_security_enabled' which is a boolean + to enable or disable port_secuirty during network creation. The + default behavior will enable port security, security group and + anti spoofing will act as before. When the attribute is set to + False, security group and anti spoofing are disabled on the ports + created on this network. diff --git a/shade/openstackcloud.py b/shade/openstackcloud.py index 7f73f233c..8af68f801 100644 --- a/shade/openstackcloud.py +++ b/shade/openstackcloud.py @@ -3420,7 +3420,8 @@ class OpenStackCloud( def create_network(self, name, shared=False, admin_state_up=True, external=False, provider=None, project_id=None, - availability_zone_hints=None): + availability_zone_hints=None, + port_security_enabled=None): """Create a network. :param string name: Name of the network being created. @@ -3433,6 +3434,7 @@ class OpenStackCloud( :param string project_id: Specify the project ID this network will be created on (admin-only). :param list availability_zone_hints: A list of availability zone hints. + :param bool port_security_enabled: Enable / Disable port security :returns: The network object. :raises: OpenStackCloudException on operation error. @@ -3475,6 +3477,12 @@ class OpenStackCloud( if external: network['router:external'] = True + if port_security_enabled is not None: + if not isinstance(port_security_enabled, bool): + raise OpenStackCloudException( + "Parameter 'port_security_enabled' must be a bool") + network['port_security_enabled'] = port_security_enabled + data = self._network_client.post("/networks.json", json={'network': network}) diff --git a/shade/tests/functional/test_network.py b/shade/tests/functional/test_network.py index 9698e2343..c85bca8da 100644 --- a/shade/tests/functional/test_network.py +++ b/shade/tests/functional/test_network.py @@ -49,6 +49,7 @@ class TestNetwork(base.BaseFunctionalTestCase): self.assertFalse(net1['shared']) self.assertFalse(net1['router:external']) self.assertTrue(net1['admin_state_up']) + self.assertTrue(net1['port_security_enabled']) def test_get_network_by_id(self): net1 = self.operator_cloud.create_network(name=self.network_name) @@ -97,6 +98,18 @@ class TestNetwork(base.BaseFunctionalTestCase): self.assertEqual('public', net1['provider:physical_network']) self.assertIsNone(net1['provider:segmentation_id']) + def test_create_network_port_security_disabled(self): + net1 = self.operator_cloud.create_network( + name=self.network_name, + port_security_enabled=False, + ) + self.assertIn('id', net1) + self.assertEqual(self.network_name, net1['name']) + self.assertTrue(net1['admin_state_up']) + self.assertFalse(net1['shared']) + self.assertFalse(net1['router:external']) + self.assertFalse(net1['port_security_enabled']) + def test_list_networks_filtered(self): net1 = self.operator_cloud.create_network(name=self.network_name) self.assertIsNotNone(net1) diff --git a/shade/tests/unit/test_network.py b/shade/tests/unit/test_network.py index bf7275d3f..31714be55 100644 --- a/shade/tests/unit/test_network.py +++ b/shade/tests/unit/test_network.py @@ -228,6 +228,28 @@ class TestNetwork(base.RequestsMockTestCase): ): self.cloud.create_network("netname", provider=provider_opts) + def test_create_network_port_security_disabled(self): + port_security_state = False + mock_new_network_rep = copy.copy(self.mock_new_network_rep) + mock_new_network_rep['port_security_enabled'] = port_security_state + self.register_uris([ + dict(method='POST', + uri=self.get_mock_url( + 'network', 'public', append=['v2.0', 'networks.json']), + json={'network': mock_new_network_rep}, + validate=dict( + json={'network': { + 'admin_state_up': True, + 'name': 'netname', + 'port_security_enabled': port_security_state}})) + ]) + network = self.cloud.create_network( + "netname", + port_security_enabled=port_security_state + ) + self.assertEqual(mock_new_network_rep, network) + self.assert_calls() + def test_delete_network(self): network_id = "test-net-id" network_name = "network"