Add config option to create networks with port_security_enabled

The port_security extension in neutron is disabled by default.

devstack enables the port_security extension for ML2 but since
it's optional we shouldn't assume it's enabled, so this change
adds a configuration option to tell us if port security is
supported as a networking feature.

We could use the extension list but that defaults to all and
we shouldn't require tempest users to have to maintain a
whitelist of extensions just to make the default configuration
work with default neutron, i.e. not devstack.

This is also slightly different from the allow_port_security_disabled
option which is a temporary flag until liberty end of life at
which point nova can handle booting a server and attaching a
port with port security disabled.

To make this run in the integrated gate, devstack will need to
set CONF.network_feature_enabled.port_security=True in all
branches except stable/liberty.

Change-Id: I1efd5c838aa0d73cc6e8864e3041eea25850198d
Closes-Bug: #1624082
diff --git a/tempest/config.py b/tempest/config.py
index f12e34e..f6c89ae 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -571,6 +571,9 @@
                 default=True,
                 help="Does the test environment support changing"
                      " port admin state"),
+    cfg.BoolOpt('port_security',
+                default=False,
+                help="Does the test environment support port security?"),
 ]
 
 validation_group = cfg.OptGroup(name='validation',
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 2f31ea3..4baf420 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -667,8 +667,11 @@
         if not tenant_id:
             tenant_id = networks_client.tenant_id
         name = data_utils.rand_name(namestart)
-        network_kwargs = dict(name=name, tenant_id=tenant_id,
-                              port_security_enabled=port_security_enabled)
+        network_kwargs = dict(name=name, tenant_id=tenant_id)
+        # Neutron disables port security by default so we have to check the
+        # config before trying to create the network with port_security_enabled
+        if CONF.network_feature_enabled.port_security:
+            network_kwargs['port_security_enabled'] = port_security_enabled
         result = networks_client.create_network(**network_kwargs)
         network = result['network']
 
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index b893aad..2c16be8 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -634,6 +634,14 @@
     @testtools.skipUnless(
         CONF.compute_feature_enabled.allow_port_security_disabled,
         'Port security must be enabled.')
+    # TODO(mriedem): We shouldn't actually need to check this since neutron
+    # disables the port_security extension by default, but the problem is nova
+    # assumes port_security_enabled=True if it's not set on the network
+    # resource, which will mean nova may attempt to apply a security group on
+    # a port on that network which would fail. This is really a bug in nova.
+    @testtools.skipUnless(
+        CONF.network_feature_enabled.port_security,
+        'Port security must be enabled.')
     @test.services('compute', 'network')
     def test_boot_into_disabled_port_security_network_without_secgroup(self):
         tenant = self.primary_tenant