Automation

 View Only
Expand all | Collapse all

Move-VMThin Function (Powercli Thick to Thin svMotion)

Hosted201110141

Hosted201110141Aug 06, 2011 03:12 PM

Hosted201110141

Hosted201110141Aug 06, 2011 04:03 PM

  • 1.  Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:02 PM

    Hi everyone,

    I got this fuction from LucD in another forum post and modified it to attempt to convert a large number of VMs from thick to thin disks.  I seem to be getting an error on the first VM every time and the second seems to be working fine.  If someone could point out what I've done wrong I would appreciate it.

    Error:

    You cannot call a method on a null-valued expression.
    At C:\Users\xxx\Documents\xxx.ps1:33 char:31
    +             $vmView.RelocateVM <<<< ($spec, $null)
        + CategoryInfo          : InvalidOperation: (RelocateVM:String) [], RuntimeException
        + FullyQualifiedErrorId : InvokeMethodOnNull

    Script:

    $vmarray = @("TestVM1","TestVM2")
    $datastore = Get-Datastore | Sort FreeSpaceMB -Descending
        function Move-VMThin {
            PARAM(
                 [Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="Virtual Machine Objects to Migrate")]
                 [ValidateNotNullOrEmpty()]
                    [System.String]$VM
                ,[Parameter(Mandatory=$true,HelpMessage="Destination Datastore")]
                 [ValidateNotNullOrEmpty()]
                    [System.String]$Datastore
            )
          
                Begin {
                #Nothing Necessary to process
                } #Begin
          
            Process {       
                #Prepare Migration info, uses .NET API to specify a transformation to thin disk
                $vmView = Get-View -ViewType VirtualMachine -Filter @{"Name" = "$VM"}
                $dsView = Get-View -ViewType Datastore -Filter @{"Name" = "$Datastore"}
              
                #Abort Migration if free space on destination datastore is less than 50GB
                if (($dsView.info.freespace / 1GB) -lt 50) {throw "Move-ThinVM ERROR: Destination Datastore $Datastore has less than 50GB of free space. This script requires at least 50GB of free space for safety. Please free up space or use the VMWare Client to perform this Migration"}
        
                #Prepare VM Relocation Specificatoin
                $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
                $spec.datastore =  $dsView.MoRef
                $spec.transform = "sparse"
              
                #Perform Migration
                $vmView.RelocateVM($spec, $null)
            } #Process
        }
    for ($i=0; $i -lt $vmarray.count; $i++)
    {
    $datastore
    $snapshot = Get-VM -Name $vmarray[$i] | Get-Snapshot
    if ($snapshot -eq $null)
    {
      $vmds = Get-VM -Name $vmarray[$i] | Get-Datastore
      if ($vmds -ne $datastore[0])
      {
       Move-VMThin -VM $vmarray[$i] -Datastore $datastore[0]
      }
      if ($vmds -eq $datastore[0])
      {
       Move-VMThin -VM $vmarray[$i] -Datastore $datastore[1]
      }
    }
    if ($snapshot -ne $null)
    {
      Write-Host $vmarray[$i]+"has a Snapshot" -ForegroundColor Red
    }
    }



  • 2.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:09 PM

    Could it be that the first VM has files on more than 1 datastore ?

    Does

    Get-VM -Name TestVM1 | Get-Datastore

    return more than 1 datastore ?



  • 3.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:12 PM

    LucD,

    No, it only has files on one datastore.



  • 4.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:39 PM

    Do your datastores have similar names.

    What I mean, the Get-View in the function uses a filter where it retrieves the datastore based on it's name.

    If you have datastores that start with the same characters, it can be that more than 1 object is returned.

    For example: the datastores are called "ds1" and "ds11".

    Get-View -ViewType Datastore -Filter @{"Name"="ds1"}

    will return both.



  • 5.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:50 PM

    LucD,

    Thanks for you quick responses.  I am testing this in my lab at the moment where all my datastores have radically different names.  When I am able to get this error worked out and I move the script into production the datastores will all have similar names.  I think I have midigated this issue with the following commands.

    $datastore = Get-Datastore | Sort FreeSpaceMB -Descending
    Move-VMThin -VM $vmarray[$i] -Datastore $datastore[0] or Move-VMThin -VM $vmarray[$i] -Datastore $datastore[1]

    I don't think this should be an issue there either since all datastores end in a unique 2 digit number.

    Perhaps I am just using the funciton incorrectly, but then I don't understand why some VMs error out and others don't.



  • 6.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 03:57 PM

    I may have found the issue.  It seems I have duplicated a variable that is used in the function.  I have modified my script and I am testing it out now.



  • 7.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:03 PM

    Nevermind, no change.



  • 8.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:08 PM

    There must be something failing with the Get-View cmdlet.

    Can you dump the $dsView variable to the console ?

    Just add a line in the function like this

    ...

    $dsView = Get-View -ViewType Datastore -Filter @{"Name" = "$Datastore"}
    $dsView

    ...



  • 9.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:12 PM

    Info                : VMware.Vim.VmfsDatastoreInfo
    Summary             : VMware.Vim.DatastoreSummary
    Host                : {HostSystem-host-15602, HostSystem-host-17697, HostSystem-host-18280, HostSystem-host-18661...}
    Vm                  : {VirtualMachine-vm-15756, VirtualMachine-vm-15758, VirtualMachine-vm-18849, VirtualMachine-vm-19074...}
    Browser             : HostDatastoreBrowser-datastoreBrowser-datastore-15643
    Capability          : VMware.Vim.DatastoreCapability
    IormConfiguration   : VMware.Vim.StorageIORMInfo
    Parent              : Folder-group-s5
    CustomValue         : {}
    OverallStatus       : green
    ConfigStatus        : gray
    ConfigIssue         : {}
    EffectiveRole       : {-1}
    Permission          : {}
    Name                : xxx
    DisabledMethod      : {}
    RecentTask          : {}
    DeclaredAlarmState  : {alarm-41.datastore-15643, alarm-51.datastore-15643, alarm-9.datastore-15643}
    TriggeredAlarmState : {}
    AlarmActionsEnabled : True
    Tag                 : {}
    Value               : {}
    AvailableField      : {}
    MoRef               : Datastore-datastore-15643
    Client              : VMware.Vim.VimClient

    You cannot call a method on a null-valued expression.
    At C:\Users\xxx\Documents\xxx.ps1:32 char:31
    +             $vmView.RelocateVM <<<< ($spec, $null)
        + CategoryInfo          : InvalidOperation: (RelocateVM:String) [], RuntimeException
        + FullyQualifiedErrorId : InvokeMethodOnNull



  • 10.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:15 PM

    The issue seems to fall on $vmView rather than $dsView.  It appears the $vmView is empty for the VM I'm trying to move.  Any suggestions?



  • 11.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:29 PM

    I changed:

    $vmView = Get-View -ViewType VirtualMachine -Filter @{"Name" = "$VM"}

    to
    $vmView = Get-VM -Name "$VM" | Get-View

    It now appears to work.  I'm not sure what the difference is though.



  • 12.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 04:51 PM

    LucD,

    Thanks for pointing me in the right direction.  I purchased your book the other week and I have found it to be a valuable asset.

    Hosted



  • 13.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 06:06 PM

    Thanks, and great you find the book useful.

    Does this return anyhting at all ?

    Get-View -ViewType VirtualMachine -Filter @{"Name" = "TestVM1"}


  • 14.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 06:13 PM

    Get-View -ViewType VirtualMachine -Filter @{"Name" = "TestVM1"} returns nothing.



  • 15.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 06:16 PM

    And this does return the guest ?

    Get-VM -Name "TestVM1"


  • 16.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 06, 2011 06:21 PM

    Yes,

    Get-VM -Name "TestVM1"

    and

    Get-VM -Name "TestVM1" | get-view

    both work, but

    Get-View -ViewType VirtualMachine -Filter @{"Name" = "TestVM1"}

    does not.



  • 17.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 01:07 AM

    Very strange, can't reproduce this.

    For the fun of it, can you try

    Get-View -ViewType VirtualMachine -Filter @{"Name"=(Get-VM TestVM1).Name}


  • 18.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 01:31 AM

    I agree, it is strange.  Nothing is returned from that command either.



  • 19.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 01:35 AM

    If it's not confidential, can you include the output from

    Get-VM TestVM1 | Get-View


  • 20.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)
    Best Answer

    Posted Aug 07, 2011 02:39 PM

    The mystery is solved, the actual name of the VM contained some RegEx meta-characters.

    When these were escaped with the back-slash, the Get-View filter worked without a problem.

    For example, the VM name contains parenthesis, which are RegEx grouping characters. This

    $vmName = "TestVM(1)"

    Get-View -ViewType VirtualMachine -Filter @{"Name"=$vmName}

    will not return anything.

    But

    $vmName = "TestVM\(1\)"

    Get-View -ViewType VirtualMachine -Filter @{"Name"=$vmName}

    will.

    Advice: avoid RegEx meta-characters in the name of your VMs.



  • 21.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 04:34 PM

    LucD,

    Thank for all your help.

    One thing I find interesting is that the Get-VM cmdlet seems to be able to handle RegEx data in the virtual machine name.  So, if you needed a script that was more flexible, but less efficient you could use the following.

    $vmName = "TestVM(1)"

    Get-VM $vmName | Get-View

    I realize that Get-View -ViewType VirtualMachine -Filter @{"Name"=$vmName} seems to be the almost universally excepted way to perform this operation, and in my quick testing this command took roughly 1 second less to complete.  However, when taken in the context of a script whose primary function is to storage vMotion one or many virtual machines, the difference becomes negligible.

    If the script's primary function is to gather information though, I could see how the efficient command would be highly preferred over the flexible command since running the commands 1000 times would yield a 16.6 minute difference.  A time difference that is hardly negligible.

    Hosted



  • 22.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 06:49 PM

    The Get-VM cmdlet offers very limited name masking capabilities compared to the Get-View filter.

    And the Get-View cmdlet is, as you noticed, way faster in a medium to big environment. When you also use the Property parameter it is even faster.

    In the end it isn't too difficult to copy with all the RegEx meta-characters when needed.

    The Replace method is one way how to tackle these meta-characters.



  • 23.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 07, 2011 09:40 PM

    Now I'm interested in being able to remove all RegEx metacharacters from a given string.  Is there a simple catch-all or would every string have to be something like:

    Get-View -ViewType VirtualMachine -Filter @{"Name"="$vmName".Replace('(','\(').Replace(')','\)').Replace(']','\]').Replace('[','\[').Replace('^','\^').Replace('\','\\').Replace('.','\.').Replace('|','\|').Replace('?','\?').Replace('+','\+').Replace('*','\*').Replace('$','\$')}

    Did I even get them all?  I knew I should have taken a programming class in college.

    Hosted



  • 24.  RE: Move-VMThin Function (Powercli Thick to Thin svMotion)

    Posted Aug 08, 2011 11:31 AM

    Turns out there is a much more elegant and simpler solution.

    The RegEx object has a method, called Escape, that does it all for you.

    Get-View -ViewType VirtualMachine -Filter @{"Name"=[regex]::Escape($vmName)}
    

    I'm going to start using this everytime I use a Get-View with a filter that uses a string :smileyhappy: