Merge "Refactored packstack.installer.setup_sequences"
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 | ||||||
|   | |||||||
							
								
								
									
										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(","): | ||||||
|         host = host.strip() |         host = host.strip() | ||||||
|         controller.CONF["CONFIG_NOVA_COMPUTE_HOST"] = host |         controller.CONF["CONFIG_NOVA_COMPUTE_HOST"] = host | ||||||
| @@ -348,7 +348,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]) | ||||||
| @@ -373,19 +373,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
	 Jenkins
					Jenkins