Merge "Fix octavia-tempest-plugin on old tempest releases"
diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py
index 1c25d25..a18066a 100644
--- a/octavia_tempest_plugin/tests/test_base.py
+++ b/octavia_tempest_plugin/tests/test_base.py
@@ -15,6 +15,7 @@
 import ipaddress
 import os
 import random
+import re
 import shlex
 import string
 import subprocess
@@ -989,6 +990,31 @@
         return webserver_details
 
     @classmethod
+    def _get_openssh_version(cls):
+        p = subprocess.Popen(["ssh", "-V"],
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+        output = p.communicate()[1]
+
+        try:
+            m = re.match(r"OpenSSH_(\d+)\.(\d+)", output.decode('utf-8'))
+            version_maj = int(m.group(1))
+            version_min = int(m.group(2))
+            return version_maj, version_min
+        except Exception:
+            return None, None
+
+    @classmethod
+    def _need_scp_protocol(cls):
+        # When using scp >= 8.7, force the use of the SCP protocol,
+        # the new default (SFTP protocol) doesn't work with
+        # cirros VMs.
+        ssh_version = cls._get_openssh_version()
+        LOG.debug("ssh_version = {}".format(ssh_version))
+        return (ssh_version[0] > 8 or
+                (ssh_version[0] == 8 and ssh_version[1] >= 7))
+
+    @classmethod
     def _install_start_webserver(cls, ip_address, ssh_key, start_id,
                                  revoke_cert=False):
         local_file = CONF.load_balancer.test_server_path
@@ -1001,14 +1027,20 @@
         with tempfile.NamedTemporaryFile() as key:
             key.write(ssh_key.encode('utf-8'))
             key.flush()
+            ssh_extra_args = (
+                "-o PubkeyAcceptedKeyTypes=+ssh-rsa")
+            if cls._need_scp_protocol():
+                ssh_extra_args += " -O"
             cmd = ("scp -v -o UserKnownHostsFile=/dev/null "
+                   "{7} "
                    "-o StrictHostKeyChecking=no "
                    "-o ConnectTimeout={0} -o ConnectionAttempts={1} "
                    "-i {2} {3} {4}@{5}:{6}").format(
                 CONF.load_balancer.scp_connection_timeout,
                 CONF.load_balancer.scp_connection_attempts,
                 key.name, local_file, CONF.validation.image_ssh_user,
-                ip_address, const.TEST_SERVER_BINARY)
+                ip_address, const.TEST_SERVER_BINARY,
+                ssh_extra_args)
             args = shlex.split(cmd)
             subprocess_args = {'stdout': subprocess.PIPE,
                                'stderr': subprocess.STDOUT,
@@ -1166,14 +1198,20 @@
             subprocess_args = {'stdout': subprocess.PIPE,
                                'stderr': subprocess.STDOUT,
                                'cwd': None}
+            ssh_extra_args = (
+                "-o PubkeyAcceptedKeyTypes=+ssh-rsa")
+            if cls._need_scp_protocol():
+                ssh_extra_args += " -O"
             cmd = ("scp -v -o UserKnownHostsFile=/dev/null "
+                   "{9} "
                    "-o StrictHostKeyChecking=no "
                    "-o ConnectTimeout={0} -o ConnectionAttempts={1} "
                    "-i {2} {3} {4} {5} {6}@{7}:{8}").format(
                 CONF.load_balancer.scp_connection_timeout,
                 CONF.load_balancer.scp_connection_attempts,
                 ssh_key.name, cert_filename, key_filename, client_ca_filename,
-                CONF.validation.image_ssh_user, ip_address, const.DEV_SHM_PATH)
+                CONF.validation.image_ssh_user, ip_address, const.DEV_SHM_PATH,
+                ssh_extra_args)
             args = shlex.split(cmd)
             proc = subprocess.Popen(args, **subprocess_args)
             stdout, stderr = proc.communicate()
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 77615e1..98bbd88 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -49,6 +49,16 @@
           - controller
 
 - nodeset:
+    name: octavia-single-node-centos-9-stream
+    nodes:
+      - name: controller
+        label: nested-virt-centos-9-stream
+    groups:
+      - name: tempest
+        nodes:
+          - controller
+
+- nodeset:
     name: octavia-two-node
     nodes:
       - name: controller
@@ -520,6 +530,11 @@
         USE_PYTHON3: False
 
 - job:
+    name: octavia-v2-dsvm-noop-api-stable-xena
+    parent: octavia-v2-dsvm-noop-api
+    override-checkout: stable/xena
+
+- job:
     name: octavia-v2-dsvm-noop-api-stable-wallaby
     parent: octavia-v2-dsvm-noop-api
     override-checkout: stable/wallaby
@@ -536,12 +551,6 @@
     override-checkout: stable/ussuri
 
 - job:
-    name: octavia-v2-dsvm-noop-api-stable-train
-    parent: octavia-v2-dsvm-noop-api
-    nodeset: octavia-single-node-ubuntu-bionic
-    override-checkout: stable/train
-
-- job:
     name: octavia-v2-dsvm-scenario
     parent: octavia-dsvm-live-base
     vars:
@@ -596,6 +605,11 @@
         override-checkout: 2.30.0
 
 - job:
+    name: octavia-v2-dsvm-scenario-stable-xena
+    parent: octavia-v2-dsvm-scenario
+    override-checkout: stable/xena
+
+- job:
     name: octavia-v2-dsvm-scenario-stable-wallaby
     parent: octavia-v2-dsvm-scenario
     override-checkout: stable/wallaby
@@ -610,12 +624,6 @@
     nodeset: octavia-single-node-ubuntu-bionic
     override-checkout: stable/ussuri
 
-- job:
-    name: octavia-v2-dsvm-scenario-stable-train
-    parent: octavia-v2-dsvm-scenario
-    nodeset: octavia-single-node-ubuntu-bionic
-    override-checkout: stable/train
-
 # Legacy jobs for the transition to the act-stdby two node jobs
 - job:
     name: octavia-v2-dsvm-scenario-two-node
@@ -709,6 +717,16 @@
         OCTAVIA_AMP_IMAGE_SIZE: 3
 
 - job:
+    name: octavia-v2-dsvm-scenario-centos-9-stream
+    parent: octavia-v2-dsvm-scenario
+    nodeset: octavia-single-node-centos-9-stream
+    vars:
+      devstack_localrc:
+        OCTAVIA_AMP_BASE_OS: centos
+        OCTAVIA_AMP_DISTRIBUTION_RELEASE_ID: 9-stream
+        OCTAVIA_AMP_IMAGE_SIZE: 3
+
+- job:
     name: octavia-v2-dsvm-scenario-ubuntu-focal
     parent: octavia-v2-dsvm-scenario
     vars:
@@ -742,6 +760,11 @@
       - ^octavia_tempest_plugin/tests/(?!barbican_scenario/|\w+\.py).*
 
 - job:
+    name: octavia-v2-dsvm-tls-barbican-stable-xena
+    parent: octavia-v2-dsvm-tls-barbican
+    override-checkout: stable/xena
+
+- job:
     name: octavia-v2-dsvm-tls-barbican-stable-wallaby
     parent: octavia-v2-dsvm-tls-barbican
     override-checkout: stable/wallaby
@@ -801,6 +824,11 @@
         override-checkout: 2.30.0
 
 - job:
+    name: octavia-v2-dsvm-spare-pool-stable-xena
+    parent: octavia-v2-dsvm-spare-pool
+    override-checkout: stable/xena
+
+- job:
     name: octavia-v2-dsvm-spare-pool-stable-wallaby
     parent: octavia-v2-dsvm-spare-pool
     override-checkout: stable/wallaby
@@ -817,12 +845,6 @@
     override-checkout: stable/ussuri
 
 - job:
-    name: octavia-v2-dsvm-spare-pool-stable-train
-    parent: octavia-v2-dsvm-spare-pool
-    nodeset: octavia-single-node-ubuntu-bionic
-    override-checkout: stable/train
-
-- job:
     name: octavia-v2-dsvm-cinder-amphora
     parent: octavia-v2-dsvm-scenario
     required-projects:
@@ -952,6 +974,11 @@
       tox_envlist: all
 
 - job:
+    name: octavia-v2-act-stdby-dsvm-scenario-stable-xena
+    parent: octavia-v2-act-stdby-dsvm-scenario
+    override-checkout: stable/xena
+
+- job:
     name: octavia-v2-act-stdby-dsvm-scenario-stable-wallaby
     parent: octavia-v2-act-stdby-dsvm-scenario
     override-checkout: stable/wallaby
@@ -967,12 +994,6 @@
     nodeset: octavia-single-node-ubuntu-bionic
     override-checkout: stable/ussuri
 
-- job:
-    name: octavia-v2-act-stdby-dsvm-scenario-stable-train
-    parent: octavia-v2-act-stdby-dsvm-scenario
-    nodeset: octavia-single-node-ubuntu-bionic
-    override-checkout: stable/train
-
 ######### Third party jobs ##########
 
 - job:
diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml
index 6d1b15a..49ba09d 100644
--- a/zuul.d/projects.yaml
+++ b/zuul.d/projects.yaml
@@ -9,47 +9,49 @@
     check:
       jobs:
         - octavia-v2-dsvm-noop-api
+        - octavia-v2-dsvm-noop-api-stable-xena
         - octavia-v2-dsvm-noop-api-stable-wallaby
         - octavia-v2-dsvm-noop-api-stable-victoria
         - octavia-v2-dsvm-noop-api-stable-ussuri
-        - octavia-v2-dsvm-noop-api-stable-train
         - octavia-v2-dsvm-noop-api-scoped-tokens
         - octavia-v2-dsvm-scenario
+        - octavia-v2-dsvm-scenario-stable-xena
         - octavia-v2-dsvm-scenario-stable-wallaby
         - octavia-v2-dsvm-scenario-stable-victoria
         - octavia-v2-dsvm-scenario-stable-ussuri
-        - octavia-v2-dsvm-scenario-stable-train
         - octavia-v2-dsvm-tls-barbican
+        - octavia-v2-dsvm-tls-barbican-stable-xena
         - octavia-v2-dsvm-tls-barbican-stable-wallaby
         - octavia-v2-dsvm-tls-barbican-stable-victoria
         - octavia-v2-dsvm-tls-barbican-stable-ussuri
-        - octavia-v2-dsvm-tls-barbican-stable-train
         - octavia-v2-dsvm-scenario-ipv6-only:
             voting: false
         - octavia-v2-dsvm-scenario-centos-8-stream:
             voting: false
+        - octavia-v2-dsvm-scenario-centos-9-stream:
+            voting: false
         - octavia-v2-act-stdby-dsvm-scenario-two-node:
             voting: false
         - octavia-v2-act-stdby-dsvm-scenario:
             voting: false
+        - octavia-v2-act-stdby-dsvm-scenario-stable-xena:
+            voting: false
         - octavia-v2-act-stdby-dsvm-scenario-stable-wallaby:
             voting: false
         - octavia-v2-act-stdby-dsvm-scenario-stable-victoria:
             voting: false
         - octavia-v2-act-stdby-dsvm-scenario-stable-ussuri:
             voting: false
-        - octavia-v2-act-stdby-dsvm-scenario-stable-train:
-            voting: false
         - octavia-v2-dsvm-spare-pool:
             voting: false
+        - octavia-v2-dsvm-spare-pool-stable-xena:
+            voting: false
         - octavia-v2-dsvm-spare-pool-stable-wallaby:
             voting: false
         - octavia-v2-dsvm-spare-pool-stable-victoria:
             voting: false
         - octavia-v2-dsvm-spare-pool-stable-ussuri:
             voting: false
-        - octavia-v2-dsvm-spare-pool-stable-train:
-            voting: false
         - octavia-v2-dsvm-cinder-amphora:
             voting: false
         # Third party provider jobs
@@ -62,18 +64,18 @@
       queue: octavia
       jobs:
         - octavia-v2-dsvm-noop-api
+        - octavia-v2-dsvm-noop-api-stable-xena
         - octavia-v2-dsvm-noop-api-stable-wallaby
         - octavia-v2-dsvm-noop-api-stable-victoria
         - octavia-v2-dsvm-noop-api-stable-ussuri
-        - octavia-v2-dsvm-noop-api-stable-train
         - octavia-v2-dsvm-noop-api-scoped-tokens
         - octavia-v2-dsvm-scenario
+        - octavia-v2-dsvm-scenario-stable-xena
         - octavia-v2-dsvm-scenario-stable-wallaby
         - octavia-v2-dsvm-scenario-stable-victoria
         - octavia-v2-dsvm-scenario-stable-ussuri
-        - octavia-v2-dsvm-scenario-stable-train
         - octavia-v2-dsvm-tls-barbican
+        - octavia-v2-dsvm-tls-barbican-stable-xena
         - octavia-v2-dsvm-tls-barbican-stable-wallaby
         - octavia-v2-dsvm-tls-barbican-stable-victoria
         - octavia-v2-dsvm-tls-barbican-stable-ussuri
-        - octavia-v2-dsvm-tls-barbican-stable-train