pre-commit: clean up Python flake8 excludes with black (#9793)

This commit is contained in:
John Bampton 2025-09-17 20:40:56 +10:00 committed by GitHub
parent 0d9c5065de
commit 57309314a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 607 additions and 362 deletions

View File

@ -83,17 +83,6 @@ repos:
hooks: hooks:
- id: flake8 - id: flake8
args: [--config, .github/linters/.flake8] args: [--config, .github/linters/.flake8]
exclude: >
(?x)
^agent/bindir/cloud-setup-agent\.in$|
^client/bindir/cloud-update-xenserver-licenses\.in$|
^cloud-cli/bindir/cloud-tool$|
^python/bindir/cloud-grab-dependent-library-versions$|
^python/bindir/cloud-setup-baremetal$|
^scripts/vm/hypervisor/xenserver/storagePlugin$|
^scripts/vm/hypervisor/xenserver/vmopspremium$|
^setup/bindir/cloud-setup-encryption\.in$|
^venv/.*$
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.45.0 rev: v0.45.0
hooks: hooks:

View File

@ -35,7 +35,7 @@ for pythonpath in (
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
from cloudutils.utilities import initLoging, bash from cloudutils.utilities import initLoging, bash
from cloudutils.configFileOps import configFileOps from cloudutils.configFileOps import configFileOps
from cloudutils.globalEnv import globalEnv from cloudutils.globalEnv import globalEnv
from cloudutils.networkConfig import networkConfig from cloudutils.networkConfig import networkConfig
from cloudutils.syscfg import sysConfigFactory from cloudutils.syscfg import sysConfigFactory
@ -43,35 +43,41 @@ from cloudutils.serviceConfig import configureLibvirtConfig, configure_libvirt_t
from optparse import OptionParser from optparse import OptionParser
def getUserInputs(): def getUserInputs():
print("Welcome to the CloudStack Agent Setup:") print("Welcome to the CloudStack Agent Setup:")
cfo = configFileOps("@AGENTSYSCONFDIR@/agent.properties") cfo = configFileOps("@AGENTSYSCONFDIR@/agent.properties")
oldMgt = cfo.getEntry("host") oldMgt = cfo.getEntry("host")
mgtSvr = input("Please input the Management Server Hostname/IP-Address:[%s]"%oldMgt) mgtSvr = input(
"Please input the Management Server Hostname/IP-Address:[%s]" % oldMgt
)
if mgtSvr == "": if mgtSvr == "":
mgtSvr = oldMgt mgtSvr = oldMgt
try: try:
socket.getaddrinfo(mgtSvr, 443) socket.getaddrinfo(mgtSvr, 443)
except: except:
print("Failed to resolve %s. Please input a valid hostname or IP-Address."%mgtSvr) print(
"Failed to resolve %s. Please input a valid hostname or IP-Address."
% mgtSvr
)
exit(1) exit(1)
oldToken = cfo.getEntry("zone") oldToken = cfo.getEntry("zone")
zoneToken = input("Please input the Zone Id:[%s]"%oldToken) zoneToken = input("Please input the Zone Id:[%s]" % oldToken)
if zoneToken == "": if zoneToken == "":
zoneToken = oldToken zoneToken = oldToken
oldPod = cfo.getEntry("pod") oldPod = cfo.getEntry("pod")
podId = input("Please input the Pod Id:[%s]"%oldPod) podId = input("Please input the Pod Id:[%s]" % oldPod)
if podId == "": if podId == "":
podId = oldToken podId = oldToken
oldCluster = cfo.getEntry("cluster") oldCluster = cfo.getEntry("cluster")
clusterId = input("Please input the Cluster Id:[%s]"%oldCluster) clusterId = input("Please input the Cluster Id:[%s]" % oldCluster)
if clusterId == "": if clusterId == "":
clusterId = oldCluster clusterId = oldCluster
@ -79,18 +85,20 @@ def getUserInputs():
if oldHypervisor == "": if oldHypervisor == "":
oldHypervisor = "kvm" oldHypervisor = "kvm"
hypervisor = input("Please input the Hypervisor type kvm/lxc:[%s]"%oldHypervisor) hypervisor = input("Please input the Hypervisor type kvm/lxc:[%s]" % oldHypervisor)
if hypervisor == "": if hypervisor == "":
hypervisor = oldHypervisor hypervisor = oldHypervisor
try: try:
defaultNic = networkConfig.getDefaultNetwork() defaultNic = networkConfig.getDefaultNetwork()
except: except:
print("Failed to get default route. Please configure your network to have a default route") print(
"Failed to get default route. Please configure your network to have a default route"
)
exit(1) exit(1)
defNic = defaultNic.name defNic = defaultNic.name
network = input("Please choose which network used to create VM:[%s]"%defNic) network = input("Please choose which network used to create VM:[%s]" % defNic)
if network == "": if network == "":
if defNic == "": if defNic == "":
print("You need to specify one of Nic or bridge on your system") print("You need to specify one of Nic or bridge on your system")
@ -100,7 +108,8 @@ def getUserInputs():
return [mgtSvr, zoneToken, network, podId, clusterId, hypervisor] return [mgtSvr, zoneToken, network, podId, clusterId, hypervisor]
if __name__ == '__main__':
if __name__ == "__main__":
initLoging("@AGENTLOGDIR@/setup.log") initLoging("@AGENTLOGDIR@/setup.log")
glbEnv = globalEnv() glbEnv = globalEnv()
@ -108,13 +117,23 @@ if __name__ == '__main__':
glbEnv.agentMode = "Agent" glbEnv.agentMode = "Agent"
parser = OptionParser() parser = OptionParser()
parser.add_option("-a", action="store_true", dest="auto", help="auto mode") parser.add_option("-a", action="store_true", dest="auto", help="auto mode")
parser.add_option("-m", "--host", dest="mgt", help="Management server hostname or IP-Address") parser.add_option(
"-m", "--host", dest="mgt", help="Management server hostname or IP-Address"
)
parser.add_option("-z", "--zone", dest="zone", help="zone id") parser.add_option("-z", "--zone", dest="zone", help="zone id")
parser.add_option("-p", "--pod", dest="pod", help="pod id") parser.add_option("-p", "--pod", dest="pod", help="pod id")
parser.add_option("-c", "--cluster", dest="cluster", help="cluster id") parser.add_option("-c", "--cluster", dest="cluster", help="cluster id")
parser.add_option("-t", "--hypervisor", default="kvm", dest="hypervisor", help="hypervisor type") parser.add_option(
"-t", "--hypervisor", default="kvm", dest="hypervisor", help="hypervisor type"
)
parser.add_option("-g", "--guid", dest="guid", help="guid") parser.add_option("-g", "--guid", dest="guid", help="guid")
parser.add_option("-s", action="store_true", default=False, dest="secure", help="Secure and enable TLS for libvirtd") parser.add_option(
"-s",
action="store_true",
default=False,
dest="secure",
help="Secure and enable TLS for libvirtd",
)
parser.add_option("--pubNic", dest="pubNic", help="Public traffic interface") parser.add_option("--pubNic", dest="pubNic", help="Public traffic interface")
parser.add_option("--prvNic", dest="prvNic", help="Private traffic interface") parser.add_option("--prvNic", dest="prvNic", help="Private traffic interface")
parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface") parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface")
@ -140,15 +159,15 @@ if __name__ == '__main__':
glbEnv.pod = userInputs[3] glbEnv.pod = userInputs[3]
glbEnv.cluster = userInputs[4] glbEnv.cluster = userInputs[4]
glbEnv.hypervisor = userInputs[5] glbEnv.hypervisor = userInputs[5]
#generate UUID # generate UUID
glbEnv.uuid = old_config.getEntry("guid") glbEnv.uuid = old_config.getEntry("guid")
if glbEnv.uuid == "": if glbEnv.uuid == "":
glbEnv.uuid = bash("uuidgen").getStdout() glbEnv.uuid = bash("uuidgen").getStdout()
else: else:
for para, value in list(options.__dict__.items()): for para, value in list(options.__dict__.items()):
if value is None: if value is None:
print("Missing operand:%s"%para) print("Missing operand:%s" % para)
print("Try %s --help for more information"%sys.argv[0]) print("Try %s --help for more information" % sys.argv[0])
sys.exit(1) sys.exit(1)
glbEnv.uuid = options.guid glbEnv.uuid = options.guid
@ -168,7 +187,7 @@ if __name__ == '__main__':
try: try:
syscfg.config() syscfg.config()
print("CloudStack Agent setup is done!") print("CloudStack Agent setup is done!")
except (CloudRuntimeException,CloudInternalException) as e: except (CloudRuntimeException, CloudInternalException) as e:
print(e) print(e)
print("Try to restore your system:") print("Try to restore your system:")
try: try:

View File

@ -34,16 +34,19 @@ from threading import Thread
# ---- 2) waf configured PYTHONDIR # ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path # ---- 3) System Python path
for pythonpath in ( for pythonpath in (
"@PYTHONDIR@", "@PYTHONDIR@",
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"), os.path.join(
): os.path.dirname(__file__), os.path.pardir, os.path.pardir, "python", "lib"
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath) ),
):
if os.path.isdir(pythonpath):
sys.path.insert(0, pythonpath)
# ---- End snippet of code ---- # ---- End snippet of code ----
from cloud_utils import check_call, CalledProcessError, read_properties from cloud_utils import check_call, CalledProcessError, read_properties
cfg = "@MSCONF@/db.properties" cfg = "@MSCONF@/db.properties"
#---------------------- option parsing and command line checks ------------------------ # ---------------------- option parsing and command line checks ------------------------
usage = """%prog <license file> <-a | host names / IP addresses...> usage = """%prog <license file> <-a | host names / IP addresses...>
@ -51,132 +54,171 @@ usage = """%prog <license file> <-a | host names / IP addresses...>
This command deploys the license file specified in the command line into a specific XenServer host or all XenServer hosts known to the management server.""" This command deploys the license file specified in the command line into a specific XenServer host or all XenServer hosts known to the management server."""
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
parser.add_option("-a", "--all", action="store_true", dest="all", default=False, parser.add_option(
help="deploy to all known hosts rather that a single host") "-a",
"--all",
action="store_true",
dest="all",
default=False,
help="deploy to all known hosts rather that a single host",
)
#------------------ functions -------------------- # ------------------ functions --------------------
def e(msg): parser.error(msg)
def getknownhosts(host,username,password): def e(msg):
conn = mysql.connector.connect(host=host, user=username, password=password) parser.error(msg)
cur = conn.cursor()
cur.execute("SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'username' and setup = 1")
usernames = dict(cur.fetchall()) def getknownhosts(host, username, password):
cur.execute("SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'password' and setup = 1") conn = mysql.connector.connect(host=host, user=username, password=password)
passwords = dict(cur.fetchall()) cur = conn.cursor()
creds = dict( [ [x,(usernames[x],passwords[x])] for x in list(usernames.keys()) ] ) cur.execute(
cur.close() "SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'username' and setup = 1"
conn.close() )
return creds usernames = dict(cur.fetchall())
cur.execute(
"SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'password' and setup = 1"
)
passwords = dict(cur.fetchall())
creds = dict([[x, (usernames[x], passwords[x])] for x in list(usernames.keys())])
cur.close()
conn.close()
return creds
def splitlast(string, splitter):
splitted = string.split(splitter)
first, last = splitter.join(splitted[:-1]), splitted[-1]
return first, last
def splitlast(string,splitter):
splitted = string.split(splitter)
first,last = splitter.join(splitted[:-1]),splitted[-1]
return first,last
def parseuserpwfromhosts(hosts): def parseuserpwfromhosts(hosts):
creds = {} creds = {}
for host in hosts: for host in hosts:
user = "root" user = "root"
password = "" password = ""
if "@" in host: if "@" in host:
user,host = splitlast(host,"@") user, host = splitlast(host, "@")
if ":" in user: if ":" in user:
user,password = splitlast(user,":") user, password = splitlast(user, ":")
creds[host] = (user,password) creds[host] = (user, password)
return creds return creds
class XenServerConfigurator(Thread): class XenServerConfigurator(Thread):
def __init__(self,host,user,password,keyfiledata): def __init__(self, host, user, password, keyfiledata):
Thread.__init__(self) Thread.__init__(self)
self.host = host self.host = host
self.user = user self.user = user
self.password = password self.password = password
self.keyfiledata = keyfiledata self.keyfiledata = keyfiledata
self.retval = None # means all's good self.retval = None # means all's good
self.stdout = "" self.stdout = ""
self.stderr = "" self.stderr = ""
self.state = 'initialized' self.state = "initialized"
def run(self): def run(self):
try: try:
self.state = 'running' self.state = "running"
c = paramiko.SSHClient() c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(self.host,username=self.user,password=self.password) c.connect(self.host, username=self.user, password=self.password)
sftp = c.open_sftp() sftp = c.open_sftp()
sftp.chdir("/tmp") sftp.chdir("/tmp")
f = sftp.open("xen-license","w") f = sftp.open("xen-license", "w")
f.write(self.keyfiledata) f.write(self.keyfiledata)
f.close() f.close()
sftp.close() sftp.close()
stdin,stdout,stderr = c.exec_command("xe host-license-add license-file=/tmp/xen-license") stdin, stdout, stderr = c.exec_command(
c.exec_command("false") "xe host-license-add license-file=/tmp/xen-license"
self.stdout = stdout.read(-1) )
self.stderr = stderr.read(-1) c.exec_command("false")
self.retval = stdin.channel.recv_exit_status() self.stdout = stdout.read(-1)
c.close() self.stderr = stderr.read(-1)
if self.retval != 0: self.state = 'failed' self.retval = stdin.channel.recv_exit_status()
else: self.state = 'finished' c.close()
if self.retval != 0:
self.state = "failed"
else:
self.state = "finished"
except Exception as e: except Exception as e:
self.state = 'failed' self.state = "failed"
self.retval = e self.retval = e
#raise # raise
def __str__(self): def __str__(self):
if self.state == 'failed': if self.state == "failed":
return "<%s XenServerConfigurator on %s@%s: %s>"%(self.state,self.user,self.host,str(self.retval)) return "<%s XenServerConfigurator on %s@%s: %s>" % (
else: self.state,
return "<%s XenServerConfigurator on %s@%s>"%(self.state,self.user,self.host) self.user,
self.host,
str(self.retval),
)
else:
return "<%s XenServerConfigurator on %s@%s>" % (
self.state,
self.user,
self.host,
)
#------------- actual code --------------------
# ------------- actual code --------------------
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
try: try:
licensefile,args = args[0],args[1:] licensefile, args = args[0], args[1:]
except IndexError: e("The first argument must be the license file to use") except IndexError:
e("The first argument must be the license file to use")
if options.all: if options.all:
if len(args) != 0: e("IP addresses cannot be specified if -a is specified") if len(args) != 0:
config = read_properties(cfg) e("IP addresses cannot be specified if -a is specified")
creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"]) config = read_properties(cfg)
hosts = list(creds.keys()) creds = getknownhosts(
config["db.cloud.host"],
config["db.cloud.username"],
config["db.cloud.password"],
)
hosts = list(creds.keys())
else: else:
if not args: e("You must specify at least one IP address, or -a") if not args:
hosts = args e("You must specify at least one IP address, or -a")
creds = parseuserpwfromhosts(hosts) hosts = args
creds = parseuserpwfromhosts(hosts)
try: try:
keyfiledata = file(licensefile).read(-1) keyfiledata = file(licensefile).read(-1)
except OSError as e: except OSError as e:
sys.stderr.write("The file %s cannot be opened"%licensefile) sys.stderr.write("The file %s cannot be opened" % licensefile)
sys.exit(1) sys.exit(1)
configurators = [] configurators = []
for host,(user,password) in list(creds.items()): for host, (user, password) in list(creds.items()):
configurators.append ( XenServerConfigurator(host,user,password,keyfiledata ) ) configurators.append(XenServerConfigurator(host, user, password, keyfiledata))
for c in configurators: c.start()
for c in configurators: for c in configurators:
print(c.host + "...", end=' ') c.start()
c.join()
if c.state == 'failed':
if c.retval:
msg = "failed with return code %s: %s%s"%(c.retval,c.stdout,c.stderr)
msg = msg.strip()
print(msg)
else: print("failed: %s"%c.retval)
else:
print("done")
successes = len( [ a for a in configurators if not a.state == 'failed' ] ) for c in configurators:
failures = len( [ a for a in configurators if a.state == 'failed' ] ) print(c.host + "...", end=" ")
c.join()
if c.state == "failed":
if c.retval:
msg = "failed with return code %s: %s%s" % (c.retval, c.stdout, c.stderr)
msg = msg.strip()
print(msg)
else:
print("failed: %s" % c.retval)
else:
print("done")
print("%3s successes"%successes) successes = len([a for a in configurators if not a.state == "failed"])
print("%3s failures"%failures) failures = len([a for a in configurators if a.state == "failed"])
print("%3s successes" % successes)
print("%3s failures" % failures)

View File

@ -7,9 +7,9 @@
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -25,4 +25,5 @@ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
import cloudtool import cloudtool
ret = cloudtool.main() ret = cloudtool.main()
if ret: sys.exit(ret) if ret:
sys.exit(ret)

View File

@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -18,64 +18,99 @@
import subprocess import subprocess
depLibraries = ['bzip2', 'gzip', 'unzip', 'openssh-clients', 'nfs-utils', 'wget', 'ws-commons-util', 'commons-dbcp', depLibraries = [
'commons-collections', 'commons-httpclient', 'jpackage-utils', 'mysql-connector-python3', 'python-paramiko', 'ipmitool', 'commons-httpclient', 'commons-collections', "bzip2",
'commons-pool', 'commons-dbcp', 'jakarta-commons-logging', 'java-*-openjdk'] "gzip",
"unzip",
"openssh-clients",
"nfs-utils",
"wget",
"ws-commons-util",
"commons-dbcp",
"commons-collections",
"commons-httpclient",
"jpackage-utils",
"mysql-connector-python3",
"python-paramiko",
"ipmitool",
"commons-httpclient",
"commons-collections",
"commons-pool",
"commons-dbcp",
"jakarta-commons-logging",
"java-*-openjdk",
]
def runCmd(cmds): def runCmd(cmds):
process = subprocess.Popen(' '.join(cmds), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) process = subprocess.Popen(
" ".join(cmds), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise Exception(stderr.decode('utf-8')) raise Exception(stderr.decode("utf-8"))
return stdout.decode('utf-8') return stdout.decode("utf-8")
def getDependentLibraryInfo(): def getDependentLibraryInfo():
def getVersion(res, pkgname): def getVersion(res, pkgname):
start = False start = False
for l in res.split('\n'): for l in res.split("\n"):
if "Installed Packages" in l: if "Installed Packages" in l:
start = True start = True
continue continue
if not start: continue if not start:
continue
(key, value) = l.split(':', 2)
(key, value) = l.split(":", 2)
key = key.strip() key = key.strip()
value = value.strip() value = value.strip()
if key == 'Name' and "*" not in pkgname and pkgname not in value: if key == "Name" and "*" not in pkgname and pkgname not in value:
print("Required package name %s doesn't equal to package %s installed"%(pkgname, value)) print(
return 'UNKNOWN' "Required package name %s doesn't equal to package %s installed"
if 'Version' in key: return value % (pkgname, value)
if 'Description' in key: return 'UNKNOWN' # we hit the end )
return 'UNKNOWN' return "UNKNOWN"
if "Version" in key:
return value
if "Description" in key:
return "UNKNOWN" # we hit the end
return "UNKNOWN"
libraryMap = {} libraryMap = {}
for l in depLibraries: for l in depLibraries:
cmd = ['yum', 'info', '"%s"'%l] cmd = ["yum", "info", '"%s"' % l]
try: try:
result = runCmd(cmd) result = runCmd(cmd)
version = getVersion(result, l) version = getVersion(result, l)
libraryMap[l] = version libraryMap[l] = version
except Exception as e: except Exception as e:
print("When finding %s, encounters %s"%(l, e)) print("When finding %s, encounters %s" % (l, e))
continue continue
return libraryMap return libraryMap
def arrangeOutPut(libraryMap): def arrangeOutPut(libraryMap):
msg = ['\n\n\nBelow is the checking list of library version that CloudStack depends on:'] msg = [
"\n\n\nBelow is the checking list of library version that CloudStack depends on:"
]
for l in depLibraries: for l in depLibraries:
if l in libraryMap: if l in libraryMap:
entry = "%-40s: %s"%(l, libraryMap[l]) entry = "%-40s: %s" % (l, libraryMap[l])
else: else:
entry = "%-40s: %s"%(l, 'UNKNOWN') entry = "%-40s: %s" % (l, "UNKNOWN")
msg.append(entry) msg.append(entry)
print('\n'.join(msg)) print("\n".join(msg))
if __name__ == '__main__':
pythonDepLibraries = ['python', 'python3'] if __name__ == "__main__":
relver = runCmd(['rpm', '-q', 'centos-release']) pythonDepLibraries = ["python", "python3"]
if relver.startswith('centos-release-') and int(relver[len('centos-release-')]) >= 8: relver = runCmd(["rpm", "-q", "centos-release"])
pythonDepLibraries = ['python2', 'python36'] if (
relver.startswith("centos-release-")
and int(relver[len("centos-release-")]) >= 8
):
pythonDepLibraries = ["python2", "python36"]
depLibraries = pythonDepLibraries + depLibraries depLibraries = pythonDepLibraries + depLibraries
arrangeOutPut(getDependentLibraryInfo()) arrangeOutPut(getDependentLibraryInfo())

View File

@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -23,11 +23,15 @@ import traceback
from os.path import exists, join from os.path import exists, join
from signal import alarm, signal, SIGALRM, SIGKILL from signal import alarm, signal, SIGALRM, SIGKILL
class CloudRuntimeException(Exception): class CloudRuntimeException(Exception):
def __init__(self, errMsg): def __init__(self, errMsg):
self.errMsg = errMsg self.errMsg = errMsg
def __str__(self): def __str__(self):
return self.errMsg return self.errMsg
def formatExceptionInfo(maxTBlevel=5): def formatExceptionInfo(maxTBlevel=5):
cla, exc, trbk = sys.exc_info() cla, exc, trbk = sys.exc_info()
excTb = traceback.format_tb(trbk, maxTBlevel) excTb = traceback.format_tb(trbk, maxTBlevel)
@ -36,10 +40,11 @@ def formatExceptionInfo(maxTBlevel=5):
msg += tb msg += tb
return msg return msg
class bash: class bash:
def __init__(self, args, timeout=600): def __init__(self, args, timeout=600):
self.args = args self.args = args
logging.debug("execute:%s"%args) logging.debug("execute:%s" % args)
self.timeout = timeout self.timeout = timeout
self.process = None self.process = None
self.success = False self.success = False
@ -48,6 +53,7 @@ class bash:
def run(self): def run(self):
class Alarm(Exception): class Alarm(Exception):
pass pass
def alarm_handler(signum, frame): def alarm_handler(signum, frame):
raise Alarm raise Alarm
@ -63,21 +69,21 @@ class bash:
alarm(0) alarm(0)
except Alarm: except Alarm:
os.kill(self.process.pid, SIGKILL) os.kill(self.process.pid, SIGKILL)
raise CloudRuntimeException("Timeout during command execution") raise CloudRuntimeException("Timeout during command execution")
self.success = self.process.returncode == 0 self.success = self.process.returncode == 0
except: except:
raise CloudRuntimeException(formatExceptionInfo()) raise CloudRuntimeException(formatExceptionInfo())
# if not self.success: # if not self.success:
# raise CloudRuntimeException(self.getStderr()) # raise CloudRuntimeException(self.getStderr())
def isSuccess(self): def isSuccess(self):
return self.success return self.success
def getStdout(self): def getStdout(self):
return self.stdout.strip("\n") return self.stdout.strip("\n")
def getLines(self): def getLines(self):
return self.stdout.split("\n") return self.stdout.split("\n")
@ -88,130 +94,150 @@ class bash:
def initLoging(logFile=None): def initLoging(logFile=None):
try: try:
if logFile is None: if logFile is None:
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
else: else:
logging.basicConfig(filename=logFile, level=logging.DEBUG) logging.basicConfig(filename=logFile, level=logging.DEBUG)
except: except:
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
def writeProgressBar(msg, result=None):
def writeProgressBar(msg, result=None):
if msg is not None: if msg is not None:
output = "%-80s"%msg output = "%-80s" % msg
elif result is True: elif result is True:
output = "[ \033[92m%-2s\033[0m ]\n"%"OK" output = "[ \033[92m%-2s\033[0m ]\n" % "OK"
elif result is False: elif result is False:
output = "[ \033[91m%-6s\033[0m ]\n"%"FAILED" output = "[ \033[91m%-6s\033[0m ]\n" % "FAILED"
sys.stdout.write(output) sys.stdout.write(output)
sys.stdout.flush() sys.stdout.flush()
def printError(msg): def printError(msg):
sys.stderr.write(msg) sys.stderr.write(msg)
sys.stderr.write("\n") sys.stderr.write("\n")
sys.stderr.flush() sys.stderr.flush()
def printMsg(msg): def printMsg(msg):
sys.stdout.write(msg+"\n") sys.stdout.write(msg + "\n")
sys.stdout.flush() sys.stdout.flush()
def checkRpm(pkgName): def checkRpm(pkgName):
chkPkg = bash("rpm -q %s"%pkgName) chkPkg = bash("rpm -q %s" % pkgName)
writeProgressBar("Checking %s"%pkgName, None) writeProgressBar("Checking %s" % pkgName, None)
if not chkPkg.isSuccess(): if not chkPkg.isSuccess():
writeProgressBar(None, False) writeProgressBar(None, False)
printError("%s is not found, please make sure it is installed. You may try 'yum install %s'\n"%(pkgName, pkgName)) printError(
"%s is not found, please make sure it is installed. You may try 'yum install %s'\n"
% (pkgName, pkgName)
)
return False return False
else: else:
writeProgressBar(None, True) writeProgressBar(None, True)
return True return True
def checkEnv(): def checkEnv():
writeProgressBar("Checking is root") writeProgressBar("Checking is root")
ret = bash("whoami") ret = bash("whoami")
if ret.getStdout() != "root": if ret.getStdout() != "root":
writeProgressBar(None, False) writeProgressBar(None, False)
printError("This script must run as root") printError("This script must run as root")
return False return False
else: else:
writeProgressBar(None, True) writeProgressBar(None, True)
pkgList = ['tftp-server', 'syslinux', 'xinetd', 'chkconfig', 'dhcp'] pkgList = ["tftp-server", "syslinux", "xinetd", "chkconfig", "dhcp"]
for pkg in pkgList: for pkg in pkgList:
if not checkRpm(pkg): if not checkRpm(pkg):
return False return False
return True return True
def exitIfFail(ret): def exitIfFail(ret):
if not ret: sys.exit(1) if not ret:
sys.exit(1)
def bashWithResult(cmd): def bashWithResult(cmd):
writeProgressBar("Executing '%s'"%cmd) writeProgressBar("Executing '%s'" % cmd)
ret = bash(cmd) ret = bash(cmd)
if not ret.isSuccess(): if not ret.isSuccess():
writeProgressBar(None, False) writeProgressBar(None, False)
writeProgressBar(ret.getStderr() + '\n') writeProgressBar(ret.getStderr() + "\n")
return False return False
else: else:
writeProgressBar(None, True) writeProgressBar(None, True)
return True return True
def configurePxeStuff():
stuff = ['tftp', 'xinetd', 'dhcpd'] def configurePxeStuff():
cmds = ['chkconfig --level 345 %s on' % i for i in stuff] stuff = ["tftp", "xinetd", "dhcpd"]
cmds.append('/etc/init.d/xinetd restart') cmds = ["chkconfig --level 345 %s on" % i for i in stuff]
cmds.append("/etc/init.d/xinetd restart")
for cmd in cmds: for cmd in cmds:
if not bashWithResult(cmd): return False if not bashWithResult(cmd):
return False
chkIptable = bash('chkconfig --list iptables')
if 'on' in chkIptable.getStdout(): chkIptable = bash("chkconfig --list iptables")
if "on" in chkIptable.getStdout():
printMsg("Detected iptables is running, need to open tftp port 69") printMsg("Detected iptables is running, need to open tftp port 69")
if not bashWithResult('iptables -I INPUT 1 -p udp --dport 69 -j ACCEPT'): return False if not bashWithResult("iptables -I INPUT 1 -p udp --dport 69 -j ACCEPT"):
if not bashWithResult('/etc/init.d/iptables save'): return False return False
if not bashWithResult("/etc/init.d/iptables save"):
return True return False
return True
def getTftpRootDir(tftpRootDirList): def getTftpRootDir(tftpRootDirList):
tftpRoot = bash("cat /etc/xinetd.d/tftp | grep server_args") tftpRoot = bash("cat /etc/xinetd.d/tftp | grep server_args")
if not tftpRoot.isSuccess(): if not tftpRoot.isSuccess():
printError("Cannot get tftp root directory from /etc/xinetd.d/tftp, here may be something wrong with your tftp-server, try reinstall it\n") printError(
"Cannot get tftp root directory from /etc/xinetd.d/tftp, here may be something wrong with your tftp-server, try reinstall it\n"
)
return False return False
tftpRootDir = tftpRoot.getStdout() tftpRootDir = tftpRoot.getStdout()
index = tftpRootDir.find("/") index = tftpRootDir.find("/")
if index == -1: if index == -1:
printError("Wrong server_arg in /etc/xinetd.d/tftp (%s)"%tftpRootDir) printError("Wrong server_arg in /etc/xinetd.d/tftp (%s)" % tftpRootDir)
return False return False
tftpRootDir = tftpRootDir[index:] tftpRootDir = tftpRootDir[index:]
tftpRootDirList.append(tftpRootDir) tftpRootDirList.append(tftpRootDir)
return True return True
def preparePING(tftpRootDir): def preparePING(tftpRootDir):
pingFiles = ['boot.msg', 'initrd.gz', 'kernel', 'pxelinux.0'] pingFiles = ["boot.msg", "initrd.gz", "kernel", "pxelinux.0"]
pingDir = "/usr/share/PING" pingDir = "/usr/share/PING"
for f in pingFiles: for f in pingFiles:
path = join(pingDir, f) path = join(pingDir, f)
if not exists(path): if not exists(path):
printError("Cannot find %s, please make sure PING-3.01 is installed"%path) printError("Cannot find %s, please make sure PING-3.01 is installed" % path)
return False return False
if not bashWithResult("cp -f %s %s"%(path, tftpRootDir)): return False if not bashWithResult("cp -f %s %s" % (path, tftpRootDir)):
return False
if not bashWithResult("mkdir -p %s/pxelinux.cfg"%tftpRootDir): return False
if not bashWithResult("mkdir -p %s/pxelinux.cfg" % tftpRootDir):
return False
return True return True
if __name__ == "__main__": if __name__ == "__main__":
initLoging("/tmp/cloud-setup-baremetal.log") initLoging("/tmp/cloud-setup-baremetal.log")
tftpRootDirList = [] tftpRootDirList = []
exitIfFail(checkEnv()) exitIfFail(checkEnv())
exitIfFail(configurePxeStuff()) exitIfFail(configurePxeStuff())
exitIfFail(getTftpRootDir(tftpRootDirList)) exitIfFail(getTftpRootDir(tftpRootDirList))
tftpRootDir = tftpRootDirList[0].strip() tftpRootDir = tftpRootDirList[0].strip()
exitIfFail(preparePING(tftpRootDir)) exitIfFail(preparePING(tftpRootDir))
printMsg("") printMsg("")
printMsg("Setup BareMetal PXE server successfully") printMsg("Setup BareMetal PXE server successfully")
printMsg("TFTP root directory is: %s\n"%tftpRootDir) printMsg("TFTP root directory is: %s\n" % tftpRootDir)
sys.exit(0) sys.exit(0)

View File

@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -18,11 +18,14 @@
# Version @VERSION@ # Version @VERSION@
# #
# A plugin for executing script needed by vmops cloud # A plugin for executing script needed by vmops cloud
import os, sys, time import os, sys, time
import XenAPIPlugin import XenAPIPlugin
sys.path.extend(["/opt/xensource/sm/", "/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"])
sys.path.extend(
["/opt/xensource/sm/", "/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"]
)
import util import util
import base64 import base64
import socket import socket
@ -37,15 +40,18 @@ import logging
lib.setup_logging("/var/log/cloud/storageplugin.log") lib.setup_logging("/var/log/cloud/storageplugin.log")
def echo(fn): def echo(fn):
def wrapped(*v, **k): def wrapped(*v, **k):
name = fn.__name__ name = fn.__name__
logging.debug("#### xen plugin enter %s ####" % name ) logging.debug("#### xen plugin enter %s ####" % name)
res = fn(*v, **k) res = fn(*v, **k)
logging.debug("#### xen plugin exit %s ####" % name ) logging.debug("#### xen plugin exit %s ####" % name)
return res return res
return wrapped return wrapped
@echo @echo
def downloadTemplateFromUrl(session, args): def downloadTemplateFromUrl(session, args):
destPath = args["destPath"] destPath = args["destPath"]
@ -59,17 +65,23 @@ def downloadTemplateFromUrl(session, args):
except: except:
logging.debug("exception: " + str(sys.exc_info())) logging.debug("exception: " + str(sys.exc_info()))
return "" return ""
@echo @echo
def getTemplateSize(session, args): def getTemplateSize(session, args):
srcUrl = args["srcUrl"] srcUrl = args["srcUrl"]
try: try:
template = urllib2.urlopen(srcUrl) template = urllib2.urlopen(srcUrl)
headers = template.info() headers = template.info()
return str(headers["content-length"]) return str(headers["content-length"])
except: except:
return "" return ""
if __name__ == "__main__": if __name__ == "__main__":
XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl XenAPIPlugin.dispatch(
,"getTemplateSize": getTemplateSize {
}) "downloadTemplateFromUrl": downloadTemplateFromUrl,
"getTemplateSize": getTemplateSize,
}
)

View File

@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -18,10 +18,11 @@
# Version @VERSION@ # Version @VERSION@
# #
# A plugin for executing script needed by vmops cloud # A plugin for executing script needed by vmops cloud
import os, sys, time import os, sys, time
import XenAPIPlugin import XenAPIPlugin
if os.path.exists("/opt/xensource/sm"): if os.path.exists("/opt/xensource/sm"):
sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"]) sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"])
if os.path.exists("/usr/lib/xcp/sm"): if os.path.exists("/usr/lib/xcp/sm"):
@ -33,119 +34,147 @@ import logging
lib.setup_logging("/var/log/cloud/cloud.log") lib.setup_logging("/var/log/cloud/cloud.log")
def echo(fn): def echo(fn):
def wrapped(*v, **k): def wrapped(*v, **k):
name = fn.__name__ name = fn.__name__
logging.debug("#### CLOUD enter %s ####" % name ) logging.debug("#### CLOUD enter %s ####" % name)
res = fn(*v, **k) res = fn(*v, **k)
logging.debug("#### CLOUD exit %s ####" % name ) logging.debug("#### CLOUD exit %s ####" % name)
return res return res
return wrapped return wrapped
@echo @echo
def forceShutdownVM(session, args): def forceShutdownVM(session, args):
domId = args['domId'] domId = args["domId"]
try: try:
cmd = ["/opt/xensource/debug/xenops", "destroy_domain", "-domid", domId] cmd = ["/opt/xensource/debug/xenops", "destroy_domain", "-domid", domId]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def create_privatetemplate_from_snapshot(session, args): def create_privatetemplate_from_snapshot(session, args):
templatePath = args['templatePath'] templatePath = args["templatePath"]
snapshotPath = args['snapshotPath'] snapshotPath = args["snapshotPath"]
tmpltLocalDir = args['tmpltLocalDir'] tmpltLocalDir = args["tmpltLocalDir"]
try: try:
cmd = ["bash", "/opt/cloud/bin/create_privatetemplate_from_snapshot.sh",snapshotPath, templatePath, tmpltLocalDir] cmd = [
"bash",
"/opt/cloud/bin/create_privatetemplate_from_snapshot.sh",
snapshotPath,
templatePath,
tmpltLocalDir,
]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def upgrade_snapshot(session, args): def upgrade_snapshot(session, args):
templatePath = args['templatePath'] templatePath = args["templatePath"]
snapshotPath = args['snapshotPath'] snapshotPath = args["snapshotPath"]
try: try:
cmd = ["bash", "/opt/cloud/bin/upgrate_snapshot.sh",snapshotPath, templatePath] cmd = ["bash", "/opt/cloud/bin/upgrate_snapshot.sh", snapshotPath, templatePath]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def copy_vhd_to_secondarystorage(session, args): def copy_vhd_to_secondarystorage(session, args):
mountpoint = args['mountpoint'] mountpoint = args["mountpoint"]
vdiuuid = args['vdiuuid'] vdiuuid = args["vdiuuid"]
sruuid = args['sruuid'] sruuid = args["sruuid"]
try: try:
cmd = ["bash", "/opt/cloud/bin/copy_vhd_to_secondarystorage.sh", mountpoint, vdiuuid, sruuid] cmd = [
"bash",
"/opt/cloud/bin/copy_vhd_to_secondarystorage.sh",
mountpoint,
vdiuuid,
sruuid,
]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def copy_vhd_from_secondarystorage(session, args): def copy_vhd_from_secondarystorage(session, args):
mountpoint = args['mountpoint'] mountpoint = args["mountpoint"]
sruuid = args['sruuid'] sruuid = args["sruuid"]
namelabel = args['namelabel'] namelabel = args["namelabel"]
try: try:
cmd = ["bash", "/opt/cloud/bin/copy_vhd_from_secondarystorage.sh", mountpoint, sruuid, namelabel] cmd = [
"bash",
"/opt/cloud/bin/copy_vhd_from_secondarystorage.sh",
mountpoint,
sruuid,
namelabel,
]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def remove_corrupt_vdi(session, args): def remove_corrupt_vdi(session, args):
vdifile = args['vdifile'] vdifile = args["vdifile"]
try: try:
cmd = ['rm', '-f', vdifile] cmd = ["rm", "-f", vdifile]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '10#failed' txt = "10#failed"
return txt return txt
@echo @echo
def setup_heartbeat_sr(session, args): def setup_heartbeat_sr(session, args):
host = args['host'] host = args["host"]
sr = args['sr'] sr = args["sr"]
try: try:
cmd = ["bash", "/opt/cloud/bin/setup_heartbeat_sr.sh", host, sr] cmd = ["bash", "/opt/cloud/bin/setup_heartbeat_sr.sh", host, sr]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '' txt = ""
return txt return txt
@echo @echo
def setup_heartbeat_file(session, args): def setup_heartbeat_file(session, args):
host = args['host'] host = args["host"]
sr = args['sr'] sr = args["sr"]
add = args['add'] add = args["add"]
try: try:
cmd = ["bash", "/opt/cloud/bin/setup_heartbeat_file.sh", host, sr, add] cmd = ["bash", "/opt/cloud/bin/setup_heartbeat_file.sh", host, sr, add]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt = '' txt = ""
return txt return txt
@echo @echo
def heartbeat(session, args): def heartbeat(session, args):
host = args['host'] host = args["host"]
timeout = args['timeout'] timeout = args["timeout"]
interval = args['interval'] interval = args["interval"]
try: try:
cmd = ["/bin/bash", "/opt/cloud/bin/launch_hb.sh", host, timeout, interval] cmd = ["/bin/bash", "/opt/cloud/bin/launch_hb.sh", host, timeout, interval]
txt = util.pread2(cmd) txt = util.pread2(cmd)
except: except:
txt='fail' txt = "fail"
return txt return txt
@echo @echo
def asmonitor(session, args): def asmonitor(session, args):
try: try:
@ -153,7 +182,21 @@ def asmonitor(session, args):
result = perfmod.get_vm_group_perfmon(args) result = perfmod.get_vm_group_perfmon(args)
return result return result
except: except:
return 'fail' return "fail"
if __name__ == "__main__": if __name__ == "__main__":
XenAPIPlugin.dispatch({"forceShutdownVM":forceShutdownVM, "upgrade_snapshot":upgrade_snapshot, "create_privatetemplate_from_snapshot":create_privatetemplate_from_snapshot, "copy_vhd_to_secondarystorage":copy_vhd_to_secondarystorage, "copy_vhd_from_secondarystorage":copy_vhd_from_secondarystorage, "setup_heartbeat_sr":setup_heartbeat_sr, "setup_heartbeat_file":setup_heartbeat_file, "heartbeat": heartbeat, "asmonitor": asmonitor, "remove_corrupt_vdi": remove_corrupt_vdi}) XenAPIPlugin.dispatch(
{
"forceShutdownVM": forceShutdownVM,
"upgrade_snapshot": upgrade_snapshot,
"create_privatetemplate_from_snapshot": create_privatetemplate_from_snapshot,
"copy_vhd_to_secondarystorage": copy_vhd_to_secondarystorage,
"copy_vhd_from_secondarystorage": copy_vhd_from_secondarystorage,
"setup_heartbeat_sr": setup_heartbeat_sr,
"setup_heartbeat_file": setup_heartbeat_file,
"heartbeat": heartbeat,
"asmonitor": asmonitor,
"remove_corrupt_vdi": remove_corrupt_vdi,
}
)

View File

@ -31,25 +31,33 @@ import shutil
# squelch mysqldb spurious warnings # squelch mysqldb spurious warnings
import warnings import warnings
warnings.simplefilter('ignore')
warnings.simplefilter("ignore")
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ---- # ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
# ---- We do this so cloud_utils can be looked up in the following order: # ---- We do this so cloud_utils can be looked up in the following order:
# ---- 1) Sources directory # ---- 1) Sources directory
# ---- 2) waf configured PYTHONDIR # ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path # ---- 3) System Python path
for pythonpath in ( for pythonpath in (
"@PYTHONDIR@", "@PYTHONDIR@",
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"), os.path.join(
): os.path.dirname(__file__), os.path.pardir, os.path.pardir, "python", "lib"
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath) ),
):
if os.path.isdir(pythonpath):
sys.path.insert(0, pythonpath)
# ---- End snippet of code ---- # ---- End snippet of code ----
def runCmd(cmds): def runCmd(cmds):
process = subprocess.Popen(' '.join(cmds), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) process = subprocess.Popen(
" ".join(cmds), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise Exception(stderr) raise Exception(stderr)
return stdout.decode('utf-8') return stdout.decode("utf-8")
class DBDeployer(object): class DBDeployer(object):
parser = None parser = None
@ -62,15 +70,15 @@ class DBDeployer(object):
dbConfPath = r"@MSCONF@" dbConfPath = r"@MSCONF@"
dbDotProperties = {} dbDotProperties = {}
dbDotPropertiesIndex = 0 dbDotPropertiesIndex = 0
encryptionKeyFile = '@MSCONF@/key' encryptionKeyFile = "@MSCONF@/key"
encryptionJarPath = '@COMMONLIBDIR@/lib/cloudstack-utils.jar' encryptionJarPath = "@COMMONLIBDIR@/lib/cloudstack-utils.jar"
success = False success = False
magicString = 'This_is_a_magic_string_i_think_no_one_will_duplicate' magicString = "This_is_a_magic_string_i_think_no_one_will_duplicate"
def preRun(self): def preRun(self):
def backUpDbDotProperties(): def backUpDbDotProperties():
dbpPath = os.path.join(self.dbConfPath, 'db.properties') dbpPath = os.path.join(self.dbConfPath, "db.properties")
copyPath = os.path.join(self.dbConfPath, 'db.properties.origin') copyPath = os.path.join(self.dbConfPath, "db.properties.origin")
if os.path.isfile(dbpPath): if os.path.isfile(dbpPath):
shutil.copy2(dbpPath, copyPath) shutil.copy2(dbpPath, copyPath)
@ -79,8 +87,8 @@ class DBDeployer(object):
def postRun(self): def postRun(self):
def cleanOrRecoverDbDotProperties(): def cleanOrRecoverDbDotProperties():
dbpPath = os.path.join(self.dbConfPath, 'db.properties') dbpPath = os.path.join(self.dbConfPath, "db.properties")
copyPath = os.path.join(self.dbConfPath, 'db.properties.origin') copyPath = os.path.join(self.dbConfPath, "db.properties.origin")
if os.path.isfile(copyPath): if os.path.isfile(copyPath):
if not self.success: if not self.success:
shutil.copy2(copyPath, dbpPath) shutil.copy2(copyPath, dbpPath)
@ -88,21 +96,20 @@ class DBDeployer(object):
cleanOrRecoverDbDotProperties() cleanOrRecoverDbDotProperties()
def info(self, msg, result=None): def info(self, msg, result=None):
output = "" output = ""
if msg is not None: if msg is not None:
output = "%-80s"%msg output = "%-80s" % msg
if result is True: if result is True:
output += "[ \033[92m%-2s\033[0m ]\n"%"OK" output += "[ \033[92m%-2s\033[0m ]\n" % "OK"
elif result is False: elif result is False:
output += "[ \033[91m%-6s\033[0m ]\n"%"FAILED" output += "[ \033[91m%-6s\033[0m ]\n" % "FAILED"
sys.stdout.write(output) sys.stdout.write(output)
sys.stdout.flush() sys.stdout.flush()
def debug(self, msg): def debug(self, msg):
msg = "DEBUG:%s"%msg msg = "DEBUG:%s" % msg
sys.stdout.write(msg) sys.stdout.write(msg)
sys.stdout.flush() sys.stdout.flush()
@ -122,7 +129,8 @@ class DBDeployer(object):
def errorAndExit(self, msg): def errorAndExit(self, msg):
self.postRun() self.postRun()
err = '''\n\nWe apologize for below error: err = (
"""\n\nWe apologize for below error:
*************************************************************** ***************************************************************
%s %s
*************************************************************** ***************************************************************
@ -131,36 +139,48 @@ Please run:
cloud-setup-encryption -h cloud-setup-encryption -h
for full help for full help
''' % msg """
% msg
)
sys.stderr.write(err) sys.stderr.write(err)
sys.stderr.flush() sys.stderr.flush()
sys.exit(1) sys.exit(1)
def prepareDBFiles(self): def prepareDBFiles(self):
def prepareDBDotProperties(): def prepareDBDotProperties():
dbpPath = os.path.join(self.dbConfPath, 'db.properties') dbpPath = os.path.join(self.dbConfPath, "db.properties")
dbproperties = file(dbpPath).read().splitlines() dbproperties = file(dbpPath).read().splitlines()
newdbp = [] newdbp = []
emptyLine = 0 emptyLine = 0
for line in dbproperties: for line in dbproperties:
passed = False passed = False
line = line.strip() line = line.strip()
if line.startswith("#"): key = line; value = ''; passed = True if line.startswith("#"):
if line == '' or line == '\n': key = self.magicString + str(emptyLine); value = ''; emptyLine += 1; passed = True key = line
value = ""
passed = True
if line == "" or line == "\n":
key = self.magicString + str(emptyLine)
value = ""
emptyLine += 1
passed = True
try: try:
if not passed: if not passed:
(key, value) = line.split('=', 1) (key, value) = line.split("=", 1)
except Exception as e: except Exception as e:
err = '''Wrong format in %s (%s): err = """Wrong format in %s (%s):
Besides comments beginning "#" and empty line, all key-value pairs must be in formula of Besides comments beginning "#" and empty line, all key-value pairs must be in formula of
key=value key=value
for example: for example:
db.cloud.username = cloud db.cloud.username = cloud
''' % (dbpPath, line) """ % (
dbpPath,
line,
)
self.errorAndExit(err) self.errorAndExit(err)
self.putDbProperty(key, value) self.putDbProperty(key, value)
self.info("Preparing %s"%dbpPath, True) self.info("Preparing %s" % dbpPath, True)
prepareDBDotProperties() prepareDBDotProperties()
@ -172,41 +192,69 @@ for example:
if key.startswith("#"): if key.startswith("#"):
entries.insert(index, key) entries.insert(index, key)
elif key.startswith(self.magicString): elif key.startswith(self.magicString):
entries.insert(index, '') entries.insert(index, "")
else: else:
entries.insert(index, "%s=%s"%(key, value)) entries.insert(index, "%s=%s" % (key, value))
file(os.path.join(self.dbConfPath, 'db.properties'), 'w').write('\n'.join(entries)) file(os.path.join(self.dbConfPath, "db.properties"), "w").write(
"\n".join(entries)
)
self.info("Finalizing setup ...", None) self.info("Finalizing setup ...", None)
finalizeDbProperties() finalizeDbProperties()
self.info(None, True) self.info(None, True)
self.success = True # At here, we have done successfully and nothing more after this flag is set self.success = True # At here, we have done successfully and nothing more after this flag is set
def processEncryptionStuff(self): def processEncryptionStuff(self):
def encrypt(value): def encrypt(value):
cmd = ['java','-classpath','"' + self.encryptionJarPath + '"','com.cloud.utils.crypt.EncryptionCLI','-i','"' + value + '"', '-p', '"' + self.mgmtsecretkey + '"'] cmd = [
return runCmd(cmd).strip('\n') "java",
"-classpath",
'"' + self.encryptionJarPath + '"',
"com.cloud.utils.crypt.EncryptionCLI",
"-i",
'"' + value + '"',
"-p",
'"' + self.mgmtsecretkey + '"',
]
return runCmd(cmd).strip("\n")
def saveMgmtServerSecretKey(): def saveMgmtServerSecretKey():
if self.encryptiontype == 'file': if self.encryptiontype == "file":
file(self.encryptionKeyFile, 'w').write(self.mgmtsecretkey) file(self.encryptionKeyFile, "w").write(self.mgmtsecretkey)
def formatEncryptResult(value): def formatEncryptResult(value):
return 'ENC(%s)'%value return "ENC(%s)" % value
def encryptDBSecretKey(): def encryptDBSecretKey():
self.putDbProperty('db.cloud.encrypt.secret', formatEncryptResult(encrypt(self.dbsecretkey))) self.putDbProperty(
"db.cloud.encrypt.secret",
formatEncryptResult(encrypt(self.dbsecretkey)),
)
def encryptDBPassword(): def encryptDBPassword():
dbPassword = self.getDbProperty('db.cloud.password') dbPassword = self.getDbProperty("db.cloud.password")
if dbPassword == '': return # Don't encrypt empty password if dbPassword == "":
if dbPassword == None: self.errorAndExit('Cannot find db.cloud.password in %s'%os.path.join(self.dbConfPath, 'db.properties')) return # Don't encrypt empty password
self.putDbProperty('db.cloud.password', formatEncryptResult(encrypt(dbPassword))) if dbPassword == None:
self.errorAndExit(
"Cannot find db.cloud.password in %s"
% os.path.join(self.dbConfPath, "db.properties")
)
self.putDbProperty(
"db.cloud.password", formatEncryptResult(encrypt(dbPassword))
)
usagePassword = self.getDbProperty('db.usage.password') usagePassword = self.getDbProperty("db.usage.password")
if usagePassword == '': return # Don't encrypt empty password if usagePassword == "":
if usagePassword == None: self.errorAndExit('Cannot find db.usage.password in %s'%os.path.join(self.dbConfPath, 'db.properties')) return # Don't encrypt empty password
self.putDbProperty('db.usage.password', formatEncryptResult(encrypt(usagePassword))) if usagePassword == None:
self.errorAndExit(
"Cannot find db.usage.password in %s"
% os.path.join(self.dbConfPath, "db.properties")
)
self.putDbProperty(
"db.usage.password", formatEncryptResult(encrypt(usagePassword))
)
self.info("Processing encryption ...", None) self.info("Processing encryption ...", None)
self.putDbProperty("db.cloud.encryption.type", self.encryptiontype) self.putDbProperty("db.cloud.encryption.type", self.encryptiontype)
@ -222,26 +270,55 @@ for example:
self.dbsecretkey = self.options.dbsecretkey self.dbsecretkey = self.options.dbsecretkey
self.isDebug = self.options.debug self.isDebug = self.options.debug
def validateParameters(): def validateParameters():
if self.encryptiontype != 'file' and self.encryptiontype != 'web': if self.encryptiontype != "file" and self.encryptiontype != "web":
self.errorAndExit('Wrong encryption type %s, --encrypt-type can only be "file" or "web'%self.encryptiontype) self.errorAndExit(
'Wrong encryption type %s, --encrypt-type can only be "file" or "web'
% self.encryptiontype
)
#---------------------- option parsing and command line checks ------------------------ # ---------------------- option parsing and command line checks ------------------------
usage = """%prog [-e ENCRYPTIONTYPE] [-m MGMTSECRETKEY] [-k DBSECRETKEY] [--debug] usage = """%prog [-e ENCRYPTIONTYPE] [-m MGMTSECRETKEY] [-k DBSECRETKEY] [--debug]
This command sets up the CloudStack Encryption. This command sets up the CloudStack Encryption.
""" """
self.parser = OptionParser(usage=usage) self.parser = OptionParser(usage=usage)
self.parser.add_option("-v", "--debug", action="store_true", dest="debug", default=False, self.parser.add_option(
help="If enabled, print the commands it will run as they run") "-v",
self.parser.add_option("-e", "--encrypt-type", action="store", type="string", dest="encryptiontype", default="file", "--debug",
help="Encryption method used for db password encryption. Valid values are file, web. Default is file.") action="store_true",
self.parser.add_option("-m", "--managementserver-secretkey", action="store", type="string", dest="mgmtsecretkey", default="password", dest="debug",
help="Secret key used to encrypt confidential parameters in db.properties. A string, default is password") default=False,
self.parser.add_option("-k", "--database-secretkey", action="store", type="string", dest="dbsecretkey", default="password", help="If enabled, print the commands it will run as they run",
help="Secret key used to encrypt sensitive database values. A string, default is password") )
self.parser.add_option(
"-e",
"--encrypt-type",
action="store",
type="string",
dest="encryptiontype",
default="file",
help="Encryption method used for db password encryption. Valid values are file, web. Default is file.",
)
self.parser.add_option(
"-m",
"--managementserver-secretkey",
action="store",
type="string",
dest="mgmtsecretkey",
default="password",
help="Secret key used to encrypt confidential parameters in db.properties. A string, default is password",
)
self.parser.add_option(
"-k",
"--database-secretkey",
action="store",
type="string",
dest="dbsecretkey",
default="password",
help="Secret key used to encrypt sensitive database values. A string, default is password",
)
(self.options, self.args) = self.parser.parse_args() (self.options, self.args) = self.parser.parse_args()
parseOtherOptions() parseOtherOptions()
@ -257,10 +334,11 @@ for example:
finally: finally:
self.postRun() self.postRun()
print('') print("")
print("CloudStack has successfully setup Encryption") print("CloudStack has successfully setup Encryption")
print('') print("")
if __name__ == "__main__": if __name__ == "__main__":
o = DBDeployer() o = DBDeployer()
o.run() o.run()