Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
<#
.SYNOPSIS
Create a new Ubuntu 18 Virtual Machine on a vCenter server.
.DESCRIPTION
The New-UbuntuVM.ps1 function will create a new Ubuntu 18 Virtual Machine in vCenter
if the name does not already exist in the inventory.
You will present with two credential prompts. The first is to connect to vCenter and the second is local credentials on the template with sudo privileges.
The local account on the template must have NOPASSWD sudo access.
.EXAMPLE
.\New-UbuntuVM.ps1 -vCenterServer vCenter.fqdn -VMHostname VM.fqdn -VMIPv4 192.168.1.10/24 -VMGateway 192.168.1.1 -template OStemplate -datastore DS01 -Location "DataCenter01/VirtualMachines/Linux" -VMMemory 1024 -VMCPU 2 -VMDiskSize 30
.EXAMPLE
.\New-UbuntuVM.ps1 -vCenterServer vCenter.fqdn -VMHostname VM.fqdn -VMHost vsphere1.fqdn -VMIPv4 192.168.1.10/24 -VMGateway 192.168.1.1 -template OStemplate -datastore DS01 -Location "DataCenter01/VirtualMachines/Linux" -VMMemory 1024 -VMCPU 2 -VMDiskSize 30
.EXAMPLE
$VMArguments = @{
vCenterServer = "vCenter.fqdn"
VMHostname = "VM.fqdn"
VMHost = "vsphere1.fqdn"
VMIPv4 = "192.168.1.10/24"
VMGateway = "192.168.1.1"
template = "OStemplate"
datastore = "DS01"
Location = "DataCenter01/VirtualMachines/Linux"
VMMemory = "1024"
VMCPU = "2"
VMDiskSize = "30"
}
.\New-UbuntuVM.ps1 @VMArguments
#>
Param(
#vCenter Server FQDN or IP Address
[Parameter( Mandatory=$True, HelpMessage="vCenter Server", Position=0 )]
[ValidateNotNullOrEmpty()][string]$vCenterServer
, #VMHost
[Parameter( HelpMessage="vSphere Host. Leave blank to auto-select", Position=1 )]
[string]$VMHost="*"
, #VM Hostname
[Parameter( Mandatory=$True, HelpMessage="VM Hostname", Position=2 )]
[ValidateNotNullOrEmpty()][string]$VMHostname
, #VM IPv4 Address and CIDR Subnet prefix
[Parameter( Mandatory=$True, HelpMessage="Vm IPv4 IP Address and prefix", Position=3 )]
[ValidateNotNullOrEmpty()][string]$VMIPv4
, #VM IPv4 Default Gateway
[Parameter( Mandatory=$True, HelpMessage="VM IPv4 Gateway", Position=4 )]
[ValidateNotNullOrEmpty()][string]$VMGateway
, #Define DNS Servers for the VM
[Parameter( HelpMessage="VM DNS Servers", Position=5 )]
[string]$DNSNameServers="128.113.0.9, 128.113.28.67, 128.113.26.77"
, #Define the template that will be cloned
[Parameter( Mandatory=$True, HelpMessage="Template Name", Position=6 )]
[ValidateNotNullOrEmpty()][string]$template
, #Define the VM's datastore
[Parameter( Mandatory=$True, HelpMessage="Datastore Name", Position=7 )]
[ValidateNotNullOrEmpty()][string]$datastore
, #Define the Folder Location for the new VM (including DataCenter)
[Parameter( Mandatory=$True, HelpMessage="VM Location", Position=8 )]
[ValidateNotNullOrEmpty()][string]$Location
, #VM Memory
[Parameter( Mandatory=$True, HelpMessage="Memory [MB]", Position=9 )]
[ValidateNotNullOrEmpty()][int]$VMMemory
, #VM CPU
[Parameter( Mandatory=$True, HelpMessage="vCPU [count]", Position=10 )]
[ValidateNotNullOrEmpty()][int]$VMCPU
, #VM Disk Size
[Parameter( Mandatory=$True, HelpMessage="Disk [GB]", Position=11 )]
[ValidateRange(20,300)]
[ValidateNotNullOrEmpty()][int]$VMDiskSize
)
#$PSBoundParameters
function Get-IPv4SubnetMask {
param([Parameter(
ValueFromPipeline=$true)]
[int[]]
[ValidateRange(0, 32)]
$NetworkLength
)
process {
foreach ($Length in $NetworkLength) {
$MaskBinary = ('1' * $Length).PadRight(32, '0')
$DottedMaskBinary = $MaskBinary -replace '(.{8}(?!\z))', '${1}.'
$SubnetMask = ($DottedMaskBinary.Split('.') | ForEach-Object { [Convert]::ToInt32($_, 2) }) -join '.'
$SubnetMask
}
}
}
function Test-IPAddress($IPAddress) {
$Octet = '(?:0?0?[0-9]|0?[1-9][0-9]|1[0-9]{2}|2[0-5][0-5]|2[0-4][0-9])'
$IPv4Regex = "^(?:$Octet\.){3}$Octet$"
if (!($IPAddress.Contains('/'))) {
throw "No CIDR prefix found"
}
elseif (!(Get-IPv4SubnetMask $IPAddress.Split('/')[1])){
throw "CIDR Prefix is formatted incorrectly"
}
elseif (!($IPAddress.Split("/")[0] -match $IPv4Regex)){
throw "IP Address is formatted incorrectly"
}
}
function Start-VMPower {
param ([string] $VM)
if ((Get-VM $VM).powerstate -eq "PoweredOn"){
Write-Output "------ $VM is already powered on. ------"
} else {
Write-Output "------ Starting $VM now. ------"
Start-VM $VM -Confirm:$false
do {
$status = (Get-VM $VM | Get-View).Guest.ToolsRunningStatus
Start-Sleep 10
} until ($status -eq "guestToolsRunning")
return "ok"
}
}
function Get-VMPath {
param ([string] $VMPath)
$LocationArray = $VMPath.Split("/\\") # Split string using '/' or '\'
$command = "Get-Datacenter -name `""+$LocationArray[0]+"`""
if (Invoke-Expression $command) {
for ($Location=1; $Location -lt $LocationArray.Length; $Location++) {
$command = $command+" | Get-Folder -Name `""+$LocationArray[$Location]+"`""
}
return Invoke-Expression $command
}else{ throw }
}
function New-UbuntuVM {
# Validate $VMIPv4
try {
Test-IPAddress( $VMIPv4 )
}catch{
Write-Error "VMIPv4: $_"
exit
}
# Check if PowerCLI is installed
if (!(Get-Module -Name VMware* -ListAvailable)) {
Write-Warning "VMware PowerCLI Module does not exist"
Write-Warning "Please Install PowerCLI With the below command"
Write-Output "-------------------------------------------------------------"
Write-Output "Install-Module VMware.PowerCLI -AllowClobber -Scope CurrentUser"
#Install-Module VMware.PowerCLI -AllowClobber -Scope CurrentUser
#Save-Module -Name VMware.PowerCLI -Path $home\Documents\WindowsPowerShell\Modules
Write-Output "-------------------------------------------------------------"
Exit
}
## Connect to vCenter
$VCSCred = $Host.UI.PromptForCredential("Please enter vCenter credentials", "Enter Credentials for $vCenterServer", "", "")
Write-Output "------ Connecting to vCenter Server ------"
if(!$(Connect-VIServer $vCenterServer -Credential $VCSCred)){
throw
}
# Get VM settings
$VMShortHostname = $VMHostname.Split('.')[0]
$SubnetMask = Get-IPv4SubnetMask $VMIPv4.Split('/')[1]
$IPAddress = $VMIPv4.Split('/')[0]
$VMGuestCredential = $Host.UI.PromptForCredential("Please enter VM Guest Credentials", "Enter Credentials for $VMHostname", "", "")
if($VMGuestCredential -eq $null){ Write-Error "No VM Guest Credentials provided"; exit}
Write-Output "------ Variable Values ------"
Write-Output "`$VMHostname: $VMHostname"
Write-Output "`$VMShortHostname: $VMShortHostname"
Write-Output "`$vCenterServer: $vCenterServer"
Write-Output "`$VMHost: $VMHost"
Write-Output "`$VMIPv4: $VMIPv4"
Write-Output "`$IPAddress: $IPAddress"
Write-Output "`$SubnetMask: $SubnetMask"
Write-Output "`$VMGateway: $VMGateway"
Write-Output "`$template: $template"
Write-Output "`$datastore: $datastore"
Write-Output "`$Location: $Location"
Write-Output "`$VMMemory: $VMMemory"
Write-Output "`$VMCPU: $VMCPU"
Write-Output "`$VMDiskSize: $VMDiskSize"
Write-Output "`$VMGuestCred: $VMGuestCredential"
#Uncomment below to debug variables
#Disconnect-VIServer -Server $vCenterServer -Confirm:$false
#exit 0
# Check if VM exists
if(Get-VM -name $VMHostname -ErrorAction SilentlyContinue){
Write-Error "VM $VMHostname Already Exists"
exit
}
## Create VM
Write-Output "------ Creating Virtual Machine ------"
$NewVMHost = Get-VMHost $VMHost | Sort-Object -Property MemoryusageGB | Select-Object -First 1
$NewVMLocation = Get-VMPath $Location
New-VM -Name $VMHostname -Template $template -VMHost $NewVMHost -Location $NewVMLocation -Datastore $datastore
## Set Resources
Write-Output "------ Setting Virtual Machine Memory and CPU ------"
Set-VM $VMHostname -MemoryMB $VMMemory -NumCpu $VMCPU -Confirm:$false
Write-Output "------ Setting Virtual Machine Hard Disk ------"
Get-HardDisk -VM $VMHostname|Set-HardDisk -CapacityGB $VMDiskSize -Confirm:$false
## Power on VM if not running
$VM_Power_State = Start-VMPower $VMHostname
if ($VM_Power_State -eq "ok"){
Write-Output "------ $VMHostname Started ------"
}
## Run VM-Commands
$VMNetwork = "
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
ens192:
dhcp4: no
dhcp6: no
addresses: [$VMIPv4, ]
gateway4: $VMGateway
nameservers:
addresses: [$DNSNameServers]
"
$ConfigNetwork = "
sudo netplan generate
echo `"$VMNetwork`" | sudo tee /etc/netplan/01-netcfg.yaml
sudo netplan apply
sudo rm -f /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server
"
Write-Output "------ Setting Virtual Machine Networking ------"
Invoke-VMScript -ScriptType bash -VM $VMHostname -ScriptText $ConfigNetwork -GuestCredential $VMGuestCredential
Write-Output "------ Updating Virtual Machine Packages ------"
$UpdateOS = "sudo apt-get update && sudo apt-get -y dist-upgrade"
Invoke-VMScript -ScriptType bash -VM $VMHostname -ScriptText $UpdateOS -GuestCredential $VMGuestCredential
$VMHostsFile = "
127.0.0.1 $VMhostname $VMShortHostname localhost
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
"
Write-Output "------ Setting Virtual Machine Hostname ------"
$ConfigHostsFile = "echo `"$VMHostsFile`" | sudo tee /etc/hosts && sudo hostnamectl set-hostname $VMShortHostname && echo $VMShortHostname | sudo tee /etc/hostname"
Invoke-VMScript -ScriptType bash -VM $VMHostname -ScriptText $ConfigHostsFile -GuestCredential $VMGuestCredential
## Restart VM
Write-Output "------ Restarting Virtual Machine ------"
Restart-VMGuest -VM $VMHostname -Confirm:$false
## Disconnect from vCenter
Write-Output "------ Disconnecting to vCenter Server ------"
Disconnect-VIServer -Server $vCenterServer -Confirm:$false
}
New-UbuntuVM