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