Sep
12
2017

T-SQL Tuesday #94 – Lets get all Posh! Creating VMs with PS

tsql2sday150x150

 This post is part of the T-SQL Tuesday, which is a monthly blog party on the second Tuesday of each month. Everyone is welcome and have the chance to write about SQL Server.
This month’s host is Rob Sewell (B|T) and the topic is Lets get all Posh!, and it’s nothing about wearing fancy hats and going to a horse track, but about powershell as you might have imagined already 🙂 So here it is my little addition.

 
Background

Recently at work we have redesigned our infrastructure to provide better availability and disaster recovery (HA/DR) and that involves lots of new servers for redundancy which must be as close as possible if not equal to the servers they provide failover to.

Most of these servers will be virtual machines running on different Windows 2016 Hyper-V hosts and for the shake of simplicity we want to minimise the use of UI and manual configurations, so I rolled up my sleeves and got Posh!

A good number of the steps to create a configure the new virtual machines can be scripted, which will provide consistent output as well as make our life easier in case we need to create everything from scratch again. For instance to create a new environment like DEV, TEST, PRELIVE, QA or so.

 
Virtual Machines and powershell

There are a lots of command to create or manipulate VM’s and I’m still only scratching the surface, but although I’m not a PS person, I have to admit that every time I want to do something, I find relatively easy to find a powershell command or a script for it, so I like it.

For instance, creating new virtual machines it’s a simple as one command

New-VM

And that’s only the beginning, we can add the different virtual hardware like in the UI, Drives, Network Adapters and so on. And then configure memory, CPU and NUMA, etc…

This is the script which I’m more or less running to create my VM’s, this in particular will be a Hyper-V Host itself, so there are a couple of interesting settings I’ll tell you about later.

##########################################################
#
# Script to create virtual machines 
# The VM created can be used as a Virtual Host (nested virtualization in Win 2016)
#
##########################################################

##########################################################
# Environment variables
##########################################################
$environment = "d"; # p = production, d = dev, t = test, q = qa
$envprefix = '';

switch ($environment){
    "p" {$envprefix = ''}
    "d" {$envprefix = "DEV"}
    "t" {$envprefix = "TEST"}
    "q" {$envprefix = "QA"}
};

$HyperVHost = "HYPERV-" + $envprefix;
$HyperVSwitchName = "Network Adapter Name";

##########################################################
# variables to create the new VM
##########################################################
$VmNodeNumber = "1"
$VmName = "HYPERV-" + $envprefix + $VmNodeNumber;
$VmMemory = 24GB;
$VmCpuCount = 8;
$VmCpuCountPerNuma = 4;
$VmNumaPerSocket = 2;
$VmMemoryPerNuma = 12GB;

##########################################################
# variables to create C drive for the new VM
##########################################################
$VirtualMachine_VM_path = "D:\"; # VM name will be added automatically
$VirtualMachine_C_path = "D:\$VmName\Virtual Hard Disks\";
$VirtualMachine_C_name = $VmName + "_C.vhdx";
$VirtualMachine_C_fullpath = $VirtualMachine_C_path + $VirtualMachine_C_name;
$VirtualMachine_C_size = 128GB;

##########################################################
# variables to create D drive for the new HyperVisor
##########################################################
$VirtualMachine_D_path = "D:\$VmName\Virtual Hard Disks\";
$VirtualMachine_D_name = $VmName + "_D.vhdx";
$VirtualMachine_D_fullpath = $VirtualMachine_D_path + $VirtualMachine_D_name;
$VirtualMachine_D_size = 896GB;

##########################################################
# path for the ISO file to install OS
##########################################################
$OsIsoFilePath = "D:\ISO\Windows Server 2016\en_windows_server_2016_x64_dvd_2342342.iso"


##########################################################
#
#
# Start the process
#
# 
##########################################################

##########################################################
# Open an remote session with the host
##########################################################
Enter-PSSession -computername $HyperVHost;


##########################################################
# Test the path where we want to create the new VHDX
##########################################################
if ( (Test-Path $VirtualMachine_C_path) -eq $false ) {
    mkdir $VirtualMachine_C_path;
}
elseif ( (Test-Path $VirtualMachine_C_fullpath) -eq $true){
    return "The VHDX file already exists";
    exit;
}

##########################################################
# Create New VM with C drive
##########################################################
New-VM -ComputerName $HyperVHost -Name $VmName -Generation 2 -MemoryStartupBytes $VmMemory -Path $VirtualMachine_VM_path -NewVHDPath $VirtualMachine_C_fullpath -NewVHDSizeBytes $VirtualMachine_C_size;


##########################################################        
# Create New D drive
##########################################################
if ( (Test-Path $VirtualMachine_D_path) -eq $false ) {
    mkdir $VirtualMachine_D_path;
}
elseif ( (Test-Path $VirtualMachine_D_fullpath) -eq $true){
    return "The VHDX file already exists";
    exit;
}

New-VHD -Path $VirtualMachine_D_fullpath -ComputerName $HyperVHost -Dynamic -SizeBytes $VirtualMachine_D_size;

Add-VMHardDiskDrive -ComputerName $HyperVHost -VMName $VmName -ControllerType SCSI -Path $VirtualMachine_D_fullpath;


##########################################################        
# Configure Vm processors and NUMA
##########################################################

Set-VMProcessor -ComputerName $HyperVHost -VMName $VmName -Count $VmCpuCount -MaximumCountPerNumaNode $VmCpuCountPerNuma -MaximumCountPerNumaSocket $VmNumaPerSocket;

Set-VMMemory -ComputerName $HyperVHost -VMName $VmName -MaximumAmountPerNumaNodeBytes $VmMemoryPerNuma;


##########################################################        
# Add ISO file to install OS
##########################################################

Add-VMDvdDrive -ComputerName $HyperVHost -VMName $VmName -Path $OsIsoFilePath;

##########################################################        
# Allow nested virtual hosts
##########################################################

Set-VMProcessor -VMName $VmName -ExposeVirtualizationExtensions $true;

##########################################################        
# Add Network adapter
##########################################################

Connect-VMNetworkAdapter -ComputerName $HyperVHost -VMName $VmName -SwitchName $HyperVSwitchName;
Set-VMNetworkAdapter -VMName $VmName -MacAddressSpoofing On; #Important for nested VMs to have access to the domain!!!!

##########################################################        
# Start the VM if we want to
##########################################################

#Start-VM -ComputerName $HyperVHost -Name $VmName;

##########################################################        
#
#
# at this point the machine is ready to get Windows installed
#
#
##########################################################

exit;

 
There are a couple of settings that are specific to nested Virtual Hosts, one is to allow the processor to be virtualized and the other to allow networking to work correctly in the Vm’s.

##########################################################        
# Allow nested virtual hosts
##########################################################

Set-VMProcessor -VMName $VmName -ExposeVirtualizationExtensions $true;

##########################################################        
# Add Network adapter
##########################################################

Connect-VMNetworkAdapter -ComputerName $HyperVHost -VMName $VmName -SwitchName $HyperVSwitchName;
Set-VMNetworkAdapter -VMName $VmName -MacAddressSpoofing On; #Important for nested VMs to have access to the domain!!!!

#

 
Conclusion

As I said, I’m no expert using powershell or administering Windows Server, but seems like there are a commands for all your needs which is amazing, not only for how easy we can do things, but how easy we can repeat the process should we need to.

I still have to find out how to do a couple of more things like modifying the new Vm’s network configuration or adding the VM to a domain and so on, but surely I will get to them quick!

Thanks for reading and to @sqldbawithbeard for hosting this month’s event and congratulations for his recent MVP Award!

 

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInShare on Reddit
One comment

Leave a Reply

Your email address will not be published. Required fields are marked *