Merge "Adds scenario for DNS-nameserver configuration"

This commit is contained in:
Jenkins 2015-01-19 03:39:22 +00:00 committed by Gerrit Code Review
commit 20f3743b43
6 changed files with 137 additions and 7 deletions

View File

@ -920,6 +920,11 @@
# operations testing. (integer value)
#large_ops_number = 0
# DHCP client used by images to renew DCHP lease. If left empty,
# update operation will be skipped. Supported clients: "udhcpc",
# "dhclient" (string value)
#dhcp_client = udhcpc
[service_available]

View File

@ -97,6 +97,10 @@ class RemoteClient():
cmd = "/bin/ip addr | awk '/ether/ {print $2}'"
return self.exec_command(cmd)
def get_nic_name(self, address):
cmd = "/bin/ip -o addr | awk '/%s/ {print $2}'" % address
return self.exec_command(cmd)
def get_ip_list(self):
cmd = "/bin/ip address"
return self.exec_command(cmd)
@ -116,3 +120,47 @@ class RemoteClient():
# Get pid(s) of a process/program
cmd = "ps -ef | grep %s | grep -v 'grep' | awk {'print $1'}" % pr_name
return self.exec_command(cmd).split('\n')
def get_dns_servers(self):
cmd = 'cat /etc/resolv.conf'
resolve_file = self.exec_command(cmd).strip().split('\n')
entries = (l.split() for l in resolve_file)
dns_servers = [l[1] for l in entries
if len(l) and l[0] == 'nameserver']
return dns_servers
def send_signal(self, pid, signum):
cmd = 'sudo /bin/kill -{sig} {pid}'.format(pid=pid, sig=signum)
return self.exec_command(cmd)
def _renew_lease_udhcpc(self, fixed_ip=None):
"""Renews DHCP lease via udhcpc client. """
file_path = '/var/run/udhcpc.'
nic_name = self.get_nic_name(fixed_ip)
nic_name = nic_name.strip().lower()
pid = self.exec_command('cat {path}{nic}.pid'.
format(path=file_path, nic=nic_name))
pid = pid.strip()
self.send_signal(pid, 'USR1')
def _renew_lease_dhclient(self, fixed_ip=None):
"""Renews DHCP lease via dhclient client. """
cmd = "sudo /sbin/dhclient -r && /sbin/dhclient"
self.exec_command(cmd)
def renew_lease(self, fixed_ip=None):
"""Wrapper method for renewing DHCP lease via given client
Supporting:
* udhcpc
* dhclient
"""
# TODO(yfried): add support for dhcpcd
suported_clients = ['udhcpc', 'dhclient']
dhcp_client = CONF.scenario.dhcp_client
if dhcp_client not in suported_clients:
raise exceptions.InvalidConfiguration('%s DHCP client unsupported'
% dhcp_client)
if dhcp_client == 'udhcpc' and not fixed_ip:
raise ValueError("need to set 'fixed_ip' for udhcpc client")
return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)

View File

@ -860,7 +860,14 @@ ScenarioGroup = [
'large_ops_number',
default=0,
help="specifies how many resources to request at once. Used "
"for large operations testing.")
"for large operations testing."),
# TODO(yfried): add support for dhcpcd
cfg.StrOpt('dhcp_client',
default='udhcpc',
choices=["udhcpc", "dhclient"],
help='DHCP client used by images to renew DCHP lease. '
'If left empty, update operation will be skipped. '
'Supported clients: "udhcpc", "dhclient"')
]

View File

@ -1012,12 +1012,16 @@ class NetworkScenarioTest(ScenarioTest):
router.update(admin_state_up=admin_state_up)
self.assertEqual(admin_state_up, router.admin_state_up)
def create_networks(self, client=None, tenant_id=None):
def create_networks(self, client=None, tenant_id=None,
dns_nameservers=None):
"""Create a network with a subnet connected to a router.
The baremetal driver is a special case since all nodes are
on the same shared network.
:param client: network client to create resources with.
:param tenant_id: id of tenant to create resources in.
:param dns_nameservers: list of dns servers to send to subnet.
:returns: network, subnet, router
"""
if CONF.baremetal.driver_enabled:
@ -1033,7 +1037,12 @@ class NetworkScenarioTest(ScenarioTest):
else:
network = self._create_network(client=client, tenant_id=tenant_id)
router = self._get_router(client=client, tenant_id=tenant_id)
subnet = self._create_subnet(network=network, client=client)
subnet_kwargs = dict(network=network, client=client)
# use explicit check because empty list is a valid option
if dns_nameservers is not None:
subnet_kwargs['dns_nameservers'] = dns_nameservers
subnet = self._create_subnet(**subnet_kwargs)
subnet.add_to_router(router.id)
return network, subnet, router

View File

@ -100,10 +100,10 @@ class TestNetworkBasicOps(manager.NetworkScenarioTest):
self.keypairs = {}
self.servers = []
def _setup_network_and_servers(self):
def _setup_network_and_servers(self, **kwargs):
self.security_group = \
self._create_security_group(tenant_id=self.tenant_id)
self.network, self.subnet, self.router = self.create_networks()
self.network, self.subnet, self.router = self.create_networks(**kwargs)
self.check_networks()
name = data_utils.rand_name('server-smoke')
@ -425,3 +425,62 @@ class TestNetworkBasicOps(manager.NetworkScenarioTest):
self.check_public_network_connectivity(
should_connect=True, msg="after updating "
"admin_state_up of router to True")
def _check_dns_server(self, ssh_client, dns_servers):
servers = ssh_client.get_dns_servers()
self.assertEqual(set(dns_servers), set(servers),
'Looking for servers: {trgt_serv}. '
'Retrieved DNS nameservers: {act_serv} '
'From host: {host}.'
.format(host=ssh_client.ssh_client.host,
act_serv=servers,
trgt_serv=dns_servers))
@testtools.skipUnless(CONF.scenario.dhcp_client,
"DHCP client is not available.")
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_subnet_details(self):
"""Tests that subnet's extra configuration details are affecting
the VMs
NOTE: Neutron subnets push data to servers via dhcp-agent, so any
update in subnet requires server to actively renew its DHCP lease.
1. Configure subnet with dns nameserver
2. retrieve the VM's configured dns and verify it matches the one
configured for the subnet.
3. update subnet's dns
4. retrieve the VM's configured dns and verify it matches the new one
configured for the subnet.
TODO(yfried): add host_routes
any resolution check would be testing either:
* l3 forwarding (tested in test_network_basic_ops)
* Name resolution of an external DNS nameserver - out of scope for
Tempest
"""
# this test check only updates (no actual resolution) so using
# arbitrary ip addresses as nameservers, instead of parsing CONF
initial_dns_server = '1.2.3.4'
alt_dns_server = '9.8.7.6'
self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
self.check_public_network_connectivity(should_connect=True)
floating_ip, server = self.floating_ip_tuple
ip_address = floating_ip.floating_ip_address
private_key = self._get_server_key(server)
ssh_client = self._ssh_to_server(ip_address, private_key)
self._check_dns_server(ssh_client, [initial_dns_server])
self.subnet.update(dns_nameservers=[alt_dns_server])
# asserts that Neutron DB has updated the nameservers
self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
"Failed to update subnet's nameservers")
# server needs to renew its dhcp lease in order to get the new dns
# definitions from subnet
ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
self._check_dns_server(ssh_client, [alt_dns_server])

View File

@ -82,8 +82,10 @@ class DeletableSubnet(DeletableResource):
self._router_ids = set()
def update(self, *args, **kwargs):
result = self.client.update_subnet(subnet=self.id, *args, **kwargs)
super(DeletableSubnet, self).update(**result['subnet'])
result = self.client.update_subnet(self.id,
*args,
**kwargs)
return super(DeletableSubnet, self).update(**result['subnet'])
def add_to_router(self, router_id):
self._router_ids.add(router_id)