Merge "Add --await-child option to glance-control."

This commit is contained in:
Jenkins 2012-02-02 18:42:00 +00:00 committed by Gerrit Code Review
commit dfe823a02c
4 changed files with 49 additions and 8 deletions

View File

@ -111,6 +111,18 @@ def do_start(server, conf, args):
fp.write('%d\n' % pid) fp.write('%d\n' % pid)
fp.close() fp.close()
def await_child(pid):
if conf.await_child:
bail_time = time.time() + conf.await_child
while time.time() < bail_time:
reported_pid, status = os.waitpid(pid, os.WNOHANG)
if reported_pid == pid:
global exitcode
# the exit code is encoded in 2nd least significant byte
exitcode = status >> 8
break
time.sleep(0.05)
def launch(pid_file, conf_file=None): def launch(pid_file, conf_file=None):
args = [server] args = [server]
print 'Starting %s' % server, print 'Starting %s' % server,
@ -136,6 +148,7 @@ def do_start(server, conf, args):
sys.exit(0) sys.exit(0)
else: else:
write_pid_file(pid_file, pid) write_pid_file(pid_file, pid)
await_child(pid)
if not conf.pid_file: if not conf.pid_file:
pid_file = '/var/run/glance/%s.pid' % server pid_file = '/var/run/glance/%s.pid' % server
@ -181,11 +194,19 @@ def do_stop(server, conf, args, graceful=False):
if __name__ == '__main__': if __name__ == '__main__':
exitcode = 0
conf = config.GlanceConfigOpts(usage=USAGE) conf = config.GlanceConfigOpts(usage=USAGE)
conf.register_cli_opt(cfg.StrOpt('pid-file', conf.register_cli_opt(cfg.StrOpt('pid-file',
metavar='PATH', metavar='PATH',
help='File to use as pid file. Default: ' help='File to use as pid file. Default: '
'/var/run/glance/$server.pid')) '/var/run/glance/$server.pid'))
conf.register_cli_opt(cfg.IntOpt('await-child',
metavar='DELAY',
default=0,
help='Period to wait for service death '
'in order to report exit code '
'(default is to not wait at all)'))
args = conf() args = conf()
if len(args) < 2: if len(args) < 2:
@ -235,3 +256,5 @@ if __name__ == '__main__':
for server in servers: for server in servers:
do_stop(server, conf, args, graceful=True) do_stop(server, conf, args, graceful=True)
do_start(server, conf, args) do_start(server, conf, args)
sys.exit(exitcode)

View File

@ -87,6 +87,7 @@ class Server(object):
self.server_control = './bin/glance-control' self.server_control = './bin/glance-control'
self.exec_env = None self.exec_env = None
self.deployment_flavor = '' self.deployment_flavor = ''
self.server_control_options = ''
def write_conf(self, **kwargs): def write_conf(self, **kwargs):
""" """
@ -128,7 +129,7 @@ class Server(object):
return self.conf_file_name return self.conf_file_name
def start(self, **kwargs): def start(self, expected_exitcode=0, **kwargs):
""" """
Starts the server. Starts the server.
@ -141,8 +142,12 @@ class Server(object):
cmd = ("%(server_control)s %(server_name)s start " cmd = ("%(server_control)s %(server_name)s start "
"%(conf_file_name)s --pid-file=%(pid_file)s " "%(conf_file_name)s --pid-file=%(pid_file)s "
"%(server_control_options)s"
% self.__dict__) % self.__dict__)
return execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env) return execute(cmd,
no_venv=self.no_venv,
exec_env=self.exec_env,
expected_exitcode=expected_exitcode)
def stop(self): def stop(self):
""" """
@ -439,7 +444,11 @@ class FunctionalTest(unittest.TestCase):
if os.path.exists(f): if os.path.exists(f):
os.unlink(f) os.unlink(f)
def start_server(self, server, expect_launch, **kwargs): def start_server(self,
server,
expect_launch,
expected_exitcode=0,
**kwargs):
""" """
Starts a server on an unused port. Starts a server on an unused port.
@ -449,13 +458,15 @@ class FunctionalTest(unittest.TestCase):
:param server: the server to launch :param server: the server to launch
:param expect_launch: true iff the server is expected to :param expect_launch: true iff the server is expected to
successfully start successfully start
:param expected_exitcode: expected exitcode from the launcher
""" """
self.cleanup() self.cleanup()
# Start up the requested server # Start up the requested server
exitcode, out, err = server.start(**kwargs) exitcode, out, err = server.start(expected_exitcode=expected_exitcode,
**kwargs)
self.assertEqual(0, exitcode, self.assertEqual(expected_exitcode, exitcode,
"Failed to spin up the requested server. " "Failed to spin up the requested server. "
"Got: %s" % err) "Got: %s" % err)
self.assertTrue(re.search("Starting glance-[a-z]+ with", out)) self.assertTrue(re.search("Starting glance-[a-z]+ with", out))

View File

@ -1248,8 +1248,10 @@ class TestApi(functional.FunctionalTest):
""" """
self.cleanup() self.cleanup()
self.api_server.default_store = 'shouldnotexist' self.api_server.default_store = 'shouldnotexist'
self.api_server.server_control_options += ' --await-child=1'
# ensure that the API server fails to launch # ensure that the API server fails to launch
self.start_server(self.api_server, self.start_server(self.api_server,
expect_launch=False, expect_launch=False,
expected_exitcode=255,
**self.__dict__.copy()) **self.__dict__.copy())

View File

@ -168,7 +168,11 @@ def skip_if_disabled(func):
return wrapped return wrapped
def execute(cmd, raise_error=True, no_venv=False, exec_env=None): def execute(cmd,
raise_error=True,
no_venv=False,
exec_env=None,
expected_exitcode=0):
""" """
Executes a command in a subprocess. Returns a tuple Executes a command in a subprocess. Returns a tuple
of (exitcode, out, err), where out is the string output of (exitcode, out, err), where out is the string output
@ -183,6 +187,7 @@ def execute(cmd, raise_error=True, no_venv=False, exec_env=None):
variables; values may be callables, which will variables; values may be callables, which will
be passed the current value of the named be passed the current value of the named
environment variable environment variable
:param expected_exitcode: expected exitcode from the launcher
""" """
env = os.environ.copy() env = os.environ.copy()
@ -219,7 +224,7 @@ def execute(cmd, raise_error=True, no_venv=False, exec_env=None):
result = process.communicate() result = process.communicate()
(out, err) = result (out, err) = result
exitcode = process.returncode exitcode = process.returncode
if process.returncode != 0 and raise_error: if process.returncode != expected_exitcode and raise_error:
msg = "Command %(cmd)s did not succeed. Returned an exit "\ msg = "Command %(cmd)s did not succeed. Returned an exit "\
"code of %(exitcode)d."\ "code of %(exitcode)d."\
"\n\nSTDOUT: %(out)s"\ "\n\nSTDOUT: %(out)s"\