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 <[email protected]> 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 "[email protected]" <[email protected]>.
