]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/FS.js
ui: cephfs: only allow CephFS creation if MDS is configured
[pve-manager.git] / www / manager6 / ceph / FS.js
1 /*jslint confusion: true */
2 Ext.define('PVE.CephCreateFS', {
3 extend: 'Proxmox.window.Edit',
4 alias: 'widget.pveCephCreateFS',
5
6 showTaskViewer: true,
7 //onlineHelp: 'pve_ceph_fs',
8
9 subject: 'Ceph FS',
10 isCreate: true,
11 method: 'POST',
12
13 setFSName: function(fsName) {
14 var me = this;
15
16 if (fsName === '' || fsName === undefined) {
17 fsName = 'cephfs';
18 }
19
20 me.url = "/nodes/" + me.nodename + "/ceph/fs/" + fsName;
21 },
22
23 items: [
24 {
25 xtype: 'textfield',
26 fieldLabel: gettext('Name'),
27 name: 'name',
28 value: 'cephfs',
29 listeners: {
30 change: function(f, value) {
31 this.up('pveCephCreateFS').setFSName(value);
32 }
33 },
34 submitValue: false, // already encoded in apicall URL
35 emptyText: 'cephfs'
36 },
37 {
38 xtype: 'proxmoxintegerfield',
39 fieldLabel: 'pg_num',
40 name: 'pg_num',
41 value: 64,
42 emptyText: 64,
43 minValue: 8,
44 maxValue: 32768,
45 allowBlank: false
46 },
47 {
48 xtype: 'proxmoxcheckbox',
49 fieldLabel: gettext('Add Storage'),
50 value: true,
51 name: 'add_storage'
52 }
53 ],
54
55 initComponent : function() {
56 var me = this;
57
58 if (!me.nodename) {
59 throw "no node name specified";
60 }
61 me.setFSName();
62
63 me.callParent();
64 }
65 });
66
67 Ext.define('PVE.CephCreateMDS', {
68 extend: 'Proxmox.window.Edit',
69 alias: 'widget.pveCephCreateMDS',
70
71 showProgress: true,
72 //onlineHelp: 'pve_ceph_mds',
73
74 subject: 'Ceph MDS',
75 isCreate: true,
76 method: 'POST',
77
78 setNode: function(nodename) {
79 var me = this;
80
81 me.nodename = nodename;
82 me.url = "/nodes/" + nodename + "/ceph/mds/" + nodename;
83 },
84
85 items: [
86 {
87 xtype: 'pveNodeSelector',
88 fieldLabel: gettext('Node'),
89 selectCurNode: true,
90 submitValue: false,
91 allowBlank: false,
92 listeners: {
93 change: function(f, value) {
94 this.up('pveCephCreateMDS').setNode(value);
95 }
96 }
97 }
98 ],
99
100 initComponent : function() {
101 var me = this;
102
103 if (!me.nodename) {
104 throw "no node name specified";
105 }
106 me.setNode(me.nodename);
107
108 me.callParent();
109 }
110 });
111
112 Ext.define('PVE.NodeCephFSPanel', {
113 extend: 'Ext.panel.Panel',
114 xtype: 'pveNodeCephFSPanel',
115 mixins: ['Proxmox.Mixin.CBind'],
116
117 title: gettext('CephFS'),
118 onlineHelp: 'chapter_pvecm',
119
120 border: false,
121 defaults: {
122 border: false,
123 cbind: {
124 nodename: '{nodename}'
125 }
126 },
127
128 viewModel: {
129 parent: null,
130 data: {
131 cephfsConfigured: false,
132 mdsCount: 0
133 },
134 formulas: {
135 canCreateFS: function(get) {
136 return (!get('cephfsConfigured') && get('mdsCount') > 0);
137 }
138 }
139 },
140
141 items: [
142 {
143 xtype: 'grid',
144 emptyText: Ext.String.format(gettext('No {0} configured.'), 'CephFS'),
145 controller: {
146 xclass: 'Ext.app.ViewController',
147
148 init: function(view) {
149 view.rstore = Ext.create('Proxmox.data.UpdateStore', {
150 autoLoad: true,
151 xtype: 'update',
152 interval: 5 * 1000,
153 autoStart: true,
154 storeid: 'pve-ceph-fs',
155 model: 'pve-ceph-fs'
156 });
157 view.setStore(Ext.create('Proxmox.data.DiffStore', {
158 rstore: view.rstore,
159 sorters: {
160 property: 'name',
161 order: 'DESC'
162 }
163 }));
164 Proxmox.Utils.monStoreErrors(view, view.rstore);
165 view.rstore.on('load', this.onLoad, this);
166 view.on('destroy', view.rstore.stopUpdate);
167 },
168
169 onCreate: function() {
170 var view = this.getView();
171 view.rstore.stopUpdate();
172 var win = Ext.create('PVE.CephCreateFS', {
173 autoShow: true,
174 nodename: view.nodename,
175 listeners: {
176 destroy: function() {
177 view.rstore.startUpdate();
178 }
179 }
180 });
181 },
182
183 onLoad: function(store, records, success) {
184 var vm = this.getViewModel();
185 if (!(success && records && records.length > 0)) {
186 vm.set('cephfsConfigured', false);
187 return;
188 }
189 vm.set('cephfsConfigured', true);
190 }
191 },
192 tbar: [
193 {
194 text: gettext('Create CephFS'),
195 reference: 'createButton',
196 handler: 'onCreate',
197 bind: {
198 // only one CephFS per Ceph cluster makes sense for now
199 disabled: '{!canCreateFS}'
200 }
201 }
202 ],
203 columns: [
204 {
205 header: gettext('Name'),
206 flex: 1,
207 dataIndex: 'name'
208 },
209 {
210 header: 'Data Pool',
211 flex: 1,
212 dataIndex: 'data_pool'
213 },
214 {
215 header: 'Metadata Pool',
216 flex: 1,
217 dataIndex: 'metadata_pool'
218 }
219 ],
220 cbind: {
221 nodename: '{nodename}'
222 }
223 },
224 {
225 xtype: 'grid',
226 title: gettext('Metadata Servers'),
227 emptyText: Ext.String.format(gettext('No {0} configured.'), 'MDS'),
228 controller: {
229 xclass: 'Ext.app.ViewController',
230
231 init: function(view) {
232 view.rstore = Ext.create('Proxmox.data.UpdateStore', {
233 autoLoad: true,
234 xtype: 'update',
235 interval: 3 * 1000,
236 autoStart: true,
237 storeid: 'pve-ceph-mds',
238 model: 'pve-ceph-mds'
239 });
240 view.setStore(Ext.create('Proxmox.data.DiffStore', {
241 rstore: view.rstore,
242 sorters: {
243 property: 'id',
244 order: 'DESC'
245 }
246 }));
247 Proxmox.Utils.monStoreErrors(view, view.rstore);
248 view.rstore.on('load', this.onLoad, this);
249 view.on('destroy', view.rstore.stopUpdate);
250 },
251 onLoad: function(store, records, success) {
252 var vm = this.getViewModel();
253 if (!success || !records) {
254 vm.set('mdsCount', 0);
255 return;
256 }
257 vm.set('mdsCount', records.length);
258 },
259 onCreateMDS: function() {
260 var view = this.getView();
261 view.rstore.stopUpdate();
262 var win = Ext.create('PVE.CephCreateMDS', {
263 autoShow: true,
264 nodename: view.nodename,
265 listeners: {
266 destroy: function() {
267 view.rstore.startUpdate();
268 }
269 }
270 });
271 }
272 },
273 tbar: [
274 {
275 text: gettext('Create MDS'),
276 reference: 'createButton',
277 handler: 'onCreateMDS'
278 },
279 {
280 text: gettext('Destroy MDS'),
281 xtype: 'proxmoxStdRemoveButton',
282 getUrl: function(rec) {
283 if (!rec.data.host) {
284 Ext.Msg.alert(gettext('Error'), "entry has no host");
285 return;
286 }
287 return "/nodes/" + rec.data.host + "/ceph/mds/" + rec.data.name;
288 },
289 callback: function(options, success, response) {
290 if (!success) {
291 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
292 return;
293 }
294 var upid = response.result.data;
295 var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
296 win.show();
297 }
298 }
299 ],
300 columns: [
301 {
302 header: gettext('Name'),
303 flex: 1,
304 dataIndex: 'name'
305 },
306 {
307 header: gettext('Host'),
308 flex: 1,
309 dataIndex: 'host'
310 },
311 {
312 header: gettext('Address'),
313 flex: 1,
314 dataIndex: 'addr'
315 },
316 {
317 header: gettext('State'),
318 flex: 1,
319 dataIndex: 'state'
320 }
321 ],
322 cbind: {
323 nodename: '{nodename}'
324 }
325 }
326 ]
327 }, function() {
328 Ext.define('pve-ceph-mds', {
329 extend: 'Ext.data.Model',
330 fields: [ 'name', 'host', 'addr', 'state' ],
331 proxy: {
332 type: 'proxmox',
333 url: "/api2/json/nodes/localhost/ceph/mds"
334 },
335 idProperty: 'name'
336 });
337 Ext.define('pve-ceph-fs', {
338 extend: 'Ext.data.Model',
339 fields: [ 'name', 'data_pool', 'metadata_pool' ],
340 proxy: {
341 type: 'proxmox',
342 url: "/api2/json/nodes/localhost/ceph/fs"
343 },
344 idProperty: 'name'
345 });
346 });