]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/dc/Cluster.js
ui: dc/cluster: eslint fixes and code cleanup/refactoring
[pve-manager.git] / www / manager6 / dc / Cluster.js
1 Ext.define('pve-cluster-nodes', {
2 extend: 'Ext.data.Model',
3 fields: [
4 'node', { type: 'integer', name: 'nodeid' }, 'ring0_addr', 'ring1_addr',
5 { type: 'integer', name: 'quorum_votes' },
6 ],
7 proxy: {
8 type: 'proxmox',
9 url: "/api2/json/cluster/config/nodes",
10 },
11 idProperty: 'nodeid',
12 });
13
14 Ext.define('pve-cluster-info', {
15 extend: 'Ext.data.Model',
16 proxy: {
17 type: 'proxmox',
18 url: "/api2/json/cluster/config/join",
19 },
20 });
21
22 Ext.define('PVE.ClusterAdministration', {
23 extend: 'Ext.panel.Panel',
24 xtype: 'pveClusterAdministration',
25
26 title: gettext('Cluster Administration'),
27 onlineHelp: 'chapter_pvecm',
28
29 border: false,
30 defaults: { border: false },
31
32 viewModel: {
33 parent: null,
34 data: {
35 totem: {},
36 nodelist: [],
37 preferred_node: {
38 name: '',
39 fp: '',
40 addr: '',
41 },
42 isInCluster: false,
43 nodecount: 0,
44 },
45 },
46
47 items: [
48 {
49 xtype: 'panel',
50 title: gettext('Cluster Information'),
51 controller: {
52 xclass: 'Ext.app.ViewController',
53
54 init: function(view) {
55 view.store = Ext.create('Proxmox.data.UpdateStore', {
56 autoStart: true,
57 interval: 15 * 1000,
58 storeid: 'pve-cluster-info',
59 model: 'pve-cluster-info',
60 });
61 view.store.on('load', this.onLoad, this);
62 view.on('destroy', view.store.stopUpdate);
63 },
64
65 onLoad: function(store, records, success) {
66 let vm = this.getViewModel();
67 if (!success || !records || !records[0].data) {
68 vm.set('totem', {});
69 vm.set('isInCluster', false);
70 vm.set('nodelist', []);
71 vm.set('preferred_node', {
72 name: '',
73 addr: '',
74 fp: '',
75 });
76 return;
77 }
78 let data = records[0].data;
79 vm.set('totem', data.totem);
80 vm.set('isInCluster', !!data.totem.cluster_name);
81 vm.set('nodelist', data.nodelist);
82
83 var nodeinfo = Ext.Array.findBy(data.nodelist, function(el) {
84 return el.name === data.preferred_node;
85 });
86
87 let links = {};
88 let ring_addr = [];
89 PVE.Utils.forEachCorosyncLink(nodeinfo, (num, link) => {
90 links[num] = link;
91 ring_addr.push(link);
92 });
93
94 vm.set('preferred_node', {
95 name: data.preferred_node,
96 addr: nodeinfo.pve_addr,
97 peerLinks: links,
98 ring_addr: ring_addr,
99 fp: nodeinfo.pve_fp,
100 });
101 },
102
103 onCreate: function() {
104 let view = this.getView();
105 view.store.stopUpdate();
106 Ext.create('PVE.ClusterCreateWindow', {
107 autoShow: true,
108 listeners: {
109 destroy: function() {
110 view.store.startUpdate();
111 },
112 },
113 });
114 },
115
116 onClusterInfo: function() {
117 let vm = this.getViewModel();
118 Ext.create('PVE.ClusterInfoWindow', {
119 autoShow: true,
120 joinInfo: {
121 ipAddress: vm.get('preferred_node.addr'),
122 fingerprint: vm.get('preferred_node.fp'),
123 peerLinks: vm.get('preferred_node.peerLinks'),
124 ring_addr: vm.get('preferred_node.ring_addr'),
125 totem: vm.get('totem'),
126 },
127 });
128 },
129
130 onJoin: function() {
131 let view = this.getView();
132 view.store.stopUpdate();
133 Ext.create('PVE.ClusterJoinNodeWindow', {
134 autoShow: true,
135 listeners: {
136 destroy: function() {
137 view.store.startUpdate();
138 },
139 },
140 });
141 },
142 },
143 tbar: [
144 {
145 text: gettext('Create Cluster'),
146 reference: 'createButton',
147 handler: 'onCreate',
148 bind: {
149 disabled: '{isInCluster}',
150 },
151 },
152 {
153 text: gettext('Join Information'),
154 reference: 'addButton',
155 handler: 'onClusterInfo',
156 bind: {
157 disabled: '{!isInCluster}',
158 },
159 },
160 {
161 text: gettext('Join Cluster'),
162 reference: 'joinButton',
163 handler: 'onJoin',
164 bind: {
165 disabled: '{isInCluster}',
166 },
167 },
168 ],
169 layout: 'hbox',
170 bodyPadding: 5,
171 items: [
172 {
173 xtype: 'displayfield',
174 fieldLabel: gettext('Cluster Name'),
175 bind: {
176 value: '{totem.cluster_name}',
177 hidden: '{!isInCluster}',
178 },
179 flex: 1,
180 },
181 {
182 xtype: 'displayfield',
183 fieldLabel: gettext('Config Version'),
184 bind: {
185 value: '{totem.config_version}',
186 hidden: '{!isInCluster}',
187 },
188 flex: 1,
189 },
190 {
191 xtype: 'displayfield',
192 fieldLabel: gettext('Number of Nodes'),
193 labelWidth: 120,
194 bind: {
195 value: '{nodecount}',
196 hidden: '{!isInCluster}',
197 },
198 flex: 1,
199 },
200 {
201 xtype: 'displayfield',
202 value: gettext('Standalone node - no cluster defined'),
203 bind: {
204 hidden: '{isInCluster}',
205 },
206 flex: 1,
207 },
208 ],
209 },
210 {
211 xtype: 'grid',
212 title: gettext('Cluster Nodes'),
213 autoScroll: true,
214 enableColumnHide: false,
215 controller: {
216 xclass: 'Ext.app.ViewController',
217
218 init: function(view) {
219 view.rstore = Ext.create('Proxmox.data.UpdateStore', {
220 autoLoad: true,
221 xtype: 'update',
222 interval: 5 * 1000,
223 autoStart: true,
224 storeid: 'pve-cluster-nodes',
225 model: 'pve-cluster-nodes',
226 });
227 view.setStore(Ext.create('Proxmox.data.DiffStore', {
228 rstore: view.rstore,
229 sorters: {
230 property: 'nodeid',
231 order: 'DESC',
232 },
233 }));
234 Proxmox.Utils.monStoreErrors(view, view.rstore);
235 view.rstore.on('load', this.onLoad, this);
236 view.on('destroy', view.rstore.stopUpdate);
237 },
238
239 onLoad: function(store, records, success) {
240 let view = this.getView();
241 let vm = this.getViewModel();
242
243 if (!success || !records || !records.length) {
244 vm.set('nodecount', 0);
245 return;
246 }
247 vm.set('nodecount', records.length);
248
249 // show/hide columns according to used links
250 let linkIndex = view.columns.length;
251 Ext.each(view.columns, (col, i) => {
252 if (col.linkNumber !== undefined) {
253 col.setHidden(true);
254 // save offset at which link columns start, so we can address them directly below
255 if (i < linkIndex) {
256 linkIndex = i;
257 }
258 }
259 });
260
261 PVE.Utils.forEachCorosyncLink(records[0].data,
262 (linknum, val) => {
263 if (linknum > 7) {
264 return;
265 }
266 view.columns[linkIndex + linknum].setHidden(false);
267 },
268 );
269 },
270 },
271 columns: {
272 items: [
273 {
274 header: gettext('Nodename'),
275 hidden: false,
276 dataIndex: 'name',
277 },
278 {
279 header: gettext('ID'),
280 minWidth: 100,
281 width: 100,
282 flex: 0,
283 hidden: false,
284 dataIndex: 'nodeid',
285 },
286 {
287 header: gettext('Votes'),
288 minWidth: 100,
289 width: 100,
290 flex: 0,
291 hidden: false,
292 dataIndex: 'quorum_votes',
293 },
294 {
295 header: Ext.String.format(gettext('Link {0}'), 0),
296 dataIndex: 'ring0_addr',
297 linkNumber: 0,
298 },
299 {
300 header: Ext.String.format(gettext('Link {0}'), 1),
301 dataIndex: 'ring1_addr',
302 linkNumber: 1,
303 },
304 {
305 header: Ext.String.format(gettext('Link {0}'), 2),
306 dataIndex: 'ring2_addr',
307 linkNumber: 2,
308 },
309 {
310 header: Ext.String.format(gettext('Link {0}'), 3),
311 dataIndex: 'ring3_addr',
312 linkNumber: 3,
313 },
314 {
315 header: Ext.String.format(gettext('Link {0}'), 4),
316 dataIndex: 'ring4_addr',
317 linkNumber: 4,
318 },
319 {
320 header: Ext.String.format(gettext('Link {0}'), 5),
321 dataIndex: 'ring5_addr',
322 linkNumber: 5,
323 },
324 {
325 header: Ext.String.format(gettext('Link {0}'), 6),
326 dataIndex: 'ring6_addr',
327 linkNumber: 6,
328 },
329 {
330 header: Ext.String.format(gettext('Link {0}'), 7),
331 dataIndex: 'ring7_addr',
332 linkNumber: 7,
333 },
334 ],
335 defaults: {
336 flex: 1,
337 hidden: true,
338 minWidth: 150,
339 },
340 },
341 },
342 ],
343 });