diff --git a/.zuul.yaml b/.zuul.yaml index 1063efa46..8c6072ada 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 026f52774..8d8a4bf15 100644 --- a/devstack/functions.sh +++ b/devstack/functions.sh @@ -30,3 +30,58 @@ function save_function { # 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 e7e30a9eb..25cfba6d5 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -15,5 +15,9 @@ if [[ "$1" == "stack" ]]; then 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 614376fdc..6804a4761 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 e15748d41..030a126d8 100644 --- a/neutron_tempest_plugin/config.py +++ b/neutron_tempest_plugin/config.py @@ -29,10 +29,6 @@ NeutronPluginOptions = [ 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 @@ NeutronPluginOptions = [ 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 7a9f9691f..941d499e0 100644 --- a/neutron_tempest_plugin/scenario/test_mtu.py +++ b/neutron_tempest_plugin/scenario/test_mtu.py @@ -47,8 +47,8 @@ class NetworkMtuBaseTest(base.BaseTempestTestCase): 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 @@ class NetworkMtuTest(NetworkMtuBaseTest): 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 @@ class NetworkWritableMtuTest(NetworkMtuBaseTest): 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 e6d88635e..1903180a4 100644 --- a/neutron_tempest_plugin/scenario/test_trunk.py +++ b/neutron_tempest_plugin/scenario/test_trunk.py @@ -64,12 +64,18 @@ class TrunkTest(base.BaseTempestTestCase): 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 @@ class TrunkTest(base.BaseTempestTestCase): 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 @@ class TrunkTest(base.BaseTempestTestCase): '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 @@ class TrunkTest(base.BaseTempestTestCase): '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 @@ class TrunkTest(base.BaseTempestTestCase): 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 @@ class TrunkTest(base.BaseTempestTestCase): 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)