VMware Cloud Community
StuDuncan
Contributor
Contributor

Copying VM files from ReadOnly NFS mount to Local datastore

I have an environment with 6 vCenters. I have a read-only NFS datastore (SharedTemplates) where common templates for all vCenters live.  The names will be constant, so could be static in the script, but would prefer not to.

I am trying to write a script that would copy all the VM files from the Shared Templates datastore to the local datastore of each vCenter so that they're much faster to deploy.

I don't want the VMs to be in inventory on the SharedTemplates datastore, only on the local datastore.  But I need to manually add them in order to occasionally update them.

I'm trying to determine the best way to tackle this.  Not sure if copy-datastoreitem with hardcoded paths is the best way, or if there's some other way to delete the local DS VM, then bring the VM into inventory on the SharedTemplates DS, clone it to a new template on the local DS, then remove the VM on the SharedTemplates DS from inventory. Or even just use a bash shell to ssh beneath the vCenter.

I can write the loops for the vCenters & templates, just need help doing the actual writing from one DS to another.

Appreciate any insight or feedback.

Stu Duncan

Tags (2)
0 Kudos
12 Replies
StuDuncan
Contributor
Contributor

Follow up to this.

I set the permissions for the user I was testing just a move-vm to be ReadOnly+Browse for the SharedTemplates DS.  It still removed the actual files.  Not sure how or why it did that...

The NFS isn't actually readonly as I need to be able to update the master.  So I'm controlling it by permissions.

0 Kudos
LucD
Leadership
Leadership

Just to clarify, are you talking of vSphere templates (Get-Template) or VMs (Get-VM) that serve as a template ?

In any case, I would suggest the Copy-DatastoreItem cmdlet and copy the VM's/template's folder to the destination datastore.


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

0 Kudos
StuDuncan
Contributor
Contributor

Well, yes and no.

The master templates live on the SharedTemplates DS, but aren't in inventory from there.  They're only in inventory from the local datastore.

This is my logical workflow:

foreach($v in $vCenters){

     connect to vCenter $v

     foreach($t in $templates){

          remove-template $t

          copy-datastoreitem ds:\SharedTemplates\$t ds:\local\$t

          add-template $t

     }

     disconnect $v

}

If that works, I just have to worry about which sub folder to put them in, but I could get that info from $t.

0 Kudos
LucD
Leadership
Leadership

That looks a good algorithm, provided the Remove-Template is to unregister the template from the vCenter (use the -DeletePermanently:$false switch).

And I assume the add-template is intended to register the new copy of the template on the local datastore.

You can find the path/folder from $t.ExtensionData.Config.Files.VmPathName


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

StuDuncan
Contributor
Contributor

So like this?

foreach($v in $vCenters){

     connect to vCenter $v

     foreach($t in $templates){

          $filelocation = $t.ExtensionData.Config.Files.SnapshotDirectory

          $folderlocation = get-vm $t | get-vmfolderpath

          remove-template $t -confirm:$false

          copy-datastoreitem ds:\NFS\$t\* $filelocation\ -force

          new-template $t -TemplateFilePath $filelocation -location $folderlocation

     }

     disconnect $v

}

0 Kudos
StuDuncan
Contributor
Contributor

Seems to work all except the copy-datatstore item.

This doesn't fail, but doesn't copy the 21GB of files either:

copy-datastoreitem -item "[zSharedTemplates] $t/*" -destination "[SystemsSAN] $t/" -force

Fully pathing it out with the template name doesn't work or fail either:

copy-datastoreitem -item "[zSharedTemplates] w2k8r2_64bit_withUtilities/w2k8r2_64bit_withUtilities.vmdk" -destination "[SystemsSAN] w2k8r2_64bit_withUtilities/" -force

No percentage notice or anything. And no file copied over either

0 Kudos
LucD
Leadership
Leadership

Do you get any messages ?

From where do you run the script, the PowerCLI prompt ?

Which PowerCLI version are you using ? Do a Get-PowerCLIVersion.


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

0 Kudos
StuDuncan
Contributor
Contributor

No messages at all.  Comes back immediately.

Running from a script in powershellISE or from its command line.

PS C:\Windows\system32> Get-PowerCLIVersion

PowerCLI Version

----------------

   VMware vSphere PowerCLI 5.5 Release 2 Patch 1 build 1931983

---------------

Snapin Versions

---------------

   VMWare AutoDeploy PowerCLI Component 5.5 build 1890764

   VMWare ImageBuilder PowerCLI Component 5.5 build 1890764

   VMware License PowerCLI Component 5.5 build 1265954

   VMware VDS PowerCLI Component 5.5 build 1926677

   VMware vSphere PowerCLI Component 5.5 Patch 1 build 1926677

Need this version due to Compellent plugin requirements.

0 Kudos
StuDuncan
Contributor
Contributor

Wondering if the PS-drive is still a requirement?

Re: copy-datastoreitem

Apparently it is.  This was a test script I wrote which worked:

add-pssnapin VMware.VimAutomation.Core

connect-viserver vcentersystems.dev.fco -user user@vsphere.local -password user

$ds1 = Get-Datastore zSharedTemplates

$ds2 = Get-Datastore SystemsSAN

$t = "w2k8r2_64bit_withUtilities"

New-PSDrive -Location $ds1 -Name source -PSProvider VimDatastore -Root '\'

New-PSDrive -Name dest -PSProvider ViMdatastore -Root '\' -location $ds2

Copy-DatastoreItem  dest:\$t\* -Destination source:\$t\  -Force

disconnect-viserver vcentersystems.dev.fco

I had to give 'user' admin privileges on both datastores before it would work though.

So that's my solution.

Thanks for helping!

0 Kudos
StuDuncan
Contributor
Contributor

So this is the final script in total, in case anyone else ever wants to use a master set of templates on a shared datastore to deploy to several vcenters.

#Assumes template name = file name = folder name, all templates are in "_Templates" folder

#Assumes SANS are named $teamSAN, vcenter is vcenter$team.dev.fco

if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {

    Add-PSSnapin VMware.VimAutomation.Core

    }

$team = "team1", "team2"

foreach($tm in $team){

     connect-viserver ("vcenter"+$tm+".dev.fco") -user user@vsphere.local -password user

     $ds1 = Get-Datastore zSharedTemplates

     $ds2 = Get-Datastore ($tm + "SAN")

     New-PSDrive -Location $ds1 -Name source -PSProvider VimDatastore -Root '\'

     New-PSDrive -Name dest -PSProvider ViMdatastore -Root '\' -location $ds2

     $templates = get-folder _Templates | get-template

     foreach($tmpl in $templates){

          $folderID = (get-template $tmpl).folderid

          remove-template $tmpl -DeletePermanently:$false -confirm:$false

          Copy-DatastoreItem  source:\$tmpl\* -Destination dest:\$tmpl\  -Force -Recurse

          new-template -Name $tmpl -TemplateFilePath "[$ds2] $tmpl/$tmpl.vmtx" -location (get-folder -id $folderID) -vmhost (Get-VMHost | Where { $_.ConnectionState -eq "Connected" } | Get-Random) #Doesn't work with -DiskStorageFormat Thin

     }

     disconnect-viserver ("vcenter"+$tm+".dev.fco") -confirm:$false

}

Only weirdness is that the new-template (also tried with new-vm) fails if I add the -DiskStorageFormat Thin, even though this is in the 5.5 new-template cmdlet.

Error is "Parameter set cannot be resolved using the specified named parameters."

Works fine, but now all the templates are thick provisioned.  Which isn't good.

LucD any idea how to get around this, or do I have to go the long route like you did here:

http://www.lucd.info/2013/06/30/hl-tools-part-1-clone-a-vm-without-vcenter/

0 Kudos
LucD
Leadership
Leadership

Yes, the DiskStorageFormat issue (see Datastore Clusters Not Working) is annoying.

That long path from my post could be a solution though.


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

0 Kudos
StuDuncan
Contributor
Contributor

Thanks for the confirmation, Luc. Irritating bug.

This was my solution.

remove:

Copy-DatastoreItem  source:\$tmpl\* -Destination dest:\$tmpl\  -Force -Recurse


Add:

get-harddisk -Datastore $ds1 -DatastorePath "[$ds1] $tmpl/$tmpl.vmdk" | copy-harddisk -DestinationPath "[$ds2] $tmpl/" -Force

Copy-DatastoreItem  source:\$tmpl\$tmpl.vmtx -Destination dest:\$tmpl\  -Force

Copy-DatastoreItem  source:\$tmpl\$tmpl.vmxf -Destination dest:\$tmpl\  -Force

Copy-DatastoreItem  source:\$tmpl\$tmpl.vmsd -Destination dest:\$tmpl\  -Force

Not as pretty, not as fast (10+min to copy 2.6GB), but fully functional now.

Thanks for all the help!

0 Kudos