/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.plugin.vmware;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.hyperic.sigar.vmware.VM;
import org.hyperic.sigar.vmware.VMwareException;
import org.hyperic.sigar.vmware.VMwareServer;
import org.hyperic.hq.product.Metric;
public class VMwareMetrics extends HashMap {
//XXX need to refactor after moving from MeasurementPlugin to Collector
private static final Double NO_VALUE = new Double(Double.NaN);
private static final String CPU_NUMBER = "cpu.number";
private static final String SYS_CPU_NUMBER = "system." + CPU_NUMBER;
private static final String[] VM_VARS = {
"mem.shares", "mem.min", "mem.max", "mem.size", "mem.memctl",
"mem.swapped", "mem.shared", "mem.active", "mem.overhd"
};
private static final String[] VM_CPU_VARS = {
"syssec", "usedsec", "waitsec"
};
private static final String[] VM_DISK_VARS = {
"reads", "writes", "KBread", "KBwritten",
};
private static final String[] VM_NET_VARS = {
"totPktsTx", "totPktsRx", "totKBTx", "totKBRx"
};
private static final String[] SERVER_CPU_VARS = {
"idlesec", "usedsec"
};
private static final String[] SERVER_VARS = {
"system.mem.avail", "system.mem.size", "system.mem.active"
};
private static final long EXPIRE = (60 * 1000) * 5;
private static Map cache = new HashMap();
private long timestamp = 0;
static String getResource(VM vm, String var)
throws VMwareException {
try {
return vm.getResource(var);
} catch (VMwareException e) {
throw new VMwareException(e.getMessage() + ": " + var);
}
}
static String getResource(VMwareServer server, String var)
throws VMwareException {
try {
return server.getResource(var);
} catch (VMwareException e) {
throw new VMwareException(e.getMessage() + ": " + var);
}
}
private static void getResourceVars(VM vm, String[] vars, Map metrics)
throws VMwareException {
for (int i=0; i<vars.length; i++) {
String var = vars[i];
try {
metrics.put(var, getResource(vm, var));
} catch (VMwareException e) {
metrics.put(var, NO_VALUE);
}
}
}
private static void getCPUVars(VMwareServer server,
String[] vars, Map metrics) {
final String prefix = "system.cpu.";
try {
String cpu = getResource(server, SYS_CPU_NUMBER);
int num = Integer.parseInt(cpu);
metrics.put(SYS_CPU_NUMBER, cpu);
for (int i=0; i<vars.length; i++) {
double val = 0;
for (int j=0; j<num; j++) {
String ix = prefix + j + "." + vars[i];
try {
String rval = getResource(server, ix);
val += Double.parseDouble(rval);
} catch (VMwareException e) {
}
}
metrics.put(prefix + vars[i], String.valueOf(val));
}
} catch (VMwareException e) {
}
}
private static void getCPUVars(VM vm, String[] vars, Map metrics) {
final String prefix = "cpu.";
try {
String cpu = getResource(vm, CPU_NUMBER);
int num = Integer.parseInt(cpu);
metrics.put(CPU_NUMBER, cpu);
for (int i=0; i<vars.length; i++) {
double val = 0;
for (int j=0; j<num; j++) {
String ix = prefix + j + "." + vars[i];
try {
String rval = getResource(vm, ix);
val += Double.parseDouble(rval);
} catch (VMwareException e) {
}
}
metrics.put(prefix + vars[i], String.valueOf(val));
}
} catch (VMwareException e) {
}
}
private static void getDeviceVars(VM vm, String[] vars, Map metrics,
String device)
throws VMwareException {
for (int i=0; i<vars.length; i++) {
String var = device + "." + vars[i];
try {
metrics.put(var, getResource(vm, var));
} catch (VMwareException e) {
metrics.put(var, NO_VALUE);
}
}
}
public static Map getInstance(Properties props)
throws VMwareException {
synchronized (VMwareConnectParams.LOCK) {
return getMetrics(props);
}
}
private static Map getMetrics(Properties props)
throws VMwareException {
VMwareMetrics metrics = (VMwareMetrics)cache.get(props);
if (metrics == null) {
metrics = new VMwareMetrics();
cache.put(props, metrics);
}
long timeNow = System.currentTimeMillis();
if ((timeNow - metrics.timestamp) < EXPIRE) {
return metrics;
}
VMwareConnectParams params =
new VMwareConnectParams(props);
VMwareServer server = new VMwareServer();
server.connect(params);
for (int i=0; i<SERVER_VARS.length; i++) {
String var = SERVER_VARS[i];
metrics.put(var, getResource(server, var));
}
getCPUVars(server, SERVER_CPU_VARS, metrics);
metrics.timestamp = timeNow;
server.disconnect();
server.dispose();
return metrics;
}
public static Map getInstance(Properties props,
String config)
throws VMwareException {
synchronized (VMwareConnectParams.LOCK) {
return getMetrics(props, config);
}
}
private static Map getMetrics(Properties props,
String config)
throws VMwareException {
Double up = new Double(Metric.AVAIL_UP);
VMwareMetrics metrics = (VMwareMetrics)cache.get(config);
if (metrics == null) {
metrics = new VMwareMetrics();
cache.put(config, metrics);
}
long timeNow = System.currentTimeMillis();
if ((timeNow - metrics.timestamp) < EXPIRE) {
return metrics;
}
VMwareConnectParams params =
new VMwareConnectParams(props);
VM vm = new VM();
vm.connect(params, config);
boolean isOn=false, isESX;
double avail;
switch (vm.getExecutionState()) {
case VM.EXECUTION_STATE_ON:
isOn = true;
avail = Metric.AVAIL_UP;
break;
case VM.EXECUTION_STATE_OFF:
avail = Metric.AVAIL_DOWN;
break;
case VM.EXECUTION_STATE_STUCK:
avail = Metric.AVAIL_WARN;
break;
case VM.EXECUTION_STATE_SUSPENDED:
avail = Metric.AVAIL_PAUSED;
break;
case VM.EXECUTION_STATE_UNKNOWN:
default:
avail = Metric.AVAIL_UNKNOWN;
break;
}
metrics.put("State", new Double(avail));
isESX =
vm.getProductInfo(VM.PRODINFO_PRODUCT) == VM.PRODUCT_ESX;
if (isOn) {
if (isESX) {
/* GSX does not support these metrics */
getResourceVars(vm, VM_VARS, metrics);
getCPUVars(vm, VM_CPU_VARS, metrics);
List disks = VMwareDetector.getDisks(vm);
for (int i=0; i<disks.size(); i++) {
String disk = "disk." + disks.get(i);
metrics.put(disk + ".avail", up);
getDeviceVars(vm, VM_DISK_VARS, metrics, disk);
}
List nics = VMwareDetector.getNICs(vm);
for (int i=0; i<nics.size(); i++) {
String nic = "net." + nics.get(i);
metrics.put(nic + ".avail", up);
getDeviceVars(vm, VM_NET_VARS, metrics, nic);
}
metrics.put("Uptime",
new Double(vm.getUptime()));
}
}
metrics.timestamp = timeNow;
vm.disconnect();
vm.dispose();
return metrics;
}
}