]>
git.proxmox.com Git - proxmox-backup.git/blob - www/tape/ChangerStatus.js
1 Ext
.define('PBS.TapeManagement.ChangerStatus', {
2 extend
: 'Ext.panel.Panel',
3 alias
: 'widget.pbsChangerStatus',
11 changerSelected
: (get) => get('changer') !== '',
16 xclass
: 'Ext.app.ViewController',
18 changerChange: function(field
, value
) {
20 let view
= me
.getView();
21 let vm
= me
.getViewModel();
22 vm
.set('changer', value
);
28 importTape: function(view
, rI
, cI
, button
, el
, record
) {
30 let vm
= me
.getViewModel();
31 let from = record
.data
['entry-id'];
32 let changer
= encodeURIComponent(vm
.get('changer'));
33 Ext
.create('Proxmox.window.Edit', {
34 title
: gettext('Import'),
36 submitText
: gettext('OK'),
38 url
: `/api2/extjs/tape/changer/${changer}/transfer`,
41 xtype
: 'displayfield',
45 fieldLabel
: gettext('From Slot'),
48 xtype
: 'proxmoxintegerfield',
50 fieldLabel
: gettext('To Slot'),
61 slotTransfer: function(view
, rI
, cI
, button
, el
, record
) {
63 let vm
= me
.getViewModel();
64 let from = record
.data
['entry-id'];
65 let changer
= encodeURIComponent(vm
.get('changer'));
66 Ext
.create('Proxmox.window.Edit', {
67 title
: gettext('Transfer'),
69 submitText
: gettext('OK'),
71 url
: `/api2/extjs/tape/changer/${changer}/transfer`,
74 xtype
: 'displayfield',
78 fieldLabel
: gettext('From Slot'),
81 xtype
: 'proxmoxintegerfield',
83 fieldLabel
: gettext('To Slot'),
94 load: function(view
, rI
, cI
, button
, el
, record
) {
96 let vm
= me
.getViewModel();
97 let label
= record
.data
['label-text'];
99 let changer
= vm
.get('changer');
101 Ext
.create('Proxmox.window.Edit', {
103 submitText
: gettext('OK'),
104 title
: gettext('Load Media into Drive'),
105 url
: `/api2/extjs/tape/drive`,
106 submitUrl: function(url
, values
) {
107 let drive
= values
.drive
;
109 return `${url}/${encodeURIComponent(drive)}/load-media`;
113 xtype
: 'displayfield',
117 fieldLabel
: gettext('Media'),
120 xtype
: 'pbsDriveSelector',
121 fieldLabel
: gettext('Drive'),
127 destroy: function() {
134 unload
: async
function(view
, rI
, cI
, button
, el
, record
) {
136 let drive
= record
.data
.name
;
137 Proxmox
.Utils
.setErrorMask(view
, true);
139 await PBS
.Async
.api2({
141 url
: `/api2/extjs/tape/drive/${encodeURIComponent(drive)}/unload`,
143 Proxmox
.Utils
.setErrorMask(view
);
146 Ext
.Msg
.alert(gettext('Error'), error
);
147 Proxmox
.Utils
.setErrorMask(view
);
152 driveCommand: function(driveid
, command
, callback
, params
, method
) {
154 let view
= me
.getView();
155 params
= params
|| {};
156 method
= method
|| 'GET';
157 Proxmox
.Utils
.API2Request({
158 url
: `/api2/extjs/tape/drive/${driveid}/${command}`,
162 success: function(response
) {
165 failure: function(response
) {
166 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
171 cartridgeMemory: function(view
, rI
, cI
, button
, el
, record
) {
173 let drive
= record
.data
.name
;
174 me
.driveCommand(drive
, 'cartridge-memory', function(response
) {
175 Ext
.create('Ext.window.Window', {
176 title
: gettext('Cartridge Memory'),
186 data
: response
.result
.data
,
195 text
: gettext('Name'),
200 text
: gettext('Value'),
211 cleanDrive: function(view
, rI
, cI
, button
, el
, record
) {
213 let drive
= record
.data
.name
;
214 me
.driveCommand(drive
, 'clean', function(response
) {
215 Ext
.create('Proxmox.window.TaskProgress', {
216 upid
: response
.result
.data
,
217 taskDone: function() {
224 volumeStatistics: function(view
, rI
, cI
, button
, el
, record
) {
226 let drive
= record
.data
.name
;
227 me
.driveCommand(drive
, 'volume-statistics', function(response
) {
228 Ext
.create('Ext.window.Window', {
229 title
: gettext('Volume Statistics'),
239 data
: response
.result
.data
,
248 text
: gettext('Name'),
253 text
: gettext('Value'),
264 readLabel: function(view
, rI
, cI
, button
, el
, record
) {
266 let drive
= record
.data
.name
;
267 me
.driveCommand(drive
, 'read-label', function(response
) {
269 for (const [key
, val
] of Object
.entries(response
.result
.data
)) {
270 lines
.push(`${key}: ${val}`);
273 let txt
= lines
.join('<br>');
276 title
: gettext('Label Information'),
283 status: function(view
, rI
, cI
, button
, el
, record
) {
285 let drive
= record
.data
.name
;
286 me
.driveCommand(drive
, 'status', function(response
) {
288 for (const [key
, val
] of Object
.entries(response
.result
.data
)) {
289 lines
.push(`${key}: ${val}`);
292 let txt
= lines
.join('<br>');
295 title
: gettext('Status'),
302 reloadList: function() {
304 me
.lookup('changerselector').getStore().load();
307 barcodeLabel: function() {
309 let vm
= me
.getViewModel();
310 let changer
= vm
.get('changer');
311 if (changer
=== '') {
315 Ext
.create('Proxmox.window.Edit', {
316 title
: gettext('Barcode Label'),
317 showTaskViewer
: true,
319 url
: '/api2/extjs/tape/drive',
320 submitUrl: function(url
, values
) {
321 let drive
= values
.drive
;
323 return `${url}/${encodeURIComponent(drive)}/barcode-label-media`;
328 xtype
: 'pbsDriveSelector',
329 fieldLabel
: gettext('Drive'),
334 xtype
: 'pbsMediaPoolSelector',
335 fieldLabel
: gettext('Pool'),
344 inventory: function() {
346 let vm
= me
.getViewModel();
347 let changer
= vm
.get('changer');
348 if (changer
=== '') {
352 Ext
.create('Proxmox.window.Edit', {
353 title
: gettext('Inventory'),
354 showTaskViewer
: true,
356 url
: '/api2/extjs/tape/drive',
357 submitUrl: function(url
, values
) {
358 let drive
= values
.drive
;
360 return `${url}/${encodeURIComponent(drive)}/inventory`;
365 xtype
: 'pbsDriveSelector',
366 fieldLabel
: gettext('Drive'),
374 reload
: async
function() {
376 let view
= me
.getView();
377 let vm
= me
.getViewModel();
378 let changer
= vm
.get('changer');
379 if (changer
=== '') {
384 Proxmox
.Utils
.setErrorMask(view
, true);
385 Proxmox
.Utils
.setErrorMask(me
.lookup('content'));
386 let status_fut
= PBS
.Async
.api2({
387 url
: `/api2/extjs/tape/changer/${encodeURIComponent(changer)}/status`,
389 let drives_fut
= PBS
.Async
.api2({
390 url
: `/api2/extjs/tape/drive?changer=${encodeURIComponent(changer)}`,
393 let tapes_fut
= PBS
.Async
.api2({
394 url
: '/api2/extjs/tape/media/list',
397 let [status
, drives
, tapes_list
] = await Promise
.all([status_fut
, drives_fut
, tapes_fut
]);
407 for (const tape
of tapes_list
.result
.data
) {
408 tapes
[tape
['label-text']] = {
411 status
: tape
.expired
? 'expired' : tape
.status
,
415 let drive_entries
= {};
417 for (const entry
of drives
.result
.data
) {
418 drive_entries
[entry
['changer-drivenum'] || 0] = entry
;
421 for (let entry
of status
.result
.data
) {
422 let type
= entry
['entry-kind'];
424 if (type
=== 'drive' && drive_entries
[entry
['entry-id']] !== undefined) {
425 entry
= Ext
.applyIf(entry
, drive_entries
[entry
['entry-id']]);
428 if (tapes
[entry
['label-text']] !== undefined) {
429 entry
['is-labeled'] = true;
430 entry
.pool
= tapes
[entry
['label-text']].pool
;
431 entry
.status
= tapes
[entry
['label-text']].status
;
433 entry
['is-labeled'] = false;
436 data
[type
].push(entry
);
440 me
.lookup('slots').getStore().setData(data
.slot
);
441 me
.lookup('import_export').getStore().setData(data
['import-export']);
442 me
.lookup('drives').getStore().setData(data
.drive
);
444 Proxmox
.Utils
.setErrorMask(view
);
446 Proxmox
.Utils
.setErrorMask(view
);
447 Proxmox
.Utils
.setErrorMask(me
.lookup('content'), err
);
458 fieldLabel
: gettext('Changer'),
459 xtype
: 'pbsChangerSelector',
460 reference
: 'changerselector',
463 change
: 'changerChange',
468 text
: gettext('Reload'),
469 xtype
: 'proxmoxButton',
475 text
: gettext('Barcode Label'),
476 xtype
: 'proxmoxButton',
477 handler
: 'barcodeLabel',
478 iconCls
: 'fa fa-barcode',
480 disabled
: '{!changerSelected}',
484 text
: gettext('Inventory'),
485 xtype
: 'proxmoxButton',
486 handler
: 'inventory',
487 iconCls
: 'fa fa-book',
489 disabled
: '{!changerSelected}',
501 reference
: 'content',
510 title
: gettext('Slots'),
518 text
: gettext('Slot'),
519 dataIndex
: 'entry-id',
523 text
: gettext("Content"),
524 dataIndex
: 'label-text',
526 renderer
: (value
) => value
|| '',
529 text
: gettext('Inventory'),
530 dataIndex
: 'is-labeled',
532 renderer: function(value
, mD
, record
) {
533 if (!record
.data
['label-text']) {
537 if (record
.data
['label-text'].startsWith("CLN")) {
542 return gettext('Not Labeled');
545 let status
= record
.data
.status
;
546 if (record
.data
.pool
) {
547 return `${status} (${record.data.pool})`;
553 text
: gettext('Actions'),
554 xtype
: 'actioncolumn',
558 iconCls
: 'fa fa-rotate-90 fa-exchange',
559 handler
: 'slotTransfer',
560 tooltip
: gettext('Transfer'),
561 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
564 iconCls
: 'fa fa-rotate-90 fa-upload',
566 tooltip
: gettext('Load'),
567 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
583 title
: gettext('Drives'),
585 fields
: ['entry-id', 'label-text', 'model', 'name', 'vendor', 'serial'],
590 text
: gettext('Slot'),
591 dataIndex
: 'entry-id',
595 text
: gettext("Content"),
596 dataIndex
: 'label-text',
598 renderer
: (value
) => value
|| '',
601 text
: gettext("Name"),
605 renderer
: Ext
.htmlEncode
,
608 text
: gettext("Vendor"),
612 renderer
: Ext
.htmlEncode
,
615 text
: gettext("Model"),
619 renderer
: Ext
.htmlEncode
,
622 text
: gettext("Serial"),
626 renderer
: Ext
.htmlEncode
,
629 xtype
: 'actioncolumn',
630 text
: gettext('Actions'),
634 iconCls
: 'fa fa-rotate-270 fa-upload',
636 tooltip
: gettext('Unload'),
637 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
640 iconCls
: 'fa fa-hdd-o',
641 handler
: 'cartridgeMemory',
642 tooltip
: gettext('Cartridge Memory'),
643 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
646 iconCls
: 'fa fa-line-chart',
647 handler
: 'volumeStatistics',
648 tooltip
: gettext('Volume Statistics'),
649 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
652 iconCls
: 'fa fa-tag',
653 handler
: 'readLabel',
654 tooltip
: gettext('Read Label'),
655 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
658 iconCls
: 'fa fa-info-circle',
659 tooltip
: gettext('Status'),
663 iconCls
: 'fa fa-shower',
664 tooltip
: gettext('Clean Drive'),
665 handler
: 'cleanDrive',
673 reference
: 'import_export',
677 title
: gettext('Import-Export'),
680 text
: gettext('Slot'),
681 dataIndex
: 'entry-id',
685 text
: gettext("Content"),
686 dataIndex
: 'label-text',
687 renderer
: (value
) => value
|| '',
691 text
: gettext('Actions'),
692 xtype
: 'actioncolumn',
695 iconCls
: 'fa fa-rotate-270 fa-upload',
696 handler
: 'importTape',
697 tooltip
: gettext('Import'),
698 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],