diff --git a/api/src/com/cloud/network/as/AutoScaleCounter.java b/api/src/com/cloud/network/as/AutoScaleCounter.java
index 57539729934..f25d6699a00 100644
--- a/api/src/com/cloud/network/as/AutoScaleCounter.java
+++ b/api/src/com/cloud/network/as/AutoScaleCounter.java
@@ -27,6 +27,8 @@ public class AutoScaleCounter {
public static final AutoScaleCounterType Snmp = new AutoScaleCounterType("snmp");
public static final AutoScaleCounterType Netscaler = new AutoScaleCounterType("netscaler");
+ public static final AutoScaleCounterType Cpu = new AutoScaleCounterType("cpu");
+ public static final AutoScaleCounterType Memory = new AutoScaleCounterType("memory");
public AutoScaleCounterType(String name) {
_name = name;
diff --git a/api/src/com/cloud/network/as/AutoScalePolicy.java b/api/src/com/cloud/network/as/AutoScalePolicy.java
index 434220a4c8d..8452ba1492c 100644
--- a/api/src/com/cloud/network/as/AutoScalePolicy.java
+++ b/api/src/com/cloud/network/as/AutoScalePolicy.java
@@ -17,6 +17,8 @@
package com.cloud.network.as;
+import java.util.Date;
+
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -30,6 +32,8 @@ public interface AutoScalePolicy extends ControlledEntity, InternalIdentity {
public int getDuration();
public int getQuietTime();
+
+ public Date getLastQuiteTime();
public String getAction();
diff --git a/api/src/com/cloud/network/as/AutoScaleVmGroup.java b/api/src/com/cloud/network/as/AutoScaleVmGroup.java
index 3e07fe44fb0..15f7bea9a4d 100644
--- a/api/src/com/cloud/network/as/AutoScaleVmGroup.java
+++ b/api/src/com/cloud/network/as/AutoScaleVmGroup.java
@@ -17,6 +17,8 @@
package com.cloud.network.as;
+import java.util.Date;
+
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -45,6 +47,8 @@ public interface AutoScaleVmGroup extends ControlledEntity, InternalIdentity {
int getInterval();
+ Date getLastInterval();
+
String getState();
String getUuid();
diff --git a/api/src/com/cloud/network/as/Counter.java b/api/src/com/cloud/network/as/Counter.java
index 46585f39679..99b3364419a 100644
--- a/api/src/com/cloud/network/as/Counter.java
+++ b/api/src/com/cloud/network/as/Counter.java
@@ -23,7 +23,10 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface Counter extends InternalIdentity, Identity {
public static enum Source {
- netscaler, snmp
+ netscaler,
+ snmp,
+ cpu,
+ memory
}
String getName();
@@ -31,4 +34,5 @@ public interface Counter extends InternalIdentity, Identity {
String getValue();
Source getSource();
+
}
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
new file mode 100644
index 00000000000..41fb4b32446
--- /dev/null
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -0,0 +1,956 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.cloudstack.framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/com/cloud/agent/api/PerformanceMonitorAnswer.java b/core/src/com/cloud/agent/api/PerformanceMonitorAnswer.java
new file mode 100644
index 00000000000..931e2377002
--- /dev/null
+++ b/core/src/com/cloud/agent/api/PerformanceMonitorAnswer.java
@@ -0,0 +1,11 @@
+package com.cloud.agent.api;
+
+public class PerformanceMonitorAnswer extends Answer {
+ public PerformanceMonitorAnswer() {
+ }
+
+ public PerformanceMonitorAnswer(PerformanceMonitorCommand cmd,
+ boolean result, String details) {
+ super(cmd, result, details);
+ }
+}
diff --git a/core/src/com/cloud/agent/api/PerformanceMonitorCommand.java b/core/src/com/cloud/agent/api/PerformanceMonitorCommand.java
new file mode 100644
index 00000000000..41a794543d8
--- /dev/null
+++ b/core/src/com/cloud/agent/api/PerformanceMonitorCommand.java
@@ -0,0 +1,30 @@
+package com.cloud.agent.api;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PerformanceMonitorCommand extends Command {
+
+ Map params = new HashMap();
+
+ public PerformanceMonitorCommand() {
+ }
+
+ public PerformanceMonitorCommand(Map params, int wait) {
+ setWait(wait);
+ this.params = params;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+
+ public Map getParams() {
+ return params;
+ }
+
+ public void setParams(Map params) {
+ this.params = params;
+ }
+}
diff --git a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java
index fbaf8e94d03..6a104c2cb3e 100644
--- a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java
+++ b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java
@@ -27,6 +27,8 @@ import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
import org.apache.cloudstack.api.InternalIdentity;
@@ -57,6 +59,10 @@ public class AutoScalePolicyVO implements AutoScalePolicy, InternalIdentity {
@Column(name = "quiet_time", updatable = true, nullable = false)
private int quietTime;
+ @Column(name = "last_quiet_time", updatable = true)
+ @Temporal(value = TemporalType.TIMESTAMP)
+ private Date lastQuiteTime;
+
@Column(name = "action", updatable = false, nullable = false)
private String action;
@@ -69,12 +75,14 @@ public class AutoScalePolicyVO implements AutoScalePolicy, InternalIdentity {
public AutoScalePolicyVO() {
}
- public AutoScalePolicyVO(long domainId, long accountId, int duration, int quietTime, String action) {
+ public AutoScalePolicyVO(long domainId, long accountId, int duration,
+ int quietTime, Date lastQuiteTime, String action) {
this.uuid = UUID.randomUUID().toString();
this.domainId = domainId;
this.accountId = accountId;
this.duration = duration;
this.quietTime = quietTime;
+ this.lastQuiteTime = lastQuiteTime;
this.action = action;
}
@@ -113,6 +121,11 @@ public class AutoScalePolicyVO implements AutoScalePolicy, InternalIdentity {
return quietTime;
}
+ @Override
+ public Date getLastQuiteTime() {
+ return lastQuiteTime;
+ }
+
@Override
public String getAction() {
return action;
@@ -133,4 +146,8 @@ public class AutoScalePolicyVO implements AutoScalePolicy, InternalIdentity {
public void setQuietTime(Integer quietTime) {
this.quietTime = quietTime;
}
+
+ public void setLastQuiteTime(Date lastQuiteTime) {
+ this.lastQuiteTime = lastQuiteTime;
+ }
}
diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java
index 4eed0863dd0..4d41583fd84 100644
--- a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java
+++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java
@@ -27,6 +27,8 @@ import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
import org.apache.cloudstack.api.InternalIdentity;
@@ -69,6 +71,10 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
@Column(name = "interval")
private int interval;
+ @Column(name = "last_interval", updatable = true)
+ @Temporal(value = TemporalType.TIMESTAMP)
+ private Date lastInterval;
+
@Column(name = "profile_id")
private long profileId;
@@ -84,8 +90,10 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
public AutoScaleVmGroupVO() {
}
- public AutoScaleVmGroupVO(long lbRuleId, long zoneId, long domainId, long accountId, int minMembers, int maxMembers, int memberPort, int interval, long profileId,
- String state) {
+ public AutoScaleVmGroupVO(long lbRuleId, long zoneId, long domainId,
+ long accountId, int minMembers, int maxMembers, int memberPort,
+ int interval, Date lastInterval, long profileId, String state) {
+
this.uuid = UUID.randomUUID().toString();
this.loadBalancerId = lbRuleId;
this.minMembers = minMembers;
@@ -97,6 +105,7 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
this.zoneId = zoneId;
this.state = state;
this.interval = interval;
+ this.lastInterval = lastInterval;
}
@Override
@@ -148,6 +157,11 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
return interval;
}
+ @Override
+ public Date getLastInterval() {
+ return lastInterval;
+ }
+
@Override
public long getProfileId() {
return profileId;
@@ -182,6 +196,10 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
this.interval = interval;
}
+ public void setLastInterval(Date lastInterval) {
+ this.lastInterval = lastInterval;
+ }
+
public void setLoadBalancerId(Long loadBalancerId) {
this.loadBalancerId = loadBalancerId;
}
diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVmMapVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVmMapVO.java
new file mode 100644
index 00000000000..30a89f36c72
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVmMapVO.java
@@ -0,0 +1,46 @@
+package com.cloud.network.as;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = ("autoscale_vmgroup_vm_map"))
+public class AutoScaleVmGroupVmMapVO implements InternalIdentity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "vmgroup_id")
+ private long vmGroupId;
+
+ @Column(name = "instance_id")
+ private long instanceId;
+
+ public AutoScaleVmGroupVmMapVO() {
+ }
+
+ public AutoScaleVmGroupVmMapVO(long vmGroupId, long instanceId) {
+ this.vmGroupId = vmGroupId;
+ this.instanceId = instanceId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getVmGroupId() {
+ return vmGroupId;
+ }
+
+ public long getInstanceId() {
+ return instanceId;
+ }
+
+}
diff --git a/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDao.java b/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDao.java
index f0b2f5568c7..a9cfd188cc2 100644
--- a/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDao.java
+++ b/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDao.java
@@ -26,5 +26,7 @@ public interface AutoScalePolicyConditionMapDao extends GenericDao findByPolicyId(long id);
}
diff --git a/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDaoImpl.java b/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDaoImpl.java
index 5933f36b8f7..557a6731af0 100644
--- a/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDaoImpl.java
+++ b/engine/schema/src/com/cloud/network/as/dao/AutoScalePolicyConditionMapDaoImpl.java
@@ -56,6 +56,14 @@ public class AutoScalePolicyConditionMapDaoImpl extends GenericDaoBase sc = createSearchCriteria();
sc.addAnd("policyId", SearchCriteria.Op.EQ, policyId);
- return expunge(sc) > 0;
- }
+ return expunge(sc) > 0;
+ }
+
+ @Override
+ public List findByPolicyId(long policyId) {
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("policyId", SearchCriteria.Op.EQ, policyId);
+
+ return listBy(sc);
+ }
}
diff --git a/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java b/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java
new file mode 100644
index 00000000000..1a080adb163
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java
@@ -0,0 +1,15 @@
+package com.cloud.network.as.dao;
+
+import java.util.List;
+
+import com.cloud.network.as.AutoScaleVmGroupVmMapVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface AutoScaleVmGroupVmMapDao extends GenericDao {
+ public Integer countByGroup(long vmGroupId);
+
+ public List listByGroup(long vmGroupId);
+
+ public int remove(long vmGroupId, long vmId);
+
+}
diff --git a/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java b/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java
new file mode 100644
index 00000000000..32f67930897
--- /dev/null
+++ b/engine/schema/src/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java
@@ -0,0 +1,40 @@
+package com.cloud.network.as.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.network.as.AutoScaleVmGroupVmMapVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value={AutoScaleVmGroupVmMapDao.class})
+public class AutoScaleVmGroupVmMapDaoImpl extends GenericDaoBase implements AutoScaleVmGroupVmMapDao {
+
+ @Override
+ public Integer countByGroup(long vmGroupId) {
+
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("vmGroupId", SearchCriteria.Op.EQ, vmGroupId);
+ return getCount(sc);
+ }
+
+ @Override
+ public List listByGroup(long vmGroupId) {
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("vmGroupId", SearchCriteria.Op.EQ, vmGroupId);
+ return listBy(sc);
+ }
+
+ @Override
+ public int remove(long vmGroupId, long vmId) {
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("vmGroupId", SearchCriteria.Op.EQ, vmGroupId);
+ sc.addAnd("vmId", SearchCriteria.Op.EQ, vmId);
+ return remove(sc);
+ }
+
+}
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index 015a96654c2..e9d42b44057 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -168,6 +168,9 @@ import com.cloud.agent.api.OvsSetTagAndFlowAnswer;
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
import com.cloud.agent.api.OvsSetTagAndFlowCommand;
import com.cloud.agent.api.OvsFetchInterfaceCommand;
+import com.cloud.agent.api.PerformanceMonitorAnswer;
+import com.cloud.agent.api.PerformanceMonitorCommand;
+
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
@@ -304,7 +307,6 @@ import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.utils.ssh.SSHCmdHelper;
-
/**
* CitrixResourceBase encapsulates the calls to the XenServer Xapi process
* to perform the required functionalities for CloudStack.
@@ -657,11 +659,88 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return execute((PvlanSetupCommand)cmd);
} else if (clazz == SetMonitorServiceCommand.class) {
return execute((SetMonitorServiceCommand)cmd);
+ } else if (clazz == PerformanceMonitorCommand.class) {
+ return execute((PerformanceMonitorCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
+ private Answer execute(PerformanceMonitorCommand cmd) {
+ Connection conn = getConnection();
+ String perfMon = getPerfMon(conn, cmd.getParams(), cmd.getWait());
+ if (perfMon == null) {
+ return new PerformanceMonitorAnswer(cmd, false, perfMon);
+ } else
+ return new PerformanceMonitorAnswer(cmd, true, perfMon);
+ }
+
+ private String getPerfMon(Connection conn, Map params,
+ int wait) {
+ String result = null;
+ try {
+ result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60,
+ params);
+ if (result != null)
+ return result;
+ } catch (Exception e) {
+ s_logger.error("Can not get performance monitor for AS due to ", e);
+ }
+ return null;
+ }
+
+ protected String callHostPluginAsync(Connection conn, String plugin,
+ String cmd, int wait, Map params) {
+ int timeout = wait * 1000;
+ Map args = new HashMap();
+ Task task = null;
+ try {
+ for (String key : params.keySet()) {
+ args.put(key, params.get(key));
+ }
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("callHostPlugin executing for command " + cmd
+ + " with " + getArgsString(args));
+ }
+ Host host = Host.getByUuid(conn, _host.uuid);
+ task = host.callPluginAsync(conn, plugin, cmd, args);
+ // poll every 1 seconds
+ waitForTask(conn, task, 1000, timeout);
+ checkForSuccess(conn, task);
+ String result = task.getResult(conn);
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("callHostPlugin Result: " + result);
+ }
+ return result.replace("", "").replace("", "")
+ .replace("\n", "");
+ } catch (Types.HandleInvalid e) {
+ s_logger.warn("callHostPlugin failed for cmd: " + cmd
+ + " with args " + getArgsString(args)
+ + " due to HandleInvalid clazz:" + e.clazz + ", handle:"
+ + e.handle);
+ } catch (XenAPIException e) {
+ s_logger.warn(
+ "callHostPlugin failed for cmd: " + cmd + " with args "
+ + getArgsString(args) + " due to " + e.toString(),
+ e);
+ } catch (XmlRpcException e) {
+ s_logger.warn(
+ "callHostPlugin failed for cmd: " + cmd + " with args "
+ + getArgsString(args) + " due to " + e.getMessage(),
+ e);
+ } finally {
+ if (task != null) {
+ try {
+ task.destroy(conn);
+ } catch (Exception e1) {
+ s_logger.warn("unable to destroy task(" + task.toString()
+ + ") on host(" + _host.uuid + ") due to ", e1);
+ }
+ }
+ }
+ return null;
+ }
+
protected void scaleVM(Connection conn, VM vm, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException {
Long staticMemoryMax = vm.getMemoryStaticMax(conn);
diff --git a/scripts/vm/hypervisor/xenserver/perfmon.py b/scripts/vm/hypervisor/xenserver/perfmon.py
new file mode 100644
index 00000000000..c8514b4186a
--- /dev/null
+++ b/scripts/vm/hypervisor/xenserver/perfmon.py
@@ -0,0 +1,245 @@
+#!/usr/bin/python
+
+import pprint
+import XenAPI
+import urllib
+from xml.dom import minidom
+import time
+
+
+# Per VM dictionary (used by RRDUpdates to look up column numbers by variable names)
+class VMReport(dict):
+ """Used internally by RRDUpdates"""
+ def __init__(self, uuid):
+ self.uuid = uuid
+ super(dict, self).__init__()
+
+
+# Per Host dictionary (used by RRDUpdates to look up column numbers by variable names)
+class HostReport(dict):
+ """Used internally by RRDUpdates"""
+ def __init__(self, uuid):
+ self.uuid = uuid
+ super(dict, self).__init__()
+
+
+class PerfMonException(Exception):
+ pass
+
+
+class XmlConfigException(PerfMonException):
+ pass
+
+
+class UsageException(Exception):
+ pass
+
+
+class RRDUpdates:
+ """ Object used to get and parse the output the http://localhost/rrd_udpates?...
+ """
+ def __init__(self):
+ # params are what get passed to the CGI executable in the URL
+ self.params = dict()
+ self.params['start'] = int(time.time()) - 1000 # For demo purposes!
+ self.params['host'] = 'false' # include data for host (as well as for VMs)
+ self.params['cf'] = 'AVERAGE' # consolidation function, each sample averages 12 from the 5 second RRD
+ self.params['interval'] = '60'
+
+ def get_nrows(self):
+ return self.rows
+
+ def get_vm_list(self):
+ return self.vm_reports.keys()
+
+ def get_vm_param_list(self, uuid):
+ report = self.vm_reports[uuid]
+ if not report:
+ return []
+ return report.keys()
+
+ def get_total_cpu_core(self, uuid):
+ report = self.vm_reports[uuid]
+ if not report:
+ return 0
+ else:
+ param_keys = report.keys()
+ result = 0
+ for param in param_keys:
+ if "cpu" in param:
+ result += 1
+ return result
+
+ def get_vm_data(self, uuid, param, row):
+ #pp = pprint.PrettyPrinter(indent=4)
+ #pp.pprint(self.vm_reports)
+ report = self.vm_reports[uuid]
+ col = report[param]
+ return self.__lookup_data(col, row)
+
+ def get_host_uuid(self):
+ report = self.host_report
+ if not report:
+ return None
+ return report.uuid
+
+ def get_host_param_list(self):
+ report = self.host_report
+ if not report:
+ return []
+ return report.keys()
+
+ def get_host_data(self, param, row):
+ report = self.host_report
+ col = report[param]
+ return self.__lookup_data(col, row)
+
+ def get_row_time(self, row):
+ return self.__lookup_timestamp(row)
+
+ # extract float from value () node by col,row
+ def __lookup_data(self, col, row):
+ # Note: the nodes are in reverse chronological order, and comprise
+ # a timestamp node, followed by self.columns data nodes
+ node = self.data_node.childNodes[self.rows - 1 - row].childNodes[col + 1]
+ return float(node.firstChild.toxml()) # node.firstChild should have nodeType TEXT_NODE
+
+ # extract int from value () node by row
+ def __lookup_timestamp(self, row):
+ # Note: the nodes are in reverse chronological order, and comprise
+ # a timestamp node, followed by self.columns data nodes
+ node = self.data_node.childNodes[self.rows - 1 - row].childNodes[0]
+ return int(node.firstChild.toxml()) # node.firstChild should have nodeType TEXT_NODE
+
+ def refresh(self, login, starttime, session, override_params):
+ self.params['start'] = starttime
+ params = override_params
+ params['session_id'] = session
+ params.update(self.params)
+ paramstr = "&".join(["%s=%s" % (k, params[k]) for k in params])
+ # this is better than urllib.urlopen() as it raises an Exception on http 401 'Unauthorised' error
+ # rather than drop into interactive mode
+ for host in login.host.get_all():
+ #print "http://" + str(login.host.get_address(host)) + "/rrd_updates?%s" % paramstr
+ sock = urllib.URLopener().open("http://" + str(login.host.get_address(host)) + "/rrd_updates?%s" % paramstr)
+ xmlsource = sock.read()
+ sock.close()
+ xmldoc = minidom.parseString(xmlsource)
+ self.__parse_xmldoc(xmldoc)
+ # Update the time used on the next run
+ self.params['start'] = self.end_time + 1 # avoid retrieving same data twice
+
+ def __parse_xmldoc(self, xmldoc):
+ # The 1st node contains meta data (description of the data)
+ # The 2nd node contains the data
+ self.meta_node = xmldoc.firstChild.childNodes[0]
+ self.data_node = xmldoc.firstChild.childNodes[1]
+
+ def lookup_metadata_bytag(name):
+ return int(self.meta_node.getElementsByTagName(name)[0].firstChild.toxml())
+ # rows = number of samples per variable
+ # columns = number of variables
+ self.rows = lookup_metadata_bytag('rows')
+ self.columns = lookup_metadata_bytag('columns')
+ # These indicate the period covered by the data
+ self.start_time = lookup_metadata_bytag('start')
+ self.step_time = lookup_metadata_bytag('step')
+ self.end_time = lookup_metadata_bytag('end')
+ # the