From dd5a705836d22a9d34d8d56b672d77115e817557 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 14 Feb 2018 13:29:42 -0800 Subject: [PATCH] move rolling interval backup rules to automatic content archives --- .../resources/describe-settings.json | 130 +++++++++--------- .../resources/web/content/js/content.js | 30 +++- .../resources/web/js/base-settings.js | 4 + .../src/DomainContentBackupManager.cpp | 6 +- domain-server/src/DomainServer.cpp | 9 +- .../src/DomainServerSettingsManager.cpp | 17 +++ .../src/DomainServerSettingsManager.h | 1 + 7 files changed, 123 insertions(+), 74 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 93d703c8b3..427dc62520 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 2.1, + "version": 2.2, "settings": [ { "name": "metaverse", @@ -1321,73 +1321,6 @@ "default": "30000", "advanced": true }, - { - "name": "backups", - "type": "table", - "label": "Backup Rules", - "help": "In this table you can define a set of rules for how frequently to backup copies of your entites content file.", - "numbered": false, - "can_add_new_rows": true, - "default": [ - { - "Name": "Half Hourly Rolling", - "backupInterval": 1800, - "format": ".backup.halfhourly.%N", - "maxBackupVersions": 5 - }, - { - "Name": "Daily Rolling", - "backupInterval": 86400, - "format": ".backup.daily.%N", - "maxBackupVersions": 7 - }, - { - "Name": "Weekly Rolling", - "backupInterval": 604800, - "format": ".backup.weekly.%N", - "maxBackupVersions": 4 - }, - { - "Name": "Thirty Day Rolling", - "backupInterval": 2592000, - "format": ".backup.thirtyday.%N", - "maxBackupVersions": 12 - } - ], - "columns": [ - { - "name": "Name", - "label": "Name", - "can_set": true, - "placeholder": "Example", - "default": "Example" - }, - { - "name": "format", - "label": "Rule Format", - "can_set": true, - "help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z", - "placeholder": ".backup.example.%N", - "default": ".backup.example.%N" - }, - { - "name": "backupInterval", - "label": "Backup Interval in Seconds", - "help": "Interval between backup checks in seconds.", - "placeholder": 1800, - "default": 1800, - "can_set": true - }, - { - "name": "maxBackupVersions", - "label": "Max Rolled Backup Versions", - "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", - "placeholder": 5, - "default": 5, - "can_set": true - } - ] - }, { "name": "NoPersist", "type": "checkbox", @@ -1649,6 +1582,67 @@ } ] }, + { + "name": "automatic_content_archives", + "label": "Automatic Content Archives", + "settings": [ + { + "name": "backup_rules", + "type": "table", + "label": "Rolling Backup Rules", + "help": "Define how frequently to create automatic content archives", + "numbered": false, + "can_add_new_rows": true, + "default": [ + { + "Name": "Half Hourly Rolling", + "backupInterval": 1800, + "maxBackupVersions": 5 + }, + { + "Name": "Daily Rolling", + "backupInterval": 86400, + "maxBackupVersions": 7 + }, + { + "Name": "Weekly Rolling", + "backupInterval": 604800, + "maxBackupVersions": 4 + }, + { + "Name": "Thirty Day Rolling", + "backupInterval": 2592000, + "maxBackupVersions": 12 + } + ], + "columns": [ + { + "name": "Name", + "label": "Name", + "can_set": true, + "placeholder": "Example", + "default": "Example" + }, + { + "name": "backupInterval", + "label": "Backup Interval in Seconds", + "help": "Interval between backup checks in seconds.", + "placeholder": 1800, + "default": 1800, + "can_set": true + }, + { + "name": "maxBackupVersions", + "label": "Max Rolled Backup Versions", + "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", + "placeholder": 5, + "default": 5, + "can_set": true + } + ] + } + ] + }, { "name": "wizard", "label": "Setup Wizard", diff --git a/domain-server/resources/web/content/js/content.js b/domain-server/resources/web/content/js/content.js index e2b653995f..0fd5f37a94 100644 --- a/domain-server/resources/web/content/js/content.js +++ b/domain-server/resources/web/content/js/content.js @@ -23,15 +23,17 @@ $(document).ready(function(){ var AUTOMATIC_ARCHIVES_TBODY_ID = 'automatic-archives-tbody'; var MANUAL_ARCHIVES_TABLE_ID = 'manual-archives-table'; var MANUAL_ARCHIVES_TBODY_ID = 'manual-archives-tbody'; + var AUTO_ARCHIVES_SETTINGS_LINK_ID = 'auto-archives-settings-link'; + var automaticBackups = []; var manualBackups = []; function setupContentArchives() { - // construct the HTML needed for the content archives panel var html = "
"; html += ""; - html += "Your domain server makes regular archives of the content in your domain. In the list below, you can see and download all of your domain content and settings backups." + html += "Your domain server makes regular archives of the content in your domain. In the list below, you can see and download all of your domain content and settings backups. " + html += "Click here to manage automatic content archive intervals."; html += "
"; html += ""; @@ -120,6 +122,30 @@ $(document).ready(function(){ }); } + // handle click on automatic content archive settings link + $('body').on('click', '#' + AUTO_ARCHIVES_SETTINGS_LINK_ID, function(e) { + if (Settings.pendingChanges > 0) { + // don't follow the link right away, make sure the user knows they are about to leave + // the page and lose changes + e.preventDefault(); + + var settingsLink = $(this).attr('href'); + + swal({ + title: "Are you sure?", + text: "You have pending changes to content settings that have not been saved. They will be lost if you leave the page to manage automatic content archive intervals.", + type: "warning", + showCancelButton: true, + confirmButtonText: "Leave and Lose Pending Changes", + closeOnConfirm: true + }, + function () { + // user wants to drop their changes, switch pages + window.location = settingsLink; + }); + } + }); + // handle click on manual archive creation button $('body').on('click', '#' + GENERATE_ARCHIVE_BUTTON_ID, function(e) { e.preventDefault(); diff --git a/domain-server/resources/web/js/base-settings.js b/domain-server/resources/web/js/base-settings.js index 961a7df3b2..3476792222 100644 --- a/domain-server/resources/web/js/base-settings.js +++ b/domain-server/resources/web/js/base-settings.js @@ -126,6 +126,8 @@ function reloadSettings(callback) { $('[data-toggle="tooltip"]').tooltip(); + Settings.pendingChanges = 0; + // call the callback now that settings are loaded callback(true); }).fail(function() { @@ -805,6 +807,8 @@ function badgeForDifferences(changedElement) { } }); + Settings.pendingChanges = totalChanges; + if (totalChanges == 0) { totalChanges = "" } diff --git a/domain-server/src/DomainContentBackupManager.cpp b/domain-server/src/DomainContentBackupManager.cpp index a711d2112d..345faffec4 100644 --- a/domain-server/src/DomainContentBackupManager.cpp +++ b/domain-server/src/DomainContentBackupManager.cpp @@ -63,9 +63,9 @@ DomainContentBackupManager::DomainContentBackupManager(const QString& backupDire } void DomainContentBackupManager::parseSettings(const QJsonObject& settings) { - qDebug() << settings << settings["backups"] << settings["backups"].isArray(); - if (settings["backups"].isArray()) { - const QJsonArray& backupRules = settings["backups"].toArray(); + static const QString BACKUP_RULES_KEY = "backup_rules"; + if (settings[BACKUP_RULES_KEY].isArray()) { + const QJsonArray& backupRules = settings[BACKUP_RULES_KEY].toArray(); qCDebug(domain_server) << "BACKUP RULES:"; for (const QJsonValue& value : backupRules) { diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 157eaa483f..8247e12de5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -296,8 +296,15 @@ DomainServer::DomainServer(int argc, char* argv[]) : qCDebug(domain_server) << "Created entities data directory"; } maybeHandleReplacementEntityFile(); + + auto contentArchivesGroup = _settingsManager.valueOrDefaultValueForKeyPath(AUTOMATIC_CONTENT_ARCHIVES_GROUP); + auto archivesIntervalObject = QJsonObject(); - _contentManager.reset(new DomainContentBackupManager(getContentBackupDir(), _settingsManager.settingsResponseObjectForType("6")["entity_server_settings"].toObject())); + if (contentArchivesGroup.canConvert()) { + archivesIntervalObject = QJsonObject::fromVariantMap(contentArchivesGroup.toMap()); + } + + _contentManager.reset(new DomainContentBackupManager(getContentBackupDir(), archivesIntervalObject)); connect(_contentManager.get(), &DomainContentBackupManager::started, _contentManager.get(), [this](){ _contentManager->addBackupHandler(BackupHandlerPointer(new EntitiesBackupHandler(getEntitiesFilePath(), getEntitiesReplacementFilePath()))); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 85d6a046b5..a50cde0807 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -393,6 +393,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList _standardAgentPermissions[NodePermissions::standardNameLocalhost]->set(NodePermissions::Permission::canRezTemporaryCertifiedEntities); packPermissions(); } + if (oldVersion < 2.0) { const QString WIZARD_COMPLETED_ONCE = "wizard.completed_once"; @@ -400,6 +401,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList *wizardCompletedOnce = QVariant(true); } + if (oldVersion < 2.1) { // convert old avatar scale settings into avatar height. @@ -421,6 +423,21 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList } } + if (oldVersion < 2.2) { + // migrate entity server rolling backup intervals to new location for automatic content archive intervals + + const QString ENTITY_SERVER_BACKUPS_KEYPATH = "entity_server_settings.backups"; + const QString AUTO_CONTENT_ARCHIVES_RULES_KEYPATH = "automatic_content_archives.backup_rules"; + + QVariant* previousBackupsVariant = _configMap.valueForKeyPath(ENTITY_SERVER_BACKUPS_KEYPATH); + + if (previousBackupsVariant) { + auto migratedBackupsVariant = _configMap.valueForKeyPath(AUTO_CONTENT_ARCHIVES_RULES_KEYPATH, true); + *migratedBackupsVariant = *previousBackupsVariant; + } + } + + // write the current description version to our settings *versionVariant = _descriptionVersion; diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index abc70751a8..897a15485f 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -37,6 +37,7 @@ const QString MAC_PERMISSIONS_KEYPATH = "security.mac_permissions"; const QString MACHINE_FINGERPRINT_PERMISSIONS_KEYPATH = "security.machine_fingerprint_permissions"; const QString GROUP_PERMISSIONS_KEYPATH = "security.group_permissions"; const QString GROUP_FORBIDDENS_KEYPATH = "security.group_forbiddens"; +const QString AUTOMATIC_CONTENT_ARCHIVES_GROUP = "automatic_content_archives"; using GroupByUUIDKey = QPair; // groupID, rankID