From da17f00f2f3982495bcce38927f890873f5cc957 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 11 Oct 2018 18:35:23 +0200 Subject: [PATCH] Use advanced image only when it's necessary In some scenario tests there is need to use advanced image, like Ubuntu or Centos, because Cirros doesn't provide required features. It is like that in some tests from modules: neutron_tempest_plugin.scenario.test_mtu neutron_tempest_plugin.scenario.test_trunk But such advanced image needs much more time to boot and to have SSH to vm available. There is no need to use such advanced image in all tests. This patch makes some changes in tempest plugin config options: * image_is_advanced - option is removed, * advanced_image_ref - new option added - it's uuid for advanced image, * advanced_flavor_ref - new option added - id of flavor to use with advanced image * advanced_image_ssh_user - new option added - name of user to use to ssh to vm booted from advanced image, This patch also modify neutron_tempest_plugin devstack plugin that it now can find advanced image id in installed Glance service and configure those new config options in Tempest's config file. This patch also modifies scenario jobs definitions that this new advanced_image can be configured and used when it's nesessary. Finally this patch also changes tests mentioned above that now this advanced image is used in those tests. All other scenario tests should works with default, Cirros image. Change-Id: If1b83fbaf33cc01473badeb5cabc8e8670d51d9e --- .zuul.yaml | 21 +++++-- devstack/functions.sh | 55 +++++++++++++++++++ devstack/plugin.sh | 4 ++ devstack/settings | 4 ++ neutron_tempest_plugin/config.py | 24 ++++++-- neutron_tempest_plugin/scenario/test_mtu.py | 30 +++++----- neutron_tempest_plugin/scenario/test_trunk.py | 38 +++++++++---- 7 files changed, 141 insertions(+), 35 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 1063efa4..8c6072ad 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 026f5277..8d8a4bf1 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 e7e30a9e..25cfba6d 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 614376fd..6804a476 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 e15748d4..030a126d 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 7a9f9691..941d499e 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 e6d88635..1903180a 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)