gui: refactor snapshot window

using an Proxmox.window.Edit, which does many of the things we did
manually, also rewrite is in such way that we can use it for qemu
and lxc

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2020-01-30 16:58:51 +01:00 committed by Thomas Lamprecht
parent a76a8a7d3f
commit 4e0e6b77e9
6 changed files with 140 additions and 423 deletions

View File

@ -127,6 +127,7 @@ JSSRC= \
window/Migrate.js \
window/BulkAction.js \
window/Clone.js \
window/Snapshot.js \
qemu/Monitor.js \
qemu/OSTypeEdit.js \
qemu/OSDefaults.js \
@ -146,7 +147,6 @@ JSSRC= \
qemu/ScsiHwEdit.js \
qemu/QemuBiosEdit.js \
qemu/Options.js \
qemu/Snapshot.js \
qemu/SnapshotTree.js \
qemu/Config.js \
qemu/CreateWizard.js \
@ -168,7 +168,6 @@ JSSRC= \
lxc/Config.js \
lxc/CreateWizard.js \
lxc/SnapshotTree.js \
lxc/Snapshot.js \
lxc/ResourceEdit.js \
lxc/MPResize.js \
lxc/MPEdit.js \

View File

@ -1,206 +0,0 @@
Ext.define('PVE.window.LxcSnapshot', {
extend: 'Ext.window.Window',
resizable: false,
// needed for finding the reference to submitbutton
// because we do not have a controller
referenceHolder: true,
defaultButton: 'submitbutton',
defaultFocus: 'field',
take_snapshot: function(snapname, descr, vmstate) {
var me = this;
var params = { snapname: snapname };
if (descr) {
params.description = descr;
}
Proxmox.Utils.API2Request({
params: params,
url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot",
waitMsgTarget: me,
method: 'POST',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function(response, options) {
var upid = response.result.data;
var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
win.show();
me.close();
}
});
},
update_snapshot: function(snapname, descr) {
var me = this;
Proxmox.Utils.API2Request({
params: { description: descr },
url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
snapname + '/config',
waitMsgTarget: me,
method: 'PUT',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function(response, options) {
me.close();
}
});
},
initComponent : function() {
var me = this;
if (!me.nodename) {
throw "no node name specified";
}
if (!me.vmid) {
throw "no VM ID specified";
}
var summarystore = Ext.create('Ext.data.Store', {
model: 'KeyValue',
sorters: [
{
property : 'key',
direction: 'ASC'
}
]
});
var items = [
{
xtype: me.snapname ? 'displayfield' : 'textfield',
name: 'snapname',
value: me.snapname,
fieldLabel: gettext('Name'),
vtype: 'ConfigId',
allowBlank: false
}
];
if (me.snapname) {
items.push({
xtype: 'displayfield',
name: 'snaptime',
renderer: PVE.Utils.render_timestamp_human_readable,
fieldLabel: gettext('Timestamp')
});
}
items.push({
xtype: 'textareafield',
grow: true,
name: 'description',
fieldLabel: gettext('Description')
});
if (me.snapname) {
items.push({
title: gettext('Settings'),
xtype: 'grid',
height: 200,
store: summarystore,
columns: [
{header: gettext('Key'), width: 150, dataIndex: 'key'},
{header: gettext('Value'), flex: 1, dataIndex: 'value'}
]
});
}
me.formPanel = Ext.create('Ext.form.Panel', {
bodyPadding: 10,
border: false,
fieldDefaults: {
labelWidth: 100,
anchor: '100%'
},
items: items
});
var form = me.formPanel.getForm();
var submitBtn;
if (me.snapname) {
me.title = gettext('Edit') + ': ' + gettext('Snapshot');
submitBtn = Ext.create('Ext.Button', {
text: gettext('Update'),
handler: function() {
if (form.isValid()) {
var values = form.getValues();
me.update_snapshot(me.snapname, values.description);
}
}
});
} else {
me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
submitBtn = Ext.create('Ext.Button', {
text: gettext('Take Snapshot'),
reference: 'submitbutton',
handler: function() {
if (form.isValid()) {
var values = form.getValues();
me.take_snapshot(values.snapname, values.description);
}
}
});
}
Ext.apply(me, {
modal: true,
width: 450,
border: false,
layout: 'fit',
buttons: [ submitBtn ],
items: [ me.formPanel ]
});
if (me.snapname) {
Ext.apply(me, {
width: 620,
height: 420
});
}
me.callParent();
if (!me.snapname) {
return;
}
// else load data
Proxmox.Utils.API2Request({
url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
me.snapname + '/config',
waitMsgTarget: me,
method: 'GET',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
me.close();
},
success: function(response, options) {
var data = response.result.data;
var kvarray = [];
Ext.Object.each(data, function(key, value) {
if (key === 'description' || key === 'snaptime') {
return;
}
kvarray.push({ key: key, value: value });
});
summarystore.suspendEvents();
summarystore.add(kvarray);
summarystore.sort();
summarystore.resumeEvents();
summarystore.fireEvent('refresh', summarystore);
form.findField('snaptime').setValue(data.snaptime);
form.findField('description').setValue(data.description);
}
});
}
});

View File

@ -136,6 +136,7 @@ Ext.define('PVE.lxc.SnapshotTree', {
var rec = sm.getSelection()[0];
if (valid_snapshot(rec)) {
var win = Ext.create('PVE.window.LxcSnapshot', {
type: 'lxc',
snapname: rec.data.name,
nodename: me.nodename,
vmid: me.vmid
@ -238,6 +239,9 @@ Ext.define('PVE.lxc.SnapshotTree', {
disabled: true,
handler: function() {
var win = Ext.create('PVE.window.LxcSnapshot', {
type: 'lxc',
isCreate: true,
submitText: gettext('Take Snapshot'),
nodename: me.nodename,
vmid: me.vmid
});

View File

@ -1,215 +0,0 @@
Ext.define('PVE.window.Snapshot', {
extend: 'Ext.window.Window',
resizable: false,
// needed for finding the reference to submitbutton
// because we do not have a controller
referenceHolder: true,
defaultButton: 'submitbutton',
defaultFocus: 'field',
take_snapshot: function(snapname, descr, vmstate) {
var me = this;
var params = { snapname: snapname, vmstate: vmstate ? 1 : 0 };
if (descr) {
params.description = descr;
}
Proxmox.Utils.API2Request({
params: params,
url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot",
waitMsgTarget: me,
method: 'POST',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function(response, options) {
var upid = response.result.data;
var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
win.show();
me.close();
}
});
},
update_snapshot: function(snapname, descr) {
var me = this;
Proxmox.Utils.API2Request({
params: { description: descr },
url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
snapname + '/config',
waitMsgTarget: me,
method: 'PUT',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function(response, options) {
me.close();
}
});
},
initComponent : function() {
var me = this;
if (!me.nodename) {
throw "no node name specified";
}
if (!me.vmid) {
throw "no VM ID specified";
}
var summarystore = Ext.create('Ext.data.Store', {
model: 'KeyValue',
sorters: [
{
property : 'key',
direction: 'ASC'
}
]
});
var items = [
{
xtype: me.snapname ? 'displayfield' : 'textfield',
name: 'snapname',
value: me.snapname,
fieldLabel: gettext('Name'),
vtype: 'ConfigId',
allowBlank: false
}
];
if (me.snapname) {
items.push({
xtype: 'displayfield',
name: 'snaptime',
renderer: PVE.Utils.render_timestamp_human_readable,
fieldLabel: gettext('Timestamp')
});
} else {
items.push({
xtype: 'proxmoxcheckbox',
name: 'vmstate',
uncheckedValue: 0,
defaultValue: 0,
checked: 1,
fieldLabel: gettext('Include RAM')
});
}
items.push({
xtype: 'textareafield',
grow: true,
name: 'description',
fieldLabel: gettext('Description')
});
if (me.snapname) {
items.push({
title: gettext('Settings'),
xtype: 'grid',
height: 200,
store: summarystore,
columns: [
{header: gettext('Key'), width: 150, dataIndex: 'key'},
{header: gettext('Value'), flex: 1, dataIndex: 'value'}
]
});
}
me.formPanel = Ext.create('Ext.form.Panel', {
bodyPadding: 10,
border: false,
fieldDefaults: {
labelWidth: 100,
anchor: '100%'
},
items: items
});
var form = me.formPanel.getForm();
var submitBtn;
if (me.snapname) {
me.title = gettext('Edit') + ': ' + gettext('Snapshot');
submitBtn = Ext.create('Ext.Button', {
text: gettext('Update'),
handler: function() {
if (form.isValid()) {
var values = form.getValues();
me.update_snapshot(me.snapname, values.description);
}
}
});
} else {
me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
submitBtn = Ext.create('Ext.Button', {
text: gettext('Take Snapshot'),
reference: 'submitbutton',
handler: function() {
if (form.isValid()) {
var values = form.getValues();
me.take_snapshot(values.snapname, values.description, values.vmstate);
}
}
});
}
Ext.apply(me, {
modal: true,
width: 450,
border: false,
layout: 'fit',
buttons: [ submitBtn ],
items: [ me.formPanel ]
});
if (me.snapname) {
Ext.apply(me, {
width: 620,
height: 420
});
}
me.callParent();
if (!me.snapname) {
return;
}
// else load data
Proxmox.Utils.API2Request({
url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
me.snapname + '/config',
waitMsgTarget: me,
method: 'GET',
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
me.close();
},
success: function(response, options) {
var data = response.result.data;
var kvarray = [];
Ext.Object.each(data, function(key, value) {
if (key === 'description' || key === 'snaptime') {
return;
}
kvarray.push({ key: key, value: value });
});
summarystore.suspendEvents();
summarystore.add(kvarray);
summarystore.sort();
summarystore.resumeEvents();
summarystore.fireEvent('refresh', summarystore);
form.findField('snaptime').setValue(data.snaptime);
form.findField('description').setValue(data.description);
}
});
}
});

View File

@ -134,6 +134,7 @@ Ext.define('PVE.qemu.SnapshotTree', {
var rec = sm.getSelection()[0];
if (valid_snapshot(rec)) {
var win = Ext.create('PVE.window.Snapshot', {
type: 'qemu',
snapname: rec.data.name,
nodename: me.nodename,
vmid: me.vmid
@ -228,6 +229,9 @@ Ext.define('PVE.qemu.SnapshotTree', {
disabled: true,
handler: function() {
var win = Ext.create('PVE.window.Snapshot', {
isCreate: true,
type: 'qemu',
submitText: gettext('Take Snapshot'),
nodename: me.nodename,
vmid: me.vmid
});

View File

@ -0,0 +1,131 @@
Ext.define('PVE.window.Snapshot', {
extend: 'Proxmox.window.Edit',
onGetValues: function(values) {
let me = this;
if (me.type === 'lxc') {
delete values.vmstate;
}
return values;
},
initComponent : function() {
var me = this;
if (!me.nodename) {
throw "no node name specified";
}
if (!me.vmid) {
throw "no VM ID specified";
}
if (!me.type) {
throw "no VM ID specified";
}
me.items = [
{
xtype: me.snapname ? 'displayfield' : 'textfield',
name: 'snapname',
value: me.snapname,
fieldLabel: gettext('Name'),
vtype: 'ConfigId',
allowBlank: false
},
{
xtype: 'displayfield',
hidden: !me.snapname,
disabled: !me.snapname,
name: 'snaptime',
renderer: PVE.Utils.render_timestamp_human_readable,
fieldLabel: gettext('Timestamp')
},
{
xtype: 'proxmoxcheckbox',
hidden: me.type !== 'qemu' || me.snapname,
disabled: me.type !== 'qemu' || me.snapname,
name: 'vmstate',
uncheckedValue: 0,
defaultValue: 0,
checked: 1,
fieldLabel: gettext('Include RAM')
},
{
xtype: 'textareafield',
grow: true,
editable: !me.viewonly,
name: 'description',
fieldLabel: gettext('Description')
},
{
title: gettext('Settings'),
hidden: !me.snapname,
xtype: 'grid',
itemId: 'summary',
border: true,
height: 200,
store: {
model: 'KeyValue',
sorters: [
{
property : 'key',
direction: 'ASC'
}
]
},
columns: [
{header: gettext('Key'), width: 150, dataIndex: 'key'},
{header: gettext('Value'), flex: 1, dataIndex: 'value'}
]
}
];
me.url = `/nodes/${me.nodename}/${me.type}/${me.vmid}/snapshot`;
let subject;
if (me.snapname) {
subject = gettext('Snapshot') + ` ${me.snapname}`;
me.url += `/${me.snapname}/config`;
} else {
subject = (me.type === 'qemu' ? 'VM' : 'CT') + me.vmid + ' ' + gettext('Snapshot');
me.method = 'POST';
me.showProgress = true;
}
Ext.apply(me, {
subject: subject,
width: me.snapname ? 620 : 450,
height: me.snapname ? 420 : undefined,
});
me.callParent();
if (!me.snapname) {
return;
}
me.load({
success: function(response) {
let kvarray = [];
Ext.Object.each(response.result.data, function(key, value) {
if (key === 'description' || key === 'snaptime') {
return;
}
kvarray.push({ key: key, value: value });
});
let summarystore = me.down('#summary').getStore();
summarystore.suspendEvents();
summarystore.add(kvarray);
summarystore.sort();
summarystore.resumeEvents();
summarystore.fireEvent('refresh', summarystore);
me.setValues(response.result.data);
}
});
}
});