]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/CloudInit.js
add missing onlineHelp links
[pve-manager.git] / www / manager6 / qemu / CloudInit.js
1 Ext.define('PVE.qemu.CloudInit', {
2 extend: 'Proxmox.grid.PendingObjectGrid',
3 xtype: 'pveCiPanel',
4
5 onlineHelp: 'qm_cloud_init',
6
7 tbar: [
8 {
9 xtype: 'proxmoxButton',
10 disabled: true,
11 dangerous: true,
12 confirmMsg: function(rec) {
13 var me = this.up('grid');
14 var warn = gettext('Are you sure you want to remove entry {0}');
15
16 var entry = rec.data.key;
17 var msg = Ext.String.format(warn, "'"
18 + me.renderKey(entry, {}, rec) + "'");
19
20 return msg;
21 },
22 enableFn: function(record) {
23 var me = this.up('grid');
24 var caps = Ext.state.Manager.get('GuiCap');
25 if (me.rows[record.data.key].never_delete ||
26 !caps.vms['VM.Config.Network']) {
27 return false;
28 }
29
30 if (record.data.key === 'cipassword' && !record.data.value) {
31 return false;
32 }
33 return true;
34 },
35 handler: function() {
36 var me = this.up('grid');
37 var records = me.getSelection();
38 if (!records || !records.length) {
39 return;
40 }
41
42 var id = records[0].data.key;
43 var match = id.match(/^net(\d+)$/);
44 if (match) {
45 id = 'ipconfig' + match[1];
46 }
47
48 var params = {};
49 params['delete'] = id;
50 Proxmox.Utils.API2Request({
51 url: me.baseurl + '/config',
52 waitMsgTarget: me,
53 method: 'PUT',
54 params: params,
55 failure: function(response, opts) {
56 Ext.Msg.alert('Error', response.htmlStatus);
57 },
58 callback: function() {
59 me.reload();
60 }
61 });
62 },
63 text: gettext('Remove')
64 },
65 {
66 xtype: 'proxmoxButton',
67 disabled: true,
68 handler: function() {
69 var me = this.up('grid');
70 me.run_editor();
71 },
72 text: gettext('Edit')
73 },
74 '-',
75 {
76 xtype: 'button',
77 itemId: 'savebtn',
78 text: gettext('Regenerate Image'),
79 handler: function() {
80 var me = this.up('grid');
81 var eject_params = {};
82 var insert_params = {};
83 var disk = PVE.Parser.parseQemuDrive(me.ciDriveId, me.ciDrive);
84 var storage = '';
85 var stormatch = disk.file.match(/^([^\:]+)\:/);
86 if (stormatch) {
87 storage = stormatch[1];
88 }
89 eject_params[me.ciDriveId] = 'none,media=cdrom';
90 insert_params[me.ciDriveId] = storage + ':cloudinit';
91
92 var failure = function(response, opts) {
93 Ext.Msg.alert('Error', response.htmlStatus);
94 };
95
96 Proxmox.Utils.API2Request({
97 url: me.baseurl + '/config',
98 waitMsgTarget: me,
99 method: 'PUT',
100 params: eject_params,
101 failure: failure,
102 callback: function() {
103 Proxmox.Utils.API2Request({
104 url: me.baseurl + '/config',
105 waitMsgTarget: me,
106 method: 'PUT',
107 params: insert_params,
108 failure: failure,
109 callback: function() {
110 me.reload();
111 }
112 });
113 }
114 });
115 }
116 }
117 ],
118
119 border: false,
120
121 set_button_status: function(rstore, records, success) {
122 if (!success || records.length < 1) {
123 return;
124 }
125 var me = this;
126 var found;
127 records.forEach(function(record) {
128 if (found) {
129 return;
130 }
131 var id = record.data.key;
132 var value = record.data.value;
133 var ciregex = new RegExp("vm-" + me.pveSelNode.data.vmid + "-cloudinit");
134 if (id.match(/^(ide|scsi|sata)\d+$/) && ciregex.test(value)) {
135 found = id;
136 me.ciDriveId = found;
137 me.ciDrive = value;
138 }
139 });
140
141 me.down('#savebtn').setDisabled(!found);
142 me.setDisabled(!found);
143 if (!found) {
144 me.getView().mask(gettext('No CloudInit Drive found'), ['pve-static-mask']);
145 } else {
146 me.getView().unmask();
147 }
148 },
149
150 renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
151 var me = this;
152 var rows = me.rows;
153 var rowdef = rows[key] || {};
154
155 var icon = "";
156 if (rowdef.iconCls) {
157 icon = '<i class="' + rowdef.iconCls + '"></i> ';
158 }
159 return icon + (rowdef.header || key);
160 },
161
162 listeners: {
163 activate: function () {
164 var me = this;
165 me.rstore.startUpdate();
166 },
167 itemdblclick: function() {
168 var me = this;
169 me.run_editor();
170 }
171 },
172
173 initComponent: function() {
174 var me = this;
175
176 var nodename = me.pveSelNode.data.node;
177 if (!nodename) {
178 throw "no node name specified";
179 }
180
181 var vmid = me.pveSelNode.data.vmid;
182 if (!vmid) {
183 throw "no VM ID specified";
184 }
185 var caps = Ext.state.Manager.get('GuiCap');
186 me.baseurl = '/api2/extjs/nodes/' + nodename + '/qemu/' + vmid;
187 me.url = me.baseurl + '/pending';
188 me.editorConfig.url = me.baseurl + '/config';
189 me.editorConfig.pveSelNode = me.pveSelNode;
190
191 /*jslint confusion: true*/
192 /* editor is string and object */
193 me.rows = {
194 ciuser: {
195 header: gettext('User'),
196 iconCls: 'fa fa-user',
197 never_delete: true,
198 defaultValue: '',
199 editor: caps.vms['VM.Config.Options'] ? {
200 xtype: 'proxmoxWindowEdit',
201 subject: gettext('User'),
202 items: [
203 {
204 xtype: 'proxmoxtextfield',
205 deleteEmpty: true,
206 emptyText: Proxmox.Utils.defaultText,
207 fieldLabel: gettext('User'),
208 name: 'ciuser'
209 }
210 ]
211 } : undefined,
212 renderer: function(value) {
213 return value || Proxmox.Utils.defaultText;
214 }
215 },
216 cipassword: {
217 header: gettext('Password'),
218 iconCls: 'fa fa-unlock',
219 defaultValue: '',
220 editor: caps.vms['VM.Config.Options'] ? {
221 xtype: 'proxmoxWindowEdit',
222 subject: gettext('Password'),
223 items: [
224 {
225 xtype: 'proxmoxtextfield',
226 inputType: 'password',
227 deleteEmpty: true,
228 emptyText: Proxmox.Utils.noneText,
229 fieldLabel: gettext('Password'),
230 name: 'cipassword'
231 }
232 ]
233 } : undefined,
234 renderer: function(value) {
235 return value || Proxmox.Utils.noneText;
236 }
237 },
238 searchdomain: {
239 header: gettext('DNS domain'),
240 iconCls: 'fa fa-globe',
241 editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
242 never_delete: true,
243 defaultValue: gettext('use host settings')
244 },
245 nameserver: {
246 header: gettext('DNS servers'),
247 iconCls: 'fa fa-globe',
248 editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
249 never_delete: true,
250 defaultValue: gettext('use host settings')
251 },
252 sshkeys: {
253 header: gettext('SSH public key'),
254 iconCls: 'fa fa-key',
255 editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.SSHKeyEdit' : undefined,
256 never_delete: true,
257 renderer: function(value) {
258 value = decodeURIComponent(value);
259 var keys = value.split('\n');
260 var text = [];
261 keys.forEach(function(key) {
262 if (key.length) {
263 // First erase all quoted strings (eg. command="foo"
264 var v = key.replace(/"(?:\\.|[^"\\])*"/g, '');
265 // Now try to detect the comment:
266 var res = v.match(/^\s*(\S+\s+)?(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)\s+\S+\s+(.*?)\s*$/, '');
267 if (res) {
268 key = Ext.String.htmlEncode(res[2]);
269 if (res[1]) {
270 key += ' <span style="color:gray">(' + gettext('with options') + ')</span>';
271 }
272 text.push(key);
273 return;
274 }
275 // Most likely invalid at this point, so just stick to
276 // the old value.
277 text.push(Ext.String.htmlEncode(key));
278 }
279 });
280 if (text.length) {
281 return text.join('<br>');
282 } else {
283 return Proxmox.Utils.noneText;
284 }
285 },
286 defaultValue: ''
287 }
288 };
289 var i;
290 var ipconfig_renderer = function(value, md, record, ri, ci, store, pending) {
291 var id = record.data.key;
292 var match = id.match(/^net(\d+)$/);
293 var val = '';
294 if (match) {
295 val = me.getObjectValue('ipconfig'+match[1], '', pending);
296 }
297 return val;
298 };
299 for (i = 0; i < 32; i++) {
300 // we want to show an entry for every network device
301 // even if it is empty
302 me.rows['net' + i.toString()] = {
303 multiKey: ['ipconfig' + i.toString(), 'net' + i.toString()],
304 header: gettext('IP Config') + ' (net' + i.toString() +')',
305 editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.IPConfigEdit' : undefined,
306 iconCls: 'fa fa-exchange',
307 renderer: ipconfig_renderer
308 };
309 me.rows['ipconfig' + i.toString()] = {
310 visible: false
311 };
312 }
313 /*jslint confusion: false*/
314
315 PVE.Utils.forEachBus(['ide', 'scsi', 'sata'], function(type, id) {
316 me.rows[type+id] = {
317 visible: false
318 };
319 });
320 me.callParent();
321 me.mon(me.rstore, 'load', me.set_button_status, me);
322 }
323 });