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