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