mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-1192: Add Disk I/O Statistics
This commit is contained in:
parent
8deeb90a6d
commit
b9b0168da4
|
|
@ -0,0 +1,30 @@
|
|||
// 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 VmDiskStats {
|
||||
// vm related disk stats
|
||||
|
||||
public Long getIORead();
|
||||
|
||||
public Long getIOWrite();
|
||||
|
||||
public Long getBytesRead();
|
||||
|
||||
public Long getBytesWrite();
|
||||
|
||||
}
|
||||
|
|
@ -23,5 +23,13 @@ public interface VmStats {
|
|||
public double getNetworkReadKBs();
|
||||
|
||||
public double getNetworkWriteKBs();
|
||||
|
||||
public double getDiskReadIOs();
|
||||
|
||||
public double getDiskWriteIOs();
|
||||
|
||||
public double getDiskReadKBs();
|
||||
|
||||
public double getDiskWriteKBs();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,18 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
|
|||
@SerializedName("networkkbswrite") @Param(description="the outgoing network traffic on the host")
|
||||
private Long networkKbsWrite;
|
||||
|
||||
@SerializedName("diskkbsread") @Param(description="the read (bytes) of disk on the vm")
|
||||
private Long diskKbsRead;
|
||||
|
||||
@SerializedName("diskkbswrite") @Param(description="the write (bytes) of disk on the vm")
|
||||
private Long diskKbsWrite;
|
||||
|
||||
@SerializedName("diskioread") @Param(description="the read (io) of disk on the vm")
|
||||
private Long diskIORead;
|
||||
|
||||
@SerializedName("diskiowrite") @Param(description="the write (io) of disk on the vm")
|
||||
private Long diskIOWrite;
|
||||
|
||||
@SerializedName("guestosid") @Param(description="Os type ID of the virtual machine")
|
||||
private String guestOsId;
|
||||
|
||||
|
|
@ -300,6 +312,22 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
|
|||
public void setIsoDisplayText(String isoDisplayText) {
|
||||
this.isoDisplayText = isoDisplayText;
|
||||
}
|
||||
|
||||
public void setDiskKbsRead(Long diskKbsRead) {
|
||||
this.diskKbsRead = diskKbsRead;
|
||||
}
|
||||
|
||||
public void setDiskKbsWrite(Long diskKbsWrite) {
|
||||
this.diskKbsWrite = diskKbsWrite;
|
||||
}
|
||||
|
||||
public void setDiskIORead(Long diskIORead) {
|
||||
this.diskIORead = diskIORead;
|
||||
}
|
||||
|
||||
public void setDiskIOWrite(Long diskIOWrite) {
|
||||
this.diskIOWrite = diskIOWrite;
|
||||
}
|
||||
|
||||
public void setServiceOfferingId(String serviceOfferingId) {
|
||||
this.serviceOfferingId = serviceOfferingId;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ public class UsageTypes {
|
|||
public static final int PORT_FORWARDING_RULE = 12;
|
||||
public static final int NETWORK_OFFERING = 13;
|
||||
public static final int VPN_USERS = 14;
|
||||
public static final int VM_DISK_IO_READ = 21;
|
||||
public static final int VM_DISK_IO_WRITE = 22;
|
||||
public static final int VM_DISK_BYTES_READ = 23;
|
||||
public static final int VM_DISK_BYTES_WRITE = 24;
|
||||
|
||||
public static List<UsageTypeResponse> listUsageTypes(){
|
||||
List<UsageTypeResponse> responseList = new ArrayList<UsageTypeResponse>();
|
||||
|
|
@ -53,6 +57,10 @@ public class UsageTypes {
|
|||
responseList.add(new UsageTypeResponse(PORT_FORWARDING_RULE, "Port Forwarding Usage"));
|
||||
responseList.add(new UsageTypeResponse(NETWORK_OFFERING, "Network Offering Usage"));
|
||||
responseList.add(new UsageTypeResponse(VPN_USERS, "VPN users usage"));
|
||||
responseList.add(new UsageTypeResponse(VM_DISK_IO_READ, "VM Disk usage(I/O Read)"));
|
||||
responseList.add(new UsageTypeResponse(VM_DISK_IO_WRITE, "VM Disk usage(I/O Write)"));
|
||||
responseList.add(new UsageTypeResponse(VM_DISK_BYTES_READ, "VM Disk usage(Bytes Read)"));
|
||||
responseList.add(new UsageTypeResponse(VM_DISK_BYTES_WRITE, "VM Disk usage(Bytes Write)"));
|
||||
return responseList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -464,10 +464,14 @@ label.disabled=Disabled
|
|||
label.disabling.vpn.access=Disabling VPN Access
|
||||
label.disk.allocated=Disk Allocated
|
||||
label.disk.offering=Disk Offering
|
||||
label.disk.read.bytes=Disk Read (Bytes)
|
||||
label.disk.read.io=Disk Read (IO)
|
||||
label.disk.size.gb=Disk Size (in GB)
|
||||
label.disk.size=Disk Size
|
||||
label.disk.total=Disk Total
|
||||
label.disk.volume=Disk Volume
|
||||
label.disk.write.bytes=Disk Write (Bytes)
|
||||
label.disk.write.io=Disk Write (IO)
|
||||
label.display.name=Display name
|
||||
label.display.text=Display Text
|
||||
label.dns.1=DNS 1
|
||||
|
|
|
|||
|
|
@ -341,11 +341,13 @@
|
|||
<bean id="usageVMInstanceDaoImpl" class="com.cloud.usage.dao.UsageVMInstanceDaoImpl" />
|
||||
<bean id="usageVPNUserDaoImpl" class="com.cloud.usage.dao.UsageVPNUserDaoImpl" />
|
||||
<bean id="usageVolumeDaoImpl" class="com.cloud.usage.dao.UsageVolumeDaoImpl" />
|
||||
<bean id="usageVmDiskDaoImpl" class="com.cloud.usage.dao.UsageVmDiskDaoImpl" />
|
||||
<bean id="userAccountDaoImpl" class="com.cloud.user.dao.UserAccountDaoImpl" />
|
||||
<bean id="userAccountJoinDaoImpl" class="com.cloud.api.query.dao.UserAccountJoinDaoImpl" />
|
||||
<bean id="userIpv6AddressDaoImpl" class="com.cloud.network.dao.UserIpv6AddressDaoImpl" />
|
||||
<bean id="userStatisticsDaoImpl" class="com.cloud.user.dao.UserStatisticsDaoImpl" />
|
||||
<bean id="userStatsLogDaoImpl" class="com.cloud.user.dao.UserStatsLogDaoImpl" />
|
||||
<bean id="userVmDiskStatsDaoImpl" class="com.cloud.user.dao.VmDiskStatisticsDaoImpl" />
|
||||
<bean id="userVmCloneSettingDaoImpl" class="com.cloud.vm.dao.UserVmCloneSettingDaoImpl" />
|
||||
<bean id="userVmDaoImpl" class="com.cloud.vm.dao.UserVmDaoImpl" />
|
||||
<bean id="userVmDetailsDaoImpl" class="com.cloud.vm.dao.UserVmDetailsDaoImpl" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// 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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.agent.api.LogLevel.Log4jLevel;
|
||||
|
||||
@LogLevel(Log4jLevel.Trace)
|
||||
public class GetVmDiskStatsAnswer extends Answer {
|
||||
|
||||
String hostName;
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap;
|
||||
|
||||
public GetVmDiskStatsAnswer(GetVmDiskStatsCommand cmd, String details, String hostName, HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsMap) {
|
||||
super(cmd, true, details);
|
||||
this.hostName = hostName;
|
||||
this.vmDiskStatsMap = vmDiskStatsMap;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
public HashMap<String, List<VmDiskStatsEntry>> getVmDiskStatsMap() {
|
||||
return vmDiskStatsMap;
|
||||
}
|
||||
|
||||
protected GetVmDiskStatsAnswer() {
|
||||
//no-args constructor for json serialization-deserialization
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// 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 java.util.List;
|
||||
|
||||
import com.cloud.agent.api.LogLevel.Log4jLevel;
|
||||
|
||||
@LogLevel(Log4jLevel.Trace)
|
||||
public class GetVmDiskStatsCommand extends Command {
|
||||
List<String> vmNames;
|
||||
String hostGuid;
|
||||
String hostName;
|
||||
|
||||
protected GetVmDiskStatsCommand() {
|
||||
}
|
||||
|
||||
public GetVmDiskStatsCommand(List<String> vmNames, String hostGuid, String hostName) {
|
||||
this.vmNames = vmNames;
|
||||
this.hostGuid = hostGuid;
|
||||
this.hostName = hostName;
|
||||
}
|
||||
|
||||
public List<String> getVmNames() {
|
||||
return vmNames;
|
||||
}
|
||||
|
||||
public String getHostGuid(){
|
||||
return this.hostGuid;
|
||||
}
|
||||
|
||||
public String getHostName(){
|
||||
return this.hostName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// 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.VmDiskStats;
|
||||
|
||||
public class VmDiskStatsEntry implements VmDiskStats {
|
||||
|
||||
String vmName;
|
||||
String path;
|
||||
Long ioRead = 0L;
|
||||
Long ioWrite = 0L;
|
||||
Long bytesWrite = 0L;
|
||||
Long bytesRead = 0L;
|
||||
|
||||
public VmDiskStatsEntry() {
|
||||
}
|
||||
|
||||
public VmDiskStatsEntry(String vmName, String path, Long ioWrite, Long ioRead, Long bytesWrite, Long bytesRead) {
|
||||
this.ioRead = ioRead;
|
||||
this.ioWrite = ioWrite;
|
||||
this.bytesRead = bytesRead;
|
||||
this.bytesWrite = bytesWrite;
|
||||
this.vmName = vmName;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public void setVmName(String vmName) {
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setBytesRead(Long bytesRead) {
|
||||
this.bytesRead = bytesRead;
|
||||
}
|
||||
|
||||
public Long getBytesRead() {
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public void setBytesWrite(Long bytesWrite) {
|
||||
this.bytesWrite = bytesWrite;
|
||||
}
|
||||
|
||||
public Long getBytesWrite() {
|
||||
return bytesWrite;
|
||||
}
|
||||
|
||||
public void setIORead(Long ioRead) {
|
||||
this.ioRead = ioRead;
|
||||
}
|
||||
|
||||
public Long getIORead() {
|
||||
return ioRead;
|
||||
}
|
||||
|
||||
public void setIOWrite(Long ioWrite) {
|
||||
this.ioWrite = ioWrite;
|
||||
}
|
||||
|
||||
public Long getIOWrite() {
|
||||
return ioWrite;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,10 @@ public class VmStatsEntry implements VmStats {
|
|||
double cpuUtilization;
|
||||
double networkReadKBs;
|
||||
double networkWriteKBs;
|
||||
double diskReadIOs;
|
||||
double diskWriteIOs;
|
||||
double diskReadKBs;
|
||||
double diskWriteKBs;
|
||||
int numCPUs;
|
||||
String entityType;
|
||||
|
||||
|
|
@ -37,6 +41,18 @@ public class VmStatsEntry implements VmStats {
|
|||
this.numCPUs = numCPUs;
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public VmStatsEntry(double cpuUtilization, double networkReadKBs, double networkWriteKBs,
|
||||
double diskReadKBs, double diskWriteKBs, int numCPUs, String entityType)
|
||||
{
|
||||
this.cpuUtilization = cpuUtilization;
|
||||
this.networkReadKBs = networkReadKBs;
|
||||
this.networkWriteKBs = networkWriteKBs;
|
||||
this.diskReadKBs = diskReadKBs;
|
||||
this.diskWriteKBs = diskWriteKBs;
|
||||
this.numCPUs = numCPUs;
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public double getCPUUtilization() {
|
||||
return cpuUtilization;
|
||||
|
|
@ -62,6 +78,38 @@ public class VmStatsEntry implements VmStats {
|
|||
this.networkWriteKBs = networkWriteKBs;
|
||||
}
|
||||
|
||||
public double getDiskReadIOs() {
|
||||
return diskReadIOs;
|
||||
}
|
||||
|
||||
public void setDiskReadIOs(double diskReadIOs) {
|
||||
this.diskReadIOs = diskReadIOs;
|
||||
}
|
||||
|
||||
public double getDiskWriteIOs() {
|
||||
return diskWriteIOs;
|
||||
}
|
||||
|
||||
public void setDiskWriteIOs(double diskWriteIOs) {
|
||||
this.diskWriteIOs = diskWriteIOs;
|
||||
}
|
||||
|
||||
public double getDiskReadKBs() {
|
||||
return diskReadKBs;
|
||||
}
|
||||
|
||||
public void setDiskReadKBs(double diskReadKBs) {
|
||||
this.diskReadKBs = diskReadKBs;
|
||||
}
|
||||
|
||||
public double getDiskWriteKBs() {
|
||||
return diskWriteKBs;
|
||||
}
|
||||
|
||||
public void setDiskWriteKBs(double diskWriteKBs) {
|
||||
this.diskWriteKBs = diskWriteKBs;
|
||||
}
|
||||
|
||||
public int getNumCPUs() {
|
||||
return numCPUs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
// 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.usage;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="usage_vm_disk")
|
||||
public class UsageVmDiskVO {
|
||||
@Id
|
||||
@Column(name="account_id")
|
||||
private long accountId;
|
||||
|
||||
@Column(name="zone_id")
|
||||
private long zoneId;
|
||||
|
||||
@Column(name="vm_id")
|
||||
private Long vmId;
|
||||
|
||||
@Column(name="volume_id")
|
||||
private Long volumeId;
|
||||
|
||||
@Column(name="io_read")
|
||||
private long ioRead;
|
||||
|
||||
@Column(name="io_write")
|
||||
private long ioWrite;
|
||||
|
||||
@Column(name="agg_io_write")
|
||||
private long aggIOWrite;
|
||||
|
||||
@Column(name="agg_io_read")
|
||||
private long aggIORead;
|
||||
|
||||
@Column(name="bytes_read")
|
||||
private long bytesRead;
|
||||
|
||||
@Column(name="bytes_write")
|
||||
private long bytesWrite;
|
||||
|
||||
@Column(name="agg_bytes_write")
|
||||
private long aggBytesWrite;
|
||||
|
||||
@Column(name="agg_bytes_read")
|
||||
private long aggBytesRead;
|
||||
|
||||
@Column(name="event_time_millis")
|
||||
private long eventTimeMillis = 0;
|
||||
|
||||
protected UsageVmDiskVO() {
|
||||
}
|
||||
|
||||
public UsageVmDiskVO(Long accountId, long zoneId, Long vmId, Long volumeId, long ioRead, long ioWrite, long aggIORead, long aggIOWrite,
|
||||
long bytesRead, long bytesWrite, long aggBytesRead, long aggBytesWrite, long eventTimeMillis) {
|
||||
this.accountId = accountId;
|
||||
this.zoneId = zoneId;
|
||||
this.vmId = vmId;
|
||||
this.volumeId = volumeId;
|
||||
this.ioRead = ioRead;
|
||||
this.ioWrite = ioWrite;
|
||||
this.aggIOWrite = aggIOWrite;
|
||||
this.aggIORead = aggIORead;
|
||||
this.bytesRead = bytesRead;
|
||||
this.bytesWrite = bytesWrite;
|
||||
this.aggBytesWrite = aggBytesWrite;
|
||||
this.aggBytesRead = aggBytesRead;
|
||||
this.eventTimeMillis = eventTimeMillis;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
public void setZoneId(long zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public Long getIORead() {
|
||||
return ioRead;
|
||||
}
|
||||
|
||||
public void setIORead(Long ioRead) {
|
||||
this.ioRead = ioRead;
|
||||
}
|
||||
|
||||
public Long getIOWrite() {
|
||||
return ioWrite;
|
||||
}
|
||||
|
||||
public void setIOWrite(Long ioWrite) {
|
||||
this.ioWrite = ioWrite;
|
||||
}
|
||||
|
||||
public Long getBytesRead() {
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public void setBytesRead(Long bytesRead) {
|
||||
this.bytesRead = bytesRead;
|
||||
}
|
||||
|
||||
public Long getBytesWrite() {
|
||||
return bytesWrite;
|
||||
}
|
||||
|
||||
public void setBytesWrite(Long bytesWrite) {
|
||||
this.bytesWrite = bytesWrite;
|
||||
}
|
||||
|
||||
public long getEventTimeMillis() {
|
||||
return eventTimeMillis;
|
||||
}
|
||||
public void setEventTimeMillis(long eventTimeMillis) {
|
||||
this.eventTimeMillis = eventTimeMillis;
|
||||
}
|
||||
|
||||
public Long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public Long getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
public long getAggIOWrite() {
|
||||
return aggIOWrite;
|
||||
}
|
||||
|
||||
public void setAggIOWrite(long aggIOWrite) {
|
||||
this.aggIOWrite = aggIOWrite;
|
||||
}
|
||||
|
||||
public long getAggIORead() {
|
||||
return aggIORead;
|
||||
}
|
||||
|
||||
public void setAggIORead(long aggIORead) {
|
||||
this.aggIORead = aggIORead;
|
||||
}
|
||||
|
||||
public long getAggBytesWrite() {
|
||||
return aggBytesWrite;
|
||||
}
|
||||
|
||||
public void setAggBytesWrite(long aggBytesWrite) {
|
||||
this.aggBytesWrite = aggBytesWrite;
|
||||
}
|
||||
|
||||
public long getAggBytesRead() {
|
||||
return aggBytesRead;
|
||||
}
|
||||
|
||||
public void setAggBytesRead(long aggBytesRead) {
|
||||
this.aggBytesRead = aggBytesRead;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserStatisticsVO;
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
|
@ -36,4 +37,7 @@ public interface UsageDao extends GenericDao<UsageVO, Long> {
|
|||
Long getLastAccountId();
|
||||
Long getLastUserStatsId();
|
||||
List<Long> listPublicTemplatesByAccount(long accountId);
|
||||
Long getLastVmDiskStatsId();
|
||||
void updateVmDiskStats(List<VmDiskStatisticsVO> vmNetStats);
|
||||
void saveVmDiskStats(List<VmDiskStatisticsVO> vmNetStats);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import org.springframework.stereotype.Component;
|
|||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserStatisticsVO;
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
|
@ -56,6 +57,13 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
private static final String GET_LAST_USER_STATS = "SELECT id FROM cloud_usage.user_statistics ORDER BY id DESC LIMIT 1";
|
||||
private static final String GET_PUBLIC_TEMPLATES_BY_ACCOUNTID = "SELECT id FROM cloud.vm_template WHERE account_id = ? AND public = '1' AND removed IS NULL";
|
||||
|
||||
private static final String GET_LAST_VM_DISK_STATS = "SELECT id FROM cloud_usage.vm_disk_statistics ORDER BY id DESC LIMIT 1";
|
||||
private static final String INSERT_VM_DISK_STATS = "INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, " +
|
||||
"current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) " +
|
||||
" VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
|
||||
private static final String UPDATE_VM_DISK_STATS = "UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, " +
|
||||
"net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
|
||||
|
||||
protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
|
||||
|
||||
public UsageDaoImpl () {}
|
||||
|
|
@ -270,4 +278,101 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
}
|
||||
return templateList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLastVmDiskStatsId() {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
String sql = GET_LAST_VM_DISK_STATS;
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
return Long.valueOf(rs.getLong(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("error getting last vm disk stats id", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVmDiskStats(List<VmDiskStatisticsVO> vmDiskStats) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
String sql = UPDATE_VM_DISK_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
|
||||
pstmt.setLong(1, vmDiskStat.getNetIORead());
|
||||
pstmt.setLong(2, vmDiskStat.getNetIOWrite());
|
||||
pstmt.setLong(3, vmDiskStat.getCurrentIORead());
|
||||
pstmt.setLong(4, vmDiskStat.getCurrentIOWrite());
|
||||
pstmt.setLong(5, vmDiskStat.getAggIORead());
|
||||
pstmt.setLong(6, vmDiskStat.getAggIOWrite());
|
||||
pstmt.setLong(7, vmDiskStat.getNetBytesRead());
|
||||
pstmt.setLong(8, vmDiskStat.getNetBytesWrite());
|
||||
pstmt.setLong(9, vmDiskStat.getCurrentBytesRead());
|
||||
pstmt.setLong(10, vmDiskStat.getCurrentBytesWrite());
|
||||
pstmt.setLong(11, vmDiskStat.getAggBytesRead());
|
||||
pstmt.setLong(12, vmDiskStat.getAggBytesWrite());
|
||||
pstmt.setLong(13, vmDiskStat.getId());
|
||||
pstmt.addBatch();
|
||||
}
|
||||
pstmt.executeBatch();
|
||||
txn.commit();
|
||||
} catch (Exception ex) {
|
||||
txn.rollback();
|
||||
s_logger.error("error saving vm disk stats to cloud_usage db", ex);
|
||||
throw new CloudRuntimeException(ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveVmDiskStats(List<VmDiskStatisticsVO> vmDiskStats) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
String sql = INSERT_VM_DISK_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
|
||||
pstmt.setLong(1, vmDiskStat.getId());
|
||||
pstmt.setLong(2, vmDiskStat.getDataCenterId());
|
||||
pstmt.setLong(3, vmDiskStat.getAccountId());
|
||||
if(vmDiskStat.getVmId() != null){
|
||||
pstmt.setLong(4, vmDiskStat.getVmId());
|
||||
} else {
|
||||
pstmt.setNull(4, Types.BIGINT);
|
||||
}
|
||||
if(vmDiskStat.getVolumeId() != null){
|
||||
pstmt.setLong(5, vmDiskStat.getVolumeId());
|
||||
} else {
|
||||
pstmt.setNull(5, Types.BIGINT);
|
||||
}
|
||||
pstmt.setLong(6, vmDiskStat.getNetIORead());
|
||||
pstmt.setLong(7, vmDiskStat.getNetIOWrite());
|
||||
pstmt.setLong(8, vmDiskStat.getCurrentIORead());
|
||||
pstmt.setLong(9, vmDiskStat.getCurrentIOWrite());
|
||||
pstmt.setLong(10, vmDiskStat.getAggIORead());
|
||||
pstmt.setLong(11, vmDiskStat.getAggIOWrite());
|
||||
pstmt.setLong(12, vmDiskStat.getNetBytesRead());
|
||||
pstmt.setLong(13, vmDiskStat.getNetBytesWrite());
|
||||
pstmt.setLong(14, vmDiskStat.getCurrentBytesRead());
|
||||
pstmt.setLong(15, vmDiskStat.getCurrentBytesWrite());
|
||||
pstmt.setLong(16, vmDiskStat.getAggBytesRead());
|
||||
pstmt.setLong(17, vmDiskStat.getAggBytesWrite());
|
||||
pstmt.addBatch();
|
||||
}
|
||||
pstmt.executeBatch();
|
||||
txn.commit();
|
||||
} catch (Exception ex) {
|
||||
txn.rollback();
|
||||
s_logger.error("error saving vm disk stats to cloud_usage db", ex);
|
||||
throw new CloudRuntimeException(ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// 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.usage.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.usage.UsageVmDiskVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface UsageVmDiskDao extends GenericDao<UsageVmDiskVO, Long> {
|
||||
Map<String, UsageVmDiskVO> getRecentVmDiskStats();
|
||||
void deleteOldStats(long maxEventTime);
|
||||
void saveUsageVmDisks(List<UsageVmDiskVO> usageVmDisks);
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
// 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.usage.dao;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.usage.UsageVmDiskVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
@Local(value={UsageVmDiskDao.class})
|
||||
public class UsageVmDiskDaoImpl extends GenericDaoBase<UsageVmDiskVO, Long> implements UsageVmDiskDao {
|
||||
private static final Logger s_logger = Logger.getLogger(UsageVMInstanceDaoImpl.class.getName());
|
||||
private static final String SELECT_LATEST_STATS = "SELECT uvd.account_id, uvd.zone_id, uvd.vm_id, uvd.volume_id, uvd.io_read, uvd.io_write, uvd.agg_io_read, uvd.agg_io_write, " +
|
||||
"uvd.bytes_read, uvd.bytes_write, uvd.agg_bytes_read, uvd.agg_bytes_write, uvd.event_time_millis " +
|
||||
"FROM cloud_usage.usage_vm_disk uvd INNER JOIN (SELECT vmdiskusage.account_id as acct_id, vmdiskusage.zone_id as z_id, max(vmdiskusage.event_time_millis) as max_date " +
|
||||
"FROM cloud_usage.usage_vm_disk vmdiskusage " +
|
||||
"GROUP BY vmdiskusage.account_id, vmdiskusage.zone_id " +
|
||||
") joinnet on uvd.account_id = joinnet.acct_id and uvd.zone_id = joinnet.z_id and uvd.event_time_millis = joinnet.max_date";
|
||||
private static final String DELETE_OLD_STATS = "DELETE FROM cloud_usage.usage_vm_disk WHERE event_time_millis < ?";
|
||||
|
||||
private static final String INSERT_USAGE_VM_DISK = "INSERT INTO cloud_usage.usage_vm_disk (account_id, zone_id, vm_id, volume_id, io_read, io_write, agg_io_read, agg_io_write, bytes_read, bytes_write, agg_bytes_read, agg_bytes_write, event_time_millis) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
|
||||
public UsageVmDiskDaoImpl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, UsageVmDiskVO> getRecentVmDiskStats() {
|
||||
Transaction txn = Transaction.open(Transaction.USAGE_DB);
|
||||
String sql = SELECT_LATEST_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
Map<String, UsageVmDiskVO> returnMap = new HashMap<String, UsageVmDiskVO>();
|
||||
while (rs.next()) {
|
||||
long accountId = rs.getLong(1);
|
||||
long zoneId = rs.getLong(2);
|
||||
long vmId = rs.getLong(3);
|
||||
Long volumeId = rs.getLong(4);
|
||||
long ioRead = rs.getLong(5);
|
||||
long ioWrite = rs.getLong(6);
|
||||
long aggIORead = rs.getLong(7);
|
||||
long aggIOWrite = rs.getLong(8);
|
||||
long bytesRead = rs.getLong(9);
|
||||
long bytesWrite = rs.getLong(10);
|
||||
long aggBytesRead = rs.getLong(11);
|
||||
long aggBytesWrite = rs.getLong(12);
|
||||
long eventTimeMillis = rs.getLong(13);
|
||||
if(vmId != 0){
|
||||
returnMap.put(zoneId + "-" + accountId+ "-Vm-" + vmId+ "-Disk-" + volumeId, new UsageVmDiskVO(accountId, zoneId, vmId, volumeId, ioRead, ioWrite, aggIORead, aggIOWrite, bytesRead, bytesWrite, aggBytesRead, aggBytesWrite, eventTimeMillis));
|
||||
} else {
|
||||
returnMap.put(zoneId + "-" + accountId, new UsageVmDiskVO(accountId, zoneId, vmId, volumeId, ioRead, ioWrite, aggIORead, aggIOWrite, bytesRead, bytesWrite, aggBytesRead, aggBytesWrite, eventTimeMillis));
|
||||
}
|
||||
}
|
||||
return returnMap;
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("error getting recent usage disk stats", ex);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOldStats(long maxEventTime) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
String sql = DELETE_OLD_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
try {
|
||||
txn.start();
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, maxEventTime);
|
||||
pstmt.executeUpdate();
|
||||
txn.commit();
|
||||
} catch (Exception ex) {
|
||||
txn.rollback();
|
||||
s_logger.error("error deleting old usage disk stats", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveUsageVmDisks(List<UsageVmDiskVO> usageVmDisks) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
String sql = INSERT_USAGE_VM_DISK;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (UsageVmDiskVO usageVmDisk : usageVmDisks) {
|
||||
pstmt.setLong(1, usageVmDisk.getAccountId());
|
||||
pstmt.setLong(2, usageVmDisk.getZoneId());
|
||||
pstmt.setLong(3, usageVmDisk.getVmId());
|
||||
pstmt.setLong(4, usageVmDisk.getVolumeId());
|
||||
pstmt.setLong(5, usageVmDisk.getIORead());
|
||||
pstmt.setLong(6, usageVmDisk.getIOWrite());
|
||||
pstmt.setLong(7, usageVmDisk.getAggIORead());
|
||||
pstmt.setLong(8, usageVmDisk.getAggIOWrite());
|
||||
pstmt.setLong(9, usageVmDisk.getBytesRead());
|
||||
pstmt.setLong(10, usageVmDisk.getBytesWrite());
|
||||
pstmt.setLong(11, usageVmDisk.getAggBytesRead());
|
||||
pstmt.setLong(12, usageVmDisk.getAggBytesWrite());
|
||||
pstmt.setLong(13, usageVmDisk.getEventTimeMillis());
|
||||
pstmt.addBatch();
|
||||
}
|
||||
pstmt.executeBatch();
|
||||
txn.commit();
|
||||
} catch (Exception ex) {
|
||||
txn.rollback();
|
||||
s_logger.error("error saving usage_vm_disk to cloud_usage db", ex);
|
||||
throw new CloudRuntimeException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
// 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.user;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="vm_disk_statistics")
|
||||
public class VmDiskStatisticsVO {
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||
@Column(name="id")
|
||||
private Long id;
|
||||
|
||||
@Column(name="data_center_id", updatable=false)
|
||||
private long dataCenterId;
|
||||
|
||||
@Column(name="account_id", updatable=false)
|
||||
private long accountId;
|
||||
|
||||
@Column(name="vm_id")
|
||||
private Long vmId;
|
||||
|
||||
@Column(name="volume_id")
|
||||
private Long volumeId;
|
||||
|
||||
@Column(name="net_io_read")
|
||||
private long netIORead;
|
||||
|
||||
@Column(name="net_io_write")
|
||||
private long netIOWrite;
|
||||
|
||||
@Column(name="current_io_read")
|
||||
private long currentIORead;
|
||||
|
||||
@Column(name="current_io_write")
|
||||
private long currentIOWrite;
|
||||
|
||||
@Column(name="agg_io_read")
|
||||
private long aggIORead;
|
||||
|
||||
@Column(name="agg_io_write")
|
||||
private long aggIOWrite;
|
||||
|
||||
@Column(name="net_bytes_read")
|
||||
private long netBytesRead;
|
||||
|
||||
@Column(name="net_bytes_write")
|
||||
private long netBytesWrite;
|
||||
|
||||
@Column(name="current_bytes_read")
|
||||
private long currentBytesRead;
|
||||
|
||||
@Column(name="current_bytes_write")
|
||||
private long currentBytesWrite;
|
||||
|
||||
@Column(name="agg_bytes_read")
|
||||
private long aggBytesRead;
|
||||
|
||||
@Column(name="agg_bytes_write")
|
||||
private long aggBytesWrite;
|
||||
|
||||
protected VmDiskStatisticsVO() {
|
||||
}
|
||||
|
||||
public VmDiskStatisticsVO(long accountId, long dcId, Long vmId, Long volumeId) {
|
||||
this.accountId = accountId;
|
||||
this.dataCenterId = dcId;
|
||||
this.vmId = vmId;
|
||||
this.volumeId = volumeId;
|
||||
this.netBytesRead = 0;
|
||||
this.netBytesWrite = 0;
|
||||
this.currentBytesRead = 0;
|
||||
this.currentBytesWrite = 0;
|
||||
this.netBytesRead = 0;
|
||||
this.netBytesWrite = 0;
|
||||
this.currentBytesRead = 0;
|
||||
this.currentBytesWrite = 0;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getDataCenterId() {
|
||||
return dataCenterId;
|
||||
}
|
||||
|
||||
public Long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public Long getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
public long getCurrentIORead() {
|
||||
return currentIORead;
|
||||
}
|
||||
|
||||
public void setCurrentIORead(long currentIORead) {
|
||||
this.currentIORead = currentIORead;
|
||||
}
|
||||
|
||||
public long getCurrentIOWrite() {
|
||||
return currentIOWrite;
|
||||
}
|
||||
|
||||
public void setCurrentIOWrite(long currentIOWrite) {
|
||||
this.currentIOWrite = currentIOWrite;
|
||||
}
|
||||
|
||||
public long getNetIORead() {
|
||||
return netIORead;
|
||||
}
|
||||
|
||||
public long getNetIOWrite() {
|
||||
return netIOWrite;
|
||||
}
|
||||
|
||||
public void setNetIORead(long netIORead) {
|
||||
this.netIORead = netIORead;
|
||||
}
|
||||
|
||||
public void setNetIOWrite(long netIOWrite) {
|
||||
this.netIOWrite = netIOWrite;
|
||||
}
|
||||
|
||||
public long getAggIORead() {
|
||||
return aggIORead;
|
||||
}
|
||||
|
||||
public void setAggIORead(long aggIORead) {
|
||||
this.aggIORead = aggIORead;
|
||||
}
|
||||
|
||||
public long getAggIOWrite() {
|
||||
return aggIOWrite;
|
||||
}
|
||||
|
||||
public void setAggIOWrite(long aggIOWrite) {
|
||||
this.aggIOWrite = aggIOWrite;
|
||||
}
|
||||
|
||||
public long getCurrentBytesRead() {
|
||||
return currentBytesRead;
|
||||
}
|
||||
|
||||
public void setCurrentBytesRead(long currentBytesRead) {
|
||||
this.currentBytesRead = currentBytesRead;
|
||||
}
|
||||
|
||||
public long getCurrentBytesWrite() {
|
||||
return currentBytesWrite;
|
||||
}
|
||||
|
||||
public void setCurrentBytesWrite(long currentBytesWrite) {
|
||||
this.currentBytesWrite = currentBytesWrite;
|
||||
}
|
||||
|
||||
public long getNetBytesRead() {
|
||||
return netBytesRead;
|
||||
}
|
||||
|
||||
public long getNetBytesWrite() {
|
||||
return netBytesWrite;
|
||||
}
|
||||
|
||||
public void setNetBytesRead(long netBytesRead) {
|
||||
this.netBytesRead = netBytesRead;
|
||||
}
|
||||
|
||||
public void setNetBytesWrite(long netBytesWrite) {
|
||||
this.netBytesWrite = netBytesWrite;
|
||||
}
|
||||
|
||||
public long getAggBytesRead() {
|
||||
return aggBytesRead;
|
||||
}
|
||||
|
||||
public void setAggBytesRead(long aggBytesRead) {
|
||||
this.aggBytesRead = aggBytesRead;
|
||||
}
|
||||
|
||||
public long getAggBytesWrite() {
|
||||
return aggBytesWrite;
|
||||
}
|
||||
|
||||
public void setAggBytesWrite(long aggBytesWrite) {
|
||||
this.aggBytesWrite = aggBytesWrite;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// 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.user.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface VmDiskStatisticsDao extends GenericDao<VmDiskStatisticsVO, Long> {
|
||||
VmDiskStatisticsVO findBy(long accountId, long dcId, long vmId, long volumeId);
|
||||
|
||||
VmDiskStatisticsVO lock(long accountId, long dcId, long vmId, long volumeId);
|
||||
|
||||
List<VmDiskStatisticsVO> listBy(long accountId);
|
||||
|
||||
List<VmDiskStatisticsVO> listActiveAndRecentlyDeleted(Date minRemovedDate, int startIndex, int limit);
|
||||
|
||||
List<VmDiskStatisticsVO> listUpdatedStats();
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// 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.user.dao;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
|
||||
@Component
|
||||
@Local(value={VmDiskStatisticsDao.class})
|
||||
public class VmDiskStatisticsDaoImpl extends GenericDaoBase<VmDiskStatisticsVO, Long> implements VmDiskStatisticsDao {
|
||||
private static final Logger s_logger = Logger.getLogger(VmDiskStatisticsDaoImpl.class);
|
||||
private static final String ACTIVE_AND_RECENTLY_DELETED_SEARCH = "SELECT vns.id, vns.data_center_id, vns.account_id, vns.vm_id, vns.volume_id, vns.agg_io_read, vns.agg_io_write, vns.agg_bytes_read, vns.agg_bytes_write " +
|
||||
"FROM vm_disk_statistics vns, account a " +
|
||||
"WHERE vns.account_id = a.id AND (a.removed IS NULL OR a.removed >= ?) " +
|
||||
"ORDER BY vns.id";
|
||||
private static final String UPDATED_VM_NETWORK_STATS_SEARCH = "SELECT id, current_io_read, current_io_write, net_io_read, net_io_write, agg_io_read, agg_io_write, " +
|
||||
"current_bytes_read, current_bytes_write, net_bytes_read, net_bytes_write, agg_bytes_read, agg_bytes_write " +
|
||||
"from vm_disk_statistics " +
|
||||
"where (agg_io_read < net_io_read + current_io_read) OR (agg_io_write < net_io_write + current_io_write) OR " +
|
||||
"(agg_bytes_read < net_bytes_read + current_bytes_read) OR (agg_bytes_write < net_bytes_write + current_bytes_write)";
|
||||
private final SearchBuilder<VmDiskStatisticsVO> AllFieldsSearch;
|
||||
private final SearchBuilder<VmDiskStatisticsVO> AccountSearch;
|
||||
|
||||
|
||||
public VmDiskStatisticsDaoImpl() {
|
||||
AccountSearch = createSearchBuilder();
|
||||
AccountSearch.and("account", AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountSearch.done();
|
||||
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("dc", AllFieldsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("volume", AllFieldsSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("vm", AllFieldsSearch.entity().getVmId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmDiskStatisticsVO findBy(long accountId, long dcId, long vmId, long volumeId) {
|
||||
SearchCriteria<VmDiskStatisticsVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("account", accountId);
|
||||
sc.setParameters("dc", dcId);
|
||||
sc.setParameters("volume", volumeId);
|
||||
sc.setParameters("vm", vmId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmDiskStatisticsVO lock(long accountId, long dcId, long vmId, long volumeId) {
|
||||
SearchCriteria<VmDiskStatisticsVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("account", accountId);
|
||||
sc.setParameters("dc", dcId);
|
||||
sc.setParameters("volume", volumeId);
|
||||
sc.setParameters("vm", vmId);
|
||||
return lockOneRandomRow(sc, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VmDiskStatisticsVO> listBy(long accountId) {
|
||||
SearchCriteria<VmDiskStatisticsVO> sc = AccountSearch.create();
|
||||
sc.setParameters("account", accountId);
|
||||
return search(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VmDiskStatisticsVO> listActiveAndRecentlyDeleted(Date minRemovedDate, int startIndex, int limit) {
|
||||
List<VmDiskStatisticsVO> vmDiskStats = new ArrayList<VmDiskStatisticsVO>();
|
||||
if (minRemovedDate == null) return vmDiskStats;
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
String sql = ACTIVE_AND_RECENTLY_DELETED_SEARCH + " LIMIT " + startIndex + "," + limit;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), minRemovedDate));
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
vmDiskStats.add(toEntityBean(rs, false));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("error saving vm disk stats to cloud_usage db", ex);
|
||||
}
|
||||
return vmDiskStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VmDiskStatisticsVO> listUpdatedStats() {
|
||||
List<VmDiskStatisticsVO> vmDiskStats = new ArrayList<VmDiskStatisticsVO>();
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(UPDATED_VM_NETWORK_STATS_SEARCH);
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
vmDiskStats.add(toEntityBean(rs, false));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("error lisitng updated vm disk stats", ex);
|
||||
}
|
||||
return vmDiskStats;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -57,6 +57,10 @@ public class UserVmData {
|
|||
private String cpuUsed;
|
||||
private Long networkKbsRead;
|
||||
private Long networkKbsWrite;
|
||||
private Long diskKbsRead;
|
||||
private Long diskKbsWrite;
|
||||
private Long diskIORead;
|
||||
private Long diskIOWrite;
|
||||
private Long guestOsId;
|
||||
private Long rootDeviceId;
|
||||
private String rootDeviceType;
|
||||
|
|
@ -364,6 +368,38 @@ public class UserVmData {
|
|||
this.networkKbsWrite = networkKbsWrite;
|
||||
}
|
||||
|
||||
public Long getDiskKbsRead() {
|
||||
return diskKbsRead;
|
||||
}
|
||||
|
||||
public void setDiskKbsRead(Long diskKbsRead) {
|
||||
this.diskKbsRead = diskKbsRead;
|
||||
}
|
||||
|
||||
public Long getDiskKbsWrite() {
|
||||
return diskKbsWrite;
|
||||
}
|
||||
|
||||
public void setDiskKbsWrite(Long diskKbsWrite) {
|
||||
this.diskKbsWrite = diskKbsWrite;
|
||||
}
|
||||
|
||||
public Long getDiskIORead() {
|
||||
return diskIORead;
|
||||
}
|
||||
|
||||
public void setDiskIORead(Long diskIORead) {
|
||||
this.diskIORead = diskIORead;
|
||||
}
|
||||
|
||||
public Long getDiskIOWrite() {
|
||||
return diskIOWrite;
|
||||
}
|
||||
|
||||
public void setDiskIOWrite(Long diskIOWrite) {
|
||||
this.diskIOWrite = diskIOWrite;
|
||||
}
|
||||
|
||||
public Long getGuestOsId() {
|
||||
return guestOsId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
|||
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.DomainBlockStats;
|
||||
import org.libvirt.DomainInfo;
|
||||
import org.libvirt.DomainInterfaceStats;
|
||||
import org.libvirt.DomainSnapshot;
|
||||
|
|
@ -99,6 +100,8 @@ import com.cloud.agent.api.GetHostStatsAnswer;
|
|||
import com.cloud.agent.api.GetHostStatsCommand;
|
||||
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.GetVmStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.GetVncPortAnswer;
|
||||
|
|
@ -145,6 +148,7 @@ import com.cloud.agent.api.StopCommand;
|
|||
import com.cloud.agent.api.UnPlugNicAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicCommand;
|
||||
import com.cloud.agent.api.UpgradeSnapshotCommand;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshCommand;
|
||||
|
|
@ -1117,6 +1121,8 @@ ServerResource {
|
|||
return execute((StopCommand) cmd);
|
||||
} else if (cmd instanceof GetVmStatsCommand) {
|
||||
return execute((GetVmStatsCommand) cmd);
|
||||
} else if (cmd instanceof GetVmDiskStatsCommand) {
|
||||
return execute((GetVmDiskStatsCommand) cmd);
|
||||
} else if (cmd instanceof RebootRouterCommand) {
|
||||
return execute((RebootRouterCommand) cmd);
|
||||
} else if (cmd instanceof RebootCommand) {
|
||||
|
|
@ -3007,6 +3013,26 @@ ServerResource {
|
|||
}
|
||||
}
|
||||
|
||||
protected GetVmDiskStatsAnswer execute(GetVmDiskStatsCommand cmd) {
|
||||
List<String> vmNames = cmd.getVmNames();
|
||||
try {
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsNameMap = new HashMap<String, List<VmDiskStatsEntry>>();
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
for (String vmName : vmNames) {
|
||||
List<VmDiskStatsEntry> statEntry = getVmDiskStat(conn, vmName);
|
||||
if (statEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vmDiskStatsNameMap.put(vmName, statEntry);
|
||||
}
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(), vmDiskStatsNameMap);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Can't get vm disk stats: " + e.toString());
|
||||
return new GetVmDiskStatsAnswer(cmd, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) {
|
||||
List<String> vmNames = cmd.getVmNames();
|
||||
try {
|
||||
|
|
@ -4512,10 +4538,46 @@ ServerResource {
|
|||
}
|
||||
}
|
||||
|
||||
private List<VmDiskStatsEntry> getVmDiskStat(Connect conn, String vmName)
|
||||
throws LibvirtException {
|
||||
Domain dm = null;
|
||||
try {
|
||||
dm = getDomain(conn, vmName);
|
||||
|
||||
List<VmDiskStatsEntry> stats = new ArrayList<VmDiskStatsEntry>();
|
||||
|
||||
List<DiskDef> disks = getDisks(conn, vmName);
|
||||
|
||||
for (DiskDef disk : disks) {
|
||||
DomainBlockStats blockStats = dm.blockStats(disk.getDiskLabel());
|
||||
String path = disk.getDiskPath(); // for example, path = /mnt/pool_uuid/disk_path/
|
||||
String diskPath = null;
|
||||
if (path != null) {
|
||||
String[] token = path.split("/");
|
||||
if (token.length > 3) {
|
||||
diskPath = token[3];
|
||||
VmDiskStatsEntry stat = new VmDiskStatsEntry(vmName, diskPath, blockStats.wr_req, blockStats.rd_req, blockStats.wr_bytes, blockStats.rd_bytes);
|
||||
stats.add(stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
} finally {
|
||||
if (dm != null) {
|
||||
dm.free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class vmStats {
|
||||
long _usedTime;
|
||||
long _tx;
|
||||
long _rx;
|
||||
long _io_rd;
|
||||
long _io_wr;
|
||||
long _bytes_rd;
|
||||
long _bytes_wr;
|
||||
Calendar _timestamp;
|
||||
}
|
||||
|
||||
|
|
@ -4572,10 +4634,44 @@ ServerResource {
|
|||
stats.setNetworkWriteKBs(deltatx / 1024);
|
||||
}
|
||||
|
||||
/* get disk stats */
|
||||
List<DiskDef> disks = getDisks(conn, vmName);
|
||||
long io_rd = 0;
|
||||
long io_wr = 0;
|
||||
long bytes_rd = 0;
|
||||
long bytes_wr = 0;
|
||||
for (DiskDef disk : disks) {
|
||||
DomainBlockStats blockStats = dm.blockStats(disk.getDiskLabel());
|
||||
io_rd += blockStats.rd_req;
|
||||
io_wr += blockStats.wr_req;
|
||||
bytes_rd += blockStats.rd_bytes;
|
||||
bytes_wr += blockStats.wr_bytes;
|
||||
}
|
||||
|
||||
if (oldStats != null) {
|
||||
long deltaiord = io_rd - oldStats._io_rd;
|
||||
if (deltaiord > 0)
|
||||
stats.setDiskReadIOs(deltaiord);
|
||||
long deltaiowr = io_wr - oldStats._io_wr;
|
||||
if (deltaiowr > 0)
|
||||
stats.setDiskWriteIOs(deltaiowr);
|
||||
long deltabytesrd = bytes_rd - oldStats._bytes_rd;
|
||||
if (deltabytesrd > 0)
|
||||
stats.setDiskReadKBs(deltabytesrd / 1024);
|
||||
long deltabyteswr = bytes_wr - oldStats._bytes_wr;
|
||||
if (deltabyteswr > 0)
|
||||
stats.setDiskWriteKBs(deltabyteswr / 1024);
|
||||
}
|
||||
|
||||
/* save to Hashmap */
|
||||
vmStats newStat = new vmStats();
|
||||
newStat._usedTime = info.cpuTime;
|
||||
newStat._rx = rx;
|
||||
newStat._tx = tx;
|
||||
newStat._io_rd = io_rd;
|
||||
newStat._io_wr = io_wr;
|
||||
newStat._bytes_rd = bytes_rd;
|
||||
newStat._bytes_wr = bytes_wr;
|
||||
newStat._timestamp = now;
|
||||
_vmStats.put(vmName, newStat);
|
||||
return stats;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ import com.cloud.agent.api.GetHostStatsAnswer;
|
|||
import com.cloud.agent.api.GetHostStatsCommand;
|
||||
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.GetVmStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.GetVncPortAnswer;
|
||||
|
|
@ -111,6 +113,7 @@ import com.cloud.agent.api.UnPlugNicAnswer;
|
|||
import com.cloud.agent.api.UnPlugNicCommand;
|
||||
import com.cloud.agent.api.UpdateHostPasswordCommand;
|
||||
import com.cloud.agent.api.UpgradeSnapshotCommand;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshCommand;
|
||||
|
|
@ -236,6 +239,7 @@ import com.xensource.xenapi.Types.VmBadPowerState;
|
|||
import com.xensource.xenapi.Types.VmPowerState;
|
||||
import com.xensource.xenapi.Types.XenAPIException;
|
||||
import com.xensource.xenapi.VBD;
|
||||
import com.xensource.xenapi.VBDMetrics;
|
||||
import com.xensource.xenapi.VDI;
|
||||
import com.xensource.xenapi.VIF;
|
||||
import com.xensource.xenapi.VLAN;
|
||||
|
|
@ -482,6 +486,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
return execute((GetHostStatsCommand) cmd);
|
||||
} else if (clazz == GetVmStatsCommand.class) {
|
||||
return execute((GetVmStatsCommand) cmd);
|
||||
} else if (cmd instanceof GetVmDiskStatsCommand) {
|
||||
return execute((GetVmDiskStatsCommand) cmd);
|
||||
} else if (clazz == CheckHealthCommand.class) {
|
||||
return execute((CheckHealthCommand) cmd);
|
||||
} else if (clazz == StopCommand.class) {
|
||||
|
|
@ -2584,6 +2590,80 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
return hostStats;
|
||||
}
|
||||
|
||||
protected GetVmDiskStatsAnswer execute( GetVmDiskStatsCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
List<String> vmNames = cmd.getVmNames();
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsNameMap = new HashMap<String, List<VmDiskStatsEntry>>();
|
||||
if( vmNames.size() == 0 ) {
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap);
|
||||
}
|
||||
try {
|
||||
|
||||
// Determine the UUIDs of the requested VMs
|
||||
List<String> vmUUIDs = new ArrayList<String>();
|
||||
|
||||
for (String vmName : vmNames) {
|
||||
VM vm = getVM(conn, vmName);
|
||||
vmUUIDs.add(vm.getUuid(conn));
|
||||
}
|
||||
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsUUIDMap = getVmDiskStats(conn, cmd, vmUUIDs, cmd.getHostGuid());
|
||||
if( vmDiskStatsUUIDMap == null ) {
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(), vmDiskStatsNameMap);
|
||||
}
|
||||
|
||||
for (String vmUUID : vmDiskStatsUUIDMap.keySet()) {
|
||||
List<VmDiskStatsEntry> vmDiskStatsUUID = vmDiskStatsUUIDMap.get(vmUUID);
|
||||
String vmName = vmNames.get(vmUUIDs.indexOf(vmUUID));
|
||||
for (VmDiskStatsEntry vmDiskStat : vmDiskStatsUUID) {
|
||||
vmDiskStat.setVmName(vmName);
|
||||
}
|
||||
vmDiskStatsNameMap.put(vmName, vmDiskStatsUUID);
|
||||
}
|
||||
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap);
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "Unable to get VM disk stats" + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap);
|
||||
} catch (XmlRpcException e) {
|
||||
String msg = "Unable to get VM disk stats" + e.getMessage();
|
||||
s_logger.warn(msg, e);
|
||||
return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, List<VmDiskStatsEntry>> getVmDiskStats(Connection conn, GetVmDiskStatsCommand cmd, List<String> vmUUIDs, String hostGuid) {
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmResponseMap = new HashMap<String, List<VmDiskStatsEntry>>();
|
||||
|
||||
for (String vmUUID : vmUUIDs) {
|
||||
vmResponseMap.put(vmUUID, new ArrayList<VmDiskStatsEntry>());
|
||||
}
|
||||
|
||||
try {
|
||||
for (String vmUUID : vmUUIDs) {
|
||||
VM vm = VM.getByUuid(conn, vmUUID);
|
||||
List<VmDiskStatsEntry> vmDiskStats = new ArrayList<VmDiskStatsEntry>();
|
||||
for (VBD vbd : vm.getVBDs(conn)) {
|
||||
if (!vbd.getType(conn).equals(Types.VbdType.CD)) {
|
||||
VmDiskStatsEntry stats = new VmDiskStatsEntry();
|
||||
VBDMetrics record = vbd.getMetrics(conn);
|
||||
stats.setPath(vbd.getVDI(conn).getUuid(conn));
|
||||
stats.setBytesRead((long)(record.getIoReadKbs(conn) * 1024));
|
||||
stats.setBytesWrite((long)(record.getIoWriteKbs(conn) * 1024));
|
||||
vmDiskStats.add(stats);
|
||||
}
|
||||
}
|
||||
vmResponseMap.put(vmUUID, vmDiskStats);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Error while collecting disk stats from : ", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return vmResponseMap;
|
||||
}
|
||||
|
||||
protected GetVmStatsAnswer execute( GetVmStatsCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
List<String> vmNames = cmd.getVmNames();
|
||||
|
|
@ -2693,6 +2773,29 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (String vmUUID : vmUUIDs) {
|
||||
VM vm = VM.getByUuid(conn, vmUUID);
|
||||
VmStatsEntry stats = vmResponseMap.get(vmUUID);
|
||||
double diskReadKBs = 0;
|
||||
double diskWriteKBs = 0;
|
||||
for (VBD vbd : vm.getVBDs(conn)) {
|
||||
VBDMetrics record = vbd.getMetrics(conn);
|
||||
diskReadKBs += record.getIoReadKbs(conn);
|
||||
diskWriteKBs += record.getIoWriteKbs(conn);
|
||||
}
|
||||
if (stats == null) {
|
||||
stats = new VmStatsEntry();
|
||||
}
|
||||
stats.setDiskReadKBs(diskReadKBs);
|
||||
stats.setDiskWriteKBs(diskWriteKBs);
|
||||
vmResponseMap.put(vmUUID, stats);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Error while collecting disk stats from : ", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return vmResponseMap;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3397,6 +3397,17 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString());
|
||||
usageRecResponse.setNetworkId(network.getUuid());
|
||||
|
||||
} else if(usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE ||
|
||||
usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE){
|
||||
//Device Type
|
||||
usageRecResponse.setType(usageRecord.getType());
|
||||
//VM Instance Id
|
||||
VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString());
|
||||
usageRecResponse.setUsageId(vm.getUuid());
|
||||
//Volume ID
|
||||
VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString());
|
||||
usageRecResponse.setUsageId(volume.getUuid());
|
||||
|
||||
} else if(usageRecord.getUsageType() == UsageTypes.VOLUME){
|
||||
//Volume ID
|
||||
VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString());
|
||||
|
|
|
|||
|
|
@ -160,6 +160,18 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
|
|||
|
||||
Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
|
||||
userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
|
||||
|
||||
Double diskKbsRead = Double.valueOf(vmStats.getDiskReadKBs());
|
||||
userVmResponse.setDiskKbsRead(diskKbsRead.longValue());
|
||||
|
||||
Double diskKbsWrite = Double.valueOf(vmStats.getDiskWriteKBs());
|
||||
userVmResponse.setDiskKbsWrite(diskKbsWrite.longValue());
|
||||
|
||||
Double diskIORead = Double.valueOf(vmStats.getDiskReadIOs());
|
||||
userVmResponse.setDiskIORead(diskIORead.longValue());
|
||||
|
||||
Double diskIOWrite = Double.valueOf(vmStats.getDiskWriteIOs());
|
||||
userVmResponse.setDiskIOWrite(diskIOWrite.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ public enum Config {
|
|||
NetworkGcInterval("Advanced", ManagementServer.class, Integer.class, "network.gc.interval", "600", "Seconds to wait before checking for networks to shutdown", null),
|
||||
CapacitySkipcountingHours("Advanced", ManagementServer.class, Integer.class, "capacity.skipcounting.hours", "3600", "Time (in seconds) to wait before release VM's cpu and memory when VM in stopped state", null),
|
||||
VmStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.stats.interval", "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),
|
||||
VmTransitionWaitInterval("Advanced", ManagementServer.class, Integer.class, "vm.tranisition.wait.interval", "3600", "Time (in seconds) to wait before taking over a VM in transition state", null),
|
||||
VmDestroyForcestop("Advanced", ManagementServer.class, Boolean.class, "vm.destroy.forcestop", "false", "On destroy, force-stop takes this value ", null),
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,14 @@
|
|||
package com.cloud.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
|
@ -45,8 +48,11 @@ import com.cloud.agent.api.Answer;
|
|||
import com.cloud.agent.api.GetFileStatsCommand;
|
||||
import com.cloud.agent.api.GetStorageStatsCommand;
|
||||
import com.cloud.agent.api.HostStatsEntry;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.host.Host;
|
||||
|
|
@ -59,19 +65,31 @@ import com.cloud.resource.ResourceState;
|
|||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePoolHostVO;
|
||||
import com.cloud.storage.StorageStats;
|
||||
import com.cloud.storage.Volume;
|
||||
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.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.user.UserStatisticsVO;
|
||||
import com.cloud.user.UserStatsLogVO;
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.user.dao.VmDiskStatisticsDao;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.component.ComponentMethodInterceptable;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
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.VmStats;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
|
||||
/**
|
||||
|
|
@ -96,6 +114,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
@Inject private SecondaryStorageVmManager _ssvmMgr;
|
||||
@Inject private ResourceManager _resourceMgr;
|
||||
@Inject private ConfigurationDao _configDao;
|
||||
@Inject private VmDiskStatisticsDao _vmDiskStatsDao;
|
||||
@Inject private ManagementServerHostDao _msHostDao;
|
||||
|
||||
private ConcurrentHashMap<Long, HostStats> _hostStats = new ConcurrentHashMap<Long, HostStats>();
|
||||
private final ConcurrentHashMap<Long, VmStats> _VmStats = new ConcurrentHashMap<Long, VmStats>();
|
||||
|
|
@ -107,6 +127,15 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
long hostAndVmStatsInterval = -1L;
|
||||
long storageStatsInterval = -1L;
|
||||
long volumeStatsInterval = -1L;
|
||||
int vmDiskStatsInterval = 0;
|
||||
|
||||
private ScheduledExecutorService _diskStatsUpdateExecutor;
|
||||
private int _usageAggregationRange = 1440;
|
||||
private String _usageTimeZone = "GMT";
|
||||
private final long mgmtSrvrId = MacAddress.getMacAddress().toLong();
|
||||
private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 5; // 5 seconds
|
||||
private static final int USAGE_AGGREGATION_RANGE_MIN = 10; // 10 minutes, same to com.cloud.usage.UsageManagerImpl.USAGE_AGGREGATION_RANGE_MIN
|
||||
private boolean _dailyOrHourly = false;
|
||||
|
||||
//private final GlobalLock m_capacityCheckLock = GlobalLock.getInternLock("capacity.check");
|
||||
|
||||
|
|
@ -136,6 +165,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
hostAndVmStatsInterval = NumbersUtil.parseLong(configs.get("vm.stats.interval"), 60000L);
|
||||
storageStatsInterval = NumbersUtil.parseLong(configs.get("storage.stats.interval"), 60000L);
|
||||
volumeStatsInterval = NumbersUtil.parseLong(configs.get("volume.stats.interval"), -1L);
|
||||
vmDiskStatsInterval = NumbersUtil.parseInt(configs.get("vm.disk.stats.interval"), 0);
|
||||
|
||||
if (hostStatsInterval > 0) {
|
||||
_executor.scheduleWithFixedDelay(new HostCollector(), 15000L, hostStatsInterval, TimeUnit.MILLISECONDS);
|
||||
|
|
@ -148,6 +178,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
if (storageStatsInterval > 0) {
|
||||
_executor.scheduleWithFixedDelay(new StorageCollector(), 15000L, storageStatsInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
if (vmDiskStatsInterval > 0) {
|
||||
if (vmDiskStatsInterval < 300)
|
||||
vmDiskStatsInterval = 300;
|
||||
_executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// -1 means we don't even start this thread to pick up any data.
|
||||
if (volumeStatsInterval > 0) {
|
||||
|
|
@ -155,6 +191,49 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
} else {
|
||||
s_logger.info("Disabling volume stats collector");
|
||||
}
|
||||
|
||||
//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");
|
||||
if(_usageTimeZone == null){
|
||||
_usageTimeZone = "GMT";
|
||||
}
|
||||
TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone);
|
||||
Calendar cal = Calendar.getInstance(usageTimezone);
|
||||
cal.setTime(new Date());
|
||||
long endDate = 0;
|
||||
int HOURLY_TIME = 60;
|
||||
final int DAILY_TIME = 60 * 24;
|
||||
if (_usageAggregationRange == DAILY_TIME) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.roll(Calendar.DAY_OF_YEAR, true);
|
||||
cal.add(Calendar.MILLISECOND, -1);
|
||||
endDate = cal.getTime().getTime();
|
||||
_dailyOrHourly = true;
|
||||
} else if (_usageAggregationRange == HOURLY_TIME) {
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.roll(Calendar.HOUR_OF_DAY, true);
|
||||
cal.add(Calendar.MILLISECOND, -1);
|
||||
endDate = cal.getTime().getTime();
|
||||
_dailyOrHourly = true;
|
||||
} else {
|
||||
endDate = cal.getTime().getTime();
|
||||
_dailyOrHourly = false;
|
||||
}
|
||||
if (_usageAggregationRange < USAGE_AGGREGATION_RANGE_MIN) {
|
||||
s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + USAGE_AGGREGATION_RANGE_MIN);
|
||||
_usageAggregationRange = USAGE_AGGREGATION_RANGE_MIN;
|
||||
}
|
||||
_diskStatsUpdateExecutor.scheduleAtFixedRate(new VmDiskStatsUpdaterTask(), (endDate - System.currentTimeMillis()),
|
||||
(_usageAggregationRange * 60 * 1000), TimeUnit.MILLISECONDS);
|
||||
|
||||
}
|
||||
|
||||
class HostCollector implements Runnable {
|
||||
|
|
@ -249,6 +328,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
statsInMemory.setNumCPUs(statsForCurrentIteration.getNumCPUs());
|
||||
statsInMemory.setNetworkReadKBs(statsInMemory.getNetworkReadKBs() + statsForCurrentIteration.getNetworkReadKBs());
|
||||
statsInMemory.setNetworkWriteKBs(statsInMemory.getNetworkWriteKBs() + statsForCurrentIteration.getNetworkWriteKBs());
|
||||
statsInMemory.setDiskWriteKBs(statsInMemory.getDiskWriteKBs() + statsForCurrentIteration.getDiskWriteKBs());
|
||||
statsInMemory.setDiskReadIOs(statsInMemory.getDiskReadIOs() + statsForCurrentIteration.getDiskReadIOs());
|
||||
statsInMemory.setDiskWriteIOs(statsInMemory.getDiskWriteIOs() + statsForCurrentIteration.getDiskWriteIOs());
|
||||
statsInMemory.setDiskReadKBs(statsInMemory.getDiskReadKBs() + statsForCurrentIteration.getDiskReadKBs());
|
||||
|
||||
_VmStats.put(vmId, statsInMemory);
|
||||
}
|
||||
|
|
@ -270,6 +353,175 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
|||
public VmStats getVmStats(long id) {
|
||||
return _VmStats.get(id);
|
||||
}
|
||||
|
||||
class VmDiskStatsUpdaterTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
GlobalLock scanLock = GlobalLock.getInternLock("vm.disk.stats");
|
||||
try {
|
||||
if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
|
||||
//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 aggregate disk stats update");
|
||||
scanLock.unlock();
|
||||
return;
|
||||
}
|
||||
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
|
||||
try {
|
||||
txn.start();
|
||||
//get all stats with delta > 0
|
||||
List<VmDiskStatisticsVO> updatedVmNetStats = _vmDiskStatsDao.listUpdatedStats();
|
||||
for(VmDiskStatisticsVO stat : updatedVmNetStats){
|
||||
if (_dailyOrHourly) {
|
||||
//update agg bytes
|
||||
stat.setAggBytesRead(stat.getCurrentBytesRead() + stat.getNetBytesRead());
|
||||
stat.setAggBytesWrite(stat.getCurrentBytesWrite() + stat.getNetBytesWrite());
|
||||
stat.setAggIORead(stat.getCurrentIORead() + stat.getNetIORead());
|
||||
stat.setAggIOWrite(stat.getCurrentIOWrite() + stat.getNetIOWrite());
|
||||
_vmDiskStatsDao.update(stat.getId(), stat);
|
||||
}
|
||||
}
|
||||
s_logger.debug("Successfully updated aggregate vm disk stats");
|
||||
txn.commit();
|
||||
} catch (Exception e){
|
||||
txn.rollback();
|
||||
s_logger.debug("Failed to update aggregate disk stats", e);
|
||||
} finally {
|
||||
scanLock.unlock();
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
s_logger.debug("Exception while trying to acquire disk stats lock", e);
|
||||
} finally {
|
||||
scanLock.releaseRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VmDiskStatsTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03.
|
||||
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
|
||||
try {
|
||||
txn.start();
|
||||
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<VmDiskStatsEntry>> vmDiskStatsById = _userVmMgr.getVmDiskStatistics(host.getId(), host.getName(), vmIds);
|
||||
if (vmDiskStatsById == null)
|
||||
continue;
|
||||
|
||||
Set<Long> vmIdSet = vmDiskStatsById.keySet();
|
||||
for(Long vmId : vmIdSet)
|
||||
{
|
||||
List<VmDiskStatsEntry> vmDiskStats = vmDiskStatsById.get(vmId);
|
||||
if (vmDiskStats == null)
|
||||
continue;
|
||||
UserVmVO userVm = _userVmDao.findById(vmId);
|
||||
for (VmDiskStatsEntry vmDiskStat:vmDiskStats) {
|
||||
SearchCriteria<VolumeVO> sc_volume = _volsDao.createSearchCriteria();
|
||||
sc_volume.addAnd("path", SearchCriteria.Op.EQ, vmDiskStat.getPath());
|
||||
VolumeVO volume = _volsDao.search(sc_volume, null).get(0);
|
||||
VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId());
|
||||
VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId());
|
||||
|
||||
if ((vmDiskStat.getBytesRead() == 0) && (vmDiskStat.getBytesWrite() == 0)
|
||||
&& (vmDiskStat.getIORead() == 0) && (vmDiskStat.getIOWrite() == 0)) {
|
||||
s_logger.debug("IO/bytes read and write are all 0. Not updating vm_disk_statistics");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vmDiskStat_lock == null) {
|
||||
s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and volumeId:" + volume.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (previousVmDiskStats != null
|
||||
&& ((previousVmDiskStats.getCurrentBytesRead() != vmDiskStat_lock.getCurrentBytesRead())
|
||||
|| (previousVmDiskStats.getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())
|
||||
|| (previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead())
|
||||
|| (previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock.getCurrentIOWrite()))) {
|
||||
s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " +
|
||||
"Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Read(Bytes): " + vmDiskStat.getBytesRead() + " write(Bytes): " + vmDiskStat.getBytesWrite() +
|
||||
" Read(IO): " + vmDiskStat.getIORead() + " write(IO): " + vmDiskStat.getIOWrite());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vmDiskStat_lock.getCurrentBytesRead() > vmDiskStat.getBytesRead()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Read # of bytes that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getBytesRead() + " Stored: " + vmDiskStat_lock.getCurrentBytesRead());
|
||||
}
|
||||
vmDiskStat_lock.setNetBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentBytesRead(vmDiskStat.getBytesRead());
|
||||
if (vmDiskStat_lock.getCurrentBytesWrite() > vmDiskStat.getBytesWrite()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Write # of bytes that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getBytesWrite() + " Stored: " + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
}
|
||||
vmDiskStat_lock.setNetBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentBytesWrite(vmDiskStat.getBytesWrite());
|
||||
if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Read # of IO that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getIORead() + " Stored: " + vmDiskStat_lock.getCurrentIORead());
|
||||
}
|
||||
vmDiskStat_lock.setNetIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentIORead(vmDiskStat.getIORead());
|
||||
if (vmDiskStat_lock.getCurrentIOWrite() > vmDiskStat.getIOWrite()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Write # of IO that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getIOWrite() + " Stored: " + vmDiskStat_lock.getCurrentIOWrite());
|
||||
}
|
||||
vmDiskStat_lock.setNetIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentIOWrite(vmDiskStat.getIOWrite());
|
||||
|
||||
if (! _dailyOrHourly) {
|
||||
//update agg bytes
|
||||
vmDiskStat_lock.setAggBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
vmDiskStat_lock.setAggBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
|
||||
vmDiskStat_lock.setAggIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
|
||||
vmDiskStat_lock.setAggIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
|
||||
}
|
||||
|
||||
_vmDiskStatsDao.update(vmDiskStat_lock.getId(), vmDiskStat_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Error while collecting vm disk stats from hosts", e);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class StorageCollector implements Runnable {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -128,9 +128,11 @@ import com.cloud.template.TemplateManager;
|
|||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.ResourceLimitService;
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.user.dao.VmDiskStatisticsDao;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
|
|
@ -280,6 +282,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
@Inject
|
||||
protected ResourceTagDao _resourceTagDao;
|
||||
@Inject
|
||||
protected VmDiskStatisticsDao _vmDiskStatsDao;
|
||||
@Inject
|
||||
protected VMSnapshotDao _vmSnapshotDao;
|
||||
@Inject
|
||||
protected List<StoragePoolAllocator> _storagePoolAllocators;
|
||||
|
|
@ -1558,6 +1562,13 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
} else {
|
||||
_volsDao.attachVolume(volume.getId(), vm.getId(), deviceId);
|
||||
}
|
||||
// insert record for disk I/O statistics
|
||||
VmDiskStatisticsVO diskstats = _vmDiskStatsDao.findBy(vm.getAccountId(), vm.getDataCenterId(),vm.getId(), volume.getId());
|
||||
if (diskstats == null) {
|
||||
diskstats = new VmDiskStatisticsVO(vm.getAccountId(), vm.getDataCenterId(),vm.getId(), volume.getId());
|
||||
_vmDiskStatsDao.persist(diskstats);
|
||||
}
|
||||
|
||||
return _volsDao.findById(volume.getId());
|
||||
} else {
|
||||
if (answer != null) {
|
||||
|
|
@ -1895,6 +1906,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
.getPoolId());
|
||||
cmd.setPoolUuid(volumePool.getUuid());
|
||||
|
||||
// Collect vm disk statistics from host before stopping Vm
|
||||
_userVmMgr.collectVmDiskStatistics(vm);
|
||||
|
||||
try {
|
||||
answer = _agentMgr.send(vm.getHostId(), cmd);
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.exception.*;
|
||||
|
|
@ -65,6 +66,8 @@ public interface UserVmManager extends VirtualMachineGuru<UserVmVO>, UserVmServi
|
|||
*/
|
||||
HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds);
|
||||
|
||||
HashMap<Long, List<VmDiskStatsEntry>> getVmDiskStatistics(long hostId, String hostName, List<Long> vmIds);
|
||||
|
||||
boolean deleteVmGroup(long groupId);
|
||||
|
||||
boolean addInstanceToGroup(long userVmId, String group);
|
||||
|
|
@ -95,4 +98,6 @@ public interface UserVmManager extends VirtualMachineGuru<UserVmVO>, UserVmServi
|
|||
boolean upgradeVirtualMachine(Long id, Long serviceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException;
|
||||
|
||||
boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic);
|
||||
|
||||
void collectVmDiskStatistics (UserVmVO userVm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ import org.apache.log4j.Logger;
|
|||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.AgentManager.OnError;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.GetVmDiskStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmDiskStatsCommand;
|
||||
import com.cloud.agent.api.GetVmStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.PlugNicAnswer;
|
||||
|
|
@ -75,6 +77,7 @@ import com.cloud.agent.api.StartAnswer;
|
|||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicCommand;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
|
|
@ -213,9 +216,11 @@ import com.cloud.user.SSHKeyPairVO;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserContext;
|
||||
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.VmDiskStatisticsDao;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Journal;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
|
|
@ -239,6 +244,7 @@ import com.cloud.vm.VirtualMachine.State;
|
|||
import com.cloud.vm.dao.InstanceGroupDao;
|
||||
import com.cloud.vm.dao.InstanceGroupVMMapDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
import com.cloud.vm.dao.UserVmCloneSettingDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
|
|
@ -394,6 +400,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
protected GuestOSCategoryDao _guestOSCategoryDao;
|
||||
@Inject
|
||||
UsageEventDao _usageEventDao;
|
||||
|
||||
@Inject
|
||||
SecondaryStorageVmDao _secondaryDao;
|
||||
@Inject
|
||||
VmDiskStatisticsDao _vmDiskStatsDao;
|
||||
|
||||
@Inject
|
||||
protected VMSnapshotDao _vmSnapshotDao;
|
||||
@Inject
|
||||
|
|
@ -411,6 +423,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
protected ScheduledExecutorService _executor = null;
|
||||
protected int _expungeInterval;
|
||||
protected int _expungeDelay;
|
||||
protected boolean _dailyOrHourly = false;
|
||||
|
||||
protected String _name;
|
||||
protected String _instance;
|
||||
|
|
@ -1098,6 +1111,41 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Long, List<VmDiskStatsEntry>> getVmDiskStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
|
||||
HashMap<Long, List<VmDiskStatsEntry>> vmDiskStatsById = new HashMap<Long, List<VmDiskStatsEntry>>();
|
||||
|
||||
if (vmIds.isEmpty()) {
|
||||
return vmDiskStatsById;
|
||||
}
|
||||
|
||||
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 GetVmDiskStatsCommand(vmNames, _hostDao.findById(hostId).getGuid(), hostName));
|
||||
if (answer == null || !answer.getResult()) {
|
||||
s_logger.warn("Unable to obtain VM disk statistics.");
|
||||
return null;
|
||||
} else {
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsByName = ((GetVmDiskStatsAnswer)answer).getVmDiskStatsMap();
|
||||
|
||||
if (vmDiskStatsByName == null) {
|
||||
s_logger.warn("Unable to obtain VM disk statistics.");
|
||||
return null;
|
||||
}
|
||||
|
||||
for (String vmName : vmDiskStatsByName.keySet()) {
|
||||
vmDiskStatsById.put(vmIds.get(vmNames.indexOf(vmName)), vmDiskStatsByName.get(vmName));
|
||||
}
|
||||
}
|
||||
|
||||
return vmDiskStatsById;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{
|
||||
|
|
@ -1397,6 +1445,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
|
||||
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));
|
||||
|
||||
String aggregationRange = configs.get("usage.stats.job.aggregation.range");
|
||||
int _usageAggregationRange = NumbersUtil.parseInt(aggregationRange, 1440);
|
||||
int HOURLY_TIME = 60;
|
||||
final int DAILY_TIME = 60 * 24;
|
||||
if (_usageAggregationRange == DAILY_TIME) {
|
||||
_dailyOrHourly = true;
|
||||
} else if (_usageAggregationRange == HOURLY_TIME) {
|
||||
_dailyOrHourly = true;
|
||||
} else {
|
||||
_dailyOrHourly = false;
|
||||
}
|
||||
|
||||
_itMgr.registerGuru(VirtualMachine.Type.User, this);
|
||||
|
||||
VirtualMachine.State.getStateMachine().registerListener(
|
||||
|
|
@ -2929,6 +2989,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
userVm.setPrivateMacAddress(nic.getMacAddress());
|
||||
}
|
||||
}
|
||||
|
||||
List<VolumeVO> volumes = _volsDao.findByInstance(userVm.getId());
|
||||
VmDiskStatisticsVO diskstats = null;
|
||||
for (VolumeVO volume : volumes) {
|
||||
diskstats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(),userVm.getId(), volume.getId());
|
||||
if (diskstats == null) {
|
||||
diskstats = new VmDiskStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),userVm.getId(), volume.getId());
|
||||
_vmDiskStatsDao.persist(diskstats);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3308,6 +3379,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
boolean status;
|
||||
State vmState = vm.getState();
|
||||
|
||||
// Collect vm disk statistics from host before stopping Vm
|
||||
collectVmDiskStatistics(vm);
|
||||
|
||||
try {
|
||||
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
|
||||
status = vmEntity.destroy(new Long(userId).toString());
|
||||
|
|
@ -3344,6 +3418,122 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
ex.addProxyObject(vm.getUuid(), "vmId");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectVmDiskStatistics (UserVmVO userVm) {
|
||||
// Collect vm disk statistics from host before stopping Vm
|
||||
long hostId = userVm.getHostId();
|
||||
List<String> vmNames = new ArrayList<String>();
|
||||
vmNames.add(userVm.getInstanceName());
|
||||
HostVO host = _hostDao.findById(hostId);
|
||||
|
||||
GetVmDiskStatsAnswer diskStatsAnswer = null;
|
||||
try {
|
||||
diskStatsAnswer = (GetVmDiskStatsAnswer) _agentMgr.easySend(hostId, new GetVmDiskStatsCommand(vmNames, host.getGuid(), host.getName()));
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Error while collecting disk stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e);
|
||||
return;
|
||||
}
|
||||
if (diskStatsAnswer != null) {
|
||||
if (!diskStatsAnswer.getResult()) {
|
||||
s_logger.warn("Error while collecting disk stats vm: " + userVm.getHostName() + " from host: " + host.getName() + "; details: " + diskStatsAnswer.getDetails());
|
||||
return;
|
||||
}
|
||||
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
|
||||
try {
|
||||
txn.start();
|
||||
HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsByName = diskStatsAnswer.getVmDiskStatsMap();
|
||||
List<VmDiskStatsEntry> vmDiskStats = vmDiskStatsByName.get(userVm.getInstanceName());
|
||||
|
||||
if (vmDiskStats == null)
|
||||
return;
|
||||
|
||||
for (VmDiskStatsEntry vmDiskStat:vmDiskStats) {
|
||||
SearchCriteria<VolumeVO> sc_volume = _volsDao.createSearchCriteria();
|
||||
sc_volume.addAnd("path", SearchCriteria.Op.EQ, vmDiskStat.getPath());
|
||||
VolumeVO volume = _volsDao.search(sc_volume, null).get(0);
|
||||
VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId());
|
||||
VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId());
|
||||
|
||||
if ((vmDiskStat.getIORead() == 0) && (vmDiskStat.getIOWrite() == 0) && (vmDiskStat.getBytesRead() == 0) && (vmDiskStat.getBytesWrite() == 0)) {
|
||||
s_logger.debug("Read/Write of IO and Bytes are both 0. Not updating vm_disk_statistics");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vmDiskStat_lock == null) {
|
||||
s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and volumeId:" + volume.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (previousVmDiskStats != null
|
||||
&& ((previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead())
|
||||
|| ((previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock.getCurrentIOWrite())
|
||||
|| (previousVmDiskStats.getCurrentBytesRead() != vmDiskStat_lock.getCurrentBytesRead())
|
||||
|| (previousVmDiskStats.getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())))) {
|
||||
s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " +
|
||||
"Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" IO Read: " + vmDiskStat.getIORead() + " IO Write: " + vmDiskStat.getIOWrite() +
|
||||
" Bytes Read: " + vmDiskStat.getBytesRead() + " Bytes Write: " + vmDiskStat.getBytesWrite());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Read # of IO that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getIORead() + " Stored: " + vmDiskStat_lock.getCurrentIORead());
|
||||
}
|
||||
vmDiskStat_lock.setNetIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentIORead(vmDiskStat.getIORead());
|
||||
if (vmDiskStat_lock.getCurrentIOWrite() > vmDiskStat.getIOWrite()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Write # of IO that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getIOWrite() + " Stored: " + vmDiskStat_lock.getCurrentIOWrite());
|
||||
}
|
||||
vmDiskStat_lock.setNetIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentIOWrite(vmDiskStat.getIOWrite());
|
||||
if (vmDiskStat_lock.getCurrentBytesRead() > vmDiskStat.getBytesRead()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Read # of Bytes that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getBytesRead() + " Stored: " + vmDiskStat_lock.getCurrentBytesRead());
|
||||
}
|
||||
vmDiskStat_lock.setNetBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentBytesRead(vmDiskStat.getBytesRead());
|
||||
if (vmDiskStat_lock.getCurrentBytesWrite() > vmDiskStat.getBytesWrite()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Write # of Bytes that's less than the last one. " +
|
||||
"Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
|
||||
" Reported: " + vmDiskStat.getBytesWrite() + " Stored: " + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
}
|
||||
vmDiskStat_lock.setNetBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
}
|
||||
vmDiskStat_lock.setCurrentBytesWrite(vmDiskStat.getBytesWrite());
|
||||
|
||||
if (! _dailyOrHourly) {
|
||||
//update agg bytes
|
||||
vmDiskStat_lock.setAggIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
|
||||
vmDiskStat_lock.setAggIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
|
||||
vmDiskStat_lock.setAggBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
|
||||
vmDiskStat_lock.setAggBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
|
||||
}
|
||||
|
||||
_vmDiskStatsDao.update(vmDiskStat_lock.getId(), vmDiskStat_lock);
|
||||
}
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
txn.rollback();
|
||||
s_logger.warn("Unable to update vm disk statistics for vm: " + userVm.getId() + " from host: " + hostId, e);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ under the License.
|
|||
<param name="cache.time.to.live">300</param>
|
||||
</dao>
|
||||
<dao name="UserStats" class="com.cloud.user.dao.UserStatisticsDaoImpl"/>
|
||||
<dao name="VmDiskStats" class="com.cloud.user.dao.VmDiskStatisticsDaoImpl"/>
|
||||
<dao name="Disk Template" class="com.cloud.storage.dao.DiskTemplateDaoImpl">
|
||||
<param name="cache.size">50</param>
|
||||
<param name="cache.time.to.live">-1</param>
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
|
|
@ -168,6 +169,12 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Long, List<VmDiskStatsEntry>> getVmDiskStatistics(long hostId, String hostName, List<Long> vmIds) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteVmGroup(long groupId) {
|
||||
// TODO Auto-generated method stub
|
||||
|
|
@ -461,4 +468,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
|
|||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectVmDiskStatistics (UserVmVO userVm) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1771,6 +1771,82 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag
|
|||
|
||||
UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0;
|
||||
|
||||
DROP TABLE IF EXISTS `cloud`.`vm_disk_statistics`;
|
||||
CREATE TABLE `cloud`.`vm_disk_statistics` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`data_center_id` bigint(20) unsigned NOT NULL,
|
||||
`account_id` bigint(20) unsigned NOT NULL,
|
||||
`vm_id` bigint(20) unsigned NOT NULL,
|
||||
`volume_id` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `id` (`id`),
|
||||
UNIQUE KEY `account_id` (`account_id`,`data_center_id`,`vm_id`,`volume_id`),
|
||||
KEY `i_vm_disk_statistics__account_id` (`account_id`),
|
||||
KEY `i_vm_disk_statistics__account_id_data_center_id` (`account_id`,`data_center_id`),
|
||||
CONSTRAINT `fk_vm_disk_statistics__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
|
||||
|
||||
insert into `cloud`.`vm_disk_statistics`(data_center_id,account_id,vm_id,volume_id)
|
||||
select volumes.data_center_id, volumes.account_id, vm_instance.id, volumes.id from volumes,vm_instance where vm_instance.vm_type="User" and vm_instance.state<>"Expunging" and volumes.instance_id=vm_instance.id order by vm_instance.id;
|
||||
|
||||
DROP TABLE IF EXISTS `cloud_usage`.`vm_disk_statistics`;
|
||||
CREATE TABLE `cloud_usage`.`vm_disk_statistics` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`data_center_id` bigint(20) unsigned NOT NULL,
|
||||
`account_id` bigint(20) unsigned NOT NULL,
|
||||
`vm_id` bigint(20) unsigned NOT NULL,
|
||||
`volume_id` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`net_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`current_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `id` (`id`),
|
||||
UNIQUE KEY `account_id` (`account_id`,`data_center_id`,`vm_id`,`volume_id`)
|
||||
) ENGINE=InnoDB CHARSET=utf8;
|
||||
|
||||
insert into `cloud_usage`.`vm_disk_statistics` select * from `cloud`.`vm_disk_statistics`;
|
||||
|
||||
DROP TABLE IF EXISTS `cloud_usage`.`usage_vm_disk`;
|
||||
CREATE TABLE `cloud_usage`.`usage_vm_disk` (
|
||||
`account_id` bigint(20) unsigned NOT NULL,
|
||||
`zone_id` bigint(20) unsigned NOT NULL,
|
||||
`vm_id` bigint(20) unsigned NOT NULL,
|
||||
`volume_id` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_io_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_read` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`agg_bytes_write` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`event_time_millis` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`account_id`,`zone_id`,`vm_id`,`volume_id`,`event_time_millis`)
|
||||
) ENGINE=InnoDB CHARSET=utf8;
|
||||
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.disk.stats.interval', 0, 'Interval (in seconds) to report vm disk statistics.');
|
||||
|
||||
|
||||
-- Re-enable foreign key checking, at the end of the upgrade path
|
||||
SET foreign_key_checks = 1;
|
||||
|
|
|
|||
|
|
@ -469,11 +469,15 @@ dictionary = {
|
|||
'label.disable.vpn': '<fmt:message key="label.disable.vpn" />',
|
||||
'label.disabling.vpn.access': '<fmt:message key="label.disabling.vpn.access" />',
|
||||
'label.disk.allocated': '<fmt:message key="label.disk.allocated" />',
|
||||
'label.disk.read.bytes': '<fmt:message key="label.disk.read.bytes" />',
|
||||
'label.disk.read.io': '<fmt:message key="label.disk.read.io" />',
|
||||
'label.disk.offering': '<fmt:message key="label.disk.offering" />',
|
||||
'label.disk.size': '<fmt:message key="label.disk.size" />',
|
||||
'label.disk.size.gb': '<fmt:message key="label.disk.size.gb" />',
|
||||
'label.disk.total': '<fmt:message key="label.disk.total" />',
|
||||
'label.disk.volume': '<fmt:message key="label.disk.volume" />',
|
||||
'label.disk.write.bytes': '<fmt:message key="label.disk.write.bytes" />',
|
||||
'label.disk.write.io': '<fmt:message key="label.disk.write.io" />',
|
||||
'label.display.name': '<fmt:message key="label.display.name" />',
|
||||
'label.display.text': '<fmt:message key="label.display.text" />',
|
||||
'label.dns.1': '<fmt:message key="label.dns.1" />',
|
||||
|
|
|
|||
|
|
@ -1648,7 +1648,11 @@
|
|||
totalCPU: { label: 'label.total.cpu' },
|
||||
cpuused: { label: 'label.cpu.utilized' },
|
||||
networkkbsread: { label: 'label.network.read' },
|
||||
networkkbswrite: { label: 'label.network.write' }
|
||||
networkkbswrite: { label: 'label.network.write' },
|
||||
diskkbsread: { label: 'label.disk.read.bytes' },
|
||||
diskkbswrite: { label: 'label.disk.write.bytes' },
|
||||
diskioread: { label: 'label.disk.read.io' },
|
||||
diskiowrite: { label: 'label.disk.write.io' }
|
||||
},
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
|
|
@ -1662,7 +1666,11 @@
|
|||
totalCPU: jsonObj.cpunumber + " x " + cloudStack.converters.convertHz(jsonObj.cpuspeed),
|
||||
cpuused: jsonObj.cpuused,
|
||||
networkkbsread: (jsonObj.networkkbsread == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.networkkbsread * 1024),
|
||||
networkkbswrite: (jsonObj.networkkbswrite == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.networkkbswrite * 1024)
|
||||
networkkbswrite: (jsonObj.networkkbswrite == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.networkkbswrite * 1024),
|
||||
diskkbsread: (jsonObj.diskkbsread == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.diskkbsread * 1024),
|
||||
diskkbswrite: (jsonObj.diskkbswrite == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.diskkbswrite * 1024),
|
||||
diskioread: (jsonObj.diskioread == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.diskioread * 1024),
|
||||
diskiowrite: (jsonObj.diskiowrite == null)? "N/A": cloudStack.converters.convertBytes(jsonObj.diskiowrite * 1024)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import com.cloud.usage.dao.UsageSecurityGroupDao;
|
|||
import com.cloud.usage.dao.UsageStorageDao;
|
||||
import com.cloud.usage.dao.UsageVMInstanceDao;
|
||||
import com.cloud.usage.dao.UsageVPNUserDao;
|
||||
import com.cloud.usage.dao.UsageVmDiskDao;
|
||||
import com.cloud.usage.dao.UsageVolumeDao;
|
||||
import com.cloud.usage.parser.IPAddressUsageParser;
|
||||
import com.cloud.usage.parser.LoadBalancerUsageParser;
|
||||
|
|
@ -64,13 +65,15 @@ import com.cloud.usage.parser.SecurityGroupUsageParser;
|
|||
import com.cloud.usage.parser.StorageUsageParser;
|
||||
import com.cloud.usage.parser.VMInstanceUsageParser;
|
||||
import com.cloud.usage.parser.VPNUserUsageParser;
|
||||
import com.cloud.usage.parser.VmDiskUsageParser;
|
||||
import com.cloud.usage.parser.VolumeUsageParser;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserStatisticsVO;
|
||||
import com.cloud.user.VmDiskStatisticsVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserStatisticsDao;
|
||||
|
||||
import com.cloud.user.dao.VmDiskStatisticsDao;
|
||||
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
|
|
@ -108,6 +111,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
@Inject private UsageVPNUserDao m_usageVPNUserDao;
|
||||
@Inject private UsageSecurityGroupDao m_usageSecurityGroupDao;
|
||||
@Inject private UsageJobDao m_usageJobDao;
|
||||
@Inject private VmDiskStatisticsDao m_vmDiskStatsDao;
|
||||
@Inject private UsageVmDiskDao m_usageVmDiskDao;
|
||||
@Inject protected AlertManager _alertMgr;
|
||||
@Inject protected UsageEventDao _usageEventDao;
|
||||
@Inject ConfigurationDao _configDao;
|
||||
|
|
@ -121,6 +126,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
TimeZone m_usageTimezone = TimeZone.getTimeZone("GMT");;
|
||||
private final GlobalLock m_heartbeatLock = GlobalLock.getInternLock("usage.job.heartbeat.check");
|
||||
private List<UsageNetworkVO> usageNetworks = new ArrayList<UsageNetworkVO>();
|
||||
private List<UsageVmDiskVO> usageVmDisks = new ArrayList<UsageVmDiskVO>();
|
||||
|
||||
private final ScheduledExecutorService m_executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Job"));
|
||||
private final ScheduledExecutorService m_heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-HB"));
|
||||
|
|
@ -389,6 +395,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
List<AccountVO> accounts = null;
|
||||
List<UserStatisticsVO> userStats = null;
|
||||
Map<String, UsageNetworkVO> networkStats = null;
|
||||
List<VmDiskStatisticsVO> vmDiskStats = null;
|
||||
Map<String, UsageVmDiskVO> vmDiskUsages = null;
|
||||
Transaction userTxn = Transaction.open(Transaction.CLOUD_DB);
|
||||
try {
|
||||
Long limit = Long.valueOf(500);
|
||||
|
|
@ -479,6 +487,46 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
}
|
||||
offset = new Long(offset.longValue() + limit.longValue());
|
||||
} while ((userStats != null) && !userStats.isEmpty());
|
||||
|
||||
// reset offset
|
||||
offset = Long.valueOf(0);
|
||||
|
||||
// get all the vm network stats to create usage_vm_network records for the vm network usage
|
||||
Long lastVmDiskStatsId = m_usageDao.getLastVmDiskStatsId();
|
||||
if (lastVmDiskStatsId == null) {
|
||||
lastVmDiskStatsId = Long.valueOf(0);
|
||||
}
|
||||
SearchCriteria<VmDiskStatisticsVO> sc4 = m_vmDiskStatsDao.createSearchCriteria();
|
||||
sc4.addAnd("id", SearchCriteria.Op.LTEQ, lastVmDiskStatsId);
|
||||
do {
|
||||
Filter filter = new Filter(VmDiskStatisticsVO.class, "id", true, offset, limit);
|
||||
|
||||
vmDiskStats = m_vmDiskStatsDao.search(sc4, filter);
|
||||
|
||||
if ((vmDiskStats != null) && !vmDiskStats.isEmpty()) {
|
||||
// now copy the accounts to cloud_usage db
|
||||
m_usageDao.updateVmDiskStats(vmDiskStats);
|
||||
}
|
||||
offset = new Long(offset.longValue() + limit.longValue());
|
||||
} while ((vmDiskStats != null) && !vmDiskStats.isEmpty());
|
||||
|
||||
// reset offset
|
||||
offset = Long.valueOf(0);
|
||||
|
||||
sc4 = m_vmDiskStatsDao.createSearchCriteria();
|
||||
sc4.addAnd("id", SearchCriteria.Op.GT, lastVmDiskStatsId);
|
||||
do {
|
||||
Filter filter = new Filter(VmDiskStatisticsVO.class, "id", true, offset, limit);
|
||||
|
||||
vmDiskStats = m_vmDiskStatsDao.search(sc4, filter);
|
||||
|
||||
if ((vmDiskStats != null) && !vmDiskStats.isEmpty()) {
|
||||
// now copy the accounts to cloud_usage db
|
||||
m_usageDao.saveVmDiskStats(vmDiskStats);
|
||||
}
|
||||
offset = new Long(offset.longValue() + limit.longValue());
|
||||
} while ((vmDiskStats != null) && !vmDiskStats.isEmpty());
|
||||
|
||||
} finally {
|
||||
userTxn.close();
|
||||
}
|
||||
|
|
@ -565,6 +613,53 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
s_logger.debug("created network stats helper entries for " + numAcctsProcessed + " accts");
|
||||
}
|
||||
|
||||
// get vm disk stats in order to compute vm disk usage
|
||||
vmDiskUsages = m_usageVmDiskDao.getRecentVmDiskStats();
|
||||
|
||||
// Keep track of user stats for an account, across all of its public IPs
|
||||
Map<String, VmDiskStatisticsVO> aggregatedDiskStats = new HashMap<String, VmDiskStatisticsVO>();
|
||||
startIndex = 0;
|
||||
do {
|
||||
vmDiskStats = m_vmDiskStatsDao.listActiveAndRecentlyDeleted(recentlyDeletedDate, startIndex, 500);
|
||||
|
||||
if (vmDiskUsages != null) {
|
||||
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
|
||||
if(vmDiskStat.getVmId() != null){
|
||||
String hostKey = vmDiskStat.getDataCenterId() + "-" + vmDiskStat.getAccountId()+"-Vm-" + vmDiskStat.getVmId()+"-Disk-" + vmDiskStat.getVolumeId();
|
||||
VmDiskStatisticsVO hostAggregatedStat = aggregatedDiskStats.get(hostKey);
|
||||
if (hostAggregatedStat == null) {
|
||||
hostAggregatedStat = new VmDiskStatisticsVO(vmDiskStat.getAccountId(), vmDiskStat.getDataCenterId(), vmDiskStat.getVmId(),vmDiskStat.getVolumeId());
|
||||
}
|
||||
|
||||
hostAggregatedStat.setAggIORead(hostAggregatedStat.getAggIORead() + vmDiskStat.getAggIORead());
|
||||
hostAggregatedStat.setAggIOWrite(hostAggregatedStat.getAggIOWrite() + vmDiskStat.getAggIOWrite());
|
||||
hostAggregatedStat.setAggBytesRead(hostAggregatedStat.getAggBytesRead() + vmDiskStat.getAggBytesRead());
|
||||
hostAggregatedStat.setAggBytesWrite(hostAggregatedStat.getAggBytesWrite() + vmDiskStat.getAggBytesWrite());
|
||||
aggregatedDiskStats.put(hostKey, hostAggregatedStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
startIndex += 500;
|
||||
} while ((userStats != null) && !userStats.isEmpty());
|
||||
|
||||
// loop over the user stats, create delta entries in the usage_disk helper table
|
||||
numAcctsProcessed = 0;
|
||||
usageVmDisks.clear();
|
||||
for (String key : aggregatedDiskStats.keySet()) {
|
||||
UsageVmDiskVO currentVmDiskStats = null;
|
||||
if (vmDiskStats != null) {
|
||||
currentVmDiskStats = vmDiskUsages.get(key);
|
||||
}
|
||||
|
||||
createVmDiskHelperEntry(aggregatedDiskStats.get(key), currentVmDiskStats, endDateMillis);
|
||||
numAcctsProcessed++;
|
||||
}
|
||||
m_usageVmDiskDao.saveUsageVmDisks(usageVmDisks);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("created vm disk stats helper entries for " + numAcctsProcessed + " accts");
|
||||
}
|
||||
|
||||
// commit the helper records, then start a new transaction
|
||||
usageTxn.commit();
|
||||
usageTxn.start();
|
||||
|
|
@ -701,6 +796,13 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
}
|
||||
}
|
||||
|
||||
parsed = VmDiskUsageParser.parse(account, currentStartDate, currentEndDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
if (!parsed) {
|
||||
s_logger.debug("vm disk usage successfully parsed? " + parsed + " (for account: " + account.getAccountName() + ", id: " + account.getId() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
parsed = VolumeUsageParser.parse(account, currentStartDate, currentEndDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
if (!parsed) {
|
||||
|
|
@ -1006,6 +1108,59 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
usageNetworks.add(usageNetworkVO);
|
||||
}
|
||||
|
||||
private void createVmDiskHelperEntry(VmDiskStatisticsVO vmDiskStat, UsageVmDiskVO usageVmDiskStat, long timestamp) {
|
||||
long currentAccountedIORead = 0L;
|
||||
long currentAccountedIOWrite = 0L;
|
||||
long currentAccountedBytesRead = 0L;
|
||||
long currentAccountedBytesWrite = 0L;
|
||||
if (usageVmDiskStat != null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("getting current accounted bytes for... accountId: " + usageVmDiskStat.getAccountId() + " in zone: " + vmDiskStat.getDataCenterId() + "; aiw: " + vmDiskStat.getAggIOWrite() +
|
||||
"; air: " + usageVmDiskStat.getAggIORead() + "; abw: " + vmDiskStat.getAggBytesWrite() + "; abr: " + usageVmDiskStat.getAggBytesRead());
|
||||
}
|
||||
currentAccountedIORead = usageVmDiskStat.getAggIORead();
|
||||
currentAccountedIOWrite = usageVmDiskStat.getAggIOWrite();
|
||||
currentAccountedBytesRead = usageVmDiskStat.getAggBytesRead();
|
||||
currentAccountedBytesWrite = usageVmDiskStat.getAggBytesWrite();
|
||||
}
|
||||
long ioRead = vmDiskStat.getAggIORead() - currentAccountedIORead;
|
||||
long ioWrite = vmDiskStat.getAggIOWrite() - currentAccountedIOWrite;
|
||||
long bytesRead = vmDiskStat.getAggBytesRead() - currentAccountedBytesRead;
|
||||
long bytesWrite = vmDiskStat.getAggBytesWrite() - currentAccountedBytesWrite;
|
||||
|
||||
if (ioRead < 0) {
|
||||
s_logger.warn("Calculated negative value for io read: " + ioRead + ", vm disk stats say: " + vmDiskStat.getAggIORead() + ", previous vm disk usage was: " + currentAccountedIORead);
|
||||
ioRead = 0;
|
||||
}
|
||||
if (ioWrite < 0) {
|
||||
s_logger.warn("Calculated negative value for io write: " + ioWrite + ", vm disk stats say: " + vmDiskStat.getAggIOWrite() + ", previous vm disk usage was: " + currentAccountedIOWrite);
|
||||
ioWrite = 0;
|
||||
}
|
||||
if (bytesRead < 0) {
|
||||
s_logger.warn("Calculated negative value for bytes read: " + bytesRead + ", vm disk stats say: " + vmDiskStat.getAggBytesRead() + ", previous vm disk usage was: " + currentAccountedBytesRead);
|
||||
bytesRead = 0;
|
||||
}
|
||||
if (bytesWrite < 0) {
|
||||
s_logger.warn("Calculated negative value for bytes write: " + bytesWrite + ", vm disk stats say: " + vmDiskStat.getAggBytesWrite() + ", previous vm disk usage was: " + currentAccountedBytesWrite);
|
||||
bytesWrite = 0;
|
||||
}
|
||||
|
||||
long vmId = 0;
|
||||
|
||||
if(vmDiskStat.getVmId() != null){
|
||||
vmId = vmDiskStat.getVmId();
|
||||
}
|
||||
|
||||
UsageVmDiskVO usageVmDiskVO = new UsageVmDiskVO(vmDiskStat.getAccountId(), vmDiskStat.getDataCenterId(), vmId, vmDiskStat.getVolumeId(), ioRead, ioWrite,
|
||||
vmDiskStat.getAggIORead(), vmDiskStat.getAggIOWrite(), bytesRead, bytesWrite, vmDiskStat.getAggBytesRead(), vmDiskStat.getAggBytesWrite(), timestamp);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("creating vmDiskHelperEntry... accountId: " + vmDiskStat.getAccountId() + " in zone: " + vmDiskStat.getDataCenterId() + "; aiw: " + vmDiskStat.getAggIOWrite() + "; air: " + vmDiskStat.getAggIORead() +
|
||||
"; curAIR: " + currentAccountedIORead + "; curAIW: " + currentAccountedIOWrite + "; uir: " + ioRead + "; uiw: " + ioWrite + "; abw: " + vmDiskStat.getAggBytesWrite() + "; abr: " + vmDiskStat.getAggBytesRead() +
|
||||
"; curABR: " + currentAccountedBytesRead + "; curABW: " + currentAccountedBytesWrite + "; ubr: " + bytesRead + "; ubw: " + bytesWrite);
|
||||
}
|
||||
usageVmDisks.add(usageVmDiskVO);
|
||||
}
|
||||
|
||||
private void createIPHelperEvent(UsageEventVO event) {
|
||||
|
||||
String ipAddress = event.getResourceName();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
// 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
|
||||
// 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.usage.parser;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
|
||||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.usage.UsageVmDiskVO;
|
||||
import com.cloud.usage.dao.UsageDao;
|
||||
import com.cloud.usage.dao.UsageVmDiskDao;
|
||||
import com.cloud.user.AccountVO;
|
||||
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class VmDiskUsageParser {
|
||||
public static final Logger s_logger = Logger.getLogger(VmDiskUsageParser.class.getName());
|
||||
|
||||
private static UsageDao m_usageDao;
|
||||
private static UsageVmDiskDao m_usageVmDiskDao;
|
||||
|
||||
@Inject private UsageDao _usageDao;
|
||||
@Inject private UsageVmDiskDao _usageVmDiskDao;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
m_usageDao = _usageDao;
|
||||
m_usageVmDiskDao = _usageVmDiskDao;
|
||||
}
|
||||
|
||||
public static boolean parse(AccountVO account, Date startDate, Date endDate) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Parsing all Vm Disk usage events for account: " + account.getId());
|
||||
}
|
||||
|
||||
if ((endDate == null) || endDate.after(new Date())) {
|
||||
endDate = new Date();
|
||||
}
|
||||
|
||||
// - query usage_disk table for all entries for userId with
|
||||
// event_date in the given range
|
||||
SearchCriteria<UsageVmDiskVO> sc = m_usageVmDiskDao.createSearchCriteria();
|
||||
sc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
|
||||
sc.addAnd("eventTimeMillis", SearchCriteria.Op.BETWEEN, startDate.getTime(), endDate.getTime());
|
||||
List<UsageVmDiskVO> usageVmDiskVOs = m_usageVmDiskDao.search(sc, null);
|
||||
|
||||
Map<String, VmDiskInfo> vmDiskUsageByZone = new HashMap<String, VmDiskInfo>();
|
||||
|
||||
// Calculate the bytes since last parsing
|
||||
for (UsageVmDiskVO usageVmDisk : usageVmDiskVOs) {
|
||||
long zoneId = usageVmDisk.getZoneId();
|
||||
String key = ""+zoneId;
|
||||
if(usageVmDisk.getVmId() != 0){
|
||||
key += "-Vm-" + usageVmDisk.getVmId()+"-Disk-" + usageVmDisk.getVolumeId();
|
||||
}
|
||||
VmDiskInfo vmDiskInfo = vmDiskUsageByZone.get(key);
|
||||
|
||||
long ioRead = usageVmDisk.getIORead();
|
||||
long ioWrite = usageVmDisk.getIOWrite();
|
||||
long bytesRead = usageVmDisk.getBytesRead();
|
||||
long bytesWrite = usageVmDisk.getBytesWrite();
|
||||
if (vmDiskInfo != null) {
|
||||
ioRead += vmDiskInfo.getIORead();
|
||||
ioWrite += vmDiskInfo.getIOWrite();
|
||||
bytesRead += vmDiskInfo.getBytesRead();
|
||||
bytesWrite += vmDiskInfo.getBytesWrite();
|
||||
}
|
||||
|
||||
vmDiskUsageByZone.put(key, new VmDiskInfo(zoneId, usageVmDisk.getVmId(), usageVmDisk.getVolumeId(), ioRead, ioWrite, bytesRead, bytesWrite));
|
||||
}
|
||||
|
||||
for (String key : vmDiskUsageByZone.keySet()) {
|
||||
VmDiskInfo vmDiskInfo = vmDiskUsageByZone.get(key);
|
||||
long ioRead = vmDiskInfo.getIORead();
|
||||
long ioWrite = vmDiskInfo.getIOWrite();
|
||||
long bytesRead = vmDiskInfo.getBytesRead();
|
||||
long bytesWrite = vmDiskInfo.getBytesWrite();
|
||||
|
||||
if ((ioRead > 0L) || (ioWrite > 0L) || (bytesRead > 0L) || (bytesWrite > 0L)) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating vm disk usage record, io read:" + ioRead + ", io write: " + ioWrite + "bytes read:" + bytesRead + ", bytes write: " + bytesWrite + "for account: "
|
||||
+ account.getId() + " in availability zone " + vmDiskInfo.getZoneId() + ", start: " + startDate + ", end: " + endDate);
|
||||
}
|
||||
|
||||
Long vmId = null;
|
||||
|
||||
// Create the usage record for bytes read
|
||||
String usageDesc = "disk bytes read";
|
||||
if(vmDiskInfo.getVmId() != 0){
|
||||
vmId = vmDiskInfo.getVmId();
|
||||
usageDesc += " for Vm: "+vmDiskInfo.getVmId()+" and Volume: "+ vmDiskInfo.getVolumeId();
|
||||
}
|
||||
UsageVO usageRecord = new UsageVO(vmDiskInfo.getZoneId(), account.getId(), account.getDomainId(), usageDesc, ioRead + " io read",
|
||||
UsageTypes.VM_DISK_IO_READ, new Double(ioRead), vmId, "VirtualMachine", vmDiskInfo.getVolumeId(), startDate, endDate);
|
||||
m_usageDao.persist(usageRecord);
|
||||
|
||||
// Create the usage record for bytes write
|
||||
usageDesc = "disk bytes write";
|
||||
if(vmDiskInfo.getVmId() != 0){
|
||||
usageDesc += " for Vm: "+vmDiskInfo.getVmId()+" and Volume: "+ vmDiskInfo.getVolumeId();
|
||||
}
|
||||
usageRecord = new UsageVO(vmDiskInfo.getZoneId(), account.getId(), account.getDomainId(), usageDesc, ioWrite + " io write",
|
||||
UsageTypes.VM_DISK_BYTES_WRITE, new Double(ioWrite), vmId, "VirtualMachine", vmDiskInfo.getVolumeId(), startDate, endDate);
|
||||
m_usageDao.persist(usageRecord);
|
||||
|
||||
// Create the usage record for bytes read
|
||||
usageDesc = "disk bytes read";
|
||||
if(vmDiskInfo.getVmId() != 0){
|
||||
vmId = vmDiskInfo.getVmId();
|
||||
usageDesc += " for Vm: "+vmDiskInfo.getVmId()+" and Volume: "+ vmDiskInfo.getVolumeId();
|
||||
}
|
||||
usageRecord = new UsageVO(vmDiskInfo.getZoneId(), account.getId(), account.getDomainId(), usageDesc, bytesRead + " bytes read",
|
||||
UsageTypes.VM_DISK_BYTES_READ, new Double(bytesRead), vmId, "VirtualMachine", vmDiskInfo.getVolumeId(), startDate, endDate);
|
||||
m_usageDao.persist(usageRecord);
|
||||
|
||||
// Create the usage record for bytes write
|
||||
usageDesc = "disk bytes write";
|
||||
if(vmDiskInfo.getVmId() != 0){
|
||||
usageDesc += " for Vm: "+vmDiskInfo.getVmId()+" and Volume: "+ vmDiskInfo.getVolumeId();
|
||||
}
|
||||
usageRecord = new UsageVO(vmDiskInfo.getZoneId(), account.getId(), account.getDomainId(), usageDesc, bytesWrite + " bytes write",
|
||||
UsageTypes.VM_DISK_BYTES_WRITE, new Double(bytesWrite), vmId, "VirtualMachine", vmDiskInfo.getVolumeId(), startDate, endDate);
|
||||
m_usageDao.persist(usageRecord);
|
||||
|
||||
} else {
|
||||
// Don't charge anything if there were zero bytes processed
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No vm disk usage record (0 bytes used) generated for account: " + account.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class VmDiskInfo {
|
||||
private long zoneId;
|
||||
private long vmId;
|
||||
private Long volumeId;
|
||||
private long ioRead;
|
||||
private long ioWrite;
|
||||
private long bytesRead;
|
||||
private long bytesWrite;
|
||||
|
||||
public VmDiskInfo(long zoneId, long vmId, Long volumeId, long ioRead, long ioWrite, long bytesRead, long bytesWrite) {
|
||||
this.zoneId = zoneId;
|
||||
this.vmId = vmId;
|
||||
this.volumeId = volumeId;
|
||||
this.ioRead = ioRead;
|
||||
this.ioWrite = ioWrite;
|
||||
this.bytesRead = bytesRead;
|
||||
this.bytesWrite = bytesWrite;
|
||||
}
|
||||
|
||||
public long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public Long getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
public long getIORead() {
|
||||
return ioRead;
|
||||
}
|
||||
|
||||
public long getIOWrite() {
|
||||
return ioWrite;
|
||||
}
|
||||
|
||||
public long getBytesRead() {
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public long getBytesWrite() {
|
||||
return bytesWrite;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,8 @@ public class UsageManagerTest extends TestCase {
|
|||
@Inject
|
||||
NetworkUsageParser netParser = null;
|
||||
@Inject
|
||||
VmDiskUsageParser vmdiskParser = null;
|
||||
@Inject
|
||||
PortForwardingUsageParser pfParser = null;
|
||||
@Inject
|
||||
SecurityGroupUsageParser sgParser = null;
|
||||
|
|
@ -87,6 +89,7 @@ public class UsageManagerTest extends TestCase {
|
|||
lbParser.parse(account, startDate, endDate);
|
||||
noParser.parse(account, startDate, endDate);
|
||||
netParser.parse(account, startDate, endDate);
|
||||
vmdiskParser.parse(account, startDate, endDate);
|
||||
pfParser.parse(account, startDate, endDate);
|
||||
sgParser.parse(account, startDate, endDate);
|
||||
stParser.parse(account, startDate, endDate);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import java.io.IOException;
|
|||
UsagePortForwardingRuleDaoImpl.class,
|
||||
UsageNetworkOfferingDaoImpl.class,
|
||||
UsageVPNUserDaoImpl.class,
|
||||
UsageVmDiskDaoImpl.class,
|
||||
UsageSecurityGroupDaoImpl.class,
|
||||
ConfigurationDaoImpl.class,
|
||||
UsageManagerImpl.class,
|
||||
|
|
@ -64,6 +65,7 @@ import java.io.IOException;
|
|||
PortForwardingUsageParser.class,
|
||||
SecurityGroupUsageParser.class,
|
||||
StorageUsageParser.class,
|
||||
VmDiskUsageParser.class,
|
||||
VolumeUsageParser.class,
|
||||
VPNUserUsageParser.class,
|
||||
UserStatisticsDaoImpl.class},
|
||||
|
|
|
|||
Loading…
Reference in New Issue