use of com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult.InvalidModule in project ma-modules-public by infiniteautomation.
the class ModulesRestController method uploadUpgrades.
@PreAuthorize("isAdmin()")
@ApiOperation(value = "Upload upgrade zip bundle, to be installed on restart", notes = "The bundle can be downloaded from the Mango Store")
@RequestMapping(method = RequestMethod.POST, value = "/upload-upgrades")
public UpgradeUploadResult uploadUpgrades(@ApiParam(value = "Perform Backup first", required = false, defaultValue = "false", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean backup, @ApiParam(value = "Restart after upload completes", required = false, defaultValue = "false", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean restart, MultipartHttpServletRequest multipartRequest) throws IOException {
if (env.getProperty("store.disableUpgrades", Boolean.class, false)) {
throw new FeatureDisabledException(new TranslatableMessage("modules.error.upgradesDisabled"));
}
synchronized (UPLOAD_UPGRADE_LOCK) {
if (UPLOAD_UPGRADE_IN_PROGRESS == null) {
UPLOAD_UPGRADE_IN_PROGRESS = new Object();
} else {
throw new BadRequestException(new TranslatableMessage("rest.error.upgradeUploadInProgress"));
}
}
UpgradeUploadResult result = new UpgradeUploadResult();
try {
if (backup) {
// Do the backups. They run async, so this returns immediately. The shutdown will
// wait for the
// background processes to finish though.
BackupWorkItem.queueBackup(SystemSettingsDao.getInstance().getValue(SystemSettingsDao.BACKUP_FILE_LOCATION));
DatabaseBackupWorkItem.queueBackup(SystemSettingsDao.getInstance().getValue(SystemSettingsDao.DATABASE_BACKUP_FILE_LOCATION));
}
List<MultipartFile> files = new ArrayList<>();
MultiValueMap<String, MultipartFile> filemap = multipartRequest.getMultiFileMap();
for (String nameField : filemap.keySet()) {
files.addAll(filemap.get(nameField));
}
// Validate the zip
if (files.size() == 0)
throw new BadRequestException(new TranslatableMessage("rest.error.noFileProvided"));
// Create the temp directory into which to download, if necessary.
Path tempDir = Common.getTempPath().resolve(ModuleUtils.DOWNLOAD_DIR);
Files.createDirectories(tempDir);
// Delete anything that is currently the temp directory.
FileUtils.cleanDirectory(tempDir.toFile());
try {
// Save the upload(s) to the temp dir
for (MultipartFile file : files) {
Path newFile = tempDir.resolve(file.getOriginalFilename());
try (InputStream is = file.getInputStream()) {
Files.copy(is, newFile);
}
}
List<Path> potentialUpgrades = Files.list(tempDir).filter(p -> p.toString().endsWith(".zip")).collect(Collectors.toList());
List<String> upgraded = new ArrayList<>();
List<String> unsigned = new ArrayList<>();
boolean developmentMode = env.getProperty("development.enabled", Boolean.class, false);
for (Path file : potentialUpgrades) {
boolean core = false;
boolean hasWebModules = false;
// Test to see if it is a core or a bundle of only zips or many zip files
try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
ZipEntry entry = is.getNextEntry();
if (entry == null) {
// Not a zip file or empty, either way we don't care
throw new BadRequestException(new TranslatableMessage("rest.error.badUpgradeFile"));
} else {
do {
String entryName = entry.getName();
if ("release.signed".equals(entryName) || "release.properties".equals(entryName)) {
if (!developmentMode && "release.properties".equals(entryName)) {
throw new BadRequestException(new TranslatableMessage("modules.unsigned.core.development"));
}
core = true;
break;
} else if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
hasWebModules = true;
}
} while ((entry = is.getNextEntry()) != null);
}
}
if (core) {
// move file to core directory
Files.move(file, Common.MA_HOME_PATH.resolve("m2m2-core-upgrade.zip"));
upgraded.add(file.getFileName().toString());
} else if (hasWebModules) {
// This is a zip with modules in web/modules move them all out into the MA_HOME/web/modules dir
try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
ZipEntry entry;
while ((entry = is.getNextEntry()) != null) {
if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
Path newModule = Common.MA_HOME_PATH.resolve(entry.getName());
Files.copy(is, newModule);
upgraded.add(newModule.getFileName().toString());
}
}
}
} else {
// if its a module move it to the modules folder
if (isModule(file, unsigned)) {
// Its extra work but we better check that it is a module from the store:
Files.move(file, Common.MODULES.resolve(file.getFileName()));
upgraded.add(file.getFileName().toString());
} else {
// Is this a zip of modules?
try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
ZipEntry entry;
while ((entry = is.getNextEntry()) != null) {
if (entry.getName().startsWith(ModuleUtils.Constants.MODULE_PREFIX)) {
// Extract it and confirm it is a module
Path newModule = tempDir.resolve(entry.getName());
Files.copy(is, newModule);
if (isModule(newModule, unsigned)) {
Files.move(newModule, Common.MODULES.resolve(newModule.getFileName()));
upgraded.add(newModule.getFileName().toString());
}
}
}
}
}
}
}
// Ensure we have some upgrades
if (upgraded.size() == 0 && unsigned.size() == 0) {
throw new BadRequestException(new TranslatableMessage("rest.error.invalidUpgradeFile"));
} else if (upgraded.size() == 0 && unsigned.size() > 0) {
throw new BadRequestException(new TranslatableMessage("modules.unsigned.development"));
}
result.setToUpgrade(upgraded);
List<InvalidModule> invalid = new ArrayList<>();
result.setInvalid(invalid);
for (String u : unsigned) {
invalid.add(new InvalidModule(u, new TranslatableMessage("modules.unsigned.development")));
}
} finally {
FileUtils.deleteDirectory(tempDir.toFile());
}
} finally {
// Release the lock
synchronized (UPLOAD_UPGRADE_LOCK) {
UPLOAD_UPGRADE_IN_PROGRESS = null;
}
}
if (restart && result.getToUpgrade().size() > 0) {
IMangoLifecycle lifecycle = Providers.get(IMangoLifecycle.class);
lifecycle.scheduleShutdown(null, true, Common.getUser());
result.setRestart(restart);
}
return result;
}
Aggregations