diff options
Diffstat (limited to 'bin/cloud-init')
-rwxr-xr-x | bin/cloud-init | 128 |
1 files changed, 66 insertions, 62 deletions
diff --git a/bin/cloud-init b/bin/cloud-init index e22f54de..dc480901 100755 --- a/bin/cloud-init +++ b/bin/cloud-init @@ -22,8 +22,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import argparse +import json import os import sys +import time import traceback # This is more just for running from the bin folder so that @@ -126,11 +128,11 @@ def run_module_section(mods, action_name, section): " under section '%s'") % (action_name, full_section_name) sys.stderr.write("%s\n" % (msg)) LOG.debug(msg) - return 0 + return [] else: LOG.debug("Ran %s modules with %s failures", len(which_ran), len(failures)) - return len(failures) + return failures def main_init(name, args): @@ -220,7 +222,7 @@ def main_init(name, args): if existing_files: LOG.debug("Exiting early due to the existence of %s files", existing_files) - return 0 + return (None, []) else: # The cache is not instance specific, so it has to be purged # but we want 'start' to benefit from a cache if @@ -249,9 +251,9 @@ def main_init(name, args): " Likely bad things to come!")) if not args.force: if args.local: - return 0 + return (None, []) else: - return 1 + return (None, ["No instance datasource found."]) # Stage 6 iid = init.instancify() LOG.debug("%s will now be targeting instance id: %s", name, iid) @@ -274,7 +276,7 @@ def main_init(name, args): init.consume_data(PER_ALWAYS) except Exception: util.logexc(LOG, "Consuming user data failed!") - return 1 + return (init.datasource, ["Consuming user data failed!"]) # Stage 8 - re-read and apply relevant cloud-config to include user-data mods = stages.Modules(init, extract_fns(args)) @@ -291,7 +293,7 @@ def main_init(name, args): logging.setupLogging(mods.cfg) # Stage 10 - return run_module_section(mods, name, name) + return (init.datasource, run_module_section(mods, name, name)) def main_modules(action_name, args): @@ -315,14 +317,12 @@ def main_modules(action_name, args): init.fetch() except sources.DataSourceNotFoundException: # There was no datasource found, theres nothing to do - util.logexc(LOG, ('Can not apply stage %s, ' - 'no datasource found!' - " Likely bad things to come!"), name) - print_exc(('Can not apply stage %s, ' - 'no datasource found!' - " Likely bad things to come!") % (name)) + msg = ('Can not apply stage %s, no datasource found! Likely bad ' + 'things to come!' % name) + util.logexc(LOG, msg) + print_exc(msg) if not args.force: - return 1 + return [(msg)] # Stage 3 mods = stages.Modules(init, extract_fns(args)) # Stage 4 @@ -418,8 +418,21 @@ def main_single(name, args): # Guess it worked return 0 -def status_wrapper(args): - (name, functor) = args.action + +def status_wrapper(args, data_d=None, link_d=None): + if data_d is None: + data_d = os.path.normpath("/var/lib/cloud/data") + if link_d is None: + link_d = os.path.normpath("/run/cloud-init") + + status_path = os.path.join(data_d, "status.json") + status_link = os.path.join(link_d, "status.json") + result_path = os.path.join(data_d, "result.json") + result_link = os.path.join(link_d, "result.json") + + util.ensure_dirs((data_d, link_d,)) + + (_name, functor) = args.action if args.name: if args.local: @@ -431,78 +444,69 @@ def status_wrapper(args): modes = ('init', 'init-local', 'modules-config', 'modules-final') - if mode == 'init': + status = None + if mode == 'init-local': + for f in (status_link, result_link, status_path, result_path): + util.del_file(f) + else: + try: + status = json.loads(util.load_file(status_path)) + except: + pass + + if status is None: nullstatus = { - 'errors': [] - 'state': None - 'start': None - 'end': None + 'errors': [], + 'state': None, + 'start': None, + 'end': None, } status = {'v1': {}} for mode in modes: status['v1'][mode] = nullstatus.copy() - else: - status = load_status() + status['v1']['datasource'] = None + status['stage'] = mode v1 = status['v1'] v1[mode]['start'] = time.time() - update_status(status) - # status - # { - # 'v1': { - # 'init': { - # errors: [] - # start: - # end: - # }, - # 'init-local': { - # errors: [] - # start: - # end: - # }, - # 'modules-final': { - # }, - # 'modules-config': { - # }, - # 'datasource': None - # 'stage': ('init', 'init-local', 'modules-final', 'modules-config', 'finished') - # 'errors': - # } - # finished - # { - # 'datasource': - # 'errors': - # } - # - # - exception = None + + util.write_file(status_path, json.dumps(status)) + util.sym_link(os.path.relpath(os.path.status_path, link_d), status_link) + try: - ret = func(args) + ret = functor(args) except Exception as e: v1[mode]['errors'] = [str(e)] v1[mode]['finished'] = time.time() v1['stage'] = None + if mode in ('init', 'init-local'): + (datasource, errors) = ret + if datasource is not None: + v1['datasource'] = datasource + v1[mode]['errors'] = errors + else: + errors = ret + v1[mode]['errors'] = ret - if mode in ('init' or 'init-local'): - # FIXME(smoser): add the datasource here - v1['datasource'] = "~~~datasource~~~" - - update_status(status) + util.write_file(status_path, json.dumps(status)) if mode == "modules-final": # write the 'finished' file errors = [] for m in modes: if v1[m]['errors']: - errors += v1[m]['errors'] - + errors.extend(v1[m].get('errors', [])) + finished = {'datasource': v1['datasource'], 'errors': errors} + util.write_file(result_path, json.dumps(finished)) + util.sym_link(os.path.relpath(os.path.result_path, link_d), + result_link) - return ret + return len(v1[mode]['errors']) def main(): |