mirror of
https://git.proxmox.com/git/proxmox-backup
synced 2025-05-03 07:03:23 +00:00

to avoid drifting definitions and reduce duplication. with the next major release, the 'upid' field could then be renamed and aliased to be in line with the other jobs, which all use 'last-run-upid'. doing it now would break existing callers of the GC status endpoint (or consumers of the on-disk status file). the main difference is that the GC status fields are now not optional (except for the UPID) in the job status, since flattening an optional value is not possible. this only affects datastores that were never GCed at all, and only direct API consumers, since the UI handles those fields correctly. Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
248 lines
5.5 KiB
JavaScript
248 lines
5.5 KiB
JavaScript
Ext.define('pbs-gc-jobs-status', {
|
|
extend: 'Ext.data.Model',
|
|
fields: [
|
|
'store', 'upid', 'removed-bytes', 'pending-bytes', 'schedule',
|
|
'next-run', 'last-run-endtime', 'last-run-state',
|
|
{
|
|
name: 'duration',
|
|
calculate: function(data) {
|
|
let endtime = data['last-run-endtime'];
|
|
if (!endtime) return undefined;
|
|
let task = Proxmox.Utils.parse_task_upid(data['upid']);
|
|
return endtime - task.starttime;
|
|
},
|
|
},
|
|
],
|
|
idProperty: 'store',
|
|
proxy: {
|
|
type: 'proxmox',
|
|
url: '/api2/json/admin/gc',
|
|
},
|
|
});
|
|
|
|
Ext.define('PBS.config.GCJobView', {
|
|
extend: 'Ext.grid.GridPanel',
|
|
alias: 'widget.pbsGCJobView',
|
|
|
|
stateful: true,
|
|
stateId: 'grid-gc-jobs-v1',
|
|
allowDeselect: false,
|
|
|
|
title: gettext('Garbage Collect Jobs'),
|
|
|
|
controller: {
|
|
xclass: 'Ext.app.ViewController',
|
|
|
|
init: function(view) {
|
|
let params = {};
|
|
let store = view.getStore();
|
|
let proxy = store.rstore.getProxy();
|
|
if (view.datastore) {
|
|
params.store = view.datastore;
|
|
|
|
// after the store is loaded, select the row to enable the Edit,.. buttons
|
|
store.rstore.proxy.on({
|
|
'afterload': {
|
|
fn: () => view.getSelectionModel().select(0),
|
|
single: true,
|
|
},
|
|
});
|
|
|
|
// do not highlight the selected row
|
|
view.items.items[0].selectedItemCls = '';
|
|
view.items.items[0].overItemCls = '';
|
|
}
|
|
proxy.setExtraParams(params);
|
|
Proxmox.Utils.monStoreErrors(view, store.rstore);
|
|
},
|
|
|
|
getDatastoreName: function() {
|
|
return this.getView().getSelection()[0]?.data.store;
|
|
},
|
|
|
|
getData: function() {
|
|
let view = this.getView();
|
|
let datastore = this.getDatastoreName();
|
|
return view.getStore().getById(datastore).data;
|
|
},
|
|
|
|
editGCJob: function() {
|
|
let data = this.getData();
|
|
Ext.create('PBS.window.GCJobEdit', {
|
|
datastore: data.store,
|
|
id: data.store,
|
|
schedule: data.schedule,
|
|
listeners: {
|
|
destroy: () => this.reload(),
|
|
},
|
|
}).show();
|
|
},
|
|
|
|
garbageCollect: function() {
|
|
let datastore = this.getDatastoreName();
|
|
Proxmox.Utils.API2Request({
|
|
url: `/admin/datastore/${datastore}/gc`,
|
|
method: 'POST',
|
|
failure: function(response) {
|
|
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
|
|
},
|
|
success: function(response, options) {
|
|
Ext.create('Proxmox.window.TaskViewer', {
|
|
upid: response.result.data,
|
|
}).show();
|
|
},
|
|
});
|
|
},
|
|
|
|
showTaskLog: function() {
|
|
let me = this;
|
|
|
|
let upid = this.getData().upid;
|
|
if (!upid) return;
|
|
|
|
Ext.create('Proxmox.window.TaskViewer', { upid }).show();
|
|
},
|
|
|
|
startStore: function() { this.getView().getStore().rstore.startUpdate(); },
|
|
stopStore: function() { this.getView().getStore().rstore.stopUpdate(); },
|
|
reload: function() { this.getView().getStore().rstore.load(); },
|
|
|
|
|
|
filterState: function(view, state) {
|
|
delete state.height;
|
|
},
|
|
},
|
|
|
|
listeners: {
|
|
activate: 'startStore',
|
|
beforedestroy: 'stopStore',
|
|
deactivate: 'stopStore',
|
|
itemdblclick: 'editGCJob',
|
|
beforestatesave: 'filterState',
|
|
},
|
|
|
|
store: {
|
|
type: 'diff',
|
|
autoDestroy: true,
|
|
autoDestroyRstore: true,
|
|
sorters: 'store',
|
|
rstore: {
|
|
type: 'update',
|
|
storeid: 'pbs-gc-jobs-status',
|
|
model: 'pbs-gc-jobs-status',
|
|
interval: 5000,
|
|
},
|
|
},
|
|
|
|
tbar: [
|
|
{
|
|
xtype: 'proxmoxButton',
|
|
text: gettext('Edit'),
|
|
handler: 'editGCJob',
|
|
enableFn: (rec) => !!rec,
|
|
disabled: true,
|
|
},
|
|
'-',
|
|
{
|
|
xtype: 'proxmoxButton',
|
|
text: gettext('Show Log'),
|
|
handler: 'showTaskLog',
|
|
enableFn: (rec) => !!rec.data.upid,
|
|
disabled: true,
|
|
},
|
|
{
|
|
xtype: 'proxmoxButton',
|
|
text: gettext('Run now'),
|
|
handler: 'garbageCollect',
|
|
enableFn: (rec) => !!rec,
|
|
disabled: true,
|
|
},
|
|
],
|
|
|
|
columns: [
|
|
{
|
|
header: gettext('Datastore'),
|
|
dataIndex: 'store',
|
|
renderer: Ext.String.htmlEncode,
|
|
sortable: true,
|
|
hideable: false,
|
|
minWidth: 120,
|
|
maxWidth: 300,
|
|
flex: 2,
|
|
},
|
|
{
|
|
header: gettext('Schedule'),
|
|
dataIndex: 'schedule',
|
|
sortable: false,
|
|
hideable: false,
|
|
renderer: (value) => value ? value : Proxmox.Utils.NoneText,
|
|
minWidth: 85,
|
|
flex: 1,
|
|
},
|
|
{
|
|
header: gettext('Last GC'),
|
|
dataIndex: 'last-run-endtime',
|
|
renderer: PBS.Utils.render_optional_timestamp,
|
|
sortable: true,
|
|
minWidth: 150,
|
|
flex: 1,
|
|
},
|
|
{
|
|
text: gettext('Duration'),
|
|
dataIndex: 'duration',
|
|
renderer: Proxmox.Utils.render_duration,
|
|
sortable: false,
|
|
minWidth: 80,
|
|
flex: 1,
|
|
},
|
|
{
|
|
header: gettext('Last Status'),
|
|
dataIndex: 'last-run-state',
|
|
renderer: PBS.Utils.render_task_status,
|
|
sortable: true,
|
|
minWidth: 80,
|
|
flex: 1,
|
|
},
|
|
{
|
|
header: gettext('Next Run'),
|
|
dataIndex: 'next-run',
|
|
renderer: PBS.Utils.render_next_task_run,
|
|
sortable: true,
|
|
minWidth: 150,
|
|
flex: 1,
|
|
},
|
|
{
|
|
header: gettext('Removed Data'),
|
|
dataIndex: 'removed-bytes',
|
|
renderer: (value, meta, record) => record.data.upid !== null
|
|
? Proxmox.Utils.format_size(value, true) : "-",
|
|
sortable: false,
|
|
minWidth: 85,
|
|
flex: 1,
|
|
},
|
|
{
|
|
header: gettext('Pending Data'),
|
|
dataIndex: 'pending-bytes',
|
|
renderer: (value, meta, record) => record.data.upid !== null
|
|
? Proxmox.Utils.format_size(value, true) : "-",
|
|
sortable: false,
|
|
minWidth: 80,
|
|
flex: 3,
|
|
},
|
|
],
|
|
|
|
initComponent: function() {
|
|
let me = this;
|
|
let hideLocalDatastore = !!me.datastore;
|
|
|
|
for (let column of me.columns) {
|
|
if (column.dataIndex === 'store') {
|
|
column.hidden = hideLocalDatastore;
|
|
break;
|
|
}
|
|
}
|
|
|
|
me.callParent();
|
|
},
|
|
});
|