use of com.infiniteautomation.mango.util.exception.FeatureDisabledException 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;
}
use of com.infiniteautomation.mango.util.exception.FeatureDisabledException in project ma-core-public by infiniteautomation.
the class ModulesService method startDownloads.
/**
* Start downloading modules
*/
public String startDownloads(List<StringStringPair> modules, boolean backup, boolean restart) {
permissionService.ensureAdminRole(Common.getUser());
if (env.getProperty("store.disableUpgrades", Boolean.class, false)) {
throw new FeatureDisabledException(new TranslatableMessage("modules.error.upgradesDisabled"));
}
synchronized (upgradeDownloaderLock) {
if (upgradeDownloader != null)
return Common.translate("modules.versionCheck.occupied");
}
// Check if the selected modules will result in a version-consistent system.
try {
// Create the request
Map<String, Object> json = new HashMap<>();
Map<String, String> jsonModules = new HashMap<>();
json.put("modules", jsonModules);
Version coreVersion = Common.getVersion();
jsonModules.put(ModuleRegistry.CORE_MODULE_NAME, coreVersion.toString());
for (StringStringPair module : modules) jsonModules.put(module.getKey(), module.getValue());
StringWriter stringWriter = new StringWriter();
new JsonWriter(Common.JSON_CONTEXT, stringWriter).writeObject(json);
String requestData = stringWriter.toString();
// Send the request
String baseUrl = env.getProperty("store.url");
if (StringUtils.isEmpty(baseUrl)) {
log.info("No consistency check performed as no store.url is defined in configuration file.");
return "No consistency check performed as no store.url is defined in configuration file.";
}
baseUrl += "/servlet/consistencyCheck";
HttpPost post = new HttpPost(baseUrl);
post.setEntity(new StringEntity(requestData));
String responseData = HttpUtils4.getTextContent(Common.getHttpClient(), post, 1);
// Parse the response
JsonTypeReader jsonReader = new JsonTypeReader(responseData);
String result = jsonReader.read().toString();
if (!"ok".equals(result))
return result;
} catch (Exception e) {
log.error("", e);
return e.getMessage();
}
synchronized (upgradeDownloaderLock) {
// Ensure that 2 downloads cannot start at the same time.
if (upgradeDownloader == null) {
upgradeDownloader = new UpgradeDownloader(modules, backup, restart, listeners, () -> {
synchronized (upgradeDownloaderLock) {
upgradeDownloader = null;
}
});
// Clear out common info
resetUpgradeStatus();
Common.backgroundProcessing.execute(upgradeDownloader);
} else
return Common.translate("modules.versionCheck.occupied");
}
return null;
}
use of com.infiniteautomation.mango.util.exception.FeatureDisabledException in project ma-core-public by infiniteautomation.
the class ModulesService method upgradesAvailable.
/**
* How many upgrades are available
*/
public int upgradesAvailable() throws Exception {
permissionService.ensureAdminRole(Common.getUser());
if (env.getProperty("store.disableUpgrades", Boolean.class, false)) {
throw new FeatureDisabledException(new TranslatableMessage("modules.error.upgradesDisabled"));
}
JsonValue jsonResponse = getAvailableUpgrades();
if (jsonResponse == null)
// Empty store.url
return 0;
if (jsonResponse instanceof JsonString)
throw new Exception("Mango Store Response Error: " + jsonResponse.toString());
JsonObject root = jsonResponse.toJsonObject();
int size = root.getJsonArray("upgrades").size();
if (size > 0) {
// Notify the listeners
JsonValue jsonUpgrades = root.get("upgrades");
JsonArray jsonUpgradesArray = jsonUpgrades.toJsonArray();
for (JsonValue v : jsonUpgradesArray) {
for (ModuleNotificationListener l : listeners) l.moduleUpgradeAvailable(v.getJsonValue("name").toString(), v.getJsonValue("version").toString());
}
JsonValue jsonInstalls = root.get("newInstalls");
JsonArray jsonInstallsArray = jsonInstalls.toJsonArray();
for (JsonValue v : jsonInstallsArray) {
for (ModuleNotificationListener l : listeners) l.newModuleAvailable(v.getJsonValue("name").toString(), v.getJsonValue("version").toString());
}
}
return size;
}
use of com.infiniteautomation.mango.util.exception.FeatureDisabledException in project ma-core-public by infiniteautomation.
the class UpgradeCheck method run.
@Override
public void run(long fireTime) {
Integer available = null;
try {
// If upgrade checks are not enabled we won't contact the store at all
if (SystemSettingsDao.getInstance().getBooleanValue(SystemSettingsDao.UPGRADE_CHECKS_ENABLED)) {
try {
available = Common.getBean(ModulesService.class).upgradesAvailable();
} catch (FeatureDisabledException e) {
// ignore
}
}
if (available != null && available > 0) {
TranslatableMessage m = new TranslatableMessage("modules.event.upgrades");
SystemEventType.raiseEvent(et, Common.timer.currentTimeMillis(), true, m);
} else
Common.eventManager.returnToNormal(et, Common.timer.currentTimeMillis(), ReturnCause.RETURN_TO_NORMAL);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
// To ensure that the monitor is set, even if it is with a null value.
this.availableUpgrades.setValue(available);
}
}
use of com.infiniteautomation.mango.util.exception.FeatureDisabledException in project ma-core-public by infiniteautomation.
the class ModulesService method getAvailableUpgrades.
/**
* Get the information for available upgrades
*/
public JsonValue getAvailableUpgrades() throws JsonException, IOException, HttpException {
permissionService.ensureAdminRole(Common.getUser());
if (env.getProperty("store.disableUpgrades", Boolean.class, false)) {
throw new FeatureDisabledException(new TranslatableMessage("modules.error.upgradesDisabled"));
}
// Create the request
List<Module> modules = ModuleRegistry.getModules();
Module.sortByName(modules);
Map<String, Object> json = new HashMap<>();
json.put("guid", Providers.get(ICoreLicense.class).getGuid());
json.put("description", SystemSettingsDao.getInstance().getValue(SystemSettingsDao.INSTANCE_DESCRIPTION));
json.put("distributor", env.getProperty("distributor"));
json.put("upgradeVersionState", SystemSettingsDao.getInstance().getIntValue(SystemSettingsDao.UPGRADE_VERSION_STATE));
Properties props = new Properties();
Path propFile = Common.MA_HOME_PATH.resolve("release.properties");
int versionState = UpgradeVersionState.DEVELOPMENT;
if (Files.isRegularFile(propFile)) {
try (InputStream in = Files.newInputStream(propFile)) {
props.load(in);
}
String currentVersionState = props.getProperty("versionState");
try {
if (currentVersionState != null)
versionState = Integer.parseInt(currentVersionState);
} catch (NumberFormatException e) {
}
}
json.put("currentVersionState", versionState);
Map<String, String> jsonModules = new HashMap<>();
json.put("modules", jsonModules);
Version coreVersion = Common.getVersion();
jsonModules.put(ModuleRegistry.CORE_MODULE_NAME, coreVersion.toString());
for (Module module : modules) if (!module.isMarkedForDeletion())
jsonModules.put(module.getName(), module.getVersion().toString());
// Add in the unloaded modules so we don't re-download them if we don't have to
for (Module module : ModuleRegistry.getUnloadedModules()) if (!module.isMarkedForDeletion())
jsonModules.put(module.getName(), module.getVersion().toString());
// Optionally Add Usage Data Check if first login for admin has happened to ensure they have
if (SystemSettingsDao.getInstance().getBooleanValue(SystemSettingsDao.USAGE_TRACKING_ENABLED)) {
// Collect statistics
List<DataSourceUsageStatistics> dataSourceCounts = DataSourceDao.getInstance().getUsage();
json.put("dataSourcesUsage", dataSourceCounts);
List<DataPointUsageStatistics> dataPointCounts = DataPointDao.getInstance().getUsage();
json.put("dataPointsUsage", dataPointCounts);
List<PublisherUsageStatistics> publisherUsage = PublisherDao.getInstance().getUsage();
json.put("publishersUsage", publisherUsage);
List<PublisherPointsUsageStatistics> publisherPointsUsageStatistics = publishedPointDao.getUsage();
json.put("publisherPointsUsage", publisherPointsUsageStatistics);
for (ValueMonitor<?> m : Common.MONITORED_VALUES.getMonitors()) {
if (m.isUploadToStore()) {
if (m.getValue() != null) {
json.put(m.getId(), m.getValue());
}
}
}
}
StringWriter stringWriter = new StringWriter();
new JsonWriter(Common.JSON_CONTEXT, stringWriter).writeObject(json);
String requestData = stringWriter.toString();
// Send the request
String baseUrl = env.getProperty("store.url");
if (StringUtils.isEmpty(baseUrl)) {
log.info("No version check performed as no store.url is defined in configuration file.");
return null;
}
baseUrl += "/servlet/versionCheck";
HttpPost post = new HttpPost(baseUrl);
post.setEntity(new StringEntity(requestData));
String responseData = HttpUtils4.getTextContent(Common.getHttpClient(), post, 1);
// Parse the response
JsonTypeReader jsonReader = new JsonTypeReader(responseData);
return jsonReader.read();
}
Aggregations