From: Fabian Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH manager 14/14] backup view: add prune window
Date: Wed, 2 Sep 2020 13:03:37 +0200 [thread overview]
Message-ID: <20200902110337.25004-15-f.ebner@proxmox.com> (raw)
In-Reply-To: <20200902110337.25004-1-f.ebner@proxmox.com>
adapted from PBS. Main differences are:
1. keep-last defaults to 1 to avoid error on load
2. keep options are loaded from the storage configuration if there are any
3. API has GET/DELETE distinction instead of 'dry-run'
4. API expects a single property string for the prune options
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/storage/BackupView.js | 25 ++++
www/manager6/window/Prune.js | 230 +++++++++++++++++++++++++++++
3 files changed, 256 insertions(+)
create mode 100644 www/manager6/window/Prune.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 4b9dcf58..b34bb41d 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -249,6 +249,7 @@ JSSRC= \
window/LoginWindow.js \
window/Migrate.js \
window/NotesEdit.js \
+ window/Prune.js \
window/Restore.js \
window/SafeDestroy.js \
window/Settings.js \
diff --git a/www/manager6/storage/BackupView.js b/www/manager6/storage/BackupView.js
index 8c1e2ed6..6bf26167 100644
--- a/www/manager6/storage/BackupView.js
+++ b/www/manager6/storage/BackupView.js
@@ -64,6 +64,31 @@ Ext.define('PVE.storage.BackupView', {
win.show();
}
},
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Prune'),
+ selModel: sm,
+ disabled: true,
+ handler: function(b, e, rec) {
+ var backup_type;
+ if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
+ backup_type = 'qemu';
+ } else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
+ backup_type = 'lxc';
+ } else {
+ return;
+ }
+
+ var win = Ext.create('PVE.window.Prune', {
+ nodename: nodename,
+ storage: storage,
+ backup_id: rec.data.vmid,
+ backup_type: backup_type,
+ });
+ win.show();
+ win.on('destroy', reload);
+ },
+ },
];
me.callParent();
diff --git a/www/manager6/window/Prune.js b/www/manager6/window/Prune.js
new file mode 100644
index 00000000..4c90f87a
--- /dev/null
+++ b/www/manager6/window/Prune.js
@@ -0,0 +1,230 @@
+Ext.define('pve-prune-list', {
+ extend: 'Ext.data.Model',
+ fields: [
+ 'backup-type',
+ 'backup-id',
+ {
+ name: 'ctime',
+ type: 'date',
+ dateFormat: 'timestamp',
+ },
+ ],
+});
+
+Ext.define('PVE.PruneInputPanel', {
+ extend: 'Proxmox.panel.InputPanel',
+ alias: 'widget.pvePruneInputPanel',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ onGetValues: function(values) {
+ var me = this;
+
+ // the API expects a single prune-backups property string
+ let prune_opts = PVE.Parser.printPropertyString(values);
+ values = {};
+ values["prune-backups"] = prune_opts;
+ values.type = me.backup_type;
+ values.vmid = me.backup_id;
+
+ return values;
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ init: function(view) {
+ if (!view.url) {
+ throw "no url specified";
+ }
+ if (!view.backup_type) {
+ throw "no backup_type specified";
+ }
+ if (!view.backup_id) {
+ throw "no backup_id specified";
+ }
+
+ this.reload(); // initial load
+ },
+
+ reload: function() {
+ var view = this.getView();
+
+ let params = view.getValues();
+
+ Proxmox.Utils.API2Request({
+ url: view.url,
+ method: "GET",
+ params: params,
+ callback: function() {
+ return; // for easy breakpoint setting
+ },
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ success: function(response, options) {
+ var data = response.result.data;
+ view.prune_store.setData(data);
+ },
+ });
+ },
+
+ control: {
+ field: { change: 'reload' },
+ },
+ },
+
+ column1: [
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-last',
+ allowBlank: true,
+ fieldLabel: gettext('keep-last'),
+ value: 1,
+ minValue: 1,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-hourly',
+ allowBlank: true,
+ fieldLabel: gettext('keep-hourly'),
+ minValue: 1,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-daily',
+ allowBlank: true,
+ fieldLabel: gettext('keep-daily'),
+ minValue: 1,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-weekly',
+ allowBlank: true,
+ fieldLabel: gettext('keep-weekly'),
+ minValue: 1,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-monthly',
+ allowBlank: true,
+ fieldLabel: gettext('keep-monthly'),
+ minValue: 1,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ name: 'keep-yearly',
+ allowBlank: true,
+ fieldLabel: gettext('keep-yearly'),
+ minValue: 1,
+ },
+ ],
+
+ initComponent: function() {
+ var me = this;
+
+ me.prune_store = Ext.create('Ext.data.Store', {
+ model: 'pve-prune-list',
+ sorters: { property: 'ctime', direction: 'DESC' },
+ });
+
+ Proxmox.Utils.API2Request({
+ url: "/storage",
+ method: 'GET',
+ success: function(response, opts) {
+ let scfg = response.result.data.find(x => x.storage === me.storage);
+ if (!scfg || !scfg["prune-backups"]) {
+ return;
+ }
+ let prune_opts = PVE.Parser.parsePropertyString(scfg["prune-backups"]);
+ me.setValues(prune_opts);
+ },
+ });
+
+ me.column2 = [
+ {
+ xtype: 'grid',
+ height: 200,
+ store: me.prune_store,
+ columns: [
+ {
+ header: gettext('Backup Time'),
+ sortable: true,
+ dataIndex: 'ctime',
+ renderer: function(value, metaData, record) {
+ let text = Ext.Date.format(value, 'Y-m-d H:i:s');
+ if (record.data.mark === 'remove') {
+ return '<div style="text-decoration: line-through;">'+ text +'</div>';
+ } else {
+ return text;
+ }
+ },
+ flex: 1,
+ },
+ {
+ text: "keep",
+ dataIndex: 'mark',
+ },
+ ],
+ },
+ ];
+
+ me.callParent();
+ },
+});
+
+Ext.define('PVE.window.Prune', {
+ extend: 'Proxmox.window.Edit',
+
+ method: 'DELETE',
+ submitText: gettext("Prune"),
+
+ isCreate: true,
+
+ initComponent: function() {
+ var me = this;
+
+ if (!me.nodename) {
+ throw "no nodename specified";
+ }
+ if (!me.storage) {
+ throw "no storage specified";
+ }
+ if (!me.backup_type) {
+ throw "no backup_type specified";
+ }
+ if (!me.backup_id) {
+ throw "no backup_id specified";
+ }
+
+ let backup_type_str;
+ if (me.backup_type === 'qemu') {
+ backup_type_str = 'VM';
+ } else if (me.backup_type === 'lxc') {
+ backup_type_str = 'CT';
+ } else {
+ throw "unknown backup type";
+ }
+ let backup_group_str = backup_type_str + '/' + me.backup_id;
+ let title = Ext.String.format(
+ gettext("Prune Backups for '{0}' on Storage '{1}'"),
+ backup_group_str,
+ me.storage,
+ );
+
+ Ext.apply(me, {
+ url: '/api2/extjs/nodes/' + me.nodename + '/storage/' + me.storage + "/prunebackups",
+ title: title,
+ items: [
+ {
+ xtype: 'pvePruneInputPanel',
+ url: '/api2/extjs/nodes/' + me.nodename + '/storage/' + me.storage + "/prunebackups",
+ backup_type: me.backup_type,
+ backup_id: me.backup_id,
+ storage: me.storage,
+ },
+ ],
+ });
+
+ me.callParent();
+ },
+});
--
2.20.1
prev parent reply other threads:[~2020-09-02 11:04 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 02/14] storage panel/browser: use insertNodes function Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 03/14] use separate view for each content type Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 04/14] remove the now unneccessary grouping Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 05/14] content view: allow specifying title bar elements for init Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 06/14] turn nodename, storage, sm into object variables Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 07/14] add upload button conditionally Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 08/14] create and use template view Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 09/14] create and use backup view Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 10/14] get rid of unneccessary enableFns Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 11/14] create ImageView and use it for VM and CT images Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 12/14] simplify reload call Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [RFC manager 13/14] content view: allow specifying which columns to show on init Fabian Ebner
2020-09-02 11:03 ` Fabian Ebner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200902110337.25004-15-f.ebner@proxmox.com \
--to=f.ebner@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.