2020-10-27 18:20:07 +03:00
Ext . define ( 'pve-rrd-datastore' , {
extend : 'Ext.data.Model' ,
fields : [
2020-10-28 23:24:25 +03:00
'used' ,
'total' ,
2022-11-09 17:25:23 +03:00
{
2023-11-29 20:32:06 +03:00
name : 'unpriv-total' , // Can't reuse 'total' here as that creates a stack overflow
2022-11-09 17:25:23 +03:00
calculate : function ( data ) {
let used = data . used ;
let avail = data . available ;
if ( avail && used ) {
return avail + used ;
}
return data . total ;
} ,
} ,
'available' ,
2020-10-28 23:24:25 +03:00
'read_ios' ,
'read_bytes' ,
'write_ios' ,
'write_bytes' ,
'io_ticks' ,
{
name : 'io_delay' , calculate : function ( data ) {
let ios = 0 ;
if ( data . read _ios !== undefined ) { ios += data . read _ios ; }
if ( data . write _ios !== undefined ) { ios += data . write _ios ; }
if ( data . io _ticks === undefined ) {
return undefined ;
} else if ( ios === 0 ) {
return 0 ;
}
return ( data . io _ticks * 1000.0 ) / ios ;
} ,
} ,
{ type : 'date' , dateFormat : 'timestamp' , name : 'time' } ,
2020-10-27 18:20:07 +03:00
] ,
} ) ;
Ext . define ( 'PBS.DataStoreInfo' , {
extend : 'Ext.panel.Panel' ,
alias : 'widget.pbsDataStoreInfo' ,
viewModel : {
data : {
countstext : '' ,
usage : { } ,
stillbad : 0 ,
mountpoint : "" ,
} ,
} ,
controller : {
xclass : 'Ext.app.ViewController' ,
onLoad : function ( store , data , success ) {
let me = this ;
2022-04-26 09:23:30 +03:00
if ( ! success ) {
Proxmox . Utils . API2Request ( {
url : ` /config/datastore/ ${ me . view . datastore } ` ,
success : function ( response ) {
const config = response . result . data ;
if ( config [ 'maintenance-mode' ] ) {
2022-04-26 09:23:34 +03:00
const [ _type , msg ] = PBS . Utils . parseMaintenanceMode ( config [ 'maintenance-mode' ] ) ;
2022-04-26 09:23:30 +03:00
me . view . el . mask (
2022-04-26 09:23:34 +03:00
` ${ gettext ( 'Datastore is in maintenance mode' ) } ${ msg ? ': ' + msg : '' } ` ,
2022-04-26 09:23:30 +03:00
'fa pbs-maintenance-mask' ,
) ;
} else {
me . view . el . mask ( gettext ( 'Datastore is not available' ) ) ;
}
} ,
} ) ;
return ;
}
me . view . el . unmask ( ) ;
2020-10-27 18:20:07 +03:00
let vm = me . getViewModel ( ) ;
let counts = store . getById ( 'counts' ) . data . value ;
2020-10-29 13:51:26 +03:00
let used = store . getById ( 'used' ) . data . value ;
2022-11-09 17:25:23 +03:00
let total = store . getById ( 'avail' ) . data . value + used ;
2020-10-27 18:20:07 +03:00
2022-05-17 11:20:05 +03:00
let usage = Proxmox . Utils . render _size _usage ( used , total , true ) ;
2020-10-27 18:20:07 +03:00
vm . set ( 'usagetext' , usage ) ;
2020-10-29 13:51:26 +03:00
vm . set ( 'usage' , used / total ) ;
2020-10-27 18:20:07 +03:00
let countstext = function ( count ) {
2020-10-29 17:52:45 +03:00
count = count || { } ;
2020-10-29 13:51:26 +03:00
return ` ${ count . groups || 0 } ${ gettext ( 'Groups' ) } , ${ count . snapshots || 0 } ${ gettext ( 'Snapshots' ) } ` ;
2020-10-27 18:20:07 +03:00
} ;
2022-05-27 11:58:38 +03:00
let gcstatus = store . getById ( 'gc-status' ) ? . data . value ;
if ( gcstatus ) {
let dedup = PBS . Utils . calculate _dedup _factor ( gcstatus ) ;
vm . set ( 'deduplication' , dedup . toFixed ( 2 ) ) ;
vm . set ( 'stillbad' , gcstatus [ 'still-bad' ] ) ;
}
2020-10-27 18:20:07 +03:00
2020-10-29 13:51:26 +03:00
vm . set ( 'ctcount' , countstext ( counts . ct ) ) ;
vm . set ( 'vmcount' , countstext ( counts . vm ) ) ;
vm . set ( 'hostcount' , countstext ( counts . host ) ) ;
2020-10-27 18:20:07 +03:00
} ,
startStore : function ( ) { this . store . startUpdate ( ) ; } ,
stopStore : function ( ) { this . store . stopUpdate ( ) ; } ,
init : function ( view ) {
let me = this ;
let datastore = encodeURIComponent ( view . datastore ) ;
me . store = Ext . create ( 'Proxmox.data.ObjectStore' , {
interval : 5 * 1000 ,
2020-11-12 13:30:31 +03:00
url : ` /api2/json/admin/datastore/ ${ datastore } /status/?verbose=true ` ,
2020-10-27 18:20:07 +03:00
} ) ;
me . store . on ( 'load' , me . onLoad , me ) ;
} ,
} ,
listeners : {
activate : 'startStore' ,
2021-05-26 12:12:01 +03:00
beforedestroy : 'stopStore' ,
2020-10-27 18:20:07 +03:00
deactivate : 'stopStore' ,
} ,
defaults : {
xtype : 'pmxInfoWidget' ,
} ,
bodyPadding : 20 ,
items : [
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa fa-fw fa-hdd-o' ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'Usage' ) ,
bind : {
data : {
usage : '{usage}' ,
text : '{usagetext}' ,
} ,
} ,
} ,
{
xtype : 'box' ,
html : ` <b> ${ gettext ( 'Backup Count' ) } </b> ` ,
padding : '10 0 5 0' ,
} ,
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa fa-fw fa-cube' ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'CT' ) ,
printBar : false ,
bind : {
data : {
text : '{ctcount}' ,
} ,
} ,
} ,
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa fa-fw fa-building' ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'Host' ) ,
printBar : false ,
bind : {
data : {
text : '{hostcount}' ,
} ,
} ,
} ,
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa fa-fw fa-desktop' ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'VM' ) ,
printBar : false ,
bind : {
data : {
text : '{vmcount}' ,
} ,
} ,
} ,
{
xtype : 'box' ,
html : ` <b> ${ gettext ( 'Stats from last Garbage Collection' ) } </b> ` ,
padding : '10 0 5 0' ,
} ,
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa fa-fw fa-compress' ,
2020-10-27 19:43:43 +03:00
title : gettext ( 'Deduplication Factor' ) ,
2020-10-27 18:20:07 +03:00
printBar : false ,
bind : {
data : {
text : '{deduplication}' ,
} ,
} ,
} ,
{
2020-10-27 19:43:10 +03:00
iconCls : 'fa critical fa-fw fa-exclamation-triangle' ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'Bad Chunks' ) ,
printBar : false ,
bind : {
data : {
text : '{stillbad}' ,
} ,
visible : '{stillbad}' ,
} ,
} ,
] ,
} ) ;
Ext . define ( 'PBS.DataStoreSummary' , {
extend : 'Ext.panel.Panel' ,
alias : 'widget.pbsDataStoreSummary' ,
mixins : [ 'Proxmox.Mixin.CBind' ] ,
layout : 'column' ,
scrollable : true ,
bodyPadding : 5 ,
defaults : {
columnWidth : 1 ,
padding : 5 ,
} ,
2023-11-29 18:49:50 +03:00
tbar : [
{
xtype : 'button' ,
text : gettext ( 'Show Connection Information' ) ,
handler : function ( ) {
let me = this ;
let datastore = me . up ( 'panel' ) . datastore ;
Ext . create ( 'PBS.window.DatastoreRepoInfo' , {
datastore ,
autoShow : true ,
} ) ;
} ,
} ,
'->' ,
{
xtype : 'proxmoxRRDTypeSelector' ,
} ,
] ,
2020-10-27 18:20:07 +03:00
items : [
{
xtype : 'container' ,
height : 300 ,
layout : {
type : 'hbox' ,
align : 'stretch' ,
} ,
items : [
{
xtype : 'pbsDataStoreInfo' ,
flex : 1 ,
padding : '0 10 0 0' ,
cbind : {
title : '{datastore}' ,
datastore : '{datastore}' ,
} ,
} ,
{
xtype : 'pbsDataStoreNotes' ,
flex : 1 ,
cbind : {
datastore : '{datastore}' ,
} ,
} ,
] ,
} ,
{
xtype : 'proxmoxRRDChart' ,
title : gettext ( 'Storage usage (bytes)' ) ,
2022-11-09 17:25:23 +03:00
fields : [ 'unpriv-total' , 'used' ] ,
2020-10-27 18:20:07 +03:00
fieldTitles : [ gettext ( 'Total' ) , gettext ( 'Storage usage' ) ] ,
} ,
{
xtype : 'proxmoxRRDChart' ,
title : gettext ( 'Transfer Rate (bytes/second)' ) ,
fields : [ 'read_bytes' , 'write_bytes' ] ,
fieldTitles : [ gettext ( 'Read' ) , gettext ( 'Write' ) ] ,
} ,
{
xtype : 'proxmoxRRDChart' ,
title : gettext ( 'Input/Output Operations per Second (IOPS)' ) ,
fields : [ 'read_ios' , 'write_ios' ] ,
fieldTitles : [ gettext ( 'Read' ) , gettext ( 'Write' ) ] ,
} ,
{
xtype : 'proxmoxRRDChart' ,
2022-01-11 12:27:08 +03:00
itemId : 'ioDelayChart' ,
hidden : true ,
2020-10-27 18:20:07 +03:00
title : gettext ( 'IO Delay (ms)' ) ,
fields : [ 'io_delay' ] ,
fieldTitles : [ gettext ( 'IO Delay' ) ] ,
} ,
] ,
listeners : {
activate : function ( ) { this . rrdstore . startUpdate ( ) ; } ,
deactivate : function ( ) { this . rrdstore . stopUpdate ( ) ; } ,
destroy : function ( ) { this . rrdstore . stopUpdate ( ) ; } ,
2021-04-19 14:02:06 +03:00
resize : function ( panel ) {
Proxmox . Utils . updateColumns ( panel ) ;
} ,
2020-10-27 18:20:07 +03:00
} ,
initComponent : function ( ) {
let me = this ;
me . rrdstore = Ext . create ( 'Proxmox.data.RRDStore' , {
rrdurl : "/api2/json/admin/datastore/" + me . datastore + "/rrd" ,
model : 'pve-rrd-datastore' ,
} ) ;
me . callParent ( ) ;
2021-04-19 14:02:06 +03:00
let sp = Ext . state . Manager . getProvider ( ) ;
me . mon ( sp , 'statechange' , function ( provider , key , value ) {
if ( key !== 'summarycolumns' ) {
return ;
}
2021-12-02 17:26:31 +03:00
if ( ! me . rendered ) {
return ;
}
2021-04-19 14:02:06 +03:00
Proxmox . Utils . updateColumns ( me ) ;
} ) ;
2020-10-27 18:20:07 +03:00
Proxmox . Utils . API2Request ( {
url : ` /config/datastore/ ${ me . datastore } ` ,
waitMsgTarget : me . down ( 'pbsDataStoreInfo' ) ,
success : function ( response ) {
let path = Ext . htmlEncode ( response . result . data . path ) ;
me . down ( 'pbsDataStoreInfo' ) . setTitle ( ` ${ me . datastore } ( ${ path } ) ` ) ;
me . down ( 'pbsDataStoreNotes' ) . setNotes ( response . result . data . comment ) ;
} ,
2020-11-13 17:02:36 +03:00
failure : function ( response ) {
// fallback if e.g. we have no permissions to the config
2020-11-26 11:27:31 +03:00
let rec = Ext . getStore ( 'pbs-datastore-list' )
. findRecord ( 'store' , me . datastore , 0 , false , true , true ) ;
2020-11-13 17:02:36 +03:00
if ( rec ) {
me . down ( 'pbsDataStoreNotes' ) . setNotes ( rec . data . comment || "" ) ;
}
} ,
2020-10-27 18:20:07 +03:00
} ) ;
2022-01-11 12:27:08 +03:00
me . mon ( me . rrdstore , 'load' , function ( store , records , success ) {
2022-05-27 11:59:42 +03:00
let hasIoTicks = records ? . some ( ( rec ) => rec ? . data ? . io _ticks !== undefined ) ;
me . down ( '#ioDelayChart' ) . setVisible ( ! success || hasIoTicks ) ;
2022-01-11 12:27:08 +03:00
} , undefined , { single : true } ) ;
2020-10-27 18:20:07 +03:00
me . query ( 'proxmoxRRDChart' ) . forEach ( ( chart ) => {
chart . setStore ( me . rrdstore ) ;
} ) ;
me . down ( 'pbsDataStoreInfo' ) . relayEvents ( me , [ 'activate' , 'deactivate' ] ) ;
} ,
} ) ;