]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/dc/ClusterEdit.js
ui: eslint: fix various spacing related issues
[pve-manager.git] / www / manager6 / dc / ClusterEdit.js
1 Ext.define('PVE.ClusterCreateWindow', {
2 extend: 'Proxmox.window.Edit',
3 xtype: 'pveClusterCreateWindow',
4
5 title: gettext('Create Cluster'),
6 width: 600,
7
8 method: 'POST',
9 url: '/cluster/config',
10
11 isCreate: true,
12 subject: gettext('Cluster'),
13 showTaskViewer: true,
14
15 onlineHelp: 'pvecm_create_cluster',
16
17 items: {
18 xtype: 'inputpanel',
19 items: [{
20 xtype: 'textfield',
21 fieldLabel: gettext('Cluster Name'),
22 allowBlank: false,
23 maxLength: 15,
24 name: 'clustername',
25 },
26 {
27 xtype: 'fieldcontainer',
28 fieldLabel: gettext("Cluster Network"),
29 items: [
30 {
31 xtype: 'pveCorosyncLinkEditor',
32 infoText: gettext("Multiple links are used as failover, lower numbers have higher priority."),
33 name: 'links',
34 },
35 ],
36 }],
37 },
38 });
39
40 Ext.define('PVE.ClusterInfoWindow', {
41 extend: 'Ext.window.Window',
42 xtype: 'pveClusterInfoWindow',
43 mixins: ['Proxmox.Mixin.CBind'],
44
45 width: 800,
46 modal: true,
47 resizable: false,
48 title: gettext('Cluster Join Information'),
49
50 joinInfo: {
51 ipAddress: undefined,
52 fingerprint: undefined,
53 totem: {},
54 },
55
56 items: [
57 {
58 xtype: 'component',
59 border: false,
60 padding: '10 10 10 10',
61 html: gettext("Copy the Join Information here and use it on the node you want to add."),
62 },
63 {
64 xtype: 'container',
65 layout: 'form',
66 border: false,
67 padding: '0 10 10 10',
68 items: [
69 {
70 xtype: 'textfield',
71 fieldLabel: gettext('IP Address'),
72 cbind: {
73 value: '{joinInfo.ipAddress}',
74 },
75 editable: false,
76 },
77 {
78 xtype: 'textfield',
79 fieldLabel: gettext('Fingerprint'),
80 cbind: {
81 value: '{joinInfo.fingerprint}',
82 },
83 editable: false,
84 },
85 {
86 xtype: 'textarea',
87 inputId: 'pveSerializedClusterInfo',
88 fieldLabel: gettext('Join Information'),
89 grow: true,
90 cbind: {
91 joinInfo: '{joinInfo}',
92 },
93 editable: false,
94 listeners: {
95 afterrender: function(field) {
96 if (!field.joinInfo) {
97 return;
98 }
99 var jsons = Ext.JSON.encode(field.joinInfo);
100 var base64s = Ext.util.Base64.encode(jsons);
101 field.setValue(base64s);
102 },
103 },
104 },
105 ],
106 },
107 ],
108 dockedItems: [{
109 dock: 'bottom',
110 xtype: 'toolbar',
111 items: [{
112 xtype: 'button',
113 handler: function(b) {
114 var el = document.getElementById('pveSerializedClusterInfo');
115 el.select();
116 document.execCommand("copy");
117 },
118 text: gettext('Copy Information'),
119 }],
120 }],
121 });
122
123 Ext.define('PVE.ClusterJoinNodeWindow', {
124 extend: 'Proxmox.window.Edit',
125 xtype: 'pveClusterJoinNodeWindow',
126
127 title: gettext('Cluster Join'),
128 width: 800,
129
130 method: 'POST',
131 url: '/cluster/config/join',
132
133 defaultFocus: 'textarea[name=serializedinfo]',
134 isCreate: true,
135 bind: {
136 submitText: '{submittxt}',
137 },
138 showTaskViewer: true,
139
140 onlineHelp: 'pvecm_join_node_to_cluster',
141
142 viewModel: {
143 parent: null,
144 data: {
145 info: {
146 fp: '',
147 ip: '',
148 clusterName: '',
149 },
150 hasAssistedInfo: false,
151 },
152 formulas: {
153 submittxt: function(get) {
154 let cn = get('info.clusterName');
155 if (cn) {
156 return Ext.String.format(gettext('Join {0}'), `'${cn}'`);
157 }
158 return gettext('Join');
159 },
160 showClusterFields: (get) => {
161 let manualMode = !get('assistedEntry.checked');
162 return get('hasAssistedInfo') || manualMode;
163 },
164 },
165 },
166
167 controller: {
168 xclass: 'Ext.app.ViewController',
169 control: {
170 '#': {
171 close: function() {
172 delete PVE.Utils.silenceAuthFailures;
173 },
174 },
175 'proxmoxcheckbox[name=assistedEntry]': {
176 change: 'onInputTypeChange',
177 },
178 'textarea[name=serializedinfo]': {
179 change: 'recomputeSerializedInfo',
180 enable: 'resetField',
181 },
182 'textfield': {
183 disable: 'resetField',
184 },
185 },
186 resetField: function(field) {
187 field.reset();
188 },
189 onInputTypeChange: function(field, assistedInput) {
190 let linkEditor = this.lookup('linkEditor');
191
192 // this also clears all links
193 linkEditor.setAllowNumberEdit(!assistedInput);
194
195 if (!assistedInput) {
196 linkEditor.setInfoText();
197 linkEditor.setDefaultLinks();
198 }
199 },
200 recomputeSerializedInfo: function(field, value) {
201 let vm = this.getViewModel();
202
203 let assistedEntryBox = this.lookup('assistedEntry');
204
205 if (!assistedEntryBox.getValue()) {
206 // not in assisted entry mode, nothing to do
207 vm.set('hasAssistedInfo', false);
208 return;
209 }
210
211 let linkEditor = this.lookup('linkEditor');
212
213 let jsons = Ext.util.Base64.decode(value);
214 let joinInfo = Ext.JSON.decode(jsons, true);
215
216 let info = {
217 fp: '',
218 ip: '',
219 clusterName: '',
220 };
221
222 if (!(joinInfo && joinInfo.totem)) {
223 field.valid = false;
224 linkEditor.setLinks([]);
225 linkEditor.setInfoText();
226 vm.set('hasAssistedInfo', false);
227 } else {
228 let interfaces = joinInfo.totem.interface;
229 let links = Object.values(interfaces).map(iface => {
230 let linkNumber = iface.linknumber;
231 let peerLink;
232 if (joinInfo.peerLinks) {
233 peerLink = joinInfo.peerLinks[linkNumber];
234 }
235 return {
236 number: linkNumber,
237 value: '',
238 text: peerLink ? Ext.String.format(gettext("peer's link address: {0}"), peerLink) : '',
239 allowBlank: false,
240 };
241 });
242
243 linkEditor.setInfoText();
244 if (links.length == 1 && joinInfo.ring_addr !== undefined &&
245 joinInfo.ring_addr[0] === joinInfo.ipAddress) {
246 links[0].allowBlank = true;
247 links[0].emptyText = gettext("IP resolved by node's hostname");
248 }
249
250 linkEditor.setLinks(links);
251
252 info = {
253 ip: joinInfo.ipAddress,
254 fp: joinInfo.fingerprint,
255 clusterName: joinInfo.totem.cluster_name,
256 };
257 field.valid = true;
258 vm.set('hasAssistedInfo', true);
259 }
260 vm.set('info', info);
261 },
262 },
263
264 submit: function() {
265 // joining may produce temporarily auth failures, ignore as long the task runs
266 PVE.Utils.silenceAuthFailures = true;
267 this.callParent();
268 },
269
270 taskDone: function(success) {
271 delete PVE.Utils.silenceAuthFailures;
272 if (success) {
273 // reload always (if user wasn't faster), but wait a bit for pveproxy
274 Ext.defer(function() {
275 window.location.reload(true);
276 }, 5000);
277 var txt = gettext('Cluster join task finished, node certificate may have changed, reload GUI!');
278 // ensure user cannot do harm
279 Ext.getBody().mask(txt, ['pve-static-mask']);
280 // TaskView may hide above mask, so tell him directly
281 Ext.Msg.show({
282 title: gettext('Join Task Finished'),
283 icon: Ext.Msg.INFO,
284 msg: txt,
285 });
286 }
287 },
288
289 items: [{
290 xtype: 'proxmoxcheckbox',
291 reference: 'assistedEntry',
292 name: 'assistedEntry',
293 itemId: 'assistedEntry',
294 submitValue: false,
295 value: true,
296 autoEl: {
297 tag: 'div',
298 'data-qtip': gettext('Select if join information should be extracted from pasted cluster information, deselect for manual entering'),
299 },
300 boxLabel: gettext('Assisted join: Paste encoded cluster join information and enter password.'),
301 },
302 {
303 xtype: 'textarea',
304 name: 'serializedinfo',
305 submitValue: false,
306 allowBlank: false,
307 fieldLabel: gettext('Information'),
308 emptyText: gettext('Paste encoded Cluster Information here'),
309 validator: function(val) {
310 return val === '' || this.valid ||
311 gettext('Does not seem like a valid encoded Cluster Information!');
312 },
313 bind: {
314 disabled: '{!assistedEntry.checked}',
315 hidden: '{!assistedEntry.checked}',
316 },
317 value: '',
318 },
319 {
320 xtype: 'panel',
321 width: 776,
322 layout: {
323 type: 'hbox',
324 align: 'center',
325 },
326 bind: {
327 hidden: '{!showClusterFields}',
328 },
329 items: [
330 {
331 xtype: 'textfield',
332 flex: 1,
333 margin: '0 5px 0 0',
334 fieldLabel: gettext('Peer Address'),
335 allowBlank: false,
336 bind: {
337 value: '{info.ip}',
338 readOnly: '{assistedEntry.checked}',
339 },
340 name: 'hostname',
341 },
342 {
343 xtype: 'textfield',
344 flex: 1,
345 margin: '0 0 10px 5px',
346 inputType: 'password',
347 emptyText: gettext("Peer's root password"),
348 fieldLabel: gettext('Password'),
349 allowBlank: false,
350 name: 'password',
351 },
352 ],
353 },
354 {
355 xtype: 'textfield',
356 fieldLabel: gettext('Fingerprint'),
357 allowBlank: false,
358 bind: {
359 value: '{info.fp}',
360 readOnly: '{assistedEntry.checked}',
361 hidden: '{!showClusterFields}',
362 },
363 name: 'fingerprint',
364 },
365 {
366 xtype: 'fieldcontainer',
367 fieldLabel: gettext("Cluster Network"),
368 bind: {
369 hidden: '{!showClusterFields}',
370 },
371 items: [
372 {
373 xtype: 'pveCorosyncLinkEditor',
374 itemId: 'linkEditor',
375 reference: 'linkEditor',
376 allowNumberEdit: false,
377 },
378 ],
379 }],
380 });