From 6fe3ca58f50312e950190c8808dbb63800720348 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 15 Apr 2025 08:59:18 +0200 Subject: [PATCH] Veeam: use pre-defined object mapper --- .../cloudstack/backup/veeam/VeeamClient.java | 45 +++++++------------ .../backup/veeam/VeeamClientTest.java | 4 +- 2 files changed, 20 insertions(+), 29 deletions(-) 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 d911736090cb..0a8b18fd65e9 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 @@ -107,7 +107,8 @@ public class VeeamClient { private static final String REPOSITORY_REFERENCE = "RepositoryReference"; private static final String RESTORE_POINT_REFERENCE = "RestorePointReference"; private static final String BACKUP_FILE_REFERENCE = "BackupFileReference"; - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static final ObjectMapper OBJECT_MAPPER = new XmlMapper(); private String veeamServerIp; @@ -127,6 +128,8 @@ public VeeamClient(final String url, final Integer version, final String usernam this.taskPollInterval = taskPollInterval; this.taskPollMaxRetry = taskPollMaxRetry; + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final RequestConfig config = RequestConfig.custom() .setConnectTimeout(timeout * 1000) .setConnectionRequestTimeout(timeout * 1000) @@ -236,8 +239,7 @@ protected HttpResponse get(final String path) throws IOException { private HttpResponse post(final String path, final Object obj) throws IOException { String xml = null; if (obj != null) { - XmlMapper xmlMapper = new XmlMapper(); - xml = xmlMapper.writer() + xml = OBJECT_MAPPER.writer() .with(ToXmlGenerator.Feature.WRITE_XML_DECLARATION) .writeValueAsString(obj); // Remove invalid/empty xmlns @@ -280,8 +282,7 @@ private String findDCHierarchy(final String vmwareDcName) { try { final HttpResponse response = get("/hierarchyRoots"); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - final EntityReferences references = objectMapper.readValue(response.getEntity().getContent(), EntityReferences.class); + final EntityReferences references = OBJECT_MAPPER.readValue(response.getEntity().getContent(), EntityReferences.class); for (final Ref ref : references.getRefs()) { if (ref.getName().equals(vmwareDcName) && ref.getType().equals(HIERARCHY_ROOT_REFERENCE)) { return ref.getUid(); @@ -300,8 +301,7 @@ private String lookupVM(final String hierarchyId, final String vmName) { try { final HttpResponse response = get(String.format("/lookup?host=%s&type=Vm&name=%s", hierarchyId, vmName)); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - final HierarchyItems items = objectMapper.readValue(response.getEntity().getContent(), HierarchyItems.class); + final HierarchyItems items = OBJECT_MAPPER.readValue(response.getEntity().getContent(), HierarchyItems.class); if (items == null || items.getItems() == null || items.getItems().isEmpty()) { throw new CloudRuntimeException("Could not find VM " + vmName + " in Veeam, please ask administrator to check Veeam B&R manager"); } @@ -319,14 +319,12 @@ private String lookupVM(final String hierarchyId, final String vmName) { private Task parseTaskResponse(HttpResponse response) throws IOException { checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - return objectMapper.readValue(response.getEntity().getContent(), Task.class); + return OBJECT_MAPPER.readValue(response.getEntity().getContent(), Task.class); } protected RestoreSession parseRestoreSessionResponse(HttpResponse response) throws IOException { checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - return objectMapper.readValue(response.getEntity().getContent(), RestoreSession.class); + return OBJECT_MAPPER.readValue(response.getEntity().getContent(), RestoreSession.class); } private boolean checkTaskStatus(final HttpResponse response) throws IOException { @@ -413,8 +411,7 @@ public Ref listBackupRepository(final String backupServerId, final String backup String repositoryName = getRepositoryNameFromJob(backupName); final HttpResponse response = get(String.format("/backupServers/%s/repositories", backupServerId)); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - final EntityReferences references = objectMapper.readValue(response.getEntity().getContent(), EntityReferences.class); + final EntityReferences references = OBJECT_MAPPER.readValue(response.getEntity().getContent(), EntityReferences.class); for (final Ref ref : references.getRefs()) { if (ref.getType().equals(REPOSITORY_REFERENCE) && ref.getName().equals(repositoryName)) { return ref; @@ -450,8 +447,7 @@ public void listAllBackups() { try { final HttpResponse response = get("/backups"); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - final EntityReferences entityReferences = objectMapper.readValue(response.getEntity().getContent(), EntityReferences.class); + final EntityReferences entityReferences = OBJECT_MAPPER.readValue(response.getEntity().getContent(), EntityReferences.class); for (final Ref ref : entityReferences.getRefs()) { logger.debug("Veeam Backup found, name: " + ref.getName() + ", uid: " + ref.getUid() + ", type: " + ref.getType()); } @@ -466,8 +462,7 @@ public List listJobs() { try { final HttpResponse response = get("/jobs"); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - final EntityReferences entityReferences = objectMapper.readValue(response.getEntity().getContent(), EntityReferences.class); + final EntityReferences entityReferences = OBJECT_MAPPER.readValue(response.getEntity().getContent(), EntityReferences.class); final List policies = new ArrayList<>(); if (entityReferences == null || entityReferences.getRefs() == null) { return policies; @@ -489,9 +484,7 @@ public Job listJob(final String jobId) { final HttpResponse response = get(String.format("/jobs/%s?format=Entity", jobId.replace("urn:veeam:Job:", ""))); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - return objectMapper.readValue(response.getEntity().getContent(), Job.class); + return OBJECT_MAPPER.readValue(response.getEntity().getContent(), Job.class); } catch (final IOException e) { logger.error("Failed to list Veeam jobs due to:", e); checkResponseTimeOut(e); @@ -571,9 +564,7 @@ public boolean removeVMFromVeeamJob(final String jobId, final String vmwareInsta final String veeamVmRefId = lookupVM(hierarchyId, vmwareInstanceName); final HttpResponse response = get(String.format("/jobs/%s/includes", jobId)); checkResponseOK(response); - final ObjectMapper objectMapper = new XmlMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - final ObjectsInJob jobObjects = objectMapper.readValue(response.getEntity().getContent(), ObjectsInJob.class); + final ObjectsInJob jobObjects = OBJECT_MAPPER.readValue(response.getEntity().getContent(), ObjectsInJob.class); if (jobObjects == null || jobObjects.getObjects() == null) { logger.warn("No objects found in the Veeam job " + jobId); return false; @@ -715,8 +706,7 @@ public Map getBackupMetricsViaVeeamAPI() { protected Map processHttpResponseForBackupMetrics(final InputStream content) { Map metrics = new HashMap<>(); try { - final ObjectMapper objectMapper = new XmlMapper(); - final BackupFiles backupFiles = objectMapper.readValue(content, BackupFiles.class); + final BackupFiles backupFiles = OBJECT_MAPPER.readValue(content, BackupFiles.class); if (backupFiles == null || CollectionUtils.isEmpty(backupFiles.getBackupFiles())) { throw new CloudRuntimeException("Could not get backup metrics via Veeam B&R API"); } @@ -885,8 +875,7 @@ public List listVmRestorePointsViaVeeamAPI(String vmInterna public List processHttpResponseForVmRestorePoints(InputStream content, String vmInternalName) { List vmRestorePointList = new ArrayList<>(); try { - final ObjectMapper objectMapper = new XmlMapper(); - final VmRestorePoints vmRestorePoints = objectMapper.readValue(content, VmRestorePoints.class); + final VmRestorePoints vmRestorePoints = OBJECT_MAPPER.readValue(content, VmRestorePoints.class); if (vmRestorePoints == null) { throw new CloudRuntimeException("Could not get VM restore points via Veeam B&R API"); } @@ -922,7 +911,7 @@ public List processHttpResponseForVmRestorePoints(InputStre } private Date formatDate(String date) throws ParseException { - return dateFormat.parse(StringUtils.substring(date, 0, 19)); + return DATE_FORMAT.parse(StringUtils.substring(date, 0, 19)); } public Pair restoreVMToDifferentLocation(String restorePointId, String hostIp, String dataStoreUuid) { diff --git a/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java b/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java index 63d6896bb85c..f972399d2b9b 100644 --- a/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java +++ b/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java @@ -475,7 +475,9 @@ public void testListVmRestorePointsViaVeeamAPI() { " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xmlns=\"http://www.veeam.com/ent/v1.0\">\n" + - " \n" + + " \n" + " \n" + " \n" + " \n" +