Merge "Add --await-child option to glance-control."
This commit is contained in:
commit
dfe823a02c
@ -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)
|
||||||
|
@ -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))
|
||||||
|
@ -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())
|
||||||
|
@ -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"\
|
||||||
|
Loading…
Reference in New Issue
Block a user