One of cool vSphere features: Tutorial:How Storage DRS works with storage policies in SPBM?

SDRS integration with storage profiles was one of the cool feature I was waiting for since vSphere 5.5. In vSphere 6.0 GA, there were some public references of its support but no detailed documentation was available. As per this KB I am happy to know that in vCenter Server 6.0.0b and above, Storage DRS is fully supported to have storage profile enforcement. Now SDRS is aware of storage policies in SPBM (Storage Policy Based Management). Recently I got opportunity to play with this feature and I thought to write a detailed post which can help all. Here we go

As part of this SDRS integration with storage profile/policy, One SDRS cluster level advanced option is introduced i.e. “EnforceStorageProfiles”. Advanced option EnforceStorageProfiles takes one of these integer values, 0,1 or 2 where the default value is 0.

When option is set to 0, it is mean that NO storage profile enforcement on the SDRS cluster.

When option is set to 1, it is mean that there is storage profile SOFT enforcement on the SDRS cluster. SDRS will try its best to comply with storage profile/policy. However if required, SDRS will violate the storage profile compliant.

When option is set to 2, it is mean that there is storage profile HARD enforcement on the SDRS cluster. In any case, SDRS will not violate the storage profile.

Refer KB 2142765 in order to know how to configure SDRS advanced option “EnforceStorageProfiles” using vSphere web client and vSphere client.

Now I will walk you through vSphere web client workflows as follows in order to play with this cool feature. This is kind of Tutorial.

1. Configuring SDRS advanced option to enable SOFT (1) storage profile enforcement with Storage DRS.

-Create a SDRS cluster (aka POD) with 3 datastores namely DS1, DS2 and DS3.
-Go to SDRS Cluster >> Manage >> Settings >> Storage DRS web client workflow. Click on Edit and configure the option “EnforceStorageProfiles” as shown in below screenshot.

Adding SDRS option

You could see I had set this option to 1 i.e. SOFT enforcement

2. Creating 2 Tags named “Gold” and Silver”.

Tags are required to attach to all the datastores in datastore cluster (as per datastore capability) as well as to create tag based VM storage policies.

– Go to Home >> Tags >> click on New tag and create a “Gold” tag with “FC SAN” category as shown in below screenshot

Create Tag

Similar to Gold tag, please create a “Silver” tag with “iSCSI SAN” category. At this point make sure you have 2 tags, Gold and Silver.

3. Assign the tags to datastores in SDRS POD.

-Go to SDRS POD >>DS1 >> Manage >> Tags >> Click on Assign tags as shown in below screenshot

Assign tags to Datastore

Please assign “Gold” tag to the DS1 as well as DS2. Finally assign “Silver” tag to datastore DS3. You can see the assigned tags for each datastore as shown below screenshot.

Assiged-tag-on-DS3

You can see in above screenshot, DS3 was assigned with “Silver” tag.

4. Creating VM storage policy

– Go to Home >> Policies and profiles >> VM storage policy >> Click on the create VM storage policy as specified in below screen shot.

Create VM storage policy

-Once you click on “Create a new VM storage policy”, specify policy name as “Gold VM Storage Policy” and Click next.
– On Rule-Sets window, click on Add tag-based rule and select “Gold” tag under “FC SAN” category as shown in below screenshot.
Adding tag based rule
– On Storage compatibility UI page, keep default and click next. Finally click on finish at the end as shown below screenshot.
VM storage policy finish

– Similar to “Gold VM Storage Policy” creation, repeat above steps to create “Silver VM Storage Policy” based on “Silver” tag. At this moment you will have 2 VM storage policies “Gold VM Storage Policy” and “Silver VM Storage Policy”.

Now we are ready to play with SDRS with Storage profile integration feature. Lets try out some workflows from SDRS perspective to verify whether profiles are being considered by SDRS. Note that in the very first step we have set the “EnforceStorageProfiles” SDRS option to 1 i.e. SOFT profile enforcement.

1. Create VM workflow: i.e. SDRS initial placement workflow.

– From web client. Start create VM workflow >> Give VM name as “GoldVM” >> select compute resource >> under select storage, select VM storage policy as “Gold VM Storage Policy” that we created in last section and storage as SDRS POD we created initially as shown in below screenshot

Warning on selecting policy create VM

If you see in above screenshot, SDRS POD is listed under “incompatible” storage. Note that this is expected as SDRS POD has 3 datastores and 2 of those have “Gold” tag attached and 3rd has “Silver” attached. Warning shown in above screenshot also shows the same. i.e. Datastore does not satisfy compatibility since it does not support one or more required properties. Tags with name “Gold” not found on datastore”. As I said, this is expected as we have selected “Gold VM Storage policy” and NOT all the datastores in SDRS POD have “Gold” tag attached. Overall, no panic, just click next.

-Finally on the finish page of VM creation, we can see SDRS initial placement recommendations as shown in below screenshotSDRS recommendations

From above screen shot you can understand that SDRS placement recommendations on DS2 are absolutely spot on as DS2 datastore has “Gold” tag attached.

Now you can check whether the created VM “GoldVM” is placed on the datastore compatible with Gold VM storage policy by SDRS. You could see in below screenshot, SDRS has placed the GoldVM on right datastore and VM storage policies are compliant.

VM-complaint

Below is the screenshot for the “GoldVM” VM files. You can see all the VM files are placed on datastore DS2 which has Gold tag attached. is not it cool?

Datastore files on DS2

Based on above screenshots we can say that SDRS is aware of VM storage policies. Now lets try another SDRS workflow i.e. Putting datastore in maintenance mode.

2. Putting datastore in maintenance mode.

As we know that all the “GoldVM” VM files are in datastore DS2 as expected, now we will put datastore DS2 into maintenance mode and we expect SDRS will storage vMotion the VM to DS1 as DS1 is the only other datastore where “Gold” tag is attached.

From web client, Go to SDRS POD >> DS2 >> right click on DS2 and select “Enter Maintenance mode”. As soon as we click Enter Maintenance mode we get SDRS migration recommendations in order to evacuate the DS2 datastore as shown in below screenshot.

After putting into MM

You could see in above screenshot, SDRS has recommended to migrate VM files to DS1 as expected. How cool is that?

To see if SOFT profile integration is working fine, I went ahead and put DS1 also into maintenance mode and I observed VM files were moved to DS3 as expected as we have set the “EnforceStorageProfiles” SDRS option to 1 i.e. SOFT profile enforcement (DS2 is already in maintenamce mode.).

3. Configuring SDRS affinity rules.

I tested first case with VMDK anti affinity (Intra VM) and second case with VM anti affinity(Inter VM), in both the cases, I have observed affinity rules will have higher precedence over storage profiles attached to the VMs/datastores. SDRS will first obey the affinity rules first.

Finally I even tested some SDRS workflows where I filled the datastores so that they cross the SDRS space threshold and finally invoked SDRS to see if SDRS really does consider storage profiles while generating space migration recommendations. I observed SDRS does consider storage profiles as expected.

Overall, above tutorial will help you to get started. Testing SDRS with HARD storage profile enforcement I leave it to you. Enjoy!

One caveat : As noted in this KB, vCloud Director (vCD) backed by SDRS cluster does NOT support Soft (1) or Hard (2) storage profile enforcements. vCloud Director (vCD) will work well with Default (0) option.

Let me know if you have comments.

Want to vMotion a VM from one vCenter server to another vCenter using vSphere API? Here you go

As part of one of customers case, I was testing vMotion across two 6.0 vCenter servers those are connected to the same SSO domain. As we know already, when 2 vCenter servers are connected to the same SSO domain, you can manage both VCs using web client. Initially I tested vMotion from web client and later in order to automate bulk VMs migration across vCenter, I was looking for vSphere APIs and I could find below 2 vSphere APIs.

1. RelocateVM_Task() under VirtualMachine Managed object
2. placevm() under ClusterComputeResource managed object

I went through above vSphere API reference and I could see RelocateVM_Task() API was already there. However, in vSphere 6.0, it is improved greatly in order to support vMotion between 2 vCenters. On the other hand, placeVM() API was new brand API introduced in vSphere 6.0. Initially, I decided to try RelocateVM_Task() API for automating vMotion across 2 vCenters with same SSO domain. After automating this, I tested my java SDK script on vCenters with same SSO domain and it worked with no any issues. Later, I just thought lets give a try across vCenters those are connected to the different SSO domains and to my surprise, it worked like charm. is it not super cool? How easy it is now to migrate your workloads across data-centers/VCs/Clusters!.

So vMotion between 2 completely different vCenter is supported in vSphere 6.0 but there is NO UI support from web client at the moment. If you want to this functionality i.e. vMotion between 2 VCs with different SSO domains. vSphere API is the only way.

After successful vMotion across different SSO domains, I was really excited and thought to play with this little more by creating a DRS cluster in both VCs. I created a VM-VM affinity rule with couple of VMs in DRS cluster in VC1 as shown in below screenshot.

VC1_Rule_before_vMotion

Now I initiated vMotion from first VC to DRS cluster in second VC using same Java SDK script and I could see the DRS rule associated the migrated VM also got migrated as shown in below screen shot. How cool is that!

VC2_Rule_After_vMotion

Below is the complete code sample which can help you quickly to vMotion from a VC to other VC.

Note that this sample works fine with VCs with same SSO or VCs with different SSO. You do not even need to have shared storage between both VCs. This script will work fine within the same VC as well (with some change).

Same script is available on my git hub repository: ExVC_vMotion.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/DRS/vMotion
//:: # Description: Extended Cross VC vMotion using RelocateVM_Task() API. vMotion between vCenters (with same SSO domain or different SSO domain)

package com.vmware.yavijava;

import java.net.MalformedURLException;
import java.net.URL;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ServiceLocator;
import com.vmware.vim25.ServiceLocatorCredential;
import com.vmware.vim25.ServiceLocatorNamePassword;
import com.vmware.vim25.VirtualDevice;
import com.vmware.vim25.VirtualDeviceConfigSpec;
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
import com.vmware.vim25.VirtualDeviceDeviceBackingInfo;
import com.vmware.vim25.VirtualEthernetCard;
import com.vmware.vim25.VirtualMachineMovePriority;
import com.vmware.vim25.VirtualMachineRelocateSpec;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.Datastore;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;


public class ExVC_vMotion {

    public static void main(String[] args) throws Exception {
        if(args.length!=7)
        {  
            //Parameters you need to pass
            System.out.println("Usage: ExVC_vMotion srcVCIP srcVCusername srcVCpassword destVCIP destVCusername destVCpassword destHostIP");
            System.exit(-1);
        }

        URL url1 = null;
        try
        {
            url1 = new URL("https://"+args[0]+"/sdk");
        } catch ( MalformedURLException urlE)
        {
            System.out.println("The URL provided is NOT valid. Please check it.");
            System.exit(-1);
        }

        String srcusername = args[1];
        String srcpassword = args[2];
        String DestVC=args[3];
        String destusername=args[4];
        String destpassword = args[5];
        String destvmhost=args[6];
       
        //Hardcoded parameters for simplification
        String vmName="VM1"; //VM name to be migrated
        String vmNetworkName="VM Network"; //destination vSphere VM port group name where VM will be migrated
        String destClusterName="ClusterVC2"; //Destination VC cluster where VM will be migrated
        String destdatastoreName="DS1"; //destination datastore where VM will be migrated
        String destVCThumpPrint="c7:bc:0c:a3:15:35:57:bd:fe:ac:60:bf:87:25:1c:07:a9:31:50:85"; //SSL Thumbprint (SHA1) of the destination VC

        // Initialize source VC
        ServiceInstance vc1si = new ServiceInstance(url1, srcusername,
                srcpassword, true);
        URL url2 = null;
        try
        {
            url2 = new URL("https://"+DestVC+"/sdk");
        } catch ( MalformedURLException urlE)
        {
            System.out.println("The URL provided is NOT valid. Please check it.");
            System.exit(-1);
        }

        // Initialize destination VC

        ServiceInstance vc2si = new ServiceInstance(url2, destusername,
                destpassword, true);
        Folder vc1rootFolder = vc1si.getRootFolder();
        Folder vc2rootFolder = vc2si.getRootFolder();

        //Virtual Machine Object to be migrated
        VirtualMachine vm = null;
        vm = (VirtualMachine) new InventoryNavigator(vc1rootFolder)
        .searchManagedEntity("VirtualMachine", vmName);
       
        //Destination host object where VM will be migrated
        HostSystem host = null;
        host = (HostSystem) new InventoryNavigator(vc2rootFolder)
        .searchManagedEntity("HostSystem", destvmhost);
        ManagedObjectReference hostMor=host.getMOR();

        //Destination cluster object creation
        ClusterComputeResource cluster = null;
        cluster = (ClusterComputeResource) new InventoryNavigator(vc2rootFolder)
        .searchManagedEntity("ClusterComputeResource", destClusterName);
       
        //Destination datastore object creation
        Datastore ds=null;
        ds = (Datastore) new InventoryNavigator(vc2rootFolder)
        .searchManagedEntity("Datastore", destdatastoreName);
        ManagedObjectReference dsMor=ds.getMOR();

        VirtualMachineRelocateSpec vmSpec=new VirtualMachineRelocateSpec();
        vmSpec.setDatastore(dsMor);
        vmSpec.setHost(hostMor);
        vmSpec.setPool(cluster.getResourcePool().getMOR());

        //VM device spec for the VM to be migrated
        VirtualDeviceConfigSpec vdcSpec=new VirtualDeviceConfigSpec();
        VirtualDevice[] devices= vm.getConfig().getHardware().getDevice();
        for(VirtualDevice device:devices){

            if(device instanceof VirtualEthernetCard){

                VirtualDeviceDeviceBackingInfo vddBackingInfo= (VirtualDeviceDeviceBackingInfo) device.getBacking();
                vddBackingInfo.setDeviceName(vmNetworkName);
                device.setBacking(vddBackingInfo);
                vdcSpec.setDevice(device);
            }

        }

        vdcSpec.setOperation(VirtualDeviceConfigSpecOperation.edit);
        VirtualDeviceConfigSpec[] vDeviceConSpec={vdcSpec};
        vmSpec.setDeviceChange(vDeviceConSpec);

        //Below is code for ServiceLOcator which is key for this vMotion happen
        ServiceLocator serviceLoc=new ServiceLocator();
        ServiceLocatorCredential credential=new ServiceLocatorNamePassword();
        ((ServiceLocatorNamePassword) credential).setPassword(destpassword);
        ((ServiceLocatorNamePassword) credential).setUsername(destusername);
        serviceLoc.setCredential(credential);

        String instanceUuid=vc2si.getServiceContent().getAbout().getInstanceUuid();
        serviceLoc.setInstanceUuid(instanceUuid);
        serviceLoc.setSslThumbprint(destVCThumpPrint);
        serviceLoc.setUrl("https://"+DestVC);
        vmSpec.setService(serviceLoc);
        System.out.println("VM relocation started....please wait");
        boolean flag=false;
        vm.relocateVM_Task(vmSpec, VirtualMachineMovePriority.highPriority);
        flag=true;
        if(flag){
            System.out.println("VM is relocated to 2nd vCenter server");
        }
        vc1si.getServerConnection().logout();
        vc2si.getServerConnection().logout();
    }
}

Notes:
– There is one imp parameter you need to pass into migration spec i.e. Destination VC Thumbprint. There are several ways to get it as shown here. I personally used below way to get the destination VC thumbprint.
From google chrome browser : URL box of the VC (besides https:// lock symbol)>>view site information >> Certificate information >> Details >> Scroll down till last as shown in below screenshot

Thumbprint

– For the sake of simplicity, I have hard-coded some parameters, you can change it based on your environment.
– You can scale the same code to vMotion multiple VMs across vCenter server
– As I said, there is another API for vMotion across VCs i.e. placevm() under ClusterComputeResource managed object . Please stay tuned for my next blog post on the same.

If you want to automate the same use case using PowerCLI, here is great post by William Lam.

If you have still not setup your YAVI JAVA Eclipse environment:Getting started tutorial

Important tutorials to start with: Part I & Part II

vSphere 6.0 cool APIs to mark local host HDD to SSD, SSD to HDD: Sample API script

Recently I wanted to test vFRC (vSphere Flash Read Cache) feature interop with vSphere DRS and vSphere HA. I was figuring out ways to emulate my hosts local HDDs as SSD as I did not have real SSDs in my lab. There are couple of ways I used to fake/emulate local HDD as SSD earlier but this time I found other cool way to automate this quickly by using readily available API. The API that I am talking about is markAsSSD(). This API got introduced in vSphere 6.0. It is important to know why this API is made officially available. The reason this API primarily introduced is: Some time SSDs behind some controllers might not be recognized as SSD correctly. Other use cases for this API can be used to test VMware vSAN (just playing around), vFRC, flash host cache, interop testing etc. Of course, performance of real SSD is incomparable with fake SSD.

Below is the complete code sample which can help you quickly to Mark the local Lun of the host as SSD..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/Storage
//:: # Description: Mark the local Lun of the host as SSD for testing purpose.


package com.vmware.yavijava;
import java.net.MalformedURLException;
import java.net.URL;
import com.vmware.vim25.ScsiLun;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostStorageSystem;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;

public class MarkAsSSD {

    public static void main(String[] args) throws Exception {
        if(args.length!=4)
        {
            System.out.println("Usage: MarkAsSSD url username password hostip/fqdn");
            System.exit(-1);
        }

        URL url = null;
        try
        {
            url = new URL(args[0]);
        } catch ( MalformedURLException urlE)
        {
            System.out.println("The URL provided is NOT valid. Please check it.");
            System.exit(-1);
        }
        String username = args[1]; //vCenter username
        String password = args[2]; //vCenter password
        String hostname = args[3]; // host IP on which local HDD is available
        String LunDisplayName="Local VMware Disk (mpx.vmhba1:C0:T2:L0)"; //Add the Display name of the lun that can be seen from VI client or NGC
        // Initialize the system, set up web services
        ServiceInstance si = new ServiceInstance(url, username,
                password, true);

        Folder rootFolder = si.getRootFolder();
        HostSystem host = null;

        host = (HostSystem) new InventoryNavigator(rootFolder)
        .searchManagedEntity("HostSystem", hostname);


        if (host == null) {
            System.out.println("Host not found on vCenter");
            si.getServerConnection().logout();
            return;
        }

        HostStorageSystem hhostsystem = host.getHostStorageSystem();
        ScsiLun[] scsilun = hhostsystem.getStorageDeviceInfo().getScsiLun();
        boolean flag = false;
        for (ScsiLun lun : scsilun) {
            System.out.println("Display Name"+lun.getDisplayName());
            if (lun.getDisplayName().equals(
                    LunDisplayName)) {
                hhostsystem.markAsSsd_Task(lun.getUuid());
                flag = true;
                break;
                // hhostsystem.markAsNonSsd_Task(lun.getUuid());

            }

        }
        if (flag) {
            System.out.println("LUN is marked as SSD successfully");

        }else{
            System.out.println("LUN is NOT marked as SSD, plz check if local lun is in use");
           
        }
       
        si.getServerConnection().logout();

    }
}

Notes:
– For the sake of simplicity, I have hard-coded LUN display name, you can change it based on your environment.
– You can scale the same code to mark all the local HDDs to SSDs in all the hosts across datacenter or multiple datacenter.
– I would like you to have your attention on other new useful/handy related vSphere 6.0 APIs such as “MarkAsNonSSD” , “MarkAsLocal”, “MarkAsNonLocal“. Same sample can be leveraged to automate these related APIs.

If you have still not setup your YAVI JAVA Eclipse environment:Getting started tutorial

Important tutorials to start with: Part I & Part II

How to get all DRS rules associated with each VM in a DRS cluster using API : Interesting API in vSphere 6.0

As we know, one VM can be associated with several DRS affinity rules. If your DRS cluster has several rules configured, it is really cumbersome to check what is the type of the rule  and how many rules are associated with each VM in a DRS cluster. There is a interesting method introduced in vSphere 6.0 which can address this pain point. New method that I am talking about is “findRulesForVm()”. This method is introduced in vSphere 6.0 under “ClusterComputeResource” managed object. It is mean that you need to have this managed object in order to call this useful method. i.e. findRulesForVm().

Note: This method can list all the VM-VM affinity/anti-affinity rules associated with particular VM. This method can not return the VM-Host affinity rules associated with the VM.

Below is the complete code sample which can help to get all the VM VM DRS rules associated with each VM in Cluster. Please do modify this sample as per your need.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/DRS
//:: # Description: Script to find all the rules associated with all the VMs in the DRS cluster

package com.vmware.yavijava;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import com.vmware.vim25.ArrayUpdateOperation;
import com.vmware.vim25.ClusterAffinityRuleSpec;
import com.vmware.vim25.ClusterAntiAffinityRuleSpec;
import com.vmware.vim25.ClusterConfigSpec;
import com.vmware.vim25.ClusterRuleInfo;
import com.vmware.vim25.ClusterRuleSpec;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;
import com.vmware.vim25.mo.util.MorUtil;

public class FindRulesForVMsInCluster {

public static void main(String[] args) throws Exception {
if(args.length!=3)
{
System.out.println("Usage: FindRulesForVMInCluster url username password");
System.exit(-1);
}

URL url = null;
try
{
url = new URL(args[0]);
} catch ( MalformedURLException urlE)
{
System.out.println("The URL provided is NOT valid. Please check it.");
System.exit(-1);
}
String username = args[1];
String password = args[2];
String ClusterName = "My-Cluster"; //Your DRS cluster Name
ManagedEntity vms[] = null;

// Initialize the system, set up web services
ServiceInstance si = new ServiceInstance(url, username,
password, true);

Folder rootFolder = si.getRootFolder();

ClusterComputeResource cluster = null;
cluster = (ClusterComputeResource) new InventoryNavigator(rootFolder)
.searchManagedEntity("ClusterComputeResource", ClusterName);

System.out.println("Cluster name::"+cluster.getName());

vms = (ManagedEntity[]) new InventoryNavigator(cluster)
.searchManagedEntities("VirtualMachine");

for(ManagedEntity vm:vms){
//New vSphere 6.0 method to find the VM affinity rules associated with particular VM
ClusterRuleInfo[] rules=cluster.findRulesForVm((VirtualMachine) vm);
System.out.println("Rules assciated with VM "+vm.getName()+" are::");
for(ClusterRuleInfo rule:rules){
System.out.println(rule.getName()+":" + rule.getEnabled());
}
System.out.println("================================");
}
si.getServerConnection().logout();
}
}

Note:
– For the sake of simplicity, I have hard-coded DRS cluster name, you can change it based on your environment.
– You can scale the same code to all the clusters in a datacenter or multiple datacenter.

If you have still not setup your YAVI JAVA Eclipse environment:Getting started tutorial

Important tutorials to start with: Part I & Part II

How to quickly get vSphere Cluster resource usage( cpu, mem, storage) using API: cool API in vSphere 6.0

Some time back, I wanted to get the cluster resource usage (cpu, memory, storage)for one of my project requirements. I was exploring the ways to get cluster resource usage and to my surprise, vSphere 6.0 has introduced new API which can fetch detailed cluster resource usage. It was tricky to get this info earlier and now single API call will help to get this. How cool it is! If you are not using vSphere HA/DRS, this API is super life saver for you in order to keep the track of the cluster resources and monitor these resources on all the cluster across vCenter. New method that I am talking about is “getResourceUsage()”. This method is introduced in vSphere 6.0 under “ClusterComputeResource” managed object. It is mean that you need to have this managed object to call this useful method. i.e. getResourceUsage(). This API can fetch not only the resource capacity but also current resource usage.

Below is the complete code sample which can help you quickly to get Cluster resource usage (cpu,memory and storage)..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/DRS
//:: # Description: Script to quickly get Cluster resource usage (cpu,memory and storage).

package com.vmware.yavijava;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import com.vmware.vim25.ClusterResourceUsageSummary;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ServiceInstance;

public class GetClusterResourceUsage {

    public static void main(String[] args) throws Exception {
        if(args.length!=3)
        {
            System.out.println("Usage: GetClusterResourceUsage url username password");
            System.exit(-1);
        }

        URL url = null;
        try
        {
            url = new URL(args[0]);
        } catch ( MalformedURLException urlE)
        {
            System.out.println("The URL provided is NOT valid. Please check it...");
            System.exit(-1);
        }
        String username = args[1];
        String password = args[2];
        String ClusterName = "Cluster1"; //Your cluster Name

        // Initialize the system, set up web services
        ServiceInstance si = new ServiceInstance(url, username,
                password, true);
        Folder rootFolder = si.getRootFolder();

        ClusterComputeResource cluster = null;
        cluster = (ClusterComputeResource) new InventoryNavigator(rootFolder)
        .searchManagedEntity("ClusterComputeResource", ClusterName);

        System.out.println();
        System.out.println("Resource Usagae Summary for cluster::"+cluster.getName());
        //Get the Cluster resource summary object
        ClusterResourceUsageSummary resourceSummary= cluster.getResourceUsage();
        System.out.println("CPU Capacity::"+resourceSummary.getCpuCapacityMHz()+" MHz");
        System.out.println("CPU used::"+resourceSummary.getCpuUsedMHz()+" MHz");
        System.out.println("Memory Capacity::"+resourceSummary.getMemCapacityMB()+" MB");
        System.out.println("Memory used::"+resourceSummary.getMemUsedMB()+" MB");
        System.out.println("Storage Capacity::"+resourceSummary.getStorageCapacityMB()+" MB");
        System.out.println("Storage used::"+resourceSummary.getStorageUsedMB()+" MB");
        si.getServerConnection().logout();
    }
}

Note:
– For the sake of simplicity, I have hard-coded DRS cluster name, you can change it based on your environment.
– You can scale the same code to all the clusters in a datacenter or multiple datacenter.

If you have still not setup your YAVI JAVA Eclipse environment:Getting started tutorial

Important tutorials to start with: Part I & Part II

VMware Rock Stars I get motivation from since I joined VMware

Recently I was going through some of the VMworld 2015 videos and I came across this interesting new concept this year i.e. VMware Rock Stars. I was very happy to see Duncan’s and William’s interview under this new concept as VMware Rockstars. For me both are the rock stars soon after I joined VMware around 2.5+ years back. I really enjoyed both the interviews and I thought it is worth to share with you all. I am sure, you will enjoy as well.

1. Duncan Epping, Chief Technologist

2. William Lam, Staff Engineer II

For all other super cool VMware related videos : CLICK HERE

Getting started with YAVI JAVA (Opensource JAVA SDK for VMware vSphere): Step by step guide for beginners

You might have read my last post on YAVI JAVA. In this post I am going to take you through setting up eclipse environment in order to get started with YAVI JAVA. This post is written by keeping not only existing VMware users in mind but also college students.

There are 4 ways listed here to get started with YAVI JAVA, one of the most used,easiest and quickest one is the first one i.e. obtaining YAVI JAVA package from Maven central repository. Here we go.

Step 1:: Download the Eclipse that has built in Maven integration. However, Maven is integrated with other IDEs such as NetBeans, Intelli IDEA etc. I like Eclipse so I am going to show you steps for eclipse, you could follow the same for other IDEs, it should work fine. Below is the Eclipse version I have downloaded which has Maven built in.
MavenEclipse

For getting started with YAVI JAVA, you are not required to be expert in Maven, even it is OK if you do not know anything about Maven. If you are interested, do read what is Maven here.

Step 2: Create a Maven project as shown in below screenshot.

Maven project

Step 3: Select the “Create Simple project” as shown below.

Maven_2

Step 4 : Next is to specify the Group id, Artifact id, version, Name etc. This can be anything of your choice as shown below and click on Finish.

Maven_3

Once clicked on FINISH, below is how it looks like when Maven project is created.

Maven_4

Step 5: Next we need to modify the POM.xml file. With every Maven project, one POM.xml file gets generated. Below is the overview of the existing POM.xml file got created when we created the project. POM.xml file is the one which tracks/resolves all the dependencies required for your project.

Maven_5

Step 6: Click on the dependencies tab in the bottom as shown below screenshot.

Maven_6

Now click on ADD button and enter the YAVI JAVA Maven group id, artifact id and version as shown in below screenshot
groupId : com.toastcoders
artifactId: yavijava
version :6.0.01 (or any YAVI JAVA version of your choice): Recommendation is to use latest available version on Maven central repository
Maven_9

Step 7: As soon as you click on OK in above step, make sure you can see entry in POM.xml file and required Maven dependencies jars as shown below.

Maven_10

That’s all. Now you are all set to play with new APIs introduced in vSphere 6.0. There are other 3 more ways to deploy the YAVI JAVA, if that works for you, please go ahead with that. Let me know if you face any issues.

All the samples and tutorials specified in this post will work just fine.

Note: YAVI JAVA supports VMware vSphere 4.0 and above (4.1, 5.0, 5.1, 5.5, 6.0).

Please do stay tuned for all the interesting samples on new features introduced in vSphere 6.0.

How to edit DRS VM VM affinity rules using vSphere API: Bit tricky solution

Recently I got a question through mail on how to edit DRS VM VM affinity rules? It is bit tricky to edit VM VM rules and vSphere API beginners are likely to get bit confused. Hence I thought its better write a program on the same which can be used as sample when anybody would like to edit DRS VM VM affinity rules.

Below is the complete code sample for the same. Please do modify this sample as per your need.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//:: # Author: Vikas Shitole
//:: # Website: www.vThinkBeyondVM.com
//:: # Product/Feature: vCenter Server/DRS
//:: # Description: Script to edit VM VM affinity rules

package com.vmware.yavijava;

import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;

import com.vmware.vim25.ArrayUpdateOperation;
import com.vmware.vim25.ClusterAffinityRuleSpec;
import com.vmware.vim25.ClusterAntiAffinityRuleSpec;
import com.vmware.vim25.ClusterConfigInfoEx;
import com.vmware.vim25.ClusterConfigSpec;
import com.vmware.vim25.ClusterRuleInfo;
import com.vmware.vim25.ClusterRuleSpec;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;
import com.vmware.vim25.mo.util.MorUtil;

public class EditVmVmDrsRule {

    public static void main(String[] args) throws InvalidProperty,
    RuntimeFault, RemoteException, MalformedURLException {
        ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1],
                args[2], true); // Pass 3 argument as vCenterIP/username/password
        String ClusterName = "Cluster"; // Cluster Name
        String VMToBeRemoved="VM1";
        String VMToBeAdded="VM3";
        Folder rootFolder = si.getRootFolder();
        VirtualMachine vm1 = (VirtualMachine) new InventoryNavigator(rootFolder)
        .searchManagedEntity("VirtualMachine", VMToBeRemoved);
        VirtualMachine vm2 = (VirtualMachine) new InventoryNavigator(rootFolder)
        .searchManagedEntity("VirtualMachine", VMToBeAdded);
        ManagedObjectReference vmMor1 = vm1.getMOR();
        ManagedObjectReference vmMor2 = vm2.getMOR();



        ClusterComputeResource cluster = null;
        cluster = (ClusterComputeResource) new InventoryNavigator(rootFolder)
        .searchManagedEntity("ClusterComputeResource", ClusterName);


        // Number of rules in a cluster
        ClusterRuleInfo[] ruleinfo = ((ClusterConfigInfoEx) cluster
                .getConfigurationEx()).getRule();


        if (ruleinfo == null || ruleinfo.length == 0) {
            System.out.println("There is no DRS rule in the cluster:: "
                    + cluster.getName());
        }

        for (ClusterRuleInfo rule : ruleinfo) {
            if (((rule instanceof ClusterAffinityRuleSpec)) && (rule.getName().equals("VM VM Rule"))){
                ManagedObjectReference[] vms=((ClusterAffinityRuleSpec) rule).getVm();
                for(ManagedObjectReference vm:vms){
                    if(vm.getVal().equals(vmMor1.getVal())){
                        //Removed the VM from rule
                        vms=(ManagedObjectReference[]) ArrayUtils.removeElement(vms, vm );
                        break;
                    }

                }
                //Added the new VM to the rule
                vms=(ManagedObjectReference[]) ArrayUtils.add(vms, vmMor2 );

                ClusterAffinityRuleSpec cars=(ClusterAffinityRuleSpec) rule;
                cars.setVm(vms);

                ClusterRuleSpec crs1 = new ClusterRuleSpec();
                crs1.setInfo(cars);
                crs1.setOperation(ArrayUpdateOperation.edit);

                ClusterConfigSpec ccs = new ClusterConfigSpec();
                ccs.setRulesSpec(new ClusterRuleSpec[]{crs1} );

                cluster.reconfigureCluster_Task(ccs, true);
                System.out.println("Rule reconfigured successfully ");

            }
        }

    }
}

Note:
– For the sake of simplicity, I have hard-coded VM names, you can change those based on your environment.
– Also you need resolve the dependency on apache.commons.lang in your java project. Let me know if you have any more doubts.

If you have still not setup your VI JAVA Eclipse environment:Getting started tutorial
Important tutorials to start with: Part I & Part II

One more exciting news: VI JAVA open source project is forked into YA VIJAVA(Yet another VI JAVA), it will have support to all the new APIs introduced in vSphere 6.0. VI JAVA itself works fine even on vSphere 6.0 (except the new features in vSphere 6.0).

Great news: YAVI JAVA : fork of VI JAVA open source project : Supports VMware vSphere 6.0

Since last stable vSphere 5.5 release of VI JAVA open source project , for more than 15+ months there was not any update on VI java, no any questions on the community were getting answered. There was lot of uncertainty among VI JAVA users on the future of the VI JAVA, discussions were picking up among VI JAVA on how to mitigate the impact if VI JAVA becomes dead and Michael Rice came to the rescue and puts the end to this speculation. He forked the VI JAVA project into YAVI JAVA (Yet Another VI JAVA) in order to give new life to this project which is for sure asset to many VMware users. I really appreciate the great proactive work done by Michael, YAVI JAVA is result of Machael’s dedication & passion for contributing to open source community. I am sure so many VI JAVA users have reason to celebrate this. I would like to thank other contributors as well. At the same time we just can not forget awesome work done by Steve Jin by leading VI JAVA project for several past releases. YAVI JAVA now available on GIT HUB and community contribution is getting increased. I would recommend all of you to spread the word about this project, start contributing, using and help in making this project a great success. Without community contribution, no open source project can become great. Along with supporting VMware vSphere 6.0, there are several new features added to YAVI JAVA, great thing about this project is: your old projects those developed using VI JAVA will work just fine. how cool it is!

Below are some of important hyperlinks about YAVI JAVA links, releases, tutorials, samples etc.

1. YAVI JAVA website

2. GIT HUB repository

3. Basic tutorials

4. All the releases of YAVI JAVA

5. All the Samples : Do not worry as I specified all these samples will just work fine on YAVI JAVA as well. Please stay tuned for my blogs on sample wrt to new APIs introduced in vSphere 6.0

Please do stay tuned for step by step getting started guide on YAVI JAVA.

How to get VMFS datastore UUIDs across all the datastores in a vCenter server using vSphere APIs

There are several vSphere API which requires vmfsUUID as one of its important properties. Some examples of such APIs are MountVmfsVolume(),mountVmfsVolumeEx(), UnmountForceMountedVmfsVolume(), unmapVmfsVolumeEx(), DeleteVmfsVolumeState(), unmountVmfsVolumeEx & unmountVmfsVolume(). Without vmfsUUID we can NOT operate on any of these APIs. Now question is how to get/know the UUID of the VMFS datastores connected to hosts using vSphere APIs. I thought its better to write the vSphere API script to solve this. The script that I am sharing is going to get all hosts and all of its associated datastores and each datastore and its associated UUID. Here we go.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.vmware.vijava;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.vmware.vim25.DatastoreInfo;
import com.vmware.vim25.VmfsDatastoreInfo;
import com.vmware.vim25.mo.Datastore;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostDatastoreBrowser;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;

public class findVMFSUUIDs {
    public static void main(String[] args) throws Exception {
        ServiceInstance si = new ServiceInstance(new URL(
                "https://10.120.30.40/sdk"), "administrator@vsphere.local",
                "Administrator!23", true);
        // Get the rootFolder
        Folder rootFolder = si.getRootFolder();

        // Get all the hosts in the vCenter server
        ManagedEntity[] hosts = new InventoryNavigator(rootFolder)
                .searchManagedEntities("HostSystem");

        if (hosts == null) {
            System.out.println("Host not found on vCenter");
            si.getServerConnection().logout();
            return;
        }

        // Map to store the datastore name as key and its UUID as the value
        Map< String , String> vmfsdatastoreUUIDs = new HashMap< String , String>();

        // Map to store host as key and all of its datastores as the value
        Map< ManagedEntity , Datastore[]> hostDatastores = new HashMap< ManagedEntity , Datastore[]>();
        for (ManagedEntity hostSystem : hosts) {
            HostDatastoreBrowser hdb = ((HostSystem) hostSystem)
                    .getDatastoreBrowser();
            Datastore[] ds = hdb.getDatastores();
            hostDatastores.put(hostSystem, ds);
        }

        System.out.println("Hosts and all of its associated datastores");
        for (Map.Entry < ManagedEntity , Datastore[]> datastores : hostDatastores
                .entrySet()) {
            System.out.println("");
            System.out.print("[" + datastores.getKey().getName() + "::");
            for (Datastore datastore : datastores.getValue()) {
                System.out.print(datastore.getName() + ",");
                DatastoreInfo dsinfo = datastore.getInfo();
                if (dsinfo instanceof VmfsDatastoreInfo) {
                    VmfsDatastoreInfo vdinfo = (VmfsDatastoreInfo) dsinfo;
                    vmfsdatastoreUUIDs.put(datastore.getName(), vdinfo
                            .getVmfs().getUuid());
                }

            }
            System.out.print("]");
        }
        System.out.println(" ");
        System.out.println("Datastore and its UUID");
        for (Map.Entry< String , String> dsuuid : vmfsdatastoreUUIDs.entrySet()) {
            System.out.println("[" + dsuuid.getKey() + "::" + dsuuid.getValue()
                    + "]");
        }

    }
}

Program Output::

Hosts and all of its associated datastores

[192.168.1.1::DS3,DS2,Local DS,DS4,NFS1,]
[192.168.1.2::LocalDS2,LocalDS1,LocalDS3,]

Datastore and its UUID

[LocalDS1::55d9b324-bad019fa-147a-f04da20356f7]
[Local DS::55b5dee1-ebd2895d-1263-002219574957]
[DS2::51e3e9f7-8ab3eac5-4715-00221957495d]
[LocalDS2::5592e051-da224dfc-ad16-f04da20356f7]
[LocalDS3::55d9b367-d145aef6-dcfe-f04da20356f7]
[DS3::51398f9b-e591008a-1b35-002219574a65]
[DS4::55cc410f-604db805-6fc0-002219574a65]

Now you could enhance this code to operate on any vSphere API that requires VMFS UUID as one of parameters. Please do comment if you have any doubts or need any help.

If you have still not setup your VI JAVA Eclipse environment:Getting started tutorial
Important tutorials to start with: Part I & Part II

Note: VI JAVA open source project is forked into YA VIJAVA(Yet another VI JAVA), it will have support to all the new APIs introduced in vSphere 6.0. VI JAVA itself works fine even on vSphere 6.0 (except the new features in vSphere 6.0). Please do stay tuned my post on YA VIJAVA.