VMware Cloud Community
jonathanw
Enthusiast
Enthusiast

vCloud Director metadata entry type?

I've been scratching my head over this one for a bit trying to get vRealize Orchestrator to properly get/set/update vCD metadata against a vApp/VM. How do I determine the type of metadata value? All of the examples I can see rely on the 'old' vCD API where the only valid metadata type was 'String'.

With 'testVm' set to a VM object correctly I can use the following to see all the 'String' metadata keys and values:

var metadata = testVm.getMetadata();

var metadataEntries = metadata.getTypedEntries().enumerate();

for each (var metadataEntry in metadataEntries) {

     var value = metadataEntry.typedValue.getValue(new VclMetadataStringValue).value;

     System.log("Metadata key: " + metadataEntry.key + " value: " + value);

}

This code works fine for metadata where the data type is 'String' (since using VclMetadataStringValue), but doesn't retrieve any keys/values from metadata fields using the other 3 data types (boolean, date/time or number). What expression can I use to determine the type of the metadataEntry so I can handle it appropriately?

Thanks in advance, Jon.

0 Kudos
10 Replies
iiliev
VMware Employee
VMware Employee

Hi Jon,

In the plug-in documentation for attribute typedValue of the class VclMetadataEntry I see the following:

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

One of:

  • MetadataStringValue
  • MetadataNumberValue
  • MetadataBooleanValue
  • MetadataDateTimeValue

Related object types:

  • VclMetadataDateTimeValue
  • VclMetadataStringValue
  • VclMetadataBooleanValue
  • VclMetadataNumberValue

0 Kudos
jonathanw
Enthusiast
Enthusiast

I know what types to expect, but how do I test an individual metadataEntry to see which of these it is?

Reading metadataEntry.typedValue gives:

DynamicWrapper (Instance) : [VclAbstractValueObject]-[class com.vmware.vmo.plugin.vcloud.model.VCloudAbstractObjectDecorator] -- VALUE : com.vmware.vmo.plugin.vcloud.model.VCloudAbstractObjectDecorator@4223fba9

I've also tried using instanceof to test for one of these object types but without success either. I'm not overly familiar with JavaScript so this is likely me not understanding object references.

0 Kudos
iiliev
VMware Employee
VMware Employee

I don't have vCloud environment to test it, but it seems that metadata entries have an attribute named type that looks suitable to determine the object type. So you can try to replace your loop with something like the following:

for each (var metadataEntry in metadataEntries) {

     var tp = metadataEntry.type;

     if (tp == ...) {

        var stringValue = metadataEntry.typedValue.getValue(new VclMetadataStringValue).value;

        System.log("Metadata key: " + metadataEntry.key + " string value: " + stringValue);

     } else if (tp == ...) {

        var booleanValue = metadataEntry.typedValue.getValue(new VclMetadataBooleanValue).value;

        System.log("Metadata key: " + metadataEntry.key + " boolean value: " + booleanValue);

     } else if (tp == ...) {

        var numberValue = metadataEntry.typedValue.getValue(new VclMetadataNumberValue).value;

        System.log("Metadata key: " + metadataEntry.key + " number value: " + numberValue);

     } else if (tp == ...) {

        var datetimeValue = metadataEntry.typedValue.getValue(new VclMetadataDateTimeValue).value;

        System.log("Metadata key: " + metadataEntry.key + " datetime value: " + datetimeValue);

     } else {

        System.log("Metadata key: " + metadataEntry.key + " value of unknown type: " + tp);

     }

}

Above, you need to replace the occurrences of '...' (on lines 3, 6, 9, and 12) with the actual values returned on line 2 for the corresponding metadata entry type (you have to experiment here, I'm not sure how the type value looks like).

0 Kudos
jonathanw
Enthusiast
Enthusiast

Thanks for the response, that was my first thought, but unfortunately metadataEntry.type returns:

application/vnd.vmware.vcloud.metadata.value+xml

For any metadata type - which while being accurate is not that helpful.

0 Kudos
iiliev
VMware Employee
VMware Employee

OK.

Could you show your code using instanceof which you said is not working?

Another thing to check (a bit stupid, but there is a chance for it to work). As there is only a handful of possible metadata entry types, for each entry you can try to retrieve its value for each possible type. there is a chance that these calls will return null or throw an error if the entry actual type doesn't match the type you pass to it. Something like the following:

for each (var metadataEntry in metadataEntries) { 

    var val = null;

    var stringValue = metadataEntry.typedValue.getValue(new VclMetadataStringValue); 

    if (val == null && stringValue != null) {

        val = stringValue;

    }

    var booleanValue = metadataEntry.typedValue.getValue(new VclMetadataBooleanValue); 

    if (val == null && booleanValue != null) {

        val = booleanValue;

    }

    var numberValue = metadataEntry.typedValue.getValue(new VclMetadataNumberValue); 

    if (val == null && numberValue != null) {

        val = numberValue;

    }

    var datetimeValue = metadataEntry.typedValue.getValue(new VclMetadataDateTimeValue);

    if (val == null && datetimeValue != null) {

        val = datetimeValue;

    }

    if (val != null) {

        System.log("Metadata key: " + metadataEntry.key + " value: " + val.value);

    }

0 Kudos
jonathanw
Enthusiast
Enthusiast

Pretty sure something like what you've suggested would work (null is returned if you attempt to read the 'wrong' type) - but I don't really like the approach of submitting up to 4 calls and expecting to get a 'null' value from them until finding one that works. Seems like there should be a 'better' way by determining the metadataEntry type first.

The instanceof test I was trying was along the lines of:

if (medadataEntry.typedValue instanceof VclMetadataStringValue) { ...handle String value }

else if (metadataEntry.typedValue instanceof VclMetadataBooleanValue) { ...handle Boolean value }

else if (metadataEntry.typedValue instanceof VclMetadataDateTimeValue) { ...handle DateTime value }

else if (metadataEntry.typedValue instanceof VclMetadataNumberValue) { ...handle Number value }

But that doesn't work (all tests fail for all metadata types)

0 Kudos
moonsurfer68
Enthusiast
Enthusiast

What you're looking for can be found with a little digging. Note that I converted the XML to JSON as I despise  XML. Smiley Happy

var metadata = vm.getMetadata();

for each (var metadataEntry in metadata.getTypedEntries().enumerate()) {

     var xmlEntry = metadataEntry.toXml();

     var jsonEntry = System.getModule("com.vmware.library.http-rest").xml2json(xmlEntry);

     var key = jsonEntry.MetadataEntryType.Key;

     var value = jsonEntry.MetadataEntryType.TypedValue.Value;

     var type = jsonEntry.MetadataEntryType.TypedValue.type;

     System.log("Key: " + key + " - Value: " + value + " - Type: " + type);

}

pastedImage_0.png

0 Kudos
moonsurfer68
Enthusiast
Enthusiast

Note that if the "ns:6" bothers you, you can just do something like this:

var type = (jsonEntry.MetadataEntryType.TypedValue.type).replace("ns6:","");

0 Kudos
iiliev
VMware Employee
VMware Employee

Yrs, this will work.

Although I'd still prefer vCloud plug-in developers to expose some public API to access the metadata entry type, without having to resort to the XML/JSON internal structure of vCloud data types (which I suppose could change over time).

0 Kudos
jonathanw
Enthusiast
Enthusiast

This finally bugged me enough to do something about it - due to issues with the built-in functions for creating/updating metadata entries, I ended up writing my own set of Actions for getting, setting and deleting metadata against any vCD objects of any type. I ended up having to use the API directly as there are some definite issues in the plugin libraries for metadata manipulation.

I've attached the 3 .action files I ended up creating (set, get and delete metadata value) to this post - hopefully these will be useful to someone else out there.

Jon.

0 Kudos