Cleaned packstack.installer.common_utils
- cleaned from useless functions - refactored to be pep8 compliant - separated to standalone modules - added unit tests Change-Id: If5a300fe04efab9e13549f2b4d05c1b28e2e40c6
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""
|
"""
|
||||||
provides all the predefined variables for engine-setup
|
This module provides all the predefined variables.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
APP_NAME = "Installer"
|
APP_NAME = "Installer"
|
||||||
|
|
||||||
FILE_YUM_VERSION_LOCK = "/etc/yum/pluginconf.d/versionlock.list"
|
FILE_YUM_VERSION_LOCK = "/etc/yum/pluginconf.d/versionlock.list"
|
||||||
@@ -17,7 +21,7 @@ except:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
_tmpdirprefix = datetime.datetime.now().strftime('%Y%m%d-%H%M%S-')
|
_tmpdirprefix = datetime.datetime.now().strftime('%Y%m%d-%H%M%S-')
|
||||||
VAR_DIR = tempfile.mkdtemp(prefix = _tmpdirprefix, dir = PACKSTACK_VAR_DIR)
|
VAR_DIR = tempfile.mkdtemp(prefix=_tmpdirprefix, dir=PACKSTACK_VAR_DIR)
|
||||||
DIR_LOG = VAR_DIR
|
DIR_LOG = VAR_DIR
|
||||||
PUPPET_MANIFEST_RELATIVE = "manifests"
|
PUPPET_MANIFEST_RELATIVE = "manifests"
|
||||||
PUPPET_MANIFEST_DIR = os.path.join(VAR_DIR, PUPPET_MANIFEST_RELATIVE)
|
PUPPET_MANIFEST_DIR = os.path.join(VAR_DIR, PUPPET_MANIFEST_RELATIVE)
|
||||||
@@ -37,17 +41,10 @@ EXEC_CHKCONFIG = "chkconfig"
|
|||||||
EXEC_SERVICE = "service"
|
EXEC_SERVICE = "service"
|
||||||
EXEC_IP = "ip"
|
EXEC_IP = "ip"
|
||||||
|
|
||||||
#text colors
|
# text colors
|
||||||
RED = "\033[0;31m"
|
|
||||||
GREEN = "\033[92m"
|
|
||||||
BLUE = "\033[94m"
|
|
||||||
YELLOW = "\033[93m"
|
|
||||||
NO_COLOR = "\033[0m"
|
NO_COLOR = "\033[0m"
|
||||||
|
COLORS = {'red': "\033[0;31m", 'green': "\033[92m", 'blue': "\033[94m",
|
||||||
|
'yellow': "\033[93m"}
|
||||||
|
|
||||||
COLORS = (RED, GREEN, BLUE, YELLOW, NO_COLOR)
|
# space len size for color print
|
||||||
|
|
||||||
#space len size for color print
|
|
||||||
SPACE_LEN = 70
|
SPACE_LEN = 70
|
||||||
|
|
||||||
RPM_LOCK_LIST = """
|
|
||||||
"""
|
|
||||||
|
|||||||
@@ -1,431 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
contains all common and re-usable code for rhevm-setup and sub packages
|
|
||||||
"""
|
|
||||||
import grp
|
|
||||||
import pwd
|
|
||||||
import logging
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import traceback
|
|
||||||
import os
|
|
||||||
import datetime
|
|
||||||
import types
|
|
||||||
import time
|
|
||||||
import socket
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
import basedefs
|
|
||||||
import output_messages
|
|
||||||
from .exceptions import NetworkError, ScriptRuntimeError
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getColoredText (text, color):
|
|
||||||
''' gets text string and color
|
|
||||||
and returns a colored text.
|
|
||||||
the color values are RED/BLUE/GREEN/YELLOW
|
|
||||||
everytime we color a text, we need to disable
|
|
||||||
the color at the end of it, for that
|
|
||||||
we use the NO_COLOR chars.
|
|
||||||
'''
|
|
||||||
return color + text + basedefs.NO_COLOR
|
|
||||||
|
|
||||||
def execCmd(cmdList, cwd=None, failOnError=False, msg=output_messages.ERR_RC_CODE, maskList=[], useShell=False, usePipeFiles=False):
|
|
||||||
"""
|
|
||||||
Run external shell command with 'shell=false'
|
|
||||||
receives a list of arguments for command line execution
|
|
||||||
"""
|
|
||||||
# All items in the list needs to be strings, otherwise the subprocess will fail
|
|
||||||
cmd = [str(item) for item in cmdList]
|
|
||||||
|
|
||||||
# We need to join cmd list into one string so we can look for passwords in it and mask them
|
|
||||||
logCmd = _maskString((' '.join(cmd)), maskList)
|
|
||||||
logging.debug("Executing command --> '%s'"%(logCmd))
|
|
||||||
|
|
||||||
stdErrFD = subprocess.PIPE
|
|
||||||
stdOutFD = subprocess.PIPE
|
|
||||||
stdInFD = subprocess.PIPE
|
|
||||||
|
|
||||||
if usePipeFiles:
|
|
||||||
(stdErrFD, stdErrFile) = tempfile.mkstemp(dir="/tmp")
|
|
||||||
(stdOutFD, stdOutFile) = tempfile.mkstemp(dir="/tmp")
|
|
||||||
(stdInFD, stdInFile) = tempfile.mkstemp(dir="/tmp")
|
|
||||||
|
|
||||||
# We use close_fds to close any file descriptors we have so it won't be copied to forked childs
|
|
||||||
proc = subprocess.Popen(cmd, stdout=stdOutFD,
|
|
||||||
stderr=stdErrFD, stdin=stdInFD, cwd=cwd, shell=useShell, close_fds=True)
|
|
||||||
|
|
||||||
out, err = proc.communicate()
|
|
||||||
if usePipeFiles:
|
|
||||||
with open(stdErrFile, 'r') as f:
|
|
||||||
err = f.read()
|
|
||||||
os.remove(stdErrFile)
|
|
||||||
|
|
||||||
with open(stdOutFile, 'r') as f:
|
|
||||||
out = f.read()
|
|
||||||
os.remove(stdOutFile)
|
|
||||||
os.remove(stdInFile)
|
|
||||||
|
|
||||||
logging.debug("output = %s"%(out))
|
|
||||||
logging.debug("stderr = %s"%(err))
|
|
||||||
logging.debug("retcode = %s"%(proc.returncode))
|
|
||||||
output = out + err
|
|
||||||
if failOnError and proc.returncode != 0:
|
|
||||||
raise Exception(msg)
|
|
||||||
return ("".join(output.splitlines(True)), proc.returncode)
|
|
||||||
|
|
||||||
def byLength(word1, word2):
|
|
||||||
"""
|
|
||||||
Compars two strings by their length
|
|
||||||
Returns:
|
|
||||||
Negative if word2 > word1
|
|
||||||
Positive if word1 > word2
|
|
||||||
Zero if word1 == word 2
|
|
||||||
"""
|
|
||||||
return len(word1) - len(word2)
|
|
||||||
|
|
||||||
def nslookup(address):
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_NSLOOKUP, address,
|
|
||||||
]
|
|
||||||
#since nslookup will return 0 no matter what, the RC is irrelevant
|
|
||||||
output, rc = execCmd(cmdList=cmd)
|
|
||||||
return output
|
|
||||||
|
|
||||||
def getConfiguredIps():
|
|
||||||
try:
|
|
||||||
iplist=set()
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_IP, "addr",
|
|
||||||
]
|
|
||||||
output, rc = execCmd(cmdList=cmd, failOnError=True, msg=output_messages.ERR_EXP_GET_CFG_IPS_CODES)
|
|
||||||
ipaddrPattern=re.compile('\s+inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).+')
|
|
||||||
list=output.splitlines()
|
|
||||||
for line in list:
|
|
||||||
foundIp = ipaddrPattern.search(line)
|
|
||||||
if foundIp:
|
|
||||||
if foundIp.group(1) != "127.0.0.1":
|
|
||||||
ipAddr = foundIp.group(1)
|
|
||||||
logging.debug("Found IP Address: %s"%(ipAddr))
|
|
||||||
iplist.add(ipAddr)
|
|
||||||
return iplist
|
|
||||||
except:
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
raise Exception(output_messages.ERR_EXP_GET_CFG_IPS)
|
|
||||||
|
|
||||||
def getCurrentDateTime(isUtc=None):
|
|
||||||
now = None
|
|
||||||
if (isUtc is not None):
|
|
||||||
now = datetime.datetime.utcnow()
|
|
||||||
else:
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
return now.strftime("%Y_%m_%d_%H_%M_%S")
|
|
||||||
|
|
||||||
def verifyStringFormat(str, matchRegex):
|
|
||||||
'''
|
|
||||||
Verify that the string given matches the matchRegex.
|
|
||||||
for example:
|
|
||||||
string: 111-222
|
|
||||||
matchRegex: \d{3}-\d{3}
|
|
||||||
this will return true since the string matches the regex
|
|
||||||
'''
|
|
||||||
pattern = re.compile(matchRegex)
|
|
||||||
result = re.match(pattern, str)
|
|
||||||
if result == None:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def compareStrIgnoreCase(str1, str2):
|
|
||||||
''' compare 2 strings and ignore case
|
|
||||||
if one of the input is not str (bool for e.g) - return normal comapre
|
|
||||||
'''
|
|
||||||
if type(str1) == types.StringType and type(str2) == types.StringType:
|
|
||||||
return str1.lower() == str2.lower()
|
|
||||||
else:
|
|
||||||
return str1 == str2
|
|
||||||
|
|
||||||
def parseStrRegex(string, regex, errMsg):
|
|
||||||
"""
|
|
||||||
Gets a text string and a regex pattern
|
|
||||||
and returns the extracted sub-string
|
|
||||||
captured.
|
|
||||||
"""
|
|
||||||
rePattern = re.compile(regex)
|
|
||||||
found = rePattern.search(string)
|
|
||||||
if found:
|
|
||||||
match = found.group(1)
|
|
||||||
logging.debug("found new parsed string: %s"%(match))
|
|
||||||
return match
|
|
||||||
else:
|
|
||||||
raise Exception(errMsg)
|
|
||||||
|
|
||||||
def _maskString(string, maskList=[]):
|
|
||||||
"""
|
|
||||||
private func to mask passwords
|
|
||||||
in utils
|
|
||||||
"""
|
|
||||||
maskedStr = string
|
|
||||||
for maskItem in maskList:
|
|
||||||
if not maskItem: continue
|
|
||||||
maskedStr = maskedStr.replace(maskItem, "*"*8)
|
|
||||||
# if looking at stderr of a script, single quotes have been converted
|
|
||||||
# to '\''
|
|
||||||
maskedStr = maskedStr.replace(maskItem.replace("'","'\\''"), "*"*8)
|
|
||||||
|
|
||||||
return maskedStr
|
|
||||||
|
|
||||||
def retry(func, expectedException=Exception, tries=None, timeout=None, sleep=1):
|
|
||||||
"""
|
|
||||||
Retry a function. Wraps the retry logic so you don't have to
|
|
||||||
implement it each time you need it.
|
|
||||||
|
|
||||||
:param func: The callable to run.
|
|
||||||
:param expectedException: The exception you expect to receive when the function fails.
|
|
||||||
:param tries: The number of time to try. None\0,-1 means infinite.
|
|
||||||
:param timeout: The time you want to spend waiting. This **WILL NOT** stop the method.
|
|
||||||
It will just not run it if it ended after the timeout.
|
|
||||||
:param sleep: Time to sleep between calls in seconds.
|
|
||||||
"""
|
|
||||||
if tries in [0, None]:
|
|
||||||
tries = -1
|
|
||||||
|
|
||||||
if timeout in [0, None]:
|
|
||||||
timeout = -1
|
|
||||||
|
|
||||||
startTime = time.time()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
tries -= 1
|
|
||||||
try:
|
|
||||||
return func()
|
|
||||||
except expectedException:
|
|
||||||
if tries == 0:
|
|
||||||
raise
|
|
||||||
|
|
||||||
if (timeout > 0) and ((time.time() - startTime) > timeout):
|
|
||||||
raise
|
|
||||||
|
|
||||||
time.sleep(sleep)
|
|
||||||
|
|
||||||
def localHost(hostname):
|
|
||||||
# Create an ip set of possible IPs on the machine. Set has only unique values, so
|
|
||||||
# there's no problem with union.
|
|
||||||
# TODO: cache the list somehow? There's no poing quering the IP configuraion all the time.
|
|
||||||
ipset = getConfiguredIps().union(set([ "localhost", "127.0.0.1"]))
|
|
||||||
if hostname in ipset:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# TODO: Support SystemD services
|
|
||||||
class Service():
|
|
||||||
def __init__(self, name):
|
|
||||||
self.wasStopped = False
|
|
||||||
self.wasStarted = False
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def isServiceAvailable(self):
|
|
||||||
if os.path.exists("/etc/init.d/%s" % self.name):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def start(self, raiseFailure = False):
|
|
||||||
logging.debug("starting %s", self.name)
|
|
||||||
(output, rc) = self._serviceFacility("start")
|
|
||||||
if rc == 0:
|
|
||||||
self.wasStarted = True
|
|
||||||
elif raiseFailure:
|
|
||||||
raise Exception(output_messages.ERR_FAILED_START_SERVICE % self.name)
|
|
||||||
|
|
||||||
return (output, rc)
|
|
||||||
|
|
||||||
def stop(self, raiseFailure = False):
|
|
||||||
logging.debug("stopping %s", self.name)
|
|
||||||
(output, rc) = self._serviceFacility("stop")
|
|
||||||
if rc == 0:
|
|
||||||
self.wasStopped = True
|
|
||||||
elif raiseFailure:
|
|
||||||
raise Exception(output_messages.ERR_FAILED_STOP_SERVICE % self.name)
|
|
||||||
|
|
||||||
return (output, rc)
|
|
||||||
|
|
||||||
def autoStart(self, start=True):
|
|
||||||
mode = "on" if start else "off"
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_CHKCONFIG, self.name, mode,
|
|
||||||
]
|
|
||||||
execCmd(cmdList=cmd, failOnError=True)
|
|
||||||
|
|
||||||
def conditionalStart(self, raiseFailure = False):
|
|
||||||
"""
|
|
||||||
Will only start if wasStopped is set to True
|
|
||||||
"""
|
|
||||||
if self.wasStopped:
|
|
||||||
logging.debug("Service %s was stopped. starting it again"%self.name)
|
|
||||||
return self.start(raiseFailure)
|
|
||||||
else:
|
|
||||||
logging.debug("Service was not stopped. there for we're not starting it")
|
|
||||||
return (False, False)
|
|
||||||
|
|
||||||
def status(self):
|
|
||||||
logging.debug("getting status for %s", self.name)
|
|
||||||
(output, rc) = self._serviceFacility("status")
|
|
||||||
return (output, rc)
|
|
||||||
|
|
||||||
def _serviceFacility(self, action):
|
|
||||||
"""
|
|
||||||
Execute the command "service NAME action"
|
|
||||||
returns: output, rc
|
|
||||||
"""
|
|
||||||
logging.debug("executing action %s on service %s", self.name, action)
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_SERVICE, self.name, action
|
|
||||||
]
|
|
||||||
return execCmd(cmdList=cmd, usePipeFiles=True)
|
|
||||||
|
|
||||||
def chown(target,uid, gid):
|
|
||||||
logging.debug("chown %s to %s:%s" % (target, uid, gid))
|
|
||||||
os.chown(target, uid, gid)
|
|
||||||
|
|
||||||
def installed(rpm):
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_RPM,
|
|
||||||
"-q",
|
|
||||||
rpm,
|
|
||||||
]
|
|
||||||
output, rc = execCmd(cmd)
|
|
||||||
return rc == 0
|
|
||||||
|
|
||||||
def returnYes(controller):
|
|
||||||
return "yes"
|
|
||||||
|
|
||||||
def getLocalhostIP():
|
|
||||||
"""
|
|
||||||
Returns IP address of localhost.
|
|
||||||
"""
|
|
||||||
# TO-DO: Will probably need to find better way to find out localhost
|
|
||||||
# address.
|
|
||||||
|
|
||||||
# find nameservers
|
|
||||||
ns_regex = re.compile('nameserver\s*(?P<ns_ip>[\d\.\:])')
|
|
||||||
resolv, rc = execCmd(['cat /etc/resolv.conf | grep nameserver',],
|
|
||||||
failOnError=False, useShell=True)
|
|
||||||
nsrvs = []
|
|
||||||
for line in resolv.split('\n'):
|
|
||||||
match = ns_regex.match(line.strip())
|
|
||||||
if match:
|
|
||||||
nsrvs.append(match.group('ns_ip'))
|
|
||||||
|
|
||||||
# try to connect to nameservers and return own IP address
|
|
||||||
nsrvs.append('8.8.8.8') # default to google dns
|
|
||||||
for i in nsrvs:
|
|
||||||
try:
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
s.connect((i, 0))
|
|
||||||
loc_ip = s.getsockname()[0]
|
|
||||||
except socket.error:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
return loc_ip
|
|
||||||
|
|
||||||
def host2ip(hostname, allow_localhost=False):
|
|
||||||
"""
|
|
||||||
Converts given hostname to IP address. Raises NetworkError
|
|
||||||
if conversion failed.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
ip_list = socket.gethostbyaddr(hostname)[2]
|
|
||||||
if allow_localhost:
|
|
||||||
return ip_list[0]
|
|
||||||
else:
|
|
||||||
local_ips = ('127.0.0.1', '::1')
|
|
||||||
for ip in ip_list:
|
|
||||||
if ip not in local_ips:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise NameError()
|
|
||||||
return ip
|
|
||||||
except NameError:
|
|
||||||
# given hostname is localhost, return appropriate IP address
|
|
||||||
ip = getLocalhostIP()
|
|
||||||
if not ip:
|
|
||||||
raise NetworkError('Failed to get local IP address.')
|
|
||||||
return ip
|
|
||||||
except socket.error:
|
|
||||||
raise NetworkError('Unknown hostname %s.' % hostname)
|
|
||||||
except Exception, ex:
|
|
||||||
raise NetworkError('Unknown error appeared: %s' % repr(ex))
|
|
||||||
|
|
||||||
def forceIP(host, allow_localhost=False):
|
|
||||||
host = host.strip()
|
|
||||||
ipv4_regex = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
|
|
||||||
ipv6_regex = re.compile('[abcdef\d\:]+')
|
|
||||||
if not ipv4_regex.match(host) or not ipv6_regex.match(host):
|
|
||||||
host = host2ip(host, allow_localhost=allow_localhost)
|
|
||||||
return host
|
|
||||||
|
|
||||||
def device_from_ip(ip):
|
|
||||||
server = ScriptRunner()
|
|
||||||
server.append("DEVICE=$(ip address show to %s | head -n 1 | sed -e 's/.*: \(.*\):.*/\\1/g')" % ip)
|
|
||||||
# Test device, raises an exception is it doesn't exist
|
|
||||||
server.append("ip link show \"$DEVICE\" > /dev/null")
|
|
||||||
server.append("echo $DEVICE")
|
|
||||||
rv, stdout = server.execute()
|
|
||||||
return stdout.strip()
|
|
||||||
|
|
||||||
class ScriptRunner(object):
|
|
||||||
def __init__(self, ip=None):
|
|
||||||
self.script = []
|
|
||||||
self.ip = ip
|
|
||||||
|
|
||||||
def append(self, s):
|
|
||||||
self.script.append(s)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.script = []
|
|
||||||
|
|
||||||
def execute(self, logerrors=True, maskList=None):
|
|
||||||
maskList = maskList or []
|
|
||||||
script = "\n".join(self.script)
|
|
||||||
logging.debug("# ============ ssh : %r =========="%self.ip)
|
|
||||||
|
|
||||||
_PIPE = subprocess.PIPE # pylint: disable=E1101
|
|
||||||
if self.ip:
|
|
||||||
cmd = ["ssh", "-o", "StrictHostKeyChecking=no",
|
|
||||||
"-o", "UserKnownHostsFile=/dev/null",
|
|
||||||
"root@%s" % self.ip, "bash -x"]
|
|
||||||
else:
|
|
||||||
cmd = ["bash", "-x"]
|
|
||||||
obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE,
|
|
||||||
close_fds=True, shell=False)
|
|
||||||
|
|
||||||
logging.debug(_maskString(script, maskList))
|
|
||||||
script = "function t(){ exit $? ; } \n trap t ERR \n" + script
|
|
||||||
stdoutdata, stderrdata = obj.communicate(script)
|
|
||||||
logging.debug("============ STDOUT ==========")
|
|
||||||
logging.debug(_maskString(stdoutdata, maskList))
|
|
||||||
returncode = obj.returncode
|
|
||||||
if returncode:
|
|
||||||
if logerrors:
|
|
||||||
logging.error("============= STDERR ==========")
|
|
||||||
logging.error(_maskString(stderrdata, maskList))
|
|
||||||
|
|
||||||
pattern = (r'^ssh\:')
|
|
||||||
if re.search(pattern, stderrdata):
|
|
||||||
raise NetworkError(stderrdata)
|
|
||||||
else:
|
|
||||||
raise ScriptRuntimeError('Error running remote script: '
|
|
||||||
'%s' % stdoutdata)
|
|
||||||
return returncode, stdoutdata
|
|
||||||
|
|
||||||
def template(self, src, dst, varsdict):
|
|
||||||
with open(src) as fp:
|
|
||||||
self.append("cat > %s <<- EOF\n%s\nEOF\n"%(dst, fp.read()%varsdict))
|
|
||||||
|
|
||||||
def ifnotexists(self, fn, s):
|
|
||||||
self.append("[ -e %s ] || %s"%(fn, s))
|
|
||||||
|
|
||||||
def ifexists(self, fn, s):
|
|
||||||
self.append("[ -e %s ] && %s"%(fn, s))
|
|
||||||
@@ -18,7 +18,11 @@ __all__ = (
|
|||||||
|
|
||||||
class PackStackError(Exception):
|
class PackStackError(Exception):
|
||||||
"""Default Exception class for packstack installer."""
|
"""Default Exception class for packstack installer."""
|
||||||
pass
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(PackStackError, self).__init__(*args)
|
||||||
|
self.stdout = kwargs.get('stdout', None)
|
||||||
|
self.stderr = kwargs.get('stderr', None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MissingRequirements(PackStackError):
|
class MissingRequirements(PackStackError):
|
||||||
@@ -55,5 +59,10 @@ class NetworkError(PackStackError):
|
|||||||
|
|
||||||
|
|
||||||
class ScriptRuntimeError(PackStackError):
|
class ScriptRuntimeError(PackStackError):
|
||||||
"""Raised when ScriptRunner.execute does not end successfully."""
|
"""
|
||||||
|
Raised when utils.ScriptRunner.execute does not end successfully.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class ExecuteRuntimeError(PackStackError):
|
||||||
|
"""Raised when utils.execute does not end successfully."""
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ ERR_IPS_NOT_CONFIGED_ON_INT="The IP (%s) which was resolved from the FQDN %s is
|
|||||||
ERR_IPS_HAS_NO_PTR="None of the IP addresses on this host(%s) holds a PTR record for the FQDN: %s"
|
ERR_IPS_HAS_NO_PTR="None of the IP addresses on this host(%s) holds a PTR record for the FQDN: %s"
|
||||||
ERR_IP_HAS_NO_PTR="The IP %s does not hold a PTR record for the FQDN: %s"
|
ERR_IP_HAS_NO_PTR="The IP %s does not hold a PTR record for the FQDN: %s"
|
||||||
ERR_EXP_FAILED_INIT_LOGGER="Unexpected error: Failed to initiate logger, please check file system permission"
|
ERR_EXP_FAILED_INIT_LOGGER="Unexpected error: Failed to initiate logger, please check file system permission"
|
||||||
ERR_RC_CODE="Return Code is not zero"
|
|
||||||
ERR_FAILURE="General failure"
|
ERR_FAILURE="General failure"
|
||||||
ERR_NO_ANSWER_FILE="Error: Could not find file %s"
|
ERR_NO_ANSWER_FILE="Error: Could not find file %s"
|
||||||
ERR_ONLY_1_FLAG="Error: The %s flag is mutually exclusive to all other command line options"
|
ERR_ONLY_1_FLAG="Error: The %s flag is mutually exclusive to all other command line options"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .common_utils import ScriptRunner, forceIP
|
from .utils import ScriptRunner, force_ip
|
||||||
from .exceptions import ParamProcessingError, NetworkError
|
from .exceptions import ParamProcessingError, NetworkError
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ def process_host(param, process_args=None):
|
|||||||
localhost = process_args and \
|
localhost = process_args and \
|
||||||
process_args.get('allow_localhost', False)
|
process_args.get('allow_localhost', False)
|
||||||
try:
|
try:
|
||||||
return forceIP(param, allow_localhost=localhost)
|
return force_ip(param, allow_localhost=localhost)
|
||||||
except NetworkError, ex:
|
except NetworkError, ex:
|
||||||
raise ParamProcessingError(str(ex))
|
raise ParamProcessingError(str(ex))
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from optparse import OptionParser, OptionGroup
|
|||||||
|
|
||||||
import basedefs
|
import basedefs
|
||||||
import validators
|
import validators
|
||||||
import common_utils as utils
|
from . import utils
|
||||||
import processors
|
import processors
|
||||||
import output_messages
|
import output_messages
|
||||||
from .exceptions import FlagValidationError, ParamValidationError
|
from .exceptions import FlagValidationError, ParamValidationError
|
||||||
@@ -35,7 +35,6 @@ def initLogging (debug):
|
|||||||
global logFile
|
global logFile
|
||||||
|
|
||||||
try:
|
try:
|
||||||
#in order to use UTC date for the log file, send True to getCurrentDateTime(True)
|
|
||||||
logFilename = "openstack-setup.log"
|
logFilename = "openstack-setup.log"
|
||||||
logFile = os.path.join(basedefs.DIR_LOG, logFilename)
|
logFile = os.path.join(basedefs.DIR_LOG, logFilename)
|
||||||
|
|
||||||
@@ -220,18 +219,19 @@ def mask(input):
|
|||||||
if type(input) == types.DictType:
|
if type(input) == types.DictType:
|
||||||
for key in input:
|
for key in input:
|
||||||
if type(input[key]) == types.StringType:
|
if type(input[key]) == types.StringType:
|
||||||
output[key] = maskString(input[key])
|
output[key] = utils.mask_string(input[key],
|
||||||
|
masked_value_set)
|
||||||
if type(input) == types.ListType:
|
if type(input) == types.ListType:
|
||||||
for item in input:
|
for item in input:
|
||||||
org = item
|
org = item
|
||||||
orgIndex = input.index(org)
|
orgIndex = input.index(org)
|
||||||
if type(item) == types.StringType:
|
if type(item) == types.StringType:
|
||||||
item = maskString(item)
|
item = utils.mask_string(item, masked_value_set)
|
||||||
if item != org:
|
if item != org:
|
||||||
output.remove(org)
|
output.remove(org)
|
||||||
output.insert(orgIndex, item)
|
output.insert(orgIndex, item)
|
||||||
if type(input) == types.StringType:
|
if type(input) == types.StringType:
|
||||||
output = maskString(input)
|
output = utils.mask_string(input, masked_value_set)
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@@ -253,13 +253,6 @@ def removeMaskString(maskedString):
|
|||||||
if found:
|
if found:
|
||||||
masked_value_set.remove(maskedString)
|
masked_value_set.remove(maskedString)
|
||||||
|
|
||||||
def maskString(str):
|
|
||||||
# Iterate sorted list, so we won't mask only part of a password
|
|
||||||
for password in sorted(masked_value_set, utils.byLength, None, True):
|
|
||||||
if password:
|
|
||||||
str = str.replace(password, '*'*8)
|
|
||||||
return str
|
|
||||||
|
|
||||||
def validate_param_value(param, value):
|
def validate_param_value(param, value):
|
||||||
cname = param.CONF_NAME
|
cname = param.CONF_NAME
|
||||||
logging.debug("Validating parameter %s." % cname)
|
logging.debug("Validating parameter %s." % cname)
|
||||||
@@ -364,7 +357,7 @@ def _handleAnswerFileParams(answerFile):
|
|||||||
|
|
||||||
# Handle pre condition match with case insensitive values
|
# Handle pre condition match with case insensitive values
|
||||||
logging.info("Comparing pre- conditions, value: '%s', and match: '%s'" % (preConditionValue, group.PRE_CONDITION_MATCH))
|
logging.info("Comparing pre- conditions, value: '%s', and match: '%s'" % (preConditionValue, group.PRE_CONDITION_MATCH))
|
||||||
if utils.compareStrIgnoreCase(preConditionValue, group.PRE_CONDITION_MATCH):
|
if preConditionValue == group.PRE_CONDITION_MATCH:
|
||||||
for param in group.parameters.itervalues():
|
for param in group.parameters.itervalues():
|
||||||
_loadParamFromFile(fconf, "general", param.CONF_NAME)
|
_loadParamFromFile(fconf, "general", param.CONF_NAME)
|
||||||
|
|
||||||
@@ -374,7 +367,7 @@ def _handleAnswerFileParams(answerFile):
|
|||||||
postConditionValue = _handleGroupCondition(fconf, group.POST_CONDITION, postConditionValue)
|
postConditionValue = _handleGroupCondition(fconf, group.POST_CONDITION, postConditionValue)
|
||||||
|
|
||||||
# Handle post condition match for group
|
# Handle post condition match for group
|
||||||
if not utils.compareStrIgnoreCase(postConditionValue, group.POST_CONDITION_MATCH):
|
if postConditionValue != group.POST_CONDITION_MATCH:
|
||||||
logging.error("The group condition (%s) returned: %s, which differs from the excpeted output: %s"%\
|
logging.error("The group condition (%s) returned: %s, which differs from the excpeted output: %s"%\
|
||||||
(group.GROUP_NAME, postConditionValue, group.POST_CONDITION_MATCH))
|
(group.GROUP_NAME, postConditionValue, group.POST_CONDITION_MATCH))
|
||||||
raise ValueError(output_messages.ERR_EXP_GROUP_VALIDATION_ANS_FILE%\
|
raise ValueError(output_messages.ERR_EXP_GROUP_VALIDATION_ANS_FILE%\
|
||||||
@@ -422,7 +415,7 @@ def _handleInteractiveParams():
|
|||||||
|
|
||||||
# If we have a match, i.e. condition returned True, go over all params in the group
|
# If we have a match, i.e. condition returned True, go over all params in the group
|
||||||
logging.info("Comparing pre-conditions; condition: '%s', and match: '%s'" % (preConditionValue, group.PRE_CONDITION_MATCH))
|
logging.info("Comparing pre-conditions; condition: '%s', and match: '%s'" % (preConditionValue, group.PRE_CONDITION_MATCH))
|
||||||
if utils.compareStrIgnoreCase(preConditionValue, group.PRE_CONDITION_MATCH):
|
if preConditionValue == group.PRE_CONDITION_MATCH:
|
||||||
while inputLoop:
|
while inputLoop:
|
||||||
for param in group.parameters.itervalues():
|
for param in group.parameters.itervalues():
|
||||||
if not param.CONDITION:
|
if not param.CONDITION:
|
||||||
@@ -546,19 +539,6 @@ def _addFinalInfoMsg():
|
|||||||
"""
|
"""
|
||||||
controller.MESSAGES.append(output_messages.INFO_LOG_FILE_PATH%(logFile))
|
controller.MESSAGES.append(output_messages.INFO_LOG_FILE_PATH%(logFile))
|
||||||
|
|
||||||
def _lockRpmVersion():
|
|
||||||
"""
|
|
||||||
Enters rpm versions into yum version-lock
|
|
||||||
"""
|
|
||||||
logging.debug("Locking rpms in yum-version-lock")
|
|
||||||
cmd = [
|
|
||||||
basedefs.EXEC_RPM, "-q",
|
|
||||||
] + basedefs.RPM_LOCK_LIST.split()
|
|
||||||
output, rc = utils.execCmd(cmdList=cmd, failOnError=True, msg=output_messages.ERR_YUM_LOCK)
|
|
||||||
|
|
||||||
with open(basedefs.FILE_YUM_VERSION_LOCK, "a") as f:
|
|
||||||
for rpm in output.splitlines():
|
|
||||||
f.write(rpm + "\n")
|
|
||||||
|
|
||||||
def _summaryParamsToLog():
|
def _summaryParamsToLog():
|
||||||
if len(controller.CONF) > 0:
|
if len(controller.CONF) > 0:
|
||||||
@@ -624,7 +604,7 @@ def remove_remote_var_dirs():
|
|||||||
msg = output_messages.ERR_REMOVE_REMOTE_VAR % (host_dir, host)
|
msg = output_messages.ERR_REMOVE_REMOTE_VAR % (host_dir, host)
|
||||||
logging.error(msg)
|
logging.error(msg)
|
||||||
logging.exception(e)
|
logging.exception(e)
|
||||||
controller.MESSAGES.append(utils.getColoredText(msg, basedefs.RED))
|
controller.MESSAGES.append(utils.color_text(msg, 'red'))
|
||||||
|
|
||||||
|
|
||||||
def generateAnswerFile(outputFile, overrides={}):
|
def generateAnswerFile(outputFile, overrides={}):
|
||||||
@@ -905,7 +885,7 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(traceback.format_exc())
|
logging.error(traceback.format_exc())
|
||||||
print
|
print
|
||||||
print utils.getColoredText("ERROR : "+str(e), basedefs.RED)
|
print utils.color_text("ERROR : " + str(e), 'red')
|
||||||
print output_messages.ERR_CHECK_LOG_FILE_FOR_MORE_INFO%(logFile)
|
print output_messages.ERR_CHECK_LOG_FILE_FOR_MORE_INFO%(logFile)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Container set for groups and parameters
|
Container set for groups and parameters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .datastructures import SortedDict
|
from .utils.datastructures import SortedDict
|
||||||
|
|
||||||
|
|
||||||
class Parameter(object):
|
class Parameter(object):
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import string
|
|||||||
import traceback
|
import traceback
|
||||||
import basedefs
|
import basedefs
|
||||||
import output_messages
|
import output_messages
|
||||||
import common_utils as utils
|
from . import utils
|
||||||
|
|
||||||
class Step(object):
|
class Step(object):
|
||||||
def __init__(self, title=None, functions=[]):
|
def __init__(self, title=None, functions=[]):
|
||||||
@@ -61,7 +61,7 @@ class Step(object):
|
|||||||
except:
|
except:
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
raise
|
raise
|
||||||
print ("[ " + utils.getColoredText(output_messages.INFO_DONE, basedefs.GREEN) + " ]").rjust(spaceLen)
|
print ("[ " + utils.color_text(output_messages.INFO_DONE, 'green') + " ]").rjust(spaceLen)
|
||||||
|
|
||||||
class Sequence(object):
|
class Sequence(object):
|
||||||
"""
|
"""
|
||||||
|
|||||||
14
packstack/installer/utils/__init__.py
Normal file
14
packstack/installer/utils/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from .datastructures import SortedDict
|
||||||
|
from .decorators import retry
|
||||||
|
from .network import get_localhost_ip, host2ip, force_ip
|
||||||
|
from .shell import ScriptRunner, execute
|
||||||
|
from .strings import color_text, mask_string
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ('SortedDict',
|
||||||
|
'retry',
|
||||||
|
'ScriptRunner', 'execute',
|
||||||
|
'get_localhost_ip', 'host2ip', 'force_ip',
|
||||||
|
'color_text', 'mask_string')
|
||||||
29
packstack/installer/utils/decorators.py
Normal file
29
packstack/installer/utils/decorators.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def retry(count=1, delay=0, retry_on=Exception):
|
||||||
|
"""
|
||||||
|
Decorator which tries to run specified fuction if the previous
|
||||||
|
run ended by given exception. Retry count and delays can be also
|
||||||
|
specified.
|
||||||
|
"""
|
||||||
|
if count < 0 or delay < 0:
|
||||||
|
raise ValueError('Count and delay has to be positive number.')
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
tried = 0
|
||||||
|
while tried <= count:
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except retry_on:
|
||||||
|
if tried >= count:
|
||||||
|
raise
|
||||||
|
if delay:
|
||||||
|
time.sleep(delay)
|
||||||
|
tried += 1
|
||||||
|
wrapper.func_name = func.func_name
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
74
packstack/installer/utils/network.py
Normal file
74
packstack/installer/utils/network.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from .shell import execute
|
||||||
|
|
||||||
|
|
||||||
|
def get_localhost_ip():
|
||||||
|
"""
|
||||||
|
Returns IP address of localhost.
|
||||||
|
"""
|
||||||
|
# TO-DO: Will probably need to find better way to find out localhost
|
||||||
|
# address.
|
||||||
|
|
||||||
|
# find nameservers
|
||||||
|
ns_regex = re.compile('nameserver\s*(?P<ns_ip>[\d\.\:])')
|
||||||
|
rc, resolv = execute('cat /etc/resolv.conf | grep nameserver',
|
||||||
|
can_fail=False, use_shell=True)
|
||||||
|
nsrvs = []
|
||||||
|
for line in resolv.split('\n'):
|
||||||
|
match = ns_regex.match(line.strip())
|
||||||
|
if match:
|
||||||
|
nsrvs.append(match.group('ns_ip'))
|
||||||
|
|
||||||
|
# try to connect to nameservers and return own IP address
|
||||||
|
nsrvs.append('8.8.8.8') # default to google dns
|
||||||
|
for i in nsrvs:
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
s.connect((i, 0))
|
||||||
|
loc_ip = s.getsockname()[0]
|
||||||
|
except socket.error:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
return loc_ip
|
||||||
|
|
||||||
|
|
||||||
|
def host2ip(hostname, allow_localhost=False):
|
||||||
|
"""
|
||||||
|
Converts given hostname to IP address. Raises NetworkError
|
||||||
|
if conversion failed.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ip_list = socket.gethostbyaddr(hostname)[2]
|
||||||
|
if allow_localhost:
|
||||||
|
return ip_list[0]
|
||||||
|
else:
|
||||||
|
local_ips = ('127.0.0.1', '::1')
|
||||||
|
for ip in ip_list:
|
||||||
|
if ip not in local_ips:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise NameError()
|
||||||
|
return ip
|
||||||
|
except NameError:
|
||||||
|
# given hostname is localhost, return appropriate IP address
|
||||||
|
ip = get_localhost_ip()
|
||||||
|
if not ip:
|
||||||
|
raise NetworkError('Failed to get local IP address.')
|
||||||
|
return ip
|
||||||
|
except socket.error:
|
||||||
|
raise NetworkError('Unknown hostname %s.' % hostname)
|
||||||
|
except Exception, ex:
|
||||||
|
raise NetworkError('Unknown error appeared: %s' % repr(ex))
|
||||||
|
|
||||||
|
|
||||||
|
def force_ip(host, allow_localhost=False):
|
||||||
|
host = host.strip()
|
||||||
|
ipv4_regex = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
|
||||||
|
ipv6_regex = re.compile('[abcdef\d\:]+')
|
||||||
|
if not ipv4_regex.match(host) or not ipv6_regex.match(host):
|
||||||
|
host = host2ip(host, allow_localhost=allow_localhost)
|
||||||
|
return host
|
||||||
118
packstack/installer/utils/shell.py
Normal file
118
packstack/installer/utils/shell.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
import types
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from ..exceptions import (ExecuteRuntimeError, ScriptRuntimeError,
|
||||||
|
NetworkError)
|
||||||
|
from .strings import mask_string
|
||||||
|
|
||||||
|
|
||||||
|
def execute(cmd, workdir=None, can_fail=False, mask_list=None,
|
||||||
|
use_shell=False):
|
||||||
|
"""
|
||||||
|
Runs shell command cmd. If can_fail is set to False
|
||||||
|
ExecuteRuntimeError is raised if command returned non-zero return
|
||||||
|
code. Otherwise
|
||||||
|
"""
|
||||||
|
mask_list = mask_list or []
|
||||||
|
repl_list = [("'","'\\''")]
|
||||||
|
|
||||||
|
if type(cmd) is not types.StringType:
|
||||||
|
import pipes
|
||||||
|
masked = ' '.join((pipes.quote(i) for i in cmd))
|
||||||
|
else:
|
||||||
|
masked = cmd
|
||||||
|
masked = mask_string(masked, mask_list, repl_list)
|
||||||
|
logging.debug("Executing command: %s" % masked)
|
||||||
|
|
||||||
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE, cwd=workdir,
|
||||||
|
shell=use_shell, close_fds=True)
|
||||||
|
out, err = proc.communicate()
|
||||||
|
logging.debug("rc: %s" % proc.returncode)
|
||||||
|
logging.debug("stdout:\n%s" % mask_string(out, mask_list, repl_list))
|
||||||
|
logging.debug("stderr:\n%s" % mask_string(err, mask_list, repl_list))
|
||||||
|
|
||||||
|
if not can_fail and proc.returncode != 0:
|
||||||
|
msg = 'Failed to execute command: %s' % masked
|
||||||
|
raise ExecuteRuntimeError(msg, stdout=out, stderr=err)
|
||||||
|
return proc.returncode, out
|
||||||
|
|
||||||
|
|
||||||
|
class ScriptRunner(object):
|
||||||
|
_pkg_search = 'rpm -q'
|
||||||
|
|
||||||
|
def __init__(self, ip=None):
|
||||||
|
self.script = []
|
||||||
|
self.ip = ip
|
||||||
|
|
||||||
|
def append(self, s):
|
||||||
|
self.script.append(s)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.script = []
|
||||||
|
|
||||||
|
def execute(self, logerrors=True, maskList=None):
|
||||||
|
maskList = maskList or []
|
||||||
|
script = "\n".join(self.script)
|
||||||
|
logging.debug("# ============ ssh : %r =========="%self.ip)
|
||||||
|
|
||||||
|
_PIPE = subprocess.PIPE # pylint: disable=E1101
|
||||||
|
if self.ip:
|
||||||
|
cmd = ["ssh", "-o", "StrictHostKeyChecking=no",
|
||||||
|
"-o", "UserKnownHostsFile=/dev/null",
|
||||||
|
"root@%s" % self.ip, "bash -x"]
|
||||||
|
else:
|
||||||
|
cmd = ["bash", "-x"]
|
||||||
|
obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE,
|
||||||
|
stderr=_PIPE, close_fds=True,
|
||||||
|
shell=False)
|
||||||
|
|
||||||
|
replace_list = [("'","'\\''")]
|
||||||
|
logging.debug(mask_string(script, maskList, replace_list))
|
||||||
|
script = "function t(){ exit $? ; } \n trap t ERR \n" + script
|
||||||
|
stdoutdata, stderrdata = obj.communicate(script)
|
||||||
|
logging.debug("============ STDOUT ==========")
|
||||||
|
logging.debug(mask_string(stdoutdata, maskList, replace_list))
|
||||||
|
returncode = obj.returncode
|
||||||
|
if returncode:
|
||||||
|
if logerrors:
|
||||||
|
logging.error("============= STDERR ==========")
|
||||||
|
logging.error(mask_string(stderrdata, maskList,
|
||||||
|
replace_list))
|
||||||
|
|
||||||
|
pattern = (r'^ssh\:')
|
||||||
|
if re.search(pattern, stderrdata):
|
||||||
|
raise NetworkError(stderrdata, stdout=stdoutdata,
|
||||||
|
stderr=stderrdata)
|
||||||
|
else:
|
||||||
|
msg = 'Error running remote script: %s' % stdoutdata
|
||||||
|
raise ScriptRuntimeError(msg, stdout=stdoutdata,
|
||||||
|
stderr=stderrdata)
|
||||||
|
return returncode, stdoutdata
|
||||||
|
|
||||||
|
def template(self, src, dst, varsdict):
|
||||||
|
with open(src) as fp:
|
||||||
|
content = fp.read() % varsdict
|
||||||
|
self.append("cat > %s <<- EOF\n%s\nEOF\n" % (dst, content))
|
||||||
|
|
||||||
|
def if_not_exists(self, path, command):
|
||||||
|
self.append("[ -e %s ] || %s" % (path, command))
|
||||||
|
|
||||||
|
def if_exists(self, path, command):
|
||||||
|
self.append("[ -e %s ] && %s" % (path, command))
|
||||||
|
|
||||||
|
def if_installed(self, pkg, command):
|
||||||
|
self.append("%s %s && %s" % (self._pkg_search, pkg, command))
|
||||||
|
|
||||||
|
def if_not_installed(self, pkg, command):
|
||||||
|
self.append("%s %s || %s" % (self._pkg_search, pkg, command))
|
||||||
|
|
||||||
|
def chown(self, target, uid, gid):
|
||||||
|
self.append("chown %s:%s %s" % (uid, gid, target))
|
||||||
|
|
||||||
|
def chmod(self, target, mode):
|
||||||
|
self.append("chown %s %s" % (mode, target))
|
||||||
34
packstack/installer/utils/strings.py
Normal file
34
packstack/installer/utils/strings.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from .. import basedefs
|
||||||
|
|
||||||
|
|
||||||
|
STR_MASK = '*' * 8
|
||||||
|
|
||||||
|
|
||||||
|
def color_text(text, color):
|
||||||
|
"""
|
||||||
|
Returns given text string with appropriate color tag. Allowed values
|
||||||
|
for color parameter are 'red', 'blue', 'green' and 'yellow'.
|
||||||
|
"""
|
||||||
|
return '%s%s%s' % (basedefs.COLORS[color], text, basedefs.NO_COLOR)
|
||||||
|
|
||||||
|
|
||||||
|
def mask_string(unmasked, mask_list=None, replace_list=None):
|
||||||
|
"""
|
||||||
|
Replaces words from mask_list with MASK in unmasked string.
|
||||||
|
If words are needed to be transformed before masking, transformation
|
||||||
|
could be describe in replace list. For example [("'","'\\''")]
|
||||||
|
replaces all ' characters with '\\''.
|
||||||
|
"""
|
||||||
|
mask_list = mask_list or []
|
||||||
|
replace_list = replace_list or []
|
||||||
|
|
||||||
|
masked = unmasked
|
||||||
|
for word in sorted(mask_list, lambda x, y: len(y) - len(x)):
|
||||||
|
if not word:
|
||||||
|
continue
|
||||||
|
for before, after in replace_list:
|
||||||
|
word = word.replace(before, after)
|
||||||
|
masked = masked.replace(word, STR_MASK)
|
||||||
|
return masked
|
||||||
@@ -12,7 +12,7 @@ import tempfile
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import basedefs
|
import basedefs
|
||||||
import common_utils as utils
|
from . import utils
|
||||||
|
|
||||||
from .setup_controller import Controller
|
from .setup_controller import Controller
|
||||||
from .exceptions import ParamValidationError
|
from .exceptions import ParamValidationError
|
||||||
@@ -175,8 +175,8 @@ def validate_ping(param, options=None):
|
|||||||
# TO-DO: to be more flexible, remove this and exit in case param is empty
|
# TO-DO: to be more flexible, remove this and exit in case param is empty
|
||||||
validate_not_empty(param)
|
validate_not_empty(param)
|
||||||
|
|
||||||
cmd = ["/bin/ping", "-c", "1", str(param)]
|
rc, out = utils.execute(['/bin/ping', '-c', '1', str(param)],
|
||||||
out, rc = utils.execCmd(cmdList=cmd)
|
can_fail=True)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
logging.debug('validate_ping(%s, options=%s) failed.' %
|
logging.debug('validate_ping(%s, options=%s) failed.' %
|
||||||
(param, options))
|
(param, options))
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from packstack.installer import exceptions
|
|||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
|
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
from packstack.installer.exceptions import ScriptRuntimeError
|
from packstack.installer.exceptions import ScriptRuntimeError
|
||||||
@@ -22,7 +22,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-Cinder"
|
PLUGIN_NAME = "OS-Cinder"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Cinder server",
|
"PROMPT" : "Enter the IP address of the Cinder server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_CINDER_HOST",
|
"CONF_NAME" : "CONFIG_CINDER_HOST",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import uuid
|
|||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs, output_messages
|
from packstack.installer import basedefs, output_messages
|
||||||
from packstack.installer import exceptions
|
from packstack.installer import exceptions
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-HORIZON"
|
PLUGIN_NAME = "OS-HORIZON"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Horizon server",
|
"PROMPT" : "Enter the IP address of the Horizon server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_HORIZON_HOST",
|
"CONF_NAME" : "CONFIG_HORIZON_HOST",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-Glance"
|
PLUGIN_NAME = "OS-Glance"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Glance server",
|
"PROMPT" : "Enter the IP address of the Glance server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_GLANCE_HOST",
|
"CONF_NAME" : "CONFIG_GLANCE_HOST",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import uuid
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-Keystone"
|
PLUGIN_NAME = "OS-Keystone"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Keystone server",
|
"PROMPT" : "Enter the IP address of the Keystone server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_KEYSTONE_HOST",
|
"CONF_NAME" : "CONFIG_KEYSTONE_HOST",
|
||||||
@@ -78,7 +78,7 @@ def initConfig(controllerObject):
|
|||||||
|
|
||||||
groupDict = { "GROUP_NAME" : "KEYSTONE",
|
groupDict = { "GROUP_NAME" : "KEYSTONE",
|
||||||
"DESCRIPTION" : "Keystone Config parameters",
|
"DESCRIPTION" : "Keystone Config parameters",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-MySQL"
|
PLUGIN_NAME = "OS-MySQL"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the MySQL server",
|
"PROMPT" : "Enter the IP address of the MySQL server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_MYSQL_HOST",
|
"CONF_NAME" : "CONFIG_MYSQL_HOST",
|
||||||
@@ -65,7 +65,7 @@ def initConfig(controllerObject):
|
|||||||
|
|
||||||
groupDict = { "GROUP_NAME" : "MYSQL",
|
groupDict = { "GROUP_NAME" : "MYSQL",
|
||||||
"DESCRIPTION" : "MySQL Config parameters",
|
"DESCRIPTION" : "MySQL Config parameters",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs, output_messages
|
from packstack.installer import basedefs, output_messages
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import gethostlist,\
|
from packstack.modules.ospluginutils import gethostlist,\
|
||||||
getManifestTemplate,\
|
getManifestTemplate,\
|
||||||
@@ -18,7 +18,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-Nagios"
|
PLUGIN_NAME = "OS-Nagios"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nagios server",
|
"PROMPT" : "Enter the IP address of the Nagios server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NAGIOS_HOST",
|
"CONF_NAME" : "CONFIG_NAGIOS_HOST",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import uuid
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
from packstack.installer.exceptions import ScriptRuntimeError
|
from packstack.installer.exceptions import ScriptRuntimeError
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import NovaConfig, getManifestTemplate, appendManifestFile, manifestfiles
|
from packstack.modules.ospluginutils import NovaConfig, getManifestTemplate, appendManifestFile, manifestfiles
|
||||||
@@ -29,7 +29,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova API service",
|
"PROMPT" : "Enter the IP address of the Nova API service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_API_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_API_HOST",
|
||||||
@@ -41,7 +41,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova Cert service",
|
"PROMPT" : "Enter the IP address of the Nova Cert service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_CERT_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_CERT_HOST",
|
||||||
@@ -53,7 +53,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova VNC proxy",
|
"PROMPT" : "Enter the IP address of the Nova VNC proxy",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_VNCPROXY_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_VNCPROXY_HOST",
|
||||||
@@ -65,7 +65,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter a comma separated list of IP addresses on which to install the Nova Compute services",
|
"PROMPT" : "Enter a comma separated list of IP addresses on which to install the Nova Compute services",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_multi_ssh],
|
"VALIDATORS" : [validators.validate_multi_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_COMPUTE_HOSTS",
|
"CONF_NAME" : "CONFIG_NOVA_COMPUTE_HOSTS",
|
||||||
@@ -89,7 +89,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova Network service",
|
"PROMPT" : "Enter the IP address of the Nova Network service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_NETWORK_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_NETWORK_HOST",
|
||||||
@@ -101,7 +101,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova Conductor service",
|
"PROMPT" : "Enter the IP address of the Nova Conductor service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_CONDUCTOR_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_CONDUCTOR_HOST",
|
||||||
@@ -209,7 +209,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Nova Scheduler service",
|
"PROMPT" : "Enter the IP address of the Nova Scheduler service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_NOVA_SCHED_HOST",
|
"CONF_NAME" : "CONFIG_NOVA_SCHED_HOST",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs, output_messages
|
from packstack.installer import basedefs, output_messages
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-CLIENT"
|
PLUGIN_NAME = "OS-CLIENT"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the client server",
|
"PROMPT" : "Enter the IP address of the client server",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_OSCLIENT_HOST",
|
"CONF_NAME" : "CONFIG_OSCLIENT_HOST",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs, output_messages
|
from packstack.installer import basedefs, output_messages
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import gethostlist,\
|
from packstack.modules.ospluginutils import gethostlist,\
|
||||||
getManifestTemplate, \
|
getManifestTemplate, \
|
||||||
@@ -28,7 +28,7 @@ def initConfig(controllerObject):
|
|||||||
|
|
||||||
groupDict = {"GROUP_NAME" : "POSTSCRIPT",
|
groupDict = {"GROUP_NAME" : "POSTSCRIPT",
|
||||||
"DESCRIPTION" : "POSTSCRIPT Config parameters",
|
"DESCRIPTION" : "POSTSCRIPT Config parameters",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import uuid
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import gethostlist,\
|
from packstack.modules.ospluginutils import gethostlist,\
|
||||||
getManifestTemplate, \
|
getManifestTemplate, \
|
||||||
@@ -123,7 +123,7 @@ def initConfig(controllerObject):
|
|||||||
]
|
]
|
||||||
groupDict = { "GROUP_NAME" : "GLOBAL",
|
groupDict = { "GROUP_NAME" : "GLOBAL",
|
||||||
"DESCRIPTION" : "Global Options",
|
"DESCRIPTION" : "Global Options",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
from packstack.installer import basedefs, output_messages
|
from packstack.installer import basedefs, output_messages
|
||||||
from packstack.installer.exceptions import ScriptRuntimeError
|
from packstack.installer.exceptions import ScriptRuntimeError
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OSPUPPET"
|
PLUGIN_NAME = "OSPUPPET"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ def initConfig(controllerObject):
|
|||||||
|
|
||||||
groupDict = {"GROUP_NAME" : "PUPPET",
|
groupDict = {"GROUP_NAME" : "PUPPET",
|
||||||
"DESCRIPTION" : "Puppet Config parameters",
|
"DESCRIPTION" : "Puppet Config parameters",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
@@ -162,7 +162,7 @@ def waitforpuppet(currently_running):
|
|||||||
# check the log file for errors
|
# check the log file for errors
|
||||||
validate_puppet_logfile(log)
|
validate_puppet_logfile(log)
|
||||||
sys.stdout.write(("\r%s : " % log_file).ljust(basedefs.SPACE_LEN))
|
sys.stdout.write(("\r%s : " % log_file).ljust(basedefs.SPACE_LEN))
|
||||||
print ("[ " + utils.getColoredText(output_messages.INFO_DONE, basedefs.GREEN) + " ]")
|
print ("[ " + utils.color_text(output_messages.INFO_DONE, 'green') + " ]")
|
||||||
|
|
||||||
|
|
||||||
def applyPuppetManifest():
|
def applyPuppetManifest():
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import logging
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-QPID"
|
PLUGIN_NAME = "OS-QPID"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the QPID service",
|
"PROMPT" : "Enter the IP address of the QPID service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_QPID_HOST",
|
"CONF_NAME" : "CONFIG_QPID_HOST",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import datetime
|
|||||||
import platform
|
import platform
|
||||||
|
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
from packstack.installer import common_utils as utils
|
from packstack.installer import utils
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer.exceptions import InstallError
|
from packstack.installer.exceptions import InstallError
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-SERVERPREPARE"
|
PLUGIN_NAME = "OS-SERVERPREPARE"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ def initConfig(controllerObject):
|
|||||||
conf_groups = [
|
conf_groups = [
|
||||||
{"GROUP_NAME" : "SERVERPREPARE",
|
{"GROUP_NAME" : "SERVERPREPARE",
|
||||||
"DESCRIPTION" : "Server Prepare Configs ",
|
"DESCRIPTION" : "Server Prepare Configs ",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True},
|
"POST_CONDITION_MATCH" : True},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import tempfile
|
|||||||
from packstack.installer import processors
|
from packstack.installer import processors
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import gethostlist
|
from packstack.modules.ospluginutils import gethostlist
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-SSHKEYS"
|
PLUGIN_NAME = "OS-SSHKEYS"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ def initConfig(controllerObject):
|
|||||||
|
|
||||||
groupDict = { "GROUP_NAME" : "SSHKEY",
|
groupDict = { "GROUP_NAME" : "SSHKEY",
|
||||||
"DESCRIPTION" : "SSH Configs ",
|
"DESCRIPTION" : "SSH Configs ",
|
||||||
"PRE_CONDITION" : utils.returnYes,
|
"PRE_CONDITION" : lambda x: 'yes',
|
||||||
"PRE_CONDITION_MATCH" : "yes",
|
"PRE_CONDITION_MATCH" : "yes",
|
||||||
"POST_CONDITION" : False,
|
"POST_CONDITION" : False,
|
||||||
"POST_CONDITION_MATCH" : True}
|
"POST_CONDITION_MATCH" : True}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import os
|
|||||||
|
|
||||||
from packstack.installer import validators
|
from packstack.installer import validators
|
||||||
from packstack.installer import basedefs
|
from packstack.installer import basedefs
|
||||||
import packstack.installer.common_utils as utils
|
from packstack.installer import utils
|
||||||
|
|
||||||
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile, manifestfiles
|
from packstack.modules.ospluginutils import getManifestTemplate, appendManifestFile, manifestfiles
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ controller = None
|
|||||||
|
|
||||||
# Plugin name
|
# Plugin name
|
||||||
PLUGIN_NAME = "OS-SWIFT"
|
PLUGIN_NAME = "OS-SWIFT"
|
||||||
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
|
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||||
|
|
||||||
logging.debug("plugin %s loaded", __name__)
|
logging.debug("plugin %s loaded", __name__)
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the IP address of the Swift proxy service",
|
"PROMPT" : "Enter the IP address of the Swift proxy service",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_SWIFT_PROXY_HOSTS", #XXX: Shouldn't be here CONFIG_SWIFT_PROXY_HOST?
|
"CONF_NAME" : "CONFIG_SWIFT_PROXY_HOSTS", #XXX: Shouldn't be here CONFIG_SWIFT_PROXY_HOST?
|
||||||
@@ -55,7 +55,7 @@ def initConfig(controllerObject):
|
|||||||
"PROMPT" : "Enter the Swift Storage servers e.g. host/dev,host/dev",
|
"PROMPT" : "Enter the Swift Storage servers e.g. host/dev,host/dev",
|
||||||
"OPTION_LIST" : [],
|
"OPTION_LIST" : [],
|
||||||
"VALIDATORS" : [validators.validate_not_empty, validate_storage],
|
"VALIDATORS" : [validators.validate_not_empty, validate_storage],
|
||||||
"DEFAULT_VALUE" : utils.getLocalhostIP(),
|
"DEFAULT_VALUE" : utils.get_localhost_ip(),
|
||||||
"MASK_INPUT" : False,
|
"MASK_INPUT" : False,
|
||||||
"LOOSE_VALIDATION": True,
|
"LOOSE_VALIDATION": True,
|
||||||
"CONF_NAME" : "CONFIG_SWIFT_STORAGE_HOSTS",
|
"CONF_NAME" : "CONFIG_SWIFT_STORAGE_HOSTS",
|
||||||
|
|||||||
93
tests/installer/test_utils.py
Normal file
93
tests/installer/test_utils.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Test cases for packstack.installer.utils module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from ..test_base import PackstackTestCaseMixin
|
||||||
|
from packstack.installer.utils import *
|
||||||
|
from packstack.installer.utils.strings import STR_MASK
|
||||||
|
from packstack.installer.exceptions import ExecuteRuntimeError
|
||||||
|
|
||||||
|
|
||||||
|
cnt = 0
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterTestCase(PackstackTestCaseMixin, TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# Creating a temp directory that can be used by tests
|
||||||
|
self.tempdir = tempfile.mkdtemp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# remove the temp directory
|
||||||
|
shutil.rmtree(self.tempdir)
|
||||||
|
|
||||||
|
def test_sorteddict(self):
|
||||||
|
"""Test packstack.installer.utils.datastructures.SortedDict"""
|
||||||
|
sdict = SortedDict()
|
||||||
|
sdict['1'] = 1
|
||||||
|
sdict['2'] = 2
|
||||||
|
sdict.update(SortedDict([('3', 3), ('4', 4), ('5', 5)]))
|
||||||
|
self.assertListEqual(sdict.keys(), ['1', '2', '3', '4', '5'])
|
||||||
|
self.assertListEqual(sdict.values(), [1, 2, 3, 4, 5])
|
||||||
|
|
||||||
|
def test_retry(self):
|
||||||
|
"""Test packstack.installer.utils.decorators.retry"""
|
||||||
|
|
||||||
|
@retry(count=3, delay=0, retry_on=ValueError)
|
||||||
|
def test_sum():
|
||||||
|
global cnt
|
||||||
|
cnt += 1
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
global cnt
|
||||||
|
cnt = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
test_sum()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
self.assertEqual(cnt, 4)
|
||||||
|
self.assertRaises(ValueError, test_sum)
|
||||||
|
|
||||||
|
def test_network(self):
|
||||||
|
"""Test packstack.installer.utils.network functions"""
|
||||||
|
self.assertIn(host2ip('google-public-dns-a.google.com'),
|
||||||
|
['8.8.8.8', '2001:4860:4860::8888'])
|
||||||
|
self.assertIn(host2ip('localhost', allow_localhost=True),
|
||||||
|
['127.0.0.1', '::1'])
|
||||||
|
|
||||||
|
def test_shell(self):
|
||||||
|
"""Test packstack.installer.utils.shell functions"""
|
||||||
|
rc, out = execute(['echo', 'this is test'])
|
||||||
|
self.assertEqual(out.strip(), 'this is test')
|
||||||
|
rc, out = execute('echo "this is test"', use_shell=True)
|
||||||
|
self.assertEqual(out.strip(), 'this is test')
|
||||||
|
try:
|
||||||
|
execute('echo "mask the password" && exit 1',
|
||||||
|
use_shell=True, mask_list=['password'])
|
||||||
|
raise AssertionError('Masked execution failed.')
|
||||||
|
except ExecuteRuntimeError, ex:
|
||||||
|
should_be = ('Failed to execute command: '
|
||||||
|
'echo "mask the %s" && exit 1' % STR_MASK)
|
||||||
|
self.assertEqual(str(ex), should_be)
|
||||||
|
|
||||||
|
script = ScriptRunner()
|
||||||
|
script.append('echo "this is test"')
|
||||||
|
rc, out = script.execute()
|
||||||
|
self.assertEqual(out.strip(), 'this is test')
|
||||||
|
|
||||||
|
def test_strings(self):
|
||||||
|
"""Test packstack.installer.utils.strings functions"""
|
||||||
|
self.assertEqual(color_text('test text', 'red'),
|
||||||
|
'\033[0;31mtest text\033[0m')
|
||||||
|
self.assertEqual(mask_string('test text', mask_list=['text']),
|
||||||
|
'test %s' % STR_MASK)
|
||||||
|
masked = mask_string("test '\\''text'\\''",
|
||||||
|
mask_list=["'text'"],
|
||||||
|
replace_list=[("'", "'\\''")])
|
||||||
|
self.assertEqual(masked, 'test %s' % STR_MASK)
|
||||||
Reference in New Issue
Block a user