Bdawk_20
Contributor
Contributor

Clone VM workflows - clusters instead of hosts

The clone VM workflows all take Host/Datastore arguments for where the clone should be created.  Is it possible to point to a cluster instead where it will be autobalanced?   I would like to avoid having a "build host" if at all possible.

17 Replies
iiliev
VMware Employee
VMware Employee

Yes, it should be possible.

For example, 'cloneVM' action creates/uses a VirtualMachineRelocateSpec object, and according to the vCenter docs here http://pubs.vmware.com/vsphere-51/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.RelocateSp... the host parameter is not strictly required.

pabloramos
Enthusiast
Enthusiast

Do you have a sample workflow that clones a VM using template that uses the "cluster" resource?

0 Kudos
Bdawk_20
Contributor
Contributor

I do not.  I am getting my workflow functional before i circle back around and try to implement the nice to haves.  This is something that i would imagine many people have run into though.  Someone has to have one Smiley Happy

0 Kudos
schepp
Leadership
Leadership

Hi,

I had the same problem. The normal cloning workflows always want an explicit host, but I wanted to choose a cluster.

I scripted a workaround and called to following to save all hosts of the cluster in an array:

var hostarray = System.getModule("com.vmware.library.vc.cluster").getAllHostSystemsOfCluster(cluster);

Then I pick a random entry from the array and forward that to the cloning workflow as selected host.

Tim

Bdawk_20
Contributor
Contributor

Interesting!  What did you use to randomly choose if you don't mind sharing?

0 Kudos
schepp
Leadership
Leadership

Like this:

var hostarray = System.getModule("com.vmware.library.vc.cluster").getAllHostSystemsOfCluster(cluster);

var deploytohost = hostarray[Math.floor(Math.random()*hostarray.length)];

Edit: You also need to specify the resourcepool in the most clone workflow. If you don't use resourcepools and just want to place it in the hidden top level resourcepool, you can get is like this:

var deploytopool = deploytohost.parent.resourcePool;

DefiantFrog
Enthusiast
Enthusiast

I'm finding that specifying a Host to deploy to is usually optional.  If it is, ignore that value.

You can use whatever attribute has the type 'VC:ResourcePool'.  Specify either the default Resource Pool in a Cluster, or a specific one if you have granular resource pools within your clusters, and the new VM will go to the cluster that houses the resource pool and pick an ESXi host within the cluster all by itself.

0 Kudos
SieQ79
Contributor
Contributor

I was facing same problem, fortunately I had a support from vCO consultant. What we did, we created a new action called "getAllDatastoresOfHost" which takes host as VC:HostSystem as input and returns the array of host data stores "return host.datastore". Then using this action I built the WF to get less used datastore of the host and return it as output from workflow.

For the host of the cluster I also built a WF to get one, WF takes cluster name as string as input and returns the first element of "getAllHostSystemsOfCluster" because we're using DRS so the starting host of the VM doesn't really matters, DRS will move the VM to a proper host, according to the defined policies.

0 Kudos
pabloramos
Enthusiast
Enthusiast

Tim, I am attempting to use your code with some mods to print to the System.log. First I run a Scriptable task to get the value for deploytopool, then I am binding the deploytopool to the pool variable which is part of the main clone, windows /with single nic workflow. We don't use ResourcePool(s) in our env, so I just need to get the hidden top resourcepool value (Resources) to pass on to clone workflow. Problem is that the code is spitting out a complete line of data and I just need the 'Resouces" to pass on as the VC:ResourcePool value to the workflow.

var hostarray = System.getModule("com.vmware.library.vc.cluster").getAllHostSystemsOfCluster(cluster)

var deploytohost = hostarray[Math.floor(Math.random()*hostarray.length)];

var deploytopool = deploytohost.parent.resourcePool;

System.log("This is the host: " + deploytohost);

System.log("This is the Resource Pool: " + deploytopool);

[2014-10-24 09:11:22.883] [I] This is the host: DynamicWrapper (Instance) : [VcHostSystem]-[class com.vmware.vmo.plugin.vi4.model.VimHostSystem] -- VALUE : HostSystem'pablo'

[2014-10-24 09:11:22.883] [I] This is the Resource Pool: DynamicWrapper (Instance) : [VcResourcePool]-[class com.vmware.vmo.plugin.vi4.model.VimResourcePool] -- VALUE : ResourcePool'Resources'

0 Kudos
SieQ79
Contributor
Contributor

If you don't use Resource Pools, so why don't you simply create an attribute in a workflow of type VC:ResourcePool and bind it to fixed value. then just pass it to the cloneVM action.

0 Kudos
pabloramos
Enthusiast
Enthusiast

Not sure, but this is not working. I run a copy of the Clone Windows workflow in my master provisioning workflow. I added an Attribute type String called resourcePool with a value of Resources and bounded it to the pool parameter (VC:ResourcePool) on the Clone Windows workflow. I get this error: [2014-10-24 10:18:45.488] [I] Workflow:LM Copy of Clone, Windows with single NIC / checkVMwareInput (item0) : ch.dunes.model.type.ConvertorException: Cannot convert to object , reason : finder not found for type : null I have a feeling since every cluster has a default top level pool, I just can't pass "Resources" as a value.

0 Kudos
schepp
Leadership
Leadership

Hey,

it spits out a whole line because you print out the whole object of the type VC:ResourcePool and not just the name. So for your log you could write deploytopool.name I think.

But for your clone workflow you need the whole object.

So define the both deploy to vars as outputs and throw them into your cloning workflow.

0 Kudos
pabloramos
Enthusiast
Enthusiast

Tim, you were spot on. I overlooked step to assign value as out parameter.

0 Kudos
spavlov
Contributor
Contributor

Hello!

How did you exclude hosts with states: Disconnected, Not Responding and hosts in Maintenance Mode?

I had tried to use while cicle for searching hosts only in Connected state and not in Maintenance Mode, but It's not working and returns me random host regardless of its state.

if(!cluster){

     throw "UndefinedParameter: cluster mandatory input is not defined.";

}

var host = cluster.host[Math.floor(Math.random() * cluster.host.length)];

var hoststate = 'connected';

while (host.state != hoststate && !host.runtime.inMaintenanceMode){

     host = cluster.host[Math.floor(Math.random() * cluster.host.length)];

};

System.debug('Host Status: '+host.state);

System.debug('Random hostname: '+host.name);

return host;

0 Kudos
MC2016
Enthusiast
Enthusiast

See below sample to find online host.

// All hosts in the cluster

var hosts = cluster.host;

// Filter the 'online' hosts

var hostsOn = hosts.filter(function(host) {

  return host.runtime.powerState == VcHostSystemPowerState.poweredOn

    && host.runtime.inMaintenanceMode == false;

})

spavlov
Contributor
Contributor

Thank you for your help, it works!

0 Kudos
qc4vmware
Virtuoso
Virtuoso

Replace this line:

while (host.state != hoststate && !host.runtime.inMaintenanceMode){

With this line:

while (host.summary.runtime.connectionState.name.toLowerCase() != hoststate && !host.runtime.inMaintenanceMode){

0 Kudos