'Accept': 'application/json'
};
-// do not send '_dc' parameter
-Ext.Ajax.disableCaching = false;
-
Ext.Ajax.on('beforerequest', function(conn, options) {
if (PVE.CSRFPreventionToken) {
if (!options.headers) {
var IP64_match = new RegExp("^(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + ")$");
-// custom Vtypes
-Ext.apply(Ext.form.field.VTypes, {
- IPAddress: function(v) {
- return IP4_match.test(v);
- },
- IPAddressText: gettext('Example') + ': 192.168.1.1',
- IPAddressMask: /[\d\.]/i,
-
- IP64Address: function(v) {
- return IP64_match.test(v);
- },
- IP64AddressText: gettext('Example') + ': 192.168.1.1 2001:DB8::42',
- IP64AddressMask: /[A-Fa-f0-9\.:]/,
-
- MacAddress: function(v) {
- return (/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/).test(v);
- },
- MacAddressMask: /[a-fA-F0-9:]/,
- MacAddressText: gettext('Example') + ': 01:23:45:67:89:ab',
-
- BridgeName: function(v) {
- return (/^vmbr\d{1,4}$/).test(v);
- },
- BridgeNameText: gettext('Format') + ': vmbr<b>N</b>, where 0 <= <b>N</b> <= 9999',
-
- BondName: function(v) {
- return (/^bond\d{1,4}$/).test(v);
- },
- BondNameText: gettext('Format') + ': bond<b>N</b>, where 0 <= <b>N</b> <= 9999',
-
- QemuStartDate: function(v) {
- return (/^(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)$/).test(v);
- },
- QemuStartDateText: gettext('Format') + ': "now" or "2006-06-17T16:01:21" or "2006-06-17"',
-
- StorageId: function(v) {
- return (/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i).test(v);
- },
- StorageIdText: gettext("Allowed characters") + ": 'a-z', '0-9', '-', '_', '.'",
-
- HttpProxy: function(v) {
- return (/^http:\/\/.*$/).test(v);
- },
- HttpProxyText: gettext('Example') + ": http://username:password@host:port/",
-
- DnsName: function(v) {
- return (/^(([a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?)\.)*([A-Za-z0-9]([A-Za-z0-9\-]*[A-Za-z0-9])?)$/).test(v);
- },
- DnsNameText: gettext('This is not a valid DNS name')
-});
-
-// we dont want that a displayfield set the form dirty flag!
-Ext.override(Ext.form.field.Display, {
- isDirty: function() { return false; }
-});
-
-// hack: ExtJS does not display the correct value if we
-// call setValue while the store is loading, so we need
-// to call it again after loading
-Ext.override(Ext.form.field.ComboBox, {
- onLoad: function() {
- this.setValue(this.value, false);
- this.callOverridden(arguments);
- }
-});
-
Ext.define('PVE.Utils', { statics: {
// this class only contains static functions
+ toolkit: undefined, // (extjs|touch), set inside Toolkit.js
+
log_severity_hash: {
0: "panic",
1: "alert",
return value;
},
+ render_hotplug_features: function (value) {
+ var fa = [];
+
+ if (!value || (value === '0')) {
+ return gettext('disabled');
+ }
+
+ Ext.each(value.split(','), function(el) {
+ if (el === 'disk') {
+ fa.push(gettext('Disk'));
+ } else if (el === 'network') {
+ fa.push(gettext('Network'));
+ } else if (el === 'usb') {
+ fa.push(gettext('USB'));
+ } else if (el === 'memory') {
+ fa.push(gettext('Memory'));
+ } else if (el === 'cpu') {
+ fa.push(gettext('CPU'));
+ } else {
+ fa.push(el);
+ }
+ });
+
+ return fa.join(', ');
+ },
+
+ network_iface_types: {
+ eth: gettext("Network Device"),
+ bridge: 'Linux Bridge',
+ bond: 'Linux Bond',
+ OVSBridge: 'OVS Bridge',
+ OVSBond: 'OVS Bond',
+ OVSPort: 'OVS Port',
+ OVSIntPort: 'OVS IntPort'
+ },
+
+ render_network_iface_type: function(value) {
+ return PVE.Utils.network_iface_types[value] ||
+ PVE.Utils.unknownText;
+ },
+
render_scsihw: function(value) {
if (!value) {
return PVE.Utils.defaultText + ' (LSI 53C895A)';
render_console_viewer: function(value) {
if (!value) {
- return PVE.Utils.defaultText + ' (Java VNC Applet)';
+ return PVE.Utils.defaultText + ' (HTML5)';
} else if (value === 'applet') {
return 'Java VNC Applet';
} else if (value === 'vv') {
return 'SPICE (remote-viewer)';
+ } else if (value === 'html5') {
+ return 'HTML5 (noVNC)';
} else {
return value;
}
language_map: {
zh_CN: 'Chinese',
ca: 'Catalan',
- ja: 'Japanese',
- en: 'English',
da: 'Danish',
- de: 'German',
- es: 'Spanish',
+ en: 'English',
+ eu: 'Euskera (Basque)',
fr: 'French',
+ de: 'German',
it: 'Italian',
+ ja: 'Japanese',
nb: 'Norwegian (Bokmal)',
nn: 'Norwegian (Nynorsk)',
+ fa: 'Persian (Farsi)',
+ pl: 'Polish',
+ pt_BR: 'Portuguese (Brazil)',
ru: 'Russian',
sl: 'Slovenian',
+ es: 'Spanish',
sv: 'Swedish',
- pl: 'Polish',
- pt_BR: 'Portuguese (Brazil)',
tr: 'Turkish'
},
Ext.apply(newopts, {
success: function(response, options) {
if (options.waitMsgTarget) {
- options.waitMsgTarget.setLoading(false);
+ if (PVE.Utils.toolkit === 'touch') {
+ options.waitMsgTarget.setMasked(false);
+ } else {
+ options.waitMsgTarget.setLoading(false);
+ }
}
var result = Ext.decode(response.responseText);
response.result = result;
},
failure: function(response, options) {
if (options.waitMsgTarget) {
- options.waitMsgTarget.setLoading(false);
+ if (PVE.Utils.toolkit === 'touch') {
+ options.waitMsgTarget.setMasked(false);
+ } else {
+ options.waitMsgTarget.setLoading(false);
+ }
}
response.result = {};
try {
var target = newopts.waitMsgTarget;
if (target) {
- // Note: ExtJS bug - this does not work when component is not rendered
- target.setLoading(newopts.waitMsg);
+ if (PVE.Utils.toolkit === 'touch') {
+ target.setMasked({ xtype: 'loadmask', message: newopts.waitMsg} );
+ } else {
+ // Note: ExtJS bug - this does not work when component is not rendered
+ target.setLoading(newopts.waitMsg);
+ }
}
Ext.Ajax.request(newopts);
},
vzmount: ['CT', gettext('Mount') ],
vzumount: ['CT', gettext('Unmount') ],
vzshutdown: ['CT', gettext('Shutdown') ],
+ vzsuspend: [ 'CT', gettext('Suspend') ],
+ vzresume: [ 'CT', gettext('Resume') ],
hamigrate: [ 'HA', gettext('Migrate') ],
hastart: [ 'HA', gettext('Start') ],
hastop: [ 'HA', gettext('Stop') ],
srvstop: ['SRV', gettext('Stop') ],
srvrestart: ['SRV', gettext('Restart') ],
srvreload: ['SRV', gettext('Reload') ],
+ cephcreatemon: ['Ceph Monitor', gettext('Create') ],
+ cephdestroymon: ['Ceph Monitor', gettext('Destroy') ],
+ cephcreateosd: ['Ceph OSD', gettext('Create') ],
+ cephdestroyosd: ['Ceph OSD', gettext('Destroy') ],
imgcopy: ['', gettext('Copy data') ],
imgdel: ['', gettext('Erase data') ],
download: ['', gettext('Download') ],
vzdump: ['', gettext('Backup') ],
aptupdate: ['', gettext('Update package database') ],
startall: [ '', gettext('Start all VMs and Containers') ],
- stopall: [ '', gettext('Stop all VMs and Containers') ]
+ stopall: [ '', gettext('Stop all VMs and Containers') ],
+ migrateall: [ '', gettext('Migrate all VMs and Containers') ]
},
format_task_description: function(type, id) {
yesText: gettext('Yes'),
noText: gettext('No'),
+ noneText: gettext('none'),
errorText: gettext('Error'),
unknownText: gettext('Unknown'),
defaultText: gettext('Default'),
neverText: gettext('never'),
totalText: gettext('Total'),
usedText: gettext('Used'),
+ directoryText: gettext('Directory'),
+ imagesText: gettext('Disk image'),
+ backupFileText: gettext('VZDump backup file'),
+ vztmplText: gettext('OpenVZ template'),
+ isoImageText: gettext('ISO image'),
+ containersText: gettext('OpenVZ Container'),
format_expire: function(date) {
if (!date) {
format_storage_type: function(value) {
if (value === 'dir') {
- return 'Directory';
+ return PVE.Utils.directoryText;
} else if (value === 'nfs') {
return 'NFS';
} else if (value === 'glusterfs') {
} else if (value === 'sheepdog') {
return 'Sheepdog';
} else if (value === 'zfs') {
+ return 'ZFS over iSCSI';
+ } else if (value === 'zfspool') {
return 'ZFS';
} else if (value === 'iscsidirect') {
return 'iSCSIDirect';
Ext.each(value.split(',').sort(), function(ct) {
if (ct === 'images') {
- cta.push('Images');
+ cta.push(PVE.Utils.imagesText);
} else if (ct === 'backup') {
- cta.push('Backups');
+ cta.push(PVE.Utils.backupFileText);
} else if (ct === 'vztmpl') {
- cta.push('Templates');
+ cta.push(PVE.Utils.vztmplText);
} else if (ct === 'iso') {
- cta.push('ISO');
+ cta.push(PVE.Utils.isoImageText);
} else if (ct === 'rootdir') {
- cta.push('Containers');
+ cta.push(PVE.Utils.containersText);
}
});
}
},
- openConsoleWindow: function(vmtype, vmid, nodename, vmname) {
+ openDefaultConsoleWindow: function(allowSpice, vmtype, vmid, nodename, vmname) {
+ var dv = PVE.Utils.defaultViewer(allowSpice);
+ PVE.Utils.openConsoleWindow(dv, vmtype, vmid, nodename, vmname);
+ },
+
+ openConsoleWindow: function(viewer, vmtype, vmid, nodename, vmname) {
+ // kvm, openvz, shell, upgrade
+
+ if (vmid == undefined && (vmtype === 'kvm' || vmtype === 'openvz')) {
+ throw "missing vmid";
+ }
+
+ if (!nodename) {
+ throw "no nodename specified";
+ }
+
+ if (viewer === 'applet' || viewer === 'html5') {
+ PVE.Utils.openVNCViewer(vmtype, vmid, nodename, vmname, viewer === 'html5');
+ } else if (viewer === 'vv') {
+ var url;
+ var params = { proxy: window.location.hostname };
+ if (vmtype === 'kvm') {
+ url = '/nodes/' + nodename + '/qemu/' + vmid.toString() + '/spiceproxy';
+ PVE.Utils.openSpiceViewer(url, params);
+ } else if (vmtype === 'openvz') {
+ url = '/nodes/' + nodename + '/openvz/' + vmid.toString() + '/spiceproxy';
+ PVE.Utils.openSpiceViewer(url, params);
+ } else if (vmtype === 'shell') {
+ url = '/nodes/' + nodename + '/spiceshell';
+ PVE.Utils.openSpiceViewer(url, params);
+ } else if (vmtype === 'upgrade') {
+ url = '/nodes/' + nodename + '/spiceshell';
+ params.upgrade = 1;
+ PVE.Utils.openSpiceViewer(url, params);
+ }
+ } else {
+ throw "unknown viewer type";
+ }
+ },
+
+ defaultViewer: function(allowSpice) {
+ var vncdefault = 'html5';
+ var dv = PVE.VersionInfo.console || vncdefault;
+ if (dv === 'vv' && !allowSpice) {
+ dv = vncdefault;
+ }
+
+ return dv;
+ },
+
+ openVNCViewer: function(vmtype, vmid, nodename, vmname, novnc) {
var url = Ext.urlEncode({
- console: vmtype, // kvm, openvz or shell
+ console: vmtype, // kvm, openvz, upgrade or shell
+ novnc: novnc ? 1 : 0,
vmid: vmid,
vmname: vmname,
node: nodename
});
- var nw = window.open("?" + url, '_blank',
- "innerWidth=745,innerheight=427");
+ var nw = window.open("?" + url, '_blank', "innerWidth=745,innerheight=427");
nw.focus();
},
- defaultViewer: function(){
- return PVE.VersionInfo.console || 'applet';
- },
-
openSpiceViewer: function(url, params){
+
+ var downloadWithName = function(uri, name) {
+ var link = Ext.DomHelper.append(document.body, {
+ tag: 'a',
+ href: uri,
+ css : 'display:none;visibility:hidden;height:0px;'
+ });
+
+ // Note: we need to tell android the correct file name extension
+ // but we do not set 'download' tag for other environments, because
+ // It can have strange side effects (additional user prompt on firefox)
+ var andriod = navigator.userAgent.match(/Android/i) ? true : false;
+ if (andriod) {
+ link.download = name;
+ }
+
+ if (link.fireEvent) {
+ link.fireEvent('onclick');
+ } else {
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
+ link.dispatchEvent(evt);
+ }
+ };
+
PVE.Utils.API2Request({
url: url,
params: params,
var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
encodeURIComponent(raw);
- window.open(url, "_top");
+ downloadWithName(url, "pve-spice.vv");
}
});
},