Home > Powershell > Powershell: Importing Hyper-V VM’s

Powershell: Importing Hyper-V VM’s

In my previous post Creating Hyper-V Symolic Links using Powershell I created a small but useful function called Create-SymbolicLinks which was used to execute one or more .bat files that created symbolic links to base or middle tier VHD’s as part of the initial classroom VM setup.  Once this was completed the next step was to import the VM’s and of course what better way to automate this then to use Powershell.

The first task at hand is to download and import the Hyper-V module from Codeplex.  There are 2 versions of this module available to download, with the latest version being R2 SP1.  Once downloaded I then place it into the directory where I will be running the script\function so that it can be copied to the appropriate Modules directory on the server.   Both the module path and name are defined in the Param statement as follows, along with the path to the VM’s.

 Param (
  $ModulePath = ($env:psmodulePath -split ";")[1],
  $ModuleName = "HyperV",
  $path = "C:\Program Files\Microsoft Learning\6419\Drives\"
  )

The code to copy the HyperV module and import it is:

 #Copy the HyperV module if it doesn't already exist
 if(!((Dir $ModulePath) -match $ModuleName)) {
  Copy-Item .\$ModuleName $ModulePath -Recurse
  }
 #Import the HyperV module if not already imported
 if(!(Get-Module | ?{$_.Name -like $ModuleName})) {
   Import-Module $ModuleName
  }

Now the real work begins.  I need to determine what VM’s have already imported into Hyper-V to make sure we don’t 1) do more work then is necessary and 2) don’t try overwriting any previously imported VMs.  Doing this involves using Get-VM and extracting just he name property ( or in this case the ElementName property) and putting those results into an array called $ActiveVMs.
In order to get a list of the VM’s I need to import I run a Get-ChildItem $Path and extract just the Name property and put the results into an array called $VMsToImport.

 #Create array to contain active VM's
 $ActiveVMs = Get-VM | Foreach{$_.ElementName}
 #Create array to contain VM's to be imported
 $VMsToImport = (Get-ChildItem $path) | Foreach{ $_.Name }

Now comes the interesting part.  How to do a comparision of the two arrays and determine if any VM names overlap.  This seemed like a perfect opportunity to use a regular expression.  I remember reading an article on the Scripting Guys called “Speed Up Array Comparisions in Powershell with a Runtime Regex” where the author discussed the benefits of using the -Match operator with a regular expression  instead of the -Contains comparison operator.  Needless to say using a regular expression was way faster…10x faster and since Powershell is all about automation and efficiency , creating a regex seems like the way to go.

 [regex]$ActiveVMs_Regex = '(?i)^('+(($ActiveVMs |
        Foreach {[regex]::Escape($_)})-join "|" )+')$'

The only thing left now was to run the -Match comparison and import the VM’s  using Import-VM.   I also needed to use Start-Sleep 5 because during my initial tests ( and there were many of them ) some VM’s weren’t imported.  It was random and not consistent but after having the script pause before each import provided just the rate of success I was looking for.   Powershell you rock!!!

            
 #Import the VMs            
 $VMsToImport -notmatch $ActiveVMs_Regex |             
        Foreach{ Import-VM (Join-Path $path $_ )             
        Start-Sleep 5            
  }

Here is the complete function..

Function Import-VMs {            

 Param (
  $ModulePath = ($env:psmodulePath -split ";")[1],
  $ModuleName = "HyperV",
  $path = "C:\Program Files\Microsoft Learning\6419\Drives\"
     )            
 #Copy the HyperV module if it doesn't already exist
 if(!((Dir $ModulePath) -match $ModuleName)) {
  Copy-Item .\$ModuleName $ModulePath -Recurse
     }             

 #Import the HyperV module if not already imported
 if(!(Get-Module | Where{$_.Name -like $ModuleName})) {
   Import-Module $ModuleName
     }            

 #Create array to contain active VM's
 $ActiveVMs = Get-VM | Foreach{$_.ElementName}            

 #Create array to contain VM's to be imported
 $VMsToImport = ( Get-ChildItem $path ) | Foreach{$_.Name}
 [regex]$ActiveVMs_Regex = '(?i)^('+(($ActiveVMs |
        Foreach {[regex]::Escape($_)})-join "|" )+')$'            

 #Import the VMs            
 $VMsToImport -notmatch $ActiveVMs_Regex |             
        Foreach{ Import-VM ( Join-Path $path $_ )             
        Start-Sleep 5            
     }
}#End Function
Advertisements
Categories: Powershell Tags: ,
  1. January 21, 2013 at 6:27 am

    “Powershell: Importing Hyper-V VMs The Tech
    Cafe..” ended up being a quite excellent blog post,
    . Keep publishing and I’ll continue viewing! Many thanks -Dirk

  2. January 24, 2013 at 12:42 pm

    I believe this amazing blog , “Powershell: Importing Hyper-V VMs
    The Tech Cafe..”, incredibly interesting and the blog post ended
    up being a good read. Thank you,Boyd

  3. May 13, 2013 at 11:04 pm

    I must thank you for the efforts you’ve put in penning this website. I am hoping to see the same high-grade blog posts by you in the future as well. In fact, your creative writing abilities has encouraged me to get my own site now 😉

  4. July 6, 2013 at 1:22 pm

    Everything is very open with a clear clarification of the issues.

    It was truly informative. Your website is very useful.
    Thanks for sharing!

  5. July 27, 2013 at 2:45 pm

    I have fun with, cause I discovered just what I used
    to be having a look for. You’ve ended my four day lengthy hunt! God Bless you man. Have a nice day. Bye

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: