PowerShell Function to Prevent Starting Hyper-V VM’s that are Connected to an External Network
Beginning with Windows 8 (Professional and Enterprise Edition), Hyper-V is available on workstations that have a processor that supports SLAT (Second Level Address Translation). For specifics about the requirements, see the Client Hyper-V blog article on Microsoft TechNet. That means you have a Hypervisor running right on your desktop or laptop computer for free. With the price of hardware these days, your regular everyday computer can be spec'd out with an i7 processor, 16 gigabytes of memory, and one or more solid state drives and in addition to performing your everyday work on it, you have an awesome test environment without the need for additional physical computers.
Thanks to the server core (no-GUI) installation of newer versions of Windows Server, you can run a number of VM's on the previously referenced hardware with no issues. I have a domain controller, web server, and a couple of SQL servers all running on Windows Server 2012 R2 with the server core installation. I also have more than a half dozen test Windows 8.1 machines on that same hardware, all of which can be running at the same time if needed thanks to Hyper-V's dynamic memory feature.
All of that is well and fine until you decided to run something like the DHCP Server role on one of the servers in that test lab environment. Accidentally connect it to an external network and it could reap havoc on your production network to say the least.
That's why I created the following function to only boot VM's that are connected to internal or private network. It will also start VM's that are not connected to a network.
1#Requires -Version 3.0
2#Requires -Modules Hyper-V
3function Start-MrVM {
4
5<#
6.SYNOPSIS
7 Starts Hyper-V VM's that are valid, not already running, and not connected
8 to an external network.
9
10.DESCRIPTION
11 Start-MrVM is a function that is designed to start a test lab environment of
12 VM's running on Hyper-V on a Windoes 8.1 machine. It is designed specifically
13 to prevent VM's that are connected to an external switch from being started
14 since this could interfere with a production environment because of the
15 potiential of things like a DHCP server running in the test VM environment.
16
17.PARAMETER VMName
18 The name of the VM(s) to start.
19
20.EXAMPLE
21 Start-MrVM -VMName DC01, SQL01, PC01
22
23.EXAMPLE
24 'DC01', 'SQL01', 'PC01' | Start-MrVM
25
26.EXAMPLE
27 Get-VM | Start-MrVM
28
29.INPUTS
30 String
31
32.OUTPUTS
33 None
34
35.NOTES
36 Author: Mike F Robbins
37 Website: http://mikefrobbins.com
38 Twitter: @mikefrobbins
39#>
40
41 [CmdletBinding()]
42 param (
43 [Parameter(Mandatory,
44 ValueFromPipeline,
45 ValueFromPipelineByPropertyName)]
46 [Alias('Name')]
47 [string[]]$VMName
48 )
49
50 BEGIN {
51 try {
52 $VMs = Get-VM -ErrorAction Stop
53 $VMSwitches = Get-VMSwitch -SwitchType Internal, Private -ErrorAction Stop |
54 Select-Object -ExpandProperty Name
55 }
56 catch {
57 Write-Warning -Message "An error has occured. Error details: $_.Exception.Message"
58 }
59 }
60
61 PROCESS {
62 foreach ($v in $VMName) {
63
64 if ($VMs.Name -contains $v) {
65
66 $VM = $VMs | Where-Object Name -eq $v
67
68 if ($VM.State -ne 'Running') {
69
70 $VMSwitch = $VM | Get-VMNetworkAdapter | Select-Object -ExpandProperty SwitchName
71
72 if ($VMSwitches -contains $VMSwitch -or (-not($VMSwitch))) {
73
74 Write-Verbose -Message "Starting VM: $($VM.Name)"
75
76 try {
77 Start-VM -Name $VM.VMName -ErrorAction Stop
78 }
79 catch {
80 Write-Warning -Message "An error has occured. Error details: $_.Exception.Message"
81 }
82
83 }
84 else {
85 Write-Warning -Message "VM: $($VM.Name) was not started because it's network is set to External!"
86 }
87 }
88 else {
89 Write-Warning -Message "VM: $($VM.Name) is Already Running!"
90 }
91 }
92 else {
93 Write-Warning -Message "VM: $v is invalid or was not found!"
94 }
95 }
96 }
97}
In the following example, an attempt is being made to start the VM's named DC01, SQL01, PC01, and
PC02. The VM's are being specified via parameter input. DC01 is connected to an internal virtual
switch, PC01 is set to Not Connected
on its network adapter, PC02 is set to a private virtual
switch, and SQL01 is set to an external virtual switch.
1. .\Start-MrVM.ps1
2Start-MrVM -VMName DC01, SQL01, PC01, PC02
Same network settings in the following example. This time DC01 is already running. The same computers are specified in this example except via pipeline input this time:
1'DC01', 'SQL01', 'PC01', 'PC02' | Start-MrVM
And this time, the Get-VM
cmdlet which is part of the Hyper-V PowerShell module is being used to
specify the VM's and the output of that cmdlet is being piped to my function.
1Get-VM -Name DC01, SQL01, PC01, PC02 | Start-MrVM -Verbose
Notice in the previous example, the verbose parameter was specified so you could see what VM's are attempting to be started.
µ