Add -o option, fix isSummary save, add beta esxi-vm-destroy

master
Jonathan Senkerik 2017-10-23 21:44:46 -04:00
parent 625e4f269c
commit 5809a2df0b
6 changed files with 300 additions and 17 deletions

1
.gitignore vendored 100644
View File

@ -0,0 +1 @@
esxi_vm_functions.pyc

14
Makefile 100644
View File

@ -0,0 +1,14 @@
all:
@echo "make install"
install:
install -m 755 ./esxi-vm-create /usr/local/bin/
install -m 755 ./esxi-vm-destroy /usr/local/bin/
install -m 755 ./esxi_vm_functions.py /usr/local/bin/
@echo "Install Success."
uninstall:
rm -fr /usr/local/bin/esxi-vm-create
rm -fr /usr/local/bin/esxi-vm-destroy
rm -fr /usr/local/bin/esxi_vm_functions.py
rm -fr /usr/local/bin/esxi_vm_functions.pyc

View File

@ -34,7 +34,7 @@ Usage
Requirements
------------
You must enable ssh access on your ESXi server. The VMware VIX API tools are not required.
You must enable ssh access on your ESXi server. Google 'how to enable ssh access on esxi' for instructions. The VMware VIX API tools are not required.
It's HIGHLY RECOMMENDED to use password-less authentication by copying your ssh public keys to the ESXi host, otherwise your ESXi root password could be stored in clear-text in your home directory.
@ -50,9 +50,11 @@ Command Line Args
```
./esxi-vm-create --help
usage: esxi-vm-create [-h] [-d] [-H HOST] [-U USER] [-P PASSWORD] [-n NAME]
[-c CPU] [-m MEM] [-v HDISK] [-i ISO] [-N NET] [-M MAC]
[-S STORE] [-g GUESTOS] [-V] [--summary] [-u]
[-S STORE] [-g GUESTOS] [-o VMXOPTS] [-V] [--summary]
[-u]
ESXi Create VM utility.
@ -65,20 +67,21 @@ optional arguments:
ESXi Host password (*****)
-n NAME, --name NAME VM name
-c CPU, --cpu CPU Number of vCPUS (2)
-m MEM, --mem MEM Memory in GB (2)
-m MEM, --mem MEM Memory in GB (4)
-v HDISK, --vdisk HDISK
Size of virt hdisk (12)
Size of virt hdisk (20)
-i ISO, --iso ISO CDROM ISO Path | None (None)
-N NET, --net NET Network Interface | None (192.168.1)
-N NET, --net NET Network Interface | None (None)
-M MAC, --mac MAC MAC address
-S STORE, --store STORE
vmfs Store | LeastUsed (DS_3TB_m)
vmfs Store | LeastUsed (LeastUsed)
-g GUESTOS, --guestos GUESTOS
Guest OS. (centos-64)
-o VMXOPTS, --options VMXOPTS
Comma list of VMX Options.
-V, --verbose Enable Verbose mode (False)
--summary Display Summary (False)
-u, --updateDefaults Update Default VM settings stored in ~/.esxi-vm.yml
```
@ -176,6 +179,12 @@ Guest OS: centos-64
MAC: 00:0c:29:ea:a0:42
00:0c:29:ea:a0:42
```
Merge/Add extra VMX options, saved as default.
```
./esxi-vm-create -o 'floppy0.present = "TRUE",svga.autodetect = "TRUE",svga.present = "TRUE"' -u
Saving new Defaults to ~/.esxi-vm.yml
```
License
@ -202,4 +211,3 @@ Support
Website : http://www.jintegrate.co
github : http://github.com/josenk/

View File

@ -31,6 +31,7 @@ STORE = ConfigData['STORE']
NET = ConfigData['NET']
ISO = ConfigData['ISO']
GUESTOS = ConfigData['GUESTOS']
VMXOPTS = ConfigData['VMXOPTS']
ErrorMessages = ""
MAC = ""
@ -60,6 +61,7 @@ parser.add_argument("-N", "--net", dest='NET', type=str, help="Network Interface
parser.add_argument("-M", "--mac", dest='MAC', type=str, help="MAC address")
parser.add_argument("-S", "--store", dest='STORE', type=str, help="vmfs Store | LeastUsed (" + str(STORE) + ")")
parser.add_argument("-g", "--guestos", dest='GUESTOS', type=str, help="Guest OS. (" + str(GUESTOS) + ")")
parser.add_argument("-o", "--options", dest='VMXOPTS', type=str, default='NIL', help="Comma list of VMX Options.")
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")
@ -100,11 +102,17 @@ if STORE == "":
STORE = "LeastUsed"
if args.GUESTOS:
GUESTOS=args.GUESTOS
if args.VMXOPTS == '' and VMXOPTS != '':
VMXOPTS=''
if args.VMXOPTS and args.VMXOPTS != 'NIL':
VMXOPTS=args.VMXOPTS.split(",")
if args.UPDATE:
print "Saving new Defaults to ~/.esxi-vm.yml"
ConfigData['isDryRun'] = isDryRun
ConfigData['isVerbose'] = isVerbose
ConfigData['isSummary'] = isSummary
ConfigData['HOST'] = HOST
ConfigData['USER'] = USER
ConfigData['PASSWORD'] = PASSWORD
@ -117,6 +125,7 @@ if args.UPDATE:
ConfigData['NET'] = NET
ConfigData['ISO'] = ISO
ConfigData['GUESTOS'] = GUESTOS
ConfigData['VMXOPTS'] = VMXOPTS
SaveConfig(ConfigData)
if NAME == "":
sys.exit(0)
@ -353,6 +362,33 @@ if NET != "None":
VMX.append('ethernet0.addressType = "static"')
VMX.append('ethernet0.address = "' + MAC + '"')
#
# Merge extra VMX options
for VMXopt in VMXOPTS:
try:
k,v = VMXopt.split("=")
except:
k=""
v=""
key = k.lstrip().strip()
value = v.lstrip().strip()
for i in VMX:
try:
ikey,ivalue = i.split("=")
except:
break
if ikey.lstrip().strip().lower() == key.lower():
index = VMX.index(i)
VMX[index] = ikey + " = " + value
break
else:
if key != '' and value != '':
VMX.append(key + " = " + value)
if isVerbose and VMXOPTS != '':
print "VMX file:"
for i in VMX:
print i
MyVM = FullPath + "/" + NAME
if CheckHasErrors:
@ -472,5 +508,3 @@ else:
else:
print GeneratedMAC
sys.exit(0)

224
esxi-vm-destroy 100755
View File

@ -0,0 +1,224 @@
#!/usr/bin/python
import argparse # Argument parser
import datetime # For current Date/Time
import time
import os.path # To check if file exists
import sys # For args
import re # For regex
import paramiko # For remote ssh
import yaml
import warnings
from esxi_vm_functions import *
# Defaults and Variable setup
ConfigData = setup_config()
NAME = ""
LOG = ConfigData['LOG']
isDryRun = ConfigData['isDryRun']
isVerbose = ConfigData['isVerbose']
isSummary = ConfigData['isSummary']
HOST = ConfigData['HOST']
USER = ConfigData['USER']
PASSWORD = ConfigData['PASSWORD']
CPU = ConfigData['CPU']
MEM = ConfigData['MEM']
HDISK = int(ConfigData['HDISK'])
DISKFORMAT = ConfigData['DISKFORMAT']
VIRTDEV = ConfigData['VIRTDEV']
STORE = ConfigData['STORE']
NET = ConfigData['NET']
ISO = ConfigData['ISO']
GUESTOS = ConfigData['GUESTOS']
ErrorMessages = ""
CheckHasErrors = False
DSPATH=""
DSSTORE=""
#
# Process Arguments
#
parser = argparse.ArgumentParser(description='ESXi Create VM utility.')
parser.add_argument("-H", "--Host", dest='HOST', type=str, help="ESXi Host/IP (" + str(HOST) + ")")
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 (*****)")
parser.add_argument("-n", "--name", dest='NAME', type=str, help="VM name")
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) + ")")
args = parser.parse_args()
if args.isVerbosearg:
isVerbose = True
if args.isSummaryarg:
isSummary = True
if args.HOST:
HOST=args.HOST
if args.USER:
USER=args.USER
if args.PASSWORD:
PASSWORD=args.PASSWORD
if args.NAME:
NAME=args.NAME
#
# main()
#
LogOutput = '{'
LogOutput += '"datetime":"' + str(theCurrDateTime()) + '",'
if NAME == "":
print "ERROR: Missing required option --name"
sys.exit(1)
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username=USER, password=PASSWORD)
(stdin, stdout, stderr) = ssh.exec_command("esxcli system version get |grep Version")
type(stdin)
if re.match("Version", str(stdout.readlines())) is not None:
print "Unable to determine if this is a ESXi Host: %s, username: %s" % (HOST, USER)
sys.exit(1)
except:
print "The Error is " + str(sys.exc_info()[0])
print "Unable to access ESXi Host: %s, username: %s" % (HOST, USER)
sys.exit(1)
#
# Check if VM exists
#
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]
JNK = line.split('[')[1]
STORE = JNK.split(']')[0]
VMDIR = splitLine[3]
if VMID == -1:
print "Warning: VM " + NAME + " doesn't exists."
ErrorMessages += " VM " + NAME + " doesn't exists."
CheckHasErrors = True
CheckHasWarnings = True
except:
print "The Error is " + str(sys.exc_info()[0])
sys.exit(1)
# Get List of Volumes,
try:
(stdin, stdout, stderr) = ssh.exec_command("esxcli storage filesystem list |grep '/vmfs/volumes/.*true VMFS' |sort -nk7")
type(stdin)
VOLUMES = {}
for line in stdout.readlines():
splitLine = line.split()
VOLUMES[splitLine[0]] = splitLine[1]
except:
print "The Error is " + str(sys.exc_info()[0])
sys.exit(1)
# Convert STORE to path and visa-versa
V = []
for Path in VOLUMES:
V.append(VOLUMES[Path])
if STORE == Path or STORE == VOLUMES[Path]:
DSPATH = Path
DSSTORE = VOLUMES[Path]
if CheckHasErrors:
Result = "Errors"
else:
Result = "Success"
if not CheckHasErrors:
try:
CurrentState = ""
CurrentStateCounter = 0
while CurrentState != "off":
if isVerbose:
print "Get state VM"
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/power.getstate " + str(VMID))
type(stdin)
lines = str(stdout.readlines()) + str(stderr.readlines())
if isVerbose:
print "power.getstate: " + lines
if re.search("Powered off", lines):
CurrentState = "off"
# Power off VM
if isVerbose:
print "Power OFF VM"
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/power.off " + str(VMID) + " ||echo")
type(stdin)
lines = str(stdout.readlines()) + str(stderr.readlines())
if isVerbose:
print "power.off: " + str(lines)
CurrentStateCounter += 1
if CurrentStateCounter >10:
break
time.sleep(1)
# destroy VM
if isVerbose:
print "Destroy VM"
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/destroy " + str(VMID))
type(stdin)
lines = str(stdout.readlines()) + str(stderr.readlines())
if isVerbose:
print "destroy: " + str(lines)
except:
print "There was an error destroying the VM."
ErrorMessages += " There was an error destroying the VM."
CheckHasErrors = True
Result = "Fail"
# Print Summary
#
# The output log string
LogOutput += '"Host":"' + HOST + '",'
LogOutput += '"Name":"' + NAME + '",'
LogOutput += '"Store Used":"' + DSPATH + '",'
LogOutput += '"Verbose":"' + str(isVerbose) + '",'
if ErrorMessages != "":
LogOutput += '"Error Message":"' + ErrorMessages + '",'
LogOutput += '"Result":"' + Result + '",'
LogOutput += '"Completion Time":"' + str(theCurrDateTime()) + '"'
LogOutput += '}\n'
try:
with open(LOG, "a+w") as FD:
FD.write(LogOutput)
except:
print "Error writing to log file: " + LOG
if isSummary:
if isVerbose:
print "ESXi Host: " + HOST
print "VM NAME: " + NAME
print "Path: " + DSSTORE
else:
pass
if CheckHasErrors and not CheckHasWarnings:
print "Failed"
sys.exit(1)
else:
print "Success"
sys.exit(0)

View File

@ -57,7 +57,10 @@ def setup_config():
ISO="None",
# Default GuestOS type. (See VMware documentation for all available options)
GUESTOS="centos-64"
GUESTOS="centos-64",
# Extra VMX options
VMXOPTS=""
)
ConfigDataFileLocation = os.path.expanduser("~") + "/.esxi-vm.yml"
@ -112,4 +115,3 @@ def float2human(num):
return '0 bytes'
if num == 1:
return '1 byte'