diff --git a/nova/tests/unit/test_utils.py b/nova/tests/unit/test_utils.py index 03f565b7e49..639191fedf3 100644 --- a/nova/tests/unit/test_utils.py +++ b/nova/tests/unit/test_utils.py @@ -73,24 +73,25 @@ def test_parse_server_string(self): self.assertEqual(('', ''), result) def test_hostname_unicode_sanitization(self): - hostname = u"\u7684.test.example.com" - self.assertEqual("test.example.com", - utils.sanitize_hostname(hostname)) + hostname = u'\u7684myamazinghostname' + self.assertEqual( + 'myamazinghostname', utils.sanitize_hostname(hostname)) def test_hostname_sanitize_periods(self): - hostname = "....test.example.com..." - self.assertEqual("test.example.com", - utils.sanitize_hostname(hostname)) + hostname = '....test.example.com...' + self.assertEqual( + 'test-example-com', utils.sanitize_hostname(hostname)) def test_hostname_sanitize_dashes(self): - hostname = "----test.example.com---" - self.assertEqual("test.example.com", - utils.sanitize_hostname(hostname)) + hostname = '----my-amazing-hostname---' + self.assertEqual( + "my-amazing-hostname", utils.sanitize_hostname(hostname)) def test_hostname_sanitize_characters(self): hostname = "(#@&$!(@*--#&91)(__=+--test-host.example!!.com-0+" - self.assertEqual("91----test-host.example.com-0", - utils.sanitize_hostname(hostname)) + self.assertEqual( + "91----test-host-example-com-0", + utils.sanitize_hostname(hostname)) def test_hostname_translate(self): hostname = "<}\x1fh\x10e\x08l\x02l\x05o\x12!{>" @@ -99,20 +100,20 @@ def test_hostname_translate(self): def test_hostname_has_default(self): hostname = u"\u7684hello" defaultname = "Server-1" - self.assertEqual("hello", utils.sanitize_hostname(hostname, - defaultname)) + self.assertEqual( + "hello", utils.sanitize_hostname(hostname, defaultname)) def test_hostname_empty_has_default(self): hostname = u"\u7684" defaultname = "Server-1" - self.assertEqual(defaultname, utils.sanitize_hostname(hostname, - defaultname)) + self.assertEqual( + defaultname, utils.sanitize_hostname(hostname, defaultname)) def test_hostname_empty_has_default_too_long(self): hostname = u"\u7684" defaultname = "a" * 64 - self.assertEqual("a" * 63, utils.sanitize_hostname(hostname, - defaultname)) + self.assertEqual( + "a" * 63, utils.sanitize_hostname(hostname, defaultname)) def test_hostname_empty_no_default(self): hostname = u"\u7684" diff --git a/nova/utils.py b/nova/utils.py index 0575b9a8f65..a4a1abaaa17 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -372,7 +372,7 @@ def truncate_hostname(name): hostname = hostname.encode('latin-1', 'ignore').decode('latin-1') hostname = truncate_hostname(hostname) - hostname = re.sub('[ _]', '-', hostname) + hostname = re.sub(r'[ _\.]', '-', hostname) hostname = re.sub(r'[^\w.-]+', '', hostname) hostname = hostname.lower() hostname = hostname.strip('.-') diff --git a/releasenotes/notes/bug-1581977-310e5f218ccb1d16.yaml b/releasenotes/notes/bug-1581977-310e5f218ccb1d16.yaml new file mode 100644 index 00000000000..8498b5c36e9 --- /dev/null +++ b/releasenotes/notes/bug-1581977-310e5f218ccb1d16.yaml @@ -0,0 +1,24 @@ +--- +fixes: + - | + Nova will now replace periods (``.``) with dashes (``-``) when santizing an + instance's display name for use as a hostname. + + Nova publishes hostnames for instances via the metadata service and config + drives. This hostname is based on a sanitized version of the instance name + combined with the domain value specified in ``[api] dhcp_domain``. The + previous sanitization of the hostname included the replacement of whitespace + and underscores with dashes and the stripping of unicode characters along + with leading and trailing periods and dashes. It did not, however, include + the removal of periods in the name. Periods are not valid in the hostname + or, more specifically, in the host-specific or leaf label (the ``host`` in + ``host.example.com``) and their presence can cause conflicts when ``[api] + dhcp_domain`` is configured, leading to instances being mistakenly + configured with hostnames like ``host.example.com.example.com``. More + pressingly, their use can result in a failure to boot instances if DNS + integration is enabled in neutron, likely via designate, as the hostname is + identified as a FQDN (fully-qualified domain name) by neutron and reasonable + instance names like ``test-ubuntu20.04`` will be rejected as invalid FQDNs, + in this case because the name would yield a TLD (top-level domain) of ``04`` + and TLDs cannot be entire numerical. To avoid these issues, periods are now + replaced with dashes.