VMware Cloud Community
Subnet88
Enthusiast
Enthusiast

Retrieve list of cluster DRS Affinity rules

Hi,

Not wanting to re-invent the wheel, I thought I would ask the community first. Has anybody written a workflow to retrieve a list of DRS Affinity rules attached to a cluster?

Reply
0 Kudos
18 Replies
Burke-
VMware Employee
VMware Employee

I didn't find any code samples for that one in any of my libraries.

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you! Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
Reply
0 Kudos
robrtb12
Enthusiast
Enthusiast

Hello,
Here's a snippet of code I use, maybe this will help you

var rules = att_clusterComputeResource.configurationEx.rule;
var ruleFound = false;

if (rules)
{
for each (var rule in rules)
{
  if ((rule.enabled) && (rule.name.toLowerCase() == att_ruleName.toLowerCase()))
  {
   ruleFound = true;
   break;
  }
}
}

Reply
0 Kudos
Burke-
VMware Employee
VMware Employee

May have found something helpful... Modifying inline to hopefully present what you need....

assuming a VC:ClusterComputeResource object named "my_vimcluster", this action code will hopefully return an array of strings containing the names of the affinity rules:

i in my_vimcluster.configuration.rule) {

var clusterRules = new Array();

for (i in my_vimcluster.configuration.rule) {
var ruleName = my_vimcluster.configuration.rule[i].name;
clusterRules.push(ruleName)
//System.log("Adding rule '"+ruleName+"' to array...");
}
return clusterRules;

Please let me know if the above code works, it could be placed in an action called something like: getAffinityRuleNamesForCluster

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you! Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
Subnet88
Enthusiast
Enthusiast

Thank you guys, that pulled the names. Is there any documentation on this method? I would like top pull an array of morefs that are included in this rule, and the type of rule it is.

Reply
0 Kudos
Burke-
VMware Employee
VMware Employee

Get familiar with the API Explorer... In this case, find the VC:ClusterComputeResource object type and select it... the bottom pane will link you to the Scriptable Object for that type.

Screen Shot 2013-06-12 at 11.18.48 AM.png

Once you're on the Scriptable Object (Green dot icon), expand it to see all the properties/methods... From there, based on my code, click on the "configuration" property and see what it's return type is - VcClusterConfigInfo (in bottom pane - click on it)

Screen Shot 2013-06-12 at 11.20.47 AM.png

Once you have the VcClusterConfigInfo Scriptable object selected, look at it's properties and again, based on my code - look at the "rule" property:

Screen Shot 2013-06-12 at 11.22.53 AM.png

From here, you can see that you have an array of VcCluterRuleInfo objects returned. To see the available properties, click on that Return Type ....

Screen Shot 2013-06-12 at 11.25.03 AM.png

That is how we got the names of the rules... but the rule doesn't appear to contain a reference to the VMs...

I don't see anything off hand on listing VMs associated with a rule.. I'm sure it's in there somewhere, but probably a different path through the api Smiley Wink

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you! Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
Reply
0 Kudos
Subnet88
Enthusiast
Enthusiast

It looks like the objects I need to retrieve is "VCClusterAffinityRuleSpec" and "VcClusterAntiAffinityRuleSpec". The problem I have is how  do I work my way up the tree?

Reply
0 Kudos
WWI
Enthusiast
Enthusiast

The API explorer shows you expected types and the types being returned. So you only have to follow the types from attribute to attribute which are also links through the explorer. Otherwise you can take a look to your https://vcenterserver.domain/mob/ where you can browse your life environment and also see the objects and types and how they are familiar with each other. The hardest point in the beginning on my side was to handle attribute arrays. But its worth it Smiley Wink

Reply
0 Kudos
rkuechler
Enthusiast
Enthusiast

Hi

With the imformation above, I managed to get (almost) all informations (properties) about all DRS rules and DRS groups from a specific cluster:

 

// Get all groups
var varVmGroups = winEsxiCluster.configurationEx.group;

System.log("")
System.log(" *** All Cluster Groups *** ")
System.log(" -------------------------- ")

for (i in varVmGroups) {
    System.log("");
    System.log("Group Nr.: " + i);
    System.log(  "Name:  " + varVmGroups[i].Name);

    for (j in varVmGroups[i].Vm){
        System.log("    VM Nr. " + j + " Name: " + varVmGroups[i].Vm[j].Name)
    }    

    for (j in varVmGroups[i].Host){
        System.log("    Host Nr. " + j + " Name: " + varVmGroups[i].Host[j].Name)
    }
}


// Get all VM rules
var varVmRule = winEsxiCluster.configurationEx.rule;

System.log("")
System.log(" *** All Cluster Rules *** ")
System.log(" -------------------------- ")

for (i in varVmRule) {
    System.log("");
    System.log("Rule Nr.: " + i);
    System.log("  Name:         " + varVmRule[i].Name);
    System.log("  Enabled:      " + varVmRule[i].Enabled);
    System.log("  Mandatory:    " + varVmRule[i].Mandatory);
    System.log("  VmGroup:      " + varVmRule[i].VmGroupName);
    System.log("  Affine hosts: " + varVmRule[i].AffineHostGroupName);
    System.log("  Anti-Affiny:  " + varVmRule[i].AntiAffineGroupName);

    for (j in varVmRule[i].Vm){
        System.log("    VM Nr. " + j + " Name: " + varVmRule[i].Vm[j].Name)
    }

    System.log("  VM Group:     " + varVmRule[i].VmGroup);
    System.log("  Depends on:   " + varVmRule[i].DependsOnVmGroup);
}

 

 

This is the partially output, e.g. of all Groups:

 

2023-04-26 13:35:20.600 +02:00INFO *** All Cluster Groups *** 
2023-04-26 13:35:20.601 +02:00INFO -------------------------- 
2023-04-26 13:35:20.602 +02:00INFO
2023-04-26 13:35:20.603 +02:00INFOGroup Nr.: 0
2023-04-26 13:35:20.604 +02:00INFOName:  GO-Hosts
2023-04-26 13:35:20.605 +02:00INFO    Host Nr. 0 Name: xxxxxxxxxxxxxxx
2023-04-26 13:35:20.606 +02:00INFO
2023-04-26 13:35:20.607 +02:00INFOGroup Nr.: 1
2023-04-26 13:35:20.608 +02:00INFOName:  SG-Hosts
2023-04-26 13:35:20.609 +02:00INFO    Host Nr. 0 Name: xxxxxxxxxxxxxxxx
2023-04-26 13:35:20.610 +02:00INFO
2023-04-26 13:35:20.611 +02:00INFOGroup Nr.: 2
2023-04-26 13:35:20.612 +02:00INFOName:  NUMU_VMs
2023-04-26 13:35:20.613 +02:00INFO    VM Nr. 0 Name: vax00222
2023-04-26 13:35:20.614 +02:00INFO    VM Nr. 1 Name: vax00387
2023-04-26 13:35:20.615 +02:00INFO    VM Nr. 2 Name: vax00262
2023-04-26 13:35:20.618 +02:00INFO    VM Nr. 3 Name: vax00101
2023-04-26 13:35:20.619 +02:00INFO
2023-04-26 13:35:20.620 +02:00INFOGroup Nr.: 3
2023-04-26 13:35:20.621 +02:00INFOName:  NOMO_VMs
2023-04-26 13:35:20.622 +02:00INFO    VM Nr. 0 Name: vax00100
2023-04-26 13:35:20.623 +02:00INFO

 

 

But one information I cannot extract: the type of the group (VM or Host group?) or the type of the rule (VM to Host, Affinity, Anti-Affinity...?)

If I print all the output out, I can see that this information is at the start of the output. In this example, here one can see, the this muss be a AntiAffinityRule, because this information is three times mentioned  as a substring in the first two lines:

 

2023-04-26 13:35:20.628 +02:00INFO  DynamicWrapper (Instance) : [VcClusterAntiAffinityRuleSpec]-[class com.vmware.o11n.plugin.vsphere_gen.AntiAffinityRuleSpec_Wrapper] -- VALUE : (vim.cluster.AntiAffinityRuleSpec) {
   dynamicType = null,
   dynamicProperty = null,
   key = 501,
   status = null,
   enabled = true,
   name = Separate_VMs,
   mandatory = null,
   userCreated = true,
   inCompliance = null,
   ruleUuid = 52acd385-27a0-2220-a866-8ead2dd94aa0,
   vm = (vim.VirtualMachine) [
      Stub: moRef = (ManagedObjectReference: type = VirtualMachine, value = vm-15262, serverGuid = null), binding = https://xxxxxxxxxxxx:443/sdk,
      Stub: moRef = (ManagedObjectReference: type = VirtualMachine, value = vm-15007, serverGuid = null), binding = https://xxxxxxxxxxxx:443/sdk
   ]
}

 

 

The same about the output of the groups...

But I cannot figure out, how I can read out this type information as a single property from a rule or a group?

Any tipps?

Regards
Roman

 

 

Reply
0 Kudos
eoinbyrne
Expert
Expert

Hi,

Worst case you could use the instanceof operator to detect the rule object type?

 

for (i in varVmRule) {
    var rule = varVmRule[i];
    System.log("");
    System.log("Rule Nr.: " + i);
    if(rule instanceof VcClusterAffinityRuleSpec){
        System.log("This one is Affinity!");
    }
    else if(rule instanceof VcClusterAntiAffinityRuleSpec){
        System.log("This one is ANTI-Affinity!");
    }
    else {
        throw "Strange rule type detected! " + typeof(rule);
    }
}

 

 

-HTH

rkuechler
Enthusiast
Enthusiast

Great!
I'm going to try it out, as soon I have a little time.
Stay tuned...

Reply
0 Kudos
rkuechler
Enthusiast
Enthusiast

@eoinbyrne 

Many thanks, that works very well.
Regards

Reply
0 Kudos
rkuechler
Enthusiast
Enthusiast

Now, I have all the data I need for the groups and rules, but I recognize that I have to put them in an object (or array) by myself so that I can then convert them into JSON format and save them.

In PowerCLI I can list (and generate an object) of all groups and rules of a cluster with the CmdLets

  • Get-DRSClusterGroup
  • Get-DRSVMHostRule

then I can convert them easily to JSON.

Are there comparable methods available in vRO to get all DRS groups or rules  in an object at once? I browsed the API explorer and tryed around a bit, but wasn't successful.

Regards
Roman

 

Reply
0 Kudos
eoinbyrne
Expert
Expert

Hi

I think to convert this to JSON for logging/export, you'd have to hand-roll something. You can try using JSON.stringify on vRO plugin classes but it generally just reports something like "[object Object]" for anything coming from scripting object

I normally just create JS objects like this

// create the object this way
var myCustomObj = {};

var customKeyName = "test-inner-key"
// add values like this
myCustomObj.innerObj = {};
// if you need to reference a var for a key name do it this way
myCustomObj.innerObj[customKeyName] = "put a value here";

// retrieve the value this way
var storedInner = myCustomObj.innerObj[customKeyName];

 

 

eoinbyrne
Expert
Expert

I was having a quiet day so had a crack at what you might need to do here - totally not tested so please consider this just a starting point 🙂

// Create a custom object to contain the JSON data you want
var clusterRuleObj = {};

var clusterName = winEsxiCluster.name;

// create an entry in there with the cluster name as the key
clusterRuleObj[clusterName] = {};

// Get all groups
var varVmGroups = winEsxiCluster.configurationEx.group;

System.log("")
System.log(" *** All Cluster Groups *** ")
System.log(" -------------------------- ")

for (i in varVmGroups) {
    System.log("");
    System.log("Group Nr.: " + i);
    System.log(  "Name:  " + varVmGroups[i].Name);

    // create a place to store the groupConfig & list of VM names & hosts
    var groupConfig = {};
    groupConfig.vmNames = [];
    groupConfig.hostNames = [];

    for (j in varVmGroups[i].Vm){
        System.log("    VM Nr. " + j + " Name: " + varVmGroups[i].Vm[j].Name)
        groupConfig.vmNames.push(varVmGroups[i].Vm[j].Name);
    }    

    for (j in varVmGroups[i].Host){
        System.log("    Host Nr. " + j + " Name: " + varVmGroups[i].Host[j].Name)
        groupConfig.hostNames.push(varVmGroups[i].Host[j].Name);
    }

    // store the groupConfig in the object under the cluster name
    var grpName = varVmGroups[i].Name
    clusterRuleObj[clusterName]["groups"][grpName] = groupConfig;
}

// print the story so far (pretty printed using 2 spaces for indentation + the "null" is for an optional formatter/modifier/filter if you want it)
System.log(JSON.stringify(clusterRuleObj, null, 2));

// Get all VM rules
var varVmRule = winEsxiCluster.configurationEx.rule;

System.log("")
System.log(" *** All Cluster Rules *** ")
System.log(" -------------------------- ")

for (i in varVmRule) {
    System.log("");
    System.log("Rule Nr.: " + i);
    System.log("  Name:         " + varVmRule[i].Name);
    System.log("  Enabled:      " + varVmRule[i].Enabled);
    System.log("  Mandatory:    " + varVmRule[i].Mandatory);
    System.log("  VmGroup:      " + varVmRule[i].VmGroupName);
    System.log("  Affine hosts: " + varVmRule[i].AffineHostGroupName);
    System.log("  Anti-Affiny:  " + varVmRule[i].AntiAffineGroupName);

    var rule = varVmRule[i];

    var affinityRules = [];
    var antiAffinityRules = [];

    var ruleData = {};
    ruleData.name = rule.Name;
    ruleData.vmGroupName = rule.VmGroupName;
    ruleData.enabled = rule.Enabled;
    ruleData.mandatory = rule.Mandatory;

    if(rule instanceof VcClusterAffinityRuleSpec){
        System.log("This one is Affinity!");
        ruleData.affineHostName = rule.AffineHostGroupName;
        affinityRules.push(ruleData);
    }
    else if(rule instanceof VcClusterAntiAffinityRuleSpec){
        System.log("This one is ANTI-Affinity!");
        ruleData.antiAffineHostName = rule.AntiAffineGroupName;
        antiAffinityRules.push(ruleData);
    }
    else {
        throw "Strange rule type detected! " + typeof(rule);
    }

    // NB: I can't find these members on the VcClusterRuleInfo scripting objects + your log examples don't show these printing....?
    //System.log("  VM Group:     " + varVmRule[i].VmGroup);
    //System.log("  Depends on:   " + varVmRule[i].DependsOnVmGroup);
}

// print the final object content as text in the log
System.log(JSON.stringify(clusterRuleObj, null, 2));

// this is how you can capture the JSON and store in a var
var exportableJSONContent = JSON.stringify(clusterRuleObj, null, 2);

// for later when you get there, read the object back from a string like this
var recoveredClusterRuleInfo = JSON.parse(exportableJSONContent);
rkuechler
Enthusiast
Enthusiast

You are incredible, thank you very much for your efforts.
I will try it out as soon as possible.

Kind regards
Roman

Reply
0 Kudos
rkuechler
Enthusiast
Enthusiast

While you were preparing your last post, I tried a little bit by trying to write all the data into one object. But because I didn't get the desired result from this object with JSON.stringify() afterwards, I tried it with an array as an alternative. This worked better for me, except that when I finally wrote the data formatted in JSON into a file as "vRO resource", vRO showed me this JSON file as a single, long string, and not as expected nicely divided, in several lines and with indentations?

I see that in your approach you write the data into an object.
Is that the better approach in this case? In principle, should data that is ultimately saved as JSON always be organized in objects, or is it sometimes better in arrays? (Even if arrays are actually "objects" too, right?)

Reply
0 Kudos
eoinbyrne
Expert
Expert

Hi

Using arrays VS Objects doesn't matter at all, it's really just down to the internal structure of the data. Also, since this is your custom data you get to choose 🙂

I generally use Objects as they permit child keys which can be other Objects, properties, arrays so you can model quite complex data relationships this way.

Arrays are great for lists of values or objects

Which you choose is up to you.

On the JSON format, the call I generally use for printable JSON is the first one here

// This one formats the JSON using system linebreaks & 
// 2 spaces as the indent character. 
// Good for logs statements, write to file or other cases 
// where humans will read it
// Parameter 2 is an optional replacer function which can
// be used to hide/replace parts of the object you don't want to
// see in the output
var prettyPrintedJson = JSON.stringify(myObject, null, 2);

// This one prints it all in one line. Good for API calls mostly
var singleLineOutput = JSON.stringify(myObject)

  

MDN docs for JSON.stringify are here  - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

eoinbyrne_0-1684329625176.png

 

JSON.parse can always read back the JSON string whether you pretty printed or not, so you can safely use the pretty printed version for your backup file

-HTH

 

rkuechler
Enthusiast
Enthusiast

Problem solved - please ignore.
(Can't delete this post anymore...)

Reply
0 Kudos