]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/node/LVM.js
ui: node: storage removal: add checkbox for cleaning up disks
[pve-manager.git] / www / manager6 / node / LVM.js
1 Ext.define('PVE.node.CreateLVM', {
2 extend: 'Proxmox.window.Edit',
3 xtype: 'pveCreateLVM',
4
5 onlineHelp: 'chapter_lvm',
6 subject: 'LVM Volume Group',
7
8 showProgress: true,
9 isCreate: true,
10
11 initComponent: function() {
12 let me = this;
13
14 if (!me.nodename) {
15 throw "no node name specified";
16 }
17
18 me.isCreate = true;
19
20 Ext.applyIf(me, {
21 url: `/nodes/${me.nodename}/disks/lvm`,
22 method: 'POST',
23 items: [
24 {
25 xtype: 'pmxDiskSelector',
26 name: 'device',
27 nodename: me.nodename,
28 diskType: 'unused',
29 fieldLabel: gettext('Disk'),
30 allowBlank: false,
31 },
32 {
33 xtype: 'proxmoxtextfield',
34 name: 'name',
35 fieldLabel: gettext('Name'),
36 allowBlank: false,
37 },
38 {
39 xtype: 'proxmoxcheckbox',
40 name: 'add_storage',
41 fieldLabel: gettext('Add Storage'),
42 value: '1',
43 },
44 ],
45 });
46
47 me.callParent();
48 },
49 });
50
51 Ext.define('PVE.node.LVMList', {
52 extend: 'Ext.tree.Panel',
53 xtype: 'pveLVMList',
54
55 viewModel: {
56 data: {
57 volumeGroup: '',
58 },
59 },
60
61 controller: {
62 xclass: 'Ext.app.ViewController',
63
64 destroyVolumeGroup: function() {
65 let me = this;
66 let vm = me.getViewModel();
67 let view = me.getView();
68
69 const volumeGroup = vm.get('volumeGroup');
70
71 if (!view.nodename) {
72 throw "no node name specified";
73 }
74
75 if (!volumeGroup) {
76 throw "no volume group specified";
77 }
78
79 Ext.create('PVE.window.SafeDestroyStorage', {
80 url: `/nodes/${view.nodename}/disks/lvm/${volumeGroup}`,
81 item: { id: volumeGroup },
82 taskName: 'lvmremove',
83 taskDone: () => { view.reload(); },
84 }).show();
85 },
86 },
87
88 emptyText: gettext('No Volume Groups found'),
89
90 stateful: true,
91 stateId: 'grid-node-lvm',
92
93 rootVisible: false,
94 useArrows: true,
95
96 columns: [
97 {
98 xtype: 'treecolumn',
99 text: gettext('Name'),
100 dataIndex: 'name',
101 flex: 1,
102 },
103 {
104 text: gettext('Number of LVs'),
105 dataIndex: 'lvcount',
106 width: 150,
107 align: 'right',
108 },
109 {
110 header: gettext('Usage'),
111 width: 110,
112 dataIndex: 'usage',
113 tdCls: 'x-progressbar-default-cell',
114 xtype: 'widgetcolumn',
115 widget: {
116 xtype: 'pveProgressBar',
117 },
118 },
119 {
120 header: gettext('Size'),
121 width: 100,
122 align: 'right',
123 sortable: true,
124 renderer: Proxmox.Utils.format_size,
125 dataIndex: 'size',
126 },
127 {
128 header: gettext('Free'),
129 width: 100,
130 align: 'right',
131 sortable: true,
132 renderer: Proxmox.Utils.format_size,
133 dataIndex: 'free',
134 },
135 ],
136
137 tbar: [
138 {
139 text: gettext('Reload'),
140 iconCls: 'fa fa-refresh',
141 handler: function() {
142 this.up('panel').reload();
143 },
144 },
145 {
146 text: gettext('Create') + ': Volume Group',
147 handler: function() {
148 let view = this.up('panel');
149 Ext.create('PVE.node.CreateLVM', {
150 nodename: view.nodename,
151 taskDone: () => view.reload(),
152 autoShow: true,
153 });
154 },
155 },
156 '->',
157 {
158 xtype: 'tbtext',
159 data: {
160 volumeGroup: undefined,
161 },
162 bind: {
163 data: {
164 volumeGroup: "{volumeGroup}",
165 },
166 },
167 tpl: [
168 '<tpl if="volumeGroup">',
169 'Volume group {volumeGroup}:',
170 '<tpl else>',
171 Ext.String.format(gettext('No {0} selected'), 'volume group'),
172 '</tpl>',
173 ],
174 },
175 {
176 text: gettext('More'),
177 iconCls: 'fa fa-bars',
178 disabled: true,
179 bind: {
180 disabled: '{!volumeGroup}',
181 },
182 menu: [
183 {
184 text: gettext('Destroy'),
185 itemId: 'remove',
186 iconCls: 'fa fa-fw fa-trash-o',
187 handler: 'destroyVolumeGroup',
188 disabled: true,
189 bind: {
190 disabled: '{!volumeGroup}',
191 },
192 },
193 ],
194 },
195 ],
196
197 reload: function() {
198 let me = this;
199 let sm = me.getSelectionModel();
200 Proxmox.Utils.API2Request({
201 url: `/nodes/${me.nodename}/disks/lvm`,
202 waitMsgTarget: me,
203 method: 'GET',
204 failure: (response, opts) => Proxmox.Utils.setErrorMask(me, response.htmlStatus),
205 success: function(response, opts) {
206 sm.deselectAll();
207 me.setRootNode(response.result.data);
208 me.expandAll();
209 },
210 });
211 },
212
213 listeners: {
214 activate: function() {
215 this.reload();
216 },
217 selectionchange: function(model, selected) {
218 let me = this;
219 let vm = me.getViewModel();
220
221 if (selected.length < 1 || selected[0].data.parentId !== 'root') {
222 vm.set('volumeGroup', '');
223 } else {
224 vm.set('volumeGroup', selected[0].data.name);
225 }
226 },
227 },
228
229 selModel: 'treemodel',
230 fields: [
231 'name',
232 'size',
233 'free',
234 {
235 type: 'string',
236 name: 'iconCls',
237 calculate: data => `fa x-fa-tree fa-${data.leaf ? 'hdd-o' : 'object-group'}`,
238 },
239 {
240 type: 'number',
241 name: 'usage',
242 calculate: data => (data.size - data.free) / data.size,
243 },
244 ],
245 sorters: 'name',
246
247 initComponent: function() {
248 let me = this;
249
250 me.nodename = me.pveSelNode.data.node;
251 if (!me.nodename) {
252 throw "no node name specified";
253 }
254 me.callParent();
255
256 me.reload();
257 },
258 });
259