VMware Cloud Community
jlombardo529
Contributor
Contributor

I need help with Actions after upgrade of vRO

We moved from vRO 7.1 to 7.4   

The action that isn't working is one that will select a template by version and then pass that on for cloning to VM.   The new version of vRO throws an error that the split is undefined.   I'm not sure why I was hoping someone can help me track this down. 


var filter = '^' + os + '\\-template\\-\\d+\\.\\d+\\.\\d+$'; // string
var targetTypes = ['VirtualMachine'];// string[]
var properties = ['name'];// string[]
var rootObject = null;// Any
var foundObjects = [];
var containerRoot = null
if (typeof rootObject === 'undefined' || rootObject == null || rootObject == '<<null>>') {
    containerRoot = vc.rootFolder
} else {
    containerRoot = rootObject
}
var recursive = true
var containerView = vc.viewManager.createContainerView(containerRoot, targetTypes, recursive)
// create an object spec for the beginning of the traversal;
// container view is the root object for this traversal
var oSpec = new VcObjectSpec()
oSpec.obj = containerView.reference
oSpec.skip = true
// create a traversal spec to select all objects in the view
var tSpec = new VcTraversalSpec()
tSpec.name = 'traverseEntities'
tSpec.path = 'view'
tSpec.skip = false
tSpec.type = 'ContainerView'
// add it to the object spec
oSpec.selectSet = [tSpec]
var propertySpecs = new Array()
for (var t in targetTypes) {
    // specify the properties for retrieval
    var pSpec = new VcPropertySpec()
    pSpec.type = targetTypes[t]
    pSpec.pathSet = properties
    propertySpecs.push(pSpec)
}
var fs = new VcPropertyFilterSpec()
fs.objectSet = [ oSpec ]
fs.propSet = propertySpecs
var retrieveOptions = new VcRetrieveOptions()
var propertyCollector = vc.propertyCollector.createPropertyCollector()
try {
retrieveResult = propertyCollector.retrievePropertiesEx([fs], retrieveOptions)
do {
    if (typeof retrieveResult !== 'undefined' && retrieveResult !== null) {
processObjects(retrieveResult)
if (retrieveResult.token !== 'undefined' && retrieveResult.token !== null) {
    retrieveResult = propertyCollector.continueRetrievePropertiesEx(retrieveResult.token)
} else {
    break
}     
    } else {
      break;
    }
} while(true)
} finally {
    propertyCollector.destroyPropertyCollector()
}
for (i=0;i<foundObjects.length;i++) {
System.log(foundObjects[i]);
}
System.log(foundObjects.length);
vms = new Array()
for (var i in foundObjects) {
    vms.push(Server.fromUri(foundObjects[i]))
}
if(vms.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
vms.sort(versionCompare);
var indexToReturn = vms.length - 1;
System.log("The most current " + os + " template is " + vms[indexToReturn].name);
return vms[indexToReturn];
}
function processObjects(retrieveResult) {
    var resultObjects = retrieveResult.objects
    if (typeof foundObjects === 'undefined' || foundObjects === null) {
        foundObjects = new Array()
    }
    var pattern = new RegExp(filter,'i')
    for (r in resultObjects) {
      var objContent = resultObjects[r]
      var id = objContent.obj.value
      var type = objContent.obj.type
      var props = objContent.propSet
      for (p in props) {
        if (pattern.test(props[p].val)) {
var dunesId = "dunes://service.dunes.ch/CustomSDKObject?id='" 
                                      + vc.id + "/" + id +"'&dunesName='VC:" + type + "'"
            foundObjects.push(dunesId)
            break
        }
      }
    }
}
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
    if (v1parts.length != v2parts.length) {
        return -1;
    }
    return 0;
}

var filter = '^' + os + '\\-template\\-\\d+\\.\\d+\\.\\d+$'; // string
var targetTypes = ['VirtualMachine'];// string[]
var properties = ['name'];// string[]
var rootObject = null;// Any
var foundObjects = [];
 
var containerRoot = null
 
if (typeof rootObject === 'undefined' || rootObject == null || rootObject == '<<null>>') {
    containerRoot = vc.rootFolder
} else {
    containerRoot = rootObject
}
 
var recursive = true
 
var containerView = vc.viewManager.createContainerView(containerRoot, targetTypes, recursive)
 
// create an object spec for the beginning of the traversal;
// container view is the root object for this traversal
var oSpec = new VcObjectSpec()
oSpec.obj = containerView.reference
oSpec.skip = true
 
// create a traversal spec to select all objects in the view
var tSpec = new VcTraversalSpec()
tSpec.name = 'traverseEntities'
tSpec.path = 'view'
tSpec.skip = false
tSpec.type = 'ContainerView'
 
// add it to the object spec
oSpec.selectSet = [tSpec]
 
var propertySpecs = new Array()
for (var t in targetTypes) {
    // specify the properties for retrieval
    var pSpec = new VcPropertySpec()
    pSpec.type = targetTypes[t]
    pSpec.pathSet = properties
    propertySpecs.push(pSpec)
}
 
var fs = new VcPropertyFilterSpec()
fs.objectSet = [ oSpec ]
fs.propSet = propertySpecs
 
var retrieveOptions = new VcRetrieveOptions()
 
var propertyCollector = vc.propertyCollector.createPropertyCollector()
 
try {
retrieveResult = propertyCollector.retrievePropertiesEx([fs], retrieveOptions)
 
do {
    if (typeof retrieveResult !== 'undefined' && retrieveResult !== null) {
processObjects(retrieveResult)
if (retrieveResult.token !== 'undefined' && retrieveResult.token !== null) {
    retrieveResult = propertyCollector.continueRetrievePropertiesEx(retrieveResult.token)
} else {
    break
}     
    } else {
      break;
    }
} while(true)
} finally {
    propertyCollector.destroyPropertyCollector()
}
for (i=0;i<foundObjects.length;i++) {
System.log(foundObjects[i]);
}
System.log(foundObjects.length);
 
vms = new Array()
for (var i in foundObjects) {
    vms.push(Server.fromUri(foundObjects[i]))
}
 
if(vms.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
vms.sort(versionCompare);
var indexToReturn = vms.length - 1;
System.log("The most current " + os + " template is " + vms[indexToReturn].name);
return vms[indexToReturn];
}
 
function processObjects(retrieveResult) {
    var resultObjects = retrieveResult.objects
    if (typeof foundObjects === 'undefined' || foundObjects === null) {
        foundObjects = new Array()
    }
    var pattern = new RegExp(filter,'i')
    for (r in resultObjects) {
      var objContent = resultObjects[r]
      var id = objContent.obj.value
      var type = objContent.obj.type
      var props = objContent.propSet
      for (p in props) {
        if (pattern.test(props[p].val)) {
var dunesId = "dunes://service.dunes.ch/CustomSDKObject?id='" 
                                      + vc.id + "/" + id +"'&dunesName='VC:" + type + "'"
            foundObjects.push(dunesId)
            break
        }
      }
    }
}
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}
Reply
0 Kudos
12 Replies
iiliev
VMware Employee
VMware Employee

Could you show the exact error?

split is used only in the function versionCompare() so I'd suggest to add a couple of System.log() statements in the beginning of this function to log the values of v1.name and v2.name. Perhaps the values that are being sorted/compared has a different format than expected.

Reply
0 Kudos
jlombardo529
Contributor
Contributor

2019-11-25 21:30:37.956] [E] (com.domain.ORG/getMostCurrentTemplateByOs) Error in (Dynamic Script Module name : getMostCurrentTemplateByOs#142) TypeError: Cannot call method "split" of undefined

 

 

THat is the error

Reply
0 Kudos
iiliev
VMware Employee
VMware Employee

Here are the relevant lines:

v1parts = v1.name.split('-')[2].split('.');

v2parts = v2.name.split('-')[2].split('.');

The error means that the expression on which the method split() is invoked in null/undefined. Which could happen in the following cases:

  • either v1.name or v2.name is null/undefined
  • either v1.name or v2.name have value which, when split on dash character, produces less than 3 parts (that is, the name has less than 2 dashes, so when the code breaks when it tries to fetch the 3rd element using [2] index)

That's why I suggested to add additional System.log() statements before the above code to dump and see how the values of v1.name and v2.name look like. It looks like some of your machines have names with less than 2 dashes.

Reply
0 Kudos
jlombardo529
Contributor
Contributor

So,  I took your advice and did some extra logging.  It seems something is coming back undefined and so the system name isn't there for the split to analyze 

I now have this before the same error 

This worked in 7.1  so I'm inclined to believe it's an API that has changed.   It's just a matter of isolating and finding it.  

Does that sound correct?  

 

 

[2019-11-26 12:41:24.296] [I] 16

[2019-11-26 12:41:26.466] [I] notfound

[2019-11-26 12:41:27.690] [I] notfound,notfound

[2019-11-26 12:41:29.182] [I] notfound,notfound,notfound

[2019-11-26 12:41:30.618] [I] notfound,notfound,notfound,notfound

[2019-11-26 12:41:32.066] [I] notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:33.511] [I] notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:34.955] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:36.430] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:37.871] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:39.429] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:40.908] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:42.427] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:44.118] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:45.581] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:47.118] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:48.611] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound

[2019-11-26 12:41:24.296] [I] 16
[2019-11-26 12:41:26.466] [I] notfound
[2019-11-26 12:41:27.690] [I] notfound,notfound
[2019-11-26 12:41:29.182] [I] notfound,notfound,notfound
[2019-11-26 12:41:30.618] [I] notfound,notfound,notfound,notfound
[2019-11-26 12:41:32.066] [I] notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:33.511] [I] notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:34.955] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:36.430] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:37.871] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:39.429] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:40.908] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:42.427] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:44.118] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:45.581] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:47.118] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
[2019-11-26 12:41:48.611] [I] notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound,notfound
Reply
0 Kudos
iiliev
VMware Employee
VMware Employee

Is this output the content of the array foundObjects? If so, then maybe the call Server.fromUri(foundObjects[i]) is not returning what you expect? Could you log also the results from this call?

BTW, there were some changes between 7.1 and 7.4, including a completely new implementation of vCenter plug-in (from 7.3 onward), so it's possible there is some regression. Using an extra logging to isolate the exact change sounds like a good approach to me.

You can also try to upgrade vCenter plug-in to one of the more recent versions available for download, but lets first try to isolate the problem.

Reply
0 Kudos
jlombardo529
Contributor
Contributor

test
Reply
0 Kudos
jlombardo529
Contributor
Contributor

I get an error when adding logging to this portion of the script. 

I did ensure the machine names match the format I'm calling out and found no issues there. 

System.log(vm1.name);  causes an error that I've got a ; before a statement. 

Reply
0 Kudos
stevedrummond
Hot Shot
Hot Shot

The dunes path has changed for objects in the vCenter plug-in. As Illiav said the plug-in was completely redone and is one reason why accessing objects through the full dunes path is not a good idea.

You need to change your find to this (I have bolded the relevant part):

var dunesId =

"dunes://service.dunes.ch/CustomSDKObject?id='" +

vc.id +

",id:" +

id +

"'&dunesName='VC:" +

type +

"'";

foundObjects.push(dunesId);

You should also be doing a System.isNotFound() before adding it to the vm array when doing Server.fromUri(dunesId); as the return type is NotFound from that method (rather than null or undefined) you are getting the error on .split instead of simply accessing the .name property of vm1 or vm2.

As for when you attempted to do System.log(vm1.name) and got the parsing error, I'm assuming you tried to put inside the var lexicographical =  instantiation which is one statement split across four lines (notice the commas).

Finally, as an aside, this whole thing is a nightmare to read and you should really redo your entire approach if you can.

Reply
0 Kudos
jlombardo529
Contributor
Contributor

Thank you for the reply.  
I agree this is hard to read and every linter I've tried complains as such in different ways.   My goal is to keep this working until I can get it vRO to 8.0 and then write things that work well with it.
 
I've gonee ahead with thee changed you've recommended and you are correct in your assumptions so I can now see  vm1.name and vm2.name are undefined. 
   I tested this after making the changes to the search that we recommended. 
 
 
It iterates over 16 objects but lists them as 
[2019-12-02 08:00:32.644] [I] dunes://service.dunes.ch/CustomSDKObject?id='ccvsphprdvc01.org.domain.com,id:'&dunesName='VC:VirtualMachine'
 
in vRO 7.1 it iterates over one and finds the template.  So I'm fairly certian my issue is in there somewhere. 
Reply
0 Kudos
stevedrummond
Hot Shot
Hot Shot

When processing the VC:ManagedObject results to create your dunesId, change this line:

var id = objContent.obj.value;

to this

var id = objContent.obj.moref.value;

I tested it in my vRO 7.4 just now and the whole script is working.

Reply
0 Kudos
jlombardo529
Contributor
Contributor

Wow,  Thank you for that.  I wish I'd seen this sooner. 

I could not make heads or tales of any of this and took the route below. 

I'm pasting the whole script for anyone that wants to do anything similiar 

 

Thank you very much for the help. 

One extra question: 

 

How can I ensure this will work with vcenter 6.5 once I upgrade?  I'm currently on 6

 

 

vms = vc.getAllVirtualMachines(['name'],'xpath:isTemplate');

 
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}
= vc.getAllVirtualMachines(['name'],'xpath:isTemplate');
 
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}
= vc.getAllVirtualMachines(['name'],'xpath:isTemplate');
 
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}vms = vc.getAllVirtualMachines(['name'],'xpath:isTemplate');
 
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}vms = vc.getAllVirtualMachines(['name'],'xpath:isTemplate');
 
function checkMatch(vm) {
var re = new RegExp('^' + this + '-template-\\d+\\.\\d+\\.\\d+$')
return re.test(vm.name)
}
 
var templatesMatchingOs = vms.filter(checkMatch, os)
 
if(templatesMatchingOs.length === 0) {
System.warn("No template could be found for OS '" + os + "'");
return null;
} else {
templatesMatchingOs.sort(versionCompare);
var indexToReturn = templatesMatchingOs.length - 1;
System.log("The most current " + os + " template is " + templatesMatchingOs[indexToReturn].name);
return templatesMatchingOs[indexToReturn];
}
 
 
/**
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
 *
 * This function was born in http://stackoverflow.com/a/6832721.
 *
 * @param {string} v1 The first version to be compared.
 * @param {string} v2 The second version to be compared.
 * @param {object} [options] Optional flags that affect comparison behavior:
 * <ul>
 *     <li>
 *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
 *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
 *         "1.2".
 *     </li>
 *     <li>
 *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
 *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
 *     </li>
 * </ul>
 * @returns {number|NaN}
 * <ul>
 *    <li>0 if the versions are equal</li>
 *    <li>a negative integer iff v1 < v2</li>
 *    <li>a positive integer iff v1 > v2</li>
 *    <li>NaN if either version string is in the wrong format</li>
 * </ul>
 *
 * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
 * @license This function is in the public domain. Do what you want with it, no strings attached.
 */
function versionCompare(v1, v2, options) {
    var lexicographical = options && options.lexicographical,
        zeroExtend = options && options.zeroExtend,
        v1parts = v1.name.split('-')[2].split('.');
        v2parts = v2.name.split('-')[2].split('.');
 
 
    function isValidPart(x) {
        return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
 
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
        return NaN;
    }
 
    if (zeroExtend) {
        while (v1parts.length < v2parts.length) v1parts.push("0");
        while (v2parts.length < v1parts.length) v2parts.push("0");
    }
 
    if (!lexicographical) {
        v1parts = v1parts.map(Number);
        v2parts = v2parts.map(Number);
    }
 
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return 1;
        }
 
        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    if (v1parts.length != v2parts.length) {
        return -1;
    }
 
    return 0;
}
Reply
0 Kudos
stevedrummond
Hot Shot
Hot Shot

How can I ensure this will work with vcenter 6.5 once I upgrade?  I'm currently on 6

There is no guarantee. You could be affected by changes to vCenter itself or by any changes VMware make to the vCenter plug-in.

Any time items are upgraded you'll need to regression test.

Reply
0 Kudos