Merge "trunk: Skip trunk tests because of bug 1740885"
diff --git a/neutron_tempest_plugin/api/test_trunk.py b/neutron_tempest_plugin/api/test_trunk.py
index 6c781ab..e02cf92 100644
--- a/neutron_tempest_plugin/api/test_trunk.py
+++ b/neutron_tempest_plugin/api/test_trunk.py
@@ -54,8 +54,20 @@
         trunks_cleanup(cls.client, cls.trunks)
         super(TrunkTestJSONBase, cls).resource_cleanup()
 
-    def _create_trunk_with_network_and_parent(self, subports, **kwargs):
-        network = self.create_network()
+    @classmethod
+    def is_type_driver_enabled(cls, type_driver):
+        return (type_driver in
+                config.CONF.neutron_plugin_options.available_type_drivers)
+
+    def _create_trunk_with_network_and_parent(
+            self, subports, parent_network_type=None, **kwargs):
+        client = None
+        network_kwargs = {}
+        if parent_network_type:
+            client = self.admin_client
+            network_kwargs = {"provider:network_type": parent_network_type,
+                              "tenant_id": self.client.tenant_id}
+        network = self.create_network(client=client, **network_kwargs)
         parent_port = self.create_port(network)
         trunk = self.client.create_trunk(parent_port['id'], subports, **kwargs)
         self.trunks.append(trunk['trunk'])
@@ -266,9 +278,7 @@
     @classmethod
     def skip_checks(cls):
         super(TrunkTestMtusJSONBase, cls).skip_checks()
-        if any(t
-               not in config.CONF.neutron_plugin_options.available_type_drivers
-               for t in ['gre', 'vxlan']):
+        if not all(cls.is_type_driver_enabled(t) for t in ['gre', 'vxlan']):
             msg = "Either vxlan or gre type driver not enabled."
             raise cls.skipException(msg)
 
diff --git a/neutron_tempest_plugin/api/test_trunk_negative.py b/neutron_tempest_plugin/api/test_trunk_negative.py
index 699b26f..4d7ead1 100644
--- a/neutron_tempest_plugin/api/test_trunk_negative.py
+++ b/neutron_tempest_plugin/api/test_trunk_negative.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from oslo_utils import uuidutils
+from tempest.common import utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 import testtools
@@ -103,8 +104,14 @@
 
     @decorators.attr(type='negative')
     @decorators.idempotent_id('40aed9be-e976-47d0-dada-bde2c7e74e57')
+    @utils.requires_ext(extension="provider", service="network")
     def test_create_subport_invalid_inherit_network_segmentation_type(self):
-        trunk = self._create_trunk_with_network_and_parent([])
+        if not self.is_type_driver_enabled('vxlan'):
+            msg = "Vxlan type driver must be enabled for this test."
+            raise self.skipException(msg)
+
+        trunk = self._create_trunk_with_network_and_parent(
+            subports=[], parent_network_type='vxlan')
         subport_network = self.create_network()
         parent_port = self.create_port(subport_network)
         self.assertRaises(lib_exc.BadRequest, self.client.add_subports,
diff --git a/neutron_tempest_plugin/config.py b/neutron_tempest_plugin/config.py
index 804fece..d6db315 100644
--- a/neutron_tempest_plugin/config.py
+++ b/neutron_tempest_plugin/config.py
@@ -38,6 +38,11 @@
                help='The availability zone for all agents in the deployment. '
                     'Configure this only when the single value is used by '
                     'all agents in the deployment.'),
+    cfg.IntOpt('max_networks_per_project',
+               default=4,
+               help='Max number of networks per project. '
+                    'Configure this only when project is limited with real '
+                    'vlans in deployment.'),
 ]
 
 # TODO(amuller): Redo configuration options registration as part of the planned
diff --git a/neutron_tempest_plugin/scenario/test_security_groups.py b/neutron_tempest_plugin/scenario/test_security_groups.py
index 1244535..9503fe3 100644
--- a/neutron_tempest_plugin/scenario/test_security_groups.py
+++ b/neutron_tempest_plugin/scenario/test_security_groups.py
@@ -26,13 +26,13 @@
 CONF = config.CONF
 
 
-class NetworkDefaultSecGroupTest(base.BaseTempestTestCase):
+class NetworkSecGroupTest(base.BaseTempestTestCase):
     credentials = ['primary', 'admin']
     required_extensions = ['router', 'security-group']
 
     @classmethod
     def resource_setup(cls):
-        super(NetworkDefaultSecGroupTest, cls).resource_setup()
+        super(NetworkSecGroupTest, cls).resource_setup()
         # setup basic topology for servers we can log into it
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
@@ -40,15 +40,26 @@
         cls.create_router_interface(router['id'], cls.subnet['id'])
         cls.keypair = cls.create_keypair()
 
-    def create_vm_testing_sec_grp(self, num_servers=2, security_groups=None):
+    def create_vm_testing_sec_grp(self, num_servers=2, security_groups=None,
+                                  ports=None):
+        """Create instance for security group testing
+        :param num_servers (int): number of servers to spawn
+        :param security_groups (list): list of security groups
+        :param ports* (list): list of ports
+        *Needs to be the same length as num_servers
+        """
         servers, fips, server_ssh_clients = ([], [], [])
         for i in range(num_servers):
-            servers.append(self.create_server(
-                flavor_ref=CONF.compute.flavor_ref,
-                image_ref=CONF.compute.image_ref,
-                key_name=self.keypair['name'],
-                networks=[{'uuid': self.network['id']}],
-                security_groups=security_groups))
+            server_args = {
+                'flavor_ref': CONF.compute.flavor_ref,
+                'image_ref': CONF.compute.image_ref,
+                'key_name': self.keypair['name'],
+                'networks': [{'uuid': self.network['id']}],
+                'security_groups': security_groups
+            }
+            if ports is not None:
+                server_args['networks'][0].update({'port': ports[i]['id']})
+            servers.append(self.create_server(**server_args))
         for i, server in enumerate(servers):
             waiters.wait_for_server_status(
                 self.os_primary.servers_client, server['server']['id'],
@@ -210,3 +221,70 @@
                       'direction': constants.INGRESS_DIRECTION,
                       'remote_ip_prefix': cidr}]
         self._test_ip_prefix(rule_list, should_succeed=False)
+
+    @decorators.idempotent_id('7ed39b86-006d-40fb-887a-ae46693dabc9')
+    def test_remote_group(self):
+        # create a new sec group
+        ssh_secgrp_name = data_utils.rand_name('ssh_secgrp')
+        ssh_secgrp = self.os_primary.network_client.create_security_group(
+            name=ssh_secgrp_name)
+        # add cleanup
+        self.security_groups.append(ssh_secgrp['security_group'])
+        # configure sec group to support SSH connectivity
+        self.create_loginable_secgroup_rule(
+            secgroup_id=ssh_secgrp['security_group']['id'])
+        # spawn two instances with the sec group created
+        server_ssh_clients, fips, servers = self.create_vm_testing_sec_grp(
+            security_groups=[{'name': ssh_secgrp_name}])
+        # verify SSH functionality
+        for i in range(2):
+            self.check_connectivity(fips[i]['floating_ip_address'],
+                                    CONF.validation.image_ssh_user,
+                                    self.keypair['private_key'])
+        # try to ping instances without ICMP permissions
+        self.check_remote_connectivity(
+            server_ssh_clients[0], fips[1]['fixed_ip_address'],
+            should_succeed=False)
+        # add ICMP support to the remote group
+        rule_list = [{'protocol': constants.PROTO_NUM_ICMP,
+                      'direction': constants.INGRESS_DIRECTION,
+                      'remote_group_id': ssh_secgrp['security_group']['id']}]
+        self.create_secgroup_rules(
+            rule_list, secgroup_id=ssh_secgrp['security_group']['id'])
+        # verify ICMP connectivity between instances works
+        self.check_remote_connectivity(
+            server_ssh_clients[0], fips[1]['fixed_ip_address'])
+        # make sure ICMP connectivity doesn't work from framework
+        self.ping_ip_address(fips[0]['floating_ip_address'],
+                             should_succeed=False)
+
+    @decorators.idempotent_id('f07d0159-8f9e-4faa-87f5-a869ab0ad488')
+    def test_multiple_ports_secgroup_inheritance(self):
+        """This test creates two ports with security groups, then
+        boots two instances and verify that the security group was
+        inherited properly and enforced in these instances.
+        """
+        # create a security group and make it loginable and pingable
+        secgrp = self.os_primary.network_client.create_security_group(
+            name=data_utils.rand_name('secgrp'))
+        self.create_loginable_secgroup_rule(
+            secgroup_id=secgrp['security_group']['id'])
+        self.create_pingable_secgroup_rule(
+            secgroup_id=secgrp['security_group']['id'])
+        # add security group to cleanup
+        self.security_groups.append(secgrp['security_group'])
+        # create two ports with fixed IPs and the security group created
+        ports = []
+        for i in range(2):
+            ports.append(self.create_port(
+                self.network, fixed_ips=[{'subnet_id': self.subnets[0]['id']}],
+                security_groups=[secgrp['security_group']['id']]))
+        # spawn instances with the ports created
+        server_ssh_clients, fips, servers = self.create_vm_testing_sec_grp(
+            ports=ports)
+        # verify ICMP reachability and ssh connectivity
+        for fip in fips:
+            self.ping_ip_address(fip['floating_ip_address'])
+            self.check_connectivity(fip['floating_ip_address'],
+                                    CONF.validation.image_ssh_user,
+                                    self.keypair['private_key'])
diff --git a/neutron_tempest_plugin/scenario/test_trunk.py b/neutron_tempest_plugin/scenario/test_trunk.py
index 085a648..bb4266c 100644
--- a/neutron_tempest_plugin/scenario/test_trunk.py
+++ b/neutron_tempest_plugin/scenario/test_trunk.py
@@ -174,9 +174,12 @@
             exception=RuntimeError("Timed out waiting for trunk %s to "
                                    "transition to ACTIVE." % trunk2_id))
         # create a few more networks and ports for subports
+        # check limit of networks per project
+        max_vlan = 3 + CONF.neutron_plugin_options.max_networks_per_project
+        allowed_vlans = range(3, max_vlan)
         subports = [{'port_id': self.create_port(self.create_network())['id'],
                      'segmentation_type': 'vlan', 'segmentation_id': seg_id}
-                    for seg_id in range(3, 7)]
+                    for seg_id in allowed_vlans]
         # add all subports to server1
         self.client.add_subports(trunk1_id, subports)
         # ensure trunk transitions to ACTIVE