backups: split config and policy
keeping them together makes the test/validation quite complicated. for example, when policy is changed, we test the storage backends part of #817
This commit is contained in:
@@ -108,40 +108,40 @@
|
||||
</div>
|
||||
|
||||
<!-- modal backup config -->
|
||||
<div class="modal fade" id="configureScheduleAndRetentionModal" tabindex="-1" role="dialog">
|
||||
<div class="modal fade" id="backupPolicyModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.configureBackupSchedule.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="configureScheduleAndRetentionForm" role="form" novalidate ng-submit="configureScheduleAndRetention.submit()" autocomplete="off">
|
||||
<p class="has-error text-center" ng-show="configureScheduleAndRetention.error">{{ configureScheduleAndRetention.error.generic }}</p>
|
||||
<form name="backupPolicyForm" role="form" novalidate ng-submit="backupPolicy.submit()" autocomplete="off">
|
||||
<p class="has-error text-center" ng-show="backupPolicy.error">{{ backupPolicy.error.generic }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="backupSchedule">{{ 'backups.configureBackupSchedule.schedule' | tr }}</label>
|
||||
<p ng-bind-html="'backups.configureBackupSchedule.scheduleDescription' | tr"></p>
|
||||
|
||||
<div class="row" style="margin-left: 20px;">
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !configureScheduleAndRetention.days.length }">
|
||||
{{ 'backups.configureBackupSchedule.days' | tr }}: <multiselect id="backupSchedule" class="input-sm stretch" ng-model="configureScheduleAndRetention.days" options="a.name for a in cronDays" data-multiple="true" ng-required></multiselect>
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !backupPolicy.days.length }">
|
||||
{{ 'backups.configureBackupSchedule.days' | tr }}: <multiselect id="backupSchedule" class="input-sm stretch" ng-model="backupPolicy.days" options="a.name for a in cronDays" data-multiple="true" ng-required></multiselect>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !configureScheduleAndRetention.hours.length }">
|
||||
{{ 'backups.configureBackupSchedule.hours' | tr }}: <multiselect class="input-sm stretch" ng-model="configureScheduleAndRetention.hours" options="a.name for a in cronHours" data-multiple="true"></multiselect>
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !backupPolicy.hours.length }">
|
||||
{{ 'backups.configureBackupSchedule.hours' | tr }}: <multiselect class="input-sm stretch" ng-model="backupPolicy.hours" options="a.name for a in cronHours" data-multiple="true"></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="backupRetention">{{ 'backups.configureBackupSchedule.retentionPolicy' | tr }}</label>
|
||||
<select class="form-control" id="backupRetention" ng-model="configureScheduleAndRetention.retentionPolicy" ng-options="a.value as a.name for a in retentionPolicies"></select>
|
||||
<select class="form-control" id="backupRetention" ng-model="backupPolicy.retention" ng-options="a.value as a.name for a in backupRetentions"></select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer ">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="configureScheduleAndRetention.submit()" ng-disabled="!configureScheduleAndRetention.valid() || configureScheduleAndRetention.busy"><i class="fa fa-circle-notch fa-spin" ng-show="configureScheduleAndRetention.busy"></i><span> {{ 'main.dialog.save' | tr }}</span></button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="backupPolicy.submit()" ng-disabled="!backupPolicy.valid() || backupPolicy.busy"><i class="fa fa-circle-notch fa-spin" ng-show="backupPolicy.busy"></i><span> {{ 'main.dialog.save' | tr }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -533,7 +533,7 @@
|
||||
<span class="text-muted">{{ 'backups.schedule.schedule' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<span>{{ prettyBackupSchedule(backupConfig.schedulePattern) }}</span>
|
||||
<span>{{ prettyBackupSchedule(backupPolicy.currentPolicy.schedule) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -541,14 +541,14 @@
|
||||
<span class="text-muted">{{ 'backups.schedule.retentionPolicy' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<span>{{ prettyBackupRetentionPolicy(backupConfig.retentionPolicy) }}</span>
|
||||
<span>{{ prettyBackupRetention(backupPolicy.currentPolicy.retention) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button class="btn btn-default" ng-click="cleanupBackups.ask()" ng-disabled="cleanupBackups.busy" style="margin-right: 5px"><i class="fa fa-circle-notch fa-spin" ng-show="cleanupBackups.busy"></i> {{ 'backups.listing.cleanupBackups' | tr }}</button>
|
||||
<button class="btn btn-outline btn-primary pull-right" ng-show="user.isAtLeastOwner" ng-click="configureScheduleAndRetention.show()">{{ 'backups.schedule.configure' | tr }}</button>
|
||||
<button class="btn btn-outline btn-primary pull-right" ng-show="user.isAtLeastOwner" ng-click="backupPolicy.show()">{{ 'backups.schedule.configure' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
{ name: 'No-op (Only for testing)', value: 'noop' }
|
||||
]);
|
||||
|
||||
$scope.retentionPolicies = [
|
||||
$scope.backupRetentions = [
|
||||
{ name: '2 days', value: { keepWithinSecs: 2 * 24 * 60 * 60 }},
|
||||
{ name: '1 week', value: { keepWithinSecs: 7 * 24 * 60 * 60 }}, // default
|
||||
{ name: '1 month', value: { keepWithinSecs: 30 * 24 * 60 * 60 }},
|
||||
@@ -85,8 +85,8 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
return prettyDay + ' at ' + prettyHour;
|
||||
};
|
||||
|
||||
$scope.prettyBackupRetentionPolicy = function (retentionPolicy) {
|
||||
var tmp = $scope.retentionPolicies.find(function (p) { return angular.equals(p.value, retentionPolicy); });
|
||||
$scope.prettyBackupRetention = function (retention) {
|
||||
var tmp = $scope.backupRetentions.find(function (p) { return angular.equals(p.value, retention); });
|
||||
return tmp ? tmp.name : '';
|
||||
};
|
||||
|
||||
@@ -347,68 +347,76 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
}
|
||||
};
|
||||
|
||||
$scope.configureScheduleAndRetention = {
|
||||
$scope.backupPolicy = {
|
||||
busy: false,
|
||||
error: {},
|
||||
|
||||
retentionPolicy: $scope.retentionPolicies[0],
|
||||
currentPolicy: null,
|
||||
|
||||
retention: null,
|
||||
days: [],
|
||||
hours: [],
|
||||
|
||||
init: function () {
|
||||
Client.getBackupPolicy(function (error, policy) {
|
||||
if (error) Client.error(error);
|
||||
$scope.backupPolicy.currentPolicy = policy;
|
||||
});
|
||||
},
|
||||
|
||||
show: function () {
|
||||
$scope.configureScheduleAndRetention.error = {};
|
||||
$scope.configureScheduleAndRetention.busy = false;
|
||||
$scope.backupPolicy.error = {};
|
||||
$scope.backupPolicy.busy = false;
|
||||
|
||||
var selectedPolicy = $scope.retentionPolicies.find(function (x) { return angular.equals(x.value, $scope.backupConfig.retentionPolicy); });
|
||||
if (!selectedPolicy) selectedPolicy = $scope.retentionPolicies[0];
|
||||
var selectedRetention = $scope.backupRetentions.find(function (x) { return angular.equals(x.value, $scope.backupPolicy.currentPolicy.retention); });
|
||||
if (!selectedRetention) selectedRetention = $scope.backupRetentions[0];
|
||||
|
||||
$scope.configureScheduleAndRetention.retentionPolicy = selectedPolicy.value;
|
||||
$scope.backupPolicy.retention = selectedRetention.value;
|
||||
|
||||
var tmp = $scope.backupConfig.schedulePattern.split(' ');
|
||||
var tmp = $scope.backupPolicy.currentPolicy.schedule.split(' ');
|
||||
var hours = tmp[2].split(','), days = tmp[5].split(',');
|
||||
if (days[0] === '*') {
|
||||
$scope.configureScheduleAndRetention.days = angular.copy($scope.cronDays, []);
|
||||
$scope.backupPolicy.days = angular.copy($scope.cronDays, []);
|
||||
} else {
|
||||
$scope.configureScheduleAndRetention.days = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)]; });
|
||||
$scope.backupPolicy.days = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)]; });
|
||||
}
|
||||
$scope.configureScheduleAndRetention.hours = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)]; });
|
||||
$scope.backupPolicy.hours = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)]; });
|
||||
|
||||
$('#configureScheduleAndRetentionModal').modal('show');
|
||||
$('#backupPolicyModal').modal('show');
|
||||
},
|
||||
|
||||
valid: function () {
|
||||
return $scope.configureScheduleAndRetention.days.length && $scope.configureScheduleAndRetention.hours.length;
|
||||
return $scope.backupPolicy.days.length && $scope.backupPolicy.hours.length;
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
if (!$scope.configureScheduleAndRetention.days.length) return;
|
||||
if (!$scope.configureScheduleAndRetention.hours.length) return;
|
||||
if (!$scope.backupPolicy.days.length) return;
|
||||
if (!$scope.backupPolicy.hours.length) return;
|
||||
|
||||
$scope.configureScheduleAndRetention.error = {};
|
||||
$scope.configureScheduleAndRetention.busy = true;
|
||||
|
||||
// start with the full backupConfig since the api requires all fields
|
||||
var backupConfig = $scope.backupConfig;
|
||||
backupConfig.retentionPolicy = $scope.configureScheduleAndRetention.retentionPolicy;
|
||||
$scope.backupPolicy.error = {};
|
||||
$scope.backupPolicy.busy = true;
|
||||
|
||||
var daysPattern;
|
||||
if ($scope.configureScheduleAndRetention.days.length === 7) daysPattern = '*';
|
||||
else daysPattern = $scope.configureScheduleAndRetention.days.map(function (d) { return d.value; });
|
||||
if ($scope.backupPolicy.days.length === 7) daysPattern = '*';
|
||||
else daysPattern = $scope.backupPolicy.days.map(function (d) { return d.value; });
|
||||
|
||||
var hoursPattern;
|
||||
if ($scope.configureScheduleAndRetention.hours.length === 24) hoursPattern = '*';
|
||||
else hoursPattern = $scope.configureScheduleAndRetention.hours.map(function (d) { return d.value; });
|
||||
if ($scope.backupPolicy.hours.length === 24) hoursPattern = '*';
|
||||
else hoursPattern = $scope.backupPolicy.hours.map(function (d) { return d.value; });
|
||||
|
||||
backupConfig.schedulePattern ='00 00 ' + hoursPattern + ' * * ' + daysPattern;
|
||||
var policy = {
|
||||
retention: $scope.backupPolicy.retention,
|
||||
schedule: '00 00 ' + hoursPattern + ' * * ' + daysPattern
|
||||
};
|
||||
|
||||
Client.setBackupConfig(backupConfig, function (error) {
|
||||
$scope.configureScheduleAndRetention.busy = false;
|
||||
Client.setBackupPolicy(policy, function (error) {
|
||||
$scope.backupPolicy.busy = false;
|
||||
|
||||
if (error) {
|
||||
if (error.statusCode === 424) {
|
||||
$scope.configureScheduleAndRetention.error.generic = error.message;
|
||||
$scope.backupPolicy.error.generic = error.message;
|
||||
} else if (error.statusCode === 400) {
|
||||
$scope.configureScheduleAndRetention.error.generic = error.message;
|
||||
$scope.backupPolicy.error.generic = error.message;
|
||||
} else {
|
||||
console.error('Unable to change schedule or retention.', error);
|
||||
}
|
||||
@@ -416,9 +424,9 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
return;
|
||||
}
|
||||
|
||||
$('#configureScheduleAndRetentionModal').modal('hide');
|
||||
$('#backupPolicyModal').modal('hide');
|
||||
|
||||
getBackupConfig();
|
||||
$scope.backupPolicy.init();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -813,6 +821,7 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
// show backup status
|
||||
$scope.createBackup.init();
|
||||
$scope.cleanupBackups.init();
|
||||
$scope.backupPolicy.init();
|
||||
|
||||
getBackupTasks();
|
||||
getCleanupTasks();
|
||||
|
||||
Reference in New Issue
Block a user