mirror of https://github.com/Kodomo/esxi-vm
Init commit
commit
390d04b57b
|
@ -0,0 +1,136 @@
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This utility is a simple to use comand line tool to create VMs on an ESXi host from from a system running python and ssh. vCenter is not required. You need to enable ssh access on your ESXi server. It's HIGHLY RECOMMENDED to use password-less authentication by copying your ssh public keys to the ESXi host.
|
||||||
|
|
||||||
|
|
||||||
|
Command Line Args
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
```
|
||||||
|
./esxi-vm-create -h
|
||||||
|
usage: esxi-vm-create [-h] [-d] [-v] [-H HOST] [-U USER] [-P PASSWORD]
|
||||||
|
[-n NAME] [-c CPU] [-m MEM] [-s SIZE] [-i ISO] [-N NET]
|
||||||
|
[-S STORE] [-g GUESTOS] [-u]
|
||||||
|
|
||||||
|
ESXi Create VM utility.
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-d, --dry Enable Dry Run mode (False)
|
||||||
|
-v, --verbose Enable Verbose mode (False)
|
||||||
|
-H HOST, --Host HOST ESXi Host (esxi)
|
||||||
|
-U USER, --User USER ESXi Host username (root)
|
||||||
|
-P PASSWORD, --Password PASSWORD
|
||||||
|
ESXi Host password (*****)
|
||||||
|
-n NAME, --name NAME VM name
|
||||||
|
-c CPU, --cpu CPU Number of vCPUS (2)
|
||||||
|
-m MEM, --mem MEM Memory in GB (4)
|
||||||
|
-s SIZE, --size SIZE Size of virt disk (20)
|
||||||
|
-i ISO, --iso ISO CDROM ISO Path | None (None)
|
||||||
|
-N NET, --net NET Network Interface | None (None)
|
||||||
|
-S STORE, --store STORE
|
||||||
|
vmfs Store | LeastUsed (DS_3TB_m)
|
||||||
|
-g GUESTOS, --guestos GUESTOS
|
||||||
|
Guest OS. (centos-64)
|
||||||
|
-u, --updateDefaults Update Default VM settings stored in ~/.esxi-vm.yml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
|
||||||
|
Create a new VM named testvm01 using all defaults from ~/.esxi-vm.yml.
|
||||||
|
```
|
||||||
|
./esxi-vm-create -n testvm01
|
||||||
|
|
||||||
|
Create VM Success
|
||||||
|
ESXi Host: esxi
|
||||||
|
VM NAME: testvm01
|
||||||
|
vCPU: 2
|
||||||
|
Memory: 4GB
|
||||||
|
VM Disk: 20GB
|
||||||
|
DS Store: DS_4TB
|
||||||
|
Network: None
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Change default number of vCPUs to 4, Memory to 8GB and vDisk size to 40GB.
|
||||||
|
```
|
||||||
|
./esxi-vm-create -c 4 -m 8 -s 40 -u
|
||||||
|
Saving new Defaults to ~/.esxi-vm.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a new VM named testvm02 using new defaults from ~/.esxi-vm.yml and specifying a Network interface.
|
||||||
|
```
|
||||||
|
./esxi-vm-create -n testvm02 -N 192.168.1
|
||||||
|
|
||||||
|
Create VM Success
|
||||||
|
ESXi Host: esxi
|
||||||
|
VM NAME: testvm02
|
||||||
|
vCPU: 4
|
||||||
|
Memory: 8GB
|
||||||
|
VM Disk: 40GB
|
||||||
|
DS Store: DS_4TB
|
||||||
|
Network: 192.168.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Available Network Interfaces and Available Disk Storage volumes will be listed if an invalid entry is made.
|
||||||
|
|
||||||
|
```
|
||||||
|
./esxi-vm-create -n testvm03 -N BadNet -S BadDS
|
||||||
|
ERROR: Disk Storage BadDS doesn't exist.
|
||||||
|
Available Disk Stores: ['DS_SSD500s', 'DS_SSD500c', 'DS_SSD250', 'DS_4TB', 'DS_3TB_m']
|
||||||
|
LeastUsed Disk Store : DS_4TB
|
||||||
|
ERROR: Virtual NIC BadNet doesn't exist.
|
||||||
|
Available VM NICs: ['192.168.1', '192.168.0', 'VM Network test'] or 'None'
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a new VM named testvm03 using a valid Network Interface, valid Disk Storage volume, enabled verbose and saving the settings as default.
|
||||||
|
```
|
||||||
|
./esxi-vm-create -n testvm03 -N 192.168.1 -S DS_3TB_m -v -u
|
||||||
|
Saving new Defaults to ~/.esxi-vm.yml
|
||||||
|
Create testvm03.vmx file
|
||||||
|
Create testvm03.vmdk file
|
||||||
|
Register VM
|
||||||
|
Power ON VM
|
||||||
|
|
||||||
|
Create VM Success
|
||||||
|
ESXi Host: esxi
|
||||||
|
VM NAME: testvm03
|
||||||
|
vCPU: 4
|
||||||
|
Memory: 8GB
|
||||||
|
VM Disk: 40GB
|
||||||
|
Format: thin
|
||||||
|
DS Store: DS_3TB_m
|
||||||
|
Network: 192.168.1
|
||||||
|
Guest OS: centos-64
|
||||||
|
```
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Copyright (C) 2017 Jonathan Senkerik
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
Support
|
||||||
|
-------
|
||||||
|
Website : http://www.jintegrate.co
|
||||||
|
|
||||||
|
github : http://github.com/josenk/
|
||||||
|
|
|
@ -0,0 +1,369 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
|
||||||
|
import argparse # Argument parser
|
||||||
|
import datetime # For current Date/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']
|
||||||
|
HOST = ConfigData['HOST']
|
||||||
|
USER = ConfigData['USER']
|
||||||
|
PASSWORD = ConfigData['PASSWORD']
|
||||||
|
CPU = ConfigData['CPU']
|
||||||
|
MEM = ConfigData['MEM']
|
||||||
|
SIZE = int(ConfigData['SIZE'])
|
||||||
|
DISKFORMAT = ConfigData['DISKFORMAT']
|
||||||
|
VIRTDEV = ConfigData['VIRTDEV']
|
||||||
|
STORE = ConfigData['STORE']
|
||||||
|
NET = ConfigData['NET']
|
||||||
|
ISO = ConfigData['ISO']
|
||||||
|
GUESTOS = ConfigData['GUESTOS']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Process Arguments
|
||||||
|
#
|
||||||
|
parser = argparse.ArgumentParser(description='ESXi Create VM utility.')
|
||||||
|
|
||||||
|
parser.add_argument('-d', '--dry', dest='isDryRunarg', action='store_true', help="Enable Dry Run mode (" + str(isDryRun) + ")")
|
||||||
|
parser.add_argument('-v', '--verbose', dest='isVerbosearg', action='store_true', help="Enable Verbose mode (" + str(isVerbose) + ")")
|
||||||
|
parser.add_argument("-H", "--Host", dest='HOST', type=str, help="ESXi Host (" + 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("-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) + ")")
|
||||||
|
parser.add_argument("-s", "--size", dest='SIZE', type=str, help="Size of virt disk (" + str(SIZE) + ")")
|
||||||
|
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) + ")")
|
||||||
|
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("-u", "--updateDefaults", dest='UPDATE', action='store_true', help="Update Default VM settings stored in ~/.esxi-vm.yml")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.isDryRunarg:
|
||||||
|
isDryRun = True
|
||||||
|
if args.isVerbosearg:
|
||||||
|
isVerbose = 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
|
||||||
|
if args.CPU:
|
||||||
|
CPU=int(args.CPU)
|
||||||
|
if args.mem:
|
||||||
|
MEM=int(args.mem)
|
||||||
|
if args.SIZE:
|
||||||
|
SIZE=int(args.SIZE)
|
||||||
|
if args.ISO:
|
||||||
|
ISO=args.ISO
|
||||||
|
if args.NET:
|
||||||
|
NET=args.NET
|
||||||
|
if args.STORE:
|
||||||
|
STORE=args.STORE
|
||||||
|
if STORE == "":
|
||||||
|
STORE = "LeastUsed"
|
||||||
|
if args.GUESTOS:
|
||||||
|
GUESTOS=args.GUESTOS
|
||||||
|
|
||||||
|
if args.UPDATE:
|
||||||
|
print "Saving new Defaults to ~/.esxi-vm.yml"
|
||||||
|
ConfigData['isDryRun'] = isDryRun
|
||||||
|
ConfigData['isVerbose'] = isVerbose
|
||||||
|
ConfigData['HOST'] = HOST
|
||||||
|
ConfigData['USER'] = USER
|
||||||
|
ConfigData['PASSWORD'] = PASSWORD
|
||||||
|
ConfigData['CPU'] = CPU
|
||||||
|
ConfigData['MEM'] = MEM
|
||||||
|
ConfigData['SIZE'] = SIZE
|
||||||
|
ConfigData['DISKFORMAT'] = DISKFORMAT
|
||||||
|
ConfigData['VIRTDEV'] = VIRTDEV
|
||||||
|
ConfigData['STORE'] = STORE
|
||||||
|
ConfigData['NET'] = NET
|
||||||
|
ConfigData['ISO'] = ISO
|
||||||
|
ConfigData['GUESTOS'] = GUESTOS
|
||||||
|
SaveConfig(ConfigData)
|
||||||
|
if NAME == "":
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
#
|
||||||
|
# main()
|
||||||
|
#
|
||||||
|
# print "Current Date " + theCurrDateTime()
|
||||||
|
CheckHasErrors = False
|
||||||
|
|
||||||
|
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", stdout.readlines()) is not None:
|
||||||
|
print "Unable to access ESXi Host: %s, username: %s" % (HOST, USER)
|
||||||
|
sys.exit(1)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get list of DataStores, store in VOLUMES
|
||||||
|
#
|
||||||
|
LeastUsedDS = ""
|
||||||
|
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]
|
||||||
|
LeastUsedDS = splitLine[1]
|
||||||
|
except:
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if STORE == "LeastUsed":
|
||||||
|
STORE = LeastUsedDS
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get list of Networks available, store in VMNICS
|
||||||
|
#
|
||||||
|
try:
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("esxcli network vswitch standard list|grep Portgroups|sed 's/^ Portgroups: //g'")
|
||||||
|
type(stdin)
|
||||||
|
VMNICS = []
|
||||||
|
for line in stdout.readlines():
|
||||||
|
splitLine = re.split(',|\n', line)
|
||||||
|
VMNICS.append(splitLine[0])
|
||||||
|
except:
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get from ESXi host if ISO exists
|
||||||
|
#
|
||||||
|
ISOfound = False
|
||||||
|
if ISO == "None":
|
||||||
|
ISO = ""
|
||||||
|
if ISO != "":
|
||||||
|
try:
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("ls " + str(ISO))
|
||||||
|
type(stdin)
|
||||||
|
if not stdout.readlines() and stderr.readlines():
|
||||||
|
ISOfound = True
|
||||||
|
except:
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
#
|
||||||
|
# Check if VM already 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]
|
||||||
|
print "ERROR: VM " + NAME + " already exists."
|
||||||
|
CheckHasErrors = True
|
||||||
|
except:
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Do checks here
|
||||||
|
#
|
||||||
|
|
||||||
|
# Check CPU
|
||||||
|
if CPU < 1 or CPU > 128:
|
||||||
|
print str(CPU) + " CPU out of range. [1-128]"
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check MEM
|
||||||
|
if MEM < 1 or MEM > 4080:
|
||||||
|
print str(MEM) + "GB Memory out of range. [1-4080]"
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check SIZE
|
||||||
|
if SIZE < 1 or SIZE > 63488:
|
||||||
|
print "Virtual Disk size " + str(SIZE) + "GB out of range. [1-63488]"
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check STORE
|
||||||
|
V = []
|
||||||
|
DSPATH=""
|
||||||
|
DSSTORE=""
|
||||||
|
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:
|
||||||
|
print "ERROR: Disk Storage " + STORE + " doesn't exist. "
|
||||||
|
print " Available Disk Stores: " + str(V)
|
||||||
|
print " LeastUsed Disk Store : " + str(LeastUsedDS)
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check NIC (NIC record)
|
||||||
|
if (NET not in VMNICS) and (NET != "None"):
|
||||||
|
print "ERROR: Virtual NIC " + NET + " doesn't exist."
|
||||||
|
print " Available VM NICs: " + str(VMNICS) + " or 'None'"
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check ISO exists
|
||||||
|
if ISO != "" and not ISOfound:
|
||||||
|
print "ERROR: ISO " + ISO + " not found. Use full path to ISO"
|
||||||
|
CheckHasErrors = True
|
||||||
|
|
||||||
|
# Check if DSPATH/NAME aready exists
|
||||||
|
FullPathExists = False
|
||||||
|
try:
|
||||||
|
FullPath = DSPATH + "/" + NAME
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("ls -d " + FullPath)
|
||||||
|
type(stdin)
|
||||||
|
if stdout.readlines() and not stderr.readlines():
|
||||||
|
print "ERROR: Directory " + FullPath + " already exists."
|
||||||
|
CheckHasErrors = True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
#
|
||||||
|
# Exit if there are any errors
|
||||||
|
#
|
||||||
|
if CheckHasErrors:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create the VM
|
||||||
|
#
|
||||||
|
VMX = []
|
||||||
|
VMX.append('config.version = "8"')
|
||||||
|
VMX.append('virtualHW.version = "8"')
|
||||||
|
VMX.append('vmci0.present = "TRUE"')
|
||||||
|
VMX.append('displayName = "' + NAME + '"')
|
||||||
|
VMX.append('floppy0.present = "FALSE"')
|
||||||
|
VMX.append('numvcpus = "' + str(CPU) + '"')
|
||||||
|
VMX.append('scsi0.present = "TRUE"')
|
||||||
|
VMX.append('scsi0.sharedBus = "none"')
|
||||||
|
VMX.append('scsi0.virtualDev = "pvscsi"')
|
||||||
|
VMX.append('memsize = "' + str(MEM * 1024) + '"')
|
||||||
|
VMX.append('scsi0:0.present = "TRUE"')
|
||||||
|
VMX.append('scsi0:0.fileName = "' + NAME + '.vmdk"')
|
||||||
|
VMX.append('scsi0:0.deviceType = "scsi-hardDisk"')
|
||||||
|
if ISO == "":
|
||||||
|
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"')
|
||||||
|
else:
|
||||||
|
VMX.append('ide1:0.present = "TRUE"')
|
||||||
|
VMX.append('ide1:0.fileName = "' + ISO + '"')
|
||||||
|
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"')
|
||||||
|
VMX.append('guestOS = "' + GUESTOS + '"')
|
||||||
|
if NET != "None":
|
||||||
|
VMX.append('ethernet0.virtualDev = "vmxnet3"')
|
||||||
|
VMX.append('ethernet0.present = "TRUE"')
|
||||||
|
VMX.append('ethernet0.networkName = "' + NET + '"')
|
||||||
|
VMX.append('ethernet0.addressType = "generated"')
|
||||||
|
|
||||||
|
if isDryRun:
|
||||||
|
print "Dry Run Enabled. No VM created..."
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Create NAME.vmx
|
||||||
|
if isVerbose:
|
||||||
|
print "Create " + NAME + ".vmx file"
|
||||||
|
MyVM = FullPath + "/" + NAME
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("mkdir " + FullPath )
|
||||||
|
type(stdin)
|
||||||
|
for line in VMX:
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("echo " + line + " >>" + MyVM + ".vmx")
|
||||||
|
type(stdin)
|
||||||
|
|
||||||
|
# Create vmdk
|
||||||
|
if isVerbose:
|
||||||
|
print "Create " + NAME + ".vmdk file"
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("vmkfstools -c " + str(SIZE) + "G -d " + DISKFORMAT + " " + MyVM + ".vmdk")
|
||||||
|
type(stdin)
|
||||||
|
|
||||||
|
# Register VM
|
||||||
|
if isVerbose:
|
||||||
|
print "Register VM"
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd solo/registervm " + MyVM + ".vmx")
|
||||||
|
type(stdin)
|
||||||
|
Jnk = stdout.readlines()
|
||||||
|
VMID = int(Jnk[0])
|
||||||
|
|
||||||
|
# Power on VM
|
||||||
|
if isVerbose:
|
||||||
|
print "Power ON VM"
|
||||||
|
(stdin, stdout, stderr) = ssh.exec_command("vim-cmd vmsvc/power.on " + str(VMID))
|
||||||
|
type(stdin)
|
||||||
|
if stderr.readlines():
|
||||||
|
print "Error Power.on VM."
|
||||||
|
sys.exit(1)
|
||||||
|
except:
|
||||||
|
print "There was an error creating the VM!"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Print Summary
|
||||||
|
print "\nCreate VM Success"
|
||||||
|
print "ESXi Host: " + HOST
|
||||||
|
print "VM NAME: " + NAME
|
||||||
|
print "vCPU: " + str(CPU)
|
||||||
|
print "Memory: " + str(MEM) + "GB"
|
||||||
|
print "VM Disk: " + str(SIZE) + "GB"
|
||||||
|
if isVerbose:
|
||||||
|
print "Format: " + DISKFORMAT
|
||||||
|
print "DS Store: " + DSSTORE
|
||||||
|
print "Network: " + NET
|
||||||
|
if ISO:
|
||||||
|
print "ISO: " + ISO
|
||||||
|
if isVerbose:
|
||||||
|
print "Guest OS: " + GUESTOS
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import os.path
|
||||||
|
import yaml
|
||||||
|
import datetime # For current Date/Time
|
||||||
|
import paramiko # For remote ssh
|
||||||
|
from math import log
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Functions
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def setup_config():
|
||||||
|
|
||||||
|
#
|
||||||
|
# System wide defaults
|
||||||
|
#
|
||||||
|
ConfigData = dict(
|
||||||
|
LOG="~/esxi-vm.log",
|
||||||
|
isDryRun=False,
|
||||||
|
isVerbose=False,
|
||||||
|
HOST="esxi",
|
||||||
|
USER="root",
|
||||||
|
PASSWORD="",
|
||||||
|
CPU=2,
|
||||||
|
MEM=4,
|
||||||
|
SIZE=20,
|
||||||
|
DISKFORMAT="thin",
|
||||||
|
VIRTDEV="pvscsi",
|
||||||
|
STORE="LeastUsed",
|
||||||
|
NET="None",
|
||||||
|
ISO="None",
|
||||||
|
GUESTOS="centos-64"
|
||||||
|
)
|
||||||
|
|
||||||
|
ConfigDataFileLocation = os.path.expanduser("~") + "/.esxi-vm.yml"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get ConfigData from ConfigDataFile, then merge.
|
||||||
|
if os.path.exists(ConfigDataFileLocation):
|
||||||
|
FromFileConfigData = yaml.safe_load(open(ConfigDataFileLocation))
|
||||||
|
ConfigData.update(FromFileConfigData)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(ConfigDataFileLocation, 'w') as FD:
|
||||||
|
yaml.dump(ConfigData, FD, default_flow_style=False)
|
||||||
|
FD.close()
|
||||||
|
except:
|
||||||
|
print "Unable to create/update config file " + ConfigDataFileLocation
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
return ConfigData
|
||||||
|
|
||||||
|
def SaveConfig(ConfigData):
|
||||||
|
ConfigDataFileLocation = os.path.expanduser("~") + "/.esxi-vm.yml"
|
||||||
|
try:
|
||||||
|
with open(ConfigDataFileLocation, 'w') as FD:
|
||||||
|
yaml.dump(ConfigData, FD, default_flow_style=False)
|
||||||
|
FD.close()
|
||||||
|
except:
|
||||||
|
print "Unable to create/update config file " + ConfigDataFileLocation
|
||||||
|
e = sys.exc_info()[0]
|
||||||
|
print "The Error is " + str(e)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def theCurrDateTime():
|
||||||
|
i = datetime.datetime.now()
|
||||||
|
return str(i.isoformat())
|
||||||
|
|
||||||
|
|
||||||
|
unit_list = zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2])
|
||||||
|
def float2human(num):
|
||||||
|
"""Integer to Human readable"""
|
||||||
|
if num > 1:
|
||||||
|
exponent = min(int(log(float(num), 1024)), len(unit_list) - 1)
|
||||||
|
quotient = float(num) / 1024**exponent
|
||||||
|
unit, num_decimals = unit_list[exponent]
|
||||||
|
format_string = '{:.%sf} {}' % (num_decimals)
|
||||||
|
return format_string.format(quotient, unit)
|
||||||
|
if num == 0:
|
||||||
|
return '0 bytes'
|
||||||
|
if num == 1:
|
||||||
|
return '1 byte'
|
||||||
|
|
Loading…
Reference in New Issue