]>
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 erase: 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');
100 Ext
.create('PBS.TapeManagement.EraseWindow', {
104 destroy: function() {
111 load: function(view
, rI
, cI
, button
, el
, record
) {
113 let vm
= me
.getViewModel();
114 let label
= record
.data
['label-text'];
116 let changer
= vm
.get('changer');
118 Ext
.create('Proxmox.window.Edit', {
121 submitText
: gettext('OK'),
122 title
: gettext('Load Media into Drive'),
123 url
: `/api2/extjs/tape/drive`,
126 submitUrl: function(url
, values
) {
127 let drive
= values
.drive
;
129 return `${url}/${encodeURIComponent(drive)}/load-media`;
133 xtype
: 'displayfield',
137 fieldLabel
: gettext('Media'),
140 xtype
: 'pbsDriveSelector',
141 fieldLabel
: gettext('Drive'),
147 destroy: function() {
154 unload
: async
function(view
, rI
, cI
, button
, el
, record
) {
156 let drive
= record
.data
.name
;
158 let response
= await PBS
.Async
.api2({
161 url
: `/api2/extjs/tape/drive/${encodeURIComponent(drive)}/unload`,
164 Ext
.create('Proxmox.window.TaskProgress', {
166 upid
: response
.result
.data
,
167 taskDone
: () => me
.reload(),
170 Ext
.Msg
.alert(gettext('Error'), error
);
175 driveCommand: function(driveid
, command
, callback
, params
, method
) {
177 let view
= me
.getView();
178 params
= params
|| {};
179 method
= method
|| 'GET';
180 Proxmox
.Utils
.API2Request({
181 url
: `/api2/extjs/tape/drive/${driveid}/${command}`,
186 success: function(response
) {
189 failure: function(response
) {
190 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
195 cartridgeMemory: function(view
, rI
, cI
, button
, el
, record
) {
197 let drive
= record
.data
.name
;
198 me
.driveCommand(drive
, 'cartridge-memory', function(response
) {
199 Ext
.create('Ext.window.Window', {
200 title
: gettext('Cartridge Memory'),
210 data
: response
.result
.data
,
219 text
: gettext('Name'),
224 text
: gettext('Value'),
235 cleanDrive: function(view
, rI
, cI
, button
, el
, record
) {
237 let drive
= record
.data
.name
;
238 me
.driveCommand(drive
, 'clean', function(response
) {
239 Ext
.create('Proxmox.window.TaskProgress', {
240 upid
: response
.result
.data
,
241 taskDone: function() {
248 volumeStatistics: function(view
, rI
, cI
, button
, el
, record
) {
250 let drive
= record
.data
.name
;
251 me
.driveCommand(drive
, 'volume-statistics', function(response
) {
252 Ext
.create('Ext.window.Window', {
253 title
: gettext('Volume Statistics'),
263 data
: response
.result
.data
,
272 text
: gettext('Name'),
277 text
: gettext('Value'),
288 readLabel: function(view
, rI
, cI
, button
, el
, record
) {
290 let drive
= record
.data
.name
;
291 me
.driveCommand(drive
, 'read-label', function(response
) {
293 for (const [key
, val
] of Object
.entries(response
.result
.data
)) {
294 lines
.push(`${key}: ${val}`);
297 let txt
= lines
.join('<br>');
300 title
: gettext('Label Information'),
307 status: function(view
, rI
, cI
, button
, el
, record
) {
309 let drive
= record
.data
.name
;
310 me
.driveCommand(drive
, 'status', function(response
) {
312 for (const [key
, val
] of Object
.entries(response
.result
.data
)) {
313 lines
.push(`${key}: ${val}`);
316 let txt
= lines
.join('<br>');
319 title
: gettext('Status'),
326 reloadList: function() {
328 me
.lookup('changerselector').getStore().load();
331 barcodeLabel: function() {
333 let vm
= me
.getViewModel();
334 let changer
= vm
.get('changer');
335 if (changer
=== '') {
339 Ext
.create('Proxmox.window.Edit', {
340 title
: gettext('Barcode Label'),
341 showTaskViewer
: true,
343 url
: '/api2/extjs/tape/drive',
344 submitUrl: function(url
, values
) {
345 let drive
= values
.drive
;
347 return `${url}/${encodeURIComponent(drive)}/barcode-label-media`;
352 xtype
: 'pbsDriveSelector',
353 fieldLabel
: gettext('Drive'),
358 xtype
: 'pbsMediaPoolSelector',
359 fieldLabel
: gettext('Pool'),
368 inventory: function() {
370 let vm
= me
.getViewModel();
371 let changer
= vm
.get('changer');
372 if (changer
=== '') {
376 Ext
.create('Proxmox.window.Edit', {
377 title
: gettext('Inventory'),
378 showTaskViewer
: true,
380 url
: '/api2/extjs/tape/drive',
381 submitUrl: function(url
, values
) {
382 let drive
= values
.drive
;
384 return `${url}/${encodeURIComponent(drive)}/inventory`;
389 xtype
: 'pbsDriveSelector',
390 fieldLabel
: gettext('Drive'),
399 this.reload_full(true);
402 reload_no_cache: function() {
403 this.reload_full(false);
406 reload_full
: async
function(use_cache
) {
408 let view
= me
.getView();
409 let vm
= me
.getViewModel();
410 let changer
= vm
.get('changer');
411 if (changer
=== '') {
416 Proxmox
.Utils
.setErrorMask(view
, true);
417 Proxmox
.Utils
.setErrorMask(me
.lookup('content'));
418 let status_fut
= PBS
.Async
.api2({
421 url
: `/api2/extjs/tape/changer/${encodeURIComponent(changer)}/status`,
426 let drives_fut
= PBS
.Async
.api2({
428 url
: `/api2/extjs/tape/drive?changer=${encodeURIComponent(changer)}`,
431 let tapes_fut
= PBS
.Async
.api2({
433 url
: '/api2/extjs/tape/media/list',
436 "update-status": false,
440 let [status
, drives
, tapes_list
] = await Promise
.all([status_fut
, drives_fut
, tapes_fut
]);
450 for (const tape
of tapes_list
.result
.data
) {
451 tapes
[tape
['label-text']] = {
454 status
: tape
.expired
? 'expired' : tape
.status
,
458 let drive_entries
= {};
460 for (const entry
of drives
.result
.data
) {
461 drive_entries
[entry
['changer-drivenum'] || 0] = entry
;
464 for (let entry
of status
.result
.data
) {
465 let type
= entry
['entry-kind'];
467 if (type
=== 'drive' && drive_entries
[entry
['entry-id']] !== undefined) {
468 entry
= Ext
.applyIf(entry
, drive_entries
[entry
['entry-id']]);
471 if (tapes
[entry
['label-text']] !== undefined) {
472 entry
['is-labeled'] = true;
473 entry
.pool
= tapes
[entry
['label-text']].pool
;
474 entry
.status
= tapes
[entry
['label-text']].status
;
476 entry
['is-labeled'] = false;
479 data
[type
].push(entry
);
483 me
.lookup('slots').getStore().setData(data
.slot
);
484 me
.lookup('import_export').getStore().setData(data
['import-export']);
485 me
.lookup('drives').getStore().setData(data
.drive
);
487 Proxmox
.Utils
.setErrorMask(view
);
489 Proxmox
.Utils
.setErrorMask(view
);
490 Proxmox
.Utils
.setErrorMask(me
.lookup('content'), err
);
494 renderIsLabeled: function(value
, mD
, record
) {
495 if (!record
.data
['label-text']) {
499 if (record
.data
['label-text'].startsWith("CLN")) {
504 return gettext('Not Labeled');
507 let status
= record
.data
.status
;
508 if (record
.data
.pool
) {
509 return `${status} (${record.data.pool})`;
514 renderState: function(value
, md
, record
) {
516 return gettext('Idle');
519 let icon
= '<i class="fa fa-spinner fa-pulse fa-fw"></i>';
521 if (value
.startsWith("UPID")) {
522 let upid
= Proxmox
.Utils
.parse_task_upid(value
);
523 md
.tdCls
= "pointer";
524 return `${icon} ${upid.desc}`;
527 return `${icon} ${value}`;
531 'grid[reference=drives]': {
532 cellclick: function(table
, td
, ci
, rec
, tr
, ri
, e
) {
533 if (e
.position
.column
.dataIndex
!== 'state') {
537 let upid
= rec
.data
.state
;
538 if (!upid
|| !upid
.startsWith("UPID")) {
542 Ext
.create('Proxmox.window.TaskViewer', {
557 fieldLabel
: gettext('Changer'),
558 xtype
: 'pbsChangerSelector',
559 reference
: 'changerselector',
562 change
: 'changerChange',
567 text
: gettext('Reload'),
568 xtype
: 'proxmoxButton',
569 handler
: 'reload_no_cache',
574 text
: gettext('Barcode Label'),
575 xtype
: 'proxmoxButton',
576 handler
: 'barcodeLabel',
577 iconCls
: 'fa fa-barcode',
579 disabled
: '{!changerSelected}',
583 text
: gettext('Inventory'),
584 xtype
: 'proxmoxButton',
585 handler
: 'inventory',
586 iconCls
: 'fa fa-book',
588 disabled
: '{!changerSelected}',
600 reference
: 'content',
609 title
: gettext('Slots'),
618 dataIndex
: 'entry-id',
622 text
: gettext("Content"),
623 dataIndex
: 'label-text',
625 renderer
: (value
) => value
|| '',
628 text
: gettext('Inventory'),
629 dataIndex
: 'is-labeled',
630 renderer
: 'renderIsLabeled',
634 text
: gettext('Actions'),
635 xtype
: 'actioncolumn',
639 iconCls
: 'fa fa-rotate-90 fa-exchange',
640 handler
: 'slotTransfer',
641 tooltip
: gettext('Transfer'),
642 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
645 iconCls
: 'fa fa-trash-o',
647 tooltip
: gettext('Erase'),
648 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
651 iconCls
: 'fa fa-rotate-90 fa-upload',
653 tooltip
: gettext('Load'),
654 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
670 title
: gettext('Drives'),
672 fields
: ['entry-id', 'label-text', 'model', 'name', 'vendor', 'serial'],
678 dataIndex
: 'entry-id',
683 text
: gettext("Content"),
684 dataIndex
: 'label-text',
686 renderer
: (value
) => value
|| '',
689 text
: gettext('Inventory'),
690 dataIndex
: 'is-labeled',
691 renderer
: 'renderIsLabeled',
695 text
: gettext("Name"),
699 renderer
: Ext
.htmlEncode
,
702 text
: gettext('State'),
705 renderer
: 'renderState',
708 text
: gettext("Vendor"),
713 renderer
: Ext
.htmlEncode
,
716 text
: gettext("Model"),
721 renderer
: Ext
.htmlEncode
,
724 text
: gettext("Serial"),
729 renderer
: Ext
.htmlEncode
,
732 xtype
: 'actioncolumn',
733 text
: gettext('Actions'),
737 iconCls
: 'fa fa-rotate-270 fa-upload',
739 tooltip
: gettext('Unload'),
740 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
743 iconCls
: 'fa fa-hdd-o',
744 handler
: 'cartridgeMemory',
745 tooltip
: gettext('Cartridge Memory'),
746 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
749 iconCls
: 'fa fa-line-chart',
750 handler
: 'volumeStatistics',
751 tooltip
: gettext('Volume Statistics'),
752 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
755 iconCls
: 'fa fa-tag',
756 handler
: 'readLabel',
757 tooltip
: gettext('Read Label'),
758 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],
761 iconCls
: 'fa fa-info-circle',
762 tooltip
: gettext('Status'),
766 iconCls
: 'fa fa-shower',
767 tooltip
: gettext('Clean Drive'),
768 handler
: 'cleanDrive',
776 reference
: 'import_export',
780 title
: gettext('Import-Export Slots'),
784 dataIndex
: 'entry-id',
788 text
: gettext("Content"),
789 dataIndex
: 'label-text',
790 renderer
: (value
) => value
|| '',
794 text
: gettext('Inventory'),
795 dataIndex
: 'is-labeled',
796 renderer
: 'renderIsLabeled',
800 text
: gettext('Actions'),
801 xtype
: 'actioncolumn',
804 iconCls
: 'fa fa-rotate-270 fa-upload',
805 handler
: 'importTape',
806 tooltip
: gettext('Import'),
807 isDisabled
: (v
, r
, c
, i
, rec
) => !rec
.data
['label-text'],