]>
Commit | Line | Data |
---|---|---|
462f0688 DM |
1 | Ext.define('pmg-cluster', { |
2 | extend: 'Ext.data.Model', | |
3 | fields: [ | |
4 | 'type', 'name', 'ip', 'hostrsapubkey', 'rootrsapubkey', | |
96a898b1 DM |
5 | 'fingerprint', { type: 'integer', name: 'cid' }, |
6 | { type: 'boolean', name: 'insync' }, | |
24e6dc95 | 7 | 'memory', 'loadavg', 'uptime', 'rootfs', 'conn_error', 'level', |
c87d46fb TL |
8 | { |
9 | type: 'number', name: 'memory_per', | |
a6f800c4 DM |
10 | calculate: function(data) { |
11 | var mem = data.memory; | |
12 | return Ext.isObject(mem) ? mem.used/mem.total : 0; | |
c87d46fb | 13 | }, |
a6f800c4 | 14 | }, |
c87d46fb TL |
15 | { |
16 | type: 'number', name: 'rootfs_per', | |
a6f800c4 DM |
17 | calculate: function(data) { |
18 | var du = data.rootfs; | |
19 | return Ext.isObject(du) ? du.used/du.total : 0; | |
c87d46fb TL |
20 | }, |
21 | }, | |
462f0688 DM |
22 | ], |
23 | proxy: { | |
24 | type: 'proxmox', | |
c87d46fb | 25 | url: "/api2/json/config/cluster/status", |
462f0688 | 26 | }, |
c87d46fb | 27 | idProperty: 'cid', |
462f0688 DM |
28 | }); |
29 | ||
c6a1bc6b DM |
30 | Ext.define('PMG.ClusterJoinNodeWindow', { |
31 | extend: 'Proxmox.window.Edit', | |
32 | xtype: 'pmgClusterJoinNodeWindow', | |
573a6e8b | 33 | onlineHelp: 'pmgcm_join', |
c6a1bc6b DM |
34 | |
35 | title: gettext('Cluster Join'), | |
36 | ||
37 | width: 800, | |
38 | ||
39 | method: 'POST', | |
40 | ||
41 | url: '/config/cluster/join', | |
42 | ||
43 | items: [ | |
44 | { | |
45 | xtype: 'textfield', | |
46 | fieldLabel: 'IP Address', | |
c87d46fb | 47 | name: 'master_ip', |
c6a1bc6b DM |
48 | }, |
49 | { | |
50 | xtype: 'textfield', | |
51 | inputType: 'password', | |
52 | fieldLabel: gettext('Password'), | |
c87d46fb | 53 | name: 'password', |
c6a1bc6b DM |
54 | }, |
55 | { | |
56 | xtype: 'textfield', | |
57 | fieldLabel: gettext('Fingerprint'), | |
c87d46fb TL |
58 | name: 'fingerprint', |
59 | }, | |
60 | ], | |
c6a1bc6b DM |
61 | }); |
62 | ||
ee138d2d DM |
63 | Ext.define('PMG.ClusterAddNodeWindow', { |
64 | extend: 'Ext.window.Window', | |
65 | xtype: 'pmgClusterAddNodeWindow', | |
66 | mixins: ['Proxmox.Mixin.CBind'], | |
67 | ||
68 | width: 800, | |
69 | ||
70 | modal: true, | |
71 | ||
c6a1bc6b | 72 | title: gettext('Cluster Join') + ' : ' + gettext('Information'), |
ee138d2d DM |
73 | |
74 | ipAddress: undefined, | |
75 | ||
76 | fingerprint: undefined, | |
77 | ||
78 | items: [ | |
79 | { | |
80 | xtype: 'component', | |
81 | border: false, | |
de0ebd99 | 82 | padding: '10 10 10 10', |
c87d46fb | 83 | html: gettext("Please use the 'Join' button on the node you want to add, using the following IP address and fingerprint."), |
ee138d2d DM |
84 | }, |
85 | { | |
86 | xtype: 'container', | |
87 | layout: 'form', | |
88 | border: false, | |
89 | padding: '0 10 10 10', | |
90 | items: [ | |
91 | { | |
92 | xtype: 'textfield', | |
93 | fieldLabel: gettext('IP Address'), | |
94 | cbind: { value: '{ipAddress}' }, | |
c87d46fb | 95 | editable: false, |
ee138d2d DM |
96 | }, |
97 | { | |
98 | xtype: 'textfield', | |
99 | fieldLabel: gettext('Fingerprint'), | |
100 | cbind: { value: '{fingerprint}' }, | |
c87d46fb TL |
101 | editable: false, |
102 | }, | |
103 | ], | |
104 | }, | |
105 | ], | |
ee138d2d DM |
106 | }); |
107 | ||
462f0688 DM |
108 | Ext.define('PMG.ClusterAdministration', { |
109 | extend: 'Ext.tab.Panel', | |
c77675e9 | 110 | xtype: 'pmgClusterAdministration', |
462f0688 DM |
111 | |
112 | title: gettext('Cluster Administration'), | |
113 | ||
114 | border: false, | |
115 | defaults: { border: false }, | |
116 | ||
c745a875 DM |
117 | viewModel: { |
118 | parent: null, | |
119 | data: { | |
120 | nodecount: 0, | |
c87d46fb TL |
121 | master: null, |
122 | }, | |
c745a875 DM |
123 | }, |
124 | ||
125 | items: [ | |
462f0688 DM |
126 | { |
127 | xtype: 'grid', | |
128 | title: gettext('Nodes'), | |
129 | controller: { | |
130 | xclass: 'Ext.app.ViewController', | |
131 | ||
132 | init: function(view) { | |
133 | view.store.on('load', this.onLoad, this); | |
285cb4be | 134 | Proxmox.Utils.monStoreErrors(view, view.getStore(), true); |
462f0688 DM |
135 | }, |
136 | ||
201f1b70 | 137 | onLoad: function(store, records, success) { |
c745a875 | 138 | var vm = this.getViewModel(); |
201f1b70 DC |
139 | if (!success || !records) { |
140 | return; | |
141 | } | |
c745a875 | 142 | vm.set('nodecount', records.length); |
462f0688 | 143 | |
c6a1bc6b | 144 | var master = null; |
462f0688 | 145 | Ext.Array.each(records, function(ni) { |
462f0688 | 146 | if (ni.data.type === 'master') { |
c745a875 | 147 | master = ni; |
462f0688 DM |
148 | } |
149 | }); | |
c745a875 DM |
150 | vm.set('master', master); |
151 | }, | |
462f0688 | 152 | |
c6a1bc6b DM |
153 | onCreate: function() { |
154 | var view = this.getView(); | |
155 | ||
156 | Proxmox.Utils.API2Request({ | |
157 | url: '/config/cluster/create', | |
158 | method: 'POST', | |
159 | waitMsgTarget: view, | |
c87d46fb | 160 | failure: function(response, opts) { |
c6a1bc6b DM |
161 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); |
162 | }, | |
163 | success: function(response, options) { | |
164 | var upid = response.result.data; | |
165 | var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid }); | |
166 | win.show(); | |
167 | win.on('destroy', function() { view.store.load(); }); | |
c87d46fb | 168 | }, |
c6a1bc6b DM |
169 | }); |
170 | }, | |
171 | ||
172 | onJoin: function() { | |
c6a1bc6b DM |
173 | var win = Ext.create('PMG.ClusterJoinNodeWindow', {}); |
174 | win.show(); | |
175 | win.on('destroy', function() { | |
176 | // fixme: logout | |
177 | }); | |
178 | }, | |
179 | ||
c745a875 DM |
180 | onAdd: function() { |
181 | var vm = this.getViewModel(); | |
ee138d2d DM |
182 | |
183 | var win = Ext.create('PMG.ClusterAddNodeWindow', { | |
184 | ipAddress: vm.get('master').get('ip'), | |
c87d46fb | 185 | fingerprint: vm.get('master').get('fingerprint'), |
c745a875 | 186 | }); |
ee138d2d | 187 | |
c745a875 | 188 | win.show(); |
c87d46fb | 189 | }, |
462f0688 DM |
190 | }, |
191 | store: { | |
192 | autoLoad: true, | |
ad80b560 | 193 | model: 'pmg-cluster', |
c87d46fb | 194 | sorters: ['cid'], |
462f0688 DM |
195 | }, |
196 | tbar: [ | |
197 | { | |
c745a875 | 198 | text: gettext('Create'), |
462f0688 | 199 | reference: 'createButton', |
c6a1bc6b | 200 | handler: 'onCreate', |
c745a875 | 201 | bind: { |
c87d46fb TL |
202 | disabled: '{nodecount}', |
203 | }, | |
c745a875 DM |
204 | }, |
205 | { | |
206 | text: gettext('Add'), | |
207 | reference: 'addButton', | |
208 | handler: 'onAdd', | |
209 | bind: { | |
c87d46fb TL |
210 | disabled: '{!master}', |
211 | }, | |
c745a875 DM |
212 | }, |
213 | { | |
214 | text: gettext('Join'), | |
215 | reference: 'joinButton', | |
c6a1bc6b | 216 | handler: 'onJoin', |
c745a875 | 217 | bind: { |
c87d46fb TL |
218 | disabled: '{nodecount}', |
219 | }, | |
220 | }, | |
462f0688 DM |
221 | ], |
222 | columns: [ | |
223 | { | |
224 | header: gettext('Node'), | |
225 | width: 150, | |
c87d46fb | 226 | dataIndex: 'name', |
462f0688 DM |
227 | }, |
228 | { | |
229 | header: gettext('Role'), | |
230 | width: 100, | |
c87d46fb | 231 | dataIndex: 'type', |
462f0688 DM |
232 | }, |
233 | { | |
234 | header: gettext('ID'), | |
235 | width: 80, | |
c87d46fb | 236 | dataIndex: 'cid', |
462f0688 DM |
237 | }, |
238 | { | |
239 | ||
240 | header: gettext('IP'), | |
241 | width: 150, | |
c87d46fb | 242 | dataIndex: 'ip', |
462f0688 | 243 | }, |
96a898b1 DM |
244 | { |
245 | header: gettext('State'), | |
ef7b87d8 | 246 | width: 100, |
96a898b1 DM |
247 | renderer: function(value, metaData, record) { |
248 | var d = record.data; | |
249 | var state = 'active'; | |
c17f9fe4 DC |
250 | if (!d.insync) { |
251 | state = 'syncing'; | |
252 | } | |
96a898b1 DM |
253 | if (d.conn_error) { |
254 | metaData.tdCls = 'x-form-invalid-field'; | |
c87d46fb | 255 | var html = '<p>' + Ext.htmlEncode(d.conn_error) + '</p>'; |
96a898b1 DM |
256 | html = html.replace(/\n/g, '<br>'); |
257 | metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' + | |
28eb60c0 | 258 | html.replace(/"/g, '"') + '"'; |
96a898b1 DM |
259 | state = 'error'; |
260 | } | |
261 | return state; | |
262 | }, | |
c87d46fb | 263 | dataIndex: 'insync', |
96a898b1 | 264 | }, |
24e6dc95 DM |
265 | { |
266 | header: gettext('Subscription'), | |
267 | width: 120, | |
268 | renderer: Proxmox.Utils.format_subscription_level, | |
c87d46fb | 269 | dataIndex: 'level', |
24e6dc95 | 270 | }, |
96a898b1 DM |
271 | { |
272 | header: gettext('Uptime'), | |
ef7b87d8 | 273 | width: 150, |
96a898b1 | 274 | renderer: Proxmox.Utils.render_uptime, |
c87d46fb | 275 | dataIndex: 'uptime', |
96a898b1 DM |
276 | }, |
277 | { | |
278 | header: gettext('Load average'), | |
279 | renderer: function(value) { | |
d7dd1562 DM |
280 | if (Ext.isDefined(value)) { |
281 | if (Ext.isArray(value)) { | |
282 | return value[0]; | |
283 | } | |
284 | return value.toString(); | |
96a898b1 | 285 | } |
d7dd1562 | 286 | return ''; |
96a898b1 | 287 | }, |
c87d46fb | 288 | dataIndex: 'loadavg', |
96a898b1 DM |
289 | }, |
290 | { | |
a6f800c4 DM |
291 | xtype: 'widgetcolumn', |
292 | widget: { | |
293 | xtype: 'progressbarwidget', | |
c87d46fb | 294 | textTpl: '{value:percent}', |
96a898b1 | 295 | }, |
a6f800c4 | 296 | header: gettext('RAM usage'), |
c87d46fb | 297 | dataIndex: 'memory_per', |
96a898b1 DM |
298 | }, |
299 | { | |
a6f800c4 DM |
300 | xtype: 'widgetcolumn', |
301 | widget: { | |
302 | xtype: 'progressbarwidget', | |
c87d46fb | 303 | textTpl: '{value:percent}', |
96a898b1 | 304 | }, |
a6f800c4 | 305 | header: gettext('HD space'), |
c87d46fb TL |
306 | dataIndex: 'rootfs_per', |
307 | }, | |
308 | ], | |
309 | }, | |
310 | ], | |
462f0688 | 311 | }); |