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