Blaze4up
Enthusiast
Enthusiast

Move only config files of a vm

Jump to solution

Hi all,

We are in this big migration of moving 1000+ vms over 100+ datastores in total 1500 TB

And i'm automating it with PowerCLI.

So, we have a lot of vms and with multiple disks and not all of them needed to be moved.

I split the migration up in two, move the config files and move the disk.

This because it can happen that the config file and the disks are not on the same datastore for some reason.

I found this really cool script from LucD


$spec
= New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec
.datastore = (Get-Datastore -Name $Des_datastore).Extensiondata.MoRef
$comp_disks | %{
   
$disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
    $disk.diskId = $_.Extensiondata.Key
   
$disk.datastore = $_.Extensiondata.Backing.Datastore
   
$spec.disk += $disk
}

$ vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")

But apparently i'm doing something wrong because it's moving the vm entirely instead of only the config file.

Can anyone help me ?

0 Kudos
1 Solution

Accepted Solutions
Blaze4up
Enthusiast
Enthusiast

Hi Luc,

Thanks for the script, but also not what i'm looking for.

But it gave me inspiration, and now I have fixed it!

The vmx file and disks are moved separately, so for the vms how has a vmx file on a different datastore then the disks, it will leave it that way.

When I start the script I use the start-transscript cmdlet for the logging, that's why there is so random a 'date' in the script.

This works perfect!

# Variables

$source_datastore = Get-Datastore -Name lsi07

$destination_datastore = Get-Datastore -Name lsi06

$source_datastore_name = "lsi07"

$vms  = Get-Datastore -Name $source_datastore | get-vm | where {$_.name -like "test*"}

# Loop for the script

date

Foreach ($vm in $vms){

    # Locate the vmx file, if on source datastore move to another datastore

    if ($vm.ExtensionData.Config.Files.VmPathName -like "*$source_datastore_name*"){

        Write-Host "vm $vm has config file on $source_datastore, move config file"

        $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

        $spec.datastore = $destination_datastore.Extensiondata.MoRef

      

        Get-HardDisk -VM $vm | %{

            if($_.Name -ne 'Hard disk *'){

                $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator

                $disk.diskId = $_.Extensiondata.Key

                $disk.datastore = $_.Extensiondata.Backing.Datastore

                $spec.disk += $disk

            }

        }

        $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") | out-null

        Write-host "Config file moved" 

    }

    else {write-host "vm $vm has no config file on $source_datastore"}

  

     # move the disk(s) off the source datastore to the destination datastore

     $count = (get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*$source_datastore_name*" }).count

     if ($count -gt 0){

         $comp_disks = get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*$source_datastore_name*" }

         Write-Host "Move $count disks off $source_datastore for vm $vm"

         Move-hardDisk -HardDisk $comp_disks -Datastore $destination_datastore -Confirm:$false |Out-Null

         Write-Host "Disks are moved to $destination_datastore"

        

     }

    else {write-host "There are no disks on $source_datastore "

         }

       sleep 5

       $view_vm= get-view –viewtype VirtualMachine –filter @{“Name”="$vm”}

      

       $view_vm.Config.Files.VmPathName

       $view_vm.Layout.Disk.Diskfile

          

           Write-Host "VM $vm done"

           sleep 10

}

View solution in original post

0 Kudos
8 Replies
LucD
Leadership
Leadership

You're missing the creation of the content of the $comp_disks variable.

The following will move all VM files, except the harddisks, to a target datastore.

$vmName = 'MyVM'

$destDatastore = 'MyDS'

$vm = Get-VM -Name $vmName

$hd = Get-HardDisk -VM $vm

$destDS = Get-Datastore -Name $destDatastore

$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

$spec.datastore = $destDS.Extensiondata.MoRef

$hd | %{

    $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator

    $disk.diskId = $_.Extensiondata.Key

    $disk.datastore = $_.Extensiondata.Backing.Datastore

    $spec.disk += $disk

}

$vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Blaze4up
Enthusiast
Enthusiast

Hi Luc,

Thanks for your quick reaction!

This is the complete script I used :

# Variables

$source_datastore = Get-Datastore -Name lsi06

$destination_datastore =Get-Datastore -Name lsi02

$vms  = Get-Datastore -Name $source_datastore | get-vm | where {$_.name -like "test*"}

$date = date

# functions

Function Get-VMConfigFile {

    [CmdletBinding()]

    param (

        [Parameter(

            Mandatory=$true,

            ValueFromPipeline=$true,

            ValueFromPipelineByPropertyName=$true)]

            [String[]]$VMName

    )

Get-VM $VMName | select Name,@{E={$_.ExtensionData.Config.Files.VmPathName};L="VMPath"}

}

# Loop for the script

Foreach ($vm in $vms){

# main

# Count disks and decide of the vm will be moved in total or only disks or config file

$comp_disks = get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*lsi06*" }

$count = (get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*lsi06*" }).count

date

    # Loctae the vmx file, if on compellent move to another datastore

    $vm_conf = Get-VMConfigFile $vm

    if ($vm_conf.VMPath -like "*lsi06*"){

  

    Write-host "vm $vm has config file on $source_datastore, move config file"

   $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

   $spec.datastore = (Get-Datastore -Name $destination_datastore).Extensiondata.MoRef

    $comp_disks | foreach {

        $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator

        $disk.diskId = $_.Extensiondata.Key

        $disk.datastore = $_.Extensiondata.Backing.Datastore

        $spec.disk += $disk

        }

    $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") #| out-null

    Write-host "Config file moved"   

    }

    else {write-host "vm $vm has no config file on $source_datastore"}

   

     # move the disk(s) off the compellent to the destination datastore

     Write-Host "Move $count disks off compellent for vm $vm"

     Move-hardDisk -HardDisk $comp_disks -Datastore $destination_datastore -Confirm:$false

     Write-Host "VM $vm done"

0 Kudos
LucD
Leadership
Leadership

It depends what exactly you want to move:

  • all the VM's files except for all the harddisks
  • all the VM's files except some of the harddisks

The script you have seems to

  • move all the VM's fles for VMs, that are on datastore lsi06 to datastore lsi02
  • exclude the harddisks that are on datastore lsi06.

Is that what you want to do?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Blaze4up
Enthusiast
Enthusiast

Hi Luc,

I only want to move : all the VM's files except for all the harddisks

and later on move the harddisk with the move-harddisk cmdlet

0 Kudos
LucD
Leadership
Leadership

My 1st answer moves the VM without moving the harddisks.

Not sure what you are missing?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Blaze4up
Enthusiast
Enthusiast

well, when I run the full script I have posted, the vm is moved completely.

We have vms like :

Config (vmx) files : datastore a

disk 1                   : datastore a

disk 2                   : datastore b              

disk 3                   : datastore c

I only want to move the config file (vmx and other files) and disk 1 of datastore a

The other disks of the vm need to left on the other datastores

I have run the script in parts and every part is doing it right except the part that moved only the config file (vmx )

I guess I'm doing something wrong there

0 Kudos
LucD
Leadership
Leadership

Try with this, it will move all the VM's config files and Hard disk 1 to the destination datastore.

All other harddisks should stay where they are.

# Variables

$source_datastore = Get-Datastore -Name lsi06

$destination_datastore = Get-Datastore -Name lsi02

$vms  = Get-VM -Datastore | where {$_.name -like "test*"}

$date = Get-Date

# Loop for the script

Foreach ($vm in $vms){

    # Locate the vmx file, if on compellent move to another datastore

    if ($vm.ExtensionData.Config.Files.VmPathName -like "*lsi06*"){

        Write-Host "vm $vm has config file on $source_datastore, move config file"

        $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

        $spec.datastore = $destination_datastore.Extensiondata.MoRef

       

        Get-HardDisk -VM $vm | %{

            if($_.Name -ne 'Hard disk 1'){

                $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator

                $disk.diskId = $_.Extensiondata.Key

                $disk.datastore = $_.Extensiondata.Backing.Datastore

                $spec.disk += $disk

            }

        }

        $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") #| out-null

        Write-host "Config file moved"  

    }

    else {write-host "vm $vm has no config file on $source_datastore"}

    Write-Host "VM $vm done"

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Blaze4up
Enthusiast
Enthusiast

Hi Luc,

Thanks for the script, but also not what i'm looking for.

But it gave me inspiration, and now I have fixed it!

The vmx file and disks are moved separately, so for the vms how has a vmx file on a different datastore then the disks, it will leave it that way.

When I start the script I use the start-transscript cmdlet for the logging, that's why there is so random a 'date' in the script.

This works perfect!

# Variables

$source_datastore = Get-Datastore -Name lsi07

$destination_datastore = Get-Datastore -Name lsi06

$source_datastore_name = "lsi07"

$vms  = Get-Datastore -Name $source_datastore | get-vm | where {$_.name -like "test*"}

# Loop for the script

date

Foreach ($vm in $vms){

    # Locate the vmx file, if on source datastore move to another datastore

    if ($vm.ExtensionData.Config.Files.VmPathName -like "*$source_datastore_name*"){

        Write-Host "vm $vm has config file on $source_datastore, move config file"

        $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

        $spec.datastore = $destination_datastore.Extensiondata.MoRef

      

        Get-HardDisk -VM $vm | %{

            if($_.Name -ne 'Hard disk *'){

                $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator

                $disk.diskId = $_.Extensiondata.Key

                $disk.datastore = $_.Extensiondata.Backing.Datastore

                $spec.disk += $disk

            }

        }

        $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") | out-null

        Write-host "Config file moved" 

    }

    else {write-host "vm $vm has no config file on $source_datastore"}

  

     # move the disk(s) off the source datastore to the destination datastore

     $count = (get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*$source_datastore_name*" }).count

     if ($count -gt 0){

         $comp_disks = get-vm -Name $vm |Get-HardDisk | Where {$_.filename -like "*$source_datastore_name*" }

         Write-Host "Move $count disks off $source_datastore for vm $vm"

         Move-hardDisk -HardDisk $comp_disks -Datastore $destination_datastore -Confirm:$false |Out-Null

         Write-Host "Disks are moved to $destination_datastore"

        

     }

    else {write-host "There are no disks on $source_datastore "

         }

       sleep 5

       $view_vm= get-view –viewtype VirtualMachine –filter @{“Name”="$vm”}

      

       $view_vm.Config.Files.VmPathName

       $view_vm.Layout.Disk.Diskfile

          

           Write-Host "VM $vm done"

           sleep 10

}

View solution in original post

0 Kudos