This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 1065e9046b1 Fix backup dates (#6473)
1065e9046b1 is described below
commit 1065e9046b15360713a36c364fc25fc77fe362d4
Author: João Jandre <[email protected]>
AuthorDate: Fri Aug 18 05:51:36 2023 -0300
Fix backup dates (#6473)
Co-authored-by: João Paraquetti <[email protected]>
Co-authored-by: dahn <[email protected]>
---
.../cloudstack/api/response/BackupResponse.java | 10 +-
.../api/response/BackupRestorePointResponse.java | 10 +-
.../java/org/apache/cloudstack/backup/Backup.java | 14 +--
.../com/cloud/upgrade/dao/Upgrade41810to41900.java | 111 +++++++++++++++++++++
.../org/apache/cloudstack/backup/BackupVO.java | 12 ++-
.../cloudstack/backup/DummyBackupProvider.java | 2 +-
.../cloudstack/backup/NetworkerBackupProvider.java | 11 +-
.../backup/networker/NetworkerClient.java | 10 +-
.../cloudstack/backup/veeam/VeeamClient.java | 10 +-
ui/src/components/view/ListResourceTable.vue | 5 +
10 files changed, 171 insertions(+), 24 deletions(-)
diff --git
a/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java
b/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java
index d0c8e588450..63419680fea 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java
@@ -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;
}
diff --git
a/api/src/main/java/org/apache/cloudstack/api/response/BackupRestorePointResponse.java
b/api/src/main/java/org/apache/cloudstack/api/response/BackupRestorePointResponse.java
index afb3e9ffc5f..22bb099b1b0 100644
---
a/api/src/main/java/org/apache/cloudstack/api/response/BackupRestorePointResponse.java
+++
b/api/src/main/java/org/apache/cloudstack/api/response/BackupRestorePointResponse.java
@@ -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;
}
diff --git a/api/src/main/java/org/apache/cloudstack/backup/Backup.java
b/api/src/main/java/org/apache/cloudstack/backup/Backup.java
index 75c7ab4cca5..f369367957d 100644
--- a/api/src/main/java/org/apache/cloudstack/backup/Backup.java
+++ b/api/src/main/java/org/apache/cloudstack/backup/Backup.java
@@ -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();
diff --git
a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41810to41900.java
b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41810to41900.java
index c9ac468dc53..57f87d1f2cc 100644
--- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41810to41900.java
+++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41810to41900.java
@@ -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);
+ }
+ }
+
}
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
index dc47fcb6bb3..e5582609d68 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
@@ -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;
}
diff --git
a/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java
b/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java
index 0297ce82f5e..fabc9821fd3 100644
---
a/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java
+++
b/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java
@@ -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);
diff --git
a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
index 37051f9b5ee..9703203108a 100644
---
a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
+++
b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
@@ -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);
diff --git
a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/networker/NetworkerClient.java
b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/networker/NetworkerClient.java
index 939543df387..8bb89b635e9 100644
---
a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/networker/NetworkerClient.java
+++
b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/networker/NetworkerClient.java
@@ -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);
diff --git
a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
index 40fbe97028a..1438dca4838 100644
---
a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
+++
b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
@@ -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();
diff --git a/ui/src/components/view/ListResourceTable.vue
b/ui/src/components/view/ListResourceTable.vue
index c97aa0fb17e..16c1b388c5d 100644
--- a/ui/src/components/view/ListResourceTable.vue
+++ b/ui/src/components/view/ListResourceTable.vue
@@ -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;">