"""
import contextlib
import logging
+import re
from teuthology import misc
from teuthology.exceptions import ConfigError
packaging.remove_package('dnsmasq', remote)
@contextlib.contextmanager
-def backup_resolv(remote, path):
+def backup_resolv(remote, path, table):
"""
Store a backup of resolv.conf in the testdir and restore it after the task.
+ Reserve 'nameserver' values per remote name in lookup 'table' for future use.
"""
- remote.run(args=['cp', '/etc/resolv.conf', path])
+ resolv_conf = remote.sh(f"cat /etc/resolv.conf | tee {path}")
+ nameserver_re = re.compile(r'\s*nameserver\s+([^\s]*)')
+ for line in resolv_conf.split('\n'):
+ if m := nameserver_re.match(line):
+ table.setdefault(remote.name, {}).setdefault('nameserver', []).append(m[1])
try:
yield
finally:
remote.run(args=['rm', path])
@contextlib.contextmanager
-def replace_resolv(remote, path):
+def replace_resolv(remote, path, table):
"""
Update resolv.conf to point the nameserver at localhost.
"""
remote.run(args=['rm', path])
@contextlib.contextmanager
-def setup_dnsmasq(remote, testdir, cnames):
+def setup_dnsmasq(remote, testdir, cnames, table):
""" configure dnsmasq on the given remote, adding each cname given """
log.info('Configuring dnsmasq on remote %s..', remote.name)
+ # banner first
+ dnsmasq = ["# This file is generated by dnsmasq teuthology task", ""]
+
+ # lookup previously used nameservers for the remote in the table
+ servers = table.get(remote.name, {}).get('nameserver', None)
+ if servers:
+ log.info('Reusing nameservers: %s', servers)
+ dnsmasq.extend(f"server={a}" for a in servers)
+ else:
+ log.info('No predefined nameservers found, using 8.8.x.x')
+ dnsmasq.extend(["server=8.8.8.8", "server=8.8.4.4"])
- # add address entries for each cname
- dnsmasq = "server=8.8.8.8\nserver=8.8.4.4\n"
- address_template = "address=/{cname}/{ip_address}\n"
for cname, ip_address in cnames.items():
- dnsmasq += address_template.format(cname=cname, ip_address=ip_address)
+ dnsmasq.append(f"address=/{cname}/{ip_address}")
- # write to temporary dnsmasq file
- dnsmasq_tmp = '/'.join((testdir, 'ceph.tmp'))
- remote.write_file(dnsmasq_tmp, dnsmasq)
-
- # move into /etc/dnsmasq.d/
+ dnsmasq.append('')
+ dnsmasq_data = "\n".join(dnsmasq)
dnsmasq_path = '/etc/dnsmasq.d/ceph'
- remote.run(args=['sudo', 'mv', dnsmasq_tmp, dnsmasq_path])
+ remote.sudo_write_file(dnsmasq_path, dnsmasq_data)
# restore selinux context if necessary
remote.run(args=['sudo', 'restorecon', dnsmasq_path], check_status=False)
# restart dnsmasq
remote.run(args=['sudo', 'systemctl', 'restart', 'dnsmasq'])
+ # some pause is required for dnsmasq to become operational,
+ # though, trying to just print out the config now instead
+ remote.sh(f'cat {dnsmasq_path}')
# verify dns name is set
remote.run(args=['ping', '-c', '4', next(iter(cnames.keys()))])
testdir = misc.get_testdir(ctx)
resolv_bak = '/'.join((testdir, 'resolv.bak'))
resolv_tmp = '/'.join((testdir, 'resolv.tmp'))
+ resolv_tbl = dict() # { remote.name -> nameserver list } lookup table
# run subtasks for each unique remote
subtasks = []
for remote, cnames in remote_names.items():
subtasks.extend([ lambda r=remote: install_dnsmasq(r) ])
- subtasks.extend([ lambda r=remote: backup_resolv(r, resolv_bak) ])
- subtasks.extend([ lambda r=remote: replace_resolv(r, resolv_tmp) ])
- subtasks.extend([ lambda r=remote, cn=cnames: setup_dnsmasq(r, testdir, cn) ])
+ subtasks.extend([ lambda r=remote: backup_resolv(r, resolv_bak, resolv_tbl) ])
+ subtasks.extend([ lambda r=remote: replace_resolv(r, resolv_tmp, resolv_tbl) ])
+ subtasks.extend([ lambda r=remote, cn=cnames: setup_dnsmasq(r, testdir, cn, resolv_tbl) ])
with contextutil.nested(*subtasks):
yield