package com.sungardas.enhancedsnapshots.util; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ListObjectsRequest; import com.amazonaws.services.s3.model.S3Object; import com.sungardas.enhancedsnapshots.exception.EnhancedSnapshotsException; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class EnhancedSnapshotSystemMetadataUtil { private static final Logger LOG = LogManager.getLogger(EnhancedSnapshotSystemMetadataUtil.class); private static final String TEMP_DIRECTORY_PREFIX = "systemBackupFiles"; private static final String INFO_FILE_NAME = "info"; private static final String VERSION_KEY = "version"; private static final String TEMP_FILE_SUFFIX = "ZIP"; private static final ObjectMapper objectMapper = new ObjectMapper(); private EnhancedSnapshotSystemMetadataUtil() { } /** * Return true when S3 bucket contains SDFS backup, false otherwise */ public static boolean containsSdfsMetadata(String sBucket, String sdfsBackupFileName, AmazonS3 amazonS3) { if(!isBucketExits(sBucket, amazonS3)){ return false; } ListObjectsRequest request = new ListObjectsRequest().withBucketName(sBucket).withPrefix(sdfsBackupFileName); return amazonS3.listObjects(request).getObjectSummaries().size() > 0; } public static boolean isBucketExits(String s3Bucket, AmazonS3 amazonS3) { try { String location = amazonS3.getBucketLocation(s3Bucket); return location != null; } catch (Exception e) { return false; } } /** * Method for defining application version, which created system backup * * @param tempDirectory directory to which was unzipped system backup * @return application version */ public static String getBackupVersion(final Path tempDirectory) { Path infoFile = Paths.get(tempDirectory.toString(), INFO_FILE_NAME); if (infoFile.toFile().exists()) { try (FileInputStream fileInputStream = new FileInputStream(infoFile.toFile())) { HashMap<String, String> info = objectMapper.readValue(fileInputStream, HashMap.class); if (info.containsKey(VERSION_KEY)) { return info.get(VERSION_KEY); } else { LOG.error("Invalid info file formant"); throw new EnhancedSnapshotsException("Invalid info file formant"); } } catch (IOException e) { LOG.error("Failed to parse info file"); LOG.error(e); throw new EnhancedSnapshotsException(e); } } return "0.0.1"; } /** * Method for defining application version, which created system backup * * @param bucketName * @param sdfsBackupFileName * @param amazonS3 * @return application version */ public static String getBackupVersion(final String bucketName, String sdfsBackupFileName, AmazonS3 amazonS3) { Path tempDirectory = null; String version = null; if (containsSdfsMetadata(bucketName, sdfsBackupFileName, amazonS3)) { try { tempDirectory = Files.createTempDirectory(TEMP_DIRECTORY_PREFIX); EnhancedSnapshotSystemMetadataUtil.downloadFromS3(tempDirectory, bucketName, sdfsBackupFileName, amazonS3); version = getBackupVersion(tempDirectory); } catch (IOException e) { LOG.error(e); } finally { if (tempDirectory != null) { try { FileUtils.deleteDirectory(tempDirectory.toFile()); } catch (IOException e) { } } } } return version; } public static void downloadFromS3(Path tempDirectory, String s3Bucket, String sdfsBackupFileName, AmazonS3 amazonS3) throws IOException { // download LOG.info("-Download"); GetObjectRequest getObjectRequest = new GetObjectRequest(s3Bucket, sdfsBackupFileName); S3Object s3object = amazonS3.getObject(getObjectRequest); Path tempFile = Files.createTempFile(TEMP_DIRECTORY_PREFIX, TEMP_FILE_SUFFIX); Files.copy(s3object.getObjectContent(), tempFile, StandardCopyOption.REPLACE_EXISTING); LOG.info(" -Unzip"); //unzip try (FileInputStream fileInputStream = new FileInputStream(tempFile.toFile()); ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) { ZipEntry entry; while ((entry = zipInputStream.getNextEntry()) != null) { // in case entry is directory system backup relates to version 0.0.1 // copy /etc/sdfs/awspool-volume-cfg.xml to temp dir if (entry.isDirectory()) { zipInputStream.getNextEntry(); zipInputStream.getNextEntry(); Path dest = Paths.get(tempDirectory.toString(), "awspool-volume-cfg.xml"); Files.copy(zipInputStream, dest, StandardCopyOption.REPLACE_EXISTING); break; } Path dest = Paths.get(tempDirectory.toString(), entry.getName()); Files.copy(zipInputStream, dest, StandardCopyOption.REPLACE_EXISTING); } } //cleanup tempFile.toFile().delete(); } }