]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/Utils.js
d2ad7a149800a1b013ad418fbb102659caee63c8
2 Ext
. ns ( 'Proxmox.Setup' );
4 if (! Ext
. isDefined ( Proxmox
. Setup
. auth_cookie_name
)) {
5 throw "Proxmox library not initialized" ;
8 // avoid errors related to Accessible Rich Internet Applications
9 // (access for people with disabilities)
10 // TODO reenable after all components are upgraded
11 Ext
. enableAria
= false ;
12 Ext
. enableAriaButtons
= false ;
13 Ext
. enableAriaPanels
= false ;
15 // avoid errors when running without development tools
16 if (! Ext
. isDefined ( Ext
. global
. console
)) {
28 Ext
. global
. console
= console
;
31 Ext
. Ajax
. defaultHeaders
= {
32 'Accept' : 'application/json' ,
35 Ext
. Ajax
. on ( 'beforerequest' , function ( conn
, options
) {
36 if ( Proxmox
. CSRFPreventionToken
) {
37 if (! options
. headers
) {
40 options
. headers
. CSRFPreventionToken
= Proxmox
. CSRFPreventionToken
;
42 let storedUser
= Proxmox
. Utils
. getStoredUser ();
43 if ( storedUser
. token
) {
44 options
. headers
. Authorization
= storedUser
. token
;
48 Ext
. define ( 'Proxmox.Utils' , { // a singleton
51 yesText
: gettext ( 'Yes' ),
52 noText
: gettext ( 'No' ),
53 enabledText
: gettext ( 'Enabled' ),
54 disabledText
: gettext ( 'Disabled' ),
55 noneText
: gettext ( 'none' ),
56 NoneText
: gettext ( 'None' ),
57 errorText
: gettext ( 'Error' ),
58 unknownText
: gettext ( 'Unknown' ),
59 defaultText
: gettext ( 'Default' ),
60 daysText
: gettext ( 'days' ),
61 dayText
: gettext ( 'day' ),
62 runningText
: gettext ( 'running' ),
63 stoppedText
: gettext ( 'stopped' ),
64 neverText
: gettext ( 'never' ),
65 totalText
: gettext ( 'Total' ),
66 usedText
: gettext ( 'Used' ),
67 directoryText
: gettext ( 'Directory' ),
68 stateText
: gettext ( 'State' ),
69 groupText
: gettext ( 'Group' ),
78 eu
: 'Euskera (Basque)' ,
79 fa
: 'Persian (Farsi)' ,
84 nb
: 'Norwegian (Bokmal)' ,
85 nn
: 'Norwegian (Nynorsk)' ,
87 pt_BR
: 'Portuguese (Brazil)' ,
92 zh_CN
: 'Chinese (Simplified)' ,
93 zh_TW
: 'Chinese (Traditional)' ,
96 render_language : function ( value
) {
98 return Proxmox
. Utils
. defaultText
+ ' (English)' ;
100 let text
= Proxmox
. Utils
. language_map
[ value
];
102 return text
+ ' (' + value
+ ')' ;
107 language_array : function () {
108 let data
= [[ '__default__' , Proxmox
. Utils
. render_language ( '' )]];
109 Ext
. Object
. each ( Proxmox
. Utils
. language_map
, function ( key
, value
) {
110 data
. push ([ key
, Proxmox
. Utils
. render_language ( value
)]);
116 bond_mode_gettext_map
: {
117 '802.3ad' : 'LACP (802.3ad)' ,
118 'lacp-balance-slb' : 'LACP (balance-slb)' ,
119 'lacp-balance-tcp' : 'LACP (balance-tcp)' ,
122 render_bond_mode
: value
=> Proxmox
. Utils
. bond_mode_gettext_map
[ value
] || value
|| '' ,
124 bond_mode_array : function ( modes
) {
125 return modes
. map ( mode
=> [ mode
, Proxmox
. Utils
. render_bond_mode ( mode
)]);
128 getNoSubKeyHtml : function ( url
) {
129 // url http://www.proxmox.com/products/proxmox-ve/subscription-service-plans
130 return Ext
. String
. format ( 'You do not have a valid subscription for this server. Please visit <a target="_blank" href="{0}">www.proxmox.com</a> to get a list of available options.' , url
|| 'https://www.proxmox.com' );
133 format_boolean_with_default : function ( value
) {
134 if ( Ext
. isDefined ( value
) && value
!== '__default__' ) {
135 return value
? Proxmox
. Utils
. yesText
: Proxmox
. Utils
. noText
;
137 return Proxmox
. Utils
. defaultText
;
140 format_boolean : function ( value
) {
141 return value
? Proxmox
. Utils
. yesText
: Proxmox
. Utils
. noText
;
144 format_neg_boolean : function ( value
) {
145 return ! value
? Proxmox
. Utils
. yesText
: Proxmox
. Utils
. noText
;
148 format_enabled_toggle : function ( value
) {
149 return value
? Proxmox
. Utils
. enabledText
: Proxmox
. Utils
. disabledText
;
152 format_expire : function ( date
) {
154 return Proxmox
. Utils
. neverText
;
156 return Ext
. Date
. format ( date
, "Y-m-d" );
159 // somewhat like a human would tell durations, omit zero values and do not
160 // give seconds precision if we talk days already
161 format_duration_human : function ( ut
) {
162 let seconds
= 0 , minutes
= 0 , hours
= 0 , days
= 0 ;
169 seconds
= Number (( remaining
% 60 ). toFixed ( 1 ));
170 remaining
= Math
. trunc ( remaining
/ 60 );
172 minutes
= remaining
% 60 ;
173 remaining
= Math
. trunc ( remaining
/ 60 );
175 hours
= remaining
% 24 ;
176 remaining
= Math
. trunc ( remaining
/ 24 );
184 let add
= ( t
, unit
) => {
185 if ( t
> 0 ) res
. push ( t
+ unit
);
189 let addSeconds
= ! add ( days
, 'd' );
195 return res
. join ( ' ' );
198 format_duration_long : function ( ut
) {
199 let days
= Math
. floor ( ut
/ 86400 );
201 let hours
= Math
. floor ( ut
/ 3600 );
203 let mins
= Math
. floor ( ut
/ 60 );
206 let hours_str
= '00' + hours
. toString ();
207 hours_str
= hours_str
. substr ( hours_str
. length
- 2 );
208 let mins_str
= "00" + mins
. toString ();
209 mins_str
= mins_str
. substr ( mins_str
. length
- 2 );
210 let ut_str
= "00" + ut
. toString ();
211 ut_str
= ut_str
. substr ( ut_str
. length
- 2 );
214 let ds
= days
> 1 ? Proxmox
. Utils
. daysText
: Proxmox
. Utils
. dayText
;
215 return days
. toString () + ' ' + ds
+ ' ' +
216 hours_str
+ ':' + mins_str
+ ':' + ut_str
;
218 return hours_str
+ ':' + mins_str
+ ':' + ut_str
;
222 format_subscription_level : function ( level
) {
225 } else if ( level
=== 'b' ) {
227 } else if ( level
=== 's' ) {
229 } else if ( level
=== 'p' ) {
232 return Proxmox
. Utils
. noneText
;
236 compute_min_label_width : function ( text
, width
) {
237 if ( width
=== undefined ) { width
= 100 ; }
239 let tm
= new Ext
. util
. TextMetrics ();
240 let min
= tm
. getWidth ( text
+ ':' );
242 return min
< width
? width
: min
;
245 getStoredAuth : function () {
246 let storedAuth
= JSON
. parse ( window
. localStorage
. getItem ( 'ProxmoxUser' ));
247 return storedAuth
|| {};
250 setAuthData : function ( data
) {
251 Proxmox
. UserName
= data
. username
;
252 Proxmox
. LoggedOut
= data
. LoggedOut
;
253 // creates a session cookie (expire = null)
254 // that way the cookie gets deleted after the browser window is closed
256 Proxmox
. CSRFPreventionToken
= data
. CSRFPreventionToken
;
257 Ext
. util
. Cookies
. set ( Proxmox
. Setup
. auth_cookie_name
, data
. ticket
, null , '/' , null , true );
261 window
. localStorage
. setItem ( 'ProxmoxUser' , JSON
. stringify ( data
));
266 if ( Proxmox
. LoggedOut
) {
269 let storedAuth
= Proxmox
. Utils
. getStoredUser ();
270 let cookie
= Ext
. util
. Cookies
. get ( Proxmox
. Setup
. auth_cookie_name
);
271 if (( Proxmox
. UserName
!== '' && cookie
&& ! cookie
. startsWith ( "PVE:tfa!" )) || storedAuth
. token
) {
272 return cookie
|| storedAuth
. token
;
278 authClear : function () {
279 if ( Proxmox
. LoggedOut
) {
282 Ext
. util
. Cookies
. clear ( Proxmox
. Setup
. auth_cookie_name
);
283 window
. localStorage
. removeItem ( "ProxmoxUser" );
286 // comp.setLoading() is buggy in ExtJS 4.0.7, so we
287 // use el.mask() instead
288 setErrorMask : function ( comp
, msg
) {
295 } else if ( msg
=== true ) {
296 el
. mask ( gettext ( "Loading..." ));
302 getResponseErrorMessage
: ( err
) => {
303 if (! err
. statusText
) {
304 return gettext ( 'Connection error' );
306 let msg
= [ ` ${err.statusText} ( ${err.status} )` ];
307 if ( err
. response
&& err
. response
. responseText
) {
308 let txt
= err
. response
. responseText
;
310 let res
= JSON
. parse ( txt
);
311 if ( res
. errors
&& typeof res
. errors
=== 'object' ) {
312 for ( let [ key
, value
] of Object
. entries ( res
. errors
)) {
313 msg
. push ( Ext
. String
. htmlEncode ( ` ${key} : ${value} ` ));
317 // fallback to string
318 msg
. push ( Ext
. String
. htmlEncode ( txt
));
321 return msg
. join ( '<br>' );
324 monStoreErrors : function ( component
, store
, clearMaskBeforeLoad
) {
325 if ( clearMaskBeforeLoad
) {
326 component
. mon ( store
, 'beforeload' , function ( s
, operation
, eOpts
) {
327 Proxmox
. Utils
. setErrorMask ( component
, false );
330 component
. mon ( store
, 'beforeload' , function ( s
, operation
, eOpts
) {
331 if (! component
. loadCount
) {
332 component
. loadCount
= 0 ; // make sure it is nucomponent.ic
333 Proxmox
. Utils
. setErrorMask ( component
, true );
338 // only works with 'proxmox' proxy
339 component
. mon ( store
. proxy
, 'afterload' , function ( proxy
, request
, success
) {
340 component
. loadCount
++;
343 Proxmox
. Utils
. setErrorMask ( component
, false );
347 let error
= request
. _operation
. getError ();
348 let msg
= Proxmox
. Utils
. getResponseErrorMessage ( error
);
349 Proxmox
. Utils
. setErrorMask ( component
, msg
);
353 extractRequestError : function ( result
, verbose
) {
354 let msg
= gettext ( 'Successful' );
356 if (! result
. success
) {
357 msg
= gettext ( "Unknown error" );
358 if ( result
. message
) {
359 msg
= result
. message
;
361 msg
+= ' (' + result
. status
+ ')' ;
364 if ( verbose
&& Ext
. isObject ( result
. errors
)) {
366 Ext
. Object
. each ( result
. errors
, function ( prop
, desc
) {
367 msg
+= "<br><b>" + Ext
. htmlEncode ( prop
) + "</b>: " +
368 Ext
. htmlEncode ( desc
);
377 API2Request : function ( reqOpts
) {
378 let newopts
= Ext
. apply ({
379 waitMsg
: gettext ( 'Please wait...' ),
382 if (! newopts
. url
. match ( /^\/api2/ )) {
383 newopts
. url
= '/api2/extjs' + newopts
. url
;
385 delete newopts
. callback
;
387 let createWrapper = function ( successFn
, callbackFn
, failureFn
) {
389 success : function ( response
, options
) {
390 if ( options
. waitMsgTarget
) {
391 if ( Proxmox
. Utils
. toolkit
=== 'touch' ) {
392 options
. waitMsgTarget
. setMasked ( false );
394 options
. waitMsgTarget
. setLoading ( false );
397 let result
= Ext
. decode ( response
. responseText
);
398 response
. result
= result
;
399 if (! result
. success
) {
400 response
. htmlStatus
= Proxmox
. Utils
. extractRequestError ( result
, true );
401 Ext
. callback ( callbackFn
, options
. scope
, [ options
, false , response
]);
402 Ext
. callback ( failureFn
, options
. scope
, [ response
, options
]);
405 Ext
. callback ( callbackFn
, options
. scope
, [ options
, true , response
]);
406 Ext
. callback ( successFn
, options
. scope
, [ response
, options
]);
408 failure : function ( response
, options
) {
409 if ( options
. waitMsgTarget
) {
410 if ( Proxmox
. Utils
. toolkit
=== 'touch' ) {
411 options
. waitMsgTarget
. setMasked ( false );
413 options
. waitMsgTarget
. setLoading ( false );
416 response
. result
= {};
418 response
. result
= Ext
. decode ( response
. responseText
);
422 let msg
= gettext ( 'Connection error' ) + ' - server offline?' ;
423 if ( response
. aborted
) {
424 msg
= gettext ( 'Connection error' ) + ' - aborted.' ;
425 } else if ( response
. timedout
) {
426 msg
= gettext ( 'Connection error' ) + ' - Timeout.' ;
427 } else if ( response
. status
&& response
. statusText
) {
428 msg
= gettext ( 'Connection error' ) + ' ' + response
. status
+ ': ' + response
. statusText
;
430 response
. htmlStatus
= msg
;
431 Ext
. callback ( callbackFn
, options
. scope
, [ options
, false , response
]);
432 Ext
. callback ( failureFn
, options
. scope
, [ response
, options
]);
437 createWrapper ( reqOpts
. success
, reqOpts
. callback
, reqOpts
. failure
);
439 let target
= newopts
. waitMsgTarget
;
441 if ( Proxmox
. Utils
. toolkit
=== 'touch' ) {
442 target
. setMasked ({ xtype
: 'loadmask' , message
: newopts
. waitMsg
});
444 // Note: ExtJS bug - this does not work when component is not rendered
445 target
. setLoading ( newopts
. waitMsg
);
448 Ext
. Ajax
. request ( newopts
);
451 checked_command : function ( orig_cmd
) {
452 Proxmox
. Utils
. API2Request ({
453 url
: '/nodes/localhost/subscription' ,
455 failure : function ( response
, opts
) {
456 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
458 success : function ( response
, opts
) {
459 let data
= response
. result
. data
;
460 if ( data
. status
!== 'Active' ) {
462 title
: gettext ( 'No valid subscription' ),
463 icon
: Ext
. Msg
. WARNING
,
464 message
: Proxmox
. Utils
. getNoSubKeyHtml ( data
. url
),
466 callback : function ( btn
) {
480 assemble_field_data : function ( values
, data
) {
481 if (! Ext
. isObject ( data
)) {
484 Ext
. Object
. each ( data
, function ( name
, val
) {
485 if ( Object
. prototype . hasOwnProperty
. call ( values
, name
)) {
486 let bucket
= values
[ name
];
487 if (! Ext
. isArray ( bucket
)) {
488 bucket
= values
[ name
] = [ bucket
];
490 if ( Ext
. isArray ( val
)) {
491 values
[ name
] = bucket
. concat ( val
);
501 updateColumnWidth : function ( container
) {
502 let mode
= Ext
. state
. Manager
. get ( 'summarycolumns' ) || 'auto' ;
504 if ( mode
!== 'auto' ) {
505 factor
= parseInt ( mode
, 10 );
506 if ( Number
. isNaN ( factor
)) {
510 factor
= container
. getSize (). width
< 1600 ? 1 : 2 ;
513 if ( container
. oldFactor
=== factor
) {
517 let items
= container
. query ( '>' ); // direct childs
518 factor
= Math
. min ( factor
, items
. length
);
519 container
. oldFactor
= factor
;
521 items
. forEach (( item
) => {
522 item
. columnWidth
= 1 / factor
;
525 // we have to update the layout twice, since the first layout change
526 // can trigger the scrollbar which reduces the amount of space left
527 container
. updateLayout ();
528 container
. updateLayout ();
531 dialog_title : function ( subject
, create
, isAdd
) {
534 return gettext ( 'Add' ) + ': ' + subject
;
536 return gettext ( 'Create' ) + ': ' + subject
;
539 return gettext ( 'Edit' ) + ': ' + subject
;
543 network_iface_types
: {
544 eth
: gettext ( "Network Device" ),
545 bridge
: 'Linux Bridge' ,
548 OVSBridge
: 'OVS Bridge' ,
551 OVSIntPort
: 'OVS IntPort' ,
554 render_network_iface_type : function ( value
) {
555 return Proxmox
. Utils
. network_iface_types
[ value
] ||
556 Proxmox
. Utils
. unknownText
;
560 acmenewcert
: [ 'SRV' , gettext ( 'Order Certificate' )],
561 acmeregister
: [ 'ACME Account' , gettext ( 'Register' )],
562 acmedeactivate
: [ 'ACME Account' , gettext ( 'Deactivate' )],
563 acmeupdate
: [ 'ACME Account' , gettext ( 'Update' )],
564 acmerefresh
: [ 'ACME Account' , gettext ( 'Refresh' )],
565 acmerenew
: [ 'SRV' , gettext ( 'Renew Certificate' )],
566 acmerevoke
: [ 'SRV' , gettext ( 'Revoke Certificate' )],
567 'auth-realm-sync' : [ gettext ( 'Realm' ), gettext ( 'Sync' )],
568 'auth-realm-sync-test' : [ gettext ( 'Realm' ), gettext ( 'Sync Preview' )],
569 'move_volume' : [ 'CT' , gettext ( 'Move Volume' )],
570 clustercreate
: [ '' , gettext ( 'Create Cluster' )],
571 clusterjoin
: [ '' , gettext ( 'Join Cluster' )],
572 diskinit
: [ 'Disk' , gettext ( 'Initialize Disk with GPT' )],
573 vncproxy
: [ 'VM/CT' , gettext ( 'Console' )],
574 spiceproxy
: [ 'VM/CT' , gettext ( 'Console' ) + ' (Spice)' ],
575 vncshell
: [ '' , gettext ( 'Shell' )],
576 spiceshell
: [ '' , gettext ( 'Shell' ) + ' (Spice)' ],
577 qmsnapshot
: [ 'VM' , gettext ( 'Snapshot' )],
578 qmrollback
: [ 'VM' , gettext ( 'Rollback' )],
579 qmdelsnapshot
: [ 'VM' , gettext ( 'Delete Snapshot' )],
580 qmcreate
: [ 'VM' , gettext ( 'Create' )],
581 qmrestore
: [ 'VM' , gettext ( 'Restore' )],
582 qmdestroy
: [ 'VM' , gettext ( 'Destroy' )],
583 qmigrate
: [ 'VM' , gettext ( 'Migrate' )],
584 qmclone
: [ 'VM' , gettext ( 'Clone' )],
585 qmmove
: [ 'VM' , gettext ( 'Move disk' )],
586 qmtemplate
: [ 'VM' , gettext ( 'Convert to template' )],
587 qmstart
: [ 'VM' , gettext ( 'Start' )],
588 qmstop
: [ 'VM' , gettext ( 'Stop' )],
589 qmreset
: [ 'VM' , gettext ( 'Reset' )],
590 qmshutdown
: [ 'VM' , gettext ( 'Shutdown' )],
591 qmreboot
: [ 'VM' , gettext ( 'Reboot' )],
592 qmsuspend
: [ 'VM' , gettext ( 'Hibernate' )],
593 qmpause
: [ 'VM' , gettext ( 'Pause' )],
594 qmresume
: [ 'VM' , gettext ( 'Resume' )],
595 qmconfig
: [ 'VM' , gettext ( 'Configure' )],
596 vzsnapshot
: [ 'CT' , gettext ( 'Snapshot' )],
597 vzrollback
: [ 'CT' , gettext ( 'Rollback' )],
598 vzdelsnapshot
: [ 'CT' , gettext ( 'Delete Snapshot' )],
599 vzcreate
: [ 'CT' , gettext ( 'Create' )],
600 vzrestore
: [ 'CT' , gettext ( 'Restore' )],
601 vzdestroy
: [ 'CT' , gettext ( 'Destroy' )],
602 vzmigrate
: [ 'CT' , gettext ( 'Migrate' )],
603 vzclone
: [ 'CT' , gettext ( 'Clone' )],
604 vztemplate
: [ 'CT' , gettext ( 'Convert to template' )],
605 vzstart
: [ 'CT' , gettext ( 'Start' )],
606 vzstop
: [ 'CT' , gettext ( 'Stop' )],
607 vzmount
: [ 'CT' , gettext ( 'Mount' )],
608 vzumount
: [ 'CT' , gettext ( 'Unmount' )],
609 vzshutdown
: [ 'CT' , gettext ( 'Shutdown' )],
610 vzreboot
: [ 'CT' , gettext ( 'Reboot' )],
611 vzsuspend
: [ 'CT' , gettext ( 'Suspend' )],
612 vzresume
: [ 'CT' , gettext ( 'Resume' )],
613 push_file
: [ 'CT' , gettext ( 'Push file' )],
614 pull_file
: [ 'CT' , gettext ( 'Pull file' )],
615 hamigrate
: [ 'HA' , gettext ( 'Migrate' )],
616 hastart
: [ 'HA' , gettext ( 'Start' )],
617 hastop
: [ 'HA' , gettext ( 'Stop' )],
618 hashutdown
: [ 'HA' , gettext ( 'Shutdown' )],
619 srvstart
: [ 'SRV' , gettext ( 'Start' )],
620 srvstop
: [ 'SRV' , gettext ( 'Stop' )],
621 srvrestart
: [ 'SRV' , gettext ( 'Restart' )],
622 srvreload
: [ 'SRV' , gettext ( 'Reload' )],
623 cephcreatemgr
: [ 'Ceph Manager' , gettext ( 'Create' )],
624 cephdestroymgr
: [ 'Ceph Manager' , gettext ( 'Destroy' )],
625 cephcreatemon
: [ 'Ceph Monitor' , gettext ( 'Create' )],
626 cephdestroymon
: [ 'Ceph Monitor' , gettext ( 'Destroy' )],
627 cephcreateosd
: [ 'Ceph OSD' , gettext ( 'Create' )],
628 cephdestroyosd
: [ 'Ceph OSD' , gettext ( 'Destroy' )],
629 cephcreatepool
: [ 'Ceph Pool' , gettext ( 'Create' )],
630 cephdestroypool
: [ 'Ceph Pool' , gettext ( 'Destroy' )],
631 cephfscreate
: [ 'CephFS' , gettext ( 'Create' )],
632 cephcreatemds
: [ 'Ceph Metadata Server' , gettext ( 'Create' )],
633 cephdestroymds
: [ 'Ceph Metadata Server' , gettext ( 'Destroy' )],
634 imgcopy
: [ '' , gettext ( 'Copy data' )],
635 imgdel
: [ '' , gettext ( 'Erase data' )],
636 unknownimgdel
: [ '' , gettext ( 'Destroy image from unknown guest' )],
637 download
: [ '' , gettext ( 'Download' )],
638 vzdump
: ( type
, id
) => id
? `VM/CT ${id} - ${gettext('Backup')} ` : gettext ( 'Backup Job' ),
639 aptupdate
: [ '' , gettext ( 'Update package database' )],
640 startall
: [ '' , gettext ( 'Start all VMs and Containers' )],
641 stopall
: [ '' , gettext ( 'Stop all VMs and Containers' )],
642 migrateall
: [ '' , gettext ( 'Migrate all VMs and Containers' )],
643 dircreate
: [ gettext ( 'Directory Storage' ), gettext ( 'Create' )],
644 lvmcreate
: [ gettext ( 'LVM Storage' ), gettext ( 'Create' )],
645 lvmthincreate
: [ gettext ( 'LVM-Thin Storage' ), gettext ( 'Create' )],
646 zfscreate
: [ gettext ( 'ZFS Storage' ), gettext ( 'Create' )],
649 // to add or change existing for product specific ones
650 override_task_descriptions : function ( extra
) {
651 for ( const [ key
, value
] of Object
. entries ( extra
)) {
652 Proxmox
. Utils
. task_desc_table
[ key
] = value
;
656 format_task_description : function ( type
, id
) {
657 let farray
= Proxmox
. Utils
. task_desc_table
[ type
];
665 } else if ( Ext
. isFunction ( farray
)) {
666 return farray ( type
, id
);
668 let prefix
= farray
[ 0 ];
670 if ( prefix
&& id
!== undefined ) {
671 return prefix
+ ' ' + id
+ ' - ' + text
;
676 format_size : function ( size
) {
677 let units
= [ '' , 'Ki' , 'Mi' , 'Gi' , 'Ti' , 'Pi' , 'Ei' , 'Zi' , 'Yi' ];
679 while ( size
>= 1024 && num
++ <= units
. length
) {
683 return size
. toFixed ( num
> 0 ? 2 : 0 ) + " " + units
[ num
] + "B" ;
686 render_upid : function ( value
, metaData
, record
) {
687 let task
= record
. data
;
688 let type
= task
. type
|| task
. worker_type
;
689 let id
= task
. id
|| task
. worker_id
;
691 return Proxmox
. Utils
. format_task_description ( type
, id
);
694 render_uptime : function ( value
) {
697 if ( uptime
=== undefined ) {
705 return Proxmox
. Utils
. format_duration_long ( uptime
);
708 parse_task_upid : function ( upid
) {
711 let res
= upid
. match ( /^UPID:([^\s:]+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8,9}):(([0-9A-Fa-f]{8,16}):)?([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/ );
713 throw "unable to parse upid '" + upid
+ "'" ;
716 task
. pid
= parseInt ( res
[ 2 ], 16 );
717 task
. pstart
= parseInt ( res
[ 3 ], 16 );
718 if ( res
[ 5 ] !== undefined ) {
719 task
. task_id
= parseInt ( res
[ 5 ], 16 );
721 task
. starttime
= parseInt ( res
[ 6 ], 16 );
726 task
. desc
= Proxmox
. Utils
. format_task_description ( task
. type
, task
. id
);
731 parse_task_status : function ( status
) {
732 if ( status
=== 'OK' ) {
736 if ( status
=== 'unknown' ) {
740 let match
= status
. match ( /^WARNINGS: (.*)$/ );
748 render_duration : function ( value
) {
749 if ( value
=== undefined ) {
752 return Proxmox
. Utils
. format_duration_human ( value
);
755 render_timestamp : function ( value
, metaData
, record
, rowIndex
, colIndex
, store
) {
756 let servertime
= new Date ( value
* 1000 );
757 return Ext
. Date
. format ( servertime
, 'Y-m-d H:i:s' );
760 render_zfs_health : function ( value
) {
761 if ( typeof value
=== 'undefined' ) {
764 var iconCls
= 'question-circle' ;
768 iconCls
= 'check-circle good' ;
772 iconCls
= 'exclamation-circle warning' ;
777 iconCls
= 'times-circle critical' ;
782 return '<i class="fa fa-' + iconCls
+ '"></i> ' + value
;
785 get_help_info : function ( section
) {
787 if ( typeof proxmoxOnlineHelpInfo
!== 'undefined' ) {
788 helpMap
= proxmoxOnlineHelpInfo
; // eslint-disable-line no-undef
789 } else if ( typeof pveOnlineHelpInfo
!== 'undefined' ) {
790 // be backward compatible with older pve-doc-generators
791 helpMap
= pveOnlineHelpInfo
; // eslint-disable-line no-undef
793 throw "no global OnlineHelpInfo map declared" ;
796 return helpMap
[ section
];
799 get_help_link : function ( section
) {
800 let info
= Proxmox
. Utils
. get_help_info ( section
);
804 return window
. location
. origin
+ info
. link
;
807 openXtermJsViewer : function ( vmtype
, vmid
, nodename
, vmname
, cmd
) {
808 let url
= Ext
. Object
. toQueryString ({
809 console
: vmtype
, // kvm, lxc, upgrade or shell
817 let nw
= window
. open ( "?" + url
, '_blank' , 'toolbar=no,location=no,status=no,menubar=no,resizable=yes,width=800,height=420' );
826 constructor : function () {
828 Ext
. apply ( me
, me
. utilities
);
830 let IPV4_OCTET
= "(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])" ;
831 let IPV4_REGEXP
= "(?:(?:" + IPV4_OCTET
+ " \\ .){3}" + IPV4_OCTET
+ ")" ;
832 let IPV6_H16
= "(?:[0-9a-fA-F]{1,4})" ;
833 let IPV6_LS32
= "(?:(?:" + IPV6_H16
+ ":" + IPV6_H16
+ ")|" + IPV4_REGEXP
+ ")" ;
834 let IPV4_CIDR_MASK
= "([0-9]{1,2})" ;
835 let IPV6_CIDR_MASK
= "([0-9]{1,3})" ;
838 me
. IP4_match
= new RegExp ( "^(?:" + IPV4_REGEXP
+ ")$" );
839 me
. IP4_cidr_match
= new RegExp ( "^(?:" + IPV4_REGEXP
+ ")/" + IPV4_CIDR_MASK
+ "$" );
841 /* eslint-disable no-useless-concat,no-multi-spaces */
842 let IPV6_REGEXP
= "(?:" +
843 "(?:(?:" + "(?:" + IPV6_H16
+ ":){6})" + IPV6_LS32
+ ")|" +
844 "(?:(?:" + "::" + "(?:" + IPV6_H16
+ ":){5})" + IPV6_LS32
+ ")|" +
845 "(?:(?:(?:" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){4})" + IPV6_LS32
+ ")|" +
846 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,1}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){3})" + IPV6_LS32
+ ")|" +
847 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,2}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){2})" + IPV6_LS32
+ ")|" +
848 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,3}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){1})" + IPV6_LS32
+ ")|" +
849 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,4}" + IPV6_H16
+ ")?::" + ")" + IPV6_LS32
+ ")|" +
850 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,5}" + IPV6_H16
+ ")?::" + ")" + IPV6_H16
+ ")|" +
851 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,7}" + IPV6_H16
+ ")?::" + ")" + ")" +
853 /* eslint-enable no-useless-concat,no-multi-spaces */
855 me
. IP6_match
= new RegExp ( "^(?:" + IPV6_REGEXP
+ ")$" );
856 me
. IP6_cidr_match
= new RegExp ( "^(?:" + IPV6_REGEXP
+ ")/" + IPV6_CIDR_MASK
+ "$" );
857 me
. IP6_bracket_match
= new RegExp ( "^ \\ [(" + IPV6_REGEXP
+ ") \\ ]" );
859 me
. IP64_match
= new RegExp ( "^(?:" + IPV6_REGEXP
+ "|" + IPV4_REGEXP
+ ")$" );
860 me
. IP64_cidr_match
= new RegExp ( "^(?:" + IPV6_REGEXP
+ "/" + IPV6_CIDR_MASK
+ ")|(?:" + IPV4_REGEXP
+ "/" + IPV4_CIDR_MASK
+ ")$" );
862 let DnsName_REGEXP
= "(?:(([a-zA-Z0-9]([a-zA-Z0-9 \\ -]*[a-zA-Z0-9])?) \\ .)*([A-Za-z0-9]([A-Za-z0-9 \\ -]*[A-Za-z0-9])?))" ;
863 me
. DnsName_match
= new RegExp ( "^" + DnsName_REGEXP
+ "$" );
865 me
. HostPort_match
= new RegExp ( "^(" + IPV4_REGEXP
+ "|" + DnsName_REGEXP
+ ")(: \\ d+)?$" );
866 me
. HostPortBrackets_match
= new RegExp ( "^ \\ [(?:" + IPV6_REGEXP
+ "|" + IPV4_REGEXP
+ "|" + DnsName_REGEXP
+ ") \\ ](: \\ d+)?$" );
867 me
. IP6_dotnotation_match
= new RegExp ( "^" + IPV6_REGEXP
+ "( \\ . \\ d+)?$" );
868 me
. Vlan_match
= /^vlan(\\d+)/ ;
869 me
. VlanInterface_match
= /(\\w+)\\.(\\d+)/ ;