Taking Control of VM Sprawl (Part 14)

If you would like to read the other parts in this article series please go to:

Introduction

Welcome back! In my previous article, I created a massive script that tracks virtual machine creation and deletion trends for an entire year. In this article, I want to build onto that script by showing you how to track virtual machine creation and deletion trends across your entire organization.

Building a Loop Structure

The easiest way to analyze the event logs from across an entire organization is to build a loop into the script body. This is surprisingly easy to do. To show you what I mean, take a look at the block of code below:

#Script Body

$Servers = @(“Hyper-V-1”, “Hyper-V-2”, “Hyper-V-3”, “Hyper-V-4”, “Prod1”, “Prod2”)

                ForEach ($Server in $Servers) {

                $ServerName = $Server

Get-MyData $ServerName

                }

This block of code doesn’t really do anything by itself, and has nothing to do with VM sprawl (at least not yet). I wanted to keep things simple and show you how the loop works. After that, we can adapt the loop to our script.

The first line of code is nothing more than a comment indicating that this is the script body. The second line is where things get interesting. In this line of code, we are creating a variable called $Servers. This variable will act as an array, and store the names of all of the Hyper-V servers that I want to analyze. In this particular case, I have hard coded the server names, and six servers are listed within the array.

The third line of code is where the loop begins. This line of code establishes a loop in which Windows will look at each server ($server) in the list of servers ($servers). Notice that two distinct variables are used – $server and $servers. $server will store the name of the server that is currently being analyzed, whereas $servers will store the entire list of servers. All of the loop actions are enclosed in braces {}.

There are two lines of code within the loop. The first of these lines assigns the name of the server that is currently being analyzed, to a variable named $ServerName. I did this because the name $SeverName makes it a little bit easier to keep track of the fact that the variable stores the name of one individual Hyper-V server.

The second line of code within the loop calls a PowerShell function named Get-MyData. This line passes the name of the server that is currently being analyzed, to the Get-MyData function. The Get-MyData function has not yet been written, but will contain the code that performs the actual analysis.

So let’s go ahead and build the Get-MyData function. If you think back to the previous article, you will recall that I wrote a massive PowerShell script that analyzes an entire year’s worth of event logs. It is this code that we will be placing into the function. However, some minor code modification will be required.

Rather than trying to create a huge, monolithic function right off the bat, let’s limit the analysis to looking at two months’ worth of data. Once we have everything working as intended, we can go back and analyze the rest of the months. So with that said, here is a script that examines two months worth of event log data for all of my servers:

Function Get-MyData($Server){

#Function to get VM log data information

 

Write-Host “The Current Server Name is ” -NoNewLine; Write-Host $Server

$MySession = New-PSSession -ComputerName $Server

Invoke-Command -Session $MySession -ScriptBlock {

 

#January 2015

 

$NumJanCreateEvents = ‘0’

$JanCreateEvents = ”

$NumJanDeleteEvents = ‘0’

$JanDeleteEvents = ”

$JanStartDate = ‘01/01/2016 12:00:00 AM’

$JanEndDate = ‘01/30/2016 11:59:59 PM’

$JanCreateEvents = Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$JanStartDate;EndTime=$JanEndDate} -ErrorAction ‘SilentlyContinue’

$NumJanCreateEvents = $JanCreateEvents.count

$JanDeleteEvents = Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$JanStartDate;EndTime=$JanEndDate} -ErrorAction ‘SilentlyContinue’

$NumJanDeleteEvents = $JanDeleteEvents.count

Write-Host “In January 2016, there were ” -NoNewLine; Write-Host $NumJanCreateEvents -NoNewLine; Write-Host ” New virtual machines created.”

Write-Host “In the same time period, there were ” -NoNewLine; Write-Host $NumJanDeleteEvents -NoNewLine; Write-Host ” virtual machines deleted.”

 

#February 2016

 

$NumFebCreateEvents = ‘0’

$FebCreateEvents = ”

$NumFebDeleteEvents = ‘0’

$FebDeleteEvents = ”

$FebStartDate = ‘02/01/2016 12:00:00 AM’

$FebEndDate = ‘02/29/2016 11:59:59 PM’

$FebCreateEvents = Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$FebStartDate;EndTime=$FebEndDate} -ErrorAction ‘SilentlyContinue’

$NumFebCreateEvents = $FebCreateEvents.count

$FebDeleteEvents = Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$FebStartDate;EndTime=$FebEndDate} -ErrorAction ‘SilentlyContinue’

$NumFebDeleteEvents = $FebDeleteEvents.count

Write-Host “In February 2016, there were ” -NoNewLine; Write-Host $NumFebCreateEvents -NoNewLine; Write-Host ” New virtual machines created.”

Write-Host “In the same time period, there were ” -NoNewLine; Write-Host $NumFebDeleteEvents -NoNewLine; Write-Host ” virtual machines deleted.”

Exit-PSSession

}

}

 

#Script Body

$Servers = @(“Hyper-V-1”, “Hyper-V-2”, “Hyper-V-4”, “Prod1”, “Prod2”)

                ForEach ($Server in $Servers) {

 

$ServerName = $Server

Get-MyData $ServerName

 

                }

This script can appear a bit overwhelming at first glance, but as you take a closer look, you will notice that we aren’t really doing much that is new. The script body is identical to what I walked you through a moment ago, and the code that analyzes the event logs is nearly identical to what I covered in the previous article. Here are the lines of code that you need to pay attention to:

Function Get-MyData($Server){

#Function to get VM log data information

 

Write-Host “The Current Server Name is ” -NoNewLine; Write-Host $Server

$MySession = New-PSSession -ComputerName $Server

Invoke-Command -Session $MySession -ScriptBlock {

 

#January 2016

 

$NumJanCreateEvents = ‘0’

$JanCreateEvents = ”

$NumJanDeleteEvents = ‘0’

$JanDeleteEvents = ”

The first line of code simply declares the function and tells PowerShell that the function is going to be accepting the name of a server. The second line is simply a comment.

The third line of the function is designed to display the name of the server that is currently being analyzed. This line can be helpful for diagnostic purposes, because you can use it to confirm that the server name is being passed to the function correctly.

The next two lines are designed to establish a remote session to the server that is being analyzed. We are creating a session called $MySession and establishing that session on the Hyper-V server whose name has been passed to the function. Next, we are invoking a command on the remote Hyper-V machine. Notice the use of the ScriptBlock parameter. This parameter allows us to run all of the code remaining in the function against the remote server.

The last thing that I wanted to show you was that I added a few lines of code after the January 2016 comment. These lines of code initialize my variables. In all honesty, we may not even need these lines. I wrote them as a precaution, just to make sure that we didn’t accidentally carry over any data from a previously analyzed server.

You can see the output from this script in Figure A. As you can see in the figure, the script breaks down virtual machine creation and deletion on a per host server basis for January and February of 2016.

Image
Figure A: The script now analyzes multiple servers.

Conclusion

There are three more things that we need to do in order to complete this project. First, we need to add a bit of code to tally the running total of VM creation and deletion events across all of the servers. Second, we need to add in the code for analyzing the rest of the year. Finally, we need to dump the trend data into a chart. All of this sounds like a lot of work, but we have already finished the difficult part. It will take relatively little effort to complete the script.

If you would like to read the other parts in this article series please go to:

About The Author

Leave a Comment

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top