}
});
+var IPV4_OCTET = "(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])";
+var IPV4_REGEXP = "(?:(?:" + IPV4_OCTET + "\\.){3}" + IPV4_OCTET + ")";
+var IPV6_H16 = "(?:[0-9a-fA-F]{1,4})";
+var IPV6_LS32 = "(?:(?:" + IPV6_H16 + ":" + IPV6_H16 + ")|" + IPV4_REGEXP + ")";
+
+
+var IP4_match = new RegExp("^(?:" + IPV4_REGEXP + ")$");
+
+var IPV6_REGEXP = "(?:" +
+ "(?:(?:" + "(?:" + IPV6_H16 + ":){6})" + IPV6_LS32 + ")|" +
+ "(?:(?:" + "::" + "(?:" + IPV6_H16 + ":){5})" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){4})" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,1}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){3})" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,2}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){2})" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,3}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){1})" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,4}" + IPV6_H16 + ")?::" + ")" + IPV6_LS32 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,5}" + IPV6_H16 + ")?::" + ")" + IPV6_H16 + ")|" +
+ "(?:(?:(?:(?:" + IPV6_H16 + ":){0,7}" + IPV6_H16 + ")?::" + ")" + ")" +
+ ")";
+
+var IP64_match = new RegExp("^(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + ")$");
+
// custom Vtypes
Ext.apply(Ext.form.field.VTypes, {
IPAddress: function(v) {
- return (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/).test(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);
},
},
BondNameText: gettext('Format') + ': bond<b>N</b>, where 0 <= <b>N</b> <= 9999',
+ InterfaceName: function(v) {
+ return (/^[a-z][a-z0-9_]{1,20}$/).test(v);
+ },
+ InterfaceNameText: gettext('Format') + ': [a-z][a-z0-9_]{1,20}',
+
+
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);
},
HttpProxyText: gettext('Example') + ": http://username:password@host:port/",
DnsName: function(v) {
- return (/^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/).test(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')
});
7: "debug"
},
+ support_level_hash: {
+ 'c': gettext('Community'),
+ 'b': gettext('Basic'),
+ 's': gettext('Standard'),
+ 'p': gettext('Premium')
+ },
+
+ noSubKeyHtml: 'You do not have a valid subscription for this server. Please visit <a target="_blank" href="http://www.proxmox.com/products/proxmox-ve/subscription-service-plans">www.proxmox.com</a> to get a list of available options.',
+
kvm_ostypes: {
other: gettext('Other OS types'),
wxp: 'Microsoft Windows XP/2003',
w2k: 'Microsoft Windows 2000',
w2k8: 'Microsoft Windows Vista/2008',
win7: 'Microsoft Windows 7/2008r2',
+ win8: 'Microsoft Windows 8/2012',
l24: 'Linux 2.4 Kernel',
- l26: 'Linux 3.X/2.6 Kernel'
+ l26: 'Linux 3.X/2.6 Kernel',
+ solaris: 'Solaris Kernel'
},
render_kvm_ostype: function (value) {
return value;
},
+ 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)';
+ } else if (value === 'lsi') {
+ return 'LSI 53C895A';
+ } else if (value === 'lsi53c810') {
+ return 'LSI 53C810';
+ } else if (value === 'megasas') {
+ return 'MegaRAID SAS 8708EM2';
+ } else if (value === 'virtio-scsi-pci') {
+ return 'VIRTIO';
+ } else if (value === 'pvscsi') {
+ return 'VMware PVSCSI';
+ } else {
+ return value;
+ }
+ },
+
// fixme: auto-generate this
// for now, please keep in sync with PVE::Tools::kvmkeymaps
kvm_keymaps: {
pt: 'Portuguese',
'pt-br': 'Portuguese (Brazil)',
//ru: 'Russian',
- si: 'Slovenian',
- sv: 'Swedish'
+ sl: 'Slovenian',
+ sv: 'Swedish',
//th: 'Thai',
- //tr: 'Turkish'
+ tr: 'Turkish'
},
kvm_vga_drivers: {
- std: 'Standard VGA',
- vmware: 'VMWare compatible',
- cirrus: 'Cirrus Logic GD5446'
+ std: gettext('Standard VGA'),
+ vmware: gettext('VMWare compatible'),
+ cirrus: 'Cirrus Logic GD5446',
+ qxl: 'SPICE',
+ qxl2: 'SPICE dual monitor',
+ qxl3: 'SPICE three monitors',
+ qxl4: 'SPICE four monitors',
+ serial0: gettext('Serial terminal') + ' 0',
+ serial1: gettext('Serial terminal') + ' 1',
+ serial2: gettext('Serial terminal') + ' 2',
+ serial3: gettext('Serial terminal') + ' 3'
},
render_kvm_language: function (value) {
return data;
},
+ render_console_viewer: function(value) {
+ if (!value) {
+ return PVE.Utils.defaultText + ' (Java VNC Applet)';
+ } else if (value === 'applet') {
+ return 'Java VNC Applet';
+ } else if (value === 'vv') {
+ return 'SPICE (remote-viewer)';
+ } else {
+ return value;
+ }
+ },
+
language_map: {
+ zh_CN: 'Chinese',
+ ca: 'Catalan',
ja: 'Japanese',
en: 'English',
+ da: 'Danish',
de: 'German',
es: 'Spanish',
fr: 'French',
- sv: 'Swedish'
+ it: 'Italian',
+ nb: 'Norwegian (Bokmal)',
+ nn: 'Norwegian (Nynorsk)',
+ ru: 'Russian',
+ sl: 'Slovenian',
+ sv: 'Swedish',
+ pl: 'Polish',
+ pt_BR: 'Portuguese (Brazil)',
+ tr: 'Turkish'
},
render_language: function (value) {
return data;
},
+ render_kvm_startup: function(value) {
+ var startup = PVE.Parser.parseStartup(value);
+
+ var res = 'order=';
+ if (startup.order === undefined) {
+ res += 'any';
+ } else {
+ res += startup.order;
+ }
+ if (startup.up !== undefined) {
+ res += ',up=' + startup.up;
+ }
+ if (startup.down !== undefined) {
+ res += ',down=' + startup.down;
+ }
+
+ return res;
+ },
+
authOK: function() {
return Ext.util.Cookies.get('PVEAuthCookie');
},
var target = newopts.waitMsgTarget;
if (target) {
// Note: ExtJS bug - this does not work when component is not rendered
- target.setLoading(newopts.waitMsg, true);
+ target.setLoading(newopts.waitMsg);
}
Ext.Ajax.request(newopts);
},
}
},
+ checked_command: function(orig_cmd) {
+ PVE.Utils.API2Request({
+ url: '/nodes/localhost/subscription',
+ method: 'GET',
+ //waitMsgTarget: me,
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ success: function(response, opts) {
+ var data = response.result.data;
+
+ if (data.status !== 'Active') {
+ Ext.Msg.show({
+ title: gettext('No valid subscription'),
+ icon: Ext.Msg.WARNING,
+ msg: PVE.Utils.noSubKeyHtml,
+ buttons: Ext.Msg.OK,
+ callback: function(btn) {
+ if (btn !== 'ok') {
+ return;
+ }
+ orig_cmd();
+ }
+ });
+ } else {
+ orig_cmd();
+ }
+ }
+ });
+ },
+
task_desc_table: {
vncproxy: [ 'VM/CT', gettext('Console') ],
+ spiceproxy: [ 'VM/CT', gettext('Console') + ' (Spice)' ],
vncshell: [ '', gettext('Shell') ],
+ spiceshell: [ '', gettext('Shell') + ' (Spice)' ],
+ qmsnapshot: [ 'VM', gettext('Snapshot') ],
+ qmrollback: [ 'VM', gettext('Rollback') ],
+ qmdelsnapshot: [ 'VM', gettext('Delete Snapshot') ],
qmcreate: [ 'VM', gettext('Create') ],
qmrestore: [ 'VM', gettext('Restore') ],
qmdestroy: [ 'VM', gettext('Destroy') ],
qmigrate: [ 'VM', gettext('Migrate') ],
+ qmclone: [ 'VM', gettext('Clone') ],
+ qmmove: [ 'VM', gettext('Move disk') ],
+ qmtemplate: [ 'VM', gettext('Convert to template') ],
qmstart: [ 'VM', gettext('Start') ],
qmstop: [ 'VM', gettext('Stop') ],
qmreset: [ 'VM', gettext('Reset') ],
qmshutdown: [ 'VM', gettext('Shutdown') ],
qmsuspend: [ 'VM', gettext('Suspend') ],
qmresume: [ 'VM', gettext('Resume') ],
+ qmconfig: [ 'VM', gettext('Configure') ],
vzcreate: ['CT', gettext('Create') ],
vzrestore: ['CT', gettext('Restore') ],
vzdestroy: ['CT', gettext('Destroy') ],
vzmount: ['CT', gettext('Mount') ],
vzumount: ['CT', gettext('Unmount') ],
vzshutdown: ['CT', gettext('Shutdown') ],
+ hamigrate: [ 'HA', gettext('Migrate') ],
+ hastart: [ 'HA', gettext('Start') ],
+ hastop: [ 'HA', gettext('Stop') ],
srvstart: ['SRV', gettext('Start') ],
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') ]
+ vzdump: ['', gettext('Backup') ],
+ aptupdate: ['', gettext('Update package database') ],
+ startall: [ '', gettext('Start all VMs and Containers') ],
+ stopall: [ '', gettext('Stop all VMs and Containers') ]
},
format_task_description: function(type, id) {
parse_task_upid: function(upid) {
var task = {};
- var res = upid.match(/^UPID:(\S+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/);
+ var res = upid.match(/^UPID:(\S+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8,9}):([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/);
if (!res) {
throw "unable to parse upid '" + upid + "'";
}
runningText: gettext('running'),
stoppedText: gettext('stopped'),
neverText: gettext('never'),
+ totalText: gettext('Total'),
+ usedText: gettext('Used'),
format_expire: function(date) {
if (!date) {
return 'Directory';
} else if (value === 'nfs') {
return 'NFS';
+ } else if (value === 'glusterfs') {
+ return 'GlusterFS';
} else if (value === 'lvm') {
return 'LVM';
} else if (value === 'iscsi') {
return 'iSCSI';
+ } else if (value === 'rbd') {
+ return 'RBD';
+ } else if (value === 'sheepdog') {
+ return 'Sheepdog';
+ } else if (value === 'zfs') {
+ return 'ZFS';
+ } else if (value === 'iscsidirect') {
+ return 'iSCSIDirect';
} else {
return PVE.Utils.unknownText;
}
if (record.data.running) {
metaData.tdCls = cls + "-running";
+ } else if (record.data.template) {
+ metaData.tdCls = cls + "-template";
} else {
metaData.tdCls = cls;
}
return PVE.Utils.format_duration_long(uptime);
},
+ render_support_level: function(value, metaData, record) {
+ return PVE.Utils.support_level_hash[value] || '-';
+ },
+
render_upid: function(value, metaData, record) {
var type = record.data.type;
var id = record.data.id;
}
},
- openConoleWindow: function(vmtype, vmid, nodename, vmname) {
+ openConsoleWindow: function(vmtype, vmid, nodename, vmname) {
var url = Ext.urlEncode({
console: vmtype, // kvm, openvz or shell
vmid: vmid,
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,
+ method: 'POST',
+ failure: function(response, opts){
+ Ext.Msg.alert('Error', response.htmlStatus);
+ },
+ success: function(response, opts){
+ var raw = "[virt-viewer]\n";
+ Ext.Object.each(response.result.data, function(k, v) {
+ raw += k + "=" + v + "\n";
+ });
+ var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
+ encodeURIComponent(raw);
+
+ downloadWithName(url, "pve-spice.vv");
+ }
+ });
+ },
+
// comp.setLoading() is buggy in ExtJS 4.0.7, so we
// use el.mask() instead
setErrorMask: function(comp, msg) {