summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/cloud-init128
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():