You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2017/07/23 15:15:27 UTC
[cloudstack] branch master updated (61208b5 -> c03923c)
This is an automated email from the ASF dual-hosted git repository.
bhaisaab pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git.
from 61208b5 Merge remote-tracking branch 'origin/4.10'
new 960cb84 CLOUDSTACK-7984: Collect network statistics for VMs on shared network (KVM implementation)
new 047a57d CLOUDSTACK-7984: Add vm.{disk,network}.stats.interval.min global setting
new c03923c CLOUDSTACK-9113: skip vm with inconsistent state when getVmNetworkStats
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
api/src/com/cloud/vm/UserVmService.java | 4 +
.../vm/{RunningOn.java => VmNetworkStats.java} | 10 +-
.../com/cloud/agent/api/GetVmDiskStatsAnswer.java | 2 +-
...atsAnswer.java => GetVmNetworkStatsAnswer.java} | 16 +-
...sCommand.java => GetVmNetworkStatsCommand.java} | 6 +-
...rkUsageAnswer.java => VmNetworkStatsEntry.java} | 53 +++---
.../com/cloud/vm/VirtualMachineManagerImpl.java | 7 +
.../kvm/resource/LibvirtComputingResource.java | 25 +++
...=> LibvirtGetVmNetworkStatsCommandWrapper.java} | 28 +--
.../hypervisor/vmware/resource/VmwareResource.java | 8 +
... => CitrixGetVmNetworkStatsCommandWrapper.java} | 12 +-
server/src/com/cloud/api/ApiResponseHelper.java | 2 +-
server/src/com/cloud/configuration/Config.java | 1 -
server/src/com/cloud/server/StatsCollector.java | 194 ++++++++++++++++++++-
.../com/cloud/storage/VolumeApiServiceImpl.java | 9 +
server/src/com/cloud/vm/UserVmManager.java | 5 +-
server/src/com/cloud/vm/UserVmManagerImpl.java | 158 ++++++++++++++++-
setup/db/db/schema-480to481.sql | 1 +
18 files changed, 470 insertions(+), 71 deletions(-)
copy api/src/com/cloud/vm/{RunningOn.java => VmNetworkStats.java} (85%)
copy core/src/com/cloud/agent/api/{GetVmDiskStatsAnswer.java => GetVmNetworkStatsAnswer.java} (69%)
copy core/src/com/cloud/agent/api/{GetVmDiskStatsCommand.java => GetVmNetworkStatsCommand.java} (88%)
copy core/src/com/cloud/agent/api/{NetworkUsageAnswer.java => VmNetworkStatsEntry.java} (55%)
copy plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/{LibvirtGetVmDiskStatsCommandWrapper.java => LibvirtGetVmNetworkStatsCommandWrapper.java} (60%)
copy plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/{CitrixCheckOnHostCommandWrapper.java => CitrixGetVmNetworkStatsCommandWrapper.java} (69%)
--
To stop receiving notification emails like this one, please contact
['"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>'].
[cloudstack] 03/03: CLOUDSTACK-9113: skip vm with inconsistent
state when getVmNetworkStats
Posted by bh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit c03923c7e75b70b3c7b33fb2e28cd1bed8ac5c7d
Author: Wei Zhou <w....@tech.leaseweb.com>
AuthorDate: Mon Dec 7 12:02:43 2015 +0100
CLOUDSTACK-9113: skip vm with inconsistent state when getVmNetworkStats
---
.../wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
index 19a0a46..20ee4fd 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
@@ -48,12 +48,16 @@ public final class LibvirtGetVmNetworkStatsCommandWrapper extends CommandWrapper
final HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsNameMap = new HashMap<String, List<VmNetworkStatsEntry>>();
final Connect conn = libvirtUtilitiesHelper.getConnection();
for (final String vmName : vmNames) {
- final List<VmNetworkStatsEntry> statEntry = libvirtComputingResource.getVmNetworkStat(conn, vmName);
- if (statEntry == null) {
- continue;
- }
+ try {
+ final List<VmNetworkStatsEntry> statEntry = libvirtComputingResource.getVmNetworkStat(conn, vmName);
+ if (statEntry == null) {
+ continue;
+ }
- vmNetworkStatsNameMap.put(vmName, statEntry);
+ vmNetworkStatsNameMap.put(vmName, statEntry);
+ } catch (LibvirtException e) {
+ s_logger.warn("Can't get vm network stats: " + e.toString() + ", continue");
+ }
}
return new GetVmNetworkStatsAnswer(command, "", command.getHostName(), vmNetworkStatsNameMap);
} catch (final LibvirtException e) {
@@ -61,4 +65,4 @@ public final class LibvirtGetVmNetworkStatsCommandWrapper extends CommandWrapper
return new GetVmNetworkStatsAnswer(command, null, null, null);
}
}
-}
\ No newline at end of file
+}
--
To stop receiving notification emails like this one, please contact
"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>.
[cloudstack] 02/03: CLOUDSTACK-7984: Add vm.{disk,
network}.stats.interval.min global setting
Posted by bh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 047a57ddf25c42a688f17ae037d8692856833c00
Author: Wei Zhou <w....@tech.leaseweb.com>
AuthorDate: Mon Oct 19 14:34:46 2015 +0200
CLOUDSTACK-7984: Add vm.{disk,network}.stats.interval.min global setting
---
server/src/com/cloud/configuration/Config.java | 2 -
server/src/com/cloud/server/StatsCollector.java | 59 +++++++++++++++++++------
setup/db/db/schema-480to481.sql | 1 +
3 files changed, 46 insertions(+), 16 deletions(-)
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index b607502..993f9c5 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -868,8 +868,6 @@ public enum Config {
"60000",
"The interval (in milliseconds) when vm stats are retrieved from agents.",
null),
- VmDiskStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.disk.stats.interval", "0", "Interval (in seconds) to report vm disk statistics.", null),
- VmNetworkStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.network.stats.interval", "0", "Interval (in seconds) to report vm network statistics (for Shared networks).", null),
VmTransitionWaitInterval(
"Advanced",
ManagementServer.class,
diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java
index 0431301..e520867 100644
--- a/server/src/com/cloud/server/StatsCollector.java
+++ b/server/src/com/cloud/server/StatsCollector.java
@@ -47,6 +47,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
@@ -138,7 +140,7 @@ import com.cloud.vm.dao.VMInstanceDao;
*
*/
@Component
-public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable {
+public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable, Configurable {
public static enum ExternalStatsProtocol {
NONE("none"), GRAPHITE("graphite");
@@ -156,6 +158,15 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
public static final Logger s_logger = Logger.getLogger(StatsCollector.class.getName());
+ static final ConfigKey<Integer> vmDiskStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval", "0",
+ "Interval (in seconds) to report vm disk statistics. Vm disk statistics will be disabled if this is set to 0 or less than 0.", false);
+ static final ConfigKey<Integer> vmDiskStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval.min", "300",
+ "Minimal interval (in seconds) to report vm disk statistics. If vm.disk.stats.interval is smaller than this, use this to report vm disk statistics.", false);
+ static final ConfigKey<Integer> vmNetworkStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval", "0",
+ "Interval (in seconds) to report vm network statistics (for Shared networks). Vm network statistics will be disabled if this is set to 0 or less than 0.", false);
+ static final ConfigKey<Integer> vmNetworkStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval.min", "300",
+ "Minimal Interval (in seconds) to report vm network statistics (for Shared networks). If vm.network.stats.interval is smaller than this, use this to report vm network statistics.", false);
+
private static StatsCollector s_instance = null;
private ScheduledExecutorService _executor = null;
@@ -238,8 +249,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
long storageStatsInterval = -1L;
long volumeStatsInterval = -1L;
long autoScaleStatsInterval = -1L;
- int vmDiskStatsInterval = 0;
- int vmNetworkStatsInterval = 0;
+
List<Long> hostIds = null;
private double _imageStoreCapacityThreshold = 0.90;
@@ -286,8 +296,6 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
storageStatsInterval = NumbersUtil.parseLong(configs.get("storage.stats.interval"), 60000L);
volumeStatsInterval = NumbersUtil.parseLong(configs.get("volume.stats.interval"), -1L);
autoScaleStatsInterval = NumbersUtil.parseLong(configs.get("autoscale.stats.interval"), 60000L);
- vmDiskStatsInterval = NumbersUtil.parseInt(configs.get("vm.disk.stats.interval"), 0);
- vmNetworkStatsInterval = NumbersUtil.parseInt(configs.get("vm.network.stats.interval"), 0);
/* URI to send statistics to. Currently only Graphite is supported */
String externalStatsUri = configs.get("stats.output.uri");
@@ -345,18 +353,26 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
_executor.scheduleWithFixedDelay(new AutoScaleMonitor(), 15000L, autoScaleStatsInterval, TimeUnit.MILLISECONDS);
}
- if (vmDiskStatsInterval > 0) {
- if (vmDiskStatsInterval < 300)
- vmDiskStatsInterval = 300;
- _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS);
+ if (vmDiskStatsInterval.value() > 0) {
+ if (vmDiskStatsInterval.value() < vmDiskStatsIntervalMin.value()) {
+ s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is smaller than vm.disk.stats.interval.min - " + vmDiskStatsIntervalMin.value() + ", so use vm.disk.stats.interval.min");
+ _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsIntervalMin.value(), vmDiskStatsIntervalMin.value(), TimeUnit.SECONDS);
+ } else {
+ _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval.value(), vmDiskStatsInterval.value(), TimeUnit.SECONDS);
+ }
+ } else {
+ s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm disk stats thread");
}
- if (vmNetworkStatsInterval > 0) {
- if (vmNetworkStatsInterval < 300)
- vmNetworkStatsInterval = 300;
- _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsInterval, vmNetworkStatsInterval, TimeUnit.SECONDS);
+ if (vmNetworkStatsInterval.value() > 0) {
+ if (vmNetworkStatsInterval.value() < vmNetworkStatsIntervalMin.value()) {
+ s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is smaller than vm.network.stats.interval.min - " + vmNetworkStatsIntervalMin.value() + ", so use vm.network.stats.interval.min");
+ _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsIntervalMin.value(), vmNetworkStatsIntervalMin.value(), TimeUnit.SECONDS);
+ } else {
+ _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsInterval.value(), vmNetworkStatsInterval.value(), TimeUnit.SECONDS);
+ }
} else {
- s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval + " so not scheduling the vm network stats thread");
+ s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm network stats thread");
}
//Schedule disk stats update task
@@ -841,6 +857,11 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
if (vmNetworkStats == null)
continue;
UserVmVO userVm = _userVmDao.findById(vmId);
+ if (userVm == null) {
+ s_logger.debug("Cannot find uservm with id: " + vmId + " , continue");
+ continue;
+ }
+ s_logger.debug("Now we are updating the user_statistics table for VM: " + userVm.getInstanceName() + " after collecting vm network statistics from host: " + host.getName());
for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) {
SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
sc_nic.addAnd("macAddress", SearchCriteria.Op.EQ, vmNetworkStat.getMacAddress());
@@ -1279,4 +1300,14 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
public StorageStats getStoragePoolStats(long id) {
return _storagePoolStats.get(id);
}
+
+ @Override
+ public String getConfigComponentName() {
+ return this.getClass().getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] { vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin };
+ }
}
diff --git a/setup/db/db/schema-480to481.sql b/setup/db/db/schema-480to481.sql
index 3b2d40b..4c8637b 100644
--- a/setup/db/db/schema-480to481.sql
+++ b/setup/db/db/schema-480to481.sql
@@ -18,3 +18,4 @@
--;
-- Schema upgrade from 4.8.0 to 4.8.1;
--;
+
--
To stop receiving notification emails like this one, please contact
"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>.
[cloudstack] 01/03: CLOUDSTACK-7984: Collect network statistics for
VMs on shared network (KVM implementation)
Posted by bh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 960cb84083d5a0293c3c595f06cf312560ba4bc9
Author: Wei Zhou <w....@tech.leaseweb.com>
AuthorDate: Mon Oct 12 14:22:29 2015 +0200
CLOUDSTACK-7984: Collect network statistics for VMs on shared network (KVM implementation)
---
api/src/com/cloud/vm/UserVmService.java | 4 +
api/src/com/cloud/vm/VmNetworkStats.java | 26 ++++
.../com/cloud/agent/api/GetVmDiskStatsAnswer.java | 2 +-
...atsAnswer.java => GetVmNetworkStatsAnswer.java} | 16 +--
...tsAnswer.java => GetVmNetworkStatsCommand.java} | 33 +++--
.../com/cloud/agent/api/VmNetworkStatsEntry.java | 74 ++++++++++
.../com/cloud/vm/VirtualMachineManagerImpl.java | 7 +
.../kvm/resource/LibvirtComputingResource.java | 25 ++++
.../LibvirtGetVmNetworkStatsCommandWrapper.java | 64 +++++++++
.../hypervisor/vmware/resource/VmwareResource.java | 8 ++
.../CitrixGetVmNetworkStatsCommandWrapper.java | 36 +++++
server/src/com/cloud/api/ApiResponseHelper.java | 2 +-
server/src/com/cloud/configuration/Config.java | 1 +
server/src/com/cloud/server/StatsCollector.java | 149 +++++++++++++++++++
.../com/cloud/storage/VolumeApiServiceImpl.java | 9 ++
server/src/com/cloud/vm/UserVmManager.java | 5 +-
server/src/com/cloud/vm/UserVmManagerImpl.java | 158 ++++++++++++++++++++-
17 files changed, 592 insertions(+), 27 deletions(-)
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index db9ded8..68425c3 100644
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -482,4 +482,8 @@ public interface UserVmService {
*/
public boolean isDisplayResourceEnabled(Long vmId);
+ void collectVmDiskStatistics(UserVm userVm);
+
+ void collectVmNetworkStatistics (UserVm userVm);
+
}
diff --git a/api/src/com/cloud/vm/VmNetworkStats.java b/api/src/com/cloud/vm/VmNetworkStats.java
new file mode 100644
index 0000000..7f96fdf
--- /dev/null
+++ b/api/src/com/cloud/vm/VmNetworkStats.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.cloud.vm;
+
+public interface VmNetworkStats {
+ // vm related network stats
+
+ public long getBytesSent();
+
+ public long getBytesReceived();
+
+}
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
index 77fe8ae..cb52c46 100644
--- a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
+++ b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
@@ -24,7 +24,7 @@ import java.util.List;
import com.cloud.agent.api.LogLevel.Log4jLevel;
-@LogLevel(Log4jLevel.Trace)
+@LogLevel(Log4jLevel.Debug)
public class GetVmDiskStatsAnswer extends Answer {
String hostName;
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java
similarity index 69%
copy from core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
copy to core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java
index 77fe8ae..85a99cb 100644
--- a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
+++ b/core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java
@@ -24,27 +24,27 @@ import java.util.List;
import com.cloud.agent.api.LogLevel.Log4jLevel;
-@LogLevel(Log4jLevel.Trace)
-public class GetVmDiskStatsAnswer extends Answer {
+@LogLevel(Log4jLevel.Debug)
+public class GetVmNetworkStatsAnswer extends Answer {
String hostName;
- HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap;
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsMap;
- public GetVmDiskStatsAnswer(GetVmDiskStatsCommand cmd, String details, String hostName, HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap) {
+ public GetVmNetworkStatsAnswer(GetVmNetworkStatsCommand cmd, String details, String hostName, HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsMap) {
super(cmd, true, details);
this.hostName = hostName;
- this.vmDiskStatsMap = vmDiskStatsMap;
+ this.vmNetworkStatsMap = vmNetworkStatsMap;
}
public String getHostName() {
return hostName;
}
- public HashMap<String, List<VmDiskStatsEntry>> getVmDiskStatsMap() {
- return vmDiskStatsMap;
+ public HashMap<String, List<VmNetworkStatsEntry>> getVmNetworkStatsMap() {
+ return vmNetworkStatsMap;
}
- protected GetVmDiskStatsAnswer() {
+ protected GetVmNetworkStatsAnswer() {
//no-args constructor for json serialization-deserialization
}
}
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java
similarity index 63%
copy from core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
copy to core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java
index 77fe8ae..266045e 100644
--- a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
+++ b/core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java
@@ -19,32 +19,39 @@
package com.cloud.agent.api;
-import java.util.HashMap;
import java.util.List;
import com.cloud.agent.api.LogLevel.Log4jLevel;
@LogLevel(Log4jLevel.Trace)
-public class GetVmDiskStatsAnswer extends Answer {
-
+public class GetVmNetworkStatsCommand extends Command {
+ List<String> vmNames;
+ String hostGuid;
String hostName;
- HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap;
- public GetVmDiskStatsAnswer(GetVmDiskStatsCommand cmd, String details, String hostName, HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap) {
- super(cmd, true, details);
+ protected GetVmNetworkStatsCommand() {
+ }
+
+ public GetVmNetworkStatsCommand(List<String> vmNames, String hostGuid, String hostName) {
+ this.vmNames = vmNames;
+ this.hostGuid = hostGuid;
this.hostName = hostName;
- this.vmDiskStatsMap = vmDiskStatsMap;
}
- public String getHostName() {
- return hostName;
+ public List<String> getVmNames() {
+ return vmNames;
}
- public HashMap<String, List<VmDiskStatsEntry>> getVmDiskStatsMap() {
- return vmDiskStatsMap;
+ public String getHostGuid() {
+ return this.hostGuid;
+ }
+
+ public String getHostName() {
+ return this.hostName;
}
- protected GetVmDiskStatsAnswer() {
- //no-args constructor for json serialization-deserialization
+ @Override
+ public boolean executeInSequence() {
+ return false;
}
}
diff --git a/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java b/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java
new file mode 100644
index 0000000..41db54a
--- /dev/null
+++ b/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java
@@ -0,0 +1,74 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.cloud.agent.api;
+
+import com.cloud.vm.VmNetworkStats;
+
+public class VmNetworkStatsEntry implements VmNetworkStats {
+ String vmName;
+ String macAddress;
+ long bytesSent;
+ long bytesReceived;
+
+ public VmNetworkStatsEntry() {
+ }
+
+ public VmNetworkStatsEntry(String vmName, String macAddress, long bytesSent, long bytesReceived) {
+ this.bytesSent = bytesSent;
+ this.bytesReceived = bytesReceived;
+ this.vmName = vmName;
+ this.macAddress = macAddress;
+ }
+
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+ public String getVmName() {
+ return vmName;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setBytesSent(long bytesSent) {
+ this.bytesSent = bytesSent;
+ }
+
+ @Override
+ public long getBytesSent() {
+ return bytesSent;
+ }
+
+ public void setBytesReceived(long bytesReceived) {
+ this.bytesReceived = bytesReceived;
+ }
+
+ @Override
+ public long getBytesReceived() {
+ return bytesReceived;
+ }
+
+}
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index f370111..5127cf3 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -236,6 +236,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject
protected UserVmDao _userVmDao;
@Inject
+ protected UserVmService _userVmService;
+ @Inject
protected CapacityManager _capacityMgr;
@Inject
protected NicDao _nicsDao;
@@ -3637,6 +3639,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final VMInstanceVO router = _vmDao.findById(vm.getId());
if (router.getState() == State.Running) {
+ // collect vm network statistics before unplug a nic
+ UserVmVO userVm = _userVmDao.findById(vm.getId());
+ if (userVm != null && userVm.getType() == VirtualMachine.Type.User) {
+ _userVmService.collectVmNetworkStatistics(userVm);
+ }
try {
final Commands cmds = new Commands(Command.OnError.Stop);
final UnPlugNicCommand unplugNicCmd = new UnPlugNicCommand(nic, vm.getName());
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 58db466..2440e62 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -89,6 +89,7 @@ import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocVpcCommand;
@@ -3114,6 +3115,30 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return command.execute();
}
+ public List<VmNetworkStatsEntry> getVmNetworkStat(Connect conn, String vmName) throws LibvirtException {
+ Domain dm = null;
+ try {
+ dm = getDomain(conn, vmName);
+
+ List<VmNetworkStatsEntry> stats = new ArrayList<VmNetworkStatsEntry>();
+
+ List<InterfaceDef> nics = getInterfaces(conn, vmName);
+
+ for (InterfaceDef nic : nics) {
+ DomainInterfaceStats nicStats = dm.interfaceStats(nic.getDevName());
+ String macAddress = nic.getMacAddress();
+ VmNetworkStatsEntry stat = new VmNetworkStatsEntry(vmName, macAddress, nicStats.tx_bytes, nicStats.rx_bytes);
+ stats.add(stat);
+ }
+
+ return stats;
+ } finally {
+ if (dm != null) {
+ dm.free();
+ }
+ }
+ }
+
public List<VmDiskStatsEntry> getVmDiskStat(final Connect conn, final String vmName) throws LibvirtException {
Domain dm = null;
try {
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
new file mode 100644
index 0000000..19a0a46
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
@@ -0,0 +1,64 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.cloud.hypervisor.kvm.resource.wrapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.libvirt.Connect;
+import org.libvirt.LibvirtException;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
+import com.cloud.agent.api.VmNetworkStatsEntry;
+import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+
+@ResourceWrapper(handles = GetVmNetworkStatsCommand.class)
+public final class LibvirtGetVmNetworkStatsCommandWrapper extends CommandWrapper<GetVmNetworkStatsCommand, Answer, LibvirtComputingResource> {
+
+ private static final Logger s_logger = Logger.getLogger(LibvirtGetVmNetworkStatsCommandWrapper.class);
+
+ @Override
+ public Answer execute(final GetVmNetworkStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
+ final List<String> vmNames = command.getVmNames();
+ final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
+
+ try {
+ final HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsNameMap = new HashMap<String, List<VmNetworkStatsEntry>>();
+ final Connect conn = libvirtUtilitiesHelper.getConnection();
+ for (final String vmName : vmNames) {
+ final List<VmNetworkStatsEntry> statEntry = libvirtComputingResource.getVmNetworkStat(conn, vmName);
+ if (statEntry == null) {
+ continue;
+ }
+
+ vmNetworkStatsNameMap.put(vmName, statEntry);
+ }
+ return new GetVmNetworkStatsAnswer(command, "", command.getHostName(), vmNetworkStatsNameMap);
+ } catch (final LibvirtException e) {
+ s_logger.debug("Can't get vm network stats: " + e.toString());
+ return new GetVmNetworkStatsAnswer(command, null, null, null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 8b78534..bddd61a 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -139,6 +139,8 @@ import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.GetVmDiskStatsAnswer;
import com.cloud.agent.api.GetVmDiskStatsCommand;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.GetVncPortAnswer;
@@ -407,6 +409,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
answer = execute((GetHostStatsCommand)cmd);
} else if (clz == GetVmStatsCommand.class) {
answer = execute((GetVmStatsCommand)cmd);
+ } else if (clz == GetVmNetworkStatsCommand.class) {
+ answer = execute((GetVmNetworkStatsCommand) cmd);
} else if (clz == GetVmDiskStatsCommand.class) {
answer = execute((GetVmDiskStatsCommand)cmd);
} else if (clz == CheckHealthCommand.class) {
@@ -3206,6 +3210,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return new GetVmDiskStatsAnswer(cmd, null, null, null);
}
+ protected Answer execute(GetVmNetworkStatsCommand cmd) {
+ return new GetVmNetworkStatsAnswer(cmd, null, null, null);
+ }
+
protected Answer execute(CheckHealthCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CheckHealthCommand: " + _gson.toJson(cmd));
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java
new file mode 100644
index 0000000..45cacf1
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java
@@ -0,0 +1,36 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.cloud.hypervisor.xenserver.resource.wrapper.xenbase;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
+import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+
+@ResourceWrapper(handles = GetVmNetworkStatsCommand.class)
+public final class CitrixGetVmNetworkStatsCommandWrapper extends CommandWrapper<GetVmNetworkStatsCommand, Answer, CitrixResourceBase> {
+
+ @Override
+ public Answer execute(final GetVmNetworkStatsCommand command, final CitrixResourceBase citrixResourceBase) {
+ return new GetVmNetworkStatsAnswer(command, null, null, null);
+ }
+}
\ No newline at end of file
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 9a09917..fd7c67d 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -3266,7 +3266,7 @@ public class ApiResponseHelper implements ResponseGenerator {
} else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
//Device Type
usageRecResponse.setType(usageRecord.getType());
- if (usageRecord.getType().equals("DomainRouter")) {
+ if (usageRecord.getType().equals("DomainRouter") || usageRecord.getType().equals("UserVm")) {
//Domain Router Id
VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString());
if (vm != null) {
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 50e3e7a..b607502 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -869,6 +869,7 @@ public enum Config {
"The interval (in milliseconds) when vm stats are retrieved from agents.",
null),
VmDiskStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.disk.stats.interval", "0", "Interval (in seconds) to report vm disk statistics.", null),
+ VmNetworkStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.network.stats.interval", "0", "Interval (in seconds) to report vm network statistics (for Shared networks).", null),
VmTransitionWaitInterval(
"Advanced",
ManagementServer.class,
diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java
index f47123d..0431301 100644
--- a/server/src/com/cloud/server/StatsCollector.java
+++ b/server/src/com/cloud/server/StatsCollector.java
@@ -62,9 +62,13 @@ import com.cloud.agent.api.HostStatsEntry;
import com.cloud.agent.api.PerformanceMonitorCommand;
import com.cloud.agent.api.VgpuTypesInfo;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao;
+import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.gpu.dao.HostGpuGroupsDao;
import com.cloud.host.Host;
@@ -103,7 +107,9 @@ import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
+import com.cloud.user.UserStatisticsVO;
import com.cloud.user.VmDiskStatisticsVO;
+import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.user.dao.VmDiskStatisticsDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -117,11 +123,13 @@ import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.net.MacAddress;
+import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmStats;
+import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@@ -186,6 +194,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Inject
private ManagementServerHostDao _msHostDao;
@Inject
+ private UserStatisticsDao _userStatsDao;
+ @Inject
+ private NicDao _nicDao;
+ @Inject
+ private VlanDao _vlanDao;
+ @Inject
private AutoScaleVmGroupDao _asGroupDao;
@Inject
private AutoScaleVmGroupVmMapDao _asGroupVmDao;
@@ -225,6 +239,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
long volumeStatsInterval = -1L;
long autoScaleStatsInterval = -1L;
int vmDiskStatsInterval = 0;
+ int vmNetworkStatsInterval = 0;
List<Long> hostIds = null;
private double _imageStoreCapacityThreshold = 0.90;
@@ -272,6 +287,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
volumeStatsInterval = NumbersUtil.parseLong(configs.get("volume.stats.interval"), -1L);
autoScaleStatsInterval = NumbersUtil.parseLong(configs.get("autoscale.stats.interval"), 60000L);
vmDiskStatsInterval = NumbersUtil.parseInt(configs.get("vm.disk.stats.interval"), 0);
+ vmNetworkStatsInterval = NumbersUtil.parseInt(configs.get("vm.network.stats.interval"), 0);
/* URI to send statistics to. Currently only Graphite is supported */
String externalStatsUri = configs.get("stats.output.uri");
@@ -335,8 +351,17 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
_executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS);
}
+ if (vmNetworkStatsInterval > 0) {
+ if (vmNetworkStatsInterval < 300)
+ vmNetworkStatsInterval = 300;
+ _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsInterval, vmNetworkStatsInterval, TimeUnit.SECONDS);
+ } else {
+ s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval + " so not scheduling the vm network stats thread");
+ }
+
//Schedule disk stats update task
_diskStatsUpdateExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DiskStatsUpdater"));
+
String aggregationRange = configs.get("usage.stats.job.aggregation.range");
_usageAggregationRange = NumbersUtil.parseInt(aggregationRange, 1440);
_usageTimeZone = configs.get("usage.aggregation.timezone");
@@ -641,11 +666,20 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
class VmDiskStatsTask extends ManagedContextRunnable {
@Override
protected void runInContext() {
+ //Check for ownership
+ //msHost in UP state with min id should run the job
+ ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){
+ s_logger.debug("Skipping collect vm disk stats from hosts");
+ return;
+ }
// collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03.
try {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
+ s_logger.debug("VmDiskStatsTask is running...");
+
SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance,
@@ -763,6 +797,121 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
}
+ class VmNetworkStatsTask extends ManagedContextRunnable {
+ @Override
+ protected void runInContext() {
+ //Check for ownership
+ //msHost in UP state with min id should run the job
+ ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){
+ s_logger.debug("Skipping collect vm network stats from hosts");
+ return;
+ }
+ // collect the vm network statistics(total) from hypervisor
+ try {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ s_logger.debug("VmNetworkStatsTask is running...");
+
+ SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
+ sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
+ sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance);
+ sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.Routing.toString());
+ List<HostVO> hosts = _hostDao.search(sc, null);
+
+ for (HostVO host : hosts)
+ {
+ List<UserVmVO> vms = _userVmDao.listRunningByHostId(host.getId());
+ List<Long> vmIds = new ArrayList<Long>();
+
+ for (UserVmVO vm : vms) {
+ if (vm.getType() == VirtualMachine.Type.User) // user vm
+ vmIds.add(vm.getId());
+ }
+
+ HashMap<Long, List<VmNetworkStatsEntry>> vmNetworkStatsById = _userVmMgr.getVmNetworkStatistics(host.getId(), host.getName(), vmIds);
+ if (vmNetworkStatsById == null)
+ continue;
+
+ Set<Long> vmIdSet = vmNetworkStatsById.keySet();
+ for(Long vmId : vmIdSet)
+ {
+ List<VmNetworkStatsEntry> vmNetworkStats = vmNetworkStatsById.get(vmId);
+ if (vmNetworkStats == null)
+ continue;
+ UserVmVO userVm = _userVmDao.findById(vmId);
+ for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) {
+ SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
+ sc_nic.addAnd("macAddress", SearchCriteria.Op.EQ, vmNetworkStat.getMacAddress());
+ NicVO nic = _nicDao.search(sc_nic, null).get(0);
+ List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId());
+ if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached)
+ continue; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
+ UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), vmId, "UserVm");
+ if (previousvmNetworkStats == null) {
+ previousvmNetworkStats = new UserStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),nic.getIPv4Address(), vmId, "UserVm", nic.getNetworkId());
+ _userStatsDao.persist(previousvmNetworkStats);
+ }
+ UserStatisticsVO vmNetworkStat_lock = _userStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), vmId, "UserVm");
+
+ if ((vmNetworkStat.getBytesSent() == 0) && (vmNetworkStat.getBytesReceived() == 0)) {
+ s_logger.debug("bytes sent and received are all 0. Not updating user_statistics");
+ continue;
+ }
+
+ if (vmNetworkStat_lock == null) {
+ s_logger.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and nicId:" + nic.getId());
+ continue;
+ }
+
+ if (previousvmNetworkStats != null
+ && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent())
+ || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) {
+ s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " +
+ "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): " + vmNetworkStat.getBytesReceived());
+ continue;
+ }
+
+ if (vmNetworkStat_lock.getCurrentBytesSent() > vmNetworkStat.getBytesSent()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Sent # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesSent() + " Stored: " + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setNetBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setCurrentBytesSent(vmNetworkStat.getBytesSent());
+
+ if (vmNetworkStat_lock.getCurrentBytesReceived() > vmNetworkStat.getBytesReceived()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Received # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesReceived() + " Stored: " + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setNetBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setCurrentBytesReceived(vmNetworkStat.getBytesReceived());
+
+ if (! _dailyOrHourly) {
+ //update agg bytes
+ vmNetworkStat_lock.setAggBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ vmNetworkStat_lock.setAggBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+
+ _userStatsDao.update(vmNetworkStat_lock.getId(), vmNetworkStat_lock);
+ }
+ }
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.warn("Error while collecting vm network stats from hosts", e);
+ }
+ }
+ }
+
class StorageCollector extends ManagedContextRunnable {
@Override
protected void runInContext() {
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 98fd1a3..3330cc7 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -84,6 +84,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.UserVmManager;
+import com.cloud.vm.UserVmService;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
@@ -205,6 +206,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Inject
UserVmDao _userVmDao;
@Inject
+ UserVmService _userVmService;
+ @Inject
VolumeDataStoreDao _volumeStoreDao;
@Inject
VMInstanceDao _vmInstanceDao;
@@ -1799,6 +1802,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
Answer answer = null;
if (sendCommand) {
+ // collect vm disk statistics before detach a volume
+ UserVmVO userVm = _userVmDao.findById(vmId);
+ if (userVm != null && userVm.getType() == VirtualMachine.Type.User) {
+ _userVmService.collectVmDiskStatistics(userVm);
+ }
+
DataTO volTO = volFactory.getVolume(volume.getId()).getTO();
DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType());
diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java
index 411fd9b..51cce9d 100644
--- a/server/src/com/cloud/vm/UserVmManager.java
+++ b/server/src/com/cloud/vm/UserVmManager.java
@@ -24,6 +24,7 @@ import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@@ -100,8 +101,6 @@ public interface UserVmManager extends UserVmService {
boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic);
- void collectVmDiskStatistics(UserVmVO userVm);
-
UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName, List<Long> securityGroupIdList) throws ResourceUnavailableException, InsufficientCapacityException;
@@ -116,4 +115,6 @@ public interface UserVmManager extends UserVmService {
void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType);
void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString);
+
+ HashMap<Long, List<VmNetworkStatsEntry>> getVmNetworkStatistics(long hostId, String hostName, List<Long> vmIds);
}
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 3a47f38..5b3c5ba 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -99,6 +99,8 @@ import com.cloud.agent.api.Command;
import com.cloud.agent.api.GetVmDiskStatsAnswer;
import com.cloud.agent.api.GetVmDiskStatsCommand;
import com.cloud.agent.api.GetVmIpAddressCommand;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.PvlanSetupCommand;
@@ -106,6 +108,7 @@ import com.cloud.agent.api.RestoreVMSnapshotAnswer;
import com.cloud.agent.api.RestoreVMSnapshotCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
@@ -128,6 +131,9 @@ import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.dc.dao.HostPodDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlanner;
@@ -248,11 +254,13 @@ import com.cloud.user.ResourceLimitService;
import com.cloud.user.SSHKeyPair;
import com.cloud.user.SSHKeyPairVO;
import com.cloud.user.User;
+import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.SSHKeyPairDao;
import com.cloud.user.dao.UserDao;
+import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.user.dao.VmDiskStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
@@ -454,6 +462,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Inject
private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
@Inject
+ private UserStatisticsDao _userStatsDao;
+ @Inject
+ private VlanDao _vlanDao;
+ @Inject
VolumeService _volService;
@Inject
VolumeDataFactory volFactory;
@@ -902,6 +914,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (vm.getState() == State.Running && vm.getHostId() != null) {
collectVmDiskStatistics(vm);
+ collectVmNetworkStatistics(vm);
DataCenterVO dc = _dcDao.findById(vm.getDataCenterId());
try {
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
@@ -3689,6 +3702,144 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
+ @Override
+ public HashMap<Long, List<VmNetworkStatsEntry>> getVmNetworkStatistics(long hostId, String hostName, List<Long> vmIds) {
+ HashMap<Long, List<VmNetworkStatsEntry>> vmNetworkStatsById = new HashMap<Long, List<VmNetworkStatsEntry>>();
+
+ if (vmIds.isEmpty()) {
+ return vmNetworkStatsById;
+ }
+
+ List<String> vmNames = new ArrayList<String>();
+
+ for (Long vmId : vmIds) {
+ UserVmVO vm = _vmDao.findById(vmId);
+ vmNames.add(vm.getInstanceName());
+ }
+
+ Answer answer = _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(vmNames, _hostDao.findById(hostId).getGuid(), hostName));
+ if (answer == null || !answer.getResult()) {
+ s_logger.warn("Unable to obtain VM network statistics.");
+ return null;
+ } else {
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsByName = ((GetVmNetworkStatsAnswer)answer).getVmNetworkStatsMap();
+
+ if (vmNetworkStatsByName == null) {
+ s_logger.warn("Unable to obtain VM network statistics.");
+ return null;
+ }
+
+ for (String vmName : vmNetworkStatsByName.keySet()) {
+ vmNetworkStatsById.put(vmIds.get(vmNames.indexOf(vmName)), vmNetworkStatsByName.get(vmName));
+ }
+ }
+
+ return vmNetworkStatsById;
+ }
+
+ @Override
+ public void collectVmNetworkStatistics (final UserVm userVm) {
+ if (!userVm.getHypervisorType().equals(HypervisorType.KVM))
+ return;
+ s_logger.debug("Collect vm network statistics from host before stopping Vm");
+ long hostId = userVm.getHostId();
+ List<String> vmNames = new ArrayList<String>();
+ vmNames.add(userVm.getInstanceName());
+ final HostVO host = _hostDao.findById(hostId);
+
+ GetVmNetworkStatsAnswer networkStatsAnswer = null;
+ try {
+ networkStatsAnswer = (GetVmNetworkStatsAnswer) _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(vmNames, host.getGuid(), host.getName()));
+ } catch (Exception e) {
+ s_logger.warn("Error while collecting network stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e);
+ return;
+ }
+ if (networkStatsAnswer != null) {
+ if (!networkStatsAnswer.getResult()) {
+ s_logger.warn("Error while collecting network stats vm: " + userVm.getHostName() + " from host: " + host.getName() + "; details: " + networkStatsAnswer.getDetails());
+ return;
+ }
+ try {
+ final GetVmNetworkStatsAnswer networkStatsAnswerFinal = networkStatsAnswer;
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsByName = networkStatsAnswerFinal.getVmNetworkStatsMap();
+ if (vmNetworkStatsByName == null)
+ return;
+ List<VmNetworkStatsEntry> vmNetworkStats = vmNetworkStatsByName.get(userVm.getInstanceName());
+ if (vmNetworkStats == null)
+ return;
+
+ for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) {
+ SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
+ sc_nic.addAnd("macAddress", SearchCriteria.Op.EQ, vmNetworkStat.getMacAddress());
+ NicVO nic = _nicDao.search(sc_nic, null).get(0);
+ List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId());
+ if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached)
+ break; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
+ UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm");
+ if (previousvmNetworkStats == null) {
+ previousvmNetworkStats = new UserStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),nic.getIPv4Address(), userVm.getId(), "UserVm", nic.getNetworkId());
+ _userStatsDao.persist(previousvmNetworkStats);
+ }
+ UserStatisticsVO vmNetworkStat_lock = _userStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm");
+
+ if ((vmNetworkStat.getBytesSent() == 0) && (vmNetworkStat.getBytesReceived() == 0)) {
+ s_logger.debug("bytes sent and received are all 0. Not updating user_statistics");
+ continue;
+ }
+
+ if (vmNetworkStat_lock == null) {
+ s_logger.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and nicId:" + nic.getId());
+ continue;
+ }
+
+ if (previousvmNetworkStats != null
+ && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent())
+ || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) {
+ s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " +
+ "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): " + vmNetworkStat.getBytesReceived());
+ continue;
+ }
+
+ if (vmNetworkStat_lock.getCurrentBytesSent() > vmNetworkStat.getBytesSent()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Sent # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesSent() + " Stored: " + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setNetBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setCurrentBytesSent(vmNetworkStat.getBytesSent());
+
+ if (vmNetworkStat_lock.getCurrentBytesReceived() > vmNetworkStat.getBytesReceived()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Received # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesReceived() + " Stored: " + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setNetBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setCurrentBytesReceived(vmNetworkStat.getBytesReceived());
+
+ if (! _dailyOrHourly) {
+ //update agg bytes
+ vmNetworkStat_lock.setAggBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ vmNetworkStat_lock.setAggBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+
+ _userStatsDao.update(vmNetworkStat_lock.getId(), vmNetworkStat_lock);
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.warn("Unable to update vm network statistics for vm: " + userVm.getId() + " from host: " + hostId, e);
+ }
+ }
+ }
+
private void validateUserData(String userData, HTTPMethod httpmethod) {
byte[] decodedUserData = null;
if (userData != null) {
@@ -4232,7 +4383,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
@Override
- public void collectVmDiskStatistics(final UserVmVO userVm) {
+ public void collectVmDiskStatistics(final UserVm userVm) {
// support KVM only util 2013.06.25
if (!userVm.getHypervisorType().equals(HypervisorType.KVM))
return;
@@ -4748,6 +4899,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
UserVmVO uservm = _vmDao.findById(vmId);
if (uservm != null) {
collectVmDiskStatistics(uservm);
+ collectVmNetworkStatistics(uservm);
}
_itMgr.migrate(vm.getUuid(), srcHostId, dest);
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
@@ -5871,8 +6023,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Override
public void prepareStop(VirtualMachineProfile profile) {
UserVmVO vm = _vmDao.findById(profile.getId());
- if (vm != null && vm.getState() == State.Stopping)
+ if (vm != null && vm.getState() == State.Stopping) {
collectVmDiskStatistics(vm);
+ collectVmNetworkStatistics(vm);
+ }
}
private void encryptAndStorePassword(UserVmVO vm, String password) {
--
To stop receiving notification emails like this one, please contact
"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>.