Make nova-dhcpbridge use CONFIG_FILE over FLAGFILE

nova-dhcpbridge's FLAGFILE environment variable is one of the few
remaining references we have to "flags".

Switching to use a new environment variable is easy, but we need
to take care that when you upgrade the code the compute and network
services might not be restarted immediately.

If this happens, the services may launch a new dnsmasq (so rootwrap
needs to continue to support FLAGFILE) or an existing dnsmasq might run
the lease script (so the script needs to support FLAGFILE).

Change-Id: Ieb55daa2507abb8327c7f5a2ef2f682740f31a5d
This commit is contained in:
Mark McLoughlin
2012-11-23 12:38:15 +00:00
parent d5620b2f5a
commit baa1006747
6 changed files with 28 additions and 9 deletions

View File

@@ -95,8 +95,11 @@ def init_leases(network_id):
def main():
"""Parse environment and arguments and call the approproate action."""
argv = config.parse_args(sys.argv,
default_config_files=[os.environ['FLAGFILE']])
try:
config_file = os.environ['CONFIG_FILE']
except KeyError:
config_file = os.environ['FLAGFILE']
argv = config.parse_args(sys.argv, default_config_files=[config_file])
logging.setup("nova")
if int(os.environ.get('TESTING', '0')):

View File

@@ -148,6 +148,7 @@ kill_radvd: KillFilter, root, /usr/sbin/radvd
# nova/network/linux_net.py: dnsmasq call
dnsmasq: DnsmasqFilter, /usr/sbin/dnsmasq, root
dnsmasq_deprecated: DeprecatedDnsmasqFilter, /usr/sbin/dnsmasq, root
# nova/network/linux_net.py: 'radvd', '-C', '%s' % _ra_file(dev, 'conf'..
radvd: CommandFilter, /usr/sbin/radvd, root

View File

@@ -63,6 +63,7 @@ kill_radvd: KillFilter, root, /usr/sbin/radvd
# nova/network/linux_net.py: dnsmasq call
dnsmasq: DnsmasqFilter, /usr/sbin/dnsmasq, root
dnsmasq_deprecated: DeprecatedDnsmasqFilter, /usr/sbin/dnsmasq, root
# nova/network/linux_net.py: 'radvd', '-C', '%s' % _ra_file(dev, 'conf'..
radvd: CommandFilter, /usr/sbin/radvd, root

View File

@@ -840,7 +840,7 @@ def restart_dhcp(context, dev, network_ref):
LOG.debug(_('Pid %d is stale, relaunching dnsmasq'), pid)
cmd = ['env',
'FLAGFILE=%s' % CONF.dhcpbridge_flagfile,
'CONFIG_FILE=%s' % CONF.dhcpbridge_flagfile,
'NETWORK_ID=%s' % str(network_ref['id']),
'dnsmasq',
'--strict-order',

View File

@@ -72,9 +72,11 @@ class RegExpFilter(CommandFilter):
class DnsmasqFilter(CommandFilter):
"""Specific filter for the dnsmasq call (which includes env)"""
CONFIG_FILE_ARG = 'CONFIG_FILE'
def match(self, userargs):
if (userargs[0] == 'env' and
userargs[1].startswith('FLAGFILE=') and
userargs[1].startswith(self.CONFIG_FILE_ARG) and
userargs[2].startswith('NETWORK_ID=') and
userargs[3] == 'dnsmasq'):
return True
@@ -86,11 +88,16 @@ class DnsmasqFilter(CommandFilter):
def get_environment(self, userargs):
env = os.environ.copy()
env['FLAGFILE'] = userargs[1].split('=')[-1]
env[self.CONFIG_FILE_ARG] = userargs[1].split('=')[-1]
env['NETWORK_ID'] = userargs[2].split('=')[-1]
return env
class DeprecatedDnsmasqFilter(DnsmasqFilter):
"""Variant of dnsmasq filter to support old-style FLAGFILE"""
CONFIG_FILE_ARG = 'FLAGFILE'
class KillFilter(CommandFilter):
"""Specific filter for the kill calls.
1st argument is the user to run /bin/kill under

View File

@@ -54,15 +54,22 @@ class RootwrapTestCase(test.TestCase):
filtermatch = wrapper.match_filter(self.filters, invalid)
self.assertTrue(filtermatch is None)
def test_DnsmasqFilter(self):
usercmd = ['env', 'FLAGFILE=A', 'NETWORK_ID=foobar', 'dnsmasq', 'foo']
f = filters.DnsmasqFilter("/usr/bin/dnsmasq", "root")
def _test_DnsmasqFilter(self, filter_class, config_file_arg):
usercmd = ['env', config_file_arg + '=A', 'NETWORK_ID=foobar',
'dnsmasq', 'foo']
f = filter_class("/usr/bin/dnsmasq", "root")
self.assertTrue(f.match(usercmd))
self.assertEqual(f.get_command(usercmd), ['/usr/bin/dnsmasq', 'foo'])
env = f.get_environment(usercmd)
self.assertEqual(env.get('FLAGFILE'), 'A')
self.assertEqual(env.get(config_file_arg), 'A')
self.assertEqual(env.get('NETWORK_ID'), 'foobar')
def test_DnsmasqFilter(self):
self._test_DnsmasqFilter(filters.DnsmasqFilter, 'CONFIG_FILE')
def test_DeprecatedDnsmasqFilter(self):
self._test_DnsmasqFilter(filters.DeprecatedDnsmasqFilter, 'FLAGFILE')
def test_KillFilter(self):
if not os.path.exists("/proc/%d" % os.getpid()):
self.skipTest("Test requires /proc filesystem (procfs)")