]>
git.proxmox.com Git - pve-manager.git/blob - www/manager/Utils.js
8fd8fcf9136a87a1c1f41defa39079341110574e
3 // avoid errors when running without development tools
4 if (!Ext
.isDefined(Ext
.global
.console
)) {
10 console
.log("Starting PVE Manager");
12 Ext
.Ajax
.defaultHeaders
= {
13 'Accept': 'application/json'
16 // do not send '_dc' parameter
17 Ext
.Ajax
.disableCaching
= false;
19 Ext
.Ajax
.on('beforerequest', function(conn
, options
) {
20 if (PVE
.CSRFPreventionToken
) {
21 if (!options
.headers
) {
24 options
.headers
.CSRFPreventionToken
= PVE
.CSRFPreventionToken
;
29 Ext
.apply(Ext
.form
.field
.VTypes
, {
30 IPAddress: function(v
) {
31 return (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/).test(v
);
33 IPAddressText
: 'Must be a numeric IP address',
34 IPAddressMask
: /[\d\.]/i,
36 MacAddress: function(v
) {
37 return (/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/).test(v
);
39 MacAddressMask
: /[a-fA-F0-9:]/,
40 MacAddressText
: 'Must be a valid MAC address (example: "01:23:45:67:89:ab")',
42 BridgeName: function(v
) {
43 return (/^vmbr\d{1,4}$/).test(v
);
45 BridgeNameText
: 'Allowable bridge names: vmbr<b>N</b>, where 0 <= <b>N</b> <= 9999',
47 BondName: function(v
) {
48 return (/^bond\d{1,4}$/).test(v
);
50 BondNameText
: 'Allowable bond names: bond<b>N</b>, where 0 <= <b>N</b> <= 9999',
52 QemuStartDate: function(v
) {
53 return (/^(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)$/).test(v
);
55 QemuStartDateText
: 'Valid format for date are: "now" or "2006-06-17T16:01:21" or "2006-06-17"',
57 StorageId: function(v
) {
58 return (/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i).test(v
);
60 StorageIdText
: "ID contains illegal characters (allowed characters: 'a-z', '0-9', '-', '_' and '.')",
62 HttpProxy: function(v
) {
63 return (/^http:\/\/.*$/).test(v
);
65 HttpProxyText
: "Must confirm to schema 'http://.*' (example: 'http://username:password@host:port/')"
68 // we dont want that a displayfield set the form dirty flag!
69 Ext
.override(Ext
.form
.field
.Display
, {
70 isDirty: function() { return false; }
73 // hack: ExtJS does not display the correct value if we
74 // call setValue while the store is loading, so we need
75 // to call it again after loading
76 Ext
.override(Ext
.form
.field
.ComboBox
, {
78 this.setValue(this.value
, false);
79 this.callOverridden(arguments
);
83 Ext
.define('PVE.Utils', { statics
: {
85 // this class only contains static functions
100 wxp
: 'Microsoft Windows XP/2003',
101 w2k
: 'Microsoft Windows 2000',
102 w2k8
: 'Microsoft Windows Vista/2008',
103 win7
: 'Microsoft Windows 7/2008r2',
104 l24
: 'Linux 2.4 Kernel',
105 l26
: 'Linux 3.X/2.6 Kernel'
108 render_kvm_ostype: function (value
) {
112 var text
= PVE
.Utils
.kvm_ostypes
[value
];
114 return text
+ ' (' + value
+ ')';
119 // fixme: auto-generate this
120 // for now, please keep in sync with PVE::Tools::kvmkeymaps
125 'de-ch': 'German (Swiss)',
126 'en-gb': 'English (UK)',
127 'en-us': 'English (USA',
131 //fo: 'Faroe Islands',
133 'fr-be': 'French (Belgium)',
134 'fr-ca': 'French (Canada)',
135 'fr-ch': 'French (Swiss)',
145 //'nl-be': 'Dutch (Belgium)',
149 'pt-br': 'Portuguese (Brazil)',
159 vmware
: 'VMWare compatible',
160 cirrus
: 'Cirrus Logic GD5446'
163 render_kvm_language: function (value
) {
167 var text
= PVE
.Utils
.kvm_keymaps
[value
];
169 return text
+ ' (' + value
+ ')';
174 kvm_keymap_array: function() {
175 var data
= [['', PVE
.Utils
.render_kvm_language('')]];
176 Ext
.Object
.each(PVE
.Utils
.kvm_keymaps
, function(key
, value
) {
177 data
.push([key
, PVE
.Utils
.render_kvm_language(value
)]);
188 render_language: function (value
) {
190 return 'Default (English)';
192 var text
= PVE
.Utils
.language_map
[value
];
194 return text
+ ' (' + value
+ ')';
199 language_array: function() {
200 var data
= [['', PVE
.Utils
.render_language('')]];
201 Ext
.Object
.each(PVE
.Utils
.language_map
, function(key
, value
) {
202 data
.push([key
, PVE
.Utils
.render_language(value
)]);
208 render_kvm_vga_driver: function (value
) {
212 var text
= PVE
.Utils
.kvm_vga_drivers
[value
];
214 return text
+ ' (' + value
+ ')';
219 kvm_vga_driver_array: function() {
220 var data
= [['', PVE
.Utils
.render_kvm_vga_driver('')]];
221 Ext
.Object
.each(PVE
.Utils
.kvm_vga_drivers
, function(key
, value
) {
222 data
.push([key
, PVE
.Utils
.render_kvm_vga_driver(value
)]);
229 return Ext
.util
.Cookies
.get('PVEAuthCookie');
232 authClear: function() {
233 Ext
.util
.Cookies
.clear("PVEAuthCookie");
236 // fixme: remove - not needed?
237 gridLineHeigh: function() {
245 extractRequestError: function(result
, verbose
) {
246 var msg
= 'Successful';
248 if (!result
.success
) {
249 msg
= "Unknown error";
250 if (result
.message
) {
251 msg
= result
.message
;
253 msg
+= ' (' + result
.status
+ ')';
256 if (verbose
&& Ext
.isObject(result
.errors
)) {
258 Ext
.Object
.each(result
.errors
, function(prop
, desc
) {
259 msg
+= "<br><b>" + Ext
.htmlEncode(prop
) + "</b>: " +
260 Ext
.htmlEncode(desc
);
268 extractFormActionError: function(action
) {
270 switch (action
.failureType
) {
271 case Ext
.form
.action
.Action
.CLIENT_INVALID
:
272 msg
= 'Form fields may not be submitted with invalid values';
274 case Ext
.form
.action
.Action
.CONNECT_FAILURE
:
275 msg
= 'Connect failure';
276 var resp
= action
.response
;
277 if (resp
.status
&& resp
.statusText
) {
278 msg
+= " " + resp
.status
+ ": " + resp
.statusText
;
281 case Ext
.form
.action
.Action
.LOAD_FAILURE
:
282 case Ext
.form
.action
.Action
.SERVER_INVALID
:
283 msg
= PVE
.Utils
.extractRequestError(action
.result
, true);
290 API2Request: function(reqOpts
) {
292 var newopts
= Ext
.apply({
293 waitMsg
: 'Please wait...'
296 if (!newopts
.url
.match(/^\/api2/)) {
297 newopts
.url
= '/api2/extjs' + newopts
.url
;
299 delete newopts
.callback
;
301 var createWrapper = function(successFn
, callbackFn
, failureFn
) {
303 success: function(response
, options
) {
304 if (options
.waitMsgTarget
) {
305 options
.waitMsgTarget
.setLoading(false);
307 var result
= Ext
.decode(response
.responseText
);
308 response
.result
= result
;
309 if (!result
.success
) {
310 response
.htmlStatus
= PVE
.Utils
.extractRequestError(result
, true);
311 Ext
.callback(callbackFn
, options
.scope
, [options
, false, response
]);
312 Ext
.callback(failureFn
, options
.scope
, [response
, options
]);
315 Ext
.callback(callbackFn
, options
.scope
, [options
, true, response
]);
316 Ext
.callback(successFn
, options
.scope
, [response
, options
]);
318 failure: function(response
, options
) {
319 if (options
.waitMsgTarget
) {
320 options
.waitMsgTarget
.setLoading(false);
322 response
.result
= {};
324 response
.result
= Ext
.decode(response
.responseText
);
326 var msg
= "Connection error - server offline?";
327 if (response
.aborted
) {
328 msg
= 'Transaction aborted.';
329 } else if (response
.timedout
) {
330 msg
= 'Communication failure: Timeout.';
331 } else if (response
.status
&& response
.statusText
) {
332 msg
= 'Connection error ' + response
.status
+ ': ' + response
.statusText
;
334 response
.htmlStatus
= msg
;
335 Ext
.callback(callbackFn
, options
.scope
, [options
, false, response
]);
336 Ext
.callback(failureFn
, options
.scope
, [response
, options
]);
341 createWrapper(reqOpts
.success
, reqOpts
.callback
, reqOpts
.failure
);
343 var target
= newopts
.waitMsgTarget
;
345 // Note: ExtJS bug - this does not work when component is not rendered
346 target
.setLoading(newopts
.waitMsg
, true);
348 Ext
.Ajax
.request(newopts
);
351 assemble_field_data: function(values
, data
) {
352 if (Ext
.isObject(data
)) {
353 Ext
.Object
.each(data
, function(name
, val
) {
354 if (values
.hasOwnProperty(name
)) {
355 var bucket
= values
[name
];
356 if (!Ext
.isArray(bucket
)) {
357 bucket
= values
[name
] = [bucket
];
359 if (Ext
.isArray(val
)) {
360 values
[name
] = bucket
.concat(val
);
372 vncproxy
: 'VNC connection to VM/CT {0}',
373 vncshell
: 'VNC shell',
374 qmcreate
: 'Create VM {0}',
375 qmrestore
: 'Restore VM {0}',
376 qmdestroy
: 'Destroy VM {0}',
377 qmigrate
: 'Migrate VM {0}',
378 qmstart
: 'Start VM {0}',
379 qmstop
: 'Stop VM {0}',
380 qmreset
: 'Reset VM {0}',
381 qmshutdown
: 'Shutdown VM {0}',
382 qmsuspend
: 'Suspend VM {0}',
383 qmresume
: 'Resume VM {0}',
384 vzcreate
: 'Create CT {0}',
385 vzrestore
: 'Restore CT {0}',
386 vzdestroy
: 'Destroy CT {0}',
387 vzstart
: 'Start CT {0}',
388 vzstop
: 'Stop CT {0}',
389 srvstart
: 'Start service {0}',
390 srvstop
: 'Stop service {0}',
391 srvrestart
: 'Restart service {0}',
392 srvreload
: 'Reload service {0}',
396 format_task_description: function(type
, id
) {
397 var format
= PVE
.Utils
.task_desc_table
[type
];
399 return Ext
.String
.format(format
, id
);
404 parse_task_upid: function(upid
) {
407 var res
= upid
.match(/^UPID:(\S+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/);
409 throw "unable to parse upid '" + upid
+ "'";
412 task
.pid
= parseInt(res
[2], 16);
413 task
.pstart
= parseInt(res
[3], 16);
414 task
.starttime
= parseInt(res
[4], 16);
419 task
.desc
= PVE
.Utils
.format_task_description(task
.type
, task
.id
);
424 format_size: function(size
) {
425 /*jslint confusion: true */
431 var kb
= size
/ 1024;
434 return kb
.toFixed(0) + "KB";
437 var mb
= size
/ (1024*1024);
440 return mb
.toFixed(0) + "MB";
446 return gb
.toFixed(2) + "GB";
451 return tb
.toFixed(2) + "TB";
455 format_html_bar: function(per
, text
) {
457 return "<div class='pve-bar-wrap'>" + text
+ "<div class='pve-bar-border'>" +
458 "<div class='pve-bar-inner' style='width:" + per
+ "%;'></div>" +
463 format_cpu_bar: function(per1
, per2
, text
) {
465 return "<div class='pve-bar-border'>" +
466 "<div class='pve-bar-inner' style='width:" + per1
+ "%;'></div>" +
467 "<div class='pve-bar-inner2' style='width:" + per2
+ "%;'></div>" +
468 "<div class='pve-bar-text'>" + text
+ "</div>" +
472 format_large_bar: function(per
, text
) {
475 text
= per
.toFixed(1) + "%";
478 return "<div class='pve-largebar-border'>" +
479 "<div class='pve-largebar-inner' style='width:" + per
+ "%;'></div>" +
480 "<div class='pve-largebar-text'>" + text
+ "</div>" +
484 format_duration_long: function(ut
) {
486 var days
= Math
.floor(ut
/ 86400);
488 var hours
= Math
.floor(ut
/ 3600);
490 var mins
= Math
.floor(ut
/ 60);
493 var hours_str
= '00' + hours
.toString();
494 hours_str
= hours_str
.substr(hours_str
.length
- 2);
495 var mins_str
= "00" + mins
.toString();
496 mins_str
= mins_str
.substr(mins_str
.length
- 2);
497 var ut_str
= "00" + ut
.toString();
498 ut_str
= ut_str
.substr(ut_str
.length
- 2);
501 var ds
= days
> 1 ? 'days' : 'day';
502 return days
.toString() + ' ' + ds
+ ' ' +
503 hours_str
+ ':' + mins_str
+ ':' + ut_str
;
505 return hours_str
+ ':' + mins_str
+ ':' + ut_str
;
509 format_duration_short: function(ut
) {
512 return ut
.toString() + 's';
517 return mins
.toFixed(0) + 'm';
521 var hours
= ut
/ 3600;
522 return hours
.toFixed(0) + 'h';
525 var days
= ut
/ 86400;
526 return days
.toFixed(0) + 'd';
529 format_storage_type: function(value
) {
530 if (value
=== 'dir') {
532 } else if (value
=== 'nfs') {
534 } else if (value
=== 'lvm') {
536 } else if (value
=== 'iscsi') {
543 format_boolean_with_default: function(value
) {
544 if (Ext
.isDefined(value
) && value
!== '') {
545 return value
? 'Yes' : 'No';
550 format_boolean: function(value
) {
551 return value
? 'Yes' : 'No';
554 format_neg_boolean: function(value
) {
555 return !value
? 'Yes' : 'No';
558 format_content_types: function(value
) {
561 Ext
.each(value
.split(',').sort(), function(ct
) {
562 if (ct
=== 'images') {
564 } else if (ct
=== 'backup') {
566 } else if (ct
=== 'vztmpl') {
567 cta
.push('Templates');
568 } else if (ct
=== 'iso') {
570 } else if (ct
=== 'rootdir') {
571 cta
.push('Containers');
575 return cta
.join(', ');
578 render_storage_content: function(value
, metaData
, record
) {
579 var data
= record
.data
;
580 if (Ext
.isNumber(data
.channel
) &&
581 Ext
.isNumber(data
.id
) &&
582 Ext
.isNumber(data
.lun
)) {
584 Ext
.String
.leftPad(data
.channel
,2, '0') +
585 " ID " + data
.id
+ " LUN " + data
.lun
;
587 return data
.volid
.replace(/^.*:(.*\/)?/,'');
590 render_serverity: function (value
) {
591 return PVE
.Utils
.log_severity_hash
[value
] || value
;
594 render_cpu: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
596 if (!(record
.data
.uptime
&& Ext
.isNumeric(value
))) {
600 var maxcpu
= record
.data
.maxcpu
|| 1;
602 if (!Ext
.isNumeric(maxcpu
) && (maxcpu
>= 1)) {
606 var per
= value
* 100;
608 return per
.toFixed(1) + '% of ' + maxcpu
.toString() + (maxcpu
> 1 ? 'CPUs' : 'CPU');
611 render_size: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
612 /*jslint confusion: true */
614 if (!Ext
.isNumeric(value
)) {
618 return PVE
.Utils
.format_size(value
);
621 render_timestamp: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
622 var servertime
= new Date(value
* 1000);
623 return Ext
.Date
.format(servertime
, 'Y-m-d H:i:s');
626 render_mem_usage: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
629 var maxmem
= record
.data
.maxmem
;
631 if (!record
.data
.uptime
) {
635 if (!(Ext
.isNumeric(mem
) && maxmem
)) {
639 var per
= (mem
* 100) / maxmem
;
641 return per
.toFixed(1) + '%';
644 render_disk_usage: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
647 var maxdisk
= record
.data
.maxdisk
;
649 if (!(Ext
.isNumeric(disk
) && maxdisk
)) {
653 var per
= (disk
* 100) / maxdisk
;
655 return per
.toFixed(1) + '%';
658 render_resource_type: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
660 var cls
= 'pve-itype-icon-' + value
;
662 if (record
.data
.running
) {
663 metaData
.tdCls
= cls
+ "-running";
665 metaData
.tdCls
= cls
;
671 render_uptime: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
675 if (uptime
=== undefined) {
683 return PVE
.Utils
.format_duration_long(uptime
);
686 render_upid: function(value
, metaData
, record
) {
687 var type
= record
.data
.type
;
688 var id
= record
.data
.id
;
690 return PVE
.Utils
.format_task_description(type
, id
);
693 openConoleWindow: function(vmtype
, vmid
, nodename
) {
694 var url
= Ext
.urlEncode({
695 console
: vmtype
, // kvm or openvz
699 var nw
= window
.open("?" + url
, '_blank',
700 "innerWidth=745,innerheight=427");