def start(self): lsErrors = list() # Be idempotent if self.status( True, KiscRuntime.STATUS_STARTED) == KiscRuntime.STATUS_STARTED: if self._iVerbose: self._INFO('Already started') return lsErrors # Start the resource if self._iVerbose: self._INFO('Starting') try: # ... stonith command lsCommand = [ 'stonith', '-s', '-S', '-t', self._dsConfig['device_type'] ] # ... arguments lsCommand.extend(['-c', self._dsConfig.get('count', '1')]) # ... parameters if 'parameters' in self._dsConfig: dsParameters = KiscRuntime.parseDictionary( self._dsConfig['parameters'], _sAssignmentOperator='=') for sParameter_name in dsParameters: lsCommand.append( '%s=%s' % (sParameter_name, dsParameters[sParameter_name])) # ... do it ! KiscRuntime.shell( lsCommand, _bTrace=self._iVerbose >= KiscRuntime.VERBOSE_TRACE) self._iStatus = KiscRuntime.STATUS_STARTED if self._iVerbose: self._INFO('Started') except (OSError, RuntimeError) as e: if self._iVerbose: self._ERROR(str(e)) self._iStatus = KiscRuntime.STATUS_ERROR lsErrors.append(str(e)) # Done return lsErrors
def resolveString(self, _sString, _mHost = None, _mResource = None, _bBootstrap = False): """ Resolve the cluster variables in the given string This method will resolve cluster variables defined as '%{<ID>[.<setting>][|<filter>][|...]}'. The following filter can be applied: - int, float, strip, lower, upper, dirname, basename - add(<int|float>), sub(<int|float>), mul(<int|float>), div(<int|float>) - remove(<str>), replace(<str>,<str>) @param str _sString Input string @param str _mHost Target host object or ID (substition for '$HOST' magic ID) @param str _mResource Target resource object or ID (substition for '$SELF' magic ID) @param bool _bBootstrap Whether to consider bootstrap (host startup) resources @return str String with cluster variables resolved @exception RuntimeError On cluster variables subsitution error """ if self._iVerbose: self._DEBUG('Resolving cluster variables string (%s)' % _sString) # 'HOST' host if _mHost is not None and type(_mHost) is str: _mHost = self.getHost(_mHost) # 'SELF' resource if _mResource is not None and type(_mResource) is str: _mResource = self.getResource(_mResource, _bBootstrap) # Prepare filter regexp import re lsRegexpFilters = [ re.compile('(int|float|strip|lower|upper|dirname|basename)'), re.compile('(add|sub|mul|div)\( *([.0-9]+) *\)'), re.compile('(remove)\( *\'([^\']+)\' *\)'), re.compile('(replace)\( *\'([^\']+)\' *, *\'([^\']+)\' *\)'), ] # Look for cluster variables for sVariable in set(re.findall('%\{[^\{]*\}', _sString)): if self._iVerbose: self._DEBUG('Substituting variable (%s)' % sVariable) # ... split <resource-id>.<setting> try: (sResource_id, sSetting) = sVariable[2:-1].split('.') except ValueError as e: sResource_id = sVariable[2:-1] sSetting = 'ID' # ... apply filters lsSettingFilters = sSetting.split('|') if len(lsSettingFilters) > 1: sSetting = lsSettingFilters[0] # ... retrieve value try: # ... retrieve configuration if sResource_id == 'KiSC': dsConfig = self._dsConfig elif sResource_id == '$HOST': if _mHost is None: raise RuntimeError('Target host not specified') dsConfig = _mHost.config() elif sResource_id == '$SELF': if _mResource is None: raise RuntimeError('Target resource not specified') dsConfig = _mResource.config() else: try: oResource_sub = self.getResource(sResource_id, False) except RuntimeError as e: oResource_sub = self.getResource(sResource_id, True) dsConfig = oResource_sub.config() # ... retrieve configuration setting if sSetting[:8] == 'CONSUMES': sConsumable_id = sSetting[9:-1] diConsumables = KiscRuntime.parseDictionary(dsConfig['CONSUMES'], 1, int) sValue = str(diConsumables[sConsumable_id]) elif sSetting[:11] == 'CONSUMABLES': sConsumable_id = sSetting[12:-1] diConsumables = KiscRuntime.parseDictionary(dsConfig['CONSUMABLES'], 1, int) sValue = str(diConsumables[sConsumable_id]) else: sValue = dsConfig[sSetting] except (RuntimeError, KeyError) as e: raise RuntimeError('Invalid cluster variable; %s (%s)' % (sVariable, str(e))) if self._iVerbose: self._DEBUG('Variable value is: %s' % sValue) # ... apply filters if len(lsSettingFilters) > 1: mValue = sValue try: for sFilter in lsSettingFilters[1:]: bMatched = False for sRegexpFilter in lsRegexpFilters: oMatch = sRegexpFilter.match(sFilter) if oMatch is None: continue if self._iVerbose: self._DEBUG('Applying filter: %s' % sFilter) bMatched = True sOperator = oMatch.group(1) tValue = type(mValue) if sOperator == 'int': mValue = int(mValue) elif sOperator == 'float': mValue = float(mValue) elif sOperator == 'strip': mValue = mValue.strip() elif sOperator == 'lower': mValue = mValue.lower() elif sOperator == 'upper': mValue = mValue.upper() elif sOperator == 'dirname': mValue = os.path.dirname(mValue) elif sOperator == 'basename': mValue = os.path.basename(mValue) elif sOperator == 'add': if tValue is float: mValue += float(oMatch.group(2)) else: mValue += int(oMatch.group(2)) elif sOperator == 'sub': if tValue is float: mValue -= float(oMatch.group(2)) else: mValue -= int(oMatch.group(2)) elif sOperator == 'mul': if tValue is float: mValue *= float(oMatch.group(2)) else: mValue *= int(oMatch.group(2)) elif sOperator == 'div': if tValue is float: mValue /= float(oMatch.group(2)) else: mValue /= int(oMatch.group(2)) elif sOperator == 'remove': mValue = mValue.replace(oMatch.group(2), '') elif sOperator == 'replace': mValue = mValue.replace(oMatch.group(2), oMatch.group(3)) break if not bMatched: raise RuntimeError(sFilter) sValue = str(mValue) if self._iVerbose: self._DEBUG('Final variable value is: %s' % sValue) except Exception as e: raise RuntimeError('Invalid variable filter; %s' % str(e)) # ... substitute value _sString = _sString.replace(sVariable, sValue) # Done if self._iVerbose: self._DEBUG('Resolved cluster variables string (%s)' % _sString) return _sString