282 lines
9.4 KiB
Python
Executable File
282 lines
9.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import operator
|
|
import os
|
|
import os.path
|
|
import sys
|
|
|
|
#TODO is this needed?
|
|
sys.path.append("devstack")
|
|
|
|
import Logger
|
|
import Options
|
|
from Util import (welcome, rcf8222date, determine_os, get_pkg_list, fetch_deps)
|
|
from Util import (NOVA, GLANCE, QUANTUM, SWIFT, KEYSTONE, HORIZON, DB, RABBIT,
|
|
INSTALL, UNINSTALL, START, STOP,
|
|
ACTIONS, COMPONENT_NAMES, NAMES_PRIORITY,
|
|
UBUNTU11, RHEL6,
|
|
STACK_CFG_LOC)
|
|
from Shell import (mkdir, joinpths, unlink)
|
|
from Config import (EnvConfigParser)
|
|
from Exceptions import (NoTraceException)
|
|
|
|
import Glance
|
|
import Horizon
|
|
import Keystone
|
|
import Nova
|
|
import Quantum
|
|
import Config
|
|
import Swift
|
|
import Db
|
|
import Rabbit
|
|
|
|
LOG = Logger.getLogger("install")
|
|
|
|
#this determines what classes to use to install/uninstall/...
|
|
ACTION_CLASSES = {
|
|
INSTALL: {
|
|
NOVA: Nova.NovaInstaller,
|
|
GLANCE: Glance.GlanceInstaller,
|
|
QUANTUM: Quantum.QuantumInstaller,
|
|
SWIFT: Swift.SwiftInstaller,
|
|
HORIZON: Horizon.HorizonInstaller,
|
|
KEYSTONE: Keystone.KeystoneInstaller,
|
|
DB: Db.DBInstaller,
|
|
RABBIT: Rabbit.RabbitInstaller,
|
|
},
|
|
UNINSTALL: {
|
|
NOVA: Nova.NovaUninstaller,
|
|
GLANCE: Glance.GlanceUninstaller,
|
|
QUANTUM: Quantum.QuantumUninstaller,
|
|
SWIFT: Swift.SwiftUninstaller,
|
|
HORIZON: Horizon.HorizonUninstaller,
|
|
KEYSTONE: Keystone.KeystoneUninstaller,
|
|
DB: Db.DBUninstaller,
|
|
RABBIT: Rabbit.RabbitUninstaller,
|
|
},
|
|
START: {
|
|
NOVA: Nova.NovaRuntime,
|
|
GLANCE: Glance.GlanceRuntime,
|
|
QUANTUM: Quantum.QuantumRuntime,
|
|
SWIFT: Swift.SwiftRuntime,
|
|
HORIZON: Horizon.HorizonRuntime,
|
|
KEYSTONE: Keystone.KeystoneRuntime,
|
|
DB: Db.DBRuntime,
|
|
RABBIT: Rabbit.RabbitRuntime,
|
|
},
|
|
STOP: {
|
|
NOVA: Nova.NovaRuntime,
|
|
GLANCE: Glance.GlanceRuntime,
|
|
QUANTUM: Quantum.QuantumRuntime,
|
|
SWIFT: Swift.SwiftRuntime,
|
|
HORIZON: Horizon.HorizonRuntime,
|
|
KEYSTONE: Keystone.KeystoneRuntime,
|
|
DB: Db.DBRuntime,
|
|
RABBIT: Rabbit.RabbitRuntime,
|
|
},
|
|
}
|
|
|
|
#actions which need dependent actions to occur
|
|
DEP_ACTIONS_NEEDED = set([START, STOP, INSTALL])
|
|
|
|
|
|
def get_package_manager_class(distro):
|
|
klass = None
|
|
if(distro == UBUNTU11):
|
|
#late import required
|
|
#TODO better way to do this?
|
|
from packaging import Apt
|
|
klass = Apt.AptPackager
|
|
elif(distro == RHEL6):
|
|
#late import required
|
|
#TODO better way to do this?
|
|
from packaging import Yum
|
|
klass = Yum.YumPackager
|
|
return klass
|
|
|
|
|
|
def get_config(action):
|
|
LOG.info("Loading config from %s" % (STACK_CFG_LOC))
|
|
cfg = EnvConfigParser()
|
|
cfg.read(STACK_CFG_LOC)
|
|
return cfg
|
|
|
|
|
|
def print_cfgs(cfg, action):
|
|
cfg_str = str(cfg).strip()
|
|
if(len(cfg)):
|
|
LOG.info("After %s your config is:" % (action))
|
|
LOG.info(cfg_str)
|
|
|
|
|
|
def runner(action_name, component_set, distro, root_dir, program_args):
|
|
#have to make the root dir....
|
|
if(action_name == INSTALL):
|
|
mkdir(root_dir)
|
|
pkg_manager_cls = get_package_manager_class(distro)
|
|
pkg_manager = pkg_manager_cls()
|
|
config = get_config(action_name)
|
|
LOG.info("Will %s [%s] using root directory %s" % (action_name, ", ".join(component_set), root_dir))
|
|
results = list()
|
|
class_lookup = ACTION_CLASSES.get(action_name)
|
|
force = program_args.get('force', False)
|
|
for c in component_set:
|
|
klass = class_lookup.get(c)
|
|
instance = klass(components=component_set, distro=distro, pkg=pkg_manager, cfg=config, root=root_dir)
|
|
if(action_name == INSTALL):
|
|
LOG.info("Downloading %s." % (c))
|
|
instance.download()
|
|
LOG.info("Configuring %s." % (c))
|
|
instance.configure()
|
|
LOG.info("Installing %s." % (c))
|
|
trace = instance.install()
|
|
if(trace):
|
|
LOG.info("Finished install of %s - check %s for traces of what happened." % (c, trace))
|
|
results.append(trace)
|
|
else:
|
|
LOG.info("Finished install of %s" % (c))
|
|
elif(action_name == STOP):
|
|
try:
|
|
LOG.info("Stopping %s." % (c))
|
|
instance.stop()
|
|
LOG.info("Finished stop of %s" % (c))
|
|
except NoTraceException, e:
|
|
if(force):
|
|
LOG.info("Passing on stopping %s since no trace file was found." % (c))
|
|
else:
|
|
raise
|
|
elif(action_name == START):
|
|
LOG.info("Starting %s." % (c))
|
|
trace_locs = instance.start() or list()
|
|
LOG.info("Finished start of %s - check [%s] for traces of what happened." % (c, ", ".join(trace_locs)))
|
|
if(trace_locs):
|
|
results = results + trace_locs
|
|
elif(action_name == UNINSTALL):
|
|
try:
|
|
LOG.info("Unconfiguring %s." % (c))
|
|
instance.unconfigure()
|
|
LOG.info("Uninstalling %s." % (c))
|
|
instance.uninstall()
|
|
except NoTraceException, e:
|
|
if(force):
|
|
LOG.info("Passing on uninstalling %s since no trace file was found." % (c))
|
|
else:
|
|
raise
|
|
#display any configs touched...
|
|
print_cfgs(config, action_name)
|
|
#attempt to remove the root dir (might fail if not empty)
|
|
if(action_name == UNINSTALL):
|
|
try:
|
|
os.rmdir(root_dir)
|
|
except OSError, e:
|
|
pass
|
|
return results
|
|
|
|
|
|
def resolve_dependencies(action, components):
|
|
if(action in DEP_ACTIONS_NEEDED):
|
|
new_components = list()
|
|
for c in components:
|
|
component_deps = list(set(fetch_deps(c)))
|
|
if(len(component_deps)):
|
|
LOG.info("Having to %s [%s] since they are dependencies for %s." % (action, ", ".join(component_deps), c))
|
|
new_components = new_components + component_deps
|
|
new_components.append(c)
|
|
return set(new_components)
|
|
else:
|
|
return set(components)
|
|
|
|
|
|
def check_root(action, rootdir):
|
|
if(action == INSTALL):
|
|
root_there = False
|
|
if(os.path.isdir(rootdir)):
|
|
sublisting = os.listdir(rootdir)
|
|
if(len(sublisting) != 0):
|
|
#something exists, not good
|
|
root_there = True
|
|
if(root_there):
|
|
LOG.error("Root directory [%s] already exists (and it's not empty)! Please remove it or uninstall components!" % (rootdir))
|
|
return False
|
|
else:
|
|
return True
|
|
else:
|
|
return True
|
|
|
|
|
|
def prioritize_components(action, components):
|
|
#get the right component order (by priority)
|
|
mporder = dict()
|
|
for c in components:
|
|
priority = NAMES_PRIORITY.get(c)
|
|
if(priority == None):
|
|
priority = sys.maxint
|
|
mporder[c] = priority
|
|
#sort by priority value
|
|
priority_order = sorted(mporder.iteritems(), key=operator.itemgetter(1))
|
|
#extract the right order
|
|
component_order = [x[0] for x in priority_order]
|
|
return component_order
|
|
|
|
def main():
|
|
me = __file__
|
|
args = Options.parse()
|
|
components = args.pop("component") or []
|
|
if(len(components) == 0):
|
|
components = list(COMPONENT_NAMES)
|
|
components = set([x.lower() for x in components])
|
|
components = set(COMPONENT_NAMES).intersection(components)
|
|
if(len(components) == 0):
|
|
LOG.error("No valid components specified!")
|
|
LOG.info("Perhaps you should try %s --help" % (me))
|
|
return 1
|
|
action = args.pop("action") or ""
|
|
#normalize the action
|
|
action = action.strip().lower()
|
|
if(not (action in ACTIONS)):
|
|
LOG.error("No valid action specified!")
|
|
LOG.info("Perhaps you should try %s --help" % (me))
|
|
return 1
|
|
rootdir = args.pop("dir") or ""
|
|
if(len(rootdir) == 0 or not check_root(action, rootdir)):
|
|
LOG.error("No valid root directory specified!")
|
|
LOG.info("Perhaps you should try %s --help" % (me))
|
|
return 1
|
|
#ensure os/distro is known
|
|
(install_os, plt) = determine_os()
|
|
if(install_os == None):
|
|
LOG.error("Unsupported operating system/distro: %s" % (plt))
|
|
return 1
|
|
#start it
|
|
welcome(action)
|
|
#need to figure out dependencies for components (if any)
|
|
components = resolve_dependencies(action, components)
|
|
#get the right component order (by priority)
|
|
components = prioritize_components(action, components)
|
|
#now do it!
|
|
LOG.info("Starting action [%s] on %s for operating system/distro [%s]" % (action, rcf8222date(), install_os))
|
|
resultList = runner(action, components, install_os, rootdir, args)
|
|
LOG.info("Finished action [%s] on %s" % (action, rcf8222date()))
|
|
if(resultList and len(resultList)):
|
|
msg = "Check [%s] for traces of what happened." % (", ".join(resultList))
|
|
LOG.info(msg)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
rc = main()
|
|
sys.exit(rc)
|