I am working on adding some functionality to the FlashArray workflow package for vRealize Orchestrator and one of those features is automating the process to increase the capacity of a VMFS volume. The FlashArray potion of that is pretty straight forward but what of the VMFS portion? Not much on the internet directly about this. Luckily using the vCenter SDK with vRO, this is pretty easy.
There is really only one piece of information that you need a user to specify, and that is the datastore that is to be re-sized. From that you can figure everything else out.
vRealize Orchestrator uses Javascript as a scripting language so all of this will be done with that. A great resource for the vSphere API specifically in context to vRO is https://www.vroapi.com/.
When you have a datastore passed into the workflow, it is stored in memory to be referenced by the Javascript as a custom vCenter Datastore object (information can be found here).
Looking at the spec for that object, you can see the various information it stores/references. One of those being the hosts that see the datastore. The expand operation is done by a ESXi host, so we need to choose one. For my purposes I just choose the first in that array of hosts.
We want the vcHostSystem object, but the host array is not an array of those, it is an array of keys that then contains (points to) those objects.
So each object in the array will have an attribute “key” which points to the vcHostSystem (the ESXi server) and the mountinfo. We want the former. To store the first one in a variable I have my first line of Javascript as so:
1 |
var esxihost = datastore.host[0].key; |
Replace 0 with 1 to get the second host, etc. etc.
So I stored it in a variable esxihost. If you need to rescan that host you can pass it to the vCenter vRO module for rescanning:
1 |
System.getModule(“com.vmware.library.vc.storage”).rescanAll(esxihost); |
Now you need to get the information for the new partition on the device. ESXi has a handy method for this called queryVmfsDatastoreExpandOptions. When run against a datastore object, it will return the options you have for expanding that datastore. Either creating a new partition and adding it as a new extent (no thank you!) or expanding the current partition to consume it (yes!). This will give you the partition information that is needed for the expansion operation. See some information about this method here:
All you need to do to run this is pass in the datastore object. queryVmfsDatastoreExpandOption is a method available from the “datastore subsystem” of the ESXi host. We could run this in one command from what we have like so:
1 |
var expandSpec = esxihost.configManager.datastoreSystem.queryVmfsDatastoreExpandOptions(datastore); |
but for readability, I prefer to make this into two lines, by storing the datastoreSystem in a variable first and calling the method directly from it:
1 2 3 |
var datastoreSystem = esxihost.configManager.datastoreSystem; var expandSpec = datastoreSystem.queryVmfsDatastoreExpandOptions(datastore); |
I store the partition information in a variable called expandSpec. Looking at the spec for this method, you can see it returns the following:
vcVmfsDatastoreOption. This is the custom object it returns that has all of the information we need. So how about running the expansion? We have all of the information we need. The expansion method is called expandVmfsDatastore. Simple enough. We can see the SDK info here:
It takes in two things, the datastore and something called vcVmfsDatastoreExpandSpec. So the second one is new, that isn’t what is stored in my expandSpec variable, that is of type vcVmfsDatastoreOption. So how to we get vcVmfsDatastoreExpandSpec? Well it is part of vcVmfsDatastoreOption!
So our variable called expandSpec contains this! So instead of passing the whole thing we specify the right part. So expandSpec.spec, which is the name of the location where the object of type vcVmfsDatastoreExpandSpec is stored. We can re-use our variable hosting the storage system, because that is also where the expandVmfsDatastore method is called from.
1 |
datastoreSystem.expandVmfsDatastore(datastore, expandSpec[0].spec); |
You will note that I had to call expandSpec as an array (using [0]). This is because it is an array! This is very easy to miss, because 99.99% of the time this will be an array with only one top-level object. So if you just use expandSpec.spec you will get “undefined” errors. Took me quite some time to catch.
That will expand our datastore. Done! If this host is in a vCenter cluster you will see it rescan the other hosts automatically to see the new VMFS size. If you have hosts elsewhere that see the datastore, you might want to add logic to rescan those too.
In vCenter you will see the “Expand VMFS Datastore” event complete.
All of the Javascript that I used to do this is here. Some extra logging mainly and I am outputting the new datastore object out in a variable named newDatastore. No error handling right now, to make it easier to understand.
1 2 3 4 5 6 7 8 |
var esxihost = datastore.host[0].key; System.log(“Rescanning ESXi host “ + esxihost.name); System.getModule(“com.vmware.library.vc.storage”).rescanAll(esxihost); var datastoreSystem = esxihost.configManager.datastoreSystem; var expandSpec = datastoreSystem.queryVmfsDatastoreExpandOptions(datastore); newDatastore = datastoreSystem.expandVmfsDatastore(datastore, expandSpec[0].spec); newSize = (newDatastore.info.vmfs.capacity / 1024 / 1024 /1024); System.log(“New capacity for datastore “ + newDatastore.name + ” is “ + newSize + ” GB”); |
The workflow object looks like so. Only really three screens of changes. One input (the datastore), one output (the same datastore but with updated size) and the script:
This workflow does the following:
- Takes in a datastore
- Finds the new capacity information (this assumes the physical device has already been increased in capacity)
- Expands the VMFS partition to use it all
- Rescans the cluster for the host used to expand
- Returns the new datastore object. Logs the host used and the new size.
So if we were to run this: