]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/Pool.js
ui: ceph/pool: allow autoscale on create
[pve-manager.git] / www / manager6 / ceph / Pool.js
1 Ext.define('PVE.CephCreatePool', {
2 extend: 'Proxmox.window.Edit',
3 alias: 'widget.pveCephCreatePool',
4
5 showProgress: true,
6 onlineHelp: 'pve_ceph_pools',
7
8 subject: 'Ceph Pool',
9 isCreate: true,
10 method: 'POST',
11 items: [
12 {
13 xtype: 'textfield',
14 fieldLabel: gettext('Name'),
15 name: 'name',
16 allowBlank: false
17 },
18 {
19 xtype: 'proxmoxintegerfield',
20 fieldLabel: gettext('Size'),
21 name: 'size',
22 value: 3,
23 minValue: 1,
24 maxValue: 7,
25 allowBlank: false
26 },
27 {
28 xtype: 'proxmoxintegerfield',
29 fieldLabel: gettext('Min. Size'),
30 name: 'min_size',
31 value: 2,
32 minValue: 1,
33 maxValue: 7,
34 allowBlank: false
35 },
36 {
37 xtype: 'pveCephRuleSelector',
38 fieldLabel: 'Crush Rule', // do not localize
39 name: 'crush_rule',
40 allowBlank: false
41 },
42 {
43 xtype: 'proxmoxintegerfield',
44 fieldLabel: 'pg_num',
45 name: 'pg_num',
46 value: 128,
47 minValue: 8,
48 maxValue: 32768,
49 allowBlank: true,
50 emptyText: gettext('Autoscale'),
51 },
52 {
53 xtype: 'proxmoxcheckbox',
54 fieldLabel: gettext('Add as Storage'),
55 value: true,
56 name: 'add_storages',
57 autoEl: {
58 tag: 'div',
59 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
60 },
61 }
62 ],
63 initComponent : function() {
64 /*jslint confusion: true */
65 var me = this;
66
67 if (!me.nodename) {
68 throw "no node name specified";
69 }
70
71 Ext.apply(me, {
72 url: "/nodes/" + me.nodename + "/ceph/pools",
73 defaults: {
74 nodename: me.nodename
75 }
76 });
77
78 me.callParent();
79 }
80 });
81
82 Ext.define('PVE.node.CephPoolList', {
83 extend: 'Ext.grid.GridPanel',
84 alias: 'widget.pveNodeCephPoolList',
85
86 onlineHelp: 'chapter_pveceph',
87
88 stateful: true,
89 stateId: 'grid-ceph-pools',
90 bufferedRenderer: false,
91
92 features: [ { ftype: 'summary'} ],
93
94 columns: [
95 {
96 header: gettext('Name'),
97 width: 120,
98 sortable: true,
99 dataIndex: 'pool_name'
100 },
101 {
102 header: gettext('Size') + '/min',
103 width: 100,
104 align: 'right',
105 renderer: function(v, meta, rec) {
106 return v + '/' + rec.data.min_size;
107 },
108 dataIndex: 'size'
109 },
110 {
111 text: 'Placement Groups',
112 columns: [
113 {
114 text: '# of PGs', // pg_num',
115 width: 150,
116 align: 'right',
117 dataIndex: 'pg_num'
118 },
119 {
120 text: gettext('Autoscale'),
121 width: 140,
122 align: 'right',
123 dataIndex: 'pg_autoscale_mode'
124 },
125 ]
126 },
127 {
128 text: 'CRUSH Rule',
129 columns: [
130 {
131 text: 'ID',
132 align: 'right',
133 width: 50,
134 dataIndex: 'crush_rule'
135 },
136 {
137 text: gettext('Name'),
138 width: 150,
139 dataIndex: 'crush_rule_name',
140 },
141 ]
142 },
143 {
144 text: gettext('Used'),
145 columns: [
146 {
147 text: '%',
148 width: 100,
149 sortable: true,
150 align: 'right',
151 renderer: function(val) {
152 return Ext.util.Format.percent(val, '0.00');
153 },
154 dataIndex: 'percent_used',
155 summaryType: 'sum',
156 summaryRenderer: function(val) {
157 return Ext.util.Format.percent(val, '0.00');
158 },
159 },
160 {
161 text: gettext('Total'),
162 width: 100,
163 sortable: true,
164 renderer: PVE.Utils.render_size,
165 align: 'right',
166 dataIndex: 'bytes_used',
167 summaryType: 'sum',
168 summaryRenderer: PVE.Utils.render_size
169 }
170 ]
171 }
172 ],
173 initComponent: function() {
174 var me = this;
175
176 var nodename = me.pveSelNode.data.node;
177 if (!nodename) {
178 throw "no node name specified";
179 }
180
181 var sm = Ext.create('Ext.selection.RowModel', {});
182
183 var rstore = Ext.create('Proxmox.data.UpdateStore', {
184 interval: 3000,
185 storeid: 'ceph-pool-list' + nodename,
186 model: 'ceph-pool-list',
187 proxy: {
188 type: 'proxmox',
189 url: "/api2/json/nodes/" + nodename + "/ceph/pools"
190 }
191 });
192
193 var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore });
194
195 var regex = new RegExp("not (installed|initialized)", "i");
196 PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
197 me.store.rstore.stopUpdate();
198 PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
199 function(win){
200 me.mon(win, 'cephInstallWindowClosed', function(){
201 me.store.rstore.startUpdate();
202 });
203 }
204 );
205 });
206
207 var create_btn = new Ext.Button({
208 text: gettext('Create'),
209 handler: function() {
210 var win = Ext.create('PVE.CephCreatePool', {
211 nodename: nodename
212 });
213 win.show();
214 win.on('destroy', function() {
215 rstore.load();
216 });
217 }
218 });
219
220 var destroy_btn = Ext.create('Proxmox.button.Button', {
221 text: gettext('Destroy'),
222 selModel: sm,
223 disabled: true,
224 handler: function() {
225 var rec = sm.getSelection()[0];
226
227 if (!rec.data.pool_name) {
228 return;
229 }
230 var base_url = '/nodes/' + nodename + '/ceph/pools/' +
231 rec.data.pool_name;
232
233 var win = Ext.create('PVE.window.SafeDestroy', {
234 showProgress: true,
235 url: base_url,
236 params: {
237 remove_storages: 1
238 },
239 item: { type: 'CephPool', id: rec.data.pool_name }
240 }).show();
241 win.on('destroy', function() {
242 rstore.load();
243 });
244 }
245 });
246
247 Ext.apply(me, {
248 store: store,
249 selModel: sm,
250 tbar: [ create_btn, destroy_btn ],
251 listeners: {
252 activate: () => rstore.startUpdate(),
253 destroy: () => rstore.stopUpdate(),
254 }
255 });
256
257 me.callParent();
258 }
259 }, function() {
260
261 Ext.define('ceph-pool-list', {
262 extend: 'Ext.data.Model',
263 fields: [ 'pool_name',
264 { name: 'pool', type: 'integer'},
265 { name: 'size', type: 'integer'},
266 { name: 'min_size', type: 'integer'},
267 { name: 'pg_num', type: 'integer'},
268 { name: 'bytes_used', type: 'integer'},
269 { name: 'percent_used', type: 'number'},
270 { name: 'crush_rule', type: 'integer'},
271 { name: 'crush_rule_name', type: 'string'}
272 ],
273 idProperty: 'pool_name'
274 });
275 });
276
277 Ext.define('PVE.form.CephRuleSelector', {
278 extend: 'Ext.form.field.ComboBox',
279 alias: 'widget.pveCephRuleSelector',
280
281 allowBlank: false,
282 valueField: 'name',
283 displayField: 'name',
284 editable: false,
285 queryMode: 'local',
286
287 initComponent: function() {
288 var me = this;
289
290 if (!me.nodename) {
291 throw "no nodename given";
292 }
293
294 var store = Ext.create('Ext.data.Store', {
295 fields: ['name'],
296 sorters: 'name',
297 proxy: {
298 type: 'proxmox',
299 url: '/api2/json/nodes/' + me.nodename + '/ceph/rules'
300 }
301 });
302
303 Ext.apply(me, {
304 store: store
305 });
306
307 me.callParent();
308
309 store.load({
310 callback: function(rec, op, success){
311 if (success && rec.length > 0) {
312 me.select(rec[0]);
313 }
314 }
315 });
316 }
317
318 });