Merge pull request #345 from harlowja/master
Lots of goodies (see the commit log)
This commit is contained in:
commit
c7ab9b3ba2
@ -82,7 +82,7 @@ def run(args):
|
||||
|
||||
# Stash the dryrun value (if any)
|
||||
if 'dryrun' in args:
|
||||
env.set("ANVIL_DRYRUN", str(args['dryrun']))
|
||||
sh.set_dry_run(args['dryrun'])
|
||||
|
||||
# Ensure the anvil dirs are there if others are about to use it...
|
||||
ensure_anvil_dirs()
|
||||
|
@ -33,6 +33,10 @@ from anvil.utils import OrderedDict
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Include the general yaml during all interpolation
|
||||
# actions since it typically contains useful shared settings...
|
||||
BASE_YAML_INTERP = ('general', )
|
||||
|
||||
|
||||
class PhaseFunctors(object):
|
||||
def __init__(self, start, run, end):
|
||||
@ -74,7 +78,7 @@ class Action(object):
|
||||
already_gotten = set()
|
||||
for c in component_order:
|
||||
instance = instances[c]
|
||||
wanted_passwords = instance.get_option('wanted_passwords') or []
|
||||
wanted_passwords = instance.get_option('wanted_passwords')
|
||||
if not wanted_passwords:
|
||||
continue
|
||||
for (name, prompt) in wanted_passwords.items():
|
||||
@ -160,11 +164,18 @@ class Action(object):
|
||||
sibling_instances[action][name] = a_sibling
|
||||
return there_siblings
|
||||
|
||||
def _get_interpolated_names(self, name):
|
||||
# Return which sources that will be interpolated from
|
||||
# Note(harlowja): if one of the bases here pulls in
|
||||
# another yaml, it will be done automatically so this
|
||||
# list is more of the starting list and not the end list...
|
||||
return list(BASE_YAML_INTERP) + [name]
|
||||
|
||||
def _get_interpolated_options(self, name):
|
||||
interpolated_opts = {}
|
||||
for c in ['general', name]:
|
||||
interpolated_opts.update(self.interpolator.extract(c))
|
||||
return interpolated_opts
|
||||
opts = {}
|
||||
for c in self._get_interpolated_names(name):
|
||||
opts.update(self.interpolator.extract(c))
|
||||
return opts
|
||||
|
||||
def _construct_instances(self, persona):
|
||||
"""
|
||||
@ -240,6 +251,7 @@ class Action(object):
|
||||
utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
|
||||
|
||||
def _get_phase_filename(self, phase_name):
|
||||
# Do some canonicalization of the phase name so its in a semi-standard format...
|
||||
phase_name = phase_name.lower().strip()
|
||||
phase_name = phase_name.replace("-", '_')
|
||||
phase_name = phase_name.replace(" ", "_")
|
||||
@ -251,12 +263,23 @@ class Action(object):
|
||||
"""
|
||||
Run a given 'functor' across all of the components, in order.
|
||||
"""
|
||||
# All the results for each component end up in here
|
||||
# in the order in which they ran...
|
||||
component_results = OrderedDict()
|
||||
|
||||
# This phase recorder will be used to check if a given component
|
||||
# and action has ran in the past, if so that components action
|
||||
# will not be ran again. It will also be used to mark that a given
|
||||
# component has completed a phase (if that phase runs).
|
||||
if not phase_name:
|
||||
phase_recorder = phase.NullPhaseRecorder()
|
||||
else:
|
||||
phase_recorder = phase.PhaseRecorder(self._get_phase_filename(phase_name))
|
||||
|
||||
# These phase recorders will be used to undo other actions activities
|
||||
# ie, when an install completes you want to uninstall phase to be
|
||||
# removed from that actions phase file (and so on). This list will be
|
||||
# used to accomplish that.
|
||||
neg_phase_recs = []
|
||||
if inv_phase_names:
|
||||
for n in inv_phase_names:
|
||||
@ -266,7 +289,14 @@ class Action(object):
|
||||
neg_phase_recs.append(phase.PhaseRecorder(self._get_phase_filename(n)))
|
||||
|
||||
def change_activate(instance, on_off):
|
||||
# Activate/deactivate them and there siblings (if any)
|
||||
# Activate/deactivate a component instance and there siblings (if any)
|
||||
#
|
||||
# This is used when you say are looking at components
|
||||
# that have been activated before your component has been.
|
||||
#
|
||||
# Typically this is useful for checking if a previous component
|
||||
# has a shared dependency with your component and if so then there
|
||||
# is no need to reinstall said dependency...
|
||||
instance.activated = on_off
|
||||
for (_name, sibling_instance) in instance.siblings.items():
|
||||
sibling_instance.activated = on_off
|
||||
|
59
anvil/cfg.py
59
anvil/cfg.py
@ -139,6 +139,13 @@ class YamlInterpolator(object):
|
||||
self.included = {}
|
||||
self.interpolated = {}
|
||||
self.base = base
|
||||
self.auto_specials = {
|
||||
'ip': utils.get_host_ip,
|
||||
'user': sh.getuser,
|
||||
'group': sh.getgroupname,
|
||||
'home': sh.gethomedir,
|
||||
'hostname': sh.hostname,
|
||||
}
|
||||
|
||||
def _interpolate_iterable(self, what):
|
||||
if isinstance(what, (set)):
|
||||
@ -150,6 +157,8 @@ class YamlInterpolator(object):
|
||||
n_what = []
|
||||
for v in what:
|
||||
n_what.append(self._interpolate(v))
|
||||
if isinstance(what, (tuple)):
|
||||
n_what = tuple(n_what)
|
||||
return n_what
|
||||
|
||||
def _interpolate_dictionary(self, what):
|
||||
@ -174,6 +183,8 @@ class YamlInterpolator(object):
|
||||
n_what = []
|
||||
for v in what:
|
||||
n_what.append(self._do_include(v))
|
||||
if isinstance(what, (tuple)):
|
||||
n_what = tuple(n_what)
|
||||
return n_what
|
||||
|
||||
def _interpolate(self, value):
|
||||
@ -188,13 +199,16 @@ class YamlInterpolator(object):
|
||||
|
||||
def _interpolate_string(self, what):
|
||||
if not re.search(INTERP_PAT, what):
|
||||
# Leave it alone if the sub won't do
|
||||
# anything to begin with
|
||||
return what
|
||||
|
||||
def replacer(match):
|
||||
who = match.group(1).strip()
|
||||
key = match.group(2).strip()
|
||||
if self._process_special(who, key):
|
||||
return self._process_special(who, key)
|
||||
(is_special, special_value) = self._process_special(who, key)
|
||||
if is_special:
|
||||
return special_value
|
||||
if who not in self.interpolated:
|
||||
self.interpolated[who] = self.included[who]
|
||||
self.interpolated[who] = self._interpolate(self.included[who])
|
||||
@ -203,37 +217,42 @@ class YamlInterpolator(object):
|
||||
return re.sub(INTERP_PAT, replacer, what)
|
||||
|
||||
def _process_special(self, who, key):
|
||||
if key == 'ip' and who == 'auto':
|
||||
return utils.get_host_ip()
|
||||
if key == 'user' and who == 'auto':
|
||||
return sh.getuser()
|
||||
if who == 'auto':
|
||||
raise KeyError("Unknown auto key type %s" % (key))
|
||||
return None
|
||||
if who and who.lower() in ['auto']:
|
||||
if key not in self.auto_specials:
|
||||
raise KeyError("Unknown auto key %r" % (key))
|
||||
functor = self.auto_specials[key]
|
||||
return (True, functor())
|
||||
return (False, None)
|
||||
|
||||
def _include_string(self, what):
|
||||
if not re.search(INTERP_PAT, what):
|
||||
# Leave it alone if the sub won't do
|
||||
# anything to begin with
|
||||
return what
|
||||
|
||||
def replacer(match):
|
||||
who = match.group(1).strip()
|
||||
key = match.group(2).strip()
|
||||
if self._process_special(who, key):
|
||||
return self._process_special(who, key)
|
||||
(is_special, special_value) = self._process_special(who, key)
|
||||
if is_special:
|
||||
return special_value
|
||||
# Process there includes and then
|
||||
# fetch the value that should have been
|
||||
# populated
|
||||
self._process_includes(who)
|
||||
return str(self.included[who][key])
|
||||
|
||||
return re.sub(INTERP_PAT, replacer, what)
|
||||
|
||||
def _do_include(self, v):
|
||||
n_v = v
|
||||
if v and isinstance(v, (basestring, str)):
|
||||
n_v = self._include_string(v)
|
||||
elif isinstance(v, dict):
|
||||
n_v = self._include_dictionary(v)
|
||||
elif isinstance(v, (list, set, tuple)):
|
||||
n_v = self._include_iterable(v)
|
||||
return n_v
|
||||
def _do_include(self, value):
|
||||
new_value = value
|
||||
if value and isinstance(value, (basestring, str)):
|
||||
new_value = self._include_string(value)
|
||||
elif isinstance(value, (dict)):
|
||||
new_value = self._include_dictionary(value)
|
||||
elif isinstance(value, (list, set, tuple)):
|
||||
new_value = self._include_iterable(value)
|
||||
return new_value
|
||||
|
||||
def _process_includes(self, root):
|
||||
if root in self.included:
|
||||
|
@ -23,13 +23,15 @@ from anvil import type_utils as tu
|
||||
|
||||
COLORS = termcolor.COLORS.keys()
|
||||
|
||||
LOG_COLOR = True
|
||||
if 'LOG_COLOR' in env.get():
|
||||
LOG_COLOR = tu.make_bool(env.get_key('LOG_COLOR'))
|
||||
if not sys.stdout.isatty():
|
||||
LOG_COLOR = False
|
||||
|
||||
|
||||
def color_enabled():
|
||||
if 'LOG_COLOR' in env.get() and not tu.make_bool(env.get_key('LOG_COLOR')):
|
||||
return False
|
||||
if not sys.stdout.isatty():
|
||||
return False
|
||||
return True
|
||||
return LOG_COLOR
|
||||
|
||||
|
||||
def quote(data, quote_color='green', **kargs):
|
||||
|
@ -856,6 +856,10 @@ class PythonTestingComponent(component.Component):
|
||||
cmd.append('--nologcapture')
|
||||
for e in self._get_test_exclusions():
|
||||
cmd.append('--exclude=%s' % (e))
|
||||
xunit_fn = self.get_option("xunit_filename"):
|
||||
if xunit_fn:
|
||||
cmd.append("--with-xunit")
|
||||
cmd.append("--xunit-file=%s" % (xunit_fn))
|
||||
return cmd
|
||||
|
||||
def _use_pep8(self):
|
||||
@ -922,7 +926,7 @@ class PythonTestingComponent(component.Component):
|
||||
cmd = self._get_test_command()
|
||||
env = self._get_env()
|
||||
with open(os.devnull, 'wb') as null_fh:
|
||||
if self.get_bool_option("tests_verbose", default_value=False):
|
||||
if self.get_bool_option("verbose", default_value=False):
|
||||
null_fh = None
|
||||
sh.execute(*cmd, stdout_fh=None, stderr_fh=null_fh,
|
||||
cwd=app_dir, env_overrides=env)
|
||||
|
@ -286,7 +286,7 @@ class ConfConfigurator(object):
|
||||
# Used more than once so we calculate it ahead of time
|
||||
hostip = self.installer.get_option('ip')
|
||||
|
||||
nova_conf.add('verbose', self.installer.get_bool_option('verbose'))
|
||||
nova_conf.add('verbose', self.installer.get_bool_option('log_verbose'))
|
||||
|
||||
# Allow destination machine to match source for resize.
|
||||
nova_conf.add('allow_resize_to_same_host', True)
|
||||
|
@ -42,13 +42,15 @@ SHELL_QUOTE_REPLACERS = {
|
||||
"$": '\$',
|
||||
'`': '\`',
|
||||
}
|
||||
ROOT_PATH = os.sep
|
||||
|
||||
# Locally stash these so that they can not be changed
|
||||
# by others after this is first fetched...
|
||||
SUDO_UID = env.get_key('SUDO_UID')
|
||||
SUDO_GID = env.get_key('SUDO_GID')
|
||||
|
||||
# Set only once
|
||||
IS_DRYRUN = None
|
||||
|
||||
|
||||
class Process(psutil.Process):
|
||||
def __str__(self):
|
||||
@ -72,11 +74,17 @@ class Rooted(object):
|
||||
self.engaged = False
|
||||
|
||||
|
||||
def set_dry_run(on_off):
|
||||
global IS_DRYRUN
|
||||
if not isinstance(on_off, (bool)):
|
||||
raise TypeError("Dry run value must be a boolean")
|
||||
if IS_DRYRUN is not None:
|
||||
raise RuntimeError("Dry run value has already been previously set to '%s'" % (IS_DRYRUN))
|
||||
IS_DRYRUN = on_off
|
||||
|
||||
|
||||
def is_dry_run():
|
||||
# Not stashed locally since the main entrypoint
|
||||
# actually adjusts this value depending on a command
|
||||
# line option...
|
||||
return tu.make_bool(env.get_key('ANVIL_DRYRUN'))
|
||||
return bool(IS_DRYRUN)
|
||||
|
||||
|
||||
# Originally borrowed from nova computes execute...
|
||||
@ -85,13 +93,12 @@ def execute(*cmd, **kwargs):
|
||||
check_exit_code = kwargs.pop('check_exit_code', [0])
|
||||
cwd = kwargs.pop('cwd', None)
|
||||
env_overrides = kwargs.pop('env_overrides', None)
|
||||
close_stdin = kwargs.pop('close_stdin', False)
|
||||
ignore_exit_code = kwargs.pop('ignore_exit_code', False)
|
||||
|
||||
if isinstance(check_exit_code, bool):
|
||||
if isinstance(check_exit_code, (bool)):
|
||||
ignore_exit_code = not check_exit_code
|
||||
check_exit_code = [0]
|
||||
elif isinstance(check_exit_code, int):
|
||||
elif isinstance(check_exit_code, (int)):
|
||||
check_exit_code = [check_exit_code]
|
||||
|
||||
run_as_root = kwargs.pop('run_as_root', False)
|
||||
@ -109,22 +116,28 @@ def execute(*cmd, **kwargs):
|
||||
stdin_fh = subprocess.PIPE
|
||||
stdout_fh = subprocess.PIPE
|
||||
stderr_fh = subprocess.PIPE
|
||||
close_file_descriptors = True
|
||||
|
||||
if 'stdout_fh' in kwargs.keys():
|
||||
stdout_fh = kwargs.get('stdout_fh')
|
||||
stdout_fn = kwargs.get('stdout_fn')
|
||||
stderr_fn = kwargs.get('stderr_fn')
|
||||
trace_writer = kwargs.get('tracewriter')
|
||||
|
||||
if 'stdin_fh' in kwargs.keys():
|
||||
stdin_fh = kwargs.get('stdin_fh')
|
||||
process_input = None
|
||||
if 'stdout_fh' in kwargs:
|
||||
stdout_fh = kwargs['stdout_fh']
|
||||
if stdout_fn:
|
||||
LOG.warn("Stdout file handles and stdout file names can not be used simultaneously!")
|
||||
stdout_fn = None
|
||||
|
||||
if 'stderr_fh' in kwargs.keys():
|
||||
stderr_fh = kwargs.get('stderr_fh')
|
||||
if 'stderr_fh' in kwargs:
|
||||
stderr_fh = kwargs['stderr_fh']
|
||||
if stderr_fn:
|
||||
LOG.warn("Stderr file handles and stderr file names can not be used simultaneously!")
|
||||
stderr_fn = None
|
||||
|
||||
if not shell:
|
||||
LOG.debug('Running cmd: %r' % (execute_cmd))
|
||||
else:
|
||||
LOG.debug('Running shell cmd: %r' % (execute_cmd))
|
||||
|
||||
if process_input is not None:
|
||||
LOG.debug('With stdin: %s' % (process_input))
|
||||
if cwd:
|
||||
@ -145,8 +158,12 @@ def execute(*cmd, **kwargs):
|
||||
return doit
|
||||
|
||||
if not run_as_root:
|
||||
# Ensure we drop down to the suid user before the command
|
||||
# is executed (ensuring we don't run in root mode when we
|
||||
# should not be)
|
||||
(user_uid, user_gid) = get_suids()
|
||||
demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid)
|
||||
if user_uid is not None and user_gid is not None:
|
||||
demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid)
|
||||
|
||||
rc = None
|
||||
result = None
|
||||
@ -157,7 +174,7 @@ def execute(*cmd, **kwargs):
|
||||
else:
|
||||
try:
|
||||
obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh,
|
||||
close_fds=close_file_descriptors, cwd=cwd, shell=shell,
|
||||
close_fds=True, cwd=cwd, shell=shell,
|
||||
preexec_fn=demoter, env=process_env)
|
||||
if process_input is not None:
|
||||
result = obj.communicate(str(process_input))
|
||||
@ -166,8 +183,6 @@ def execute(*cmd, **kwargs):
|
||||
except OSError as e:
|
||||
raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror),
|
||||
cmd=str_cmd)
|
||||
if (stdin_fh != subprocess.PIPE and obj.stdin and close_stdin):
|
||||
obj.stdin.close()
|
||||
rc = obj.returncode
|
||||
|
||||
if not result:
|
||||
@ -188,13 +203,10 @@ def execute(*cmd, **kwargs):
|
||||
LOG.debug("A failure may of just happened when running command %r [%s] (%s, %s)",
|
||||
str_cmd, rc, stdout, stderr)
|
||||
# See if a requested storage place was given for stderr/stdout
|
||||
trace_writer = kwargs.get('tracewriter')
|
||||
stdout_fn = kwargs.get('stdout_fn')
|
||||
if stdout_fn:
|
||||
write_file(stdout_fn, stdout)
|
||||
if trace_writer:
|
||||
trace_writer.file_touched(stdout_fn)
|
||||
stderr_fn = kwargs.get('stderr_fn')
|
||||
if stderr_fn:
|
||||
write_file(stderr_fn, stderr)
|
||||
if trace_writer:
|
||||
@ -204,7 +216,7 @@ def execute(*cmd, **kwargs):
|
||||
|
||||
def abspth(path):
|
||||
if not path:
|
||||
path = ROOT_PATH
|
||||
path = "/"
|
||||
if path == "~":
|
||||
path = gethomedir()
|
||||
return os.path.abspath(path)
|
||||
|
@ -102,7 +102,7 @@ nova_version: "1.1"
|
||||
scheduler: nova.scheduler.filter_scheduler.FilterScheduler
|
||||
|
||||
# Should nova be in verbose mode?
|
||||
verbose: True
|
||||
log_verbose: True
|
||||
|
||||
# Virtualization settings
|
||||
# Drivers known (libvirt, xensever, vmware, baremetal)
|
||||
|
4
conf/messages/fails.1.txt
Normal file
4
conf/messages/fails.1.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
__________
|
||||
< Failure! >
|
||||
----------
|
6
conf/messages/fails.10.txt
Normal file
6
conf/messages/fails.10.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
_____________________
|
||||
/ We were in the nick \
|
||||
| of time. You were |
|
||||
\ in great peril. /
|
||||
---------------------
|
8
conf/messages/fails.11.txt
Normal file
8
conf/messages/fails.11.txt
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
___________________
|
||||
/ I know a dead \
|
||||
| parrot when I see |
|
||||
| one, and I'm |
|
||||
| looking at one |
|
||||
\ right now. /
|
||||
-------------------
|
6
conf/messages/fails.12.txt
Normal file
6
conf/messages/fails.12.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
_________________
|
||||
/ Welcome to the \
|
||||
| National Cheese |
|
||||
\ Emporium /
|
||||
-----------------
|
6
conf/messages/fails.13.txt
Normal file
6
conf/messages/fails.13.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
______________________
|
||||
/ What is the airspeed \
|
||||
| velocity of an |
|
||||
\ unladen swallow? /
|
||||
----------------------
|
5
conf/messages/fails.14.txt
Normal file
5
conf/messages/fails.14.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
______________________
|
||||
/ Now stand aside, \
|
||||
\ worthy adversary. /
|
||||
----------------------
|
5
conf/messages/fails.15.txt
Normal file
5
conf/messages/fails.15.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
___________________
|
||||
/ Okay, we'll call \
|
||||
\ it a draw. /
|
||||
-------------------
|
5
conf/messages/fails.16.txt
Normal file
5
conf/messages/fails.16.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
_______________
|
||||
/ She turned me \
|
||||
\ into a newt! /
|
||||
---------------
|
4
conf/messages/fails.17.txt
Normal file
4
conf/messages/fails.17.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
___________________
|
||||
< Fetchez la vache! >
|
||||
-------------------
|
6
conf/messages/fails.18.txt
Normal file
6
conf/messages/fails.18.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
__________________________
|
||||
/ We'd better not risk \
|
||||
| another frontal assault, |
|
||||
\ that rabbit's dynamite. /
|
||||
--------------------------
|
8
conf/messages/fails.19.txt
Normal file
8
conf/messages/fails.19.txt
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
______________________
|
||||
/ This is supposed to \
|
||||
| be a happy occasion. |
|
||||
| Let's not bicker and |
|
||||
| argue about who |
|
||||
\ killed who. /
|
||||
----------------------
|
4
conf/messages/fails.2.txt
Normal file
4
conf/messages/fails.2.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
___________
|
||||
< Run away! >
|
||||
-----------
|
4
conf/messages/fails.20.txt
Normal file
4
conf/messages/fails.20.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
_______________________
|
||||
< You have been borked. >
|
||||
-----------------------
|
6
conf/messages/fails.21.txt
Normal file
6
conf/messages/fails.21.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
__________________
|
||||
/ We used to dream \
|
||||
| of living in a |
|
||||
\ corridor! /
|
||||
-------------------
|
5
conf/messages/fails.3.txt
Normal file
5
conf/messages/fails.3.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
______________________
|
||||
/ NOBODY expects the \
|
||||
\ Spanish Inquisition! /
|
||||
----------------------
|
5
conf/messages/fails.4.txt
Normal file
5
conf/messages/fails.4.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
______________________
|
||||
/ Spam spam spam spam \
|
||||
\ baked beans and spam /
|
||||
----------------------
|
5
conf/messages/fails.5.txt
Normal file
5
conf/messages/fails.5.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
____________________
|
||||
/ Brave Sir Robin \
|
||||
\ ran away. /
|
||||
--------------------
|
4
conf/messages/fails.6.txt
Normal file
4
conf/messages/fails.6.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
_______________________
|
||||
< Message for you, sir. >
|
||||
-----------------------
|
5
conf/messages/fails.7.txt
Normal file
5
conf/messages/fails.7.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
____________________
|
||||
/ We are the knights \
|
||||
\ who say.... NI! /
|
||||
--------------------
|
6
conf/messages/fails.8.txt
Normal file
6
conf/messages/fails.8.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
____________________
|
||||
/ Now go away or I \
|
||||
| shall taunt you a |
|
||||
\ second time. /
|
||||
--------------------
|
7
conf/messages/fails.9.txt
Normal file
7
conf/messages/fails.9.txt
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
____________________
|
||||
/ It's time for the \
|
||||
| penguin on top of |
|
||||
| your television to |
|
||||
\ explode. /
|
||||
--------------------
|
7
conf/messages/stacks.1.txt
Normal file
7
conf/messages/stacks.1.txt
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
___ ____ _____ _ _ ____ _____ _ ____ _ __
|
||||
/ _ \| _ \| ____| \ | / ___|_ _|/ \ / ___| |/ /
|
||||
| | | | |_) | _| | \| \___ \ | | / _ \| | | ' /
|
||||
| |_| | __/| |___| |\ |___) || |/ ___ \ |___| . \
|
||||
\___/|_| |_____|_| \_|____/ |_/_/ \_\____|_|\_\
|
||||
|
6
conf/messages/stacks.2.txt
Normal file
6
conf/messages/stacks.2.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
___ ___ ___ _ _ ___ _____ _ ___ _ __
|
||||
/ _ \| _ \ __| \| / __|_ _/_\ / __| |/ /
|
||||
| (_) | _/ _|| .` \__ \ | |/ _ \ (__| ' <
|
||||
\___/|_| |___|_|\_|___/ |_/_/ \_\___|_|\_\
|
||||
|
5
conf/messages/stacks.3.txt
Normal file
5
conf/messages/stacks.3.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
____ ___ ____ _ _ ____ ___ ____ ____ _ _
|
||||
| | |__] |___ |\ | [__ | |__| | |_/
|
||||
|__| | |___ | \| ___] | | | |___ | \_
|
||||
|
6
conf/messages/stacks.4.txt
Normal file
6
conf/messages/stacks.4.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
_ ___ ___ _ _ __ ___ _ __ _ _
|
||||
/ \| o \ __|| \| |/ _||_ _|/ \ / _|| |//
|
||||
( o ) _/ _| | \\ |\_ \ | || o ( (_ | (
|
||||
\_/|_| |___||_|\_||__/ |_||_n_|\__||_|\\
|
||||
|
6
conf/messages/stacks.5.txt
Normal file
6
conf/messages/stacks.5.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
_ ___ ___ _ __ ___ _____ _ __ _
|
||||
,' \ / o |/ _/ / |/ /,' _//_ _/.' \ ,'_/ / //7
|
||||
/ o |/ _,'/ _/ / || /_\ `. / / / o // /_ / ,'
|
||||
|_,'/_/ /___//_/|_//___,' /_/ /_n_/ |__//_/\\
|
||||
|
8
conf/messages/stacks.6.txt
Normal file
8
conf/messages/stacks.6.txt
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
_____ ___ ___ _ _ ___ _____ _____ ___ _ _
|
||||
( _ )( _`\ ( _`\ ( ) ( )( _`\(_ _)( _ )( _`\ ( ) ( )
|
||||
| ( ) || |_) )| (_(_)| `\| || (_(_) | | | (_) || ( (_)| |/'/'
|
||||
| | | || ,__/'| _)_ | , ` |`\__ \ | | | _ || | _ | , <
|
||||
| (_) || | | (_( )| |`\ |( )_) | | | | | | || (_( )| |\`\
|
||||
(_____)(_) (____/'(_) (_)`\____) (_) (_) (_)(____/'(_) (_)
|
||||
|
10
conf/messages/success.1.txt
Normal file
10
conf/messages/success.1.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
___________
|
||||
/ You shine \
|
||||
| out like |
|
||||
| a shaft |
|
||||
| of gold |
|
||||
| when all |
|
||||
| around is |
|
||||
\ dark. /
|
||||
-----------
|
4
conf/messages/success.2.txt
Normal file
4
conf/messages/success.2.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
______________________________
|
||||
< I'm a lumberjack and I'm OK. >
|
||||
------------------------------
|
7
conf/messages/success.3.txt
Normal file
7
conf/messages/success.3.txt
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
____________________
|
||||
/ Australia! \
|
||||
| Australia! |
|
||||
| Australia! |
|
||||
\ We love you, amen. /
|
||||
--------------------
|
6
conf/messages/success.4.txt
Normal file
6
conf/messages/success.4.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
______________
|
||||
/ Say no more, \
|
||||
| Nudge nudge |
|
||||
\ wink wink. /
|
||||
--------------
|
5
conf/messages/success.5.txt
Normal file
5
conf/messages/success.5.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
________________
|
||||
/ And there was \
|
||||
\ much rejoicing /
|
||||
----------------
|
4
conf/messages/success.6.txt
Normal file
4
conf/messages/success.6.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
__________
|
||||
< Success! >
|
||||
----------
|
1
conf/messages/welcome.1.txt
Normal file
1
conf/messages/welcome.1.txt
Normal file
@ -0,0 +1 @@
|
||||
And now for something completely different!
|
1
conf/messages/welcome.2.txt
Normal file
1
conf/messages/welcome.2.txt
Normal file
@ -0,0 +1 @@
|
||||
Let us get on with the show!
|
20
smithy
20
smithy
@ -28,7 +28,6 @@ if [ -n "$SUDO_USER" ]; then
|
||||
fi
|
||||
|
||||
ARGS="$@"
|
||||
VER=$(python -c "from anvil import version; print version.version_string()")
|
||||
PWD=`pwd`
|
||||
if [ -z "$BOOT_FILES" ]; then
|
||||
BOOT_FN=".anvil_bootstrapped"
|
||||
@ -85,10 +84,11 @@ bootstrap_epel()
|
||||
|
||||
has_bootstrapped()
|
||||
{
|
||||
checksums=$(get_checksums)
|
||||
for i in $BOOT_FILES; do
|
||||
if [ -f $i ]; then
|
||||
contents=`cat $i`
|
||||
if [ "$contents" == "$VER" ]; then
|
||||
if [ "$contents" == "$checksums" ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
@ -96,6 +96,14 @@ has_bootstrapped()
|
||||
return 1
|
||||
}
|
||||
|
||||
get_checksums()
|
||||
{
|
||||
pkg_checksum=$(md5sum tools/pkg-requires)
|
||||
pip_checksum=$(md5sum tools/pip-requires)
|
||||
echo "$pkg_checksum"
|
||||
echo "$pip_checksum"
|
||||
}
|
||||
|
||||
bootstrap_rhel()
|
||||
{
|
||||
echo "Bootstrapping RHEL: $1"
|
||||
@ -122,7 +130,7 @@ run_smithy()
|
||||
puke()
|
||||
{
|
||||
# TODO(harlowja) better way to do this??
|
||||
cleaned_force=$(python -c "f='$FORCE';print(f.lower().strip())")
|
||||
cleaned_force=$(python -c "f='$FORCE'; print(f.lower().strip())")
|
||||
if [[ "$cleaned_force" == "yes" ]]; then
|
||||
run_smithy
|
||||
else
|
||||
@ -146,8 +154,12 @@ if [[ "$TYPE" =~ "Red Hat Enterprise Linux Server" ]]; then
|
||||
fi
|
||||
bootstrap_rhel $RH_VER
|
||||
if [ $? -eq 0 ]; then
|
||||
# Write the checksums of the requirement files
|
||||
# which if new requirements are added will cause new checksums
|
||||
# and a new dependency install...
|
||||
checksums=$(get_checksums)
|
||||
for i in $BOOT_FILES; do
|
||||
echo "$VER" > $i
|
||||
echo -e "$checksums" > $i
|
||||
done
|
||||
run_smithy
|
||||
else
|
||||
|
@ -1,3 +1,4 @@
|
||||
PyYAML
|
||||
gcc
|
||||
git
|
||||
pylint
|
||||
@ -6,6 +7,6 @@ python-cheetah
|
||||
python-iso8601
|
||||
python-netifaces
|
||||
python-ordereddict
|
||||
python-pip
|
||||
python-progressbar
|
||||
python-psutil
|
||||
PyYAML
|
||||
|
Loading…
x
Reference in New Issue
Block a user