]>
Commit | Line | Data |
---|---|---|
1 | Ext.define('PVE.window.Snapshot', { | |
2 | extend: 'Proxmox.window.Edit', | |
3 | ||
4 | viewModel: { | |
5 | data: { | |
6 | type: undefined, | |
7 | isCreate: undefined, | |
8 | running: false, | |
9 | guestAgentEnabled: false, | |
10 | }, | |
11 | formulas: { | |
12 | runningWithoutGuestAgent: (get) => get('type') === 'qemu' && get('running') && !get('guestAgentEnabled'), | |
13 | shouldWarnAboutFS: (get) => get('isCreate') && get('runningWithoutGuestAgent') && get('!vmstate.checked'), | |
14 | }, | |
15 | }, | |
16 | ||
17 | onGetValues: function(values) { | |
18 | let me = this; | |
19 | ||
20 | if (me.type === 'lxc') { | |
21 | delete values.vmstate; | |
22 | } | |
23 | ||
24 | return values; | |
25 | }, | |
26 | ||
27 | initComponent: function() { | |
28 | var me = this; | |
29 | var vm = me.getViewModel(); | |
30 | ||
31 | if (!me.nodename) { | |
32 | throw "no node name specified"; | |
33 | } | |
34 | ||
35 | if (!me.vmid) { | |
36 | throw "no VM ID specified"; | |
37 | } | |
38 | ||
39 | if (!me.type) { | |
40 | throw "no type specified"; | |
41 | } | |
42 | ||
43 | vm.set('type', me.type); | |
44 | vm.set('running', me.running); | |
45 | vm.set('isCreate', me.isCreate); | |
46 | ||
47 | if (me.type === 'qemu' && me.isCreate) { | |
48 | Proxmox.Utils.API2Request({ | |
49 | url: `/nodes/${me.nodename}/${me.type}/${me.vmid}/config`, | |
50 | params: { 'current': '1' }, | |
51 | method: 'GET', | |
52 | success: function(response, options) { | |
53 | let res = response.result.data; | |
54 | let enabled = PVE.Parser.parsePropertyString(res.agent, 'enabled'); | |
55 | vm.set('guestAgentEnabled', !!PVE.Parser.parseBoolean(enabled.enabled)); | |
56 | }, | |
57 | }); | |
58 | } | |
59 | ||
60 | me.items = [ | |
61 | { | |
62 | xtype: me.isCreate ? 'textfield' : 'displayfield', | |
63 | name: 'snapname', | |
64 | value: me.snapname, | |
65 | fieldLabel: gettext('Name'), | |
66 | vtype: 'ConfigId', | |
67 | allowBlank: false, | |
68 | }, | |
69 | { | |
70 | xtype: 'displayfield', | |
71 | hidden: me.isCreate, | |
72 | disabled: me.isCreate, | |
73 | name: 'snaptime', | |
74 | renderer: PVE.Utils.render_timestamp_human_readable, | |
75 | fieldLabel: gettext('Timestamp'), | |
76 | }, | |
77 | { | |
78 | xtype: 'proxmoxcheckbox', | |
79 | hidden: me.type !== 'qemu' || !me.isCreate || !me.running, | |
80 | disabled: me.type !== 'qemu' || !me.isCreate || !me.running, | |
81 | name: 'vmstate', | |
82 | reference: 'vmstate', | |
83 | uncheckedValue: 0, | |
84 | defaultValue: 0, | |
85 | checked: 1, | |
86 | fieldLabel: gettext('Include RAM'), | |
87 | }, | |
88 | { | |
89 | xtype: 'textareafield', | |
90 | grow: true, | |
91 | editable: !me.viewonly, | |
92 | name: 'description', | |
93 | fieldLabel: gettext('Description'), | |
94 | }, | |
95 | { | |
96 | xtype: 'displayfield', | |
97 | userCls: 'pmx-hint', | |
98 | name: 'fswarning', | |
99 | hidden: true, | |
100 | value: gettext('It is recommended to either include the RAM or use the QEMU Guest Agent when taking a snapshot of a running VM to avoid inconsistencies.'), | |
101 | bind: { | |
102 | hidden: '{!shouldWarnAboutFS}', | |
103 | }, | |
104 | }, | |
105 | { | |
106 | title: gettext('Settings'), | |
107 | hidden: me.isCreate, | |
108 | xtype: 'grid', | |
109 | itemId: 'summary', | |
110 | border: true, | |
111 | height: 200, | |
112 | store: { | |
113 | model: 'KeyValue', | |
114 | sorters: [ | |
115 | { | |
116 | property: 'key', | |
117 | direction: 'ASC', | |
118 | }, | |
119 | ], | |
120 | }, | |
121 | columns: [ | |
122 | { | |
123 | header: gettext('Key'), | |
124 | width: 150, | |
125 | dataIndex: 'key', | |
126 | }, | |
127 | { | |
128 | header: gettext('Value'), | |
129 | flex: 1, | |
130 | dataIndex: 'value', | |
131 | }, | |
132 | ], | |
133 | }, | |
134 | ]; | |
135 | ||
136 | me.url = `/nodes/${me.nodename}/${me.type}/${me.vmid}/snapshot`; | |
137 | ||
138 | let subject; | |
139 | if (me.isCreate) { | |
140 | subject = (me.type === 'qemu' ? 'VM' : 'CT') + me.vmid + ' ' + gettext('Snapshot'); | |
141 | me.method = 'POST'; | |
142 | me.showTaskViewer = true; | |
143 | } else { | |
144 | subject = `${gettext('Snapshot')} ${me.snapname}`; | |
145 | me.url += `/${me.snapname}/config`; | |
146 | } | |
147 | ||
148 | Ext.apply(me, { | |
149 | subject: subject, | |
150 | width: me.isCreate ? 450 : 620, | |
151 | height: me.isCreate ? undefined : 420, | |
152 | }); | |
153 | ||
154 | me.callParent(); | |
155 | ||
156 | if (!me.snapname) { | |
157 | return; | |
158 | } | |
159 | ||
160 | me.load({ | |
161 | success: function(response) { | |
162 | let kvarray = []; | |
163 | Ext.Object.each(response.result.data, function(key, value) { | |
164 | if (key === 'description' || key === 'snaptime') { | |
165 | return; | |
166 | } | |
167 | kvarray.push({ key: key, value: value }); | |
168 | }); | |
169 | ||
170 | let summarystore = me.down('#summary').getStore(); | |
171 | summarystore.suspendEvents(); | |
172 | summarystore.add(kvarray); | |
173 | summarystore.sort(); | |
174 | summarystore.resumeEvents(); | |
175 | summarystore.fireEvent('refresh', summarystore); | |
176 | ||
177 | me.setValues(response.result.data); | |
178 | }, | |
179 | }); | |
180 | }, | |
181 | }); |