Refactored packstack.installer.setup_sequences
Change-Id: Ie4b039ed9c4996240c20a033d91b936c8113214b
This commit is contained in:
@@ -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
|
||||||
|
|||||||
0
packstack/installer/core/__init__.py
Normal file
0
packstack/installer/core/__init__.py
Normal file
105
packstack/installer/core/sequences.py
Normal file
105
packstack/installer/core/sequences.py
Normal 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)
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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')
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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")]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
98
tests/installer/test_sequences.py
Normal file
98
tests/installer/test_sequences.py
Normal 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))
|
||||||
Reference in New Issue
Block a user