/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package controllers; import static controllers.Common.flashException; import java.util.HashMap; import java.util.List; import java.util.Map; import com.emc.vipr.model.sys.backup.BackupRestoreStatus; import com.emc.vipr.model.sys.backup.BackupInfo; import models.datatable.BackupDataTable; import models.datatable.BackupDataTable.Type; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import play.data.binding.As; import play.data.validation.Required; import play.data.validation.Validation; import play.mvc.Controller; import play.mvc.With; import util.BackupUtils; import util.MessagesUtils; import util.datatable.DataTablesSupport; import com.emc.vipr.client.exceptions.ViPRException; import com.emc.vipr.model.sys.backup.BackupSets.BackupSet; import com.emc.vipr.model.sys.backup.BackupUploadStatus; import com.google.common.collect.Lists; import controllers.deadbolt.Restrict; import controllers.deadbolt.Restrictions; import controllers.util.FlashException; /** * @author mridhr * */ @With(Common.class) @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public class Backup extends Controller { private static final Logger log = LoggerFactory.getLogger(Backup.class); protected static final String SAVED_SUCCESS = "backup.save.success"; protected static final String DELETED_SUCCESS = "backup.delete.success"; protected static final String DELETED_ERROR = "backup.delete.error"; @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void list(Type type) { if (type == null) { type = Type.LOCAL; } BackupDataTable dataTable = new BackupDataTable(type); renderArgs.put("type", type); render(dataTable); } @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void listJson(Type type) { List<BackupDataTable.Backup> backups = BackupDataTable.fetch(type == null ? Type.LOCAL : type); renderJSON(DataTablesSupport.createJSON(backups, params)); } /** * Get local backup info * @param ids */ @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void itemsJson(@As(",") String[] ids) { List<BackupDataTable.Backup> results = Lists.newArrayList(); if (ids != null) { for (String id : ids) { if (StringUtils.isNotBlank(id)) { BackupSet backupSet = BackupUtils.getBackup(id); if (backupSet != null) { BackupDataTable.Backup backup = new BackupDataTable.Backup(backupSet); BackupRestoreStatus restoreStatus = BackupUtils.getRestoreStatus(id, true); backup.alterLocalBackupRestoreStatus(restoreStatus); results.add(backup); } } } } renderJSON(results); } /** * Only get the remote backup info * @param ids */ @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void externalItemsJson(@As(",") String[] ids) { List<BackupDataTable.Backup> results = Lists.newArrayList(); if (ids != null) { for (String id : ids) { if (StringUtils.isNotBlank(id)) { BackupInfo backupInfo = BackupUtils.getBackupInfo(id, false); BackupDataTable.Backup backup = new BackupDataTable.Backup(id, false); backup.creationtime = backupInfo.getCreateTime(); backup.sitename = backupInfo.getSiteName(); backup.version = backupInfo.getVersion(); backup.size = backupInfo.getBackupSize(); results.add(backup); } } } renderJSON(results); } /** * Only get the remote restore status * @param ids */ @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void externalStatusJson(@As(",") String[] ids) { List<BackupDataTable.Backup> results = Lists.newArrayList(); for (String id : ids) { if (StringUtils.isNotBlank(id)) { BackupDataTable.Backup backup = new BackupDataTable.Backup(id, false); BackupRestoreStatus restoreStatus = BackupUtils.getRestoreStatus(id, false); backup.status = restoreStatus.getStatus().name(); if (restoreStatus.getStatus() == BackupRestoreStatus.Status.RESTORE_FAILED) { backup.error = restoreStatus.getDetails(); } results.add(backup); } } renderJSON(results); } public static void create() { render(); } public static void cancel() { list(Type.LOCAL); } @FlashException(keep = true, referrer = { "create" }) public static void save() { BackupForm backupForm = new BackupForm(); backupForm.name = params.get("backupForm.name"); backupForm.force = params.get("backupForm.force", boolean.class); backupForm.validate("name"); if (Validation.hasErrors()) { Common.handleError(); } try { backupForm.save(); flash.success(MessagesUtils.get(SAVED_SUCCESS, backupForm.name)); backToReferrer(); } catch (ViPRException e) { flashException(e); error(backupForm); } } public static void edit(String id) { list(Type.LOCAL); } @FlashException(value = "list") public static void delete(@As(",") String[] ids) { if (ids != null && ids.length > 0) { boolean deleteExecuted = false; for (String backupName : ids) { BackupUtils.deleteBackup(backupName.replace("+"," ")); deleteExecuted = true; } if (deleteExecuted == true) { flash.success(MessagesUtils.get("backups.deleted")); } } list(Type.LOCAL); } @FlashException(value = "list") public static void upload(String id) { BackupUtils.uploadBackup(id); list(Type.LOCAL); } @Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SYSTEM_MONITOR"), @Restrict("RESTRICTED_SYSTEM_ADMIN") }) public static void getUploadStatus(String id) { BackupUploadStatus status = BackupUtils.getUploadStatus(id); renderJSON(status); } public static void restore(String id, Type type) { if (type == Type.REMOTE) { // pull first if remote backup set BackupUtils.pullBackup(id); } BackupRestoreStatus status = BackupUtils.getRestoreStatus(id, type == Type.LOCAL); renderArgs.put("status", status); renderArgs.put("percentages", new RestoreStatus(status).percentageMap); renderArgs.put("id", id); renderArgs.put("type", type); render(); } public static void cancelPullBackup(Type type) { if (type == Type.REMOTE) { BackupUtils.cancelPullBackup(); } list(type); } public static void doRestore() { Type type = params.get("restoreForm.type", Type.class); boolean isLocal = type == Type.LOCAL; String name = params.get("restoreForm.name"); RestoreForm restoreForm = new RestoreForm(name, params.get("restoreForm.password"), isLocal, params.get("restoreForm.isGeoFromScratch", boolean.class)); restoreForm.restore(); flash("initialTimeout", 10000); Maintenance.maintenance(Common.reverseRoute(Backup.class, "list", "type", type)); } public static void getRestoreStatus(String id, Type type) { BackupRestoreStatus status = BackupUtils.getRestoreStatus(id, type == Type.LOCAL); renderJSON(new RestoreStatus(status)); } private static void backToReferrer() { String referrer = Common.getReferrer(); if (StringUtils.isNotBlank(referrer)) { redirect(referrer); } else { list(Type.LOCAL); } } /** * Handles an error while saving a backup form. * * @param backupForm * the backup form. */ private static void error(BackupForm backupForm) { params.flash(); Validation.keep(); create(); } public static class BackupForm { @Required public String name; public boolean force; public void validate(String fieldname) { Validation.valid(fieldname, this); } public void save() throws ViPRException { BackupUtils.createBackup(name, force); } } public static class RestoreForm { @Required public String name; @Required public String password; public boolean isLocal; public boolean isGeoFromScratch = false; public RestoreForm(String name, String password, boolean isLocal, boolean isGeo) { this.name = name; this.password = password; this.isLocal = isLocal; this.isGeoFromScratch = isGeo; } public void restore() throws ViPRException { BackupUtils.restore(name, StringUtils.trimToNull(password), isLocal, isGeoFromScratch); } } public static class RestoreStatus { private String backupName; private BackupRestoreStatus.Status status; private boolean isGeo; private Map<String, Long> sizeToDownload; private Map<String, Long> downloadedSize; private Map<String, Integer> percentageMap; private String details; public RestoreStatus(BackupRestoreStatus origin) { this.backupName = origin.getBackupName(); this.sizeToDownload = origin.getSizeToDownload(); this.downloadedSize = origin.getDownloadedSize(); this.status = origin.getStatus(); this.isGeo = origin.isGeo(); this.details = origin.getDetails(); percentageMap = new HashMap<String, Integer>(sizeToDownload.size()); for (String hostname : sizeToDownload.keySet()) { int percentage = sizeToDownload.get(hostname) == 0L ? 0 : (int) (downloadedSize.get(hostname) * 100 / sizeToDownload.get(hostname)); if (percentage > 100) { percentage = 100; } percentageMap.put(hostname, percentage); } } } }