Refactored packstack.installer.setup_sequences

Change-Id: Ie4b039ed9c4996240c20a033d91b936c8113214b
This commit is contained in:
Martin Magr
2013-05-07 15:39:53 +02:00
parent e2fc1f7627
commit 4e4149db97
24 changed files with 274 additions and 216 deletions

View File

@@ -41,10 +41,5 @@ EXEC_CHKCONFIG = "chkconfig"
EXEC_SERVICE = "service" EXEC_SERVICE = "service"
EXEC_IP = "ip" EXEC_IP = "ip"
# text colors
NO_COLOR = "\033[0m"
COLORS = {'red': "\033[0;31m", 'green': "\033[92m", 'blue': "\033[94m",
'yellow': "\033[93m"}
# space len size for color print # space len size for color print
SPACE_LEN = 70 SPACE_LEN = 70

View File

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
"""
Base class for steps & sequences
"""
import re
import sys
import logging
import traceback
from .. import utils
from ..exceptions import SequenceError
class Step(object):
"""
Wrapper for function representing single setup step.
"""
def __init__(self, name, function, title=None):
self.name = name
self.title = title or ('Step: %s' % name)
# process step function
if function and not callable(function):
raise SequenceError("Function object have to be callable. "
"Object %s is not callable." % function)
self.function = function
def run(self, config=None):
config = config or {}
# TO-DO: complete logger name when logging will be setup correctly
logger = logging.getLogger()
logger.debug('Running step %s.' % self.name)
sys.stdout.write('%s...' % self.title)
sys.stdout.flush()
# count space needed for title print
title = self.title
for color in utils.COLORS.itervalues():
title = re.sub(re.escape(color), '', title)
space = 70 - len(title)
# execute and report state
state_fmt = '[ %s ]\n'
try:
self.function(config)
except Exception, ex:
logger.debug(traceback.format_exc())
state = state_fmt % utils.color_text('ERROR', 'red')
sys.stdout.write(state.rjust(space))
sys.stdout.flush()
raise SequenceError(str(ex))
else:
state = state_fmt % utils.color_text('DONE', 'green')
sys.stdout.write(state.rjust(space))
sys.stdout.flush()
class Sequence(object):
"""
Wrapper for sequence of setup steps.
"""
def __init__(self, name, steps, title=None, condition=None,
cond_match=None):
self.name = name
self.title = title
self.condition = condition
self.cond_match = cond_match
# process sequence steps
self.steps = utils.SortedDict()
for step in steps:
name, func = step['name'], step['function']
self.steps[name] = Step(name, func, title=step.get('title'))
def validate_condition(self, config):
"""
Returns True if config option condition has value given
in cond_match. Otherwise returns False.
"""
if not self.condition:
return True
result = config.get(self.condition)
return result == self.cond_match
def run(self, config=None, step=None):
"""
Runs sequence of steps. Runs only specific step if step's name
is given via 'step' parameter.
"""
config = config or {}
if not self.validate_condition(config):
return
if step:
self.steps[step].run(config=config)
return
logger = logging.getLogger()
logger.debug('Running sequence %s.' % self.name)
if self.title:
sys.stdout.write('%s\n' % self.title)
sys.stdout.flush()
for step in self.steps.itervalues():
step.run(config=config)

View File

@@ -64,5 +64,11 @@ class ScriptRuntimeError(PackStackError):
""" """
pass pass
class ExecuteRuntimeError(PackStackError): class ExecuteRuntimeError(PackStackError):
"""Raised when utils.execute does not end successfully.""" """Raised when utils.execute does not end successfully."""
class SequenceError(PackStackError):
"""Exception for errors during setup sequence run."""
pass

View File

@@ -3,7 +3,15 @@ Controller class is a SINGLETON which handles all groups, params, sequences,
steps and replaces the CONF dictionary. steps and replaces the CONF dictionary.
""" """
from setup_params import Group from setup_params import Group
from setup_sequences import Sequence from .core.sequences import Sequence
def steps_new_format(steplist):
# we have to duplicate title to name parameter and also only sigle
# function is allowed in new step
return [{'name': i['title'], 'title': i['title'],
'function': i['functions'][0]} for i in steplist]
class Controller(object): class Controller(object):
@@ -64,27 +72,32 @@ class Controller(object):
# Sequences and steps # Sequences and steps
def addSequence(self, desc, cond, cond_match, steps): def addSequence(self, desc, cond, cond_match, steps):
self.__SEQUENCES.append(Sequence(desc, cond, cond_match, steps)) self.__SEQUENCES.append(Sequence(desc, steps_new_format(steps),
condition=cond,
cond_match=cond_match))
def insertSequence(self, desc, cond, cond_match, steps, index=0): def insertSequence(self, desc, cond, cond_match, steps, index=0):
self.__SEQUENCES.insert(index, Sequence(desc, cond, cond_match, steps)) self.__SEQUENCES.insert(index, Sequence(desc,
steps_new_format(steps),
condition=cond,
cond_match=cond_match))
def getAllSequences(self): def getAllSequences(self):
return self.__SEQUENCES return self.__SEQUENCES
def runAllSequences(self): def runAllSequences(self):
for sequence in self.__SEQUENCES: for sequence in self.__SEQUENCES:
sequence.run() sequence.run(self.CONF)
def getSequenceByDesc(self, desc): def getSequenceByDesc(self, desc):
for sequence in self.getAllSequences(): for sequence in self.getAllSequences():
if sequence.getDescription() == desc: if sequence.name == desc:
return sequence return sequence
return None return None
def __getSequenceIndexByDesc(self, desc): def __getSequenceIndexByDesc(self, desc):
for sequence in self.getAllSequences(): for sequence in self.getAllSequences():
if sequence.getDescription() == desc: if sequence.name == desc:
return self.__SEQUENCES.index(sequence) return self.__SEQUENCES.index(sequence)
return None return None
@@ -97,7 +110,10 @@ class Controller(object):
index = self.__getSequenceIndexByDesc(sequenceName) index = self.__getSequenceIndexByDesc(sequenceName)
if index == None: if index == None:
index = len(self.getAllSequences()) index = len(self.getAllSequences())
self.__SEQUENCES.insert(index, Sequence(desc, cond, cond_match, steps)) self.__SEQUENCES.insert(index, Sequence(desc,
steps_new_format(steps),
condition=cond,
cond_match=cond_match))
# Groups and params # Groups and params
def addGroup(self, group, params): def addGroup(self, group, params):

View File

@@ -1,163 +0,0 @@
"""
Base class for steps & sequences
"""
import logging
import sys
import re
import string
import traceback
import basedefs
import output_messages
from . import utils
class Step(object):
def __init__(self, title=None, functions=[]):
self.__TITLE = None
self.__FUNCTIONS = []
if title:
if not isinstance(title, str):
raise TypeError("step's title should be of string type instead of %s" % type(title))
if not isinstance(functions, list):
raise TypeError("step's function should be of list type instead of %s" % type(functions))
for function in functions:
if not callable(function):
raise TypeError("All parameters which pass as functions should be callable. %s is not callable" % function)
self.setTitle(title)
for function in functions:
self.addFunction(function)
def setTitle(self, title):
self.__TITLE = title
def getTitle(self):
return self.__TITLE
def addFunction(self, function):
self.__FUNCTIONS.append(function)
def removeFunction(self, function):
self.__FUNCTIONS.remove(function)
def getFunctions(self):
return self.__FUNCTIONS
def run(self):
# keep relative space
# allow newline chars in title. This is useful for plugins
alignedTitle = self.getTitle()
if re.search('\n', alignedTitle):
alignedTitle = self.getTitle().split('\n')[-1]
for color in basedefs.COLORS:
if color in alignedTitle:
alignedTitle = string.replace(alignedTitle, color, '')
spaceLen = basedefs.SPACE_LEN - len(alignedTitle)
print "%s..."%(self.getTitle()),
sys.stdout.flush()
for function in self.getFunctions():
try:
logging.debug("running %s"%(function.func_name))
function()
except:
logging.debug(traceback.format_exc())
raise
print ("[ " + utils.color_text(output_messages.INFO_DONE, 'green') + " ]").rjust(spaceLen)
class Sequence(object):
"""
Gets 4 parameters:
description, condition's name/function, condition's expected result and steps
steps should be a list of dictionaries, example:
[ { 'title' : 'step1's title',
'functions' : [ func1, func2, func3 ] },
{ 'title' : 'step2's tittle',
'functions' : [ func4, func6 ] } ]
"""
def __init__(self, desc=None, cond=[], cond_match=[], steps=[]):
self.__DESCRIPTION = None
self.__CONDITION = None
self.__COND_MATCH = None
self.__STEPS = []
self.setDescription(desc)
self.setCondition(cond, cond_match)
for step in steps:
if not isinstance(step, dict):
raise TypeError("step should be of dictionary type instead of %s" % type(step))
self.addStep(step['title'], step['functions'])
def addStep(self, title, functions):
self.__STEPS.append(Step(title, functions))
def setDescription(self, desc):
self.__DESCRIPTION = desc
def getDescription(self):
return self.__DESCRIPTION
def getSteps(self):
return self.__STEPS
def getStepByTitle(self, stepTitle):
for step in self.__STEPS:
if step.getTitle == stepTitle:
return step
return None
def setCondition(self, cond, cond_match):
for item in [cond, cond_match]:
if not isinstance(item, list):
raise TypeError("supplied parameter should be of list type instead of %s" % type(item))
self.__CONDITION = cond
self.__COND_MATCH = cond_match
def __validateCondition(self):
"""
Both _CONDITION & _COND_MATCH are lists.
if any of them is a function that needs to be run, the first member
of the list is the function and the rest of the members in that list
are the params for the said function
i.e. self._CONDITION = [function, arg1, arg2]
will be executed as function(arg1, arg2)
if the first member of the list is not a function. we handle it
as anything else (i.e. string/bool etc)
"""
if len(self.__CONDITION) < 1 and len(self.__COND_MATCH) < 1:
return True
condResult = None
condMatchResult = None
if callable(self.__CONDITION[0]):
condResult = self.__CONDITION[0](*self.__CONDITION[1:])
else:
condResult = self.__CONDITION[0]
if callable(self.__COND_MATCH[0]):
condMatchResult = self.__COND_MATCH[0](*self.__COND_MATCH[1:])
else:
condMatchResult = self.__COND_MATCH[0]
if condResult == condMatchResult:
return True
return False
def removeStepByTitle(self, stepTitle):
self.__STEPS.remove(stepTitle)
def run(self):
if self.__validateCondition():
for step in self.__STEPS:
step.run()
def runStepByTitle(self, stepTitle):
step = self.getStepByTitle(stepTitle)
step.run()
def listStepsByTitle(self):
output = []
for step in self.__STEPS:
output.append(step.getTitle())
return output

View File

@@ -4,11 +4,11 @@ from .datastructures import SortedDict
from .decorators import retry from .decorators import retry
from .network import get_localhost_ip, host2ip, force_ip, device_from_ip from .network import get_localhost_ip, host2ip, force_ip, device_from_ip
from .shell import ScriptRunner, execute from .shell import ScriptRunner, execute
from .strings import color_text, mask_string from .strings import COLORS, color_text, mask_string
__all__ = ('SortedDict', __all__ = ('SortedDict',
'retry', 'retry',
'ScriptRunner', 'execute', 'ScriptRunner', 'execute',
'get_localhost_ip', 'host2ip', 'force_ip', 'device_from_ip', 'get_localhost_ip', 'host2ip', 'force_ip', 'device_from_ip',
'color_text', 'mask_string') 'COLORS', 'color_text', 'mask_string')

View File

@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .. import basedefs
STR_MASK = '*' * 8 STR_MASK = '*' * 8
COLORS = {'nocolor': "\033[0m", 'red': "\033[0;31m",
'green': "\033[92m", 'blue': "\033[94m",
'yellow': "\033[93m"}
def color_text(text, color): def color_text(text, color):
@@ -11,7 +12,7 @@ def color_text(text, color):
Returns given text string with appropriate color tag. Allowed values Returns given text string with appropriate color tag. Allowed values
for color parameter are 'red', 'blue', 'green' and 'yellow'. for color parameter are 'red', 'blue', 'green' and 'yellow'.
""" """
return '%s%s%s' % (basedefs.COLORS[color], text, basedefs.NO_COLOR) return '%s%s%s' % (COLORS[color], text, COLORS['nocolor'])
def mask_string(unmasked, mask_list=None, replace_list=None): def mask_string(unmasked, mask_list=None, replace_list=None):

View File

@@ -136,12 +136,12 @@ def initSequences(controller):
] ]
controller.addSequence("Installing OpenStack Cinder", [], [], cinder_steps) controller.addSequence("Installing OpenStack Cinder", [], [], cinder_steps)
def install_cinder_deps(): def install_cinder_deps(config):
server = utils.ScriptRunner(controller.CONF['CONFIG_CINDER_HOST']) server = utils.ScriptRunner(controller.CONF['CONFIG_CINDER_HOST'])
server.append("rpm -q %(package)s || yum install -y %(package)s" % {'package': "lvm2"}) server.append("rpm -q %(package)s || yum install -y %(package)s" % {'package': "lvm2"})
server.execute() server.execute()
def check_cinder_vg(): def check_cinder_vg(config):
cinders_volume = 'cinder-volumes' cinders_volume = 'cinder-volumes'
@@ -211,13 +211,13 @@ def check_cinder_vg():
raise exceptions.MissingRequirements(err) raise exceptions.MissingRequirements(err)
def create_keystone_manifest(): def create_keystone_manifest(config):
manifestfile = "%s_keystone.pp" % controller.CONF['CONFIG_KEYSTONE_HOST'] manifestfile = "%s_keystone.pp" % controller.CONF['CONFIG_KEYSTONE_HOST']
manifestdata = getManifestTemplate("keystone_cinder.pp") manifestdata = getManifestTemplate("keystone_cinder.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def create_manifest(): def create_manifest(config):
manifestfile = "%s_cinder.pp" % controller.CONF['CONFIG_CINDER_HOST'] manifestfile = "%s_cinder.pp" % controller.CONF['CONFIG_CINDER_HOST']
manifestdata = getManifestTemplate("cinder.pp") manifestdata = getManifestTemplate("cinder.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)

View File

@@ -109,7 +109,7 @@ def initSequences(controller):
controller.addSequence("Installing OpenStack Horizon", [], [], steps) controller.addSequence("Installing OpenStack Horizon", [], [], steps)
def createmanifest(): def createmanifest(config):
controller.CONF["CONFIG_HORIZON_SECRET_KEY"] = uuid.uuid4().hex controller.CONF["CONFIG_HORIZON_SECRET_KEY"] = uuid.uuid4().hex
horizon_host = controller.CONF['CONFIG_HORIZON_HOST'] horizon_host = controller.CONF['CONFIG_HORIZON_HOST']
manifestfile = "%s_horizon.pp" % horizon_host manifestfile = "%s_horizon.pp" % horizon_host

View File

@@ -87,12 +87,12 @@ def initSequences(controller):
] ]
controller.addSequence("Installing OpenStack Glance", [], [], glancesteps) controller.addSequence("Installing OpenStack Glance", [], [], glancesteps)
def createkeystonemanifest(): def createkeystonemanifest(config):
manifestfile = "%s_keystone.pp" % controller.CONF['CONFIG_KEYSTONE_HOST'] manifestfile = "%s_keystone.pp" % controller.CONF['CONFIG_KEYSTONE_HOST']
manifestdata = getManifestTemplate("keystone_glance.pp") manifestdata = getManifestTemplate("keystone_glance.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createmanifest(): def createmanifest(config):
manifestfile = "%s_glance.pp" % controller.CONF['CONFIG_GLANCE_HOST'] manifestfile = "%s_glance.pp" % controller.CONF['CONFIG_GLANCE_HOST']
manifestdata = getManifestTemplate("glance.pp") manifestdata = getManifestTemplate("glance.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)

View File

@@ -92,7 +92,7 @@ def initSequences(controller):
] ]
controller.addSequence("Installing OpenStack Keystone", [], [], keystonesteps) controller.addSequence("Installing OpenStack Keystone", [], [], keystonesteps)
def createmanifest(): def createmanifest(config):
manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST'] manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST']
manifestdata = getManifestTemplate("keystone.pp") manifestdata = getManifestTemplate("keystone.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)

View File

@@ -81,7 +81,7 @@ def initSequences(controller):
controller.addSequence("Installing MySQL", [], [], mysqlsteps) controller.addSequence("Installing MySQL", [], [], mysqlsteps)
def createmanifest(): def createmanifest(config):
host = controller.CONF['CONFIG_MYSQL_HOST'] host = controller.CONF['CONFIG_MYSQL_HOST']
manifestfile = "%s_mysql.pp" % host manifestfile = "%s_mysql.pp" % host
manifestdata = [getManifestTemplate("mysql.pp")] manifestdata = [getManifestTemplate("mysql.pp")]

View File

@@ -99,7 +99,7 @@ def nagios_host(hostname, **kwargs):
return "%s}\n" % out return "%s}\n" % out
def createmanifest(): def createmanifest(config):
manifest_entries = '' manifest_entries = ''
# I should be adding service entries with nagios_service but it appears to be broken # I should be adding service entries with nagios_service but it appears to be broken
# http://projects.puppetlabs.com/issues/3420 # http://projects.puppetlabs.com/issues/3420
@@ -167,7 +167,7 @@ def createmanifest():
manifestdata = getManifestTemplate("nagios_server.pp") manifestdata = getManifestTemplate("nagios_server.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createnrpemanifests(): def createnrpemanifests(config):
for hostname in gethostlist(controller.CONF): for hostname in gethostlist(controller.CONF):
controller.CONF['CONFIG_NRPE_HOST'] = hostname controller.CONF['CONFIG_NRPE_HOST'] = hostname
manifestfile = "%s_nagios_nrpe.pp" % hostname manifestfile = "%s_nagios_nrpe.pp" % hostname

View File

@@ -272,25 +272,25 @@ def initSequences(controller):
controller.addSequence("Installing OpenStack Nova API", [], [], novaapisteps) controller.addSequence("Installing OpenStack Nova API", [], [], novaapisteps)
def createapimanifest(): def createapimanifest(config):
manifestfile = "%s_api_nova.pp"%controller.CONF['CONFIG_NOVA_API_HOST'] manifestfile = "%s_api_nova.pp"%controller.CONF['CONFIG_NOVA_API_HOST']
manifestdata = getManifestTemplate("nova_api.pp") manifestdata = getManifestTemplate("nova_api.pp")
appendManifestFile(manifestfile, manifestdata, 'novaapi') appendManifestFile(manifestfile, manifestdata, 'novaapi')
def createkeystonemanifest(): def createkeystonemanifest(config):
manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST'] manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST']
manifestdata = getManifestTemplate("keystone_nova.pp") manifestdata = getManifestTemplate("keystone_nova.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createcertmanifest(): def createcertmanifest(config):
manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_CERT_HOST'] manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_CERT_HOST']
manifestdata = getManifestTemplate("nova_cert.pp") manifestdata = getManifestTemplate("nova_cert.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createconductormanifest(): def createconductormanifest(config):
manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_CONDUCTOR_HOST'] manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_CONDUCTOR_HOST']
manifestdata = getManifestTemplate("nova_conductor.pp") manifestdata = getManifestTemplate("nova_conductor.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
@@ -328,7 +328,7 @@ def bring_up_ifcfg(host, device):
raise ScriptRuntimeError(msg) raise ScriptRuntimeError(msg)
def createcomputemanifest(): def createcomputemanifest(config):
for host in controller.CONF["CONFIG_NOVA_COMPUTE_HOSTS"].split(","): for host in controller.CONF["CONFIG_NOVA_COMPUTE_HOSTS"].split(","):
controller.CONF["CONFIG_NOVA_COMPUTE_HOST"] = host controller.CONF["CONFIG_NOVA_COMPUTE_HOST"] = host
manifestdata = getManifestTemplate("nova_compute.pp") manifestdata = getManifestTemplate("nova_compute.pp")
@@ -347,7 +347,7 @@ def createcomputemanifest():
appendManifestFile(manifestfile, manifestdata + "\n" + nova_config_options.getManifestEntry()) appendManifestFile(manifestfile, manifestdata + "\n" + nova_config_options.getManifestEntry())
def createnetworkmanifest(): def createnetworkmanifest(config):
host = controller.CONF['CONFIG_NOVA_NETWORK_HOST'] host = controller.CONF['CONFIG_NOVA_NETWORK_HOST']
for i in ('CONFIG_NOVA_NETWORK_PRIVIF', 'CONFIG_NOVA_NETWORK_PUBIF'): for i in ('CONFIG_NOVA_NETWORK_PRIVIF', 'CONFIG_NOVA_NETWORK_PUBIF'):
check_ifcfg(host, controller.CONF[i]) check_ifcfg(host, controller.CONF[i])
@@ -372,19 +372,19 @@ def createnetworkmanifest():
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createschedmanifest(): def createschedmanifest(config):
manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_SCHED_HOST'] manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_SCHED_HOST']
manifestdata = getManifestTemplate("nova_sched.pp") manifestdata = getManifestTemplate("nova_sched.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createvncproxymanifest(): def createvncproxymanifest(config):
manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_VNCPROXY_HOST'] manifestfile = "%s_nova.pp"%controller.CONF['CONFIG_NOVA_VNCPROXY_HOST']
manifestdata = getManifestTemplate("nova_vncproxy.pp") manifestdata = getManifestTemplate("nova_vncproxy.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createcommonmanifest(): def createcommonmanifest(config):
for manifestfile, marker in manifestfiles.getFiles(): for manifestfile, marker in manifestfiles.getFiles():
if manifestfile.endswith("_nova.pp"): if manifestfile.endswith("_nova.pp"):
data = getManifestTemplate("nova_common.pp") data = getManifestTemplate("nova_common.pp")

View File

@@ -57,7 +57,7 @@ def initSequences(controller):
] ]
controller.addSequence("Installing OpenStack Client", [], [], osclientsteps) controller.addSequence("Installing OpenStack Client", [], [], osclientsteps)
def createmanifest(): def createmanifest(config):
client_host = controller.CONF['CONFIG_OSCLIENT_HOST'].strip() client_host = controller.CONF['CONFIG_OSCLIENT_HOST'].strip()
manifestfile = "%s_osclient.pp" % client_host manifestfile = "%s_osclient.pp" % client_host
manifestdata = getManifestTemplate("openstack_client.pp") manifestdata = getManifestTemplate("openstack_client.pp")

View File

@@ -42,7 +42,7 @@ def initSequences(controller):
] ]
controller.addSequence("Running post install scripts", [], [], osclientsteps) controller.addSequence("Running post install scripts", [], [], osclientsteps)
def createmanifest(): def createmanifest(config):
for hostname in gethostlist(controller.CONF): for hostname in gethostlist(controller.CONF):
manifestfile = "%s_postscript.pp" % hostname manifestfile = "%s_postscript.pp" % hostname
manifestdata = getManifestTemplate("postscript.pp") manifestdata = getManifestTemplate("postscript.pp")

View File

@@ -146,13 +146,13 @@ def initSequences(controller):
'instances might be problem for ' 'instances might be problem for '
'some OpenStack components.') 'some OpenStack components.')
def createmanifest(): def createmanifest(config):
for hostname in gethostlist(controller.CONF): for hostname in gethostlist(controller.CONF):
manifestfile = "%s_prescript.pp" % hostname manifestfile = "%s_prescript.pp" % hostname
manifestdata = getManifestTemplate("prescript.pp") manifestdata = getManifestTemplate("prescript.pp")
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def create_ntp_manifest(): def create_ntp_manifest(config):
servers = '' servers = ''
for srv in controller.CONF['CONFIG_NTP_SERVERS'].split(','): for srv in controller.CONF['CONFIG_NTP_SERVERS'].split(','):
srv = srv.strip() srv = srv.strip()

View File

@@ -59,13 +59,13 @@ def initSequences(controller):
controller.addSequence("Puppet", [], [], puppetsteps) controller.addSequence("Puppet", [], [], puppetsteps)
def runCleanup(): def runCleanup(config):
localserver = utils.ScriptRunner() localserver = utils.ScriptRunner()
localserver.append("rm -rf %s/*pp" % basedefs.PUPPET_MANIFEST_DIR) localserver.append("rm -rf %s/*pp" % basedefs.PUPPET_MANIFEST_DIR)
localserver.execute() localserver.execute()
def installdeps(): def installdeps(config):
for hostname in gethostlist(controller.CONF): for hostname in gethostlist(controller.CONF):
server = utils.ScriptRunner(hostname) server = utils.ScriptRunner(hostname)
for package in ("puppet", "openssh-clients", "tar"): for package in ("puppet", "openssh-clients", "tar"):
@@ -73,7 +73,7 @@ def installdeps():
server.execute() server.execute()
def copyPuppetModules(): def copyPuppetModules(config):
os_modules = ' '.join(('apache', 'cinder', 'concat', os_modules = ' '.join(('apache', 'cinder', 'concat',
'create_resources', 'firewall', 'create_resources', 'firewall',
'glance', 'horizon', 'inifile', 'glance', 'horizon', 'inifile',
@@ -165,7 +165,7 @@ def waitforpuppet(currently_running):
print ("[ " + utils.color_text(output_messages.INFO_DONE, 'green') + " ]") print ("[ " + utils.color_text(output_messages.INFO_DONE, 'green') + " ]")
def applyPuppetManifest(): def applyPuppetManifest(config):
print print
currently_running = [] currently_running = []
lastmarker = None lastmarker = None

View File

@@ -57,7 +57,7 @@ def initSequences(controller):
] ]
controller.addSequence("Installing QPID", [], [], qpidsteps) controller.addSequence("Installing QPID", [], [], qpidsteps)
def createmanifest(): def createmanifest(config):
manifestfile = "%s_qpid.pp"%controller.CONF['CONFIG_QPID_HOST'] manifestfile = "%s_qpid.pp"%controller.CONF['CONFIG_QPID_HOST']
manifestdata = getManifestTemplate("qpid.pp") manifestdata = getManifestTemplate("qpid.pp")
appendManifestFile(manifestfile, manifestdata, 'pre') appendManifestFile(manifestfile, manifestdata, 'pre')

View File

@@ -373,7 +373,7 @@ def initSequences(controller):
controller.addSequence("Preparing servers", [], [], preparesteps) controller.addSequence("Preparing servers", [], [], preparesteps)
def serverprep(): def serverprep(config):
config = controller.CONF config = controller.CONF
rh_username = None rh_username = None

View File

@@ -61,7 +61,7 @@ def initSequences(controller):
controller.addSequence("Setting up ssh keys", [], [], puppetsteps) controller.addSequence("Setting up ssh keys", [], [], puppetsteps)
def installKeys(): def installKeys(config):
with open(controller.CONF["CONFIG_SSH_KEY"]) as fp: with open(controller.CONF["CONFIG_SSH_KEY"]) as fp:
sshkeydata = fp.read().strip() sshkeydata = fp.read().strip()
for hostname in gethostlist(controller.CONF): for hostname in gethostlist(controller.CONF):

View File

@@ -130,7 +130,7 @@ def initSequences(controller):
controller.addSequence("Installing OpenStack Swift", [], [], steps) controller.addSequence("Installing OpenStack Swift", [], [], steps)
def createkeystonemanifest(): def createkeystonemanifest(config):
manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST'] manifestfile = "%s_keystone.pp"%controller.CONF['CONFIG_KEYSTONE_HOST']
controller.CONF['CONFIG_SWIFT_PROXY'] = controller.CONF['CONFIG_SWIFT_PROXY_HOSTS'].split(',')[0] controller.CONF['CONFIG_SWIFT_PROXY'] = controller.CONF['CONFIG_SWIFT_PROXY_HOSTS'].split(',')[0]
manifestdata = getManifestTemplate("keystone_swift.pp") manifestdata = getManifestTemplate("keystone_swift.pp")
@@ -158,7 +158,7 @@ def parse_devices(config_swift_storage_hosts):
# The ring file should be built and distributed befor the storage services # The ring file should be built and distributed befor the storage services
# come up. Specifically the replicator crashes if the ring isn't present # come up. Specifically the replicator crashes if the ring isn't present
def createbuildermanifest(): def createbuildermanifest(config):
# TODO : put this on the proxy server, will need to change this later # TODO : put this on the proxy server, will need to change this later
controller.CONF['CONFIG_SWIFT_BUILDER_HOST'] = controller.CONF['CONFIG_SWIFT_PROXY_HOSTS'].split(',')[0] controller.CONF['CONFIG_SWIFT_BUILDER_HOST'] = controller.CONF['CONFIG_SWIFT_PROXY_HOSTS'].split(',')[0]
manifestfile = "%s_ring_swift.pp"%controller.CONF['CONFIG_SWIFT_BUILDER_HOST'] manifestfile = "%s_ring_swift.pp"%controller.CONF['CONFIG_SWIFT_BUILDER_HOST']
@@ -178,7 +178,7 @@ def createbuildermanifest():
appendManifestFile(manifestfile, manifestdata, 'swiftbuilder') appendManifestFile(manifestfile, manifestdata, 'swiftbuilder')
def createproxymanifest(): def createproxymanifest(config):
manifestfile = "%s_swift.pp"%controller.CONF['CONFIG_SWIFT_PROXY_HOSTS'] manifestfile = "%s_swift.pp"%controller.CONF['CONFIG_SWIFT_PROXY_HOSTS']
manifestdata = getManifestTemplate("swift_proxy.pp") manifestdata = getManifestTemplate("swift_proxy.pp")
# If the proxy server is also a storage server then swift::ringsync will be included for the storage server # If the proxy server is also a storage server then swift::ringsync will be included for the storage server
@@ -212,7 +212,7 @@ def check_device(host, device):
return False return False
def createstoragemanifest(): def createstoragemanifest(config):
# this need to happen once per storage host # this need to happen once per storage host
for host in set([device['host'] for device in devices]): for host in set([device['host'] for device in devices]):
@@ -238,7 +238,7 @@ def createstoragemanifest():
appendManifestFile(manifestfile, manifestdata) appendManifestFile(manifestfile, manifestdata)
def createcommonmanifest(): def createcommonmanifest(config):
for manifestfile, marker in manifestfiles.getFiles(): for manifestfile, marker in manifestfiles.getFiles():
if manifestfile.endswith("_swift.pp"): if manifestfile.endswith("_swift.pp"):
data = getManifestTemplate("swift_common.pp") data = getManifestTemplate("swift_common.pp")

View File

@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013, Red Hat, Inc.
#
# 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 sys
import StringIO
from unittest import TestCase
from packstack.installer import utils
from packstack.installer.core.sequences import *
from ..test_base import PackstackTestCaseMixin
class StepTestCase(PackstackTestCaseMixin, TestCase):
def setUp(self):
super(StepTestCase, self).setUp()
self._stdout = sys.stdout
sys.stdout = StringIO.StringIO()
def tearDown(self):
super(StepTestCase, self).tearDown()
sys.stdout = self._stdout
def test_run(self):
"""
Test packstack.instaler.core.sequences.Step run.
"""
def func(config):
if 'test' not in config:
raise AssertionError('Missing config value.')
step = Step('test', func, title='Running test')
step.run(config={'test': 'test'})
contents = sys.stdout.getvalue()
state = '[ %s ]\n' % utils.color_text('DONE', 'green')
if not contents.startswith('Running test') or \
not contents.endswith(state):
raise AssertionError('Step run test failed: %s' % contents)
class SequenceTestCase(PackstackTestCaseMixin, TestCase):
def setUp(self):
super(SequenceTestCase, self).setUp()
self._stdout = sys.stdout
sys.stdout = StringIO.StringIO()
self.steps = [{'name': '1', 'function': lambda x: True,
'title': 'Step 1'},
{'name': '2', 'function': lambda x: True,
'title': 'Step 2'},
{'name': '3', 'function': lambda x: True,
'title': 'Step 3'}]
self.seq = Sequence('test', self.steps, condition='test',
cond_match='test')
def tearDown(self):
super(SequenceTestCase, self).tearDown()
sys.stdout = self._stdout
def test_run(self):
"""
Test packstack.instaler.core.sequences.Sequence run.
"""
self.seq.run()
contents = sys.stdout.getvalue()
self.assertEqual(contents, '')
self.seq.run(config={'test': 'test'}, step='2')
contents = sys.stdout.getvalue()
assert contents.startswith('Step 2')
output = []
state_fmt = '[ %s ]\n'
self.steps.insert(0, {'title': 'Step 2'})
for i in self.steps:
space = 70 - len(i['title'])
title = '[ %s ]\n' % utils.color_text('DONE', 'green')
output.append('%s...%s' % (i['title'], title.rjust(space)))
self.seq.run(config={'test': 'test'})
contents = sys.stdout.getvalue()
self.assertEqual(contents, ''.join(output))