VMworld 2009 - vSphere SDK Best Practices
Sunday, September 13, 2009
I've been back from San Francisco for a week now and finally have gotten around to writing up a note regarding my VMworld 2009 trip. My trip started off with Monday's Tech Exchange and continued with 3 more days of general VMworld sessions ranging from lower-level API discussions to high-level marketing speak. If I had to pick a favorite day, it would be the Tech Exchange. It really is geared toward developers. You get some great presentations and also a chance to meet those engineers whose APIs you might use (or frequently use as is my case). Here are some tidbits I picked up regarding performance counter queries in the vSphere Web Services SDK:
- First, when querying for performance counter information for a set of managed objects, there is no need to query for a
PerfProviderSummary
if all your managed objects are of the same entity type (e.g. VirtualMachine, ClusterComputeResource, etc.). A single query will suffice for an entity type as the "summary" will be the same for all entities of a single type. Here's a quick code snippet which shows how to retrieve aPerfProviderSummary
object for a particular managed object reference:
// The "entityMORef" variable is a ManagedObjectReferenceType for // any particular entity we are monitoring (e.g. VirtualMachine, // ResourcePool, etc.). // The "perfManager" variable is a reference to the PerformanceManager // retrieved as a property from the ServiceContent object. // The "_service" object is the VimService object. PerfProviderSummary summary = _service.QueryPerfProviderSummary(_sic.perfManager, entityMORef);
As in my case, if I'm querying for performance counters for a collection of 1,000 virtual machines, I only need to make this call once. Previously, I'd been invoking this method for all 1,000 virtual machines on the first iteration of the query. As you probably already know, if you are querying for performance counter information on a scheduled basis, there's no reason to make this call on every query iteration. Make the call to QueryPerfProviderSummary()
on the first query and then cache those summary objects away (in your PerfQuerySpec
object(s)) for use in later queries.
- Second, when querying for performance counter information be aware that said counters/metrics can change based on changes to the entity hardware. For example, let's say you have a virtual machine entity who currently isn't configured with any virtual disks. If you create a new virtual disk for this VM a number of new metrics will become available. Therefore you need to make sure you requery the performance counter metric IDs for this particular entity. This means a new call to the
QueryAvailablePerfMetric()
method so that any new (or missing)metricID
objects can be retrieved. Here's a sample of how to make this call:
// The "_service" object is the VimService object. // Let's collect performance metrics for the last 5 minutes. DateTime serverTime = _service.CurrentTime(serviceRef); DateTime startTime = _service.AddMinutes(0 - 5); DateTime endTime = serverTime; // Query all available metrics for the managed object reference int dataInterval = 30; // Note: this interval is for real-time metrics PerfMetricId[] aMetrics = null; try { aMetrics = _service.QueryAvailablePerfMetric(perfManagerRef, vmMORef, startTime, false, endTime, false, dataInterval, true); } catch (Exception) { // Some exception handling here... }
-
Lastly, if you are querying a large number of managed entities (e.g. 100+ virtual machines), it is better to use CSV format in your
PerfQuerySpec
objects and this reduces the overall object serialization. Metric information is returned in a comma-separated format and therefore the returned XML contains less objects. This is the object serialization reduction I just mentioned. You specify the counter query format in thePerfQuerySpec
object. Here's a sample of how to set this property:
PerfQuerySpec spec = new PerfQuerySpec(); spec.entity = vmMORef; spec.maxSample = 1; spec.maxSampleSpecified = true; spec.startTime = startTime; spec.startTimeSpecified = true; spec.endTime = endTime; spec.endTimeSpecified = true; spec.intervalId = dataInterval; spec.intervalIdSpecified = true; // Set your format to "csv" spec.format = "csv";
This last tidbit will improve your performance queries significantly. The only downside is that you now are required to parse the comma-separated values instead of iterating through an array of objects. I plan on implementing this last portion ASAP b/c I usually am querying in excess of 500 VMs frequently and this will help my query time significantly.
- Gilemonster
Labels: VMware
posted by Gilemonster @ 11:53 AM,