|
Packit Service |
a04d08 |
#!/usr/bin/python
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Copyright (C) 2012 Canonical Ltd.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2012 Yahoo! Inc.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2017 Amazon.com, Inc. or its affiliates
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Scott Moser <scott.moser@canonical.com>
|
|
Packit Service |
a04d08 |
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
|
|
Packit Service |
a04d08 |
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
|
|
Packit Service |
a04d08 |
# Author: Andrew Jorgensen <ajorgens@amazon.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import argparse
|
|
Packit Service |
a04d08 |
import json
|
|
Packit Service |
a04d08 |
import os
|
|
Packit Service |
a04d08 |
import sys
|
|
Packit Service |
a04d08 |
import time
|
|
Packit Service |
a04d08 |
import traceback
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import patcher
|
|
Packit Service |
a04d08 |
patcher.patch() # noqa
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import log as logging
|
|
Packit Service |
a04d08 |
from cloudinit import netinfo
|
|
Packit Service |
a04d08 |
from cloudinit import signal_handler
|
|
Packit Service |
a04d08 |
from cloudinit import sources
|
|
Packit Service |
a04d08 |
from cloudinit import stages
|
|
Packit Service |
a04d08 |
from cloudinit import url_helper
|
|
Packit Service |
a04d08 |
from cloudinit import util
|
|
Packit Service |
a04d08 |
from cloudinit import version
|
|
Packit Service |
a04d08 |
from cloudinit import warnings
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import reporting
|
|
Packit Service |
a04d08 |
from cloudinit.reporting import events
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
|
|
Packit Service |
a04d08 |
CLOUD_CONFIG)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import atomic_helper
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit.config import cc_set_hostname
|
|
Packit Service |
a04d08 |
from cloudinit import dhclient_hook
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Welcome message template
|
|
Packit Service |
a04d08 |
WELCOME_MSG_TPL = ("Cloud-init v. {version} running '{action}' at "
|
|
Packit Service |
a04d08 |
"{timestamp}. Up {uptime} seconds.")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Module section template
|
|
Packit Service |
a04d08 |
MOD_SECTION_TPL = "cloud_%s_modules"
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Frequency shortname to full name
|
|
Packit Service |
a04d08 |
# (so users don't have to remember the full name...)
|
|
Packit Service |
a04d08 |
FREQ_SHORT_NAMES = {
|
|
Packit Service |
a04d08 |
'instance': PER_INSTANCE,
|
|
Packit Service |
a04d08 |
'always': PER_ALWAYS,
|
|
Packit Service |
a04d08 |
'once': PER_ONCE,
|
|
Packit Service |
a04d08 |
}
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
LOG = logging.getLogger()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Used for when a logger may not be active
|
|
Packit Service |
a04d08 |
# and we still want to print exceptions...
|
|
Packit Service |
a04d08 |
def print_exc(msg=''):
|
|
Packit Service |
a04d08 |
if msg:
|
|
Packit Service |
a04d08 |
sys.stderr.write("%s\n" % (msg))
|
|
Packit Service |
a04d08 |
sys.stderr.write('-' * 60)
|
|
Packit Service |
a04d08 |
sys.stderr.write("\n")
|
|
Packit Service |
a04d08 |
traceback.print_exc(file=sys.stderr)
|
|
Packit Service |
a04d08 |
sys.stderr.write('-' * 60)
|
|
Packit Service |
a04d08 |
sys.stderr.write("\n")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def welcome(action, msg=None):
|
|
Packit Service |
a04d08 |
if not msg:
|
|
Packit Service |
a04d08 |
msg = welcome_format(action)
|
|
Packit Service |
a04d08 |
util.multi_log("%s\n" % (msg),
|
|
Packit Service |
a04d08 |
console=False, stderr=True, log=LOG)
|
|
Packit Service |
a04d08 |
return msg
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def welcome_format(action):
|
|
Packit Service |
a04d08 |
return WELCOME_MSG_TPL.format(
|
|
Packit Service |
a04d08 |
version=version.version_string(),
|
|
Packit Service |
a04d08 |
uptime=util.uptime(),
|
|
Packit Service |
a04d08 |
timestamp=util.time_rfc2822(),
|
|
Packit Service |
a04d08 |
action=action)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def extract_fns(args):
|
|
Packit Service |
a04d08 |
# Files are already opened so lets just pass that along
|
|
Packit Service |
a04d08 |
# since it would of broke if it couldn't have
|
|
Packit Service |
a04d08 |
# read that file already...
|
|
Packit Service |
a04d08 |
fn_cfgs = []
|
|
Packit Service |
a04d08 |
if args.files:
|
|
Packit Service |
a04d08 |
for fh in args.files:
|
|
Packit Service |
a04d08 |
# The realpath is more useful in logging
|
|
Packit Service |
a04d08 |
# so lets resolve to that...
|
|
Packit Service |
a04d08 |
fn_cfgs.append(os.path.realpath(fh.name))
|
|
Packit Service |
a04d08 |
return fn_cfgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def run_module_section(mods, action_name, section):
|
|
Packit Service |
a04d08 |
full_section_name = MOD_SECTION_TPL % (section)
|
|
Packit Service |
a04d08 |
(which_ran, failures) = mods.run_section(full_section_name)
|
|
Packit Service |
a04d08 |
total_attempted = len(which_ran) + len(failures)
|
|
Packit Service |
a04d08 |
if total_attempted == 0:
|
|
Packit Service |
a04d08 |
msg = ("No '%s' modules to run"
|
|
Packit Service |
a04d08 |
" under section '%s'") % (action_name, full_section_name)
|
|
Packit Service |
a04d08 |
sys.stderr.write("%s\n" % (msg))
|
|
Packit Service |
a04d08 |
LOG.debug(msg)
|
|
Packit Service |
a04d08 |
return []
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("Ran %s modules with %s failures",
|
|
Packit Service |
a04d08 |
len(which_ran), len(failures))
|
|
Packit Service |
a04d08 |
return failures
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def apply_reporting_cfg(cfg):
|
|
Packit Service |
a04d08 |
if cfg.get('reporting'):
|
|
Packit Service |
a04d08 |
reporting.update_configuration(cfg.get('reporting'))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def parse_cmdline_url(cmdline, names=('cloud-config-url', 'url')):
|
|
Packit Service |
a04d08 |
data = util.keyval_str_to_dict(cmdline)
|
|
Packit Service |
a04d08 |
for key in names:
|
|
Packit Service |
a04d08 |
if key in data:
|
|
Packit Service |
a04d08 |
return key, data[key]
|
|
Packit Service |
a04d08 |
raise KeyError("No keys (%s) found in string '%s'" %
|
|
Packit Service |
a04d08 |
(cmdline, names))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def attempt_cmdline_url(path, network=True, cmdline=None):
|
|
Packit Service |
a04d08 |
"""Write data from url referenced in command line to path.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
path: a file to write content to if downloaded.
|
|
Packit Service |
a04d08 |
network: should network access be assumed.
|
|
Packit Service |
a04d08 |
cmdline: the cmdline to parse for cloud-config-url.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
This is used in MAAS datasource, in "ephemeral" (read-only root)
|
|
Packit Service |
a04d08 |
environment where the instance netboots to iscsi ro root.
|
|
Packit Service |
a04d08 |
and the entity that controls the pxe config has to configure
|
|
Packit Service |
a04d08 |
the maas datasource.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
An attempt is made on network urls even in local datasource
|
|
Packit Service |
a04d08 |
for case of network set up in initramfs.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
Return value is a tuple of a logger function (logging.DEBUG)
|
|
Packit Service |
a04d08 |
and a message indicating what happened.
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if cmdline is None:
|
|
Packit Service |
a04d08 |
cmdline = util.get_cmdline()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
cmdline_name, url = parse_cmdline_url(cmdline)
|
|
Packit Service |
a04d08 |
except KeyError:
|
|
Packit Service |
a04d08 |
return (logging.DEBUG, "No kernel command line url found.")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
path_is_local = url.startswith("file://") or url.startswith("/")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if path_is_local and os.path.exists(path):
|
|
Packit Service |
a04d08 |
if network:
|
|
Packit Service |
a04d08 |
m = ("file '%s' existed, possibly from local stage download"
|
|
Packit Service |
a04d08 |
" of command line url '%s'. Not re-writing." % (path, url))
|
|
Packit Service |
a04d08 |
level = logging.INFO
|
|
Packit Service |
a04d08 |
if path_is_local:
|
|
Packit Service |
a04d08 |
level = logging.DEBUG
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
m = ("file '%s' existed, possibly from previous boot download"
|
|
Packit Service |
a04d08 |
" of command line url '%s'. Not re-writing." % (path, url))
|
|
Packit Service |
a04d08 |
level = logging.WARN
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
return (level, m)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
kwargs = {'url': url, 'timeout': 10, 'retries': 2}
|
|
Packit Service |
a04d08 |
if network or path_is_local:
|
|
Packit Service |
a04d08 |
level = logging.WARN
|
|
Packit Service |
a04d08 |
kwargs['sec_between'] = 1
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
level = logging.DEBUG
|
|
Packit Service |
a04d08 |
kwargs['sec_between'] = .1
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
data = None
|
|
Packit Service |
a04d08 |
header = b'#cloud-config'
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
resp = url_helper.read_file_or_url(**kwargs)
|
|
Packit Service |
a04d08 |
if resp.ok():
|
|
Packit Service |
a04d08 |
data = resp.contents
|
|
Packit Service |
a04d08 |
if not resp.contents.startswith(header):
|
|
Packit Service |
a04d08 |
if cmdline_name == 'cloud-config-url':
|
|
Packit Service |
a04d08 |
level = logging.WARN
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
level = logging.INFO
|
|
Packit Service |
a04d08 |
return (
|
|
Packit Service |
a04d08 |
level,
|
|
Packit Service |
a04d08 |
"contents of '%s' did not start with %s" % (url, header))
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
return (level,
|
|
Packit Service |
a04d08 |
"url '%s' returned code %s. Ignoring." % (url, resp.code))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
except url_helper.UrlError as e:
|
|
Packit Service |
a04d08 |
return (level, "retrieving url '%s' failed: %s" % (url, e))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
util.write_file(path, data, mode=0o600)
|
|
Packit Service |
a04d08 |
return (logging.INFO,
|
|
Packit Service |
a04d08 |
"wrote cloud-config data from %s='%s' to %s" %
|
|
Packit Service |
a04d08 |
(cmdline_name, url, path))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def main_init(name, args):
|
|
Packit Service |
a04d08 |
deps = [sources.DEP_FILESYSTEM, sources.DEP_NETWORK]
|
|
Packit Service |
a04d08 |
if args.local:
|
|
Packit Service |
a04d08 |
deps = [sources.DEP_FILESYSTEM]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
early_logs = [attempt_cmdline_url(
|
|
Packit Service |
a04d08 |
path=os.path.join("%s.d" % CLOUD_CONFIG,
|
|
Packit Service |
a04d08 |
"91_kernel_cmdline_url.cfg"),
|
|
Packit Service |
a04d08 |
network=not args.local)]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Cloud-init 'init' stage is broken up into the following sub-stages
|
|
Packit Service |
a04d08 |
# 1. Ensure that the init object fetches its config without errors
|
|
Packit Service |
a04d08 |
# 2. Setup logging/output redirections with resultant config (if any)
|
|
Packit Service |
a04d08 |
# 3. Initialize the cloud-init filesystem
|
|
Packit Service |
a04d08 |
# 4. Check if we can stop early by looking for various files
|
|
Packit Service |
a04d08 |
# 5. Fetch the datasource
|
|
Packit Service |
a04d08 |
# 6. Connect to the current instance location + update the cache
|
|
Packit Service |
a04d08 |
# 7. Consume the userdata (handlers get activated here)
|
|
Packit Service |
a04d08 |
# 8. Construct the modules object
|
|
Packit Service |
a04d08 |
# 9. Adjust any subsequent logging/output redirections using the modules
|
|
Packit Service |
a04d08 |
# objects config as it may be different from init object
|
|
Packit Service |
a04d08 |
# 10. Run the modules for the 'init' stage
|
|
Packit Service |
a04d08 |
# 11. Done!
|
|
Packit Service |
a04d08 |
if not args.local:
|
|
Packit Service |
a04d08 |
w_msg = welcome_format(name)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
w_msg = welcome_format("%s-local" % (name))
|
|
Packit Service |
a04d08 |
init = stages.Init(ds_deps=deps, reporter=args.reporter)
|
|
Packit Service |
a04d08 |
# Stage 1
|
|
Packit Service |
a04d08 |
init.read_cfg(extract_fns(args))
|
|
Packit Service |
a04d08 |
# Stage 2
|
|
Packit Service |
a04d08 |
outfmt = None
|
|
Packit Service |
a04d08 |
errfmt = None
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
early_logs.append((logging.DEBUG, "Closing stdin."))
|
|
Packit Service |
a04d08 |
util.close_stdin()
|
|
Packit Service |
a04d08 |
(outfmt, errfmt) = util.fixup_output(init.cfg, name)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
msg = "Failed to setup output redirection!"
|
|
Packit Service |
a04d08 |
util.logexc(LOG, msg)
|
|
Packit Service |
a04d08 |
print_exc(msg)
|
|
Packit Service |
a04d08 |
early_logs.append((logging.WARN, msg))
|
|
Packit Service |
a04d08 |
if args.debug:
|
|
Packit Service |
a04d08 |
# Reset so that all the debug handlers are closed out
|
|
Packit Service |
a04d08 |
LOG.debug(("Logging being reset, this logger may no"
|
|
Packit Service |
a04d08 |
" longer be active shortly"))
|
|
Packit Service |
a04d08 |
logging.resetLogging()
|
|
Packit Service |
a04d08 |
logging.setupLogging(init.cfg)
|
|
Packit Service |
a04d08 |
apply_reporting_cfg(init.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Any log usage prior to setupLogging above did not have local user log
|
|
Packit Service |
a04d08 |
# config applied. We send the welcome message now, as stderr/out have
|
|
Packit Service |
a04d08 |
# been redirected and log now configured.
|
|
Packit Service |
a04d08 |
welcome(name, msg=w_msg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# re-play early log messages before logging was setup
|
|
Packit Service |
a04d08 |
for lvl, msg in early_logs:
|
|
Packit Service |
a04d08 |
LOG.log(lvl, msg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 3
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
init.initialize()
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed to initialize, likely bad things to come!")
|
|
Packit Service |
a04d08 |
# Stage 4
|
|
Packit Service |
a04d08 |
path_helper = init.paths
|
|
Packit Service |
a04d08 |
mode = sources.DSMODE_LOCAL if args.local else sources.DSMODE_NETWORK
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_NETWORK:
|
|
Packit Service |
a04d08 |
existing = "trust"
|
|
Packit Service |
a04d08 |
sys.stderr.write("%s\n" % (netinfo.debug_info()))
|
|
Packit Service |
a04d08 |
LOG.debug(("Checking to see if files that we need already"
|
|
Packit Service |
a04d08 |
" exist from a previous run that would allow us"
|
|
Packit Service |
a04d08 |
" to stop early."))
|
|
Packit Service |
a04d08 |
# no-net is written by upstart cloud-init-nonet when network failed
|
|
Packit Service |
a04d08 |
# to come up
|
|
Packit Service |
a04d08 |
stop_files = [
|
|
Packit Service |
a04d08 |
os.path.join(path_helper.get_cpath("data"), "no-net"),
|
|
Packit Service |
a04d08 |
]
|
|
Packit Service |
a04d08 |
existing_files = []
|
|
Packit Service |
a04d08 |
for fn in stop_files:
|
|
Packit Service |
a04d08 |
if os.path.isfile(fn):
|
|
Packit Service |
a04d08 |
existing_files.append(fn)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if existing_files:
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] Exiting. stop file %s existed",
|
|
Packit Service |
a04d08 |
mode, existing_files)
|
|
Packit Service |
a04d08 |
return (None, [])
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("Execution continuing, no previous run detected that"
|
|
Packit Service |
a04d08 |
" would allow us to stop early.")
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
existing = "check"
|
|
Packit Service |
a04d08 |
mcfg = util.get_cfg_option_bool(init.cfg, 'manual_cache_clean', False)
|
|
Packit Service |
a04d08 |
if mcfg:
|
|
Packit Service |
a04d08 |
LOG.debug("manual cache clean set from config")
|
|
Packit Service |
a04d08 |
existing = "trust"
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
mfile = path_helper.get_ipath_cur("manual_clean_marker")
|
|
Packit Service |
a04d08 |
if os.path.exists(mfile):
|
|
Packit Service |
a04d08 |
LOG.debug("manual cache clean found from marker: %s", mfile)
|
|
Packit Service |
a04d08 |
existing = "trust"
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
init.purge_cache()
|
|
Packit Service |
a04d08 |
# Delete the no-net file as well
|
|
Packit Service |
a04d08 |
util.del_file(os.path.join(path_helper.get_cpath("data"), "no-net"))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 5
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
init.fetch(existing=existing)
|
|
Packit Service |
a04d08 |
# if in network mode, and the datasource is local
|
|
Packit Service |
a04d08 |
# then work was done at that stage.
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_NETWORK and init.datasource.dsmode != mode:
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] Exiting. datasource %s in local mode",
|
|
Packit Service |
a04d08 |
mode, init.datasource)
|
|
Packit Service |
a04d08 |
return (None, [])
|
|
Packit Service |
a04d08 |
except sources.DataSourceNotFoundException:
|
|
Packit Service |
a04d08 |
# In the case of 'cloud-init init' without '--local' it is a bit
|
|
Packit Service |
a04d08 |
# more likely that the user would consider it failure if nothing was
|
|
Packit Service |
a04d08 |
# found. When using upstart it will also mentions job failure
|
|
Packit Service |
a04d08 |
# in console log if exit code is != 0.
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_LOCAL:
|
|
Packit Service |
a04d08 |
LOG.debug("No local datasource found")
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, ("No instance datasource found!"
|
|
Packit Service |
a04d08 |
" Likely bad things to come!"))
|
|
Packit Service |
a04d08 |
if not args.force:
|
|
Packit Service |
a04d08 |
init.apply_network_config(bring_up=not args.local)
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] Exiting without datasource", mode)
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_LOCAL:
|
|
Packit Service |
a04d08 |
return (None, [])
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
return (None, ["No instance datasource found."])
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] barreling on in force mode without datasource",
|
|
Packit Service |
a04d08 |
mode)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
_maybe_persist_instance_data(init)
|
|
Packit Service |
a04d08 |
# Stage 6
|
|
Packit Service |
a04d08 |
iid = init.instancify()
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] %s will now be targeting instance id: %s. new=%s",
|
|
Packit Service |
a04d08 |
mode, name, iid, init.is_new_instance())
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_LOCAL:
|
|
Packit Service |
a04d08 |
# Before network comes up, set any configured hostname to allow
|
|
Packit Service |
a04d08 |
# dhcp clients to advertize this hostname to any DDNS services
|
|
Packit Service |
a04d08 |
# LP: #1746455.
|
|
Packit Service |
a04d08 |
_maybe_set_hostname(init, stage='local', retry_stage='network')
|
|
Packit Service |
a04d08 |
init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if mode == sources.DSMODE_LOCAL:
|
|
Packit Service |
a04d08 |
if init.datasource.dsmode != mode:
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] Exiting. datasource %s not in local mode.",
|
|
Packit Service |
a04d08 |
mode, init.datasource)
|
|
Packit Service |
a04d08 |
return (init.datasource, [])
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("[%s] %s is in local mode, will apply init modules now.",
|
|
Packit Service |
a04d08 |
mode, init.datasource)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Give the datasource a chance to use network resources.
|
|
Packit Service |
a04d08 |
# This is used on Azure to communicate with the fabric over network.
|
|
Packit Service |
a04d08 |
init.setup_datasource()
|
|
Packit Service |
a04d08 |
# update fully realizes user-data (pulling in #include if necessary)
|
|
Packit Service |
a04d08 |
init.update()
|
|
Packit Service |
a04d08 |
_maybe_set_hostname(init, stage='init-net', retry_stage='modules:config')
|
|
Packit Service |
a04d08 |
# Stage 7
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
# Attempt to consume the data per instance.
|
|
Packit Service |
a04d08 |
# This may run user-data handlers and/or perform
|
|
Packit Service |
a04d08 |
# url downloads and such as needed.
|
|
Packit Service |
a04d08 |
(ran, _results) = init.cloudify().run('consume_data',
|
|
Packit Service |
a04d08 |
init.consume_data,
|
|
Packit Service |
a04d08 |
args=[PER_INSTANCE],
|
|
Packit Service |
a04d08 |
freq=PER_INSTANCE)
|
|
Packit Service |
a04d08 |
if not ran:
|
|
Packit Service |
a04d08 |
# Just consume anything that is set to run per-always
|
|
Packit Service |
a04d08 |
# if nothing ran in the per-instance code
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# See: https://bugs.launchpad.net/bugs/819507 for a little
|
|
Packit Service |
a04d08 |
# reason behind this...
|
|
Packit Service |
a04d08 |
init.consume_data(PER_ALWAYS)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Consuming user data failed!")
|
|
Packit Service |
a04d08 |
return (init.datasource, ["Consuming user data failed!"])
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
apply_reporting_cfg(init.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 8 - re-read and apply relevant cloud-config to include user-data
|
|
Packit Service |
a04d08 |
mods = stages.Modules(init, extract_fns(args), reporter=args.reporter)
|
|
Packit Service |
a04d08 |
# Stage 9
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
outfmt_orig = outfmt
|
|
Packit Service |
a04d08 |
errfmt_orig = errfmt
|
|
Packit Service |
a04d08 |
(outfmt, errfmt) = util.get_output_cfg(mods.cfg, name)
|
|
Packit Service |
a04d08 |
if outfmt_orig != outfmt or errfmt_orig != errfmt:
|
|
Packit Service |
a04d08 |
LOG.warning("Stdout, stderr changing to (%s, %s)",
|
|
Packit Service |
a04d08 |
outfmt, errfmt)
|
|
Packit Service |
a04d08 |
(outfmt, errfmt) = util.fixup_output(mods.cfg, name)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed to re-adjust output redirection!")
|
|
Packit Service |
a04d08 |
logging.setupLogging(mods.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# give the activated datasource a chance to adjust
|
|
Packit Service |
a04d08 |
init.activate_datasource()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
di_report_warn(datasource=init.datasource, cfg=init.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 10
|
|
Packit Service |
a04d08 |
return (init.datasource, run_module_section(mods, name, name))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def di_report_warn(datasource, cfg):
|
|
Packit Service |
a04d08 |
if 'di_report' not in cfg:
|
|
Packit Service |
a04d08 |
LOG.debug("no di_report found in config.")
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
dicfg = cfg['di_report']
|
|
Packit Service |
a04d08 |
if dicfg is None:
|
|
Packit Service |
a04d08 |
# ds-identify may write 'di_report:\n #comment\n'
|
|
Packit Service |
a04d08 |
# which reads as {'di_report': None}
|
|
Packit Service |
a04d08 |
LOG.debug("di_report was None.")
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if not isinstance(dicfg, dict):
|
|
Packit Service |
a04d08 |
LOG.warning("di_report config not a dictionary: %s", dicfg)
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
dslist = dicfg.get('datasource_list')
|
|
Packit Service |
a04d08 |
if dslist is None:
|
|
Packit Service |
a04d08 |
LOG.warning("no 'datasource_list' found in di_report.")
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
elif not isinstance(dslist, list):
|
|
Packit Service |
a04d08 |
LOG.warning("di_report/datasource_list not a list: %s", dslist)
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# ds.__module__ is like cloudinit.sources.DataSourceName
|
|
Packit Service |
a04d08 |
# where Name is the thing that shows up in datasource_list.
|
|
Packit Service |
a04d08 |
modname = datasource.__module__.rpartition(".")[2]
|
|
Packit Service |
a04d08 |
if modname.startswith(sources.DS_PREFIX):
|
|
Packit Service |
a04d08 |
modname = modname[len(sources.DS_PREFIX):]
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.warning("Datasource '%s' came from unexpected module '%s'.",
|
|
Packit Service |
a04d08 |
datasource, modname)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if modname in dslist:
|
|
Packit Service |
a04d08 |
LOG.debug("used datasource '%s' from '%s' was in di_report's list: %s",
|
|
Packit Service |
a04d08 |
datasource, modname, dslist)
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
warnings.show_warning('dsid_missing_source', cfg,
|
|
Packit Service |
a04d08 |
source=modname, dslist=str(dslist))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def main_modules(action_name, args):
|
|
Packit Service |
a04d08 |
name = args.mode
|
|
Packit Service |
a04d08 |
# Cloud-init 'modules' stages are broken up into the following sub-stages
|
|
Packit Service |
a04d08 |
# 1. Ensure that the init object fetches its config without errors
|
|
Packit Service |
a04d08 |
# 2. Get the datasource from the init object, if it does
|
|
Packit Service |
a04d08 |
# not exist then that means the main_init stage never
|
|
Packit Service |
a04d08 |
# worked, and thus this stage can not run.
|
|
Packit Service |
a04d08 |
# 3. Construct the modules object
|
|
Packit Service |
a04d08 |
# 4. Adjust any subsequent logging/output redirections using
|
|
Packit Service |
a04d08 |
# the modules objects configuration
|
|
Packit Service |
a04d08 |
# 5. Run the modules for the given stage name
|
|
Packit Service |
a04d08 |
# 6. Done!
|
|
Packit Service |
a04d08 |
w_msg = welcome_format("%s:%s" % (action_name, name))
|
|
Packit Service |
a04d08 |
init = stages.Init(ds_deps=[], reporter=args.reporter)
|
|
Packit Service |
a04d08 |
# Stage 1
|
|
Packit Service |
a04d08 |
init.read_cfg(extract_fns(args))
|
|
Packit Service |
a04d08 |
# Stage 2
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
init.fetch(existing="trust")
|
|
Packit Service |
a04d08 |
except sources.DataSourceNotFoundException:
|
|
Packit Service |
a04d08 |
# There was no datasource found, theres nothing to do
|
|
Packit Service |
a04d08 |
msg = ('Can not apply stage %s, no datasource found! Likely bad '
|
|
Packit Service |
a04d08 |
'things to come!' % name)
|
|
Packit Service |
a04d08 |
util.logexc(LOG, msg)
|
|
Packit Service |
a04d08 |
print_exc(msg)
|
|
Packit Service |
a04d08 |
if not args.force:
|
|
Packit Service |
a04d08 |
return [(msg)]
|
|
Packit Service |
a04d08 |
_maybe_persist_instance_data(init)
|
|
Packit Service |
a04d08 |
# Stage 3
|
|
Packit Service |
a04d08 |
mods = stages.Modules(init, extract_fns(args), reporter=args.reporter)
|
|
Packit Service |
a04d08 |
# Stage 4
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
LOG.debug("Closing stdin")
|
|
Packit Service |
a04d08 |
util.close_stdin()
|
|
Packit Service |
a04d08 |
util.fixup_output(mods.cfg, name)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed to setup output redirection!")
|
|
Packit Service |
a04d08 |
if args.debug:
|
|
Packit Service |
a04d08 |
# Reset so that all the debug handlers are closed out
|
|
Packit Service |
a04d08 |
LOG.debug(("Logging being reset, this logger may no"
|
|
Packit Service |
a04d08 |
" longer be active shortly"))
|
|
Packit Service |
a04d08 |
logging.resetLogging()
|
|
Packit Service |
a04d08 |
logging.setupLogging(mods.cfg)
|
|
Packit Service |
a04d08 |
apply_reporting_cfg(init.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# now that logging is setup and stdout redirected, send welcome
|
|
Packit Service |
a04d08 |
welcome(name, msg=w_msg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 5
|
|
Packit Service |
a04d08 |
return run_module_section(mods, name, name)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def main_single(name, args):
|
|
Packit Service |
a04d08 |
# Cloud-init single stage is broken up into the following sub-stages
|
|
Packit Service |
a04d08 |
# 1. Ensure that the init object fetches its config without errors
|
|
Packit Service |
a04d08 |
# 2. Attempt to fetch the datasource (warn if it doesn't work)
|
|
Packit Service |
a04d08 |
# 3. Construct the modules object
|
|
Packit Service |
a04d08 |
# 4. Adjust any subsequent logging/output redirections using
|
|
Packit Service |
a04d08 |
# the modules objects configuration
|
|
Packit Service |
a04d08 |
# 5. Run the single module
|
|
Packit Service |
a04d08 |
# 6. Done!
|
|
Packit Service |
a04d08 |
mod_name = args.name
|
|
Packit Service |
a04d08 |
w_msg = welcome_format(name)
|
|
Packit Service |
a04d08 |
init = stages.Init(ds_deps=[], reporter=args.reporter)
|
|
Packit Service |
a04d08 |
# Stage 1
|
|
Packit Service |
a04d08 |
init.read_cfg(extract_fns(args))
|
|
Packit Service |
a04d08 |
# Stage 2
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
init.fetch(existing="trust")
|
|
Packit Service |
a04d08 |
except sources.DataSourceNotFoundException:
|
|
Packit Service |
a04d08 |
# There was no datasource found,
|
|
Packit Service |
a04d08 |
# that might be bad (or ok) depending on
|
|
Packit Service |
a04d08 |
# the module being ran (so continue on)
|
|
Packit Service |
a04d08 |
util.logexc(LOG, ("Failed to fetch your datasource,"
|
|
Packit Service |
a04d08 |
" likely bad things to come!"))
|
|
Packit Service |
a04d08 |
print_exc(("Failed to fetch your datasource,"
|
|
Packit Service |
a04d08 |
" likely bad things to come!"))
|
|
Packit Service |
a04d08 |
if not args.force:
|
|
Packit Service |
a04d08 |
return 1
|
|
Packit Service |
a04d08 |
_maybe_persist_instance_data(init)
|
|
Packit Service |
a04d08 |
# Stage 3
|
|
Packit Service |
a04d08 |
mods = stages.Modules(init, extract_fns(args), reporter=args.reporter)
|
|
Packit Service |
a04d08 |
mod_args = args.module_args
|
|
Packit Service |
a04d08 |
if mod_args:
|
|
Packit Service |
a04d08 |
LOG.debug("Using passed in arguments %s", mod_args)
|
|
Packit Service |
a04d08 |
mod_freq = args.frequency
|
|
Packit Service |
a04d08 |
if mod_freq:
|
|
Packit Service |
a04d08 |
LOG.debug("Using passed in frequency %s", mod_freq)
|
|
Packit Service |
a04d08 |
mod_freq = FREQ_SHORT_NAMES.get(mod_freq)
|
|
Packit Service |
a04d08 |
# Stage 4
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
LOG.debug("Closing stdin")
|
|
Packit Service |
a04d08 |
util.close_stdin()
|
|
Packit Service |
a04d08 |
util.fixup_output(mods.cfg, None)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed to setup output redirection!")
|
|
Packit Service |
a04d08 |
if args.debug:
|
|
Packit Service |
a04d08 |
# Reset so that all the debug handlers are closed out
|
|
Packit Service |
a04d08 |
LOG.debug(("Logging being reset, this logger may no"
|
|
Packit Service |
a04d08 |
" longer be active shortly"))
|
|
Packit Service |
a04d08 |
logging.resetLogging()
|
|
Packit Service |
a04d08 |
logging.setupLogging(mods.cfg)
|
|
Packit Service |
a04d08 |
apply_reporting_cfg(init.cfg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# now that logging is setup and stdout redirected, send welcome
|
|
Packit Service |
a04d08 |
welcome(name, msg=w_msg)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Stage 5
|
|
Packit Service |
a04d08 |
(which_ran, failures) = mods.run_single(mod_name,
|
|
Packit Service |
a04d08 |
mod_args,
|
|
Packit Service |
a04d08 |
mod_freq)
|
|
Packit Service |
a04d08 |
if failures:
|
|
Packit Service |
a04d08 |
LOG.warning("Ran %s but it failed!", mod_name)
|
|
Packit Service |
a04d08 |
return 1
|
|
Packit Service |
a04d08 |
elif not which_ran:
|
|
Packit Service |
a04d08 |
LOG.warning("Did not run %s, does it exist?", mod_name)
|
|
Packit Service |
a04d08 |
return 1
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
# Guess it worked
|
|
Packit Service |
a04d08 |
return 0
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def status_wrapper(name, args, data_d=None, link_d=None):
|
|
Packit Service |
a04d08 |
if data_d is None:
|
|
Packit Service |
a04d08 |
data_d = os.path.normpath("/var/lib/cloud/data")
|
|
Packit Service |
a04d08 |
if link_d is None:
|
|
Packit Service |
a04d08 |
link_d = os.path.normpath("/run/cloud-init")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
status_path = os.path.join(data_d, "status.json")
|
|
Packit Service |
a04d08 |
status_link = os.path.join(link_d, "status.json")
|
|
Packit Service |
a04d08 |
result_path = os.path.join(data_d, "result.json")
|
|
Packit Service |
a04d08 |
result_link = os.path.join(link_d, "result.json")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
util.ensure_dirs((data_d, link_d,))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
(_name, functor) = args.action
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if name == "init":
|
|
Packit Service |
a04d08 |
if args.local:
|
|
Packit Service |
a04d08 |
mode = "init-local"
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
mode = "init"
|
|
Packit Service |
a04d08 |
elif name == "modules":
|
|
Packit Service |
a04d08 |
mode = "modules-%s" % args.mode
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
raise ValueError("unknown name: %s" % name)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
modes = ('init', 'init-local', 'modules-init', 'modules-config',
|
|
Packit Service |
a04d08 |
'modules-final')
|
|
Packit Service |
a04d08 |
if mode not in modes:
|
|
Packit Service |
a04d08 |
raise ValueError(
|
|
Packit Service |
a04d08 |
"Invalid cloud init mode specified '{0}'".format(mode))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
status = None
|
|
Packit Service |
a04d08 |
if mode == 'init-local':
|
|
Packit Service |
a04d08 |
for f in (status_link, result_link, status_path, result_path):
|
|
Packit Service |
a04d08 |
util.del_file(f)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
status = json.loads(util.load_file(status_path))
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
nullstatus = {
|
|
Packit Service |
a04d08 |
'errors': [],
|
|
Packit Service |
a04d08 |
'start': None,
|
|
Packit Service |
a04d08 |
'finished': None,
|
|
Packit Service |
a04d08 |
}
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if status is None:
|
|
Packit Service |
a04d08 |
status = {'v1': {}}
|
|
Packit Service |
a04d08 |
status['v1']['datasource'] = None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
for m in modes:
|
|
Packit Service |
a04d08 |
if m not in status['v1']:
|
|
Packit Service |
a04d08 |
status['v1'][m] = nullstatus.copy()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
v1 = status['v1']
|
|
Packit Service |
a04d08 |
v1['stage'] = mode
|
|
Packit Service |
a04d08 |
v1[mode]['start'] = time.time()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
atomic_helper.write_json(status_path, status)
|
|
Packit Service |
a04d08 |
util.sym_link(os.path.relpath(status_path, link_d), status_link,
|
|
Packit Service |
a04d08 |
force=True)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
ret = functor(name, args)
|
|
Packit Service |
a04d08 |
if mode in ('init', 'init-local'):
|
|
Packit Service |
a04d08 |
(datasource, errors) = ret
|
|
Packit Service |
a04d08 |
if datasource is not None:
|
|
Packit Service |
a04d08 |
v1['datasource'] = str(datasource)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
errors = ret
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
v1[mode]['errors'] = [str(e) for e in errors]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
except Exception as e:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "failed stage %s", mode)
|
|
Packit Service |
a04d08 |
print_exc("failed run of stage %s" % mode)
|
|
Packit Service |
a04d08 |
v1[mode]['errors'] = [str(e)]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
v1[mode]['finished'] = time.time()
|
|
Packit Service |
a04d08 |
v1['stage'] = None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
atomic_helper.write_json(status_path, status)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if mode == "modules-final":
|
|
Packit Service |
a04d08 |
# write the 'finished' file
|
|
Packit Service |
a04d08 |
errors = []
|
|
Packit Service |
a04d08 |
for m in modes:
|
|
Packit Service |
a04d08 |
if v1[m]['errors']:
|
|
Packit Service |
a04d08 |
errors.extend(v1[m].get('errors', []))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
atomic_helper.write_json(
|
|
Packit Service |
a04d08 |
result_path, {'v1': {'datasource': v1['datasource'],
|
|
Packit Service |
a04d08 |
'errors': errors}})
|
|
Packit Service |
a04d08 |
util.sym_link(os.path.relpath(result_path, link_d), result_link,
|
|
Packit Service |
a04d08 |
force=True)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
return len(v1[mode]['errors'])
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _maybe_persist_instance_data(init):
|
|
Packit Service |
a04d08 |
"""Write instance-data.json file if absent and datasource is restored."""
|
|
Packit Service |
a04d08 |
if init.ds_restored:
|
|
Packit Service |
a04d08 |
instance_data_file = os.path.join(
|
|
Packit Service |
a04d08 |
init.paths.run_dir, sources.INSTANCE_JSON_FILE)
|
|
Packit Service |
a04d08 |
if not os.path.exists(instance_data_file):
|
|
Packit Service |
a04d08 |
init.datasource.persist_instance_data()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _maybe_set_hostname(init, stage, retry_stage):
|
|
Packit Service |
a04d08 |
"""Call set-hostname if metadata, vendordata or userdata provides it.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
@param stage: String representing current stage in which we are running.
|
|
Packit Service |
a04d08 |
@param retry_stage: String represented logs upon error setting hostname.
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
cloud = init.cloudify()
|
|
Packit Service |
a04d08 |
(hostname, _fqdn) = util.get_hostname_fqdn(
|
|
Packit Service |
a04d08 |
init.cfg, cloud, metadata_only=True)
|
|
Packit Service |
a04d08 |
if hostname: # meta-data or user-data hostname content
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
cc_set_hostname.handle('set-hostname', init.cfg, cloud, LOG, None)
|
|
Packit Service |
a04d08 |
except cc_set_hostname.SetHostnameError as e:
|
|
Packit Service |
a04d08 |
LOG.debug(
|
|
Packit Service |
a04d08 |
'Failed setting hostname in %s stage. Will'
|
|
Packit Service |
a04d08 |
' retry in %s stage. Error: %s.', stage, retry_stage, str(e))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def main_features(name, args):
|
|
Packit Service |
a04d08 |
sys.stdout.write('\n'.join(sorted(version.FEATURES)) + '\n')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def main(sysv_args=None):
|
|
Packit Service |
a04d08 |
if not sysv_args:
|
|
Packit Service |
a04d08 |
sysv_args = sys.argv
|
|
Packit Service |
a04d08 |
parser = argparse.ArgumentParser(prog=sysv_args[0])
|
|
Packit Service |
a04d08 |
sysv_args = sysv_args[1:]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Top level args
|
|
Packit Service |
a04d08 |
parser.add_argument('--version', '-v', action='version',
|
|
Packit Service |
a04d08 |
version='%(prog)s ' + (version.version_string()))
|
|
Packit Service |
a04d08 |
parser.add_argument('--file', '-f', action='append',
|
|
Packit Service |
a04d08 |
dest='files',
|
|
Packit Service |
a04d08 |
help=('additional yaml configuration'
|
|
Packit Service |
a04d08 |
' files to use'),
|
|
Packit Service |
a04d08 |
type=argparse.FileType('rb'))
|
|
Packit Service |
a04d08 |
parser.add_argument('--debug', '-d', action='store_true',
|
|
Packit Service |
a04d08 |
help=('show additional pre-action'
|
|
Packit Service |
a04d08 |
' logging (default: %(default)s)'),
|
|
Packit Service |
a04d08 |
default=False)
|
|
Packit Service |
a04d08 |
parser.add_argument('--force', action='store_true',
|
|
Packit Service |
a04d08 |
help=('force running even if no datasource is'
|
|
Packit Service |
a04d08 |
' found (use at your own risk)'),
|
|
Packit Service |
a04d08 |
dest='force',
|
|
Packit Service |
a04d08 |
default=False)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser.set_defaults(reporter=None)
|
|
Packit Service |
a04d08 |
subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand')
|
|
Packit Service |
a04d08 |
subparsers.required = True
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Each action and its sub-options (if any)
|
|
Packit Service |
a04d08 |
parser_init = subparsers.add_parser('init',
|
|
Packit Service |
a04d08 |
help=('initializes cloud-init and'
|
|
Packit Service |
a04d08 |
' performs initial modules'))
|
|
Packit Service |
a04d08 |
parser_init.add_argument("--local", '-l', action='store_true',
|
|
Packit Service |
a04d08 |
help="start in local mode (default: %(default)s)",
|
|
Packit Service |
a04d08 |
default=False)
|
|
Packit Service |
a04d08 |
# This is used so that we can know which action is selected +
|
|
Packit Service |
a04d08 |
# the functor to use to run this subcommand
|
|
Packit Service |
a04d08 |
parser_init.set_defaults(action=('init', main_init))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# These settings are used for the 'config' and 'final' stages
|
|
Packit Service |
a04d08 |
parser_mod = subparsers.add_parser('modules',
|
|
Packit Service |
a04d08 |
help=('activates modules using '
|
|
Packit Service |
a04d08 |
'a given configuration key'))
|
|
Packit Service |
a04d08 |
parser_mod.add_argument("--mode", '-m', action='store',
|
|
Packit Service |
a04d08 |
help=("module configuration name "
|
|
Packit Service |
a04d08 |
"to use (default: %(default)s)"),
|
|
Packit Service |
a04d08 |
default='config',
|
|
Packit Service |
a04d08 |
choices=('init', 'config', 'final'))
|
|
Packit Service |
a04d08 |
parser_mod.set_defaults(action=('modules', main_modules))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# This subcommand allows you to run a single module
|
|
Packit Service |
a04d08 |
parser_single = subparsers.add_parser('single',
|
|
Packit Service |
a04d08 |
help=('run a single module '))
|
|
Packit Service |
a04d08 |
parser_single.add_argument("--name", '-n', action="store",
|
|
Packit Service |
a04d08 |
help="module name to run",
|
|
Packit Service |
a04d08 |
required=True)
|
|
Packit Service |
a04d08 |
parser_single.add_argument("--frequency", action="store",
|
|
Packit Service |
a04d08 |
help=("frequency of the module"),
|
|
Packit Service |
a04d08 |
required=False,
|
|
Packit Service |
a04d08 |
choices=list(FREQ_SHORT_NAMES.keys()))
|
|
Packit Service |
a04d08 |
parser_single.add_argument("--report", action="store_true",
|
|
Packit Service |
a04d08 |
help="enable reporting",
|
|
Packit Service |
a04d08 |
required=False)
|
|
Packit Service |
a04d08 |
parser_single.add_argument("module_args", nargs="*",
|
|
Packit Service |
a04d08 |
metavar='argument',
|
|
Packit Service |
a04d08 |
help=('any additional arguments to'
|
|
Packit Service |
a04d08 |
' pass to this module'))
|
|
Packit Service |
a04d08 |
parser_single.set_defaults(action=('single', main_single))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_query = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'query',
|
|
Packit Service |
a04d08 |
help='Query standardized instance metadata from the command line.')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_dhclient = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
dhclient_hook.NAME, help=dhclient_hook.__doc__)
|
|
Packit Service |
a04d08 |
dhclient_hook.get_parser(parser_dhclient)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_features = subparsers.add_parser('features',
|
|
Packit Service |
a04d08 |
help=('list defined features'))
|
|
Packit Service |
a04d08 |
parser_features.set_defaults(action=('features', main_features))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_analyze = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'analyze', help='Devel tool: Analyze cloud-init logs and data')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_devel = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'devel', help='Run development tools')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_collect_logs = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'collect-logs', help='Collect and tar all cloud-init debug info')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_clean = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'clean', help='Remove logs and artifacts so cloud-init can re-run.')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
parser_status = subparsers.add_parser(
|
|
Packit Service |
a04d08 |
'status', help='Report cloud-init status or wait on completion.')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if sysv_args:
|
|
Packit Service |
a04d08 |
# Only load subparsers if subcommand is specified to avoid load cost
|
|
Packit Service |
a04d08 |
if sysv_args[0] == 'analyze':
|
|
Packit Service |
a04d08 |
from cloudinit.analyze.__main__ import get_parser as analyze_parser
|
|
Packit Service |
a04d08 |
# Construct analyze subcommand parser
|
|
Packit Service |
a04d08 |
analyze_parser(parser_analyze)
|
|
Packit Service |
a04d08 |
elif sysv_args[0] == 'devel':
|
|
Packit Service |
a04d08 |
from cloudinit.cmd.devel.parser import get_parser as devel_parser
|
|
Packit Service |
a04d08 |
# Construct devel subcommand parser
|
|
Packit Service |
a04d08 |
devel_parser(parser_devel)
|
|
Packit Service |
a04d08 |
elif sysv_args[0] == 'collect-logs':
|
|
Packit Service |
a04d08 |
from cloudinit.cmd.devel.logs import (
|
|
Packit Service |
a04d08 |
get_parser as logs_parser, handle_collect_logs_args)
|
|
Packit Service |
a04d08 |
logs_parser(parser_collect_logs)
|
|
Packit Service |
a04d08 |
parser_collect_logs.set_defaults(
|
|
Packit Service |
a04d08 |
action=('collect-logs', handle_collect_logs_args))
|
|
Packit Service |
a04d08 |
elif sysv_args[0] == 'clean':
|
|
Packit Service |
a04d08 |
from cloudinit.cmd.clean import (
|
|
Packit Service |
a04d08 |
get_parser as clean_parser, handle_clean_args)
|
|
Packit Service |
a04d08 |
clean_parser(parser_clean)
|
|
Packit Service |
a04d08 |
parser_clean.set_defaults(
|
|
Packit Service |
a04d08 |
action=('clean', handle_clean_args))
|
|
Packit Service |
a04d08 |
elif sysv_args[0] == 'query':
|
|
Packit Service |
a04d08 |
from cloudinit.cmd.query import (
|
|
Packit Service |
a04d08 |
get_parser as query_parser, handle_args as handle_query_args)
|
|
Packit Service |
a04d08 |
query_parser(parser_query)
|
|
Packit Service |
a04d08 |
parser_query.set_defaults(
|
|
Packit Service |
a04d08 |
action=('render', handle_query_args))
|
|
Packit Service |
a04d08 |
elif sysv_args[0] == 'status':
|
|
Packit Service |
a04d08 |
from cloudinit.cmd.status import (
|
|
Packit Service |
a04d08 |
get_parser as status_parser, handle_status_args)
|
|
Packit Service |
a04d08 |
status_parser(parser_status)
|
|
Packit Service |
a04d08 |
parser_status.set_defaults(
|
|
Packit Service |
a04d08 |
action=('status', handle_status_args))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
args = parser.parse_args(args=sysv_args)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Subparsers.required = True and each subparser sets action=(name, functor)
|
|
Packit Service |
a04d08 |
(name, functor) = args.action
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Setup basic logging to start (until reinitialized)
|
|
Packit Service |
a04d08 |
# iff in debug mode.
|
|
Packit Service |
a04d08 |
if args.debug:
|
|
Packit Service |
a04d08 |
logging.setupBasicLogging()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Setup signal handlers before running
|
|
Packit Service |
a04d08 |
signal_handler.attach_handlers()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if name in ("modules", "init"):
|
|
Packit Service |
a04d08 |
functor = status_wrapper
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
rname = None
|
|
Packit Service |
a04d08 |
report_on = True
|
|
Packit Service |
a04d08 |
if name == "init":
|
|
Packit Service |
a04d08 |
if args.local:
|
|
Packit Service |
a04d08 |
rname, rdesc = ("init-local", "searching for local datasources")
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
rname, rdesc = ("init-network",
|
|
Packit Service |
a04d08 |
"searching for network datasources")
|
|
Packit Service |
a04d08 |
elif name == "modules":
|
|
Packit Service |
a04d08 |
rname, rdesc = ("modules-%s" % args.mode,
|
|
Packit Service |
a04d08 |
"running modules for %s" % args.mode)
|
|
Packit Service |
a04d08 |
elif name == "single":
|
|
Packit Service |
a04d08 |
rname, rdesc = ("single/%s" % args.name,
|
|
Packit Service |
a04d08 |
"running single module %s" % args.name)
|
|
Packit Service |
a04d08 |
report_on = args.report
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
rname = name
|
|
Packit Service |
a04d08 |
rdesc = "running 'cloud-init %s'" % name
|
|
Packit Service |
a04d08 |
report_on = False
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
args.reporter = events.ReportEventStack(
|
|
Packit Service |
a04d08 |
rname, rdesc, reporting_enabled=report_on)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
with args.reporter:
|
|
Packit Service |
a04d08 |
retval = util.log_time(
|
|
Packit Service |
a04d08 |
logfunc=LOG.debug, msg="cloud-init mode '%s'" % name,
|
|
Packit Service |
a04d08 |
get_uptime=True, func=functor, args=(name, args))
|
|
Packit Service |
a04d08 |
reporting.flush_events()
|
|
Packit Service |
a04d08 |
return retval
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if __name__ == '__main__':
|
|
Packit Service |
a04d08 |
if 'TZ' not in os.environ:
|
|
Packit Service |
a04d08 |
os.environ['TZ'] = ":/etc/localtime"
|
|
Packit Service |
a04d08 |
return_value = main(sys.argv)
|
|
Packit Service |
a04d08 |
if return_value:
|
|
Packit Service |
a04d08 |
sys.exit(return_value)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# vi: ts=4 expandtab
|