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;
}
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.
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
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:
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.
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
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.
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.
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.
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.
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');
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.