Folsom continued.
1. Update how status is returned/structured/shown 2. Cleanup documentation.
This commit is contained in:
parent
6c019b0f0b
commit
5fbbd572af
@ -41,13 +41,13 @@ class PhaseFunctors(object):
|
||||
class Action(object):
|
||||
__meta__ = abc.ABCMeta
|
||||
|
||||
def __init__(self, distro, cfg, root_dir, name, **kargs):
|
||||
def __init__(self, distro, cfg, root_dir, name, **kwargs):
|
||||
self.distro = distro
|
||||
self.cfg = cfg
|
||||
self.keep_old = kargs.get('keep_old', False)
|
||||
self.force = kargs.get('force', False)
|
||||
self.root_dir = root_dir
|
||||
self.name = name
|
||||
self.keep_old = kwargs.get('keep_old', False)
|
||||
self.force = kwargs.get('force', False)
|
||||
|
||||
@property
|
||||
def lookup_name(self):
|
||||
|
@ -17,6 +17,7 @@
|
||||
from anvil import action
|
||||
from anvil import colorizer
|
||||
from anvil import log
|
||||
from anvil import utils
|
||||
|
||||
from anvil.action import PhaseFunctors
|
||||
|
||||
@ -28,6 +29,10 @@ from anvil.components import (STATUS_INSTALLED, STATUS_STARTED,
|
||||
|
||||
class StatusAction(action.Action):
|
||||
|
||||
def __init__(self, distro, cfg, root_dir, name, **kwargs):
|
||||
action.Action.__init__(self, distro, cfg, root_dir, name, **kwargs)
|
||||
self.show_full = kwargs.get('show_full')
|
||||
|
||||
@property
|
||||
def lookup_name(self):
|
||||
return 'running'
|
||||
@ -44,16 +49,30 @@ class StatusAction(action.Action):
|
||||
return colorizer.quote(status, quote_color='red')
|
||||
|
||||
def _print_status(self, component, result):
|
||||
if isinstance(result, (dict)):
|
||||
LOG.info("Status of %s is:", colorizer.quote(component.name))
|
||||
for (name, status) in result.items():
|
||||
LOG.info("|-- %s --> %s.", colorizer.quote(name, quote_color='blue'), self._quote_status(status))
|
||||
elif isinstance(result, (list, set)):
|
||||
LOG.info("Status of %s is:", colorizer.quote(component.name))
|
||||
for status in result:
|
||||
LOG.info("|-- %s.", self._quote_status(status))
|
||||
if not result:
|
||||
LOG.info("Status of %s is %s.", colorizer.quote(component.name), self._quote_status(STATUS_UNKNOWN))
|
||||
elif len(result) == 1:
|
||||
s = result[0]
|
||||
if s.name and s.name != component.name:
|
||||
LOG.info("Status of %s (%s) is %s.", colorizer.quote(component.name), s.name, self._quote_status(s.status))
|
||||
else:
|
||||
LOG.info("Status of %s is %s.", colorizer.quote(component.name), self._quote_status(s.status))
|
||||
if self.show_full and s.details:
|
||||
det = utils.truncate_text(s.details, max_len=8192, from_bottom=True)
|
||||
for line in det.splitlines():
|
||||
line = line.replace("\t", "\\t")
|
||||
line = line.replace("\r", "\\r")
|
||||
LOG.info("%s>> %s", " " * 2, line)
|
||||
else:
|
||||
LOG.info("Status of %s is %s.", colorizer.quote(component.name), self._quote_status(result))
|
||||
LOG.info("Status of %s is:", colorizer.quote(component.name))
|
||||
for s in result:
|
||||
LOG.info("|-- %s is %s.", s.name, self._quote_status(s.status))
|
||||
if self.show_full and s.details:
|
||||
det = utils.truncate_text(s.details, max_len=8192, from_bottom=True)
|
||||
for line in det.splitlines():
|
||||
line = line.replace("\t", "\\t")
|
||||
line = line.replace("\r", "\\r")
|
||||
LOG.info("%s>> %s", " " * 4, line)
|
||||
|
||||
def _run(self, persona, component_order, instances):
|
||||
self._run_phase(
|
||||
|
@ -57,6 +57,11 @@ STATUS_INSTALLED = 'installed'
|
||||
STATUS_STARTED = "started"
|
||||
STATUS_STOPPED = "stopped"
|
||||
STATUS_UNKNOWN = "unknown"
|
||||
class ProgramStatus(object):
|
||||
def __init__(self, status, name=None, details=''):
|
||||
self.name = name
|
||||
self.status = status
|
||||
self.details = details
|
||||
|
||||
|
||||
####
|
||||
@ -461,100 +466,89 @@ class ProgramRuntime(component.Component):
|
||||
mp['APP_NAME'] = app_name
|
||||
return mp
|
||||
|
||||
def _fetch_run_type(self):
|
||||
return self.cfg.getdefaulted("DEFAULT", "run_type", 'anvil.runners.fork:ForkRunner')
|
||||
|
||||
def start(self):
|
||||
# Anything to start?
|
||||
am_started = 0
|
||||
apps_to_start = self.apps_to_start
|
||||
if not apps_to_start:
|
||||
return am_started
|
||||
|
||||
# Select how we are going to start it
|
||||
run_type = self._fetch_run_type()
|
||||
starter = importer.import_entry_point(run_type)(self)
|
||||
for app_info in apps_to_start:
|
||||
app_name = app_info["name"]
|
||||
app_pth = app_info.get("path", app_name)
|
||||
app_dir = app_info.get("app_dir", self.get_option('app_dir'))
|
||||
# Adjust the program options now that we have real locations
|
||||
program_opts = utils.param_replace_list(self.app_options(app_name), self.app_params(app_name))
|
||||
# Start it with the given settings
|
||||
LOG.debug("Starting %r using %r", app_name, run_type)
|
||||
details_fn = starter.start(app_name, app_pth=app_pth, app_dir=app_dir, opts=program_opts)
|
||||
LOG.info("Started %s details are in %s", colorizer.quote(app_name), colorizer.quote(details_fn))
|
||||
# This trace is used to locate details about what to stop
|
||||
self.tracewriter.app_started(app_name, details_fn, run_type)
|
||||
if app_info.get('sleep_time'):
|
||||
LOG.info("%s requested a %s second sleep time, please wait...", colorizer.quote(app_name), app_info.get('sleep_time'))
|
||||
sh.sleep(app_info.get('sleep_time'))
|
||||
am_started += 1
|
||||
|
||||
run_type = self.cfg.getdefaulted("DEFAULT", "run_type", 'anvil.runners.fork:ForkRunner')
|
||||
starter_cls = importer.import_entry_point(run_type)
|
||||
starter = starter_cls(self)
|
||||
for i, app_info in enumerate(self.apps_to_start):
|
||||
self._start_app(app_info, start)
|
||||
am_started = i + 1
|
||||
self._post_app_start(app_info)
|
||||
return am_started
|
||||
|
||||
def _start_app(self, app_info, run_type, starter):
|
||||
app_name = app_info["name"]
|
||||
app_pth = app_info.get("path", app_name)
|
||||
app_dir = app_info.get("app_dir", self.get_option('app_dir'))
|
||||
program_opts = utils.param_replace_list(self.app_options(app_name), self.app_params(app_name))
|
||||
LOG.debug("Starting %r using %r", app_name, starter)
|
||||
details_fn = starter.start(app_name, app_pth=app_pth, app_dir=app_dir, opts=program_opts)
|
||||
LOG.info("Started sub-program %s.", colorizer.quote(app_name))
|
||||
# This trace is used to locate details about what/how to stop
|
||||
self.tracewriter.app_started(app_name, details_fn, run_type)
|
||||
|
||||
def _post_app_start(self, app_info):
|
||||
if 'sleep_time' in app_info:
|
||||
LOG.info("%s requested a %s second sleep time, please wait...", colorizer.quote(app_name), app_info.get('sleep_time'))
|
||||
sh.sleep(float(app_info.get('sleep_time')))
|
||||
|
||||
def _locate_investigators(self, apps_started):
|
||||
investigators = dict()
|
||||
to_investigate = list()
|
||||
for (app_name, trace_fn, how) in apps_started:
|
||||
investigator_created = {}
|
||||
to_investigate = []
|
||||
for (app_name, trace_fn, run_type) in apps_started:
|
||||
inv_cls = None
|
||||
try:
|
||||
inv_cls = importer.import_entry_point(how)
|
||||
inv_cls = importer.import_entry_point(run_type)
|
||||
except RuntimeError as e:
|
||||
LOG.warn("Could not load class %s which should be used to investigate %s: %s",
|
||||
colorizer.quote(how), colorizer.quote(app_name), e)
|
||||
continue
|
||||
investigator = None
|
||||
if inv_cls in investigators:
|
||||
investigator = investigators[inv_cls]
|
||||
if inv_cls in investigator_created:
|
||||
investigator = investigator_created[inv_cls]
|
||||
else:
|
||||
investigator = inv_cls(self)
|
||||
investigators[inv_cls] = investigator
|
||||
investigator_created[inv_cls] = investigator
|
||||
to_investigate.append((app_name, investigator))
|
||||
return to_investigate
|
||||
|
||||
def stop(self):
|
||||
# Anything to stop??
|
||||
killed_am = 0
|
||||
apps_started = self.tracereader.apps_started()
|
||||
apps_started = 0
|
||||
try:
|
||||
apps_started = self.tracereader.apps_started()
|
||||
except excp.NoTraceException:
|
||||
pass
|
||||
if not apps_started:
|
||||
return killed_am
|
||||
to_kill = self._locate_investigators(apps_started)
|
||||
for (app_name, handler) in to_kill:
|
||||
handler.stop(app_name)
|
||||
handler.unconfigure()
|
||||
killed_am += 1
|
||||
if len(apps_started) == killed_am:
|
||||
sh.unlink(self.tracereader.filename())
|
||||
return killed_am
|
||||
|
||||
def _multi_status(self):
|
||||
def status(self):
|
||||
statii = []
|
||||
apps_started = None
|
||||
try:
|
||||
apps_started = self.tracereader.apps_started()
|
||||
except excp.NoTraceException:
|
||||
return None
|
||||
pass
|
||||
if not apps_started:
|
||||
return None
|
||||
else:
|
||||
to_check = self._locate_investigators(apps_started)
|
||||
results = dict()
|
||||
for (name, handler) in to_check:
|
||||
try:
|
||||
results[name] = handler.status(name)
|
||||
except AttributeError:
|
||||
pass # Not all handlers can implement this..
|
||||
return results
|
||||
|
||||
def _status(self):
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
def status(self):
|
||||
stat = self._multi_status()
|
||||
if not stat:
|
||||
stat = self._status()
|
||||
if not stat:
|
||||
stat = STATUS_UNKNOWN
|
||||
return stat
|
||||
return statii
|
||||
to_check = self._locate_investigators(apps_started)
|
||||
for (name, handler) in to_check:
|
||||
(status, details) = handler.status(name)
|
||||
statii.append(ProgramStatus(name=name,
|
||||
status=status,
|
||||
details=details))
|
||||
return statii
|
||||
|
||||
def restart(self):
|
||||
return 0
|
||||
|
@ -151,16 +151,16 @@ class DBRuntime(comp.EmptyRuntime):
|
||||
self.wait_time = max(self.cfg.getint('DEFAULT', 'service_wait_seconds'), 1)
|
||||
|
||||
def _get_run_actions(self, act, exception_cls):
|
||||
dbtype = self.cfg.get("db", "type")
|
||||
distro_options = self.distro.get_command_config(dbtype)
|
||||
db_type = self.cfg.get("db", "type")
|
||||
distro_options = self.distro.get_command_config(db_type)
|
||||
if distro_options is None:
|
||||
raise NotImplementedError(BASE_ERROR % (act, dbtype))
|
||||
return self.distro.get_command(dbtype, act)
|
||||
raise NotImplementedError(BASE_ERROR % (act, db_type))
|
||||
return self.distro.get_command(db_type, act)
|
||||
|
||||
def start(self):
|
||||
if self._status() != comp.STATUS_STARTED:
|
||||
startcmd = self._get_run_actions('start', excp.StartException)
|
||||
sh.execute(*startcmd, run_as_root=True, check_exit_code=True)
|
||||
if self.status()[0].status != comp.STATUS_STARTED:
|
||||
start_cmd = self._get_run_actions('start', excp.StartException)
|
||||
sh.execute(*start_cmd, run_as_root=True, check_exit_code=True)
|
||||
LOG.info("Please wait %s seconds while it starts up." % self.wait_time)
|
||||
sh.sleep(self.wait_time)
|
||||
return 1
|
||||
@ -168,29 +168,33 @@ class DBRuntime(comp.EmptyRuntime):
|
||||
return 0
|
||||
|
||||
def stop(self):
|
||||
if self._status() != comp.STATUS_STOPPED:
|
||||
stopcmd = self._get_run_actions('stop', excp.StopException)
|
||||
sh.execute(*stopcmd, run_as_root=True, check_exit_code=True)
|
||||
if self.status()[0].status != comp.STATUS_STOPPED:
|
||||
stop_cmd = self._get_run_actions('stop', excp.StopException)
|
||||
sh.execute(*stop_cmd, run_as_root=True, check_exit_code=True)
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def restart(self):
|
||||
LOG.info("Restarting your database.")
|
||||
restartcmd = self._get_run_actions('restart', excp.RestartException)
|
||||
sh.execute(*restartcmd, run_as_root=True, check_exit_code=True)
|
||||
LOG.info("Please wait %s seconds while it restarts." % self.wait_time)
|
||||
restart_cmd = self._get_run_actions('restart', excp.RestartException)
|
||||
sh.execute(*restart_cmd, run_as_root=True, check_exit_code=True)
|
||||
LOG.info("Please wait %s seconds while it restarts.", self.wait_time)
|
||||
sh.sleep(self.wait_time)
|
||||
return 1
|
||||
|
||||
def _status(self):
|
||||
statuscmd = self._get_run_actions('status', excp.StatusException)
|
||||
(sysout, stderr) = sh.execute(*statuscmd, run_as_root=True, check_exit_code=False)
|
||||
combined = (str(sysout) + str(stderr)).lower()
|
||||
def status(self):
|
||||
status_cmd = self._get_run_actions('status', excp.StatusException)
|
||||
(sysout, stderr) = sh.execute(*status_cmd, run_as_root=True, check_exit_code=False)
|
||||
combined = (sysout + stderr).lower()
|
||||
st = comp.STATUS_UNKNOWN
|
||||
if combined.find("running") != -1:
|
||||
return comp.STATUS_STARTED
|
||||
st = comp.STATUS_STARTED
|
||||
elif combined.find("stop") != -1 or \
|
||||
combined.find('unrecognized') != -1:
|
||||
return comp.STATUS_STOPPED
|
||||
else:
|
||||
return comp.STATUS_UNKNOWN
|
||||
st = comp.STATUS_STOPPED
|
||||
return [
|
||||
comp.ProgramStatus(name=self.cfg.get("db", "type"),
|
||||
status=st,
|
||||
details=(sysout + stderr).strip()),
|
||||
]
|
||||
|
@ -194,7 +194,7 @@ class HorizonRuntime(comp.EmptyRuntime):
|
||||
comp.EmptyRuntime.__init__(self, *args, **kargs)
|
||||
|
||||
def start(self):
|
||||
if self._status() != comp.STATUS_STARTED:
|
||||
if self.status()[0].status != comp.STATUS_STARTED:
|
||||
start_cmd = self.distro.get_command('apache', 'start')
|
||||
sh.execute(*start_cmd, run_as_root=True, check_exit_code=True)
|
||||
return 1
|
||||
@ -207,22 +207,25 @@ class HorizonRuntime(comp.EmptyRuntime):
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
if self._status() != comp.STATUS_STOPPED:
|
||||
if self.status()[0].status != comp.STATUS_STOPPED:
|
||||
stop_cmd = self.distro.get_command('apache', 'stop')
|
||||
sh.execute(*stop_cmd, run_as_root=True, check_exit_code=True)
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def _status(self):
|
||||
def status(self):
|
||||
status_cmd = self.distro.get_command('apache', 'status')
|
||||
(sysout, stderr) = sh.execute(*status_cmd, run_as_root=True, check_exit_code=False)
|
||||
combined = (str(sysout) + str(stderr)).lower()
|
||||
combined = (sysout + stderr).lower()
|
||||
st = comp.STATUS_UNKNOWN
|
||||
if combined.find("is running") != -1:
|
||||
return comp.STATUS_STARTED
|
||||
st = comp.STATUS_STARTED
|
||||
elif combined.find("not running") != -1 or \
|
||||
combined.find("stopped") != -1 or \
|
||||
combined.find('unrecognized') != -1:
|
||||
return comp.STATUS_STOPPED
|
||||
else:
|
||||
return comp.STATUS_UNKNOWN
|
||||
st = comp.STATUS_STOPPED
|
||||
return [
|
||||
comp.ProgramStatus(status=st,
|
||||
details=(sysout + stderr).strip()),
|
||||
]
|
||||
|
@ -81,27 +81,30 @@ class RabbitRuntime(comp.EmptyRuntime):
|
||||
self.wait_time = max(self.cfg.getint('DEFAULT', 'service_wait_seconds'), 1)
|
||||
|
||||
def start(self):
|
||||
if self._status() != comp.STATUS_STARTED:
|
||||
if self.status()[0].status != comp.STATUS_STARTED:
|
||||
self._run_cmd(self.distro.get_command('rabbit-mq', 'start'))
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def _status(self):
|
||||
def status(self):
|
||||
# This has got to be the worst status output.
|
||||
#
|
||||
# I have ever seen (its like a weird mix json+crap)
|
||||
status_cmd = self.distro.get_command('rabbit-mq', 'status')
|
||||
(sysout, stderr) = sh.execute(*status_cmd, check_exit_code=False, run_as_root=True)
|
||||
combined = (str(sysout) + str(stderr)).lower()
|
||||
st = comp.STATUS_UNKNOWN
|
||||
combined = (sysout + stderr).lower()
|
||||
if combined.find('nodedown') != -1 or \
|
||||
combined.find("unable to connect to node") != -1 or \
|
||||
combined.find('unrecognized') != -1:
|
||||
return comp.STATUS_STOPPED
|
||||
st = comp.STATUS_STOPPED
|
||||
elif combined.find('running_applications') != -1:
|
||||
return comp.STATUS_STARTED
|
||||
else:
|
||||
return comp.STATUS_UNKNOWN
|
||||
st = comp.STATUS_STARTED
|
||||
return [
|
||||
comp.ProgramStatus(status=st,
|
||||
details=(sysout + stderr).strip()),
|
||||
]
|
||||
|
||||
def _run_cmd(self, cmd, check_exit=True):
|
||||
# This seems to fix one of the bugs with rabbit mq starting and stopping
|
||||
@ -124,8 +127,8 @@ class RabbitRuntime(comp.EmptyRuntime):
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
if self._status() != comp.STATUS_STOPPED:
|
||||
self._run_cmd(self.distro.get_command('rabbit-mq', 'stop'))
|
||||
if self.status()[0].status != comp.STATUS_STOPPED:
|
||||
self._run_cmd(self.distro.get_command('rabbitmq-server', 'stop'))
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
@ -107,7 +107,17 @@ def parse():
|
||||
default=False)
|
||||
parser.add_option_group(un_group)
|
||||
|
||||
# Extract only what we care about
|
||||
status_group = OptionGroup(parser, "Status specific options")
|
||||
status_group.add_option('-s', "--show",
|
||||
action="store_true",
|
||||
dest="show_full",
|
||||
help="show the stderr/stdout log files if applicable when showing status (default: %default)",
|
||||
default=False)
|
||||
parser.add_option_group(status_group)
|
||||
|
||||
# Extract only what we care about, these will be passed
|
||||
# to the constructor of actions as arguments
|
||||
# so don't adjust the naming wily nilly...
|
||||
(options, args) = parser.parse_args()
|
||||
output = {}
|
||||
output['dir'] = (options.dir or "")
|
||||
@ -121,5 +131,6 @@ def parse():
|
||||
output['verbosity'] = len(options.verbosity)
|
||||
output['cli_overrides'] = (options.cli_overrides or [])
|
||||
output['prompt_for_passwords'] = options.prompt_for_passwords
|
||||
output['show_full'] = options.show_full
|
||||
|
||||
return output
|
||||
|
@ -57,7 +57,11 @@ class Packager(object):
|
||||
if version:
|
||||
# This won't work for all package versions (ie crazy names)
|
||||
# but good enough for now...
|
||||
p_version = pkg_resources.Requirement.parse(version)
|
||||
if contains_version_check(version):
|
||||
full_name = "%s%s" %(name, version)
|
||||
else:
|
||||
full_name = "%s==%s" %(name, version)
|
||||
p_version = pkg_resources.Requirement.parse(full_name)
|
||||
else:
|
||||
p_version = NullVersion(name)
|
||||
return p_version
|
||||
@ -139,3 +143,10 @@ def get_packager(pkg_info, distro, default_packager_class):
|
||||
p_instance = p_cls(distro, PackageRegistry())
|
||||
FETCHED_PACKAGERS[p_cls] = p_instance
|
||||
return p_instance
|
||||
|
||||
|
||||
def contains_version_check(version):
|
||||
for c in ['==', '>', "<", '<=', '>=']:
|
||||
if version.find(c) != -1:
|
||||
return True
|
||||
return False
|
||||
|
10
anvil/pip.py
10
anvil/pip.py
@ -30,14 +30,10 @@ class Packager(pack.Packager):
|
||||
def _make_pip_name(self, name, version):
|
||||
if version is None:
|
||||
return str(name)
|
||||
found_char = False
|
||||
for c in ['==', '>', "<", '<=', '>=']:
|
||||
if version.find(c) != -1:
|
||||
found_char = True
|
||||
break
|
||||
if found_char:
|
||||
if pack.contains_version_check(version):
|
||||
return "%s%s" % (name, version)
|
||||
return "%s==%s" % (name, version)
|
||||
else:
|
||||
return "%s==%s" % (name, version)
|
||||
|
||||
def _get_pip_command(self):
|
||||
return self.distro.get_command_config('pip')
|
||||
|
@ -36,5 +36,5 @@ class Runner(object):
|
||||
pass
|
||||
|
||||
def status(self, app_name):
|
||||
# Attempt to give the status of a app
|
||||
return STATUS_UNKNOWN
|
||||
# Attempt to give the status of a app + details
|
||||
return (STATUS_UNKNOWN, '')
|
||||
|
@ -83,13 +83,15 @@ class ForkRunner(base.Runner):
|
||||
def status(self, app_name):
|
||||
trace_dir = self.runtime.get_option('trace_dir')
|
||||
if not sh.isdir(trace_dir):
|
||||
return STATUS_UNKNOWN
|
||||
return (STATUS_UNKNOWN, '')
|
||||
(pid_file, stderr_fn, stdout_fn) = self._form_file_names(FORK_TEMPL % (app_name))
|
||||
pid = self._extract_pid(pid_file)
|
||||
stderr = sh.load_file(stderr_fn)
|
||||
stdout = sh.load_file(stderr_fn)
|
||||
if pid and sh.is_running(pid):
|
||||
return STATUS_STARTED
|
||||
return (STATUS_STARTED, (stdout + stderr).strip())
|
||||
else:
|
||||
return STATUS_UNKNOWN
|
||||
return (STATUS_UNKNOWN, (stdout + stderr).strip())
|
||||
|
||||
def _form_file_names(self, file_name):
|
||||
trace_dir = self.runtime.get_option('trace_dir')
|
||||
|
@ -197,8 +197,8 @@ def execute(*cmd, **kwargs):
|
||||
else:
|
||||
# Log it anyway
|
||||
if rc not in check_exit_code:
|
||||
LOG.warn("A failure may of just happened when running command %r [%s] (%s, %s)",
|
||||
str_cmd, rc, stdout, stderr)
|
||||
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('trace_writer')
|
||||
stdout_fn = kwargs.get('stdout_fn')
|
||||
|
@ -212,6 +212,18 @@ def to_bytes(text):
|
||||
return byte_val
|
||||
|
||||
|
||||
def truncate_text(text, max_len, from_bottom=False):
|
||||
if len(text) < max_len:
|
||||
return text
|
||||
if not from_bottom:
|
||||
return (text[0:max_len] + "...")
|
||||
else:
|
||||
text = text[::-1]
|
||||
text = truncate_text(text, max_len)
|
||||
text = text[::-1]
|
||||
return text
|
||||
|
||||
|
||||
def log_object(to_log, logger=None, level=logging.INFO, item_max_len=64):
|
||||
if not to_log:
|
||||
return
|
||||
|
@ -37,7 +37,7 @@ source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = anvil_settings.PROG_NAME.upper()
|
||||
project = 'ANVIL'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
@ -6,13 +6,6 @@ ANVIL Documentation
|
||||
|
||||
.. rubric:: Everything about ANVIL, a set of **python** scripts and utilities to quickly deploy an OpenStack cloud.
|
||||
|
||||
Why the rename?
|
||||
----
|
||||
|
||||
- Helps avoid confusion with devstack.org
|
||||
- Allows our team to focus on any different features
|
||||
- Creates a clearer goal as to where we diverge
|
||||
- More awesomeness?
|
||||
|
||||
----
|
||||
|
||||
@ -26,5 +19,4 @@ Why the rename?
|
||||
topics/qanda
|
||||
topics/knownissues
|
||||
topics/bugshugscode
|
||||
topics/advanced/index
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
==========
|
||||
Adding your own distribution
|
||||
==========
|
||||
|
||||
|
||||
Your mission...
|
||||
=============
|
||||
|
||||
So you have decided you want to venture into the bowels of ANVIL
|
||||
and want to get support for your latest and greatest distribution. This
|
||||
wiki will hopefully make that adventure simpler by listing out the key
|
||||
places, files and configs that may have to be adjusted to get that to
|
||||
work. This tape will self-destruct in 5 seconds. 1..2..3..4..5, boom!
|
||||
|
||||
Steps
|
||||
=====
|
||||
|
||||
Snapshot
|
||||
--------
|
||||
|
||||
One of the most useful things to do will be to get a virtual machine
|
||||
with your distribution and setup a stable state. Create a snapshot of
|
||||
that stable state just in-case you *bork* your machine later on.
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
Now turn ensure you run ``DEBUG/VERBOSE`` logging using ``-vv``. This
|
||||
will be useful to see exactly what actions and commands are being ran
|
||||
instead of the default ``INFO`` level logging which is just meant for
|
||||
simple informational messages about the underlying actions which are
|
||||
occurring.
|
||||
|
||||
Configs
|
||||
-------
|
||||
|
||||
By looking at the config folder ``distros`` you should exactly which
|
||||
packages and pips and commands are needed for each component by looking
|
||||
at a similar distribution. So you first task is to determine exactly
|
||||
what versions are available for your distribution. If a version doesn’t
|
||||
exist the you may need to resort to either using the `pypi`_ index or
|
||||
having to package it yourself. If a version is to new, this is usually
|
||||
ok (your mileage may vary) and if its to old then that might also not be
|
||||
ok (your mileage may vary).
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
Now that you have provided a new `YAML`_ distro file you should be able
|
||||
to run through the simple setup wiki and see if the install will pass.
|
||||
If that does try starting and then seeing if everything has started up
|
||||
correctly.
|
||||
|
||||
.. _pypi: http://pypi.python.org
|
||||
.. _YAML: http://yaml.org/
|
@ -1,60 +0,0 @@
|
||||
==========
|
||||
Adding your own persona
|
||||
==========
|
||||
|
||||
|
||||
Your mission...
|
||||
=============
|
||||
|
||||
So you have decided you want to venture into the bowels of ANVIL
|
||||
and want to alter what is installed/started/stopped, the order of what
|
||||
is installed/started/stopped, what subsystems are activated (or the
|
||||
component options). This wiki will hopefully make that adventure simpler
|
||||
by listing out the key places, files and configs that may have to be
|
||||
adjusted to get that to work. This tape will self-destruct in 5 seconds.
|
||||
1..2..3..4..5, boom!
|
||||
|
||||
Steps
|
||||
=====
|
||||
|
||||
Snapshot
|
||||
--------
|
||||
|
||||
One of the most useful things to do will be to get a virtual machine
|
||||
with your distribution and setup a stable state. Create a snapshot of
|
||||
that stable state just in-case you *bork* your machine later on.
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
Now turn ensure you run ``DEBUG/VERBOSE`` logging using ``-vv``. This
|
||||
will be useful to see exactly what actions and commands are being ran
|
||||
instead of the default ``INFO`` level logging which is just meant for
|
||||
simple informational messages about the underlying actions which are
|
||||
occurring.
|
||||
|
||||
Configs
|
||||
-------
|
||||
|
||||
By looking at the config folder ``personas`` you should a file called
|
||||
``devstack.sh.yaml``. This file contains the component order of
|
||||
installation (ie the ``db`` before ``keystone``), a nice useful
|
||||
description of the persona and subsystems for the previously specified
|
||||
components and any options these components may have. So you first task
|
||||
is to determine exactly what of these you wish to change (if any). Note
|
||||
that changing the component order may not always work (ie typically
|
||||
starting components are dependent, ie the message queue needs to be
|
||||
started before nova). To add in new components check the ``distros``
|
||||
folder to determine exactly what that component is named (typically this
|
||||
is common) and alter the persona file as desired. To alter the
|
||||
``subsystems`` or ``options`` section you will have to jump in the code
|
||||
and check for what these values could be (TODO make that better).
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
Now that you have provided a new `YAML`_ persona file you should be able
|
||||
to run the ``stack`` program with that persona through the ``-p``
|
||||
option.
|
||||
|
||||
.. _YAML: http://yaml.org/
|
@ -1,163 +0,0 @@
|
||||
========
|
||||
Design
|
||||
========
|
||||
|
||||
How it works
|
||||
------------
|
||||
|
||||
ANVIL is based along the following system design
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Having shared components/actions be shared (using object oriented
|
||||
practices)
|
||||
- Having specific actions be isolated to its component (and easily
|
||||
readable)
|
||||
- Being simple enough to read yet following standard python software
|
||||
development practices and patterns
|
||||
|
||||
Directory structure is the following
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Parent classes located in *anvil/component.py*, it contains the
|
||||
root install/uninstall/start/stop classes
|
||||
- Subclasses in *anvil/components/*, it contains the individual
|
||||
install classes for each openstack component
|
||||
- Running modes implementations in *anvil/runners/* (ie fork,
|
||||
screen, upstart)
|
||||
- Packaging implementations in *anvil/packaging/*
|
||||
- Image uploading/registry/management (for glance) in *anvil/image/*
|
||||
- Shared classes and utils in *anvil/*
|
||||
- Main entry point/s in *anvil/progs/*
|
||||
- Other various tools in *tools/*
|
||||
- Configuration in *conf/* (see below)
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
Install object model
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Here is the **install** components (default set only) class hierarchy:
|
||||
|
||||
.. figure:: http://farm8.staticflickr.com/7043/6894250521_d882b770d1_o.png
|
||||
:align: center
|
||||
|
||||
Classes
|
||||
'''''''
|
||||
|
||||
From this example the root classes job are:
|
||||
|
||||
- Python install component
|
||||
- Ensures *pips* are installed (child classes specify which pips)
|
||||
- Ensures python directories (ie *setup.py*) are setup (child classes
|
||||
specify which directories)
|
||||
- Package install component
|
||||
- Installs packages that are required for install (child classes
|
||||
specify which packages)
|
||||
- Sets up and performs parameter replacement on config files (child
|
||||
classes specify which config files)
|
||||
- Sets up symlinks to config or other files (child classes specify
|
||||
these symlinks)
|
||||
- Tracks what was setup so that it can be removed/uninstalled
|
||||
- Component base (used by **all** install/uninstall/start/stop
|
||||
component classes)
|
||||
- Holds configuration object, component name, packaging and other
|
||||
shared members…
|
||||
- Allows for overriding of dependency function and pre-run verification
|
||||
|
||||
Functions
|
||||
'''''''''
|
||||
|
||||
For a install class the following functions are activated (in the
|
||||
following order by *anvil/actions.py*):
|
||||
|
||||
::
|
||||
|
||||
download()
|
||||
|
||||
Performs the main git download (or other download type) to the
|
||||
application target directory.
|
||||
|
||||
::
|
||||
|
||||
configure()
|
||||
|
||||
Configures the components files (symlinks, configuration and logging
|
||||
files…)
|
||||
|
||||
::
|
||||
|
||||
pre_install()
|
||||
|
||||
Child class specific function that can be used to do anything before
|
||||
an install (ie set a ubuntu mysql pre-install root password)
|
||||
|
||||
::
|
||||
|
||||
install()
|
||||
|
||||
Installs distribution packages, python packages (*pip*), sets up
|
||||
python directories (ie *python setup.py develop*) and any other
|
||||
child class specific actions.
|
||||
|
||||
::
|
||||
|
||||
post_install()
|
||||
|
||||
Child class specific function that can be used to do anything after
|
||||
an install (ie run *nova-manage db sync*)
|
||||
|
||||
Other object models
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- `Start object model (for default set only)`_
|
||||
- `Stop object model (for default set only)`_
|
||||
- `Uninstall object model (for default set only)`_
|
||||
|
||||
Configuring
|
||||
-----------
|
||||
|
||||
For those of you that are brave enough to change *stack* here are some
|
||||
starting points.
|
||||
|
||||
conf/stack.ini
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Check out *conf/stack.ini* for various configuration settings applied
|
||||
(branches, git repositories…). Check out the header of that file for how
|
||||
the customized configuration values are parsed and what they may result
|
||||
in.
|
||||
|
||||
conf/distros
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Check out *conf/distros* for the `YAML`_ files that describe
|
||||
pkgs/cmds/pips for various distributions which are required by the
|
||||
different OpenStack components to run correctly. The versions and pip
|
||||
names listed for each distribution should be the correct version that is
|
||||
known to work with a given OpenStack release.
|
||||
|
||||
conf/templates/
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Check out *conf/templates/* for various component specific settings and
|
||||
files. All of these files are *templates* with sections or text that
|
||||
needs to be filled in by the ``stack`` script to become a *complete*
|
||||
file.
|
||||
|
||||
These files may have strings of the format ``%NAME%`` where ``NAME``
|
||||
will most often be adjusted to a real value by the *stack* script.
|
||||
|
||||
An example where this is useful is say for the following line:
|
||||
|
||||
::
|
||||
|
||||
admin_token = %SERVICE_TOKEN%
|
||||
|
||||
Since the script will either prompt for this value (or generate it for
|
||||
you) we can not have this statically set in a configuration file.
|
||||
|
||||
.. _Start object model (for default set only): http://farm8.staticflickr.com/7046/6894981327_a583bcb4fc_o.png
|
||||
.. _Stop object model (for default set only): http://farm8.staticflickr.com/7059/6894981341_e6d4901b20_o.png
|
||||
.. _Uninstall object model (for default set only): http://farm8.staticflickr.com/7177/6894981357_fef65b28d3_o.png
|
||||
.. _YAML: http://yaml.org/
|
@ -1,11 +0,0 @@
|
||||
===============
|
||||
Advanced
|
||||
===============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
addingyourowndistro
|
||||
addingyourownpersona
|
||||
design
|
||||
|
@ -25,13 +25,10 @@ Stable *tags* can also be downloaded:
|
||||
|
||||
https://github.com/yahoo/Openstack-Anvil/tags
|
||||
|
||||
**Note:** that for these tags you may have to edit ``conf/anvil.ini``
|
||||
to point to tags other than ``master``
|
||||
|
||||
Bugs/Features
|
||||
=============
|
||||
|
||||
Please use `github’s issue tracking system`_ or `launchpad’s issue tracking system`_ to report or follow bugs or to discuss features and get support.
|
||||
Please use `launchpad’s issue tracking system`_ to report or follow bugs or to discuss features and get support.
|
||||
|
||||
Hacking
|
||||
=============
|
||||
@ -42,9 +39,8 @@ Feel free to hack but please try to follow the `hacking guidelines`_
|
||||
Discussions
|
||||
===========
|
||||
|
||||
Please either use launchpad’s email system or find us on ``irc.freenode.net`` in channel ``#openstack-anvil`` or in the main openstack dev channel ``#openstack-dev``. Feel free to bug us!
|
||||
Please use launchpad’s blueprint/bug system for contacting us about bugs or new features (or submit them!). Much appreciated!
|
||||
|
||||
.. _apache version 2.0 license: https://github.com/yahoo/Openstack-Anvil/blob/master/LICENSE
|
||||
.. _github’s issue tracking system: https://github.com/yahoo/Openstack-Anvil/issues
|
||||
.. _launchpad’s issue tracking system: http://launchpad.net/anvil
|
||||
.. _hacking guidelines: https://github.com/yahoo/Openstack-Anvil/blob/master/HACKING.md
|
||||
|
@ -2,33 +2,38 @@
|
||||
Features
|
||||
========
|
||||
|
||||
- Supports more than one distribution.
|
||||
|
||||
- Currently RHEL 6.2 (with `epel`_), Ubuntu 11.10, Fedora 16, Ubuntu 12.10 (seems to work)
|
||||
|
||||
- Supports dry-run mode (to see what *would* happen)
|
||||
- Supports varying installation *personas*
|
||||
- A single ``anvil.ini`` file that shows common configuration
|
||||
- Supports install/uninstall/starting/stopping of OpenStack components.
|
||||
|
||||
- In various styles (daemonizing via `forking`_, `screen`_, `upstart`_)
|
||||
|
||||
- Multi distribution installs via a single tool (TODO: fix for folsom)
|
||||
- A single ``anvil.ini`` file that shows common/component configuration
|
||||
- Supports the following *actions* on the various of OpenStack components.
|
||||
#. **Installing**: downloading, installing dependencies (`pypi`_ and distribution packaging specifics)
|
||||
and configuring component files and symlinks
|
||||
#. **Starting**: starting of the components sub-programs with
|
||||
the needed configuration via the common `daemon`_ model (with a ``pid``, ``stderr`` and ``stdout`` file set)
|
||||
#. **Stopping**: stopping of the previously started components
|
||||
#. **Uninstalling**: removing installed configuration, undoing of installed files/directories,
|
||||
and removing of packaging to get back to an initial 'clean' state
|
||||
#. **Testing**: running each components unit tests (and in the future performing a simple set of integration tests)
|
||||
#. **Packaging**: creating a basic set of packages for the desired distributions
|
||||
#. **Status**: checking the status of the running components sub-programs
|
||||
- Supports dry-run mode (to see what *would* happen for each action)
|
||||
- Tracking of all actions taken by a component via tracking like files.
|
||||
- Written in python so it matches the style of other `OpenStack`_ components.
|
||||
- Code decoupling (thus encouraging re-use by others)
|
||||
#. Components/actions are isolated as individual classes (and so on). This
|
||||
decouples component installation from the action and decoupling of the
|
||||
commands/packages/pips the component will use to install itself from the
|
||||
component...
|
||||
#. Supports installation *personas* that define what is to be installed, thus
|
||||
decoupling the 'what' from the 'how'
|
||||
- Extensively documented distribution specifics
|
||||
|
||||
- Packages and pip (with versions known to work!) dependencies
|
||||
- Any needed distribution specific actions (ie service names…)
|
||||
|
||||
- Follows standard software development practices (for everyones sanity).
|
||||
|
||||
- Functions, classes, objects and more (oh my!)
|
||||
- Still *readable* by someone with limited python knowledge.
|
||||
|
||||
- The ability to be unit-tested!
|
||||
- Extensive logging
|
||||
- Progress resuming so that when you install you can ``ctrl+c`` ``./smithy`` and resume later (where applicable).
|
||||
- Extensive logging (and debug mode)
|
||||
|
||||
.. _epel: http://fedoraproject.org/wiki/EPEL
|
||||
.. _forking: http://users.telenet.be/bartl/classicperl/fork/all.html
|
||||
.. _screen: http://www.manpagez.com/man/1/screen/
|
||||
.. _upstart: http://upstart.ubuntu.com/
|
||||
.. _OpenStack: http://openstack.org/
|
||||
.. _pypi: http://pypi.python.org/pypi
|
||||
.. _daemon: http://en.wikipedia.org/wiki/Daemon_(computing)
|
||||
|
@ -16,18 +16,9 @@ Prerequisites
|
||||
Linux
|
||||
-----
|
||||
|
||||
One of the tested Linux distributions (RHEL 6.2, Ubuntu 11.10, Fedora
|
||||
16)
|
||||
One of the tested Linux distributions (RHEL 6.2+ until further updated)
|
||||
|
||||
You can get Ubuntu 11.10 (**64-bit** is preferred) from
|
||||
http://releases.ubuntu.com/11.10/
|
||||
|
||||
You can get RHEL 6.2 (**64-bit** is preferred) from
|
||||
http://rhn.redhat.com/.
|
||||
|
||||
You can get Fedora 16 (**64-bit** is preferred) from
|
||||
https://fedoraproject.org/get-fedora, so don’t worry if you do not have
|
||||
a RHN subscription.
|
||||
You can get RHEL 6.2+ (**64-bit** is preferred) from http://rhn.redhat.com/.
|
||||
|
||||
Networking
|
||||
----------
|
||||
@ -84,14 +75,12 @@ Installation
|
||||
Pre-setup
|
||||
---------
|
||||
|
||||
Since RHEL/Fedora requires a `tty`_ to perform ``sudo`` commands we need
|
||||
Since RHEL requires a `tty`_ to perform ``sudo`` commands we need
|
||||
to disable this so ``sudo`` can run without a `tty`_. This seems needed
|
||||
since nova and other components attempt to do ``sudo`` commands. This
|
||||
isn’t possible in RHEL/Fedora unless you disable this (since those
|
||||
isn’t possible in RHEL unless you disable this (since those
|
||||
instances won’t have a `tty`_ ).
|
||||
|
||||
**For RHEL and Fedora 16:**
|
||||
|
||||
::
|
||||
|
||||
$ sudo visudo
|
||||
@ -127,38 +116,10 @@ This can be typically solved by running the following (and then updating ``anvil
|
||||
$ sudo chmod -R a+rwx /home/openstack
|
||||
|
||||
|
||||
**For Ubuntu:**
|
||||
|
||||
You are off the hook.
|
||||
|
||||
Users
|
||||
-----
|
||||
|
||||
We need to add a admin user so that horizon can run under `apache`_.
|
||||
|
||||
**For Ubuntu:**
|
||||
|
||||
::
|
||||
|
||||
$ apt-get install sudo -y
|
||||
$ sudo adduser horizon
|
||||
$ sudo adduser horizon admin
|
||||
|
||||
**For RHEL/Fedora 16:**
|
||||
|
||||
You are off the hook as long as your user has ``sudo`` access.
|
||||
|
||||
Get git!
|
||||
--------
|
||||
|
||||
**For Ubuntu:**
|
||||
|
||||
::
|
||||
|
||||
$ sudo apt-get install git -y
|
||||
|
||||
**For RHEL/Fedora 16:**
|
||||
|
||||
::
|
||||
|
||||
$ sudo yum install git -y
|
||||
@ -173,52 +134,9 @@ We’ll grab the latest version of ANVIL via git:
|
||||
|
||||
$ git clone git://github.com/yahoo/Openstack-Anvil.git anvil
|
||||
|
||||
Now setup the prerequisites needed to run (select the appropriate shell script for your distro):
|
||||
|
||||
::
|
||||
|
||||
$ cd anvil/warmups && sudo ./$DISTRO.sh
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Apache configuration
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We need to adjust the configuration of ANVIL to reflect the above
|
||||
user (``iff you created a user``).
|
||||
|
||||
Open ``conf/anvil.ini``
|
||||
|
||||
**Change section:**
|
||||
|
||||
::
|
||||
|
||||
[horizon]
|
||||
|
||||
# What user will apache be serving from.
|
||||
#
|
||||
# Root will typically not work (for apache on most distros)
|
||||
# sudo adduser <username> then sudo adduser <username> admin will be what you want to set this up (in ubuntu)
|
||||
# I typically use user "horizon" for ubuntu and the runtime user (who will have sudo access) for RHEL.
|
||||
#
|
||||
# NOTE: If blank the currently executing user will be used.
|
||||
apache_user = ${APACHE_USER:-}
|
||||
|
||||
**To:**
|
||||
|
||||
::
|
||||
|
||||
[horizon]
|
||||
|
||||
# What user will apache be serving from.
|
||||
#
|
||||
# Root will typically not work (for apache on most distros)
|
||||
# sudo adduser <username> then sudo adduser <username> admin will be what you want to set this up (in ubuntu)
|
||||
# I typically use user "horizon" for ubuntu and the runtime user (who will have sudo access) for RHEL.
|
||||
#
|
||||
# NOTE: If blank the currently executing user will be used.
|
||||
apache_user = ${APACHE_USER:-horizon}
|
||||
|
||||
Network configuration
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -269,7 +187,7 @@ Now install *OpenStacks* components by running the following:
|
||||
|
||||
::
|
||||
|
||||
sudo ./smithy -a install -d ~/openstack
|
||||
sudo ./smithy -a install
|
||||
|
||||
You should see a set of distribution packages and/or pips being
|
||||
installed, python setups occurring and configuration files being written
|
||||
@ -285,7 +203,7 @@ Now that you have installed *OpenStack* you can now start your
|
||||
|
||||
::
|
||||
|
||||
sudo ./smithy -a start -d ~/openstack
|
||||
sudo ./smithy -a start
|
||||
|
||||
If you desire more informational output add a ``-v`` or a ``-vv`` to
|
||||
that command.
|
||||
@ -332,29 +250,28 @@ EC2 apis run the following to get your EC2 certs:
|
||||
|
||||
::
|
||||
|
||||
euca.sh $OS_USERNAME $OS_TENANT_NAME
|
||||
./euca.sh $OS_USERNAME $OS_TENANT_NAME
|
||||
|
||||
It broke?
|
||||
~~~~~~~~~
|
||||
|
||||
*Otherwise* you may have to look at the output of what was started. To
|
||||
accomplish this you may have to log at the ``stderr`` and ``stdout``
|
||||
that is being generated from the running *OpenStack* process (by default
|
||||
they are forked as daemons). For this information check the output of
|
||||
the start command for a line like
|
||||
``Check * for traces of what happened``. This is usually a good starting
|
||||
point, to check out those files contents and then look up the files that
|
||||
contain the applications `PID`_ and ``stderr`` and ``stdout``.
|
||||
First run the following to check the status of each component.
|
||||
|
||||
If the install section had warning messages or exceptions were thrown
|
||||
there, that may also be the problem. Sometimes running the uninstall
|
||||
section below will clean this up, your mileage may vary though.
|
||||
::
|
||||
|
||||
Another tip is to edit run with more verbose logging by running with the
|
||||
following ``-v`` option or the ``-vv`` option. This may give you more
|
||||
insights by showing you what was executed/installed/configured
|
||||
(uninstall & start by installing again to get the additional logging
|
||||
output).
|
||||
sudo ./smithy -a status
|
||||
|
||||
If you do not see all green status then you should run the following and see
|
||||
if any of the ``stderr`` and ``stdout`` files will give you more information
|
||||
about what is occuring
|
||||
|
||||
::
|
||||
|
||||
sudo ./smithy -a status --show
|
||||
|
||||
This will dump out those files (truncated to not be to verbose) so that anything
|
||||
peculaliar can be seen. If nothing can be then go to the installation directory (typically ``~/openstack``)
|
||||
and check the ``traces`` directory of each component and check if anything looks fishy.
|
||||
|
||||
Stopping
|
||||
--------
|
||||
@ -364,7 +281,7 @@ the following:
|
||||
|
||||
::
|
||||
|
||||
sudo ./smithy -a stop -d ~/openstack
|
||||
sudo ./smithy -a stop
|
||||
|
||||
You should see a set of stop actions happening and ``stderr`` and
|
||||
``stdout`` and ``pid`` files being removed (if you desire more
|
||||
@ -391,7 +308,7 @@ can uninstall them by running the following:
|
||||
|
||||
::
|
||||
|
||||
sudo ./smithy -a uninstall -d ~/openstack
|
||||
sudo ./smithy -a uninstall
|
||||
|
||||
You should see a set of packages, configuration and directories, being
|
||||
removed (if you desire more informational output add a ``-v`` or a
|
||||
|
@ -1,24 +1,19 @@
|
||||
===============
|
||||
Goals
|
||||
Goals
|
||||
===============
|
||||
|
||||
- To aid developers getting involved with `OpenStack`_!
|
||||
- To quickly build developer `OpenStack`_ environments in a clean
|
||||
environment (as well as start, stop, and uninstall those
|
||||
environments) with as little baggage as possible.
|
||||
- To describe working configurations of `OpenStack`_.
|
||||
|
||||
- Which code branches work together?
|
||||
- What do config files look like for those branches?
|
||||
- What packages are needed for installation for a given
|
||||
distribution?
|
||||
- How is a component installed/configured/ran?
|
||||
|
||||
- To make it easier for developers to dive into `OpenStack`_ so that
|
||||
they can productively contribute without having to understand every
|
||||
part of the system at once.
|
||||
- To make it easy to prototype cross-project features.
|
||||
- To have an installer that works!
|
||||
|
||||
|
||||
.. _OpenStack: http://openstack.org/
|
||||
|
||||
|
@ -14,10 +14,6 @@ There is a script in ``tools/clear-net-ubuntu.sh`` that might help with this.
|
||||
RHEL 6.2
|
||||
--------
|
||||
|
||||
- *numpy* (for novnc) pulls in *python-nose* which we are installing
|
||||
from *EPEL* and *symlinking* so that we don’t have to modify github
|
||||
code directly but the *numpy* dependency can’t be installed with the
|
||||
previous symlink. We are currently just using *pip* to fix this.
|
||||
- Fixing up the network on uninstall doesn’t seem to be 100% correct
|
||||
|
||||
We might need a script like the ``tools/clear-net-ubuntu.sh`` to help in this situation.
|
||||
|
@ -4,11 +4,6 @@
|
||||
Questions and Answers
|
||||
===============
|
||||
|
||||
Can I use ANVIL for production?
|
||||
------------------------------------
|
||||
|
||||
Up to u! Beware of the sea and the black waters!
|
||||
|
||||
How do I get program usage?
|
||||
---------------------------
|
||||
|
||||
@ -19,29 +14,11 @@ How do I get program usage?
|
||||
How do I run a specific OpenStack milestone?
|
||||
--------------------------------------------
|
||||
|
||||
OpenStack milestones have tags set in the git repo. Set the appropriate
|
||||
setting in the **branch** variables in *conf/anvil.ini*.
|
||||
OpenStack milestones have tags set in the git repo. Anvil also has the same
|
||||
tags so please checkout the corresponding tag for anvil to match the OpenStack
|
||||
milestone you wish to use.
|
||||
|
||||
**Note:** Swift is on its own release schedule so pick a tag in the
|
||||
Swift repo that is just before the milestone release.
|
||||
|
||||
For example:
|
||||
|
||||
::
|
||||
|
||||
# Quantum client git repo
|
||||
quantum_client_repo = git://github.com/openstack/python-quantumclient.git
|
||||
quantum_client_branch = essex-3
|
||||
|
||||
# Melange service
|
||||
melange_repo = git://github.com/openstack/melange.git
|
||||
melange_branch = essex-3
|
||||
|
||||
# Python melange client library
|
||||
melangeclient_repo = git://github.com/openstack/python-melangeclient.git
|
||||
melangeclient_branch = essex-3
|
||||
|
||||
OMG the images take forever to download!
|
||||
`OMG` the images take forever to download!
|
||||
----------------------------------------
|
||||
|
||||
Sometimes the images that will be uploaded to glance take a long time to
|
||||
|
@ -37,22 +37,6 @@ To resolve this the following seems to work:
|
||||
sudo apt-get remove --purge $MYSQL_PKGS
|
||||
|
||||
|
||||
Libguestfs not syncing
|
||||
---------------------
|
||||
|
||||
On RHEL 6.2 people have seen files not being synced when the temporary file location is unmounted.
|
||||
|
||||
Getting a newer version of libguestfs seems to help. To do this follow the ``README`` at
|
||||
http://people.redhat.com/~rjones/libguestfs-RHEL-6.3-preview/. Hopefully this will not be a problem
|
||||
on RHEL 6.3.
|
||||
|
||||
Then run:
|
||||
|
||||
::
|
||||
|
||||
sudo yum -y install libguestfs* guestfs*
|
||||
|
||||
|
||||
Horizon dead on start
|
||||
---------------------
|
||||
|
||||
|
@ -21,8 +21,8 @@ will do (with installation in ``~/openstack``) try:
|
||||
|
||||
$ sudo ./smithy -d ~/openstack -a install --dryrun
|
||||
|
||||
With more information/debugging/auditing output try:
|
||||
With more information via debug statements output try:
|
||||
|
||||
::
|
||||
|
||||
$ sudo ./smithy -d ~/openstack -a install -vv
|
||||
$ sudo ./smithy -d ~/openstack -a install -v
|
||||
|
@ -2,11 +2,13 @@
|
||||
Important!
|
||||
==========
|
||||
|
||||
**Warning:** Be sure to carefully read ``smithy`` and any other scripts
|
||||
|
||||
Warning!
|
||||
==========
|
||||
|
||||
Be sure to carefully read ``smithy`` and any other scripts
|
||||
you execute before you run them, as they install software and may alter
|
||||
your networking configuration. We strongly recommend that you run
|
||||
``smithy`` in a clean and disposable virtual machine when you are first
|
||||
getting started.
|
||||
your networking configuration.
|
||||
|
||||
.. _epel: http://fedoraproject.org/wiki/EPEL
|
||||
.. _forking: http://users.telenet.be/bartl/classicperl/fork/all.html
|
||||
|
8
smithy
8
smithy
@ -230,7 +230,10 @@ def run(args):
|
||||
if config.opts_cache:
|
||||
LOG.info("After action %s your settings which were applied are:", colorizer.quote(action))
|
||||
table = OrderedDict()
|
||||
for section in sorted(list((config.opts_read + config.opts_set).keys())):
|
||||
all_read_set = {}
|
||||
all_read_set.update(config.opts_read)
|
||||
all_read_set.update(config.opts_set)
|
||||
for section in sorted(list(all_read_set.keys())):
|
||||
options = set()
|
||||
if section in config.opts_read:
|
||||
options.update(list(config.opts_read[section]))
|
||||
@ -238,8 +241,7 @@ def run(args):
|
||||
options.update(list(config.opts_set[section]))
|
||||
option_values = {}
|
||||
for option in options:
|
||||
cache_key = cfg.make_id(section, option)
|
||||
option_values[cache_key] = config.opts_cache[cache_key]
|
||||
option_values[option] = config.opts_cache[cfg.make_id(section, option)]
|
||||
table[section] = option_values
|
||||
utils.log_object(table, item_max_len=80)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user