2017-05-03 17:00:03 -03:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
import argparse # Argument parser
|
|
|
|
import re # For regex
|
|
|
|
import paramiko # For remote ssh
|
|
|
|
|
|
|
|
from esxi_vm_functions import *
|
|
|
|
|
2018-01-10 18:59:44 -03:00
|
|
|
# Defaults and Variable setup
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData = setup_config()
|
|
|
|
NAME = ""
|
|
|
|
LOG = ConfigData['LOG']
|
|
|
|
isDryRun = ConfigData['isDryRun']
|
|
|
|
isVerbose = ConfigData['isVerbose']
|
2017-05-16 12:49:38 -04:00
|
|
|
isSummary = ConfigData['isSummary']
|
2017-05-03 17:00:03 -03:00
|
|
|
HOST = ConfigData['HOST']
|
2018-01-07 18:37:33 -03:00
|
|
|
PORT = ConfigData['PORT']
|
2017-05-03 17:00:03 -03:00
|
|
|
USER = ConfigData['USER']
|
|
|
|
PASSWORD = ConfigData['PASSWORD']
|
2018-01-07 18:37:33 -03:00
|
|
|
KEY = ConfigData['KEY']
|
2017-05-03 17:00:03 -03:00
|
|
|
CPU = ConfigData['CPU']
|
|
|
|
MEM = ConfigData['MEM']
|
2017-05-16 12:49:38 -04:00
|
|
|
HDISK = int(ConfigData['HDISK'])
|
2017-05-03 17:00:03 -03:00
|
|
|
DISKFORMAT = ConfigData['DISKFORMAT']
|
|
|
|
VIRTDEV = ConfigData['VIRTDEV']
|
|
|
|
STORE = ConfigData['STORE']
|
|
|
|
NET = ConfigData['NET']
|
|
|
|
ISO = ConfigData['ISO']
|
|
|
|
GUESTOS = ConfigData['GUESTOS']
|
2017-10-23 22:44:46 -03:00
|
|
|
VMXOPTS = ConfigData['VMXOPTS']
|
2017-05-03 17:00:03 -03:00
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
ErrorMessages = ""
|
2017-05-08 12:26:25 -03:00
|
|
|
MAC = ""
|
|
|
|
GeneratedMAC = ""
|
2017-05-16 12:49:38 -04:00
|
|
|
ISOfound = False
|
|
|
|
CheckHasErrors = False
|
|
|
|
LeastUsedDS = ""
|
2018-01-07 19:50:49 -03:00
|
|
|
DSPATH = ""
|
|
|
|
DSSTORE = ""
|
2017-05-16 12:49:38 -04:00
|
|
|
FullPathExists = False
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
#
|
|
|
|
# Process Arguments
|
|
|
|
#
|
|
|
|
parser = argparse.ArgumentParser(description='ESXi Create VM utility.')
|
|
|
|
|
2018-01-10 13:29:31 -03:00
|
|
|
parser.add_argument('-d', '--dry', dest='isDryRunarg', action='store_true',
|
|
|
|
help="Enable Dry Run mode (" + str(isDryRun) + ")")
|
2017-05-16 12:49:38 -04:00
|
|
|
parser.add_argument("-H", "--Host", dest='HOST', type=str, help="ESXi Host/IP (" + str(HOST) + ")")
|
2018-01-07 19:50:49 -03:00
|
|
|
parser.add_argument("-T", "--Port", dest='PORT', type=int, help="ESXi Port number (" + str(PORT) + ")")
|
2017-05-03 17:00:03 -03:00
|
|
|
parser.add_argument("-U", "--User", dest='USER', type=str, help="ESXi Host username (" + str(USER) + ")")
|
|
|
|
parser.add_argument("-P", "--Password", dest='PASSWORD', type=str, help="ESXi Host password (*****)")
|
2018-01-07 18:51:37 -03:00
|
|
|
parser.add_argument("-K", "--Key", dest='KEY', type=str, help="ESXi Host connection key (path to private key)")
|
2017-05-03 17:00:03 -03:00
|
|
|
parser.add_argument("-n", "--name", dest='NAME', type=str, help="VM name")
|
|
|
|
parser.add_argument("-c", "--cpu", dest='CPU', type=int, help="Number of vCPUS (" + str(CPU) + ")")
|
|
|
|
parser.add_argument("-m", "--mem", type=int, help="Memory in GB (" + str(MEM) + ")")
|
2017-05-16 12:49:38 -04:00
|
|
|
parser.add_argument("-v", "--vdisk", dest='HDISK', type=str, help="Size of virt hdisk (" + str(HDISK) + ")")
|
2017-05-03 17:00:03 -03:00
|
|
|
parser.add_argument("-i", "--iso", dest='ISO', type=str, help="CDROM ISO Path | None (" + str(ISO) + ")")
|
|
|
|
parser.add_argument("-N", "--net", dest='NET', type=str, help="Network Interface | None (" + str(NET) + ")")
|
2017-05-16 12:49:38 -04:00
|
|
|
parser.add_argument("-M", "--mac", dest='MAC', type=str, help="MAC address")
|
2018-01-07 19:50:49 -03:00
|
|
|
parser.add_argument("-S", "--store", dest='STORE', type=str, help="vmfs Store | LeastUsed (" + str(STORE) + ")")
|
2017-05-03 17:00:03 -03:00
|
|
|
parser.add_argument("-g", "--guestos", dest='GUESTOS', type=str, help="Guest OS. (" + str(GUESTOS) + ")")
|
2017-10-23 22:44:46 -03:00
|
|
|
parser.add_argument("-o", "--options", dest='VMXOPTS', type=str, default='NIL', help="Comma list of VMX Options.")
|
2018-01-10 13:29:31 -03:00
|
|
|
parser.add_argument('-V', '--verbose', dest='isVerbosearg', action='store_true',
|
|
|
|
help="Enable Verbose mode (" + str(isVerbose) + ")")
|
|
|
|
parser.add_argument('--summary', dest='isSummaryarg', action='store_true',
|
|
|
|
help="Display Summary (" + str(isSummary) + ")")
|
|
|
|
parser.add_argument("-u", "--updateDefaults", dest='UPDATE', action='store_true',
|
|
|
|
help="Update Default VM settings stored in ~/.esxi-vm.yml")
|
2017-05-16 12:49:38 -04:00
|
|
|
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.isDryRunarg:
|
|
|
|
isDryRun = True
|
|
|
|
if args.isVerbosearg:
|
|
|
|
isVerbose = True
|
2017-05-16 12:49:38 -04:00
|
|
|
if args.isSummaryarg:
|
|
|
|
isSummary = True
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.HOST:
|
2018-01-10 13:29:31 -03:00
|
|
|
HOST = args.HOST
|
2018-01-07 18:37:33 -03:00
|
|
|
if args.PORT:
|
2018-01-10 13:29:31 -03:00
|
|
|
PORT = args.PORT
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.USER:
|
2018-01-10 13:29:31 -03:00
|
|
|
USER = args.USER
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.PASSWORD:
|
2018-01-10 13:29:31 -03:00
|
|
|
PASSWORD = args.PASSWORD
|
2018-01-07 18:37:33 -03:00
|
|
|
if args.KEY:
|
2018-01-10 13:29:31 -03:00
|
|
|
KEY = args.KEY
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.NAME:
|
2018-01-10 13:29:31 -03:00
|
|
|
NAME = args.NAME
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.CPU:
|
2018-01-10 13:29:31 -03:00
|
|
|
CPU = int(args.CPU)
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.mem:
|
2018-01-10 13:29:31 -03:00
|
|
|
MEM = int(args.mem)
|
2017-05-16 12:49:38 -04:00
|
|
|
if args.HDISK:
|
2018-01-10 13:29:31 -03:00
|
|
|
HDISK = int(args.HDISK)
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.ISO:
|
2018-01-10 13:29:31 -03:00
|
|
|
ISO = args.ISO
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.NET:
|
2018-01-10 13:29:31 -03:00
|
|
|
NET = args.NET
|
2017-05-08 12:26:25 -03:00
|
|
|
if args.MAC:
|
2018-01-10 13:29:31 -03:00
|
|
|
MAC = args.MAC
|
2017-05-03 17:00:03 -03:00
|
|
|
if args.STORE:
|
2018-01-10 13:29:31 -03:00
|
|
|
STORE = args.STORE
|
2017-05-03 17:00:03 -03:00
|
|
|
if STORE == "":
|
|
|
|
STORE = "LeastUsed"
|
|
|
|
if args.GUESTOS:
|
2018-01-10 13:29:31 -03:00
|
|
|
GUESTOS = args.GUESTOS
|
2017-10-23 22:44:46 -03:00
|
|
|
if args.VMXOPTS == '' and VMXOPTS != '':
|
2018-01-07 19:50:49 -03:00
|
|
|
VMXOPTS = ''
|
2017-10-23 22:44:46 -03:00
|
|
|
if args.VMXOPTS and args.VMXOPTS != 'NIL':
|
2018-01-07 19:50:49 -03:00
|
|
|
VMXOPTS = args.VMXOPTS.split(",")
|
2017-10-23 22:44:46 -03:00
|
|
|
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
if args.UPDATE:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Saving new Defaults to ~/.esxi-vm.yml")
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData['isDryRun'] = isDryRun
|
|
|
|
ConfigData['isVerbose'] = isVerbose
|
2017-10-23 22:44:46 -03:00
|
|
|
ConfigData['isSummary'] = isSummary
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData['HOST'] = HOST
|
2018-01-07 18:37:33 -03:00
|
|
|
ConfigData['PORT'] = PORT
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData['USER'] = USER
|
|
|
|
ConfigData['PASSWORD'] = PASSWORD
|
2018-01-07 18:37:33 -03:00
|
|
|
ConfigData['KEY'] = KEY
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData['CPU'] = CPU
|
|
|
|
ConfigData['MEM'] = MEM
|
2017-05-16 12:49:38 -04:00
|
|
|
ConfigData['HDISK'] = HDISK
|
2017-05-03 17:00:03 -03:00
|
|
|
ConfigData['DISKFORMAT'] = DISKFORMAT
|
|
|
|
ConfigData['VIRTDEV'] = VIRTDEV
|
|
|
|
ConfigData['STORE'] = STORE
|
|
|
|
ConfigData['NET'] = NET
|
|
|
|
ConfigData['ISO'] = ISO
|
|
|
|
ConfigData['GUESTOS'] = GUESTOS
|
2017-10-23 22:44:46 -03:00
|
|
|
ConfigData['VMXOPTS'] = VMXOPTS
|
2018-01-10 13:29:31 -03:00
|
|
|
save_config(ConfigData)
|
2017-05-03 17:00:03 -03:00
|
|
|
if NAME == "":
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
#
|
|
|
|
# main()
|
|
|
|
#
|
2017-05-16 12:49:38 -04:00
|
|
|
LogOutput = '{'
|
2018-01-10 18:44:14 -03:00
|
|
|
LogOutput += '"datetime":"{}",'.format(the_current_date_time())
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
if NAME == "":
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: Missing required option --name")
|
2017-05-03 17:00:03 -03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
try:
|
|
|
|
ssh = paramiko.SSHClient()
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
2018-01-07 18:37:33 -03:00
|
|
|
ssh.connect(HOST, port=PORT, username=USER, password=PASSWORD, key_filename=KEY)
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("esxcli system version get |grep Version")
|
|
|
|
type(stdin)
|
2017-05-08 12:26:25 -03:00
|
|
|
if re.match("Version", str(stdout.readlines())) is not None:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Unable to determine if this is a ESXi Host: {}, port: {}, username: {}".format(HOST, PORT, USER))
|
2017-05-03 17:00:03 -03:00
|
|
|
sys.exit(1)
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
|
|
|
print("The Error is {}".format(e))
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Unable to access ESXi Host: {}, port: {}, username: {}".format(HOST, PORT, USER))
|
2017-05-08 12:26:25 -03:00
|
|
|
sys.exit(1)
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
try:
|
2018-01-10 13:29:31 -03:00
|
|
|
(stdin, stdout, stderr) = \
|
|
|
|
ssh.exec_command("esxcli storage filesystem list |grep '/vmfs/volumes/.*true VMFS' |sort -nk7")
|
2017-05-03 17:00:03 -03:00
|
|
|
type(stdin)
|
|
|
|
VOLUMES = {}
|
|
|
|
for line in stdout.readlines():
|
|
|
|
splitLine = line.split()
|
|
|
|
VOLUMES[splitLine[0]] = splitLine[1]
|
|
|
|
LeastUsedDS = splitLine[1]
|
2018-01-10 18:44:14 -03:00
|
|
|
except Exception as e:
|
|
|
|
print("The Error is {}".format(e))
|
2017-05-03 17:00:03 -03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if STORE == "LeastUsed":
|
|
|
|
STORE = LeastUsedDS
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
2018-01-10 13:29:31 -03:00
|
|
|
(stdin, stdout, stderr) = \
|
|
|
|
ssh.exec_command("esxcli network vswitch standard list|grep Portgroups|sed 's/^ Portgroups: //g'")
|
2017-05-03 17:00:03 -03:00
|
|
|
type(stdin)
|
|
|
|
VMNICS = []
|
|
|
|
for line in stdout.readlines():
|
2018-01-10 16:06:33 -03:00
|
|
|
splitLine = re.split('[,\n]', line)
|
2017-05-03 17:00:03 -03:00
|
|
|
VMNICS.append(splitLine[0])
|
2018-01-10 18:44:14 -03:00
|
|
|
except Exception as e:
|
|
|
|
print("The Error is {}".format(e))
|
2017-05-03 17:00:03 -03:00
|
|
|
sys.exit(1)
|
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
MACarg = MAC
|
2017-05-08 12:26:25 -03:00
|
|
|
if MAC != "":
|
|
|
|
MACregex = '^([a-fA-F0-9]{2}[:|\-]){5}[a-fA-F0-9]{2}$'
|
|
|
|
if re.compile(MACregex).search(MAC):
|
|
|
|
# Full MAC found. OK
|
2018-01-10 13:29:31 -03:00
|
|
|
MAC = MAC.replace("-", ":")
|
2017-05-08 12:26:25 -03:00
|
|
|
elif re.compile(MACregex).search("00:50:56:" + MAC):
|
2018-01-10 13:29:31 -03:00
|
|
|
MAC = "00:50:56:" + MAC.replace("-", ":")
|
2017-05-08 12:26:25 -03:00
|
|
|
else:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: {} Invalid MAC address.".format(MAC))
|
2017-05-16 12:49:38 -04:00
|
|
|
ErrorMessages += " " + MAC + " Invalid MAC address."
|
2017-05-08 12:26:25 -03:00
|
|
|
CheckHasErrors = True
|
2017-10-23 22:44:46 -03:00
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
ISOarg = ISO
|
2017-05-03 17:00:03 -03:00
|
|
|
if ISO == "None":
|
|
|
|
ISO = ""
|
|
|
|
if ISO != "":
|
|
|
|
try:
|
2017-05-08 12:26:25 -03:00
|
|
|
# If ISO has no "/", try to find the ISO
|
|
|
|
if not re.match('/', ISO):
|
2018-01-10 16:06:33 -03:00
|
|
|
(stdin, stdout, stderr) = \
|
|
|
|
ssh.exec_command("find /vmfs/volumes/ -type f -name " + ISO +
|
|
|
|
" -exec sh -c 'echo $1; kill $PPID' sh {} 2>/dev/null \;")
|
2017-05-08 12:26:25 -03:00
|
|
|
type(stdin)
|
|
|
|
FoundISOPath = str(stdout.readlines()[0]).strip('\n')
|
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("FoundISOPath: {}".format(FoundISOPath))
|
2017-05-08 12:26:25 -03:00
|
|
|
ISO = str(FoundISOPath)
|
|
|
|
|
2017-05-03 17:00:03 -03:00
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("ls " + str(ISO))
|
|
|
|
type(stdin)
|
2017-05-07 22:09:01 -03:00
|
|
|
if stdout.readlines() and not stderr.readlines():
|
2017-05-03 17:00:03 -03:00
|
|
|
ISOfound = True
|
2017-05-08 12:26:25 -03:00
|
|
|
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
|
|
|
print("The Error is {}".format(e))
|
2017-05-03 17:00:03 -03:00
|
|
|
sys.exit(1)
|
2017-05-16 12:49:38 -04:00
|
|
|
|
2017-05-03 17:00:03 -03:00
|
|
|
VMID = -1
|
|
|
|
try:
|
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/getallvms")
|
|
|
|
type(stdin)
|
|
|
|
for line in stdout.readlines():
|
|
|
|
splitLine = line.split()
|
|
|
|
if NAME == splitLine[1]:
|
|
|
|
VMID = splitLine[0]
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: VM {} already exists.".format(NAME))
|
2017-05-16 12:49:38 -04:00
|
|
|
ErrorMessages += " VM " + NAME + " already exists."
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
|
|
|
print("The Error is {}".format(e))
|
2018-01-10 16:06:33 -03:00
|
|
|
sys.exit(1)
|
2017-05-03 17:00:03 -03:00
|
|
|
|
|
|
|
# Check CPU
|
|
|
|
if CPU < 1 or CPU > 128:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("{} CPU out of range. [1-128].".format(CPU))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " {} CPU out of range. [1-128].".format(CPU)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
|
|
|
# Check MEM
|
|
|
|
if MEM < 1 or MEM > 4080:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("{} GB Memory out of range. [1-4080].".format(MEM))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " {} GB Memory out of range. [1-4080].".format(MEM)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
# Check HDISK
|
|
|
|
if HDISK < 1 or HDISK > 63488:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Virtual Disk size {} GB out of range. [1-63488].".format(HDISK))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " Virtual Disk size {} GB out of range. [1-63488].".format(HDISK)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
# Convert STORE to path and visa-versa
|
2017-05-03 17:00:03 -03:00
|
|
|
V = []
|
|
|
|
for Path in VOLUMES:
|
|
|
|
V.append(VOLUMES[Path])
|
|
|
|
if STORE == Path or STORE == VOLUMES[Path]:
|
|
|
|
DSPATH = Path
|
|
|
|
DSSTORE = VOLUMES[Path]
|
|
|
|
|
|
|
|
if DSSTORE not in V:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: Disk Storage {} doesn't exist. ".format(STORE))
|
|
|
|
print(" Available Disk Stores: {}".format([str(item) for item in V]))
|
|
|
|
print(" LeastUsed Disk Store : {}".format(LeastUsedDS))
|
2017-05-16 12:49:38 -04:00
|
|
|
ErrorMessages += " Disk Storage " + STORE + " doesn't exist. "
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
|
|
|
# Check NIC (NIC record)
|
|
|
|
if (NET not in VMNICS) and (NET != "None"):
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: Virtual NIC {} doesn't exist.".format(NET))
|
|
|
|
print(" Available VM NICs: {} or 'None'".format([str(item) for item in VMNICS]))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " Virtual NIC {} doesn't exist.".format(NET)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
|
|
|
# Check ISO exists
|
|
|
|
if ISO != "" and not ISOfound:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: ISO {} not found. Use full path to ISO".format(ISO))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " ISO {} not found. Use full path to ISO".format(ISO)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
|
|
|
|
|
|
|
# Check if DSPATH/NAME aready exists
|
|
|
|
try:
|
|
|
|
FullPath = DSPATH + "/" + NAME
|
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("ls -d " + FullPath)
|
|
|
|
type(stdin)
|
|
|
|
if stdout.readlines() and not stderr.readlines():
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ERROR: Directory {} already exists.".format(FullPath))
|
2018-01-10 18:44:14 -03:00
|
|
|
ErrorMessages += " Directory {} already exists.".format(FullPath)
|
2017-05-03 17:00:03 -03:00
|
|
|
CheckHasErrors = True
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
2017-05-03 17:00:03 -03:00
|
|
|
pass
|
|
|
|
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx = []
|
|
|
|
vmx.append('config.version = "8"')
|
|
|
|
vmx.append('virtualHW.version = "8"')
|
|
|
|
vmx.append('vmci0.present = "TRUE"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('displayName = "{}"'.format(NAME))
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('floppy0.present = "FALSE"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('numvcpus = "{}"'.format(CPU))
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('scsi0.present = "TRUE"')
|
|
|
|
vmx.append('scsi0.sharedBus = "none"')
|
|
|
|
vmx.append('scsi0.virtualDev = "pvscsi"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('memsize = "{}"'.format(MEM * 1024))
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('scsi0:0.present = "TRUE"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('scsi0:0.fileName = "{}.vmdk"'.format(NAME))
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('scsi0:0.deviceType = "scsi-hardDisk"')
|
2017-05-03 17:00:03 -03:00
|
|
|
if ISO == "":
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ide1:0.present = "TRUE"')
|
|
|
|
vmx.append('ide1:0.fileName = "emptyBackingString"')
|
|
|
|
vmx.append('ide1:0.deviceType = "atapi-cdrom"')
|
|
|
|
vmx.append('ide1:0.startConnected = "FALSE"')
|
|
|
|
vmx.append('ide1:0.clientDevice = "TRUE"')
|
2017-05-03 17:00:03 -03:00
|
|
|
else:
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ide1:0.present = "TRUE"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('ide1:0.fileName = "{}"'.format(ISO))
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ide1:0.deviceType = "cdrom-image"')
|
|
|
|
vmx.append('pciBridge0.present = "TRUE"')
|
|
|
|
vmx.append('pciBridge4.present = "TRUE"')
|
|
|
|
vmx.append('pciBridge4.virtualDev = "pcieRootPort"')
|
|
|
|
vmx.append('pciBridge4.functions = "8"')
|
|
|
|
vmx.append('pciBridge5.present = "TRUE"')
|
|
|
|
vmx.append('pciBridge5.virtualDev = "pcieRootPort"')
|
|
|
|
vmx.append('pciBridge5.functions = "8"')
|
|
|
|
vmx.append('pciBridge6.present = "TRUE"')
|
|
|
|
vmx.append('pciBridge6.virtualDev = "pcieRootPort"')
|
|
|
|
vmx.append('pciBridge6.functions = "8"')
|
|
|
|
vmx.append('pciBridge7.present = "TRUE"')
|
|
|
|
vmx.append('pciBridge7.virtualDev = "pcieRootPort"')
|
|
|
|
vmx.append('pciBridge7.functions = "8"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('guestOS = "{}"'.format(GUESTOS))
|
2017-05-03 17:00:03 -03:00
|
|
|
if NET != "None":
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ethernet0.virtualDev = "vmxnet3"')
|
|
|
|
vmx.append('ethernet0.present = "TRUE"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('ethernet0.networkName = "{}"'.format(NET))
|
2017-05-08 12:26:25 -03:00
|
|
|
if MAC == "":
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ethernet0.addressType = "generated"')
|
2017-05-08 12:26:25 -03:00
|
|
|
else:
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append('ethernet0.addressType = "static"')
|
2018-01-10 18:44:14 -03:00
|
|
|
vmx.append('ethernet0.address = "{}"'.format(MAC))
|
2017-05-03 17:00:03 -03:00
|
|
|
|
2017-10-23 22:44:46 -03:00
|
|
|
#
|
|
|
|
# Merge extra VMX options
|
|
|
|
for VMXopt in VMXOPTS:
|
|
|
|
try:
|
2018-01-07 19:50:49 -03:00
|
|
|
k, v = VMXopt.split("=")
|
2018-01-10 18:44:14 -03:00
|
|
|
except Exception:
|
2018-01-07 19:50:49 -03:00
|
|
|
k = ""
|
|
|
|
v = ""
|
2017-10-23 22:44:46 -03:00
|
|
|
key = k.lstrip().strip()
|
|
|
|
value = v.lstrip().strip()
|
2018-01-07 19:50:49 -03:00
|
|
|
for i in vmx:
|
2017-10-23 22:44:46 -03:00
|
|
|
try:
|
2018-01-07 19:50:49 -03:00
|
|
|
ikey, ivalue = i.split("=")
|
2018-01-10 18:44:14 -03:00
|
|
|
except Exception:
|
2017-10-23 22:44:46 -03:00
|
|
|
break
|
|
|
|
if ikey.lstrip().strip().lower() == key.lower():
|
2018-01-07 19:50:49 -03:00
|
|
|
index = vmx.index(i)
|
|
|
|
vmx[index] = ikey + " = " + value
|
2017-10-23 22:44:46 -03:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
if key != '' and value != '':
|
2018-01-07 19:50:49 -03:00
|
|
|
vmx.append(key + " = " + value)
|
2017-10-23 22:44:46 -03:00
|
|
|
|
|
|
|
if isVerbose and VMXOPTS != '':
|
2018-01-10 16:06:33 -03:00
|
|
|
print("VMX file:")
|
2018-01-07 19:50:49 -03:00
|
|
|
for i in vmx:
|
2018-01-10 16:06:33 -03:00
|
|
|
print(i)
|
2017-05-08 12:26:25 -03:00
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
MyVM = FullPath + "/" + NAME
|
|
|
|
if CheckHasErrors:
|
|
|
|
Result = "Errors"
|
|
|
|
else:
|
|
|
|
Result = "Success"
|
|
|
|
|
|
|
|
if not isDryRun and not CheckHasErrors:
|
2017-05-03 17:00:03 -03:00
|
|
|
try:
|
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Create {}.vmx file".format(NAME))
|
2018-01-10 13:29:31 -03:00
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("mkdir " + FullPath)
|
2017-05-03 17:00:03 -03:00
|
|
|
type(stdin)
|
2018-01-07 19:50:49 -03:00
|
|
|
for line in vmx:
|
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("echo '" + line + "' >>" + MyVM + ".vmx")
|
2017-05-03 17:00:03 -03:00
|
|
|
type(stdin)
|
|
|
|
|
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Create {}.vmdk file".format(NAME))
|
2018-01-10 13:29:31 -03:00
|
|
|
(stdin, stdout, stderr) = \
|
|
|
|
ssh.exec_command("vmkfstools -c " + str(HDISK) + "G -d " + DISKFORMAT + " " + MyVM + ".vmdk")
|
2017-05-03 17:00:03 -03:00
|
|
|
type(stdin)
|
|
|
|
|
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Register VM")
|
2017-05-03 17:00:03 -03:00
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd solo/registervm " + MyVM + ".vmx")
|
|
|
|
type(stdin)
|
2017-05-08 12:26:25 -03:00
|
|
|
VMID = int(stdout.readlines()[0])
|
2017-10-23 22:44:46 -03:00
|
|
|
|
2017-05-03 17:00:03 -03:00
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Power ON VM")
|
2017-05-03 17:00:03 -03:00
|
|
|
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/power.on " + str(VMID))
|
|
|
|
type(stdin)
|
|
|
|
if stderr.readlines():
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Error Powering-on VM.")
|
2018-01-10 13:29:31 -03:00
|
|
|
Result = "Fail"
|
2017-05-16 12:49:38 -04:00
|
|
|
|
|
|
|
if NET != "None":
|
|
|
|
(stdin, stdout, stderr) = ssh.exec_command(
|
|
|
|
"grep -i 'ethernet0.*ddress = ' " + MyVM + ".vmx |tail -1|awk '{print $NF}'")
|
|
|
|
type(stdin)
|
|
|
|
GeneratedMAC = str(stdout.readlines()[0]).strip('\n"')
|
|
|
|
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("There was an error creating the VM.")
|
2017-05-16 12:49:38 -04:00
|
|
|
ErrorMessages += " There was an error creating the VM."
|
|
|
|
Result = "Fail"
|
2017-05-03 17:00:03 -03:00
|
|
|
|
2018-01-10 18:44:14 -03:00
|
|
|
LogOutput += '"Host":"{}","Port":"{}","Name":"{}",'.format(HOST, PORT, NAME)
|
|
|
|
LogOutput += '"CPU":"{}","Mem":"{}",'.format(CPU, MEM)
|
|
|
|
LogOutput += '"Hdisk":"{}","DiskFormat":"{}","Virtual Device":"{}",'.format(HDISK, DISKFORMAT, VIRTDEV)
|
|
|
|
LogOutput += '"Store":"{}","Store Used":"{}",'.format(STORE, DSPATH)
|
|
|
|
LogOutput += '"Network":"{}",'.format(NET)
|
|
|
|
LogOutput += '"ISO":"{}","ISO used":"{}",'.format(ISOarg, ISO)
|
|
|
|
LogOutput += '"Guest OS":"{}",'.format(GUESTOS)
|
|
|
|
LogOutput += '"MAC":"{}","MAC Used":"'.format(MACarg, GeneratedMAC)
|
|
|
|
LogOutput += '"Dry Run":"{}","Verbose":"{}",'.format(isDryRun, isVerbose)
|
2017-05-16 12:49:38 -04:00
|
|
|
if ErrorMessages != "":
|
2018-01-10 18:44:14 -03:00
|
|
|
LogOutput += '"Error Message":"{}",'.format(ErrorMessages)
|
|
|
|
LogOutput += '"Result":"{}","Completion Time":"{}"'.format(Result, the_current_date_time())
|
2017-05-16 12:49:38 -04:00
|
|
|
LogOutput += '}\n'
|
|
|
|
try:
|
2018-01-10 18:44:14 -03:00
|
|
|
with open(LOG, "a") as FD:
|
2017-05-16 12:49:38 -04:00
|
|
|
FD.write(LogOutput)
|
2018-01-10 18:59:44 -03:00
|
|
|
except Exception as e:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Error writing to log file: {}".format(LOG))
|
2017-05-16 12:49:38 -04:00
|
|
|
|
|
|
|
if isSummary:
|
|
|
|
if isDryRun:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("\nDry Run summary:")
|
2017-05-16 12:49:38 -04:00
|
|
|
else:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("\nCreate VM Success:")
|
2017-05-16 12:49:38 -04:00
|
|
|
|
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ESXi Host: {}".format(HOST))
|
|
|
|
print("ESXi Port: {}".format(PORT))
|
|
|
|
print("VM NAME: {}".format(NAME))
|
|
|
|
print("vCPU: {}".format(CPU))
|
|
|
|
print("Memory: {} GB".format(MEM))
|
|
|
|
print("VM Disk: {} GB".format(HDISK))
|
2017-05-16 12:49:38 -04:00
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Format: {}".format(DISKFORMAT))
|
|
|
|
print("DS Store: {}".format(DSSTORE))
|
|
|
|
print("Network: {}".format(NET))
|
2017-05-16 12:49:38 -04:00
|
|
|
if ISO:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("ISO: {}".format(ISO))
|
2017-05-16 12:49:38 -04:00
|
|
|
if isVerbose:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Guest OS: {}".format(GUESTOS))
|
|
|
|
print("MAC: {}".format(GeneratedMAC))
|
2017-05-08 12:26:25 -03:00
|
|
|
else:
|
2017-05-16 12:49:38 -04:00
|
|
|
pass
|
2017-05-08 12:26:25 -03:00
|
|
|
|
2017-05-16 12:49:38 -04:00
|
|
|
if CheckHasErrors:
|
|
|
|
if isDryRun:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Dry Run: Failed.")
|
2017-05-16 12:49:38 -04:00
|
|
|
sys.exit(1)
|
|
|
|
else:
|
|
|
|
if isDryRun:
|
2018-01-10 16:06:33 -03:00
|
|
|
print("Dry Run: Success.")
|
2017-05-16 12:49:38 -04:00
|
|
|
else:
|
2018-01-10 16:06:33 -03:00
|
|
|
print(GeneratedMAC)
|
2017-05-16 12:49:38 -04:00
|
|
|
sys.exit(0)
|