]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/tree/SnapshotTree.js
1 Ext
.define('PVE.guest.SnapshotTree', {
2 extend
: 'Ext.tree.Panel',
3 xtype
: 'pveGuestSnapshotTree',
6 stateId
: 'grid-snapshots',
10 // should be 'qemu' or 'lxc'
14 snapshotAllowed
: false,
15 rollbackAllowed
: false,
16 snapshotFeature
: false,
22 canSnapshot
: (get) => get('snapshotAllowed') && get('snapshotFeature'),
23 canRollback
: (get) => get('rollbackAllowed') && get('isSnapshot'),
24 canRemove
: (get) => get('snapshotAllowed') && get('isSnapshot'),
25 isSnapshot
: (get) => get('selected') && get('selected') !== 'current',
26 buttonText
: (get) => get('snapshotAllowed') ? gettext('Edit') : gettext('View'),
27 showMemory
: (get) => get('type') === 'qemu',
32 xclass
: 'Ext.app.ViewController',
34 newSnapshot: function() {
35 this.run_editor(false);
38 editSnapshot: function() {
39 this.run_editor(true);
42 run_editor: function(edit
) {
44 let vm
= me
.getViewModel();
47 snapname
= vm
.get('selected');
48 if (!snapname
|| snapname
=== 'current') { return; }
50 let win
= Ext
.create('PVE.window.Snapshot', {
51 nodename
: vm
.get('nodename'),
53 viewonly
: !vm
.get('snapshotAllowed'),
56 submitText
: !edit
? gettext('Take Snapshot') : undefined,
58 running
: vm
.get('running'),
61 me
.mon(win
, 'destroy', me
.reload
, me
);
64 snapshotAction: function(action
, method
) {
66 let view
= me
.getView();
67 let vm
= me
.getViewModel();
68 let snapname
= vm
.get('selected');
69 if (!snapname
) { return; }
71 let nodename
= vm
.get('nodename');
72 let type
= vm
.get('type');
73 let vmid
= vm
.get('vmid');
75 Proxmox
.Utils
.API2Request({
76 url
: `/nodes/${nodename}/${type}/${vmid}/snapshot/${snapname}/${action}`,
79 callback: function() {
82 failure: function (response
, opts
) {
83 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
85 success: function(response
, options
) {
86 var upid
= response
.result
.data
;
87 var win
= Ext
.create('Proxmox.window.TaskProgress', { upid
: upid
});
93 rollback: function() {
94 this.snapshotAction('rollback', 'POST');
97 this.snapshotAction('', 'DELETE');
100 this.load_task
.cancel();
105 let view
= me
.getView();
106 let vm
= me
.getViewModel();
107 let nodename
= vm
.get('nodename');
108 let vmid
= vm
.get('vmid');
109 let type
= vm
.get('type');
110 let load_delay
= vm
.get('load_delay');
112 Proxmox
.Utils
.API2Request({
113 url
: `/nodes/${nodename}/${type}/${vmid}/snapshot`,
115 failure: function(response
, opts
) {
116 if (me
.destroyed
) return;
117 Proxmox
.Utils
.setErrorMask(view
, response
.htmlStatus
);
118 me
.load_task
.delay(load_delay
);
120 success: function(response
, opts
) {
122 // this is in a delayed task, avoid dragons if view has
123 // been destroyed already and go home.
126 Proxmox
.Utils
.setErrorMask(view
, false);
127 var digest
= 'invalid';
129 var root
= { name
: '__root', expanded
: true, children
: [] };
130 Ext
.Array
.each(response
.result
.data
, function(item
) {
133 if (item
.name
=== 'current') {
134 vm
.set('running', !!item
.running
);
135 digest
= item
.digest
+ item
.running
;
136 item
.iconCls
= PVE
.Utils
.get_object_icon_class(vm
.get('type'), item
);
138 item
.iconCls
= 'fa fa-fw fa-history x-fa-tree';
140 idhash
[item
.name
] = item
;
143 if (digest
!== me
.old_digest
) {
144 me
.old_digest
= digest
;
146 Ext
.Array
.each(response
.result
.data
, function(item
) {
147 if (item
.parent
&& idhash
[item
.parent
]) {
148 var parent_item
= idhash
[item
.parent
];
149 parent_item
.children
.push(item
);
150 parent_item
.leaf
= false;
151 parent_item
.expanded
= true;
152 parent_item
.expandable
= false;
154 root
.children
.push(item
);
158 me
.getView().setRootNode(root
);
161 me
.load_task
.delay(load_delay
);
165 // if we do not have the permissions, we don't have to check
166 // if we can create a snapshot, since the butten stays disabled
167 if (!vm
.get('snapshotAllowed')) {
171 Proxmox
.Utils
.API2Request({
172 url
: `/nodes/${nodename}/${type}/${vmid}/feature`,
173 params
: { feature
: 'snapshot' },
175 success: function(response
, options
) {
177 // this is in a delayed task, the current view could been
178 // destroyed already; then we mustn't do viemodel set
181 let res
= response
.result
.data
;
182 vm
.set('snapshotFeature', !!res
.hasFeature
);
187 select: function(grid
, val
) {
188 let vm
= this.getViewModel();
189 if (val
.length
< 1) {
190 vm
.set('selected', '');
193 vm
.set('selected', val
[0].data
.name
);
196 init: function(view
) {
198 let vm
= me
.getViewModel();
199 me
.load_task
= new Ext
.util
.DelayedTask(me
.reload
, me
);
202 throw 'guest type not set';
204 vm
.set('type', view
.type
);
206 if (!view
.pveSelNode
.data
.node
) {
207 throw "no node name specified";
209 vm
.set('nodename', view
.pveSelNode
.data
.node
);
211 if (!view
.pveSelNode
.data
.vmid
) {
212 throw "no VM ID specified";
214 vm
.set('vmid', view
.pveSelNode
.data
.vmid
);
216 let caps
= Ext
.state
.Manager
.get('GuiCap');
217 vm
.set('snapshotAllowed', !!caps
.vms
['VM.Snapshot']);
218 vm
.set('rollbackAllowed', !!caps
.vms
['VM.Snapshot.Rollback']);
220 view
.getStore().sorters
.add({
230 selectionchange
: 'select',
231 itemdblclick
: 'editSnapshot',
238 sortableColumns
: false,
242 xtype
: 'proxmoxButton',
243 text
: gettext('Take Snapshot'),
246 disabled
: "{!canSnapshot}",
248 handler
: 'newSnapshot',
252 xtype
: 'proxmoxButton',
253 text
: gettext('Rollback'),
256 disabled
: '{!canRollback}',
258 confirmMsg: function() {
259 let view
= this.up('treepanel');
260 let rec
= view
.getSelection()[0];
261 let vmid
= view
.getViewModel().get('vmid');
262 return Proxmox
.Utils
.format_task_description('qmrollback', vmid
) +
263 " '" + rec
.data
.name
+ "'";
268 xtype
: 'proxmoxButton',
269 text
: gettext('Remove'),
272 disabled
: '{!canRemove}',
274 confirmMsg: function() {
275 let view
= this.up('treepanel');
276 let rec
= view
.getSelection()[0];
277 return Ext
.String
.format(
278 gettext('Are you sure you want to remove entry {0}'),
285 xtype
: 'proxmoxButton',
286 text
: gettext('Edit'),
288 text
: '{buttonText}',
289 disabled
: '{!isSnapshot}',
293 handler
: 'editSnapshot',
297 text
: gettext("The current guest configuration does not support taking new snapshots"),
300 hidden
: "{canSnapshot}",
308 'name', 'description', 'snapstate', 'vmstate', 'running',
309 { name
: 'snaptime', type
: 'date', dateFormat
: 'timestamp' },
312 calculate: function(data
) {
313 return data
.snaptime
|| (data
.name
=== 'current' ? 'ZZZ' : data
.snapstate
);
321 text
: gettext('Name'),
324 renderer: function(value
, metaData
, record
) {
325 if (value
=== 'current') {
326 return gettext('NOW');
333 text
: gettext('RAM'),
336 hidden
: '{!showMemory}',
340 dataIndex
: 'vmstate',
342 renderer: function(value
, metaData
, record
) {
343 if (record
.data
.name
!== 'current') {
344 return Proxmox
.Utils
.format_boolean(value
);
349 text
: gettext('Date') + "/" + gettext("Status"),
350 dataIndex
: 'snaptime',
352 renderer: function(value
, metaData
, record
) {
353 if (record
.data
.snapstate
) {
354 return record
.data
.snapstate
;
357 return Ext
.Date
.format(value
,'Y-m-d H:i:s');
362 text
: gettext('Description'),
363 dataIndex
: 'description',
365 renderer: function(value
, metaData
, record
) {
366 if (record
.data
.name
=== 'current') {
367 return gettext("You are here!");
369 return Ext
.String
.htmlEncode(value
);