Wednesday, November 28, 2012

Backup-VMX & Add-VMXOption

A little while ago a student asked me to write a little script that would update all the VMs .vmx files to add in a few options (I think it was copy/paste stuff), of course pretty easy to knock up a simple little script to do that specific task, but then I thought there would be a bit of value in functioning it up. Of course I have re-invented the wheel: 

I also wanted a way to backup the vmx files before I started messing with them, and of course that became a bit bigger than I initially thought, and 'Backup-VMX'was born. 

 

Backup-VMX will do what it says, backup a VM's VMX file. It locates the location of the VMX file, and copies it to a specified location, which could be a local file, datastore or next to the existing VMX. It accepts pipeline input, so you could:
get-vm |  backup-vmx
to create a backup of every vmx file :) It wont overwrite by default, but you can set the flag to do so.

Add-VMXOption will allow you to add or update an option in a vmx file. It is a simple function that will add a single option/value to the vmx of a VM. You could easily read a csv and the loop through the csv entries to do multiple options.




Add-VMXOption

###########################################################################
#
# NAME: Add-VMXOption
#
# AUTHOR:  winter 
#
# COMMENT: 
#
# VERSION HISTORY:
# 0.1 19/10/2012 - draft
# 1.0 24/10/2012 - ready for prime time :)
#
###########################################################################

<#
.SYNOPSIS
Adds an option to a .vmx file

.DESCRIPTION
your detailed description

.PARAMETER VM
the vm you want to update
.PARAMETER VMXOption
the name of the .vmx parameter you want to add
.PARAMETER VMXValue
the value for the .vmx parameter you are adding
.PARAMETER Overwrite
allows you to overwrite an existing .vmx option (default $false)
.EXAMPLE
PS C:\tmp> get-vm delete* | Add-VMXOption -VMXOption isolation.tools.copy.disable -VMXValue false
Updating DeleteMEPls's .vmx file

Description
-----------
Adds an option to the .vmx file.

.EXAMPLE
PS C:\tmp> Add-VMXOption -VM DeleteMEPLs -VMXOption isolation.tools.copy.disable -VMXValue false
WARNING: VMX option found to already exist
Option: isolation.tools.copy.disable
Current Value: true

PS C:\tmp> get-vm delete* | Add-VMXOption -VMXOption isolation.tools.copy.disable -VMXValue true -overwrite:$true 
WARNING: VMX option found to already exist
Option: isolation.tools.copy.disable
Current Value: false
WARNING: Overwrite flag found. Updating existing value.....
Updating DeleteMEPls's .vmx file

Description
-----------
 
Updates an existing option. 1st it does not overwrite, but then we add the -overwrite flag, and -backup to copy the .vmx before modification

.NOTES
probably should be...
.LINK
about_functions_advanced
#>

function Add-VMXOption {
 param(
 [Parameter(ValueFromPipeline=$true,Mandatory=$true)]$VM,
 [Parameter(Mandatory=$true)]$VMXOption,
 [Parameter(Mandatory=$true)]$VMXValue,
 $overwrite = $false
 )
 
 Process {
  $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
  $optionvalue = New-Object VMware.Vim.optionvalue
  $optionvalue.Key=$VMXOption
  $optionvalue.Value=$VMXValue
  $vmConfigSpec.extraconfig += $optionvalue

  $VMView = get-vm $VM | Get-View 
  
  $AllVMXOptions = $VMView.Config.ExtraConfig
  foreach ($Option in $AllVMXOptions){
   if ($Option.Key -eq $VMXOption){
    Write-Warning "VMX option found to already exist"
    Write-host  Option: $VMXOption
    write-host Current Value: $Option.Value
    $ValueFound = $true
   }
  }
  if ($ValueFound -and $overwrite -eq $true){
    Write-Warning "Overwrite flag found. Updating existing value....."
    Write-Host Updating ($VMView.Name).insert($VMView.Name.length,"'s") .vmx file
    $VMView.ReconfigVM($vmConfigSpec)
   }
  if (!$ValueFound){
   Write-Host Updating ($VMView.Name).insert($VMView.Name.length,"'s") .vmx file
   $VMView.ReconfigVM($vmConfigSpec)
  }
 }
}

Backup-VMX

###########################################################################
#
# NAME: Backup-VMX
#
# AUTHOR:  winter 
#
# COMMENT: 
# TODO: 
# Allow the destination to be a VMFS Folder (this isnt a big deal as it is harder to set as a target)
#
# VERSION HISTORY:
# 0.1 19/10/2012 - draft
# 1.0 24/10/2012 - ready for prime time :)
#
#
###########################################################################

<#
    .Synopsis
    Backups up a VM (or VMs) .vmx file
 .Description
 Backup-VMX will backup a VM's .vmx file to the specified location.
 The default location is next to the VMs existing .vmx file (which is not necessarily the home dir btw)
    .Parameter  VM
    The VM (or VMs) you want to update
    .Parameter Destination
 The Destination location to copy the .vmx to
 Valid targets are, Datastore, Local Folders/Files & Default
 Default location is the existing location of the vmx. If the default is used, ".bkup" will be appended to the file name.
 .Parameter Overwrite
 Allows you to overwrite the destination, if it exists. Default = $false
 .Example
 PS C:\> backup-vmx -vm deletemepls
 Copied file vmstores:\my.vc.local@443\MyDataCenter\MyDatastore\DeleteMEPls\DeleteMEPls.vmx to vmstores:\my.vc.local@443\MyDataCenter\MyDatastore\DeleteMEPls\DeleteMEPls.vmx.bkup
 
 PS C:\> backup-vmx -vm deletemepls
 WARNING: Destination File exists...
 
 Description
 -----------
 Here we just grab the .vmx of the vm 'deletemepls' and backup it to the default location. We then try to do it again and it doesnt, as the file exists.
 
 .Example
 PS C:\> get-vm test* | Backup-VMX -Destination c:\tmp -Overwrite:$true
 WARNING: Destination File exists...
 Copied file vmstores:\my.vc.local@443\MyDataCenter\MyDatastore\Test1\Test1.vmx to c:\tmp
 WARNING: Destination File exists...
 Copied file vmstores:\my.vc.local@443\MyDataCenter\MyNFSDatastore\Test2\Test2.vmx to c:\tmp
 
 Description
 -----------
 Here we grab 2 VMs (from the preceding  get-vm cmdlet) and backup the .vmx files to c:\tmp and overwrite 
 
 .Example
 PS C:\tools> Get-VM David | Backup-VMX -Destination (Get-Datastore local-b) -Overwrite:$true
 WARNING: Destination File exists...
 Copied file vmstores:\my.vc.local@443\MyDataCenter\Local-B\David\David.vmx to \my.vc.local@443\MyDataCenter\Local-B
    
 Description
 -----------
 Here we copy the .vmx to the root of the datastore returned from 'Get-Datastore local-b'
 
 .Notes
    Probably should be....
 make blog.shonkyholdings.com your home page to drive my traffic stats ^_*
    .Link 
 http://blog.shonkyholdings.com

#>

function Backup-VMX {
 param(
 [Parameter(ValueFromPipeline=$true,Mandatory=$true)]$VM,
 [ValidateSet($true,$false)]$Overwrite = $false,
 $Destination = "default"
 )
 
 PROCESS {
 
  $VMView = Get-VM $VM | Get-View
  
  $SourceVMXLong = $VMView.Summary.Config.VmPathName
  $SourceVMXShort = $SourceVMXLong.Substring($SourceVMXLong.IndexOf("/")+1)
  
  $VMXDatastore = get-datastore ($SourceVMXLong.Substring(1,$SourceVMXLong.IndexOf("]")-1))
  
  $SourceVMXLongPath = $VMXDatastore.DatastoreBrowserPath.Insert($VMXDatastore.DatastoreBrowserPath.Length,"\")
  $SourceVMXLongPath = $SourceVMXLongPath.Insert($SourceVMXLongPath.Length,$SourceVMXLong.Substring($SourceVMXLong.IndexOf("]")+2).Replace("/","\"))
  
  if ($Destination -eq "default"){
   $Destination = $SourceVMXLongPath.Insert($SourceVMXLongPath.Length,".bkup")
  }
  
  $DestinationType = $Destination.GetType().Name
  
  switch ($DestinationType){
   "String" {
    if ((Test-Path $Destination) -eq $true){
     if ((Get-Item $Destination).GetType().Name -eq "DatastoreFolderImpl"){
      $DestinationType = "DatastoreFolderImpl"
      if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){
      Write-Warning "Destination File for $VM exists..."
      $DestinationExists = $true
      }
     }
     elseif ((Get-Item $Destination).GetType().Name -eq "DatastoreFileImpl"){
      $DestinationType = "DatastoreFileImpl"
      Write-Warning "Destination File for $VM exists..."
      $DestinationExists = $true
     }
    }
     ; continue
   }
   "DirectoryInfo" {
    if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    ; break
   }
   "FileInfo" {
    if ((Test-Path $Destination) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    ; break
   }
   "DatastoreFileImpl" {
    if ((Test-Path $Destination) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    ; break
   }
   "DatastoreFolderImpl" {
    if ((Test-Path $Destination.Insert($Destination.Length,"\").Insert(($Destination.Length)+1,$SourceVMXShort)) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    ; break
   }
   "NasDatastoreImpl" {
    New-PSDrive -Name "DestMount" -Root \ -PSProvider VimDatastore -Datastore $Destination | Out-Null
    if ((Test-Path ("DestMount:").insert(10,"\").Insert(11,$SourceVMXShort)) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    $Destination = ("DestMount:").insert(10,"\")
    ; break
   }
   "VMFSDatastoreImpl" {
    New-PSDrive -Name "DestMount" -Root \ -PSProvider VimDatastore -Datastore $Destination | Out-Null
    if ((Test-Path ("DestMount:").insert(10,"\").Insert(11,$SourceVMXShort)) -eq $true){
     Write-Warning "Destination File for $VM exists..."
     $DestinationExists = $true
    }
    $Destination = ("DestMount:").insert(10,"\")
    ; break
   }
  }
    
  if ($Overwrite -eq $true -or $DestinationExists -ne $true){
   Copy-DatastoreItem -Item $SourceVMXLongPath -Destination $Destination
   if ($? -eq $true){
    if ($DestinationType -eq "VMFSDatastoreImpl" -or $DestinationType -eq "NasDatastoreImpl" ){
     $DestinationRoot = (Get-PSDrive DestMount).Root
     Write-Host "Copied file $SourceVMXLongPath to $DestinationRoot "
    }
    else {
     Write-Host "Copied file $SourceVMXLongPath to $Destination "
    }
   }
  }
  if (Test-Path DestMount:){
   Remove-PSDrive -Name DestMount -Force:$true
  }
 }
}

Enjoy :)

0 comments:

Labels

blogs I read

Authors

My photo

Enjoys spending time in layer 6 & 7. Passionate about delivering quality education.
Based in Sydney.

certz