Custom attribute to VM ware Vsphere using Java SDK

888 views Asked by At

I am trying to add a new custom attribute to VM ware vSphere using VMware JAVA SDK but it is throwing "InvalidType" exception.

com.vmware.vim25.InvalidType
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.vmware.vim25.ws.XmlGen.fromXml(XmlGen.java:205)
at com.vmware.vim25.ws.XmlGen.parseSoapFault(XmlGen.java:82)
at com.vmware.vim25.ws.WSClient.invoke(WSClient.java:134)
at com.vmware.vim25.ws.VimStub.addCustomFieldDef(VimStub.java:284)
at com.vmware.vim25.mo.CustomFieldsManager.addCustomFieldDef(CustomFieldsManager.java:57)
at vmwaretest.Connect.setSelectedVM(Connect.java:85)
at vmwaretest.Connect.main(Connect.java:29)

Code

ServiceInstance si = null;
    try {
        si = Initialisation(url, user, password);
    } catch (RemoteException e) {

        e.printStackTrace();
    } catch (MalformedURLException e) {

        e.printStackTrace();
    }

    ServerConnection serverConnection = si.getServerConnection();
    ManagedObjectReference  mor = si.getMOR();

    CustomFieldsManager cfm = new CustomFieldsManager(serverConnection, mor);
    try {
        cfm.addCustomFieldDef("type", null, null, null);
    } catch (DuplicateName e) {
        e.printStackTrace();
    } catch (InvalidPrivilege e) {
        e.printStackTrace();
    } catch (RuntimeFault e) {
        e.printStackTrace();
    } catch (RemoteException e) {
        e.printStackTrace();
    }

Connection to the vSphere is working fine as I am able to retrieve or change the already existing Custom attributes but not able to create a new one.

What is wrong with the above code? Or is there any other way to add new custom attribute using vmware Java SDK.

CustomFieldsManager doc https://pubs.vmware.com/vsphere-6-5/index.jsp?topic=%2Fcom.vmware.wssdk.pg.doc%2FPG_Appx_Privileges_Reference.23.2.html

1

There are 1 answers

0
Rishi Anand On BEST ANSWER

Below is Tag class which I have defined. Custom Attributes' key is global to all VMware resource and only value changes per resource. So, if you are adding new custom attribute key to a VM or a host then you need to add key globally and then change the value of that key for that very specific resource.

Below is working java example.

public class Tag{
       String key;
       String value;
    }

public void addTags(ServiceInstance serviceInstance, VirtualMachine virtualMachine, List<Tag> tags) throws CloudServiceException, CloudParameterException{
        if(EmptyUtil.isNotEmpty(tags)){
            CustomFieldsManager customFieldsManager = serviceInstance.getCustomFieldsManager();
            CloudValidate.resourceNotNull(customFieldsManager, "Custom Fields cannot be set for VM as CustomFieldsManager instance could not be obtained.");
            CustomFieldDef[] customFieldDefs = customFieldsManager.getField();
            Set<String> existingTags = getExistingTags(customFieldDefs);
            for(Tag tag : tags){
                if(!existingTags.contains(tag.getKey())){
                    updateTagsKey(customFieldsManager, tag.getKey());
                }
                updateTagsValue(virtualMachine, tag);
            }
        }
    }

    private void updateTagsKey(CustomFieldsManager customFieldsManager, String key){
        try {
            customFieldsManager.addCustomFieldDef(key, Constants.VMWARE_CUSTOMATTRIBUTE_TYPE_VM, null, null);
        }catch (DuplicateName dname){
            logger.warn("Custom attribute : {} already exists.", key);
        }catch(Exception exception) {
            logger.warn("Failed to add custom field due to : {}.", exception.getMessage());
        }
    }

    private void updateTagsValue(VirtualMachine virtualMachine, Tag tag){
        try{
            logger.info("Adding {} for Virtua Machine {}", tag.toString(), virtualMachine.getName());
            virtualMachine.setCustomValue(tag.getKey(), tag.getValue());
        }catch(Exception exception) {
            logger.warn("Failed to set custom attribute on VM due to  : {}.", exception.getMessage());
        }
    }

    private Set<String> getExistingTags(CustomFieldDef[] customFieldDefs){
        Set<String> existingTags = new HashSet<>();
        if(EmptyUtil.isNotEmpty(customFieldDefs)){
            for(CustomFieldDef customFieldDef : customFieldDefs){
                existingTags.add(customFieldDef.getName());
            }
            logger.debug("Existing Custom Fields from Custom Fields Manager : {}", Arrays.toString(existingTags.toArray()));
        }
        return existingTags;
    }