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