Merge pull request #345 from harlowja/master

Lots of goodies (see the commit log)
This commit is contained in:
Joshua Harlow 2012-12-01 14:24:33 -08:00
commit c7ab9b3ba2
45 changed files with 334 additions and 64 deletions

View File

@ -82,7 +82,7 @@ def run(args):
# Stash the dryrun value (if any) # Stash the dryrun value (if any)
if 'dryrun' in args: 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 the anvil dirs are there if others are about to use it...
ensure_anvil_dirs() ensure_anvil_dirs()

View File

@ -33,6 +33,10 @@ from anvil.utils import OrderedDict
LOG = logging.getLogger(__name__) 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): class PhaseFunctors(object):
def __init__(self, start, run, end): def __init__(self, start, run, end):
@ -74,7 +78,7 @@ class Action(object):
already_gotten = set() already_gotten = set()
for c in component_order: for c in component_order:
instance = instances[c] instance = instances[c]
wanted_passwords = instance.get_option('wanted_passwords') or [] wanted_passwords = instance.get_option('wanted_passwords')
if not wanted_passwords: if not wanted_passwords:
continue continue
for (name, prompt) in wanted_passwords.items(): for (name, prompt) in wanted_passwords.items():
@ -160,11 +164,18 @@ class Action(object):
sibling_instances[action][name] = a_sibling sibling_instances[action][name] = a_sibling
return there_siblings 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): def _get_interpolated_options(self, name):
interpolated_opts = {} opts = {}
for c in ['general', name]: for c in self._get_interpolated_names(name):
interpolated_opts.update(self.interpolator.extract(c)) opts.update(self.interpolator.extract(c))
return interpolated_opts return opts
def _construct_instances(self, persona): 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) utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
def _get_phase_filename(self, phase_name): 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.lower().strip()
phase_name = phase_name.replace("-", '_') phase_name = phase_name.replace("-", '_')
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. 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() 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: if not phase_name:
phase_recorder = phase.NullPhaseRecorder() phase_recorder = phase.NullPhaseRecorder()
else: else:
phase_recorder = phase.PhaseRecorder(self._get_phase_filename(phase_name)) 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 = [] neg_phase_recs = []
if inv_phase_names: if inv_phase_names:
for n in 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))) neg_phase_recs.append(phase.PhaseRecorder(self._get_phase_filename(n)))
def change_activate(instance, on_off): 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 instance.activated = on_off
for (_name, sibling_instance) in instance.siblings.items(): for (_name, sibling_instance) in instance.siblings.items():
sibling_instance.activated = on_off sibling_instance.activated = on_off

View File

@ -139,6 +139,13 @@ class YamlInterpolator(object):
self.included = {} self.included = {}
self.interpolated = {} self.interpolated = {}
self.base = base 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): def _interpolate_iterable(self, what):
if isinstance(what, (set)): if isinstance(what, (set)):
@ -150,6 +157,8 @@ class YamlInterpolator(object):
n_what = [] n_what = []
for v in what: for v in what:
n_what.append(self._interpolate(v)) n_what.append(self._interpolate(v))
if isinstance(what, (tuple)):
n_what = tuple(n_what)
return n_what return n_what
def _interpolate_dictionary(self, what): def _interpolate_dictionary(self, what):
@ -174,6 +183,8 @@ class YamlInterpolator(object):
n_what = [] n_what = []
for v in what: for v in what:
n_what.append(self._do_include(v)) n_what.append(self._do_include(v))
if isinstance(what, (tuple)):
n_what = tuple(n_what)
return n_what return n_what
def _interpolate(self, value): def _interpolate(self, value):
@ -188,13 +199,16 @@ class YamlInterpolator(object):
def _interpolate_string(self, what): def _interpolate_string(self, what):
if not re.search(INTERP_PAT, what): if not re.search(INTERP_PAT, what):
# Leave it alone if the sub won't do
# anything to begin with
return what return what
def replacer(match): def replacer(match):
who = match.group(1).strip() who = match.group(1).strip()
key = match.group(2).strip() key = match.group(2).strip()
if self._process_special(who, key): (is_special, special_value) = self._process_special(who, key)
return self._process_special(who, key) if is_special:
return special_value
if who not in self.interpolated: if who not in self.interpolated:
self.interpolated[who] = self.included[who] self.interpolated[who] = self.included[who]
self.interpolated[who] = self._interpolate(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) return re.sub(INTERP_PAT, replacer, what)
def _process_special(self, who, key): def _process_special(self, who, key):
if key == 'ip' and who == 'auto': if who and who.lower() in ['auto']:
return utils.get_host_ip() if key not in self.auto_specials:
if key == 'user' and who == 'auto': raise KeyError("Unknown auto key %r" % (key))
return sh.getuser() functor = self.auto_specials[key]
if who == 'auto': return (True, functor())
raise KeyError("Unknown auto key type %s" % (key)) return (False, None)
return None
def _include_string(self, what): def _include_string(self, what):
if not re.search(INTERP_PAT, what): if not re.search(INTERP_PAT, what):
# Leave it alone if the sub won't do
# anything to begin with
return what return what
def replacer(match): def replacer(match):
who = match.group(1).strip() who = match.group(1).strip()
key = match.group(2).strip() key = match.group(2).strip()
if self._process_special(who, key): (is_special, special_value) = self._process_special(who, key)
return 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) self._process_includes(who)
return str(self.included[who][key]) return str(self.included[who][key])
return re.sub(INTERP_PAT, replacer, what) return re.sub(INTERP_PAT, replacer, what)
def _do_include(self, v): def _do_include(self, value):
n_v = v new_value = value
if v and isinstance(v, (basestring, str)): if value and isinstance(value, (basestring, str)):
n_v = self._include_string(v) new_value = self._include_string(value)
elif isinstance(v, dict): elif isinstance(value, (dict)):
n_v = self._include_dictionary(v) new_value = self._include_dictionary(value)
elif isinstance(v, (list, set, tuple)): elif isinstance(value, (list, set, tuple)):
n_v = self._include_iterable(v) new_value = self._include_iterable(value)
return n_v return new_value
def _process_includes(self, root): def _process_includes(self, root):
if root in self.included: if root in self.included:

View File

@ -23,13 +23,15 @@ from anvil import type_utils as tu
COLORS = termcolor.COLORS.keys() 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(): def color_enabled():
if 'LOG_COLOR' in env.get() and not tu.make_bool(env.get_key('LOG_COLOR')): return LOG_COLOR
return False
if not sys.stdout.isatty():
return False
return True
def quote(data, quote_color='green', **kargs): def quote(data, quote_color='green', **kargs):

View File

@ -856,6 +856,10 @@ class PythonTestingComponent(component.Component):
cmd.append('--nologcapture') cmd.append('--nologcapture')
for e in self._get_test_exclusions(): for e in self._get_test_exclusions():
cmd.append('--exclude=%s' % (e)) 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 return cmd
def _use_pep8(self): def _use_pep8(self):
@ -922,7 +926,7 @@ class PythonTestingComponent(component.Component):
cmd = self._get_test_command() cmd = self._get_test_command()
env = self._get_env() env = self._get_env()
with open(os.devnull, 'wb') as null_fh: 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 null_fh = None
sh.execute(*cmd, stdout_fh=None, stderr_fh=null_fh, sh.execute(*cmd, stdout_fh=None, stderr_fh=null_fh,
cwd=app_dir, env_overrides=env) cwd=app_dir, env_overrides=env)

View File

@ -286,7 +286,7 @@ class ConfConfigurator(object):
# Used more than once so we calculate it ahead of time # Used more than once so we calculate it ahead of time
hostip = self.installer.get_option('ip') 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. # Allow destination machine to match source for resize.
nova_conf.add('allow_resize_to_same_host', True) nova_conf.add('allow_resize_to_same_host', True)

View File

@ -42,13 +42,15 @@ SHELL_QUOTE_REPLACERS = {
"$": '\$', "$": '\$',
'`': '\`', '`': '\`',
} }
ROOT_PATH = os.sep
# Locally stash these so that they can not be changed # Locally stash these so that they can not be changed
# by others after this is first fetched... # by others after this is first fetched...
SUDO_UID = env.get_key('SUDO_UID') SUDO_UID = env.get_key('SUDO_UID')
SUDO_GID = env.get_key('SUDO_GID') SUDO_GID = env.get_key('SUDO_GID')
# Set only once
IS_DRYRUN = None
class Process(psutil.Process): class Process(psutil.Process):
def __str__(self): def __str__(self):
@ -72,11 +74,17 @@ class Rooted(object):
self.engaged = False 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(): def is_dry_run():
# Not stashed locally since the main entrypoint return bool(IS_DRYRUN)
# actually adjusts this value depending on a command
# line option...
return tu.make_bool(env.get_key('ANVIL_DRYRUN'))
# Originally borrowed from nova computes execute... # Originally borrowed from nova computes execute...
@ -85,13 +93,12 @@ def execute(*cmd, **kwargs):
check_exit_code = kwargs.pop('check_exit_code', [0]) check_exit_code = kwargs.pop('check_exit_code', [0])
cwd = kwargs.pop('cwd', None) cwd = kwargs.pop('cwd', None)
env_overrides = kwargs.pop('env_overrides', None) env_overrides = kwargs.pop('env_overrides', None)
close_stdin = kwargs.pop('close_stdin', False)
ignore_exit_code = kwargs.pop('ignore_exit_code', 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 ignore_exit_code = not check_exit_code
check_exit_code = [0] check_exit_code = [0]
elif isinstance(check_exit_code, int): elif isinstance(check_exit_code, (int)):
check_exit_code = [check_exit_code] check_exit_code = [check_exit_code]
run_as_root = kwargs.pop('run_as_root', False) run_as_root = kwargs.pop('run_as_root', False)
@ -109,22 +116,28 @@ def execute(*cmd, **kwargs):
stdin_fh = subprocess.PIPE stdin_fh = subprocess.PIPE
stdout_fh = subprocess.PIPE stdout_fh = subprocess.PIPE
stderr_fh = subprocess.PIPE stderr_fh = subprocess.PIPE
close_file_descriptors = True
if 'stdout_fh' in kwargs.keys(): stdout_fn = kwargs.get('stdout_fn')
stdout_fh = kwargs.get('stdout_fh') stderr_fn = kwargs.get('stderr_fn')
trace_writer = kwargs.get('tracewriter')
if 'stdin_fh' in kwargs.keys(): if 'stdout_fh' in kwargs:
stdin_fh = kwargs.get('stdin_fh') stdout_fh = kwargs['stdout_fh']
process_input = None 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(): if 'stderr_fh' in kwargs:
stderr_fh = kwargs.get('stderr_fh') 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: if not shell:
LOG.debug('Running cmd: %r' % (execute_cmd)) LOG.debug('Running cmd: %r' % (execute_cmd))
else: else:
LOG.debug('Running shell cmd: %r' % (execute_cmd)) LOG.debug('Running shell cmd: %r' % (execute_cmd))
if process_input is not None: if process_input is not None:
LOG.debug('With stdin: %s' % (process_input)) LOG.debug('With stdin: %s' % (process_input))
if cwd: if cwd:
@ -145,8 +158,12 @@ def execute(*cmd, **kwargs):
return doit return doit
if not run_as_root: 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() (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 rc = None
result = None result = None
@ -157,7 +174,7 @@ def execute(*cmd, **kwargs):
else: else:
try: try:
obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, 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) preexec_fn=demoter, env=process_env)
if process_input is not None: if process_input is not None:
result = obj.communicate(str(process_input)) result = obj.communicate(str(process_input))
@ -166,8 +183,6 @@ def execute(*cmd, **kwargs):
except OSError as e: except OSError as e:
raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror),
cmd=str_cmd) cmd=str_cmd)
if (stdin_fh != subprocess.PIPE and obj.stdin and close_stdin):
obj.stdin.close()
rc = obj.returncode rc = obj.returncode
if not result: 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)", LOG.debug("A failure may of just happened when running command %r [%s] (%s, %s)",
str_cmd, rc, stdout, stderr) str_cmd, rc, stdout, stderr)
# See if a requested storage place was given for stderr/stdout # 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: if stdout_fn:
write_file(stdout_fn, stdout) write_file(stdout_fn, stdout)
if trace_writer: if trace_writer:
trace_writer.file_touched(stdout_fn) trace_writer.file_touched(stdout_fn)
stderr_fn = kwargs.get('stderr_fn')
if stderr_fn: if stderr_fn:
write_file(stderr_fn, stderr) write_file(stderr_fn, stderr)
if trace_writer: if trace_writer:
@ -204,7 +216,7 @@ def execute(*cmd, **kwargs):
def abspth(path): def abspth(path):
if not path: if not path:
path = ROOT_PATH path = "/"
if path == "~": if path == "~":
path = gethomedir() path = gethomedir()
return os.path.abspath(path) return os.path.abspath(path)

View File

@ -102,7 +102,7 @@ nova_version: "1.1"
scheduler: nova.scheduler.filter_scheduler.FilterScheduler scheduler: nova.scheduler.filter_scheduler.FilterScheduler
# Should nova be in verbose mode? # Should nova be in verbose mode?
verbose: True log_verbose: True
# Virtualization settings # Virtualization settings
# Drivers known (libvirt, xensever, vmware, baremetal) # Drivers known (libvirt, xensever, vmware, baremetal)

View File

@ -0,0 +1,4 @@
__________
< Failure! >
----------

View File

@ -0,0 +1,6 @@
_____________________
/ We were in the nick \
| of time. You were |
\ in great peril. /
---------------------

View File

@ -0,0 +1,8 @@
___________________
/ I know a dead \
| parrot when I see |
| one, and I'm |
| looking at one |
\ right now. /
-------------------

View File

@ -0,0 +1,6 @@
_________________
/ Welcome to the \
| National Cheese |
\ Emporium /
-----------------

View File

@ -0,0 +1,6 @@
______________________
/ What is the airspeed \
| velocity of an |
\ unladen swallow? /
----------------------

View File

@ -0,0 +1,5 @@
______________________
/ Now stand aside, \
\ worthy adversary. /
----------------------

View File

@ -0,0 +1,5 @@
___________________
/ Okay, we'll call \
\ it a draw. /
-------------------

View File

@ -0,0 +1,5 @@
_______________
/ She turned me \
\ into a newt! /
---------------

View File

@ -0,0 +1,4 @@
___________________
< Fetchez la vache! >
-------------------

View File

@ -0,0 +1,6 @@
__________________________
/ We'd better not risk \
| another frontal assault, |
\ that rabbit's dynamite. /
--------------------------

View File

@ -0,0 +1,8 @@
______________________
/ This is supposed to \
| be a happy occasion. |
| Let's not bicker and |
| argue about who |
\ killed who. /
----------------------

View File

@ -0,0 +1,4 @@
___________
< Run away! >
-----------

View File

@ -0,0 +1,4 @@
_______________________
< You have been borked. >
-----------------------

View File

@ -0,0 +1,6 @@
__________________
/ We used to dream \
| of living in a |
\ corridor! /
-------------------

View File

@ -0,0 +1,5 @@
______________________
/ NOBODY expects the \
\ Spanish Inquisition! /
----------------------

View File

@ -0,0 +1,5 @@
______________________
/ Spam spam spam spam \
\ baked beans and spam /
----------------------

View File

@ -0,0 +1,5 @@
____________________
/ Brave Sir Robin \
\ ran away. /
--------------------

View File

@ -0,0 +1,4 @@
_______________________
< Message for you, sir. >
-----------------------

View File

@ -0,0 +1,5 @@
____________________
/ We are the knights \
\ who say.... NI! /
--------------------

View File

@ -0,0 +1,6 @@
____________________
/ Now go away or I \
| shall taunt you a |
\ second time. /
--------------------

View File

@ -0,0 +1,7 @@
____________________
/ It's time for the \
| penguin on top of |
| your television to |
\ explode. /
--------------------

View File

@ -0,0 +1,7 @@
___ ____ _____ _ _ ____ _____ _ ____ _ __
/ _ \| _ \| ____| \ | / ___|_ _|/ \ / ___| |/ /
| | | | |_) | _| | \| \___ \ | | / _ \| | | ' /
| |_| | __/| |___| |\ |___) || |/ ___ \ |___| . \
\___/|_| |_____|_| \_|____/ |_/_/ \_\____|_|\_\

View File

@ -0,0 +1,6 @@
___ ___ ___ _ _ ___ _____ _ ___ _ __
/ _ \| _ \ __| \| / __|_ _/_\ / __| |/ /
| (_) | _/ _|| .` \__ \ | |/ _ \ (__| ' <
\___/|_| |___|_|\_|___/ |_/_/ \_\___|_|\_\

View File

@ -0,0 +1,5 @@
____ ___ ____ _ _ ____ ___ ____ ____ _ _
| | |__] |___ |\ | [__ | |__| | |_/
|__| | |___ | \| ___] | | | |___ | \_

View File

@ -0,0 +1,6 @@
_ ___ ___ _ _ __ ___ _ __ _ _
/ \| o \ __|| \| |/ _||_ _|/ \ / _|| |//
( o ) _/ _| | \\ |\_ \ | || o ( (_ | (
\_/|_| |___||_|\_||__/ |_||_n_|\__||_|\\

View File

@ -0,0 +1,6 @@
_ ___ ___ _ __ ___ _____ _ __ _
,' \ / o |/ _/ / |/ /,' _//_ _/.' \ ,'_/ / //7
/ o |/ _,'/ _/ / || /_\ `. / / / o // /_ / ,'
|_,'/_/ /___//_/|_//___,' /_/ /_n_/ |__//_/\\

View File

@ -0,0 +1,8 @@
_____ ___ ___ _ _ ___ _____ _____ ___ _ _
( _ )( _`\ ( _`\ ( ) ( )( _`\(_ _)( _ )( _`\ ( ) ( )
| ( ) || |_) )| (_(_)| `\| || (_(_) | | | (_) || ( (_)| |/'/'
| | | || ,__/'| _)_ | , ` |`\__ \ | | | _ || | _ | , <
| (_) || | | (_( )| |`\ |( )_) | | | | | | || (_( )| |\`\
(_____)(_) (____/'(_) (_)`\____) (_) (_) (_)(____/'(_) (_)

View File

@ -0,0 +1,10 @@
___________
/ You shine \
| out like |
| a shaft |
| of gold |
| when all |
| around is |
\ dark. /
-----------

View File

@ -0,0 +1,4 @@
______________________________
< I'm a lumberjack and I'm OK. >
------------------------------

View File

@ -0,0 +1,7 @@
____________________
/ Australia! \
| Australia! |
| Australia! |
\ We love you, amen. /
--------------------

View File

@ -0,0 +1,6 @@
______________
/ Say no more, \
| Nudge nudge |
\ wink wink. /
--------------

View File

@ -0,0 +1,5 @@
________________
/ And there was \
\ much rejoicing /
----------------

View File

@ -0,0 +1,4 @@
__________
< Success! >
----------

View File

@ -0,0 +1 @@
And now for something completely different!

View File

@ -0,0 +1 @@
Let us get on with the show!

20
smithy
View File

@ -28,7 +28,6 @@ if [ -n "$SUDO_USER" ]; then
fi fi
ARGS="$@" ARGS="$@"
VER=$(python -c "from anvil import version; print version.version_string()")
PWD=`pwd` PWD=`pwd`
if [ -z "$BOOT_FILES" ]; then if [ -z "$BOOT_FILES" ]; then
BOOT_FN=".anvil_bootstrapped" BOOT_FN=".anvil_bootstrapped"
@ -85,10 +84,11 @@ bootstrap_epel()
has_bootstrapped() has_bootstrapped()
{ {
checksums=$(get_checksums)
for i in $BOOT_FILES; do for i in $BOOT_FILES; do
if [ -f $i ]; then if [ -f $i ]; then
contents=`cat $i` contents=`cat $i`
if [ "$contents" == "$VER" ]; then if [ "$contents" == "$checksums" ]; then
return 0 return 0
fi fi
fi fi
@ -96,6 +96,14 @@ has_bootstrapped()
return 1 return 1
} }
get_checksums()
{
pkg_checksum=$(md5sum tools/pkg-requires)
pip_checksum=$(md5sum tools/pip-requires)
echo "$pkg_checksum"
echo "$pip_checksum"
}
bootstrap_rhel() bootstrap_rhel()
{ {
echo "Bootstrapping RHEL: $1" echo "Bootstrapping RHEL: $1"
@ -122,7 +130,7 @@ run_smithy()
puke() puke()
{ {
# TODO(harlowja) better way to do this?? # 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 if [[ "$cleaned_force" == "yes" ]]; then
run_smithy run_smithy
else else
@ -146,8 +154,12 @@ if [[ "$TYPE" =~ "Red Hat Enterprise Linux Server" ]]; then
fi fi
bootstrap_rhel $RH_VER bootstrap_rhel $RH_VER
if [ $? -eq 0 ]; then 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 for i in $BOOT_FILES; do
echo "$VER" > $i echo -e "$checksums" > $i
done done
run_smithy run_smithy
else else

View File

@ -1,3 +1,4 @@
PyYAML
gcc gcc
git git
pylint pylint
@ -6,6 +7,6 @@ python-cheetah
python-iso8601 python-iso8601
python-netifaces python-netifaces
python-ordereddict python-ordereddict
python-pip
python-progressbar python-progressbar
python-psutil python-psutil
PyYAML