Fix backup dates (#6473)

Co-authored-by: João Paraquetti <joao@scclouds.com.br>
Co-authored-by: dahn <daan.hoogland@gmail.com>
This commit is contained in:
João Jandre 2023-08-18 05:51:36 -03:00 committed by GitHub
parent 7049a6058d
commit 1065e9046b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 171 additions and 24 deletions

View File

@ -25,6 +25,8 @@ import org.apache.cloudstack.backup.Backup;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
@EntityReference(value = Backup.class)
public class BackupResponse extends BaseResponse {
@ -50,7 +52,7 @@ public class BackupResponse extends BaseResponse {
@SerializedName(ApiConstants.CREATED)
@Param(description = "backup date")
private String date;
private Date date;
@SerializedName(ApiConstants.SIZE)
@Param(description = "backup size in bytes")
@ -140,11 +142,11 @@ public class BackupResponse extends BaseResponse {
this.type = type;
}
public String getDate() {
return date;
public Date getDate() {
return this.date;
}
public void setDate(String date) {
public void setDate(Date date) {
this.date = date;
}

View File

@ -25,6 +25,8 @@ import org.apache.cloudstack.backup.Backup;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
@EntityReference(value = Backup.RestorePoint.class)
public class BackupRestorePointResponse extends BaseResponse {
@ -34,7 +36,7 @@ public class BackupRestorePointResponse extends BaseResponse {
@SerializedName(ApiConstants.CREATED)
@Param(description = "created time")
private String created;
private Date created;
@SerializedName(ApiConstants.TYPE)
@Param(description = "restore point type")
@ -48,11 +50,11 @@ public class BackupRestorePointResponse extends BaseResponse {
this.id = id;
}
public String getCreated() {
return created;
public Date getCreated() {
return this.created;
}
public void setCreated(String created) {
public void setCreated(Date created) {
this.created = created;
}

View File

@ -17,6 +17,8 @@
package org.apache.cloudstack.backup;
import java.util.Date;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@ -58,10 +60,10 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
class RestorePoint {
private String id;
private String created;
private Date created;
private String type;
public RestorePoint(String id, String created, String type) {
public RestorePoint(String id, Date created, String type) {
this.id = id;
this.created = created;
this.type = type;
@ -75,11 +77,11 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
this.id = id;
}
public String getCreated() {
return created;
public Date getCreated() {
return this.created;
}
public void setCreated(String created) {
public void setCreated(Date created) {
this.created = created;
}
@ -134,7 +136,7 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
long getVmId();
String getExternalId();
String getType();
String getDate();
Date getDate();
Backup.Status getStatus();
Long getSize();
Long getProtectedSize();

View File

@ -17,16 +17,27 @@
package com.cloud.upgrade.dao;
import com.cloud.upgrade.SystemVmTemplateRegistration;
import com.cloud.utils.DateUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.log4j.Logger;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Upgrade41810to41900 implements DbUpgrade, DbUpgradeSystemVmTemplate {
final static Logger LOG = Logger.getLogger(Upgrade41810to41900.class);
private SystemVmTemplateRegistration systemVmTemplateRegistration;
private final SimpleDateFormat[] formats = {
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"), new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"),
new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy")};
@Override
public String[] getUpgradableVersionRange() {
return new String[] {"4.18.1.0", "4.19.0.0"};
@ -55,6 +66,7 @@ public class Upgrade41810to41900 implements DbUpgrade, DbUpgradeSystemVmTemplate
@Override
public void performDataMigration(Connection conn) {
migrateBackupDates(conn);
}
@Override
@ -82,4 +94,103 @@ public class Upgrade41810to41900 implements DbUpgrade, DbUpgradeSystemVmTemplate
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)");
}
}
public void migrateBackupDates(Connection conn) {
LOG.info("Trying to convert backups' date column from varchar(255) to datetime type.");
modifyDateColumnNameAndCreateNewOne(conn);
fetchDatesAndMigrateToNewColumn(conn);
dropOldColumn(conn);
LOG.info("Finished converting backups' date column from varchar(255) to datetime.");
}
private void modifyDateColumnNameAndCreateNewOne(Connection conn) {
String alterColumnName = "ALTER TABLE `cloud`.`backups` CHANGE COLUMN `date` `old_date` varchar(255);";
try (PreparedStatement pstmt = conn.prepareStatement(alterColumnName)) {
pstmt.execute();
} catch (SQLException e) {
String message = String.format("Unable to alter backups' date column name due to [%s].", e.getMessage());
LOG.error(message, e);
throw new CloudRuntimeException(message, e);
}
String createNewColumn = "ALTER TABLE `cloud`.`backups` ADD COLUMN `date` DATETIME;";
try (PreparedStatement pstmt = conn.prepareStatement(createNewColumn)) {
pstmt.execute();
} catch (SQLException e) {
String message = String.format("Unable to crate new backups' column date due to [%s].", e.getMessage());
LOG.error(message, e);
throw new CloudRuntimeException(message, e);
}
}
private void fetchDatesAndMigrateToNewColumn(Connection conn) {
String selectBackupDates = "SELECT `id`, `old_date` FROM `cloud`.`backups` WHERE 1;";
String date;
java.sql.Date reformatedDate;
try (PreparedStatement pstmt = conn.prepareStatement(selectBackupDates)) {
try (ResultSet result = pstmt.executeQuery()) {
while (result.next()) {
date = result.getString("old_date");
reformatedDate = tryToTransformStringToDate(date);
updateBackupDate(conn, result.getLong("id"), reformatedDate);
}
}
} catch (SQLException e) {
String message = String.format("Unable to retrieve backup dates due to [%s].", e.getMessage());
LOG.error(message, e);
throw new CloudRuntimeException(message, e);
}
}
private java.sql.Date tryToTransformStringToDate(String date) {
Date parsedDate = null;
try {
parsedDate = DateUtil.parseTZDateString(date);
} catch (ParseException e) {
for (SimpleDateFormat sdf: formats) {
try {
parsedDate = sdf.parse(date);
} catch (ParseException ex) {
continue;
}
break;
}
}
if (parsedDate == null) {
String msg = String.format("Unable to parse date [%s]. Will change backup date to null.", date);
LOG.error(msg);
return null;
}
return new java.sql.Date(parsedDate.getTime());
}
private void updateBackupDate(Connection conn, long id, java.sql.Date date) {
String updateBackupDate = "UPDATE `cloud`.`backups` SET `date` = ? WHERE `id` = ?;";
try (PreparedStatement pstmt = conn.prepareStatement(updateBackupDate)) {
pstmt.setDate(1, date);
pstmt.setLong(2, id);
pstmt.executeUpdate();
} catch (SQLException e) {
String message = String.format("Unable to update backup date with id [%s] to date [%s] due to [%s].", id, date, e.getMessage());
LOG.error(message, e);
throw new CloudRuntimeException(message, e);
}
}
private void dropOldColumn(Connection conn) {
String dropOldColumn = "ALTER TABLE `cloud`.`backups` DROP COLUMN `old_date`;";
try (PreparedStatement pstmt = conn.prepareStatement(dropOldColumn)) {
pstmt.execute();
} catch (SQLException e) {
String message = String.format("Unable to drop old_date column due to [%s].", e.getMessage());
LOG.error(message, e);
throw new CloudRuntimeException(message, e);
}
}
}

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.backup;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
@ -27,6 +28,8 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@Table(name = "backups")
@ -49,7 +52,8 @@ public class BackupVO implements Backup {
private String backupType;
@Column(name = "date")
private String date;
@Temporal(value = TemporalType.DATE)
private Date date;
@Column(name = "size")
private Long size;
@ -114,11 +118,11 @@ public class BackupVO implements Backup {
}
@Override
public String getDate() {
return date;
public Date getDate() {
return this.date;
}
public void setDate(String date) {
public void setDate(Date date) {
this.date = date;
}

View File

@ -117,7 +117,7 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider {
backup.setVmId(vm.getId());
backup.setExternalId("dummy-external-id");
backup.setType("FULL");
backup.setDate(new Date().toString());
backup.setDate(new Date());
backup.setSize(1024L);
backup.setProtectedSize(1024000L);
backup.setStatus(Backup.Status.BackedUp);

View File

@ -51,6 +51,8 @@ import javax.inject.Inject;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -605,7 +607,14 @@ public class NetworkerBackupProvider extends AdapterBase implements BackupProvid
strayBackup.setVmId(vm.getId());
strayBackup.setExternalId(strayNetworkerBackup.getId());
strayBackup.setType(strayNetworkerBackup.getType());
strayBackup.setDate(strayNetworkerBackup.getSaveTime());
SimpleDateFormat formatterDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
strayBackup.setDate(formatterDateTime.parse(strayNetworkerBackup.getSaveTime()));
} catch (ParseException e) {
String msg = String.format("Unable to parse date [%s].", strayNetworkerBackup.getSaveTime());
LOG.error(msg, e);
throw new CloudRuntimeException(msg, e);
}
strayBackup.setStatus(Backup.Status.BackedUp);
for ( Backup.VolumeInfo thisVMVol : vm.getBackupVolumeList()) {
vmBackupSize += (thisVMVol.getSize() / 1024L /1024L);

View File

@ -211,7 +211,7 @@ public class NetworkerClient {
SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat formatterTime = new SimpleDateFormat("HH:mm:ss");
SimpleDateFormat formatterDateTime = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
SimpleDateFormat formatterDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String startDate = formatterDate.format(backupJobStart);
String startTime = formatterTime.format(backupJobStart);
@ -252,7 +252,13 @@ public class NetworkerClient {
backup.setVmId(vm.getId());
backup.setExternalId(networkerLatestBackup.getId());
backup.setType(networkerLatestBackup.getType());
backup.setDate(networkerLatestBackup.getCreationTime());
try {
backup.setDate(formatterDateTime.parse(networkerLatestBackup.getCreationTime()));
} catch (ParseException e) {
String msg = String.format("Unable to parse date [%s].", networkerLatestBackup.getCreationTime());
LOG.error(msg, e);
throw new CloudRuntimeException(msg, e);
}
backup.setSize(networkerLatestBackup.getSize().getValue());
backup.setProtectedSize(networkerLatestBackup.getSize().getValue());
backup.setStatus(org.apache.cloudstack.backup.Backup.Status.BackedUp);

View File

@ -34,6 +34,8 @@ import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.UUID;
import java.util.Date;
import java.util.Calendar;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
@ -660,7 +662,7 @@ public class VeeamClient {
private Backup.RestorePoint getRestorePointFromBlock(String[] parts) {
LOG.debug(String.format("Processing block of restore points: [%s].", StringUtils.join(parts, ", ")));
String id = null;
String created = null;
Date created = null;
String type = null;
for (String part : parts) {
if (part.matches("Id(\\s)+:(.)*")) {
@ -668,7 +670,11 @@ public class VeeamClient {
id = split[1].trim();
} else if (part.matches("CreationTime(\\s)+:(.)*")) {
String [] split = part.split(":", 2);
created = split[1].trim();
split[1] = StringUtils.trim(split[1]);
String [] time = split[1].split("[:/ ]");
Calendar cal = Calendar.getInstance();
cal.set(Integer.parseInt(time[2]), Integer.parseInt(time[0]) - 1, Integer.parseInt(time[1]), Integer.parseInt(time[3]), Integer.parseInt(time[4]), Integer.parseInt(time[5]));
created = cal.getTime();
} else if (part.matches("Type(\\s)+:(.)*")) {
String [] split = part.split(":");
type = split[1].trim();

View File

@ -51,6 +51,11 @@
<status :text="text ? text : ''" />{{ text }}
</template>
</template>
<template v-slot:created="{ item }">
{{ $toLocaleDate(item) }}
</template>
</a-table>
<div v-if="!defaultPagination" style="display: block; text-align: right; margin-top: 10px;">