neutron-tempest-plugin/neutron_tempest_plugin/scenario/test_internal_dns.py
Elod Illes f2e985e8fd Add test documentation for docs tox target
Enable sphinx to generate documentation from docstrings by running
'tox -e docs'.

Change-Id: I5996e5f07493f69f14172b4bb0535852e89d5456
2023-11-08 15:52:37 +01:00

186 lines
8.2 KiB
Python

# Copyright 2018 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log
from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from neutron_tempest_plugin.common import ssh
from neutron_tempest_plugin import config
from neutron_tempest_plugin.scenario import base
CONF = config.CONF
LOG = log.getLogger(__name__)
class InternalDNSBase(base.BaseTempestTestCase):
"""Base class of useful resources and functionalities for test class."""
port_error_msg = ('Openstack command returned incorrect '
'hostname value in port.')
ssh_error_msg = ('Remote shell command returned incorrect hostname value '
"(command: 'hostname' OR 'cat /etc/hostname').")
@staticmethod
def _rand_name(name):
"""'data_utils.rand_name' wrapper, show name related to test suite."""
return data_utils.rand_name(f'internal-dns-test-{name}')
@classmethod
def resource_setup(cls):
super(InternalDNSBase, cls).resource_setup()
cls.router = cls.create_router_by_client()
cls.keypair = cls.create_keypair(
name=cls._rand_name('shared-keypair'))
cls.secgroup = cls.create_security_group(
name=cls._rand_name('shared-secgroup'))
cls.security_groups.append(cls.secgroup)
cls.create_loginable_secgroup_rule(
secgroup_id=cls.secgroup['id'])
cls.vm_kwargs = {
'flavor_ref': CONF.compute.flavor_ref,
'image_ref': CONF.compute.image_ref,
'key_name': cls.keypair['name'],
'security_groups': [{'name': cls.secgroup['name']}]
}
def _create_ssh_client(self, ip_addr):
return ssh.Client(ip_addr,
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'])
def _validate_port_dns_details(self, checked_hostname, checked_port):
"""Validates reused objects for correct dns values in tests."""
dns_details = checked_port['dns_assignment'][0]
self.assertEqual(checked_hostname, checked_port['dns_name'],
self.port_error_msg)
self.assertEqual(checked_hostname, dns_details['hostname'],
self.port_error_msg)
self.assertIn(checked_hostname, dns_details['fqdn'],
self.port_error_msg)
def _validate_ssh_dns_details(self, checked_hostname, ssh_client):
"""Validates correct dns values returned from ssh command in tests."""
ssh_output = ssh_client.get_hostname()
self.assertIn(checked_hostname, ssh_output, self.ssh_error_msg)
class InternalDNSTest(InternalDNSBase):
"""Tests internal DNS capabilities."""
credentials = ['primary', 'admin']
@utils.requires_ext(extension="dns-integration", service="network")
@decorators.idempotent_id('988347de-07af-471a-abfa-65aea9f452a6')
def test_dns_domain_and_name(self):
"""Test the ability to ping a VM's hostname from another VM.
1) Create two VMs on the same network, giving each a name
2) SSH in to the first VM:
- ping the other VM's internal IP
- ping the other VM's hostname
"""
network = self.create_network(dns_domain='starwars.')
self.setup_network_and_server(network=network, server_name='luke')
self.create_pingable_secgroup_rule(
secgroup_id=self.security_groups[-1]['id'])
self.check_connectivity(self.fip['floating_ip_address'],
CONF.validation.image_ssh_user,
self.keypair['private_key'])
leia = self.create_server(
flavor_ref=CONF.compute.flavor_ref,
image_ref=CONF.compute.image_ref,
key_name=self.keypair['name'],
networks=[{'uuid': self.network['id']}],
security_groups=[
{'name': self.security_groups[-1]['name']}],
name='leia')
ssh_client = ssh.Client(
self.fip['floating_ip_address'],
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'])
self.assertIn('luke', ssh_client.get_hostname())
leia_port = self.client.list_ports(
network_id=self.network['id'],
device_id=leia['server']['id'])['ports'][0]
# Ping with a higher timeout because spawning 2 VMs in some
# environment can put significant load on the deployment, resulting
# in very long boot times.
self.check_remote_connectivity(
ssh_client, leia_port['fixed_ips'][0]['ip_address'],
timeout=CONF.validation.ping_timeout * 10,
servers=[self.server, leia])
resolv_conf = ssh_client.exec_command('cat /etc/resolv.conf')
dns_domain = CONF.neutron_plugin_options.dns_domain
self.assertIn(dns_domain, resolv_conf)
self.assertNotIn('starwars', resolv_conf)
self.check_remote_connectivity(ssh_client, 'leia',
servers=[self.server, leia])
self.check_remote_connectivity(ssh_client, 'leia.' + dns_domain,
servers=[self.server, leia])
@utils.requires_ext(extension="dns-integration", service="network")
@decorators.idempotent_id('db5e612f-f17f-4974-b5f1-9fe89f4a6fc9')
def test_create_and_update_port_with_dns_name(self):
"""Test creation of port with correct internal dns-name (hostname)."""
# 1) Create resources: network, subnet, etc.
# 2) Create a port with wrong dns-name (not as VM name).
# 3) Verify that wrong port initial dns-name.
# was queried from openstack API.
# 4) Update the port with correct dns-name (as VM name).
# 5) Boot a VM with corrected predefined port.
# 6) Verify that correct port dns-name
# was queried from openstack API.
# 7) Validate hostname configured on VM is same as VM's name.
# NOTE: VM's hostname has to be the same as VM's name
# when a VM is created, it is a known limitation.
# Therefore VM's dns-name/hostname is checked to be as VM's name.
vm_correct_name = self._rand_name('vm')
vm_wrong_name = self._rand_name('bazinga')
# create resources
network = self.create_network(name=self._rand_name('network'))
subnet = self.create_subnet(network, name=self._rand_name('subnet'))
self.create_router_interface(self.router['id'], subnet['id'])
# create port with wrong dns-name (not as VM name)
dns_port = self.create_port(network,
dns_name=vm_wrong_name,
security_groups=[self.secgroup['id']],
name=self._rand_name('port'))
# validate dns port with wrong initial hostname from API
self._validate_port_dns_details(vm_wrong_name, dns_port)
# update port with correct dns-name (as VM name)
dns_port = self.update_port(dns_port, dns_name=vm_correct_name)
# create VM with correct predefined dns-name on port
vm_1 = self.create_server(name=vm_correct_name,
networks=[{'port': dns_port['id']}],
**self.vm_kwargs)
# validate dns port with correct changed hostname using API
self._validate_port_dns_details(vm_correct_name, dns_port)
# validate hostname configured on VM is same as VM's name.
vm_1['fip'] = self.create_floatingip(port=dns_port)
vm_1['ssh_client'] = self._create_ssh_client(
vm_1['fip']['floating_ip_address'])
self._validate_ssh_dns_details(vm_correct_name, vm_1['ssh_client'])