Merge "Fix flake8 E265 errors"
diff --git a/.zuul.yaml b/.zuul.yaml
index 1063efa..8c6072a 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -129,9 +129,11 @@
       devstack_localrc:
         PHYSICAL_NETWORK: default
         DOWNLOAD_DEFAULT_IMAGES: false
-        IMAGE_URLS: http://cloud-images.ubuntu.com/releases/16.04/release-20180622/ubuntu-16.04-server-cloudimg-amd64-disk1.img,
-        DEFAULT_INSTANCE_TYPE: ds512M
-        DEFAULT_INSTANCE_USER: ubuntu
+        IMAGE_URLS: "http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-i386-disk.img,http://cloud-images.ubuntu.com/releases/16.04/release-20180622/ubuntu-16.04-server-cloudimg-amd64-disk1.img"
+        DEFAULT_IMAGE_NAME: cirros-0.3.4-i386-disk
+        ADVANCED_IMAGE_NAME: ubuntu-16.04-server-cloudimg-amd64-disk1
+        ADVANCED_INSTANCE_TYPE: ds512M
+        ADVANCED_INSTANCE_USER: ubuntu
         BUILD_TIMEOUT: 784
       devstack_services:
         cinder: true
@@ -203,9 +205,11 @@
         NETWORK_API_EXTENSIONS: "address-scope,agent,allowed-address-pairs,auto-allocated-topology,availability_zone,binding,default-subnetpools,dhcp_agent_scheduler,dns-integration,dvr,empty-string-filtering,ext-gw-mode,external-net,extra_dhcp_opt,extraroute,fip-port-details,flavors,ip-substring-filtering,l3-flavors,l3-ha,l3_agent_scheduler,logging,metering,multi-provider,net-mtu,net-mtu-writable,network-ip-availability,network_availability_zone,pagination,port-security,project-id,provider,qos,qos-fip,quotas,quota_details,rbac-policies,router,router_availability_zone,security-group,port-security-groups-filtering,segment,service-type,sorting,standard-attr-description,standard-attr-revisions,standard-attr-segment,standard-attr-timestamp,standard-attr-tag,subnet_allocation,trunk,trunk-details"
         PHYSICAL_NETWORK: default
         DOWNLOAD_DEFAULT_IMAGES: false
-        IMAGE_URLS: http://cloud-images.ubuntu.com/releases/16.04/release-20180622/ubuntu-16.04-server-cloudimg-amd64-disk1.img,
-        DEFAULT_INSTANCE_TYPE: ds512M
-        DEFAULT_INSTANCE_USER: ubuntu
+        IMAGE_URLS: "http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-i386-disk.img,http://cloud-images.ubuntu.com/releases/16.04/release-20180622/ubuntu-16.04-server-cloudimg-amd64-disk1.img"
+        DEFAULT_IMAGE_NAME: cirros-0.3.4-i386-disk
+        ADVANCED_IMAGE_NAME: ubuntu-16.04-server-cloudimg-amd64-disk1
+        ADVANCED_INSTANCE_TYPE: ds512M
+        ADVANCED_INSTANCE_USER: ubuntu
         BUILD_TIMEOUT: 784
       devstack_plugins:
         neutron: git://git.openstack.org/openstack/neutron.git
@@ -330,6 +334,11 @@
       devstack_localrc:
         TEMPEST_PLUGINS: '"/opt/stack/designate-tempest-plugin /opt/stack/neutron-tempest-plugin"'
         DESIGNATE_BACKEND_DRIVER: bind9
+        DOWNLOAD_DEFAULT_IMAGES: false
+        IMAGE_URLS: http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-i386-disk.img,
+        # In this job advanced image is not needed, so it's name should be
+        # empty
+        ADVANCED_IMAGE_NAME: ""
       devstack_plugins:
         designate: git://git.openstack.org/openstack/designate.git
       devstack_services:
diff --git a/devstack/functions.sh b/devstack/functions.sh
index 026f527..8d8a4bf 100644
--- a/devstack/functions.sh
+++ b/devstack/functions.sh
@@ -30,3 +30,58 @@
     # Restore xtrace
     $_XTRACE_FUNCTIONS
 }
+
+#Add advanced image config to tempest.conf
+function configure_advanced_image {
+    local advanced_image_uuid
+
+    if ! is_service_enabled glance; then
+        # if glance is not enabled, there is no image for to configure
+        return 0
+    fi
+
+    if [[ -z "$ADVANCED_IMAGE_NAME" ]]; then
+        # if name of advanced image is not provided, there is no image to
+        # configure
+        return 0
+    fi
+
+    while read -r IMAGE_NAME IMAGE_UUID; do
+        if [ "$IMAGE_NAME" = "$ADVANCED_IMAGE_NAME" ]; then
+            advanced_image_uuid="$IMAGE_UUID"
+            break
+        fi
+    done < <(openstack image list --property status=active | awk -F'|' '!/^(+--)|ID|aki|ari/ { print $3,$2 }')
+
+    if [[ -z "$advanced_image_uuid" ]]; then
+        echo "No image with name $ADVANCED_IMAGE_NAME found."
+        return 1
+    fi
+
+    iniset $TEMPEST_CONFIG neutron_plugin_options advanced_image_ref $advanced_image_uuid
+    iniset $TEMPEST_CONFIG neutron_plugin_options advanced_image_ssh_user $ADVANCED_INSTANCE_USER
+}
+
+
+function configure_flavor_for_advanced_image {
+    local flavor_ref
+
+    if ! is_service_enabled nova; then
+        # if nova is not enabled, there is no flavor to configure
+        return 0
+    fi
+
+    if [[ -z "$ADVANCED_INSTANCE_TYPE" ]]; then
+        # if name of flavor for advanced image is not provided, there is no
+        # flavor to configure
+        return 0
+    fi
+
+    flavor_ref=$(openstack flavor show $ADVANCED_INSTANCE_TYPE -f value -c id)
+    if [[ -z "$flavor_ref" ]]; then
+        echo "Found no valid flavors to use for $ADVANCED_IMAGE_NAME !"
+        echo "Fallback to use $DEFAULT_INSTANCE_TYPE"
+        flavor_ref=$(iniget $TEMPEST_CONFIG compute flavor_ref)
+    fi
+    iniset $TEMPEST_CONFIG neutron_plugin_options advanced_image_flavor_ref $flavor_ref
+}
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
index e7e30a9..25cfba6 100644
--- a/devstack/plugin.sh
+++ b/devstack/plugin.sh
@@ -15,5 +15,9 @@
             echo_summary "Installing neutron-tempest-plugin"
             install_neutron_tempest_plugin
             ;;
+        test-config)
+            echo_summary "Configuring neutron-tempest-plugin tempest options"
+            configure_advanced_image
+            configure_flavor_for_advanced_image
     esac
 fi
diff --git a/devstack/settings b/devstack/settings
index 614376f..6804a47 100644
--- a/devstack/settings
+++ b/devstack/settings
@@ -1,3 +1,7 @@
 GITREPO["neutron-tempest-plugin"]=${NEUTRON_TEMPEST_REPO:-${GIT_BASE}/openstack/neutron-tempest-plugin.git}
 GITDIR["neutron-tempest-plugin"]=$DEST/neutron-tempest-plugin
 GITBRANCH["neutron-tempest-plugin"]=master
+
+ADVANCED_IMAGE_NAME=${ADVANCED_IMAGE_NAME:-""}
+ADVANCED_INSTANCE_TYPE=${ADVANCED_INSTANCE_TYPE:-$DEFAULT_INSTANCE_TYPE}
+ADVANCED_INSTANCE_USER=${ADVANCED_INSTANCE_USER:-$DEFAULT_INSTANCE_USER}
diff --git a/neutron_tempest_plugin/config.py b/neutron_tempest_plugin/config.py
index e15748d..030a126 100644
--- a/neutron_tempest_plugin/config.py
+++ b/neutron_tempest_plugin/config.py
@@ -29,10 +29,6 @@
                 default=[],
                 help='List of network types available to neutron, '
                      'e.g. vxlan,vlan,gre.'),
-    cfg.BoolOpt('image_is_advanced',
-                default=False,
-                help='Image that supports features that cirros does not, like'
-                     ' Ubuntu or CentOS supporting advanced features'),
     cfg.StrOpt('agent_availability_zone',
                help='The availability zone for all agents in the deployment. '
                     'Configure this only when the single value is used by '
@@ -75,6 +71,26 @@
     cfg.IntOpt('ssh_proxy_jump_port',
                default=22,
                help='Port used to connect to "ssh_proxy_jump_host".'),
+
+    # Options for special, "advanced" image like e.g. Ubuntu. Such image can be
+    # used in tests which require some more advanced tool than available in
+    # Cirros
+    cfg.StrOpt('advanced_image_ref',
+               default=None,
+               help='Valid advanced image uuid to be used in tests. '
+                    'It is an image that supports features that Cirros '
+                    'does not, like Ubuntu or CentOS supporting advanced '
+                    'features.'),
+    cfg.StrOpt('advanced_image_flavor_ref',
+               default=None,
+               help='Valid flavor to use with advanced image in tests. '
+                    'This is required if advanced image has to be used in '
+                    'tests.'),
+    cfg.StrOpt('advanced_image_ssh_user',
+               default=None,
+               help='Name of ssh user to use with advanced image in tests. '
+                    'This is required if advanced image has to be used in '
+                    'tests.'),
 ]
 
 # TODO(amuller): Redo configuration options registration as part of the planned
diff --git a/neutron_tempest_plugin/scenario/test_mtu.py b/neutron_tempest_plugin/scenario/test_mtu.py
index 7a9f969..941d499 100644
--- a/neutron_tempest_plugin/scenario/test_mtu.py
+++ b/neutron_tempest_plugin/scenario/test_mtu.py
@@ -47,8 +47,8 @@
 
     def create_pingable_vm(self, net, keypair, secgroup):
         server = self.create_server(
-            flavor_ref=CONF.compute.flavor_ref,
-            image_ref=CONF.compute.image_ref,
+            flavor_ref=CONF.neutron_plugin_options.advanced_image_flavor_ref,
+            image_ref=CONF.neutron_plugin_options.advanced_image_ref,
             key_name=keypair['name'],
             networks=[{'uuid': net['id']}],
             security_groups=[{'name': secgroup[
@@ -105,22 +105,23 @@
                                                 self.keypair, self.secgroup)
         server_ssh_client1 = ssh.Client(
             self.floating_ips[0]['floating_ip_address'],
-            CONF.validation.image_ssh_user,
+            CONF.neutron_plugin_options.advanced_image_ssh_user,
             pkey=self.keypair['private_key'])
         server2, fip2 = self.create_pingable_vm(self.networks[1],
                                                 self.keypair, self.secgroup)
         server_ssh_client2 = ssh.Client(
             self.floating_ips[0]['floating_ip_address'],
-            CONF.validation.image_ssh_user,
+            CONF.neutron_plugin_options.advanced_image_ssh_user,
             pkey=self.keypair['private_key'])
         for fip in (fip1, fip2):
-            self.check_connectivity(fip['floating_ip_address'],
-                                    CONF.validation.image_ssh_user,
-                                    self.keypair['private_key'])
+            self.check_connectivity(
+                fip['floating_ip_address'],
+                CONF.neutron_plugin_options.advanced_image_ssh_user,
+                self.keypair['private_key'])
         return server_ssh_client1, fip1, server_ssh_client2, fip2
 
     @testtools.skipUnless(
-          CONF.neutron_plugin_options.image_is_advanced,
+          CONF.neutron_plugin_options.advanced_image_ref,
           "Advanced image is required to run this test.")
     @decorators.idempotent_id('3d73ec1a-2ec6-45a9-b0f8-04a273d9d344')
     def test_connectivity_min_max_mtu(self):
@@ -197,22 +198,23 @@
                                                 self.keypair, self.secgroup)
         server_ssh_client1 = ssh.Client(
             self.floating_ips[0]['floating_ip_address'],
-            CONF.validation.image_ssh_user,
+            CONF.neutron_plugin_options.advanced_image_ssh_user,
             pkey=self.keypair['private_key'])
         server2, fip2 = self.create_pingable_vm(self.networks[1],
                                                 self.keypair, self.secgroup)
         server_ssh_client2 = ssh.Client(
             self.floating_ips[0]['floating_ip_address'],
-            CONF.validation.image_ssh_user,
+            CONF.neutron_plugin_options.advanced_image_ssh_user,
             pkey=self.keypair['private_key'])
         for fip in (fip1, fip2):
-            self.check_connectivity(fip['floating_ip_address'],
-                                    CONF.validation.image_ssh_user,
-                                    self.keypair['private_key'])
+            self.check_connectivity(
+                fip['floating_ip_address'],
+                CONF.neutron_plugin_options.advanced_image_ssh_user,
+                self.keypair['private_key'])
         return server_ssh_client1, fip1, server_ssh_client2, fip2
 
     @testtools.skipUnless(
-          CONF.neutron_plugin_options.image_is_advanced,
+          CONF.neutron_plugin_options.advanced_image_ref,
           "Advanced image is required to run this test.")
     @decorators.idempotent_id('bc470200-d8f4-4f07-b294-1b4cbaaa35b9')
     def test_connectivity_min_max_mtu(self):
diff --git a/neutron_tempest_plugin/scenario/test_trunk.py b/neutron_tempest_plugin/scenario/test_trunk.py
index e6d8863..1903180 100644
--- a/neutron_tempest_plugin/scenario/test_trunk.py
+++ b/neutron_tempest_plugin/scenario/test_trunk.py
@@ -64,12 +64,18 @@
         return {'port': port, 'trunk': trunk, 'fip': fip,
                 'server': server}
 
-    def _create_server_with_fip(self, port_id, **server_kwargs):
+    def _create_server_with_fip(self, port_id, use_advanced_image=False,
+                                **server_kwargs):
         fip = self.create_floatingip(port_id=port_id)
+        flavor_ref = CONF.compute.flavor_ref
+        image_ref = CONF.compute.image_ref
+        if use_advanced_image:
+            flavor_ref = CONF.neutron_plugin_options.advanced_image_flavor_ref
+            image_ref = CONF.neutron_plugin_options.advanced_image_ref
         return (
             self.create_server(
-                flavor_ref=CONF.compute.flavor_ref,
-                image_ref=CONF.compute.image_ref,
+                flavor_ref=flavor_ref,
+                image_ref=image_ref,
                 key_name=self.keypair['name'],
                 networks=[{'port': port_id}],
                 security_groups=[{'name': self.secgroup[
@@ -89,7 +95,8 @@
         t = self.client.show_trunk(trunk_id)['trunk']
         return t['status'] == 'ACTIVE'
 
-    def _create_server_with_port_and_subport(self, vlan_network, vlan_tag):
+    def _create_server_with_port_and_subport(self, vlan_network, vlan_tag,
+                                             use_advanced_image=False):
         parent_port = self.create_port(self.network, security_groups=[
             self.secgroup['security_group']['id']])
         port_for_subport = self.create_port(
@@ -102,11 +109,16 @@
             'segmentation_id': vlan_tag}
         self.create_trunk(parent_port, [subport])
 
-        server, fip = self._create_server_with_fip(parent_port['id'])
+        server, fip = self._create_server_with_fip(
+            parent_port['id'], use_advanced_image=use_advanced_image)
+
+        ssh_user = CONF.validation.image_ssh_user
+        if use_advanced_image:
+            ssh_user = CONF.neutron_plugin_options.advanced_image_ssh_user
 
         server_ssh_client = ssh.Client(
             fip['floating_ip_address'],
-            CONF.validation.image_ssh_user,
+            ssh_user,
             pkey=self.keypair['private_key'])
 
         return {
@@ -116,12 +128,15 @@
             'subport': port_for_subport,
         }
 
-    def _wait_for_server(self, server):
+    def _wait_for_server(self, server, advanced_image=False):
+        ssh_user = CONF.validation.image_ssh_user
+        if advanced_image:
+            ssh_user = CONF.neutron_plugin_options.advanced_image_ssh_user
         waiters.wait_for_server_status(self.os_primary.servers_client,
                                        server['server']['id'],
                                        constants.SERVER_STATUS_ACTIVE)
         self.check_connectivity(server['fip']['floating_ip_address'],
-                                CONF.validation.image_ssh_user,
+                                ssh_user,
                                 self.keypair['private_key'])
 
     @decorators.idempotent_id('bb13fe28-f152-4000-8131-37890a40c79e')
@@ -205,7 +220,7 @@
                                 self.keypair['private_key'])
 
     @testtools.skipUnless(
-          CONF.neutron_plugin_options.image_is_advanced,
+          CONF.neutron_plugin_options.advanced_image_ref,
           "Advanced image is required to run this test.")
     @decorators.idempotent_id('a8a02c9b-b453-49b5-89a2-cce7da66aafb')
     def test_subport_connectivity(self):
@@ -215,11 +230,12 @@
         self.create_subnet(vlan_network, gateway=None)
 
         servers = [
-            self._create_server_with_port_and_subport(vlan_network, vlan_tag)
+            self._create_server_with_port_and_subport(
+                vlan_network, vlan_tag, use_advanced_image=True)
             for i in range(2)]
 
         for server in servers:
-            self._wait_for_server(server)
+            self._wait_for_server(server, advanced_image=True)
             # Configure VLAN interfaces on server
             command = CONFIGURE_VLAN_INTERFACE_COMMANDS % {'tag': vlan_tag}
             server['ssh_client'].exec_command(command)