/*************************************************************************** * Copyright (c) 2012-2013 VMware, Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ package com.vmware.aurora.vc.test; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Map; import org.testng.annotations.Test; import com.vmware.aurora.vc.MoUtil; import com.vmware.aurora.vc.VcCache; import com.vmware.aurora.vc.VcCluster; import com.vmware.aurora.vc.VcInventory; import com.vmware.aurora.vc.VcPerformance; import com.vmware.aurora.vc.VcPerformance.PerformanceSample; import com.vmware.aurora.vc.VcPerformance.PerformanceType; import com.vmware.aurora.vc.VcResourcePool; import com.vmware.aurora.vc.vcservice.VcContext; import com.vmware.aurora.vc.vcservice.VcService; import com.vmware.vim.binding.vim.Datacenter; import com.vmware.vim.binding.vim.ElementDescription; import com.vmware.vim.binding.vim.Folder; import com.vmware.vim.binding.vim.PerformanceManager; import com.vmware.vim.binding.vim.PerformanceManager.CounterInfo; import com.vmware.vim.binding.vim.VirtualApp; import com.vmware.vim.binding.vim.VirtualMachine; import com.vmware.vim.binding.vmodl.ManagedObjectReference; /** * Test code to develop VcPerformance class. */ public class VcPerformanceTest extends AbstractVcTest { /** * Returns all datacenters in the root folder. */ public static List<Datacenter> getDatacenters() throws Exception { Folder rootFolder = MoUtil.getRootFolder(); List<Datacenter> dcList = MoUtil.getChildEntity(rootFolder, Datacenter.class); return dcList; } /** * Returns all resource pools in the data center. */ public static List<VcResourcePool> getResourcePools(VcCluster cluster) throws Exception { return cluster.getAllRPs(); } /** * Returns all virtual machines in the data center. */ public static List<VirtualMachine> getVirtualMachines(Datacenter dc) throws Exception { Folder vmFolder = MoUtil.getManagedObject(dc.getVmFolder()); List<VirtualMachine> list = MoUtil.getChildEntity(vmFolder, VirtualMachine.class); return list; } private VcPerformance vcp = new VcPerformance(); /** * Tests VcPerformance.queryPerformance for both VMs and RPs * @throws Exception */ @Test public void testGetPerformance() throws Exception { //enumClusterPerformance(); //dumpCounters(); //dumpFailingRPs(); //watchSingleRP("null:ResourcePool:resgroup-4506", 120, 10000); // every 10 seconds for 20 minutes enumClusterLatestPerformance(); } public void enumClusterPerformance() throws Exception { System.out.println("Service url is: " + vcService.getServiceUrl()); System.out.println("Supported aggregated sampling intervals: " + listToString(vcp.getHistoricalIntervals())); // iterate clusters to iterate resource pools for (VcCluster cluster : VcInventory.getClusters()) { System.out.println("CL " + cluster); for (VcResourcePool rp: getResourcePools(cluster)) { System.out.println(" RP " + rp + ":"); String refId = rp.getId(); try { String perf; Integer[] intervals = vcp.getAllSamplingIntervals(rp.getId()); int resolution = intervals[0]; // fastest sampling supported //System.out.println(" supports sampling intervals: " + listToString(intervals)); Calendar start = vcp.queryVcCurrentTime(); start.add(Calendar.MINUTE, -60); // XXX: queries for < 30 minutes are returning nothing for RPs (but work for VMs) Calendar end = null; System.out.println(String.format(" %s from %s to %s", refId, new SimpleDateFormat().format(start.getTime()), new SimpleDateFormat().format(vcp.queryVcCurrentTime().getTime()))); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.cpuAbs, resolution, 0, start, end)); System.out.println(" cpu performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memOccupiedAbs, resolution, 0, start, end)); System.out.println(" mem-occupy performance samples: " + perf); // vApps are enumerated as RPs, but don't support mem.cap.usage, so don't try this on them if (!MoUtil.isOfType(refId, VirtualApp.class)) { perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memActiveAbs, resolution, 0, start, end)); System.out.println(" mem-active performance samples: " + perf); } // Note: RP doesn't implement relative stats (cpu::usage or mem::usage), or mem::active, or net::anything List<String> ids = new ArrayList<String>(); ids.add(refId); Map<String, PerformanceSample> result = vcp.queryLatestPerformance(ids, PerformanceType.cpuAbs); PerformanceSample sample= result.get(refId); perf = (sample == null ? "unavailable" : sample.toString()); System.out.println(" latest cpu sample: " + perf); } catch (Exception e) { System.out.println(" perf query failed: " + e.getMessage()); } } } // iterate datacenters to iterate virtual machines for (Datacenter dc : getDatacenters()) { System.out.println("DC " + dc); for (VirtualMachine vm: getVirtualMachines(dc)) { // Skip templates, which can't be powered on and have no associated performance data if (vm.getConfig().isTemplate()) { continue; } System.out.println("VM " + vm.getName() + ":"); String refId = MoUtil.morefToString(vm._getRef()); try { String perf; Integer[] intervals = vcp.getAllSamplingIntervals(refId); int resolution = intervals[0]; // fastest sampling supported //System.out.println(" supports sampling intervals: " + listToString(intervals)); // NB: if you pass times (relative to present, minutes ago) 0,0 (all recent samples): get lots, some are very recent // if you pass 60,0 (all samples in last hour): tend to get 11 samples, missing recent one, newest sample can be 9 minutes old // if you pass 30,0 (all samples in last half hour): tend to get 5 samples, missing recent one, newest sample can be 9 minutes old; optimization not kicking in // if you pass 25,0 (all samples in last 25 min): get 5 samples, including most recent; the "optimization" apparently kicks in // best realtime query might be for 5,0? But that involves knowing the interval; our API should have a way to get just newest sample without knowing interval. // Anyway, note that 0,0, <30,0 and >30,0 are really different queries. Calendar start = vcp.queryVcCurrentTime(); start.add(Calendar.MINUTE, -20); Calendar end = null; perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.cpuAbs, resolution, 0, start, end)); System.out.println(" cpu performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.cpuRel, resolution, 0, start, end)); System.out.println(" cpu performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memOccupiedAbs, resolution, 0, start, end)); System.out.println(" mem-occupy performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memActiveAbs, resolution, 0, start, end)); System.out.println(" mem-active performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memActiveRel, resolution, 0, start, end)); System.out.println(" mem-active performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.netAbs, resolution, 0, start, end)); System.out.println(" net performance samples: " + perf); List<String> ids = new ArrayList<String>(); ids.add(refId); Map<String, PerformanceSample> result = vcp.queryLatestPerformance(ids, PerformanceType.cpuAbs); PerformanceSample sample= result.get(refId); perf = (sample == null ? "unavailable" : sample.toString()); System.out.println(" latest cpu sample: " + perf); } catch (Exception e) { System.out.println(" perf query failed: " + e.getMessage()); } } } } private void evalLatestSamples(String refId, int resolution, Calendar start, Calendar end) { try { String perf; System.out.println(String.format(" %s from %s to %s", refId, new SimpleDateFormat().format(start.getTime()), new SimpleDateFormat().format(vcp.queryVcCurrentTime().getTime()))); PerformanceSample[] samples = vcp.queryPerformance(refId, PerformanceType.cpuAbs, resolution, 0, start, end); if (samples.length < 2) { System.out.println(" no samples in window"); } else { PerformanceSample[] slice = new PerformanceSample[2]; slice[0] = samples[samples.length - 2]; slice[1] = samples[samples.length - 1]; perf = samplesToString(slice); System.out.println(" last 2 cpu performance samples: " + perf); List<String> ids = new ArrayList<String>(); ids.add(refId); Map<String, PerformanceSample> result = vcp.queryLatestPerformance(ids, PerformanceType.cpuAbs); PerformanceSample sample= result.get(refId); perf = (sample == null ? "unavailable" : sample.toString()); System.out.println(" 'latest' cpu sample: " + perf); if (sample.getTimestamp().equals(slice[1].getTimestamp())) { // we kept the newest sample System.out.println("tie! kept newest sample"); } else if (slice[1].getSample() == 0 && sample.getSample() != 0) { // newest sample is 0, but we didn't use it System.out.println("win! avoided invalid 0 sample"); } else if (slice[1].getSample() != 0 && sample.getTimestamp().equals(slice[0].getTimestamp())) { // latest sample is nonzero, and we didn't use it System.out.println("fail! had to skip a valid sample"); } else { // logic error System.out.println("inconceivable! not sure how to judge that one"); } } } catch (Exception e) { System.out.println(" perf query failed: " + e.getMessage()); } } public void enumClusterLatestPerformance() throws Exception { System.out.println("Service url is: " + vcService.getServiceUrl()); System.out.println("Supported aggregated sampling intervals: " + listToString(vcp.getHistoricalIntervals())); // iterate clusters to iterate resource pools for (VcCluster cluster : VcInventory.getClusters()) { System.out.println("CL " + cluster); for (VcResourcePool rp: getResourcePools(cluster)) { System.out.println(" RP " + rp + ":"); String refId = rp.getId(); Integer[] intervals = vcp.getAllSamplingIntervals(rp.getId()); int resolution = intervals[0]; // fastest sampling supported Calendar start = vcp.queryVcCurrentTime(); start.add(Calendar.MINUTE, -60); // XXX: queries for < 30 minutes are returning nothing for RPs (but work for VMs) Calendar end = null; evalLatestSamples(refId, resolution, start, end); } } // iterate datacenters to iterate virtual machines for (Datacenter dc : getDatacenters()) { System.out.println("DC " + dc); for (VirtualMachine vm: getVirtualMachines(dc)) { // Skip templates, which can't be powered on and have no associated performance data if (vm.getConfig().isTemplate()) { continue; } System.out.println("VM " + vm.getName() + ":"); String refId = MoUtil.morefToString(vm._getRef()); Integer[] intervals = vcp.getAllSamplingIntervals(refId); int resolution = intervals[0]; // fastest sampling supported Calendar start = vcp.queryVcCurrentTime(); start.add(Calendar.MINUTE, -20); Calendar end = null; evalLatestSamples(refId, resolution, start, end); } } } public void dumpCounters() throws Exception { VcService vcService = VcContext.getService(); ManagedObjectReference pmRef= vcService.getServiceInstanceContent().getPerfManager(); PerformanceManager perfMgr = MoUtil.getManagedObject(pmRef); CounterInfo[] allCounters = perfMgr.getPerfCounter(); for (CounterInfo c: allCounters) { int key = c.getKey(); String group = formatElementInfo(c.getGroupInfo()); String name = formatElementInfo(c.getNameInfo()); String unit = formatElementInfo(c.getUnitInfo()); String type = c.getStatsType().toString(); System.out.println(String.format("Counter %d: %s: group=%s, name=%s, unit=%s", key, type, group, name, unit)); } } public void dumpFailingRPs() throws Exception { /* * Print a list of RPs for which queryLatestPerformance() fails (which could mean queryPerformance() threw * an exception for any of the reasons it could do so, but most likely means it returned 0 samples, in * which case queryLatestPerformance will throw its own exception). * * In practice, this seems to happen for RPs with no powered-on VMs (as direct children or descendants). */ System.out.println("Service url is: " + vcService.getServiceUrl()); System.out.println("Supported aggregated sampling intervals: " + listToString(vcp.getHistoricalIntervals())); for (Datacenter dc : getDatacenters()) { System.out.println("DC " + dc); for (VcCluster cluster : VcInventory.getClusters()) { System.out.println("CL " + cluster); for (VcResourcePool rp: getResourcePools(cluster)) { String refId = rp.getId(); List<String> ids = new ArrayList<String>(); ids.add(refId); Map<String, PerformanceSample> result = vcp.queryLatestPerformance(ids, PerformanceType.cpuAbs); PerformanceSample sample= result.get(refId); if (null == sample) { System.out.println(" FAILED: " + rp); } } } } } public void watchSingleRP(String refId, int repeatCount, int delayMs) throws Exception { VcResourcePool rp = VcCache.get(refId); int resolution = vcp.getAllSamplingIntervals(rp.getId())[0]; System.out.println(String.format("Watching %s every %d seconds for %d repetitions", refId, delayMs / 1000, repeatCount)); for (int i = 0; i < repeatCount; i++) { Calendar start = vcp.queryVcCurrentTime(); start.add(Calendar.MINUTE, -60); // XXX: queries for < 30 minutes return nothing for RPs Calendar end = vcp.queryVcCurrentTime(); System.out.println(String.format(" %s from %s to %s", refId, new SimpleDateFormat().format(start.getTime()), new SimpleDateFormat().format(end.getTime()))); String perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.cpuAbs, resolution, 0, start, end)); System.out.println(" cpu performance samples: " + perf); perf = samplesToString(vcp.queryPerformance(refId, PerformanceType.memOccupiedAbs, resolution, 0, start, end)); System.out.println(" mem performance samples: " + perf); Thread.sleep(delayMs); } } String formatElementInfo(ElementDescription e) { return String.format("(%s, %s, %s)", e.getKey(), e.getLabel(), e.getSummary()); } private static String samplesToString(PerformanceSample[] samples) { return samples.length + " samples: " + listToString(samples); } private static String listToString(Object[] list) { String s = ""; for (Object item: list) { if (s.length() > 0) { s += ", "; } s += item.toString(); } return s; } }