Re-execute after commands and on SIGHUP

After we have run a command and committed, re-execute ourselves. This
ensures that we will get any configurations that may have come from
underlying commands. Also re-execute if os-collect-config is sent HUP.

Change-Id: I87b4d8ce44fcbc9458a3a4fbb2445e4c9d0ad4e7
This commit is contained in:
Clint Byrum 2013-07-29 16:06:54 -07:00
parent 4cc2c41bbc
commit 1dcc5a3571
2 changed files with 54 additions and 5 deletions

View File

@ -15,6 +15,7 @@
import json import json
import os import os
import signal
import subprocess import subprocess
import sys import sys
import time import time
@ -114,7 +115,23 @@ def collect_all(collectors, store=False, requests_impl_map=None):
return (any_changed, paths_or_content) return (any_changed, paths_or_content)
def reexec_self(signal=None, frame=None):
if signal:
logger.info('Signal received. Re-executing %s' % sys.argv)
# Close all but stdin/stdout/stderr
os.closerange(3, 255)
os.execv(sys.argv[0], sys.argv)
def call_command(files, command):
env = dict(os.environ)
env["OS_CONFIG_FILES"] = ':'.join(files)
logger.info("Executing %s" % command)
subprocess.call(CONF.command, env=env, shell=True)
def __main__(args=sys.argv, requests_impl_map=None): def __main__(args=sys.argv, requests_impl_map=None):
signal.signal(signal.SIGHUP, reexec_self)
setup_conf() setup_conf()
CONF(args=args[1:], prog="os-collect-config") CONF(args=args[1:], prog="os-collect-config")
@ -133,12 +150,13 @@ def __main__(args=sys.argv, requests_impl_map=None):
requests_impl_map=requests_impl_map) requests_impl_map=requests_impl_map)
if CONF.command: if CONF.command:
if any_changed: if any_changed:
env = dict(os.environ) # ignore HUP now since we will reexec after commit anyway
env["OS_CONFIG_FILES"] = ':'.join(content) signal.signal(signal.SIGHUP, signal.SIG_IGN)
logger.info("Executing %s" % CONF.command) call_command(content, CONF.command)
subprocess.call(CONF.command, env=env, shell=True)
for collector in cfg.CONF.collectors: for collector in cfg.CONF.collectors:
cache.commit(collector) cache.commit(collector)
if not CONF.one_time:
reexec_self()
else: else:
logger.debug("No changes detected.") logger.debug("No changes detected.")
if CONF.one_time: if CONF.one_time:

View File

@ -18,8 +18,11 @@ import extras
import fixtures import fixtures
import json import json
import os import os
from oslo.config import cfg import signal
import sys
import tempfile import tempfile
from oslo.config import cfg
import testtools import testtools
from testtools import matchers from testtools import matchers
@ -39,6 +42,7 @@ def _setup_local_metadata(test_case):
class TestCollect(testtools.TestCase): class TestCollect(testtools.TestCase):
def setUp(self): def setUp(self):
super(TestCollect, self).setUp() super(TestCollect, self).setUp()
self.useFixture(fixtures.FakeLogger()) self.useFixture(fixtures.FakeLogger())
@ -235,8 +239,35 @@ class TestCollectAll(testtools.TestCase):
class TestConf(testtools.TestCase): class TestConf(testtools.TestCase):
def test_setup_conf(self): def test_setup_conf(self):
collect.setup_conf() collect.setup_conf()
self.assertEquals('/var/run/os-collect-config', cfg.CONF.cachedir) self.assertEquals('/var/run/os-collect-config', cfg.CONF.cachedir)
self.assertTrue(extras.safe_hasattr(cfg.CONF, 'ec2')) self.assertTrue(extras.safe_hasattr(cfg.CONF, 'ec2'))
self.assertTrue(extras.safe_hasattr(cfg.CONF, 'cfn')) self.assertTrue(extras.safe_hasattr(cfg.CONF, 'cfn'))
class TestHup(testtools.TestCase):
def setUp(self):
super(TestHup, self).setUp()
self.log = self.useFixture(fixtures.FakeLogger())
def fake_closerange(low, high):
self.assertEquals(3, low)
self.assertEquals(255, high)
def fake_execv(path, args):
self.assertEquals(sys.argv[0], path)
self.assertEquals(sys.argv, args)
self.useFixture(fixtures.MonkeyPatch('os.execv', fake_execv))
self.useFixture(fixtures.MonkeyPatch('os.closerange', fake_closerange))
def test_reexec_self_signal(self):
collect.reexec_self(signal.SIGHUP, None)
self.assertIn('Signal received', self.log.output)
def test_reexec_self(self):
collect.reexec_self()
self.assertNotIn('Signal received', self.log.output)