extend: 'Ext.window.Window', // fixme: Proxmox.window.Edit?
resizable: false,
+ width: 500,
+ modal: true,
+ layout: 'auto',
+ border: false,
controller: {
xclass: 'Ext.app.ViewController',
start.setDisabled(newVal);
},
},
+ 'form': {
+ validitychange: function(f, valid) {
+ this.lookupReference('doRestoreBtn').setDisabled(!valid);
+ },
+ },
+ },
+
+ doRestore: function() {
+ let me = this;
+ let view = me.getView();
+
+ let values = view.down('form').getForm().getValues();
+
+ let params = {
+ vmid: view.vmid || values.vmid,
+ force: view.vmid ? 1 : 0,
+ };
+ if (values.unique) {
+ params.unique = 1;
+ }
+ if (values.start && !values['live-restore']) {
+ params.start = 1;
+ }
+ if (values['live-restore']) {
+ params['live-restore'] = 1;
+ }
+ if (values.storage) {
+ params.storage = values.storage;
+ }
+
+ ['bwlimit', 'cores', 'name', 'memory', 'sockets'].forEach(opt => {
+ if ((values[opt] ?? '') !== '') {
+ params[opt] = values[opt];
+ }
+ });
+
+ if (params.name && view.vmtype === 'lxc') {
+ params.hostname = params.name;
+ delete params.name;
+ }
+
+ let confirmMsg;
+ if (view.vmtype === 'lxc') {
+ params.ostemplate = view.volid;
+ params.restore = 1;
+ if (values.unprivileged !== 'keep') {
+ params.unprivileged = values.unprivileged;
+ }
+ confirmMsg = Proxmox.Utils.format_task_description('vzrestore', params.vmid);
+ } else if (view.vmtype === 'qemu') {
+ params.archive = view.volid;
+ confirmMsg = Proxmox.Utils.format_task_description('qmrestore', params.vmid);
+ } else {
+ throw 'unknown VM type';
+ }
+
+ let executeRestore = () => {
+ Proxmox.Utils.API2Request({
+ url: `/nodes/${view.nodename}/${view.vmtype}`,
+ params: params,
+ method: 'POST',
+ waitMsgTarget: view,
+ failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+ success: function(response, options) {
+ Ext.create('Proxmox.window.TaskViewer', {
+ autoShow: true,
+ upid: response.result.data,
+ });
+ view.close();
+ },
+ });
+ };
+
+ if (view.vmid) {
+ confirmMsg += `. ${Ext.String.format(
+ gettext('This will permanently erase current {0} data.'),
+ view.vmtype === 'lxc' ? 'CT' : 'VM',
+ )}`;
+ if (view.vmtype === 'lxc') {
+ confirmMsg += `<br>${gettext('Mount point volumes are also erased.')}`;
+ }
+ Ext.Msg.confirm(gettext('Confirm'), confirmMsg, function(btn) {
+ if (btn === 'yes') {
+ executeRestore();
+ }
+ });
+ } else {
+ executeRestore();
+ }
+ },
+
+ afterRender: function() {
+ let view = this.getView();
+
+ Proxmox.Utils.API2Request({
+ url: `/nodes/${view.nodename}/vzdump/extractconfig`,
+ method: 'GET',
+ waitMsgTarget: view,
+ params: {
+ volume: view.volid,
+ },
+ failure: response => Ext.Msg.alert('Error', response.htmlStatus),
+ success: function(response, options) {
+ let allStoragesAvailable = true;
+
+ response.result.data.split('\n').forEach(line => {
+ let [_, key, value] = line.match(/^([^:]+):\s*(\S+)\s*$/) ?? [];
+
+ if (!key) {
+ return;
+ }
+
+ if (key === '#qmdump#map') {
+ let match = value.match(/^(\S+):(\S+):(\S*):(\S*):$/) ?? [];
+ // if a /dev/XYZ disk was backed up, ther is no storage hint
+ allStoragesAvailable &&= !!match[3] && !!PVE.data.ResourceStore.getById(
+ `storage/${view.nodename}/${match[3]}`);
+ } else if (key === 'name' || key === 'hostname') {
+ view.lookupReference('nameField').setEmptyText(value);
+ } else if (key === 'memory' || key === 'cores' || key === 'sockets') {
+ view.lookupReference(`${key}Field`).setEmptyText(value);
+ }
+ });
+
+ if (!allStoragesAvailable) {
+ let storagesel = view.down('pveStorageSelector[name=storage]');
+ storagesel.allowBlank = false;
+ storagesel.setEmptyText('');
+ }
+ },
+ });
},
},
initComponent: function() {
- var me = this;
+ let me = this;
if (!me.nodename) {
throw "no node name specified";
}
-
if (!me.volid) {
throw "no volume ID specified";
}
-
if (!me.vmtype) {
throw "no vmtype specified";
}
- var storagesel = Ext.create('PVE.form.StorageSelector', {
+ let storagesel = Ext.create('PVE.form.StorageSelector', {
nodename: me.nodename,
name: 'storage',
value: '',
autoSelect: me.vmtype === 'lxc',
});
- var IDfield;
- if (me.vmid) {
- IDfield = Ext.create('Ext.form.field.Display', {
- name: 'vmid',
- value: me.vmid,
- fieldLabel: me.vmtype === 'lxc' ? 'CT' : 'VM',
- });
- } else {
- IDfield = Ext.create('PVE.form.GuestIDSelector', {
- name: 'vmid',
- guestType: me.vmtype,
- loadNextFreeID: true,
- validateExists: false,
- });
- }
-
- var items = [
+ let items = [
{
xtype: 'displayfield',
value: me.volidText || me.volid,
fieldLabel: gettext('Source'),
},
storagesel,
- IDfield,
+ {
+ xtype: 'pmxDisplayEditField',
+ name: 'vmid',
+ fieldLabel: me.vmtype === 'lxc' ? 'CT' : 'VM',
+ value: me.vmid,
+ editable: !me.vmid,
+ editConfig: {
+ xtype: 'pveGuestIDSelector',
+ guestType: me.vmtype,
+ loadNextFreeID: true,
+ validateExists: false,
+ },
+ },
{
xtype: 'pveBandwidthField',
name: 'bwlimit',
xtype: 'proxmoxcheckbox',
name: 'unique',
fieldLabel: gettext('Unique'),
- hidden: !!me.vmid,
flex: 1,
autoEl: {
tag: 'div',
fieldLabel: gettext('Live restore'),
checked: false,
hidden: !me.isPBS,
- // align checkbox with 'start' if 'unique' is hidden
- labelWidth: me.vmid ? 105 : 100,
- });
- items.push({
+ },
+ {
xtype: 'displayfield',
reference: 'liveWarning',
// TODO: Remove once more tested/stable?
- value: gettext('Note: If anything goes wrong during the live-restore, new data written by the VM will be lost.'),
+ value: gettext('Note: If anything goes wrong during the live-restore, new data written by the VM may be lost.'),
userCls: 'pmx-hint',
hidden: true,
});
}
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%',
+ items.push({
+ xtype: 'fieldset',
+ title: `${gettext('Override Settings')}:`,
+ layout: 'hbox',
+ defaults: {
+ border: false,
+ layout: 'anchor',
+ flex: 1,
},
- items: items,
- });
-
- var form = me.formPanel.getForm();
-
- var doRestore = function(url, params) {
- Proxmox.Utils.API2Request({
- url: url,
- params: params,
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ items: [
+ {
+ padding: '0 10 0 0',
+ items: [{
+ xtype: 'textfield',
+ fieldLabel: me.vmtype === 'lxc' ? gettext('Hostname') : gettext('Name'),
+ name: 'name',
+ vtype: 'DnsName',
+ reference: 'nameField',
+ allowBlank: true,
+ }, {
+ xtype: 'proxmoxintegerfield',
+ fieldLabel: gettext('Cores'),
+ name: 'cores',
+ reference: 'coresField',
+ minValue: 1,
+ maxValue: 128,
+ allowBlank: true,
+ }],
},
- success: function(response, options) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- });
- win.show();
- me.close();
+ {
+ padding: '0 0 0 10',
+ items: [
+ {
+ xtype: 'pveMemoryField',
+ fieldLabel: gettext('Memory'),
+ name: 'memory',
+ reference: 'memoryField',
+ value: '',
+ allowBlank: true,
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ fieldLabel: gettext('Sockets'),
+ name: 'sockets',
+ reference: 'socketsField',
+ minValue: 1,
+ maxValue: 4,
+ allowBlank: true,
+ hidden: me.vmtype !== 'qemu',
+ disabled: me.vmtype !== 'qemu',
+ }],
},
- });
- };
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Restore'),
- handler: function() {
- var values = form.getValues();
-
- var params = {
- vmid: me.vmid || values.vmid,
- force: me.vmid ? 1 : 0,
- };
- if (values.unique) { params.unique = 1; }
- if (values.start && !values['live-restore']) { params.start = 1; }
- if (values['live-restore']) { params['live-restore'] = 1; }
- if (values.storage) { params.storage = values.storage; }
-
- if (values.bwlimit !== undefined) {
- params.bwlimit = values.bwlimit;
- }
-
- var url;
- var msg;
- if (me.vmtype === 'lxc') {
- url = '/nodes/' + me.nodename + '/lxc';
- params.ostemplate = me.volid;
- params.restore = 1;
- if (values.unprivileged !== 'keep') {
- params.unprivileged = values.unprivileged;
- }
- msg = Proxmox.Utils.format_task_description('vzrestore', params.vmid);
- } else if (me.vmtype === 'qemu') {
- url = '/nodes/' + me.nodename + '/qemu';
- params.archive = me.volid;
- msg = Proxmox.Utils.format_task_description('qmrestore', params.vmid);
- } else {
- throw 'unknown VM type';
- }
-
- if (me.vmid) {
- msg += '. ' + gettext('This will permanently erase current VM data.');
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- doRestore(url, params);
- });
- } else {
- doRestore(url, params);
- }
- },
+ ],
});
- form.on('validitychange', function(f, valid) {
- submitBtn.setDisabled(!valid);
- });
-
- var title = gettext('Restore') + ": " + (
- me.vmtype === 'lxc' ? 'CT' : 'VM');
-
+ let title = gettext('Restore') + ": " + (me.vmtype === 'lxc' ? 'CT' : 'VM');
if (me.vmid) {
- title += " " + me.vmid;
+ title = `${gettext('Overwrite')} ${title} ${me.vmid}`;
}
Ext.apply(me, {
title: title,
- width: 500,
- modal: true,
- layout: 'auto',
- border: false,
- items: [me.formPanel],
- buttons: [submitBtn],
+ items: [
+ {
+ xtype: 'form',
+ bodyPadding: 10,
+ border: false,
+ fieldDefaults: {
+ labelWidth: 100,
+ anchor: '100%',
+ },
+ items: items,
+ },
+ ],
+ buttons: [
+ {
+ text: gettext('Restore'),
+ reference: 'doRestoreBtn',
+ handler: 'doRestore',
+ },
+ ],
});
me.callParent();