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

@ -43,19 +43,25 @@ 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")
@ -86,7 +92,9 @@ def getUserInputs():
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
@ -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")

View File

@ -35,9 +35,12 @@ from threading import Thread
# ---- 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
@ -51,30 +54,45 @@ 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 e(msg):
parser.error(msg)
def getknownhosts(host, username, password): def getknownhosts(host, username, password):
conn = mysql.connector.connect(host=host, user=username, password=password) conn = mysql.connector.connect(host=host, user=username, password=password)
cur = conn.cursor() 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") 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()) 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") 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()) passwords = dict(cur.fetchall())
creds = dict([[x, (usernames[x], passwords[x])] for x in list(usernames.keys())]) creds = dict([[x, (usernames[x], passwords[x])] for x in list(usernames.keys())])
cur.close() cur.close()
conn.close() conn.close()
return creds return creds
def splitlast(string, splitter): def splitlast(string, splitter):
splitted = string.split(splitter) splitted = string.split(splitter)
first, last = splitter.join(splitted[:-1]), splitted[-1] first, last = splitter.join(splitted[:-1]), splitted[-1]
return first, last return first, last
def parseuserpwfromhosts(hosts): def parseuserpwfromhosts(hosts):
creds = {} creds = {}
for host in hosts: for host in hosts:
@ -87,6 +105,7 @@ def parseuserpwfromhosts(hosts):
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):
@ -98,11 +117,11 @@ class XenServerConfigurator(Thread):
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)
@ -112,25 +131,39 @@ class XenServerConfigurator(Thread):
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(
"xe host-license-add license-file=/tmp/xen-license"
)
c.exec_command("false") c.exec_command("false")
self.stdout = stdout.read(-1) self.stdout = stdout.read(-1)
self.stderr = stderr.read(-1) self.stderr = stderr.read(-1)
self.retval = stdin.channel.recv_exit_status() self.retval = stdin.channel.recv_exit_status()
c.close() c.close()
if self.retval != 0: self.state = 'failed' if self.retval != 0:
else: self.state = 'finished' 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>" % (
self.state,
self.user,
self.host,
str(self.retval),
)
else: else:
return "<%s XenServerConfigurator on %s@%s>"%(self.state,self.user,self.host) return "<%s XenServerConfigurator on %s@%s>" % (
self.state,
self.user,
self.host,
)
# ------------- actual code -------------------- # ------------- actual code --------------------
@ -138,15 +171,22 @@ class XenServerConfigurator(Thread):
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:
e("IP addresses cannot be specified if -a is specified")
config = read_properties(cfg) config = read_properties(cfg)
creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"]) creds = getknownhosts(
config["db.cloud.host"],
config["db.cloud.username"],
config["db.cloud.password"],
)
hosts = list(creds.keys()) hosts = list(creds.keys())
else: else:
if not args: e("You must specify at least one IP address, or -a") if not args:
e("You must specify at least one IP address, or -a")
hosts = args hosts = args
creds = parseuserpwfromhosts(hosts) creds = parseuserpwfromhosts(hosts)
@ -161,22 +201,24 @@ 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:
c.start()
for c in configurators: for c in configurators:
print(c.host + "...", end=' ') print(c.host + "...", end=" ")
c.join() c.join()
if c.state == 'failed': if c.state == "failed":
if c.retval: if c.retval:
msg = "failed with return code %s: %s%s" % (c.retval, c.stdout, c.stderr) msg = "failed with return code %s: %s%s" % (c.retval, c.stdout, c.stderr)
msg = msg.strip() msg = msg.strip()
print(msg) print(msg)
else: print("failed: %s"%c.retval) else:
print("failed: %s" % c.retval)
else: else:
print("done") print("done")
successes = len( [ a for a in configurators if not a.state == 'failed' ] ) successes = len([a for a in configurators if not a.state == "failed"])
failures = len( [ a for a in configurators if a.state == 'failed' ] ) failures = len([a for a in configurators if a.state == "failed"])
print("%3s successes" % successes) print("%3s successes" % successes)
print("%3s failures" % failures) print("%3s failures" % failures)

View File

@ -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

@ -18,40 +18,68 @@
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)
@ -61,21 +89,28 @@ def getDependentLibraryInfo():
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

@ -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,6 +40,7 @@ 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
@ -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
@ -94,6 +100,7 @@ def initLoging(logFile=None):
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
@ -104,26 +111,33 @@ def writeProgressBar(msg, result=None):
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")
@ -134,46 +148,56 @@ def checkEnv():
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(): def configurePxeStuff():
stuff = ['tftp', 'xinetd', 'dhcpd'] stuff = ["tftp", "xinetd", "dhcpd"]
cmds = ['chkconfig --level 345 %s on' % i for i in stuff] cmds = ["chkconfig --level 345 %s on" % i for i in stuff]
cmds.append('/etc/init.d/xinetd restart') 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') chkIptable = bash("chkconfig --list iptables")
if 'on' in chkIptable.getStdout(): 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 False
return True 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("/")
@ -184,8 +208,9 @@ def getTftpRootDir(tftpRootDirList):
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:
@ -193,9 +218,11 @@ def preparePING(tftpRootDir):
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
@ -214,4 +241,3 @@ if __name__ == "__main__":
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

@ -22,7 +22,10 @@
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,6 +40,7 @@ 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__
@ -44,8 +48,10 @@ def echo(fn):
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"]
@ -60,6 +66,7 @@ def downloadTemplateFromUrl(session, args):
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"]
@ -69,7 +76,12 @@ def getTemplateSize(session, args):
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

@ -22,6 +22,7 @@
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,6 +34,7 @@ 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__
@ -40,112 +42,139 @@ def echo(fn):
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,7 +31,8 @@ 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
@ -39,17 +40,24 @@ warnings.simplefilter('ignore')
# ---- 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,7 +96,6 @@ 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:
@ -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,33 +139,45 @@ 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)
@ -172,10 +192,12 @@ 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()
@ -184,29 +206,55 @@ for example:
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,10 +270,12 @@ 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]
@ -234,14 +284,41 @@ for example:
""" """
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,9 +334,10 @@ 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()