Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / qa / tasks / dnsmasq.py
1 """
2 Task for dnsmasq configuration
3 """
4 import contextlib
5 import logging
6
7 from teuthology import misc
8 from teuthology.exceptions import ConfigError
9 from teuthology import contextutil
10 from util import get_remote_for_role
11
12 log = logging.getLogger(__name__)
13
14 @contextlib.contextmanager
15 def setup_dnsmasq(remote, cnames):
16     """ configure dnsmasq on the given remote, adding each cname given """
17     log.info('Configuring dnsmasq on remote %s..', remote.name)
18
19     # back up existing resolv.conf
20     resolv_conf = misc.get_file(remote, '/etc/resolv.conf')
21     # point resolv.conf to local dnsmasq
22     misc.sudo_write_file(remote, '/etc/resolv.conf',
23                          "nameserver 127.0.0.1\n")
24
25     # add address entries to /etc/dnsmasq.d/ceph
26     dnsmasq = "server=8.8.8.8\nserver=8.8.4.4\n"
27     address_template = "address=/{cname}/{ip_address}\n"
28     for cname, ip_address in cnames.iteritems():
29         dnsmasq += address_template.format(cname=cname, ip_address=ip_address)
30     misc.sudo_write_file(remote, '/etc/dnsmasq.d/ceph', dnsmasq)
31
32     remote.run(args=['cat', '/etc/dnsmasq.d/ceph'])
33     # restart dnsmasq
34     remote.run(args=['sudo', 'systemctl', 'restart', 'dnsmasq'])
35     remote.run(args=['sudo', 'systemctl', 'status', 'dnsmasq'])
36     # verify dns name is set
37     remote.run(args=['ping', '-c', '4', cnames.keys()[0]])
38
39     yield
40
41     log.info('Removing dnsmasq configuration from remote %s..', remote.name)
42     # restore resolv.conf
43     misc.sudo_write_file(remote, '/etc/resolv.conf', resolv_conf)
44     # restart dnsmasq
45     remote.run(args=['sudo', 'systemctl', 'restart', 'dnsmasq'])
46
47 @contextlib.contextmanager
48 def task(ctx, config):
49     """
50     Configures dnsmasq to add cnames for teuthology remotes. The task expects a
51     dictionary, where each key is a role. If all cnames for that role use the
52     same address as that role, the cnames can be given as a list. For example,
53     this entry configures dnsmasq on the remote associated with client.0, adding
54     two cnames for the ip address associated with client.0:
55
56         - dnsmasq:
57             client.0:
58             - client0.example.com
59             - c0.example.com
60
61     If the addresses do not all match the given role, a dictionary can be given
62     to specify the ip address by its target role. For example:
63
64         - dnsmasq:
65             client.0:
66               client.0.example.com: client.0
67               client.1.example.com: client.1
68     """
69     # apply overrides
70     overrides = config.get('overrides', {})
71     misc.deep_merge(config, overrides.get('dnsmasq', {}))
72
73     # multiple roles may map to the same remote, so collect names by remote
74     remote_names = {}
75     for role, cnames in config.iteritems():
76         remote = get_remote_for_role(ctx, role)
77         if remote is None:
78             raise ConfigError('no remote for role %s' % role)
79
80         names = remote_names.get(remote, {})
81
82         if isinstance(cnames, list):
83             # when given a list of cnames, point to local ip
84             for cname in cnames:
85                 names[cname] = remote.ip_address
86         elif isinstance(cnames, dict):
87             # when given a dict, look up the remote ip for each
88             for cname, client in cnames.iteritems():
89                 r = get_remote_for_role(ctx, client)
90                 if r is None:
91                     raise ConfigError('no remote for role %s' % client)
92                 names[cname] = r.ip_address
93
94         remote_names[remote] = names
95
96     # run a subtask for each unique remote
97     subtasks = []
98     for remote, cnames in remote_names.iteritems():
99         subtasks.extend([ lambda r=remote, cn=cnames: setup_dnsmasq(r, cn) ])
100
101     with contextutil.nested(*subtasks):
102         yield