• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 777
  • Last Modified:

VMWare ESXi - Linked clone, need to move parent to different datastore

Experts,

In all of my searching in dealing with Linked clones and moving them to different datastores, the writeups always involve moving the cloned machine.  I've been trying to see if the following is possible without hurting anything:

1.  Shut down all linked-clone VMs that use the parent disk in question
2.  Once everything is shut down, move the parent disk to an entirely different datastore
3.  Modify the linked VM's cfg to point to the updated parent location
          *This would mean that the child is on a completely different datastore than the parent
4.  Fire the linked clone VMs back up
5.  Take the rest of the month off

5 may be a bit too much, but if somebody has any information on whether or not it's even possible and safe to do the above items (1-4), I would be greatly appreciated.  This is in an effort to add some administrative/logical separation between datastore objects, and doing some general housekeeping on storage.

For the record, the only utility I'm using, is my VCenter appliance.  All of the linked clones were created using my home-grown script here:

//================================================================================
# *****************************************
# *** <DOMAIN> VM Clone Creation Script ***
# *****************************************

# ---------------------------------------------

# User Defined Variables
      $strVCenterHost = "<VC HOST>"
      $strOSDataStore = "iSCSI_VMFS_OS"
      $strSecondaryDataStore = "iSCSI_VMFS_Secondary"
      $strOSDataStoreVMFolder = "vm"
      $strWorkingDir = "C:\Temp\CreateVM\VMWare\LinkedClone\"

# ----------------------------------------------

# On Screen Menu
      Clear-Host
      Write-Host "*****************************************"
      Write-Host "*** <DOMAIN> VM Clone Creation Script ***"
      Write-Host "*****************************************"
      Write-Host ""
      $strVCenterHost = Read-Host "VCenter Server"
      $strUserName = Read-Host "Username that has access to create virtual machine"
      $strInputPassword = Read-Host -AsSecureString "Password for the above account"
      $strInputPassword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($strInputPassword)
      $strPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($strInputPassword)

      [Int]$intBaseChoice = 0
      While ($intBaseChoice -lt 1 -OR $intBaseChoice -gt 4) {
            Write-Host ""
            Write-Host "      1.  Server 2012 R2 Std Core"
            Write-Host "      2.  Server 2012 R2 Std Full"
            Write-Host "      3.  Ubuntu Server 14.04"
            Write-Host "      4.  Untangle NG Firewall 10.2"
            Write-Host ""
            [Int]$intBaseChoice = Read-Host "Please select the base VM"
      }
      #Valid nic options:  Unknown, e1000, Flexible, Vmxnet, EnhancedVmxnet, Vmxnet3
      Switch( $intBaseChoice ) {
            1 { $strBaseOption = "BaseLine_Server2k12_R2_Std_Core"
                  $strNicType = "Vmxnet3"
                  }
            2 { $strBaseOption = "BaseLine_Server2k12_R2_Std_Full"
                  $strNicType = "Vmxnet3"
                  }
            3 { $strBaseOption = "BaseLine_UbuntuServer_14.04"
                  $strNicType = "Vmxnet3"
                  }
            4 { $strBaseOption = "BaseLine_UntangleNGFirewall_10.2"
                  $strNicType = "e1000"
                  }
      }

      [Int]$intMemoryChoice = 0
      While ($intMemoryChoice -lt 1 -OR $intMemoryChoice -gt 7) {
            Write-Host ""
            Write-Host "      1.  256 Mb"
            Write-Host "      2.  512 Mb"
            Write-Host "      3.  1024 Mb"
            Write-Host "      4.  2048 Mb"
            Write-Host "      5.  4096 Mb"
            Write-Host "      6.  8192 Mb"
            Write-Host "      7.  16384 Mb"
            Write-Host ""
            [Int]$intMemoryChoice = Read-Host "Please select the memory amount"
      }
      Switch( $intMemoryChoice ) {
            1 { $strMemoryOption = "256" }
            2 { $strMemoryOption = "512" }
            3 { $strMemoryOption = "1024" }
            4 { $strMemoryOption = "2048" }
            5 { $strMemoryOption = "4096" }
            6 { $strMemoryOption = "8192" }
            7 { $strMemoryOption = "16384" }
      }

      [Int]$intProcChoice = 0
      While ($intProcChoice -lt 1 -OR $intProcChoice -gt 4) {
            Write-Host ""
            Write-Host "      1.  1 CPU"
            Write-Host "      2.  2 CPUs"
            Write-Host "      3.  4 CPUs"
            Write-Host "      4.  8 CPUs"
            Write-Host ""
            [Int]$intProcChoice = Read-Host "Please select the # of CPUs"
      }
      Switch( $intProcChoice ) {
            1 { $intProcOption = "1" }
            2 { $intProcOption = "2" }
            3 { $intProcOption = "4" }
            4 { $intProcOption = "8" }
      }

      [Int]$intNetworkChoice = 0
      While ($intNetworkChoice -lt 1 -OR $intNetworkChoice -gt 8) {
            Write-Host ""
            Write-Host "      1.  NET_10.0.0.0/23  Vlan 1"
            Write-Host "      2.  NET_10.0.2.0/23  Vlan 2"
            Write-Host "      3.  NET_10.0.4.0/23  Vlan 4"
            Write-Host "      4.  NET_10.0.6.0/23  Vlan 6"
            Write-Host "      5.  NET_10.0.8.0/23  Vlan 8"
            Write-Host "      6.  NET_10.0.10.0/23  Vlan 10"
            Write-Host "      7.  NET_10.0.12.0/23  Vlan 12"
            Write-Host "      8.  NET_10.0.14.0/23  Vlan 14"
            Write-Host ""
            [Int]$intNetworkChoice = Read-Host "Please select the network access for this machine"
      }
      $strMemoryMin = "256Mb"
      Switch( $intNetworkChoice ) {
            1 { $strNetworkOption = "NET_10.0.0.0/23  Vlan 1" }
            2 { $strNetworkOption = "NET_10.0.2.0/23  Vlan 2" }
            3 { $strNetworkOption = "NET_10.0.4.0/23  Vlan 4" }
            4 { $strNetworkOption = "NET_10.0.6.0/23  Vlan 6" }
            5 { $strNetworkOption = "NET_10.0.8.0/23  Vlan 8" }
            6 { $strNetworkOption = "NET_10.0.10.0/23  Vlan 10" }
            7 { $strNetworkOption = "NET_10.0.12.0/23  Vlan 12" }
            8 { $strNetworkOption = "NET_10.0.14.0/23  Vlan 14" }
      }

      [Int]$intSecondaryHDChoice = 0
      While ($intSecondaryHDChoice -lt 1 -OR $intSecondaryHDChoice -gt 2) {
            Write-Host ""
            Write-Host "      1.  Yes"
            Write-Host "      2.  No"
            Write-Host ""
            [Int]$intSecondaryHDChoice = Read-Host "Secondary hard drive requirement"
      }
      Switch( $intSecondaryHDChoice ) {
            1 { $strSecondaryHDChoice = "Yes" }
            2 { $strSecondaryHDChoice = "No" }
      }
      Write-Host ""
      $strVMClient = Read-Host 'Please provide the virtual machine name'

# ---------------------------------------------

# Process VM Creation
      Write-Host ""
      Write-Host "Creating VM based on requirements..."
      # ---------------------------------------------
      Write-Host "Creating temporary working directory"
      $strWorkingDirClone = "$strWorkingDir\$strVMClient"
      $strWorkingDirOrig = "$strWorkingDir\$strBaseOption"
      If (!(Test-Path -Path "$strWorkingDirClone" )){
          New-Item -ItemType Directory -Path "$strWorkingDirClone" | Out-Null
      }
      # ---------------------------------------------
      Write-Host "Loading PowerCLI snapin and assemblies"
      Add-PSSnapin VMWare.VimAutomation.Core | Out-Null
      [Reflection.Assembly]::LoadWithPartialName("vmware.vim") | Out-Null
            Write-Host "Connecting to server instance $strVCenterHost"
            Connect-VIServer -Server $strVCenterHost -User "$strUserName" -Password "$strPassword" -WarningAction SilentlyContinue | Out-Null
            Write-Host "Gathering datastore object"
            $objDataStore = Get-Datastore $strOSDataStore
            $strOSDataStoreURL = $objDataStore.ExtensionData.Info.Url -Replace "ds://", ""
            $strParentFileNameHint = "$strOSDataStoreURL$strBaseOption/$strBaseOption.vmdk"
      Write-Host "Removing PowerCLI snapin (Required for multiple cmdlets)"
      Remove-PSSnapin VMWare.VimAutomation.Core | Out-Null
      # ---------------------------------------------
      Write-Host "Copying source content"
      Copy-Item $strWorkingDirOrig\*.* -Destination $strWorkingDirClone\
      Write-Host "Customizing file configurations"
      Get-ChildItem $strWorkingDirClone -Recurse -Include *.* | ForEach-Object {
            (Get-Content $_) | ForEach-Object {
                  $_ -Replace $strBaseOption, $strVMClient `
                        -Replace "-000001", "" `
                        -Replace "-delta", "_Delta" `
                        -Replace '^disk.+$', "" `
                        -Replace '^ethernet.+$', "" `
                        -Replace '^evcCompatibilityMode.+$', "" `
                        -Replace '^guestCPUID.+$', "" `
                        -Replace '^hostCPUID.+$', "" `
                        -Replace '^replay.+$', "" `
                        -Replace '^sched.+$', "" `
                        -Replace '^toolsInstallManager.+$', "" `
                        -Replace '^unity.+$', "" `
                        -Replace '^userCPUID.+$', "" `
                        -Replace '^vm.+$', "" `
                        -Replace '^vmotion.+$', ""
                  } | Set-Content $_
            (Get-Content $_) | ForEach-Object {
                  $_ -Replace "parentFileNameHint=""$strVMClient.vmdk""", "parentFileNameHint=""$strParentFileNameHint"""
                  } | Set-Content $_
            }
      # ---------------------------------------------
      Write-Host "Naming files as required"
      Get-ChildItem "$strWorkingDirClone" -Recurse -Include *.* | Rename-Item -NewName {
            $_.Name -Replace $strBaseOption, $strVMClient `
                  -Replace "-000001", "" `
                  -Replace "-delta", "_Delta"
            }
      # ---------------------------------------------
      Write-Host "Reloading PowerCLI snapin and assemblies"
      Add-PSSnapin VMWare.VimAutomation.Core | Out-Null
      [Reflection.Assembly]::LoadWithPartialName("vmware.vim") | Out-Null
            Write-Host "Connecting to server instance $strVCenterHost"            
            Connect-VIServer -Server $strVCenterHost -User "$strUserName" -Password "$strPassword" -WarningAction SilentlyContinue | Out-Null
            Write-Host "Gathering datastore object"            
            $objDataStore = Get-Datastore $strOSDataStore
            Write-Host "Adding local drive reference for datastore access"
            New-PSDrive -Location $objDataStore -Name "DataStore" -PSProvider VimDatastore -Root "\"
                  $strVMClientPath = "DataStore:\" + $strVMClient
                  If (!(Test-Path -Path "$strVMClientPath" )){
                            New-Item -ItemType Directory -Path $strVMClientPath
                  }
                  Write-Host "Gathering updated files"                  
                  $arrRequiredFiles = Get-ChildItem $strWorkingDirClone -Recurse -Include *.*
                  Write-Host "Copying required files from working directory to the datastore"
                  Copy-DataStoreItem $arrRequiredFiles $strVMClientPath -Force
                  Write-Host "Cleaning up temporary working directory"
                  Remove-Item $strWorkingDir\$strVMClient -Force -Recurse
            Write-Host "Removing local drive reference to datastore"
            Remove-PSDrive "DataStore" | Out-Null
            Write-Host "Determining least taxed cluster node for virtual machine placement"
            $strLeastTaxedHost = Get-VMhost | Select Name,CpuUsageMhz | Sort-Object CpuUsageMhz -Descending | Select -First 1
            Write-Host "Collecting datastore information"
            ForEach ($strStore In Get-Datastore $strOSDataStore) {
                  $objDataStoreInstance = Get-Datastore -Name $strStore | %{Get-View $_.Id}
                  $objSearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
                  $objSearchSpec.matchpattern = "$strVMClient.vmx"
                  $strOSDataStoreInstanceBrowser = Get-View $objDataStoreInstance.Browser
                  $strOSDataStorePath = "[" + $objDataStoreInstance.Summary.Name + "]"
                   Write-Host "Gathering datastore view on vmx path"
                  $arrSearchResults = $strOSDataStoreInstanceBrowser.SearchDatastoreSubFolders($strOSDataStorePath, $objSearchSpec) | Where {$_.FolderPath -NotMatch ".snapshot"} | %{$_.FolderPath + ($_.File | Select Path).Path}
                  Write-Host "Registering virtual machine with vCenter"
                  ForEach ($strVMXFile in $arrSearchResults) {
                        Write-Host "Configuring the new virtual machine with the following information:"
                        Write-Host "Most eligible host:  $strLeastTaxedHost"
                        Write-Host "Datastore location:  $strOSDataStoreVMFolder"
                        Write-Host "VMX file:  $strVMXFile"
                        New-VM -VMFilePath $strVMXFile -VMHost $strLeastTaxedHost.Name -Location $strOSDataStoreVMFolder -RunAsync | Out-Null
                        }
                  }
            Write-Host "Holding process for virtual machine registration"
            Start-Sleep -s 10
            Write-Host "Configuring basic settings"
            Get-VM $strVMClient | Set-VM -MemoryMB $strMemoryOption -NumCPU $intProcOption -Confirm:$False -WarningAction SilentlyContinue | Out-Null
            Write-Host "Configuring network adapter"
            Get-VM $strVMClient | New-NetworkAdapter -NetworkName "$strNetworkOption" -StartConnected -WakeOnLan -Type $strNicType -Confirm:$False -WarningAction SilentlyContinue | Out-Null
            If ($strSecondaryHDChoice -eq "Yes") {
                  Write-Host "Adding secondary hard drive"
                  New-HardDisk -VM $strVMClient -CapacityGB 300 -DataStore $strSecondaryDataStore -StorageFormat Thin -Persistence persistent -WarningAction SilentlyContinue | Out-Null
            }
            Write-Host "Starting virtual machine"
            Get-Vm $strVMClient | Start-VM -ErrorAction SilentlyContinue | Out-Null
            Get-VMQuestion -VM $strVMClient | Set-VMQuestion -Option "button.uuid.copiedTheVM" -Confirm:$False
            Write-Host "Removing PowerCLI snapin"
      Remove-PSSnapin VMWare.VimAutomation.Core
      Write-Host "Process complete"

# ---------------------------------------------
0
usslindstrom
Asked:
usslindstrom
  • 2
  • 2
1 Solution
 
Andrew Hancock (VMware vExpert / EE MVE^2)VMware and Virtualization ConsultantCommented:
So I assume from reading your scripts you have created Linked Clones without the use of VMware Horizon View - which is the only supported environment for using Linked Clones?

Any other function is a hack job and hence in supported.
0
 
usslindstromAuthor Commented:
Understood.  I'm not looking for confirmation on what was created would be supported officially by VMWare.  - Otherwise this question would have been posted within the confines of support.
0
 
Andrew Hancock (VMware vExpert / EE MVE^2)VMware and Virtualization ConsultantCommented:
Your plan is sound and will work.

But make sure you have a backup.

Sorry mobile at present cannot type much!
0
 
usslindstromAuthor Commented:
Perfect.  - Thanks for the assistance.  :)

Will do on the idea of making sure everything important is backed up first.  Thanks.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now