Merge "Add wait for location import task"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ed94af0..8890109 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -538,6 +538,37 @@
                                                     volume['id'], 'available')
         return volume
 
+    @classmethod
+    def verify_metadata_from_api(self, server, ssh_client, verify_method):
+        md_url = 'http://169.254.169.254/openstack/latest/meta_data.json'
+        LOG.info('Attempting to verify tagged devices in server %s via '
+                 'the metadata service: %s', server['id'], md_url)
+
+        def get_and_verify_metadata():
+            try:
+                ssh_client.exec_command('curl -V')
+            except exceptions.SSHExecCommandFailed:
+                if not CONF.compute_feature_enabled.config_drive:
+                    raise self.skipException('curl not found in guest '
+                                             'and config drive is '
+                                             'disabled')
+                LOG.warning('curl was not found in the guest, device '
+                            'tagging metadata was not checked in the '
+                            'metadata API')
+                return True
+            cmd = 'curl %s' % md_url
+            md_json = ssh_client.exec_command(cmd)
+            return verify_method(md_json)
+        # NOTE(gmann) Keep refreshing the metadata info until the metadata
+        # cache is refreshed. For safer side, we will go with wait loop of
+        # build_interval till build_timeout. verify_method() above will return
+        # True if all metadata verification is done as expected.
+        if not test_utils.call_until_true(get_and_verify_metadata,
+                                          CONF.compute.build_timeout,
+                                          CONF.compute.build_interval):
+            raise lib_exc.TimeoutException('Timeout while verifying '
+                                           'metadata on server.')
+
     def _detach_volume(self, server, volume):
         """Helper method to detach a volume.
 
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index b7db200..0b39b8a 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -16,6 +16,8 @@
 import netaddr
 import testtools
 
+from oslo_serialization import jsonutils as json
+
 from tempest.api.compute import base
 from tempest.common import utils
 from tempest.common.utils.linux import remote_client
@@ -235,3 +237,76 @@
             servers_client=self.client)
         hostname = linux_client.exec_command("hostname").rstrip()
         self.assertEqual('guest-instance-1-domain-com', hostname)
+
+
+class ServersV294TestFqdnHostnames(base.BaseV2ComputeTest):
+    """Test creating server with FQDN hostname and verifying attributes
+
+    Starting Antelope release, Nova allows to set hostname as an FQDN
+    type and allows free form characters in hostname using --hostname
+    parameter with API above 2.94 .
+
+    This is to create server with --hostname having FQDN type value having
+    more than 64 characters
+    """
+
+    min_microversion = '2.94'
+
+    @classmethod
+    def setup_credentials(cls):
+        cls.prepare_instance_network()
+        super(ServersV294TestFqdnHostnames, cls).setup_credentials()
+
+    @classmethod
+    def setup_clients(cls):
+        super(ServersV294TestFqdnHostnames, cls).setup_clients()
+        cls.client = cls.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(ServersV294TestFqdnHostnames, cls).resource_setup()
+        cls.validation_resources = cls.get_class_validation_resources(
+            cls.os_primary)
+        cls.accessIPv4 = '1.1.1.1'
+        cls.name = 'guest-instance-1'
+        cls.password = data_utils.rand_password()
+        cls.hostname = 'x' * 52 + '-guest-test.domaintest.com'
+        cls.test_server = cls.create_test_server(
+            validatable=True,
+            validation_resources=cls.validation_resources,
+            wait_until='ACTIVE',
+            name=cls.name,
+            accessIPv4=cls.accessIPv4,
+            adminPass=cls.password,
+            hostname=cls.hostname)
+        cls.server = cls.client.show_server(cls.test_server['id'])['server']
+
+    def verify_metadata_hostname(self, md_json):
+        md_dict = json.loads(md_json)
+        dhcp_domain = CONF.compute_feature_enabled.dhcp_domain
+        if md_dict['hostname'] == f"{self.hostname}{dhcp_domain}":
+            return True
+        else:
+            return False
+
+    @decorators.idempotent_id('e7b05488-f9d5-4fce-91b3-e82216c52017')
+    @testtools.skipUnless(CONF.validation.run_validation,
+                          'Instance validation tests are disabled.')
+    def test_verify_hostname_allows_fqdn(self):
+        """Test to verify --hostname allows FQDN type name scheme
+
+        Verify the hostname has FQDN value and Freeform characters
+        in the hostname are allowed
+        """
+        self.assertEqual(
+            self.hostname, self.server['OS-EXT-SRV-ATTR:hostname'])
+        # Verify that metadata API has correct hostname inside guest
+        linux_client = remote_client.RemoteClient(
+            self.get_server_ip(self.test_server, self.validation_resources),
+            self.ssh_user,
+            self.password,
+            self.validation_resources['keypair']['private_key'],
+            server=self.test_server,
+            servers_client=self.client)
+        self.verify_metadata_from_api(
+            self.test_server, linux_client, self.verify_metadata_hostname)
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index 2640311..d2fdd52 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -23,9 +23,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 
 
 CONF = config.CONF
@@ -64,36 +62,6 @@
                                   dhcp=True)
         super(DeviceTaggingBase, cls).setup_credentials()
 
-    def verify_metadata_from_api(self, server, ssh_client, verify_method):
-        md_url = 'http://169.254.169.254/openstack/latest/meta_data.json'
-        LOG.info('Attempting to verify tagged devices in server %s via '
-                 'the metadata service: %s', server['id'], md_url)
-
-        def get_and_verify_metadata():
-            try:
-                ssh_client.exec_command('curl -V')
-            except exceptions.SSHExecCommandFailed:
-                if not CONF.compute_feature_enabled.config_drive:
-                    raise self.skipException('curl not found in guest '
-                                             'and config drive is '
-                                             'disabled')
-                LOG.warning('curl was not found in the guest, device '
-                            'tagging metadata was not checked in the '
-                            'metadata API')
-                return True
-            cmd = 'curl %s' % md_url
-            md_json = ssh_client.exec_command(cmd)
-            return verify_method(md_json)
-        # NOTE(gmann) Keep refreshing the metadata info until the metadata
-        # cache is refreshed. For safer side, we will go with wait loop of
-        # build_interval till build_timeout. verify_method() above will return
-        # True if all metadata verification is done as expected.
-        if not test_utils.call_until_true(get_and_verify_metadata,
-                                          CONF.compute.build_timeout,
-                                          CONF.compute.build_interval):
-            raise exceptions.TimeoutException('Timeout while verifying '
-                                              'metadata on server.')
-
     def verify_metadata_on_config_drive(self, server, ssh_client,
                                         verify_method):
         LOG.info('Attempting to verify tagged devices in server %s via '
diff --git a/tempest/config.py b/tempest/config.py
index bd4a7a1..0fcc71c 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -469,6 +469,15 @@
                      "the '.' with '-' to comply with fqdn hostname. Nova "
                      "changed that in Wallaby cycle, if your cloud is older "
                      "than wallaby then you can keep/make it False."),
+    cfg.StrOpt('dhcp_domain',
+               default='.novalocal',
+               help="Configure a fully-qualified domain name for instance "
+                    "hostnames. The value is suffixed to instance hostname "
+                    "from the database to construct the hostname that "
+                    "appears in the metadata API. To disable this behavior "
+                    "(for example in order to correctly support "
+                    "microversion's 2.94 FQDN hostnames), set this to the "
+                    "empty string."),
     cfg.BoolOpt('change_password',
                 default=False,
                 help="Does the test environment support changing the admin "
@@ -668,11 +677,11 @@
                help="Time in seconds between image operation status "
                     "checks."),
     cfg.ListOpt('container_formats',
-                default=['ami', 'ari', 'aki', 'bare', 'ovf', 'ova'],
+                default=['bare', 'ami', 'ari', 'aki', 'ovf', 'ova'],
                 help="A list of image's container formats "
                      "users can specify."),
     cfg.ListOpt('disk_formats',
-                default=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2',
+                default=['qcow2', 'raw', 'ami', 'ari', 'aki', 'vhd', 'vmdk',
                          'vdi', 'iso', 'vhdx'],
                 help="A list of image's disk formats "
                      "users can specify.")