mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'origin/4.14'
This commit is contained in:
commit
567524a2a5
@ -492,6 +492,7 @@ public class EventTypes {
|
||||
public static final String EVENT_VM_BACKUP_RESTORE_VOLUME_TO_VM = "BACKUP.RESTORE.VOLUME.TO.VM";
|
||||
public static final String EVENT_VM_BACKUP_SCHEDULE_CONFIGURE = "BACKUP.SCHEDULE.CONFIGURE";
|
||||
public static final String EVENT_VM_BACKUP_SCHEDULE_DELETE = "BACKUP.SCHEDULE.DELETE";
|
||||
public static final String EVENT_VM_BACKUP_USAGE_METRIC = "BACKUP.USAGE.METRIC";
|
||||
|
||||
// external network device events
|
||||
public static final String EVENT_EXTERNAL_NVP_CONTROLLER_ADD = "PHYSICAL.NVPCONTROLLER.ADD";
|
||||
|
||||
@ -20,14 +20,11 @@ package com.cloud.usage.dao;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
|
||||
import com.cloud.usage.UsageBackupVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
public interface UsageBackupDao extends GenericDao<UsageBackupVO, Long> {
|
||||
void updateMetrics(VirtualMachine vm, Backup.Metric metric);
|
||||
void removeUsage(Long accountId, Long zoneId, Long backupId);
|
||||
void updateMetrics(Long vmId, Long size, Long virtualSize);
|
||||
void removeUsage(Long accountId, Long vmId, Date eventDate);
|
||||
List<UsageBackupVO> getUsageRecords(Long accountId, Date startDate, Date endDate);
|
||||
}
|
||||
|
||||
@ -19,69 +19,68 @@ package com.cloud.usage.dao;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.exception.CloudException;
|
||||
import com.cloud.usage.UsageBackupVO;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@Component
|
||||
public class UsageBackupDaoImpl extends GenericDaoBase<UsageBackupVO, Long> implements UsageBackupDao {
|
||||
public static final Logger LOGGER = Logger.getLogger(UsageBackupDaoImpl.class);
|
||||
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, zone_id, account_id, domain_id, vm_id, backup_offering_id, size, protected_size, created, removed FROM cloud_usage.usage_backup WHERE " +
|
||||
protected static final String UPDATE_DELETED = "UPDATE usage_backup SET removed = ? WHERE account_id = ? AND vm_id = ? and removed IS NULL";
|
||||
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, zone_id, account_id, domain_id, vm_id, backup_offering_id, size, protected_size, created, removed FROM usage_backup WHERE " +
|
||||
" account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " +
|
||||
" OR ((created <= ?) AND (removed >= ?)))";
|
||||
|
||||
@Override
|
||||
public void updateMetrics(final VirtualMachine vm, Backup.Metric metric) {
|
||||
boolean result = Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(final TransactionStatus status) {
|
||||
final QueryBuilder<UsageBackupVO> qb = QueryBuilder.create(UsageBackupVO.class);
|
||||
qb.and(qb.entity().getVmId(), SearchCriteria.Op.EQ, vm.getId());
|
||||
final UsageBackupVO entry = findOneBy(qb.create());
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
entry.setSize(metric.getBackupSize());
|
||||
entry.setProtectedSize(metric.getDataSize());
|
||||
return update(entry.getId(), entry);
|
||||
public void updateMetrics(final Long vmId, final Long size, final Long virtualSize) {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
SearchCriteria<UsageBackupVO> sc = this.createSearchCriteria();
|
||||
sc.addAnd("vmId", SearchCriteria.Op.EQ, vmId);
|
||||
UsageBackupVO vo = findOneBy(sc);
|
||||
if (vo != null) {
|
||||
vo.setSize(size);
|
||||
vo.setProtectedSize(virtualSize);
|
||||
update(vo.getId(), vo);
|
||||
}
|
||||
});
|
||||
if (!result) {
|
||||
LOGGER.trace("Failed to update backup metrics for VM ID: " + vm.getId());
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error("Error updating backup metrics: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUsage(Long accountId, Long zoneId, Long vmId) {
|
||||
boolean result = Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(final TransactionStatus status) {
|
||||
final QueryBuilder<UsageBackupVO> qb = QueryBuilder.create(UsageBackupVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getZoneId(), SearchCriteria.Op.EQ, zoneId);
|
||||
qb.and(qb.entity().getVmId(), SearchCriteria.Op.EQ, vmId);
|
||||
final UsageBackupVO entry = findOneBy(qb.create());
|
||||
return remove(qb.create()) > 0;
|
||||
public void removeUsage(Long accountId, Long vmId, Date eventDate) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
txn.start();
|
||||
try (PreparedStatement pstmt = txn.prepareStatement(UPDATE_DELETED);) {
|
||||
if (pstmt != null) {
|
||||
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), eventDate));
|
||||
pstmt.setLong(2, accountId);
|
||||
pstmt.setLong(3, vmId);
|
||||
pstmt.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
LOGGER.error("Error removing UsageBackupVO: " + e.getMessage(), e);
|
||||
throw new CloudException("Remove backup usage exception: " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
if (!result) {
|
||||
LOGGER.warn("Failed to remove usage entry for backup of VM ID: " + vmId);
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
txn.rollback();
|
||||
LOGGER.error("Exception caught while removing UsageBackupVO: " + e.getMessage(), e);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -150,30 +150,28 @@ public class TransactionLegacy implements Closeable {
|
||||
|
||||
public static TransactionLegacy open(final String name, final short databaseId, final boolean forceDbChange) {
|
||||
TransactionLegacy txn = tls.get();
|
||||
boolean isNew = false;
|
||||
if (txn == null) {
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("Creating the transaction: " + name);
|
||||
}
|
||||
txn = new TransactionLegacy(name, false, databaseId);
|
||||
tls.set(txn);
|
||||
isNew = true;
|
||||
s_mbean.addTransaction(txn);
|
||||
} else if (forceDbChange) {
|
||||
final short currentDbId = txn.getDatabaseId();
|
||||
if (currentDbId != databaseId) {
|
||||
// we need to end the current transaction and switch databases
|
||||
txn.close(txn.getName());
|
||||
if (txn.close(txn.getName()) && txn.getCurrentConnection() == null) {
|
||||
s_mbean.removeTransaction(txn);
|
||||
}
|
||||
|
||||
txn = new TransactionLegacy(name, false, databaseId);
|
||||
tls.set(txn);
|
||||
isNew = true;
|
||||
s_mbean.addTransaction(txn);
|
||||
}
|
||||
}
|
||||
txn.checkConnection();
|
||||
txn.takeOver(name, false);
|
||||
if (isNew) {
|
||||
s_mbean.addTransaction(txn);
|
||||
}
|
||||
return txn;
|
||||
}
|
||||
|
||||
@ -762,8 +760,8 @@ public class TransactionLegacy implements Closeable {
|
||||
}
|
||||
_conn.close();
|
||||
_conn = null;
|
||||
s_mbean.removeTransaction(this);
|
||||
}
|
||||
|
||||
} catch (final SQLException e) {
|
||||
s_logger.warn("Unable to close connection", e);
|
||||
}
|
||||
|
||||
@ -87,8 +87,13 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider {
|
||||
public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms) {
|
||||
final Map<VirtualMachine, Backup.Metric> metrics = new HashMap<>();
|
||||
final Backup.Metric metric = new Backup.Metric(1000L, 100L);
|
||||
if (vms == null || vms.isEmpty()) {
|
||||
return metrics;
|
||||
}
|
||||
for (VirtualMachine vm : vms) {
|
||||
metrics.put(vm, metric);
|
||||
if (vm != null) {
|
||||
metrics.put(vm, metric);
|
||||
}
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
|
||||
@ -216,9 +216,12 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider,
|
||||
@Override
|
||||
public Map<VirtualMachine, Backup.Metric> getBackupMetrics(final Long zoneId, final List<VirtualMachine> vms) {
|
||||
final Map<VirtualMachine, Backup.Metric> metrics = new HashMap<>();
|
||||
if (vms == null || vms.isEmpty()) {
|
||||
return metrics;
|
||||
}
|
||||
final Map<String, Backup.Metric> backendMetrics = getClient(zoneId).getBackupMetrics();
|
||||
for (final VirtualMachine vm : vms) {
|
||||
if (!backendMetrics.containsKey(vm.getUuid())) {
|
||||
if (vm == null || !backendMetrics.containsKey(vm.getUuid())) {
|
||||
continue;
|
||||
}
|
||||
metrics.put(vm, backendMetrics.get(vm.getUuid()));
|
||||
|
||||
@ -84,7 +84,6 @@ import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.usage.dao.UsageBackupDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountService;
|
||||
@ -126,8 +125,6 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
||||
@Inject
|
||||
private AccountManager accountManager;
|
||||
@Inject
|
||||
private UsageBackupDao usageBackupDao;
|
||||
@Inject
|
||||
private VolumeDao volumeDao;
|
||||
@Inject
|
||||
private DataCenterDao dataCenterDao;
|
||||
@ -1001,7 +998,6 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
||||
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
final int SYNC_INTERVAL = BackupSyncPollingInterval.value().intValue();
|
||||
try {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Backup sync background task is running...");
|
||||
@ -1022,31 +1018,23 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sync backup usage metrics
|
||||
final Map<VirtualMachine, Backup.Metric> metrics = backupProvider.getBackupMetrics(dataCenter.getId(), new ArrayList<>(vms));
|
||||
final GlobalLock syncBackupMetricsLock = GlobalLock.getInternLock("BackupSyncTask_metrics_zone_" + dataCenter.getId());
|
||||
if (syncBackupMetricsLock.lock(SYNC_INTERVAL)) {
|
||||
try {
|
||||
for (final VirtualMachine vm : metrics.keySet()) {
|
||||
final Backup.Metric metric = metrics.get(vm);
|
||||
if (metric != null) {
|
||||
usageBackupDao.updateMetrics(vm, metric);
|
||||
}
|
||||
try {
|
||||
for (final VirtualMachine vm : metrics.keySet()) {
|
||||
final Backup.Metric metric = metrics.get(vm);
|
||||
if (metric != null) {
|
||||
// Sync out-of-band backups
|
||||
backupProvider.syncBackups(vm, metric);
|
||||
// Emit a usage event, update usage metric for the VM by the usage server
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_BACKUP_USAGE_METRIC, vm.getAccountId(),
|
||||
vm.getDataCenterId(), vm.getId(), "Backup-" + vm.getHostName() + "-" + vm.getUuid(),
|
||||
vm.getBackupOfferingId(), null, metric.getBackupSize(), metric.getDataSize(),
|
||||
Backup.class.getSimpleName(), vm.getUuid());
|
||||
}
|
||||
} finally {
|
||||
syncBackupMetricsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Sync out-of-band backups
|
||||
for (final VirtualMachine vm : vms) {
|
||||
final GlobalLock syncBackupsLock = GlobalLock.getInternLock("BackupSyncTask_backup_vm_" + vm.getId());
|
||||
if (syncBackupsLock.lock(SYNC_INTERVAL)) {
|
||||
try {
|
||||
backupProvider.syncBackups(vm, metrics.get(vm));
|
||||
} finally {
|
||||
syncBackupsLock.unlock();
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Failed to sync backup usage metrics and out-of-band backups");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1081,7 +1081,10 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
||||
}
|
||||
|
||||
private boolean isBackupEvent(String eventType) {
|
||||
return eventType != null && (eventType.equals(EventTypes.EVENT_VM_BACKUP_OFFERING_ASSIGN) || eventType.equals(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVE));
|
||||
return eventType != null && (
|
||||
eventType.equals(EventTypes.EVENT_VM_BACKUP_OFFERING_ASSIGN) ||
|
||||
eventType.equals(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVE) ||
|
||||
eventType.equals(EventTypes.EVENT_VM_BACKUP_USAGE_METRIC));
|
||||
}
|
||||
|
||||
private void createVMHelperEvent(UsageEventVO event) {
|
||||
@ -1913,7 +1916,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
||||
final UsageBackupVO backupVO = new UsageBackupVO(zoneId, accountId, domainId, vmId, backupOfferingId, created);
|
||||
usageBackupDao.persist(backupVO);
|
||||
} else if (EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVE.equals(event.getType())) {
|
||||
usageBackupDao.removeUsage(accountId, zoneId, vmId);
|
||||
usageBackupDao.removeUsage(accountId, vmId, event.getCreateDate());
|
||||
} else if (EventTypes.EVENT_VM_BACKUP_USAGE_METRIC.equals(event.getType())) {
|
||||
usageBackupDao.updateMetrics(vmId, event.getSize(), event.getVirtualSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user