remove unused files

This commit is contained in:
Dietmar Maurer 2011-08-25 08:01:20 +02:00
parent eb3b3e2905
commit dda060e7c0
89 changed files with 0 additions and 13111 deletions

View File

@ -1,89 +0,0 @@
include $(top_builddir)/common.mk
JSSRC= \
PVEUtils.js \
StateProvider.js \
VNCConsole.js \
data/TimezoneStore.js \
data/reader/JsonObject.js \
data/PVEProxy.js \
data/UpdateQueue.js \
data/UpdateStore.js \
data/DiffStore.js \
data/ObjectStore.js \
data/ResourceStore.js \
form/Checkbox.js \
form/TextField.js \
form/RRDTypeSelector.js \
form/ComboGrid.js \
form/NetworkCardSelector.js \
form/DiskFormatSelector.js \
form/BusTypeSelector.js \
form/RealmComboBox.js \
form/BondModeSelector.js \
form/ViewSelector.js \
form/NodeSelector.js \
form/FileSelector.js \
form/StorageSelector.js \
dc/Tasks.js \
dc/Log.js \
panel/StatusPanel.js \
panel/RRDView.js \
window/LoginWindow.js \
window/TaskViewer.js \
window/Wizard.js \
grid/SelectFeature.js \
grid/ObjectGrid.js \
grid/ResourceGrid.js \
tree/ResourceTree.js \
panel/ConfigPanel.js \
node/DNSEdit.js \
node/DNSView.js \
node/TimeView.js \
node/TimeEdit.js \
node/StatusView.js \
node/Summary.js \
node/ServiceView.js \
node/NetworkEdit.js \
node/NetworkView.js \
node/Syslog.js \
node/Tasks.js \
node/Config.js \
qemu/StatusView.js \
qemu/Summary.js \
qemu/Config.js \
qemu/HardwareView.js \
qemu/CreateWizard.js \
openvz/CreateWizard.js \
storage/Browser.js \
dc/UserView.js \
dc/GroupView.js \
dc/RoleView.js \
dc/ACLView.js \
dc/AuthView.js \
dc/Config.js \
Workspace.js
pvemanagerlib.js: ${JSSRC}
cat ${JSSRC} >$@
pvelib_DATA = pvemanagerlib.js
pvelibdir = ${WWW_EXTDIR}
privatedir = ${WWW_BASEDIR}
private_SCRIPTS = \
startup.pl
managerdir = ${WWW_ROOTDIR}
manager_SCRIPTS = \
index.pl
install-data-hook:
chown -R www-data:www-data ${DESTDIR}/${privatedir}
chown -R www-data:www-data ${DESTDIR}/${managerdir}
chown -R www-data:www-data ${DESTDIR}/${pvelibdir}
clean-local:
-rm -rf *~ store/*~ pvemanagerlib.js

View File

@ -1,430 +0,0 @@
Ext.ns('PVE');
// avoid errors when running without development tools
if (!Ext.isDefined(Ext.global.console)) {
var console = {
dir: function() {},
log: function() {}
};
}
console.log("Starting PVE Manager");
Ext.Ajax.defaultHeaders = {
'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)
options.headers = {};
options.headers['CSRFPreventionToken'] = PVE.CSRFPreventionToken;
}
});
// custom Vtype for vtype:'IPAddress'
Ext.apply(Ext.form.field.VTypes, {
IPAddress: function(v) {
return /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(v);
},
IPAddressText: 'Must be a numeric IP address',
IPAddressMask: /[\d\.]/i,
BridgeName: function(v) {
return /^vmbr\d{1,4}$/.test(v);
},
BridgeNameText: 'Allowable bridge names: vmbr<b>N</b>, where 0 <= <b>N</b> <= 9999',
BondName: function(v) {
return /^bond\d{1,4}$/.test(v);
},
BondNameText: 'Allowable bond names: bond<b>N</b>, where 0 <= <b>N</b> <= 9999'
});
Ext.define('PVE.Utils', {
singleton: true,
statics: {
log_severity_hash: {
0: "panic",
1: "alert",
2: "critical",
3: "error",
4: "warning",
5: "notice",
6: "info",
7: "debug"
}
},
authOK: function() {
return Ext.util.Cookies.get('PVEAuthCookie');
},
authClear: function() {
Ext.util.Cookies.clear("PVEAuthCookie");
},
// fixme: remove - not needed?
gridLineHeigh: function() {
return 21;
//if (Ext.isGecko)
//return 23;
//return 21;
},
extractRequestError: function(result, verbose) {
var msg = 'Successful';
if (!result.success) {
var msg = "Unknown error";
if (result.message) {
msg = result.message;
if (result.status)
msg += ' (' + result.status + ')';
}
if (verbose && Ext.isObject(result.errors)) {
msg += "<br>";
Ext.Object.each(result.errors, function(prop, desc) {
msg += "<br><b>" + Ext.htmlEncode(prop) + "</b>: " +
Ext.htmlEncode(desc);
});
}
}
return msg;
},
extractFormActionError: function(action) {
var msg;
switch (action.failureType) {
case Ext.form.action.Action.CLIENT_INVALID:
msg = 'Form fields may not be submitted with invalid values';
break;
case Ext.form.action.Action.CONNECT_FAILURE:
msg = 'Connect failure';
var resp = action.response;
if (resp.status && resp.statusText)
msg += " " + resp.status + ": " + resp.statusText;
break;
case Ext.form.action.Action.LOAD_FAILURE:
case Ext.form.action.Action.SERVER_INVALID:
msg = PVE.Utils.extractRequestError(action.result, true);
break;
}
return msg;
},
// Ext.Ajax.request
API2Request: function(options) {
var callbackFn = options.callback;
var successFn = options.success;
var failureFn = options.failure;
options.url = '/api2/extjs' + options.url;
delete options.callback;
options.success = function(response, options) {
var result = Ext.decode(response.responseText);
if (!result.success) {
response.htmlStatus = PVE.Utils.extractRequestError(result, true);
Ext.callback(callbackFn, options.scope, [options, false, response])
Ext.callback(failureFn, options.scope, [response, options])
return;
}
Ext.callback(callbackFn, options.scope, [options, true, response])
Ext.callback(successFn, options.scope, [response, options])
};
options.failure = function(response, options) {
var msg = "Connection error - server offline?";
if (response.status && response.statusText)
msg = "Connection error " + response.status + ": " + response.statusText;
response.htmlStatus = msg;
Ext.callback(callbackFn, options.scope, [options, false, response])
Ext.callback(failureFn, options.scope, [response, options])
};
Ext.Ajax.request(options);
},
assemble_field_data: function(values, data) {
if (Ext.isObject(data)) {
Ext.iterate(data, function(name, val) {
if (name in values) {
var bucket = values[name],
isArray = Ext.isArray;
if (!isArray(bucket)) {
bucket = values[name] = [bucket];
}
if (isArray(val)) {
values[name] = bucket.concat(val);
} else {
bucket.push(val);
}
} else {
values[name] = val;
}
});
}
},
format_task_description: function(type, id) {
if (type == 'vncproxy')
return "VNC connection to VM " + id;
if (type == 'vncshell')
return "VNC shell";
return type;
},
parse_task_upid: function(upid) {
var task = {};
var res = upid.match(/^UPID:(\w+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/);
if (!res)
throw "unable to parse upid '" + upid + "'";
task.node = res[1];
task.pid = parseInt(res[2], 16);
task.pstart = parseInt(res[3], 16);
task.starttime = parseInt(res[4], 16);
task.type = res[5];
task.id = res[6];
task.user = res[7];
task.desc = PVE.Utils.format_task_description(task.type, task.id);
return task;
},
format_size: function(size) {
var kb = size / 1024;
if (kb < 1024)
return kb.toFixed(0) + "KB";
var mb = size / (1024*1024);
if (mb < 1024)
return mb.toFixed(0) + "MB";
var gb = mb / 1024;
if (gb < 1024)
return gb.toFixed(2) + "GB";
var tb = gb / 1024;
return tb.toFixed(2) + "TB";
},
format_html_bar: function(per, text) {
return "<div class='pve-bar-wrap'>" + text + "<div class='pve-bar-border'>" +
"<div class='pve-bar-inner' style='width:" + per + "%;'></div>" +
"</div></div>";
},
format_cpu_bar: function(per1, per2, text) {
return "<div class='pve-bar-border'>" +
"<div class='pve-bar-inner' style='width:" + per1 + "%;'></div>" +
"<div class='pve-bar-inner2' style='width:" + per2 + "%;'></div>" +
"<div class='pve-bar-text'>" + text + "</div>" +
"</div>";
},
format_large_bar: function(per, text) {
if (!text)
text = per.toFixed(1) + "%";
return "<div class='pve-largebar-border'>" +
"<div class='pve-largebar-inner' style='width:" + per + "%;'></div>" +
"<div class='pve-largebar-text'>" + text + "</div>" +
"</div>";
},
format_duration_long: function(ut) {
var days = Math.floor(ut / 86400);
ut -= days*86400;
var hours = Math.floor(ut / 3600);
ut -= hours*3600;
var mins = Math.floor(ut / 60);
ut -= mins*60;
hours = "00" + hours;
hours = hours.substr(hours.length - 2);
mins = "00" + mins;
mins = mins.substr(mins.length - 2);
ut = "00" + ut;
ut = ut.substr(ut.length - 2);
if (days) {
var ds = days > 1 ? 'days' : 'day';
return days + ' ' + ds + ' ' +
hours + ':' + mins + ':' + ut;
} else {
return hours + ':' + mins + ':' + ut;
}
},
format_duration_short: function(ut) {
if (ut < 60)
return ut + 's';
if (ut < 3600) {
var mins = ut / 60;
return mins.toFixed(0) + 'm';
}
if (ut < 86400) {
var hours = ut / 3600;
return hours.toFixed(0) + 'h';
}
var days = ut / 86400;
return days.toFixed(0) + 'd';
},
format_storage_type: function(value) {
var desc = {
dir: 'Directory',
nfs: 'NFS',
lvm: 'LVM',
iscsi: 'iSCSI'
};
return desc[value] || 'unknown';
},
format_boolean: function(value) {
return value ? 'Yes' : 'No';
},
format_neg_boolean: function(value) {
return !value ? 'Yes' : 'No';
},
format_content_types: function(value) {
var cta = [];
Ext.each(value.split(','), function(ct) {
if (ct === 'images')
cta.push('Images');
if (ct === 'backup')
cta.push('Backups');
if (ct === 'vztmpl')
cta.push('Templates');
if (ct === 'iso')
cta.push('ISO');
});
return cta.join(', ');
},
render_serverity: function (value) {
return PVE.Utils.statics().log_severity_hash[value] || value;
},
render_cpu: function(value, metaData, record, rowIndex, colIndex, store) {
var maxcpu = record.data.maxcpu;
if (!record.data.uptime)
return '';
if (!(Ext.isNumeric(value) && Ext.isNumeric(maxcpu) && (maxcpu >= 1)))
return ''
var per = (value * 100) / maxcpu;
return per.toFixed(1) + '% of ' + maxcpu + (maxcpu > 1 ? 'CPUs' : 'CPU');
},
render_size: function(value, metaData, record, rowIndex, colIndex, store) {
if (!Ext.isNumeric(value))
return '';
return PVE.Utils.format_size(value);
},
render_timestamp: function(value, metaData, record, rowIndex, colIndex, store) {
var servertime = new Date(value * 1000);
return Ext.Date.format(servertime, 'Y-m-d H:i:s');
},
render_mem_usage: function(value, metaData, record, rowIndex, colIndex, store) {
var mem = value;
var maxmem = record.data.maxmem;
if (!record.data.uptime)
return '';
if (!(Ext.isNumeric(mem) && maxmem))
return ''
var per = (mem * 100) / maxmem;
return per.toFixed(1) + '%';
},
render_disk_usage: function(value, metaData, record, rowIndex, colIndex, store) {
var disk = value;
var maxdisk = record.data.maxdisk;
if (!(Ext.isNumeric(disk) && maxdisk))
return ''
var per = (disk * 100) / maxdisk;
return per.toFixed(1) + '%';
},
render_resource_type: function(value, metaData, record, rowIndex, colIndex, store) {
var cls = 'pve-itype-icon-' + value;
metaData.css = cls;
return value;
},
render_uptime: function(value, metaData, record, rowIndex, colIndex, store) {
var uptime = value;
if (uptime === undefined)
return '';
if (uptime <= 0)
return '-';
return PVE.Utils.format_duration_long(uptime);
},
render_upid: function(value, metaData, record) {
var type = record.data.type;
var id = record.data.id;
return PVE.Utils.format_task_description(type, id);
}
});

View File

@ -1,212 +0,0 @@
/* This state provider keeps part of the state inside
* the browser history.
*
* We compress (shorten) url using dictionary based compression
* i.e. use column separated list instead of url encoded hash:
* #v\d* version/format
* := indicates string values
* :\d+ lookup value in dictionary hash
* #v1:=value1:5:=value2:=value3:...
*/
Ext.define('PVE.StateProvider', {
extend: 'Ext.state.LocalStorageProvider',
// private
setHV: function(name, newvalue, fireEvents) {
var me = this;
var changes = false;
var oldtext = Ext.encode(me.UIState[name]);
var newtext = Ext.encode(newvalue);
if (newtext != oldtext) {
changes = true;
me.UIState[name] = newvalue;
//console.log("changed old " + name + " " + oldtext);
//console.log("changed new " + name + " " + newtext);
if (fireEvents)
me.fireEvent("statechange", me, name, { value: newvalue });
}
return changes;
},
// private
hslist: [
// order is important for notifications
// [ name, default ]
['view', 'server'],
['rid', 'root'],
['ltab', 'clog'],
['nodetab', ''],
['storagetab', ''],
['kvmtab', ''],
['dctab', '']
],
hprefix: 'v1',
compDict: {
content: 19,
root: 18,
domains: 17,
roles: 16,
groups: 15,
users: 14,
time: 13,
dns: 12,
network: 11,
services: 10,
options: 9,
console: 8,
hardware: 7,
permissions: 6,
summary: 5,
tasks: 4,
clog: 3,
storage: 2,
folder: 1,
server: 0
},
decodeHToken: function(token) {
var me = this;
var state = {};
if (!token) {
Ext.Array.each(me.hslist, function(rec) {
state[rec[0]] = rec[1];
});
return state;
}
// return Ext.urlDecode(token);
var items = token.split(':');
var prefix = items.shift();
if (prefix != me.hprefix)
return me.decodeHToken();
Ext.Array.each(me.hslist, function(rec) {
var value = items.shift();
if (value === '') {
// do nothing
} else if (value[0] === '=') {
value = decodeURIComponent(value.slice(1));
} else {
Ext.Object.each(me.compDict, function(key, cv) {
if (value == cv) {
value = key;
return false;
}
});
}
state[rec[0]] = value;
});
return state;
},
encodeHToken: function(state) {
var me = this;
// return Ext.urlEncode(state);
var ctoken = me.hprefix;
Ext.Array.each(me.hslist, function(rec) {
var value = state[rec[0]];
if (!Ext.isDefined(value))
value = rec[1];
value = encodeURIComponent(value);
if (!value) {
ctoken += ':';
} else {
var comp = me.compDict[value];
if (Ext.isDefined(comp))
ctoken += ":" + comp;
else
ctoken += ":=" + value;
}
});
return ctoken;
},
constructor: function(config){
var me = this;
me.callParent([config]);
me.UIState = me.decodeHToken(); // set default
var history_change_cb = function(token) {
//console.log("HC " + token);
if (!token) {
var res = confirm('Are you sure you want to navigate away from this page?');
if (res){
// process text value and close...
Ext.History.back();
} else {
Ext.History.forward();
}
return;
}
var newstate = me.decodeHToken(token);
Ext.Array.each(me.hslist, function(rec) {
if (typeof newstate[rec[0]] == "undefined")
return;
me.setHV(rec[0], newstate[rec[0]], true);
});
};
var start_token = Ext.History.getToken();
if (start_token) {
history_change_cb(start_token);
} else {
var htext = me.encodeHToken(me.UIState);
Ext.History.add(htext);
}
Ext.History.on('change', history_change_cb);
},
get: function(name, defaultValue){
var me = this;
var data;
if (typeof me.UIState[name] != "undefined") {
data = { value: me.UIState[name] };
} else {
data = me.callParent(arguments);
}
//console.log("GET " + name + " " + Ext.encode(data));
return data;
},
clear: function(name){
var me = this;
if (typeof me.UIState[name] != "undefined") {
me.UIState[name] = null;
}
me.callParent(arguments);
},
set: function(name, value){
var me = this;
//console.log("SET " + name + " " + Ext.encode(value));
if (typeof me.UIState[name] != "undefined") {
var newvalue = value ? value.value : null;
if (me.setHV(name, newvalue, false)) {
var htext = me.encodeHToken(me.UIState);
Ext.History.add(htext);
}
} else {
me.callParent(arguments);
}
}
});

View File

@ -1,334 +0,0 @@
PVE_vnc_console_event = function(appletid, action, err) {
//console.log("TESTINIT param1 " + appletid + " action " + action);
return;
var el = Ext.get(appletid);
if (!el)
return;
if (action === "close") {
// el.remove();
} else if (action === "error") {
// console.log("TESTERROR: " + err);
// var compid = appletid.replace("-vncapp", "");
// var comp = Ext.getCmp(compid);
}
//Ext.get('mytestid').remove();
};
Ext.define('PVE.VNCConsole', {
extend: 'Ext.panel.Panel',
alias: ['widget.pveVNCConsole'],
initComponent : function() {
var me = this;
if (!me.url)
throw "no url specified";
var myid = me.id + "-vncapp";
me.appletID = myid;
var box = Ext.create('Ext.Component', {
border: false,
html: ""
});
var resize_window = function() {
//console.log("resize");
var applet = Ext.getDom(myid);
//console.log("resize " + myid + " " + applet);
// try again when dom element is available
if (!(applet && Ext.isFunction(applet.getPreferredSize)))
return Ext.Function.defer(resize_window, 1000);
var tbh = me.tbar ? me.tbar.getHeight() : 0;
var ps = applet.getPreferredSize();
var aw = ps.width;
var ah = ps.height;
if (aw < 640) aw = 640;
if (ah < 400) ah = 400;
var oh;
var ow;
//console.log("size0 " + aw + " " + ah + " tbh " + tbh);
if (window.innerHeight) {
oh = window.innerHeight;
ow = window.innerWidth;
} else if (document.documentElement &&
document.documentElement.clientHeight) {
oh = document.documentElement.clientHeight;
ow = document.documentElement.clientWidth;
} else if (document.body) {
oh = document.body.clientHeight;
ow = document.body.clientWidth;
} else {
throw "can't get window size";
}
Ext.fly(applet).setSize(aw, ah + tbh);
var offsetw = aw - ow;
var offseth = ah + tbh - oh;
if (offsetw !== 0 || offseth !== 0) {
//console.log("try resize by " + offsetw + " " + offseth);
try { window.resizeBy(offsetw, offseth); } catch (e) {}
}
Ext.Function.defer(resize_window, 1000);
};
var resize_box = function() {
var applet = Ext.getDom(myid);
if ((applet && Ext.isFunction(applet.getPreferredSize))) {
var ps = applet.getPreferredSize();
Ext.fly(applet).setSize(ps.width, ps.height);
}
Ext.Function.defer(resize_box, 1000);
};
var start_vnc_viewer = function(param) {
var cert = param.cert;
cert = cert.replace(/\n/g, "|");
box.update({
id: myid,
border: false,
tag: 'applet',
code: 'com.tigervnc.vncviewer.VncViewer',
archive: '/vncterm/VncViewer.jar',
// NOTE: set size to '100%' - else resize does not work
width: "100%",
height: "100%",
cn: [
{tag: 'param', name: 'id', value: myid},
{tag: 'param', name: 'PORT', value: param.port},
{tag: 'param', name: 'PASSWORD', value: param.ticket},
{tag: 'param', name: 'USERNAME', value: param.user},
{tag: 'param', name: 'Show Controls', value: 'No'},
{tag: 'param', name: 'Offer Relogin', value: 'No'},
{tag: 'param', name: 'PVECert', value: cert}
]
});
if (me.toplevel) {
Ext.Function.defer(resize_window, 1000);
} else {
Ext.Function.defer(resize_box, 1000);
}
};
Ext.apply(me, {
layout: 'fit',
border: false,
autoScroll: me.toplevel ? false : true,
items: box,
reloadApplet: function() {
PVE.Utils.API2Request({
url: me.url,
params: me.params,
method: me.method || 'POST',
failure: function(response, opts) {
box.update("Error " + response.htmlStatus);
},
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
start_vnc_viewer(obj.data);
}
});
}
});
me.callParent();
if (me.toplevel) {
me.on("render", function() { me.reloadApplet();});
} else {
me.on("show", function() { me.reloadApplet();});
me.on("hide", function() { box.update(""); });
}
}
});
Ext.define('PVE.KVMConsole', {
extend: 'PVE.VNCConsole',
alias: ['widget.pveKVMConsole'],
initComponent : function() {
var me = this;
if (!me.nodename)
throw "no node name specified";
if (!me.vmid)
throw "no VM ID specified";
var vm_command = function(cmd, reload_applet) {
me.setLoading(true, true);
PVE.Utils.API2Request({
params: { command: cmd },
url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/status",
method: 'PUT',
callback: function() {
me.setLoading(false);
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
},
success: function() {
if (reload_applet)
Ext.Function.defer(me.reloadApplet, 1000, me);
}
});
};
var tbar = [
{
text: 'Start',
handler: function() {
vm_command("start", 1);
}
},
{
text: 'Stop',
handler: function() {
var msg = "Do you really want to stop the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command("stop");
});
}
},
{
text: 'Reset',
handler: function() {
var msg = "Do you really want to reset the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command("reset");
});
}
},
{
text: 'Shutdown',
handler: function() {
var msg = "Do you really want to shutdown the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command('shutdown');
});
}
},
{
text: 'Suspend',
handler: function() {
var msg = "Do you really want to suspend the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command("suspend");
});
}
},
{
text: 'Resume',
handler: function() {
vm_command("resume");
}
},
'->',
{
text: 'Refresh',
handler: function() {
var applet = Ext.getDom(me.appletID);
applet.sendRefreshRequest();
}
},
{
text: 'Reload',
handler: function () {
me.reloadApplet();
}
},
{
text: 'Console',
handler: function() {
var url = Ext.urlEncode({
console: 'kvm',
vmid: me.vmid,
node: me.nodename
});
var nw = window.open("?" + url, '_blank',
"innerWidth=745,innerheight=427");
nw.focus();
}
}
];
Ext.apply(me, {
tbar: tbar,
url: "/nodes/" + me.nodename + "/qemu/" + me.vmid + "/vncproxy"
});
me.callParent();
}
});
Ext.define('PVE.Shell', {
extend: 'PVE.VNCConsole',
alias: ['widget.pveShell'],
initComponent : function() {
var me = this;
if (!me.nodename)
throw "no node name specified";
var tbar = [
'->',
{
text: 'Refresh',
handler: function() {
var applet = Ext.getDom(me.appletID);
applet.sendRefreshRequest();
}
},
{
text: 'Reload',
handler: function () { me.reloadApplet(); }
},
{
text: 'Shell',
handler: function() {
var url = Ext.urlEncode({
console: 'shell',
node: me.nodename
});
var nw = window.open("?" + url, '_blank',
"innerWidth=745,innerheight=427");
nw.focus();
}
}
];
Ext.apply(me, {
tbar: tbar,
url: "/nodes/" + me.nodename + "/vncshell"
});
me.callParent();
}
});

View File

@ -1,364 +0,0 @@
/*
* Workspace base class
*
* popup login window when auth fails (call onLogin handler)
* update (re-login) ticket every 15 minutes
*
*/
Ext.define('PVE.Workspace', {
extend: 'Ext.container.Viewport',
requires: [
'Ext.tip.*',
'PVE.Utils',
'PVE.window.LoginWindow'
],
title: 'Proxmox Virtual Environment',
loginData: null, // Data from last login call
onLogin: function(loginData) {},
// private
updateLoginData: function(loginData) {
var me = this;
me.loginData = loginData;
PVE.CSRFPreventionToken = loginData.CSRFPreventionToken;
PVE.UserName = loginData.username;
me.onLogin(loginData);
},
// private
showLogin: function() {
var me = this;
PVE.Utils.authClear();
PVE.UserName = null;
me.loginData = null;
if (!me.login) {
me.login = Ext.create('PVE.window.LoginWindow', {
handler: function(data) {
me.login = null;
me.updateLoginData(data);
}
});
}
me.onLogin(null);
me.login.show();
},
initComponent : function() {
var me = this;
Ext.tip.QuickTipManager.init();
// fixme: what about other errors
Ext.Ajax.on('requestexception', function(conn, response, options) {
if (response.status == 401) { // auth failure
me.showLogin();
}
});
document.title = me.title;
me.callParent();
if (!PVE.Utils.authOK())
me.showLogin();
else
if (me.loginData)
me.onLogin(me.loginData);
Ext.TaskManager.start({
run: function() {
var ticket = PVE.Utils.authOK();
if (!ticket || !PVE.UserName)
return;
Ext.Ajax.request({
params: {
username: PVE.UserName,
password: ticket
},
url: '/api2/json/access/ticket',
method: 'POST',
success: function(response, opts) {
// cookie is automatically updated
var obj = Ext.decode(response.responseText);
me.updateLoginData(obj.data);
}
});
},
interval: 15*60*1000
});
}
});
Ext.define('PVE.ConsoleWorkspace', {
extend: 'PVE.Workspace',
requires: [
'PVE.KVMConsole'
],
alias: ['widget.pveConsoleWorkspace'],
title: 'Proxmox Console',
initComponent : function() {
var me = this;
var param = Ext.Object.fromQueryString(window.location.search);
var consoleType = me.consoleType || param.console;
var content;
if (consoleType === 'kvm') {
me.title = "VM " + param.vmid;
content = {
xtype: 'pveKVMConsole',
vmid: param.vmid,
nodename: param.node,
toplevel: true
};
} else if (consoleType === 'shell') {
me.title = "node " + param.node + " - Proxmox Shell"
content = {
xtype: 'pveShell',
nodename: param.node,
toplevel: true
};
} else {
content = {
border: false,
bodyPadding: 10,
html: 'Error: No such console type'
};
}
Ext.apply(me, {
layout: 'fit',
border: false,
items: content
});
me.callParent();
}
});
Ext.define('PVE.StdWorkspace', {
extend: 'PVE.Workspace',
requires: [
'Ext.History',
'Ext.state.*',
'Ext.selection.*',
'PVE.form.ViewSelector',
'PVE.data.ResourceStore',
'PVE.tree.ResourceTree'
],
alias: ['widget.pveStdWorkspace'],
// private
defaultContent: {
title: 'Nothing selected',
region: 'center'
},
setContent: function(comp) {
var me = this;
if (!comp)
comp = me.defaultContent;
var cont = me.child('#content');
cont.removeAll(true);
cont.add(comp);
cont.doLayout();
},
selectById: function(nodeid) {
var me = this;
var tree = me.down('pveResourceTree');
tree.selectById(nodeid);
},
onLogin: function(loginData) {
var me = this;
me.updateUserInfo();
if (loginData)
PVE.data.ResourceStore.startUpdate();
},
updateUserInfo: function() {
var me = this;
var ui = me.query('#userinfo')[0];
if (PVE.UserName) {
ui.update('<div class="x-unselectable" style="white-space:nowrap;">You are logged in as "' + PVE.UserName + '"</div>');
} else {
ui.update('');
}
ui.doLayout();
},
initComponent : function() {
var me = this;
Ext.History.init();
Ext.state.Manager.setProvider(Ext.create('PVE.StateProvider'));
//document.title = ;
var selview = new PVE.form.ViewSelector({
listeners: {
select: function(combo, records) {
if (records && records.length) {
var view = combo.getViewFilter();
combo.up('pveResourceTree').setViewFilter(view);
}
}
}
});
var rtree = Ext.createWidget('pveResourceTree', {
width: 200,
region: 'west',
margins: '0 0 0 5',
split: true,
viewFilter: selview.getViewFilter(),
tbar: [ ' ', selview ],
selModel: new Ext.selection.TreeModel({
listeners: {
selectionchange: function(sm, selected) {
var comp;
var tlckup = {
root: 'PVE.dc.Config',
node: 'PVE.node.Config',
qemu: 'PVE.qemu.Config',
storage: 'PVE.storage.Browser'
};
if (selected.length > 0) {
var n = selected[0];
comp = {
xtype: tlckup[n.data.type || 'root'] ||
'PVE.panel.Config',
layout: 'fit',
showSearch: (n.data.id === 'root') ||
Ext.isDefined(n.data.groupbyid),
pveSelNode: n,
viewFilter: selview.getViewFilter()
};
}
me.setContent(comp);
}
}
})
});
Ext.apply(me, {
layout: 'border',
border: false,
items: [
{
region: 'north',
height: 30,
layout: {
type: 'hbox',
align : 'middle'
},
baseCls: 'x-plain',
defaults: {
baseCls: 'x-plain'
},
border: false,
margins: '2 0 5 0',
items: [
{
margins: '0 0 0 4',
html: '<a class="x-unselectable" target=_blank href="http://www.proxmox.com">' +
'<img height=30 width=209 src="/pve2/images/proxmox_logo.png"/></a>'
},
{
minWidth: 200,
flex: 1,
html: '<span class="x-panel-header-text">Proxmox Virtual Environment<br>Version ' + PVE.GUIVersion + "</span>"
},
{
pack: 'end',
margins: '8 10 0 10',
id: 'userinfo',
stateful: false
},
{
pack: 'end',
margins: '3 5 0 0',
xtype: 'button',
baseCls: 'x-btn',
text: "Logout",
handler: function() {
PVE.data.ResourceStore.stopUpdate();
me.showLogin();
me.setContent();
var rt = me.down('pveResourceTree');
rt.clearTree();
}
},
{
pack: 'end',
margins: '3 5 0 0',
xtype: 'button',
baseCls: 'x-btn',
text: "Create VM",
handler: function() {
var wiz = Ext.create('PVE.qemu.CreateWizard', {});
wiz.show();
}
},
{
pack: 'end',
margins: '3 5 0 0',
xtype: 'button',
baseCls: 'x-btn',
text: "Create CT",
handler: function() {
var wiz = Ext.create('PVE.openvz.CreateWizard', {});
wiz.show();
}
}
]
},
{
region: 'center',
id: 'content',
xtype: 'panel',
layout: 'fit',
border: false,
stateful: false,
margins:'0 5 0 0',
items: me.defaultContent
},
rtree,
{
xtype: 'pveStatusPanel',
region: 'south',
margins:'0 5 5 5',
height: 200,
collapsible: true,
split:true
}
]
});
me.callParent();
me.updateUserInfo();
}
});

View File

@ -1,72 +0,0 @@
/* Config properties:
* rstore: A storage to track changes
* Only works if rstore has a model and use 'idProperty'
*/
Ext.define('PVE.data.DiffStore', {
extend: 'Ext.data.Store',
constructor: function(config) {
var me = this;
var config = config || {};
if (!config.rstore)
throw "no rstore specified";
if (!config.rstore.model)
throw "no rstore model specified";
var rstore = config.rstore;
Ext.apply(config, {
model: rstore.model,
proxy: { type: 'memory' }
});
me.callParent([config]);
var first_load = true;
var cond_add_item = function(data, id) {
var olditem = me.getById(id);
if (olditem) {
olditem.beginEdit()
me.model.prototype.fields.eachKey(function(field) {
if (olditem.data[field] !== data[field])
olditem.set(field, data[field]);
});
olditem.endEdit(true);
olditem.commit();
} else {
var newrec = Ext.ModelMgr.create(data, me.model, id);
var pos = (me.appendAtStart && !first_load) ? 0 : me.data.length;
me.insert(pos, newrec);
}
};
me.mon(rstore, 'load', function(s, records, success) {
if (!success)
return;
me.suspendEvents();
// remove vanished items
me.each(function(olditem) {
var item = rstore.getById(olditem.getId());
if (!item)
me.remove(olditem);
});
rstore.each(function(item) {
cond_add_item(item.data, item.getId());
});
me.filter();
first_load = false;
me.resumeEvents();
me.fireEvent('datachanged', me);
});
}
});

View File

@ -1,26 +0,0 @@
Ext.define('PVE.data.ObjectStore', {
extend: 'PVE.data.UpdateStore',
constructor: function(config) {
var me = this;
config = config || {};
if (!config.storeid)
config.storeid = 'pve-store-' + (++Ext.idSeed);
Ext.applyIf(config, {
model: 'KeyValue',
proxy: {
type: 'pve',
url: config.url,
reader: {
type: 'jsonobject',
rows: config.rows
}
}
});
me.callParent([config]);
}
});

View File

@ -1,84 +0,0 @@
Ext.define('PVE.RestProxy', {
extend: 'Ext.data.RestProxy',
alias : 'proxy.pve',
constructor: function(config) {
var me = this;
config = config || {};
Ext.applyIf(config, {
pageParam : null,
startParam: null,
limitParam: null,
groupParam: null,
sortParam: null,
filterParam: null,
noCache : false,
reader: {
type: 'json',
root: 'data'
}
});
me.callParent([config]);
}
}, function() {
Ext.define('pve-domains', {
extend: "Ext.data.Model",
fields: [ 'realm', 'type', 'comment', 'default' ],
proxy: {
type: 'pve',
url: "/api2/json/access/domains"
}
});
Ext.define('KeyValue', {
extend: "Ext.data.Model",
fields: [ 'key', 'value' ],
idProperty: 'key'
});
Ext.define('pve-string-list', {
extend: 'Ext.data.Model',
fields: [ 'n', 't' ],
idProperty: 'n'
});
Ext.define('pve-tasks', {
extend: 'Ext.data.Model',
fields: [
{ name: 'starttime', type : 'date', dateFormat: 'timestamp' },
{ name: 'endtime', type : 'date', dateFormat: 'timestamp' },
{ name: 'pid', type: 'int' },
'node', 'upid', 'user', 'status', 'type', 'id'
],
idProperty: 'upid'
});
Ext.define('pve-cluster-log', {
extend: 'Ext.data.Model',
fields: [
{ name: 'uid' , type: 'int' },
{ name: 'time', type : 'date', dateFormat: 'timestamp' },
{ name: 'pri', type: 'int' },
{ name: 'pid', type: 'int' },
'node', 'user', 'tag', 'msg',
{
name: 'id',
convert: function(value, record) {
var info = record.data;
var text;
if (value)
return value;
// compute unique ID
return info.uid + ':' + info.node;
}
}
],
idProperty: 'id'
});
});

View File

@ -1,190 +0,0 @@
Ext.define('PVE.data.ResourceStore', {
extend: 'PVE.data.UpdateStore',
requires: ['PVE.Utils'],
singleton: true,
findNextVMID: function() {
var me = this, i;
for (i = 100; i < 10000; i++) {
if (me.findExact('vmid', i) < 0)
return i;
}
},
findVMID: function(vmid) {
var me = this, i;
return (me.findExact('vmid', parseInt(vmid)) >= 0);
},
constructor: function(config) {
var me = this;
config = config || {};
var field_defaults = {
type: {
header: 'Type',
type: 'text',
renderer: PVE.Utils.render_resource_type,
sortable: true,
hideable: false,
width: 80
},
id: {
header: 'ID',
type: 'text',
hidden: true,
sortable: true,
width: 80
},
text: {
header: 'Text',
type: 'text',
sortable: true,
width: 200,
convert: function(value, record) {
var info = record.data;
var text;
if (value)
return value;
if (info.type === 'node') {
text = info.node;
} else if (info.type === 'storage') {
text = info.storage + ' (' + info.node + ')';
} else if (info.type === 'qemu' || info.type === 'openvz') {
text = String(info.vmid);
if (info.name)
text += " (" + info.name + ')';
} else {
text = info.id;
}
return text;
}
},
vmid: {
header: 'VMID',
type: 'integer',
hidden: true,
sortable: true,
width: 80
},
name: {
header: 'Name',
hidden: true,
sortable: true,
type: 'text'
},
disk: {
header: 'Disk usage',
type: 'integer',
renderer: PVE.Utils.render_disk_usage,
sortable: true,
width: 100
},
maxdisk: {
header: 'Disk size',
type: 'integer',
renderer: PVE.Utils.render_size,
sortable: true,
hidden: true,
width: 100
},
mem: {
header: 'Memory usage',
type: 'integer',
renderer: PVE.Utils.render_mem_usage,
sortable: true,
width: 100
},
maxmem: {
header: 'Mem size',
type:'integer',
renderer: PVE.Utils.render_size,
hidden: true,
sortable: true,
width: 100
},
cpu: {
header: 'CPU usage',
type: 'float',
renderer: PVE.Utils.render_cpu,
sortable: true,
width: 100
},
maxcpu: {
header: 'maxcpu',
type: 'integer',
hidden: true,
sortable: true,
width: 60
},
uptime: {
header: 'Uptime',
type: 'integer',
renderer: PVE.Utils.render_uptime,
sortable: true,
width: 110
},
node: {
header: 'Node',
type: 'text',
hidden: true,
sortable: true,
width: 110
},
storage: {
header: 'Storage',
type: 'text',
hidden: true,
sortable: true,
width: 110
}
};
var fields = [];
Ext.Object.each(field_defaults, function(key, value) {
if (!Ext.isDefined(value.convert))
fields.push({name: key, type: value.type});
else if (key === 'text')
fields.push({name: key, type: value.type, convert: value.convert});
});
Ext.define('PVEResources', {
extend: "Ext.data.Model",
fields: fields,
proxy: {
type: 'pve',
url: '/api2/json/cluster/resources'
}
});
Ext.define('PVETree', {
extend: "Ext.data.Model",
fields: fields,
proxy: { type: 'memory' }
});
Ext.apply(config, {
storeid: 'PVEResources',
model: 'PVEResources',
autoDestory: false,
defaultColums: function() {
var res = [];
for (field in field_defaults) {
var info = field_defaults[field];
var fi = Ext.apply({ dataIndex: field }, info);
res.push(fi);
}
return res;
}
});
me.callParent([config]);
}
});

View File

@ -1,438 +0,0 @@
Ext.define('PVE.data.TimezoneStore', {
extend: 'Ext.data.Store',
statics: {
timezones: [
['Africa/Abidjan'],
['Africa/Accra'],
['Africa/Addis_Ababa'],
['Africa/Algiers'],
['Africa/Asmara'],
['Africa/Bamako'],
['Africa/Bangui'],
['Africa/Banjul'],
['Africa/Bissau'],
['Africa/Blantyre'],
['Africa/Brazzaville'],
['Africa/Bujumbura'],
['Africa/Cairo'],
['Africa/Casablanca'],
['Africa/Ceuta'],
['Africa/Conakry'],
['Africa/Dakar'],
['Africa/Dar_es_Salaam'],
['Africa/Djibouti'],
['Africa/Douala'],
['Africa/El_Aaiun'],
['Africa/Freetown'],
['Africa/Gaborone'],
['Africa/Harare'],
['Africa/Johannesburg'],
['Africa/Kampala'],
['Africa/Khartoum'],
['Africa/Kigali'],
['Africa/Kinshasa'],
['Africa/Lagos'],
['Africa/Libreville'],
['Africa/Lome'],
['Africa/Luanda'],
['Africa/Lubumbashi'],
['Africa/Lusaka'],
['Africa/Malabo'],
['Africa/Maputo'],
['Africa/Maseru'],
['Africa/Mbabane'],
['Africa/Mogadishu'],
['Africa/Monrovia'],
['Africa/Nairobi'],
['Africa/Ndjamena'],
['Africa/Niamey'],
['Africa/Nouakchott'],
['Africa/Ouagadougou'],
['Africa/Porto-Novo'],
['Africa/Sao_Tome'],
['Africa/Tripoli'],
['Africa/Tunis'],
['Africa/Windhoek'],
['America/Adak'],
['America/Anchorage'],
['America/Anguilla'],
['America/Antigua'],
['America/Araguaina'],
['America/Argentina/Buenos_Aires'],
['America/Argentina/Catamarca'],
['America/Argentina/Cordoba'],
['America/Argentina/Jujuy'],
['America/Argentina/La_Rioja'],
['America/Argentina/Mendoza'],
['America/Argentina/Rio_Gallegos'],
['America/Argentina/Salta'],
['America/Argentina/San_Juan'],
['America/Argentina/San_Luis'],
['America/Argentina/Tucuman'],
['America/Argentina/Ushuaia'],
['America/Aruba'],
['America/Asuncion'],
['America/Atikokan'],
['America/Bahia'],
['America/Bahia_Banderas'],
['America/Barbados'],
['America/Belem'],
['America/Belize'],
['America/Blanc-Sablon'],
['America/Boa_Vista'],
['America/Bogota'],
['America/Boise'],
['America/Cambridge_Bay'],
['America/Campo_Grande'],
['America/Cancun'],
['America/Caracas'],
['America/Cayenne'],
['America/Cayman'],
['America/Chicago'],
['America/Chihuahua'],
['America/Costa_Rica'],
['America/Cuiaba'],
['America/Curacao'],
['America/Danmarkshavn'],
['America/Dawson'],
['America/Dawson_Creek'],
['America/Denver'],
['America/Detroit'],
['America/Dominica'],
['America/Edmonton'],
['America/Eirunepe'],
['America/El_Salvador'],
['America/Fortaleza'],
['America/Glace_Bay'],
['America/Godthab'],
['America/Goose_Bay'],
['America/Grand_Turk'],
['America/Grenada'],
['America/Guadeloupe'],
['America/Guatemala'],
['America/Guayaquil'],
['America/Guyana'],
['America/Halifax'],
['America/Havana'],
['America/Hermosillo'],
['America/Indiana/Indianapolis'],
['America/Indiana/Knox'],
['America/Indiana/Marengo'],
['America/Indiana/Petersburg'],
['America/Indiana/Tell_City'],
['America/Indiana/Vevay'],
['America/Indiana/Vincennes'],
['America/Indiana/Winamac'],
['America/Inuvik'],
['America/Iqaluit'],
['America/Jamaica'],
['America/Juneau'],
['America/Kentucky/Louisville'],
['America/Kentucky/Monticello'],
['America/La_Paz'],
['America/Lima'],
['America/Los_Angeles'],
['America/Maceio'],
['America/Managua'],
['America/Manaus'],
['America/Marigot'],
['America/Martinique'],
['America/Matamoros'],
['America/Mazatlan'],
['America/Menominee'],
['America/Merida'],
['America/Mexico_City'],
['America/Miquelon'],
['America/Moncton'],
['America/Monterrey'],
['America/Montevideo'],
['America/Montreal'],
['America/Montserrat'],
['America/Nassau'],
['America/New_York'],
['America/Nipigon'],
['America/Nome'],
['America/Noronha'],
['America/North_Dakota/Center'],
['America/North_Dakota/New_Salem'],
['America/Ojinaga'],
['America/Panama'],
['America/Pangnirtung'],
['America/Paramaribo'],
['America/Phoenix'],
['America/Port-au-Prince'],
['America/Port_of_Spain'],
['America/Porto_Velho'],
['America/Puerto_Rico'],
['America/Rainy_River'],
['America/Rankin_Inlet'],
['America/Recife'],
['America/Regina'],
['America/Resolute'],
['America/Rio_Branco'],
['America/Santa_Isabel'],
['America/Santarem'],
['America/Santiago'],
['America/Santo_Domingo'],
['America/Sao_Paulo'],
['America/Scoresbysund'],
['America/Shiprock'],
['America/St_Barthelemy'],
['America/St_Johns'],
['America/St_Kitts'],
['America/St_Lucia'],
['America/St_Thomas'],
['America/St_Vincent'],
['America/Swift_Current'],
['America/Tegucigalpa'],
['America/Thule'],
['America/Thunder_Bay'],
['America/Tijuana'],
['America/Toronto'],
['America/Tortola'],
['America/Vancouver'],
['America/Whitehorse'],
['America/Winnipeg'],
['America/Yakutat'],
['America/Yellowknife'],
['Antarctica/Casey'],
['Antarctica/Davis'],
['Antarctica/DumontDUrville'],
['Antarctica/Macquarie'],
['Antarctica/Mawson'],
['Antarctica/McMurdo'],
['Antarctica/Palmer'],
['Antarctica/Rothera'],
['Antarctica/South_Pole'],
['Antarctica/Syowa'],
['Antarctica/Vostok'],
['Arctic/Longyearbyen'],
['Asia/Aden'],
['Asia/Almaty'],
['Asia/Amman'],
['Asia/Anadyr'],
['Asia/Aqtau'],
['Asia/Aqtobe'],
['Asia/Ashgabat'],
['Asia/Baghdad'],
['Asia/Bahrain'],
['Asia/Baku'],
['Asia/Bangkok'],
['Asia/Beirut'],
['Asia/Bishkek'],
['Asia/Brunei'],
['Asia/Choibalsan'],
['Asia/Chongqing'],
['Asia/Colombo'],
['Asia/Damascus'],
['Asia/Dhaka'],
['Asia/Dili'],
['Asia/Dubai'],
['Asia/Dushanbe'],
['Asia/Gaza'],
['Asia/Harbin'],
['Asia/Ho_Chi_Minh'],
['Asia/Hong_Kong'],
['Asia/Hovd'],
['Asia/Irkutsk'],
['Asia/Jakarta'],
['Asia/Jayapura'],
['Asia/Jerusalem'],
['Asia/Kabul'],
['Asia/Kamchatka'],
['Asia/Karachi'],
['Asia/Kashgar'],
['Asia/Kathmandu'],
['Asia/Kolkata'],
['Asia/Krasnoyarsk'],
['Asia/Kuala_Lumpur'],
['Asia/Kuching'],
['Asia/Kuwait'],
['Asia/Macau'],
['Asia/Magadan'],
['Asia/Makassar'],
['Asia/Manila'],
['Asia/Muscat'],
['Asia/Nicosia'],
['Asia/Novokuznetsk'],
['Asia/Novosibirsk'],
['Asia/Omsk'],
['Asia/Oral'],
['Asia/Phnom_Penh'],
['Asia/Pontianak'],
['Asia/Pyongyang'],
['Asia/Qatar'],
['Asia/Qyzylorda'],
['Asia/Rangoon'],
['Asia/Riyadh'],
['Asia/Sakhalin'],
['Asia/Samarkand'],
['Asia/Seoul'],
['Asia/Shanghai'],
['Asia/Singapore'],
['Asia/Taipei'],
['Asia/Tashkent'],
['Asia/Tbilisi'],
['Asia/Tehran'],
['Asia/Thimphu'],
['Asia/Tokyo'],
['Asia/Ulaanbaatar'],
['Asia/Urumqi'],
['Asia/Vientiane'],
['Asia/Vladivostok'],
['Asia/Yakutsk'],
['Asia/Yekaterinburg'],
['Asia/Yerevan'],
['Atlantic/Azores'],
['Atlantic/Bermuda'],
['Atlantic/Canary'],
['Atlantic/Cape_Verde'],
['Atlantic/Faroe'],
['Atlantic/Madeira'],
['Atlantic/Reykjavik'],
['Atlantic/South_Georgia'],
['Atlantic/St_Helena'],
['Atlantic/Stanley'],
['Australia/Adelaide'],
['Australia/Brisbane'],
['Australia/Broken_Hill'],
['Australia/Currie'],
['Australia/Darwin'],
['Australia/Eucla'],
['Australia/Hobart'],
['Australia/Lindeman'],
['Australia/Lord_Howe'],
['Australia/Melbourne'],
['Australia/Perth'],
['Australia/Sydney'],
['Europe/Amsterdam'],
['Europe/Andorra'],
['Europe/Athens'],
['Europe/Belgrade'],
['Europe/Berlin'],
['Europe/Bratislava'],
['Europe/Brussels'],
['Europe/Bucharest'],
['Europe/Budapest'],
['Europe/Chisinau'],
['Europe/Copenhagen'],
['Europe/Dublin'],
['Europe/Gibraltar'],
['Europe/Guernsey'],
['Europe/Helsinki'],
['Europe/Isle_of_Man'],
['Europe/Istanbul'],
['Europe/Jersey'],
['Europe/Kaliningrad'],
['Europe/Kiev'],
['Europe/Lisbon'],
['Europe/Ljubljana'],
['Europe/London'],
['Europe/Luxembourg'],
['Europe/Madrid'],
['Europe/Malta'],
['Europe/Mariehamn'],
['Europe/Minsk'],
['Europe/Monaco'],
['Europe/Moscow'],
['Europe/Oslo'],
['Europe/Paris'],
['Europe/Podgorica'],
['Europe/Prague'],
['Europe/Riga'],
['Europe/Rome'],
['Europe/Samara'],
['Europe/San_Marino'],
['Europe/Sarajevo'],
['Europe/Simferopol'],
['Europe/Skopje'],
['Europe/Sofia'],
['Europe/Stockholm'],
['Europe/Tallinn'],
['Europe/Tirane'],
['Europe/Uzhgorod'],
['Europe/Vaduz'],
['Europe/Vatican'],
['Europe/Vienna'],
['Europe/Vilnius'],
['Europe/Volgograd'],
['Europe/Warsaw'],
['Europe/Zagreb'],
['Europe/Zaporozhye'],
['Europe/Zurich'],
['Indian/Antananarivo'],
['Indian/Chagos'],
['Indian/Christmas'],
['Indian/Cocos'],
['Indian/Comoro'],
['Indian/Kerguelen'],
['Indian/Mahe'],
['Indian/Maldives'],
['Indian/Mauritius'],
['Indian/Mayotte'],
['Indian/Reunion'],
['Pacific/Apia'],
['Pacific/Auckland'],
['Pacific/Chatham'],
['Pacific/Chuuk'],
['Pacific/Easter'],
['Pacific/Efate'],
['Pacific/Enderbury'],
['Pacific/Fakaofo'],
['Pacific/Fiji'],
['Pacific/Funafuti'],
['Pacific/Galapagos'],
['Pacific/Gambier'],
['Pacific/Guadalcanal'],
['Pacific/Guam'],
['Pacific/Honolulu'],
['Pacific/Johnston'],
['Pacific/Kiritimati'],
['Pacific/Kosrae'],
['Pacific/Kwajalein'],
['Pacific/Majuro'],
['Pacific/Marquesas'],
['Pacific/Midway'],
['Pacific/Nauru'],
['Pacific/Niue'],
['Pacific/Norfolk'],
['Pacific/Noumea'],
['Pacific/Pago_Pago'],
['Pacific/Palau'],
['Pacific/Pitcairn'],
['Pacific/Pohnpei'],
['Pacific/Port_Moresby'],
['Pacific/Rarotonga'],
['Pacific/Saipan'],
['Pacific/Tahiti'],
['Pacific/Tarawa'],
['Pacific/Tongatapu'],
['Pacific/Wake'],
['Pacific/Wallis']
]
},
constructor: function(config) {
var me = this;
var statics = me.statics();
config = config || {};
Ext.regModel('Timezone', {
fields: ['zone'],
proxy: {
type: 'memory',
reader: 'array'
}
});
Ext.apply(config, {
model: 'Timezone',
data: statics.timezones
});
me.callParent([config]);
}
});

View File

@ -1,44 +0,0 @@
// Serialize load (avoid too many parallel connections)
Ext.define('PVE.data.UpdateQueue', {
singleton: true,
constructor : function(){
var me = this;
var queue = [];
var queue_idx = {};
var idle = true;
var start_update = function() {
if (!idle)
return;
var store = queue.shift();
if (!store)
return;
queue_idx[store.storeid] = null;
idle = false;
store.load({
callback: function(records, operation, success) {
idle = true;
start_update();
}
});
};
Ext.apply(me, {
queue: function(store) {
if (!store.storeid)
throw "unable to queue store without storeid";
if (!queue_idx[store.storeid]) {
queue_idx[store.storeid] = store;
queue.push(store);
}
start_update();
}
});
}
});

View File

@ -1,46 +0,0 @@
Ext.define('PVE.data.UpdateStore', {
extend: 'Ext.data.Store',
requires: [
'PVE.Utils',
'Ext.util.*',
'PVE.data.UpdateQueue'
],
constructor: function(config) {
var me = this;
config = config || {};
if (!config.interval)
config.interval = 3000;
if (!config.storeid)
throw "no storeid specified";
var load_task = new Ext.util.DelayedTask();
var run_load_task = function() {
if (PVE.Utils.authOK()) {
PVE.data.UpdateQueue.queue(me);
load_task.delay(config.interval, run_load_task);
} else {
load_task.delay(200, run_load_task);
}
};
Ext.apply(config, {
startUpdate: function() {
run_load_task();
},
stopUpdate: function() {
load_task.cancel();
}
});
me.callParent([config]);
me.on('destroy', function() {
loadtask.cancel();
});
}
});

View File

@ -1,66 +0,0 @@
/* A reader to store a single JSON Object (hash) into a storage.
* Also accepts an array containing a single hash.
* So it can read:
*
* example1: { data: "xyz" }
* example2: [ { data: "xyz" } ]
*/
Ext.define('PVE.data.reader.JsonObject', {
extend: 'Ext.data.reader.Json',
alias : 'reader.jsonobject',
root: 'data',
constructor: function(config) {
var me = this;
Ext.apply(me, config || {});
me.callParent([config]);
},
getResponseData: function(response) {
var me = this;
var data = [];
try {
var result = Ext.decode(response.responseText);
var root = me.getRoot(result);
if (Ext.isArray(root)) {
if (root.length == 1)
root = root[0];
else
root = {};
}
if (me.rows) {
Ext.Object.each(me.rows, function(key, rowdef) {
if (Ext.isDefined(root[key])) {
data.push({key: key, value: root[key]});
} else if (Ext.isDefined(rowdef.defaultValue)) {
data.push({key: key, value: rowdef.defaultValue});
} else if (rowdef.required) {
data.push({key: key, value: undefined});
}
});
} else {
Ext.Object.each(root, function(key, value) {
data.push({key: key, value: value });
});
}
}
catch (ex) {
Ext.Error.raise({
response: response,
json: response.responseText,
parseError: ex,
msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
});
}
return data;
}
});

View File

@ -1,52 +0,0 @@
Ext.define('PVE.dc.Config', {
extend: 'PVE.panel.Config',
alias: 'widget.PVE.dc.Config',
initComponent: function() {
var me = this;
Ext.apply(me, {
title: "Datacenter",
hstateid: 'dctab',
items: [
{
title: 'Summary',
itemId: 'summary',
html: 'summary '
},
{
title: 'Storage',
itemId: 'storage',
html: 'storage '
},
{
xtype: 'pveUserView',
title: 'Users',
itemId: 'users'
},
{
xtype: 'pveGroupView',
title: 'Groups',
itemId: 'groups'
},
{
xtype: 'pveACLView',
title: 'Permissions',
itemId: 'permissions'
},
{
xtype: 'pveRoleView',
title: 'Roles',
itemId: 'roles'
},
{
xtype: 'pveAuthView',
title: 'Authentication',
itemId: 'domains'
}
]
});
me.callParent();
}
});

View File

@ -1,56 +0,0 @@
Ext.define('PVE.dc.GroupView', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveGroupView'],
initComponent : function() {
var me = this;
var store = new Ext.data.Store({
model: Ext.define('pve-groups', {
extend: 'Ext.data.Model',
fields: [ 'groupid', 'comment' ],
idProperty: 'groupid'
}),
proxy: {
type: 'pve',
url: "/api2/json/access/groups"
},
sorters: {
property: 'groupid',
order: 'DESC'
}
});
Ext.apply(me, {
store: store,
stateful: false,
viewConfig: {
trackOver: false
},
columns: [
{
header: 'Group name',
width: 200,
sortable: true,
dataIndex: 'groupid'
},
{
header: 'Comment',
sortable: false,
dataIndex: 'comment',
flex: 1
}
],
listeners: {
show: function() {
store.load();
}
}
});
me.callParent();
}
});

View File

@ -1,89 +0,0 @@
Ext.define('PVE.dc.Log', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveClusterLog'],
initComponent : function() {
var me = this;
var logstore = new PVE.data.UpdateStore({
storeid: 'pve-cluster-log',
model: 'pve-cluster-log',
proxy: {
type: 'pve',
url: '/api2/json/cluster/log'
}
});
var store = Ext.create('PVE.data.DiffStore', {
rstore: logstore,
appendAtStart: true
});
Ext.apply(me, {
store: store,
stateful: false,
viewConfig: {
trackOver: false,
stripeRows: false, // does not work with getRowClass()
getRowClass: function(record, index) {
var pri = record.get('pri');
if (pri && pri <= 3)
return "x-form-invalid-field";
}
},
sortableColumns: false,
columns: [
{
header: "Start Time",
dataIndex: 'time',
width: 100,
renderer: function(value) {
return Ext.Date.format(value, "M d H:i:s");
}
},
{
header: "Node",
dataIndex: 'node',
width: 100
},
{
header: "Tag",
dataIndex: 'tag',
width: 100
},
{
header: "PID",
dataIndex: 'pid',
width: 100,
},
{
header: "User",
dataIndex: 'user',
width: 150
},
{
header: "Severity",
dataIndex: 'pri',
renderer: PVE.Utils.render_serverity,
width: 100
},
{
header: "Message",
dataIndex: 'msg',
flex: 1
}
],
listeners: {
show: logstore.startUpdate,
hide: logstore.stopUpdate,
destroy: logstore.stopUpdate
}
});
me.callParent();
}
});

View File

@ -1,68 +0,0 @@
Ext.define('PVE.dc.RoleView', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveRoleView'],
initComponent : function() {
var me = this;
var store = new Ext.data.Store({
model: Ext.define('pve-roles', {
extend: 'Ext.data.Model',
fields: [ 'roleid', 'privs' ],
idProperty: 'roleid'
}),
proxy: {
type: 'pve',
url: "/api2/json/access/roles"
},
sorters: {
property: 'roleid',
order: 'DESC'
}
});
var render_privs = function(value, metaData) {
if (!value)
return '-';
// allow word wrap
metaData.style = 'white-space:normal;'
return value.replace(/\,/g, ' ');
};
Ext.apply(me, {
store: store,
stateful: false,
viewConfig: {
trackOver: false
},
columns: [
{
header: 'Role name',
width: 150,
sortable: true,
dataIndex: 'roleid'
},
{
id: 'privs',
header: 'Privileges',
sortable: false,
renderer: render_privs,
dataIndex: 'privs',
flex: 1
}
],
listeners: {
show: function() {
store.load();
}
}
});
me.callParent();
}
});

View File

@ -1,120 +0,0 @@
Ext.define('PVE.dc.Tasks', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveClusterTasks'],
initComponent : function() {
var me = this;
var taskstore = new PVE.data.UpdateStore({
storeid: 'pve-cluster-tasks',
model: 'pve-tasks',
proxy: {
type: 'pve',
url: '/api2/json/cluster/tasks'
},
sorters: [
{
property : 'starttime',
direction: 'ASC'
}
]
});
var store = Ext.create('PVE.data.DiffStore', {
rstore: taskstore,
appendAtStart: true
});
var run_task_viewer = function() {
var sm = me.getSelectionModel();
var rec = sm.getLastSelected();
if (!rec)
return;
var win = Ext.create('PVE.window.TaskViewer', {
upid: rec.data.upid
});
win.show();
};
Ext.apply(me, {
store: store,
stateful: false,
viewConfig: {
trackOver: false,
stripeRows: false, // does not work with getRowClass()
getRowClass: function(record, index) {
var status = record.get('status');
if (status && status != 'OK')
return "x-form-invalid-field";
}
},
sortableColumns: false,
columns: [
{
header: "Start Time",
dataIndex: 'starttime',
width: 100,
renderer: function(value) {
return Ext.Date.format(value, "M d H:i:s");
}
},
{
header: "End Time",
dataIndex: 'endtime',
width: 100,
renderer: function(value, metaData, record) {
if (record.data.pid) {
metaData.css = "x-grid-row-loading";
return "";
}
return Ext.Date.format(value, "M d H:i:s");
}
},
{
header: "Node",
dataIndex: 'node',
width: 100
},
{
header: "User",
dataIndex: 'user',
width: 150
},
{
header: "Description",
dataIndex: 'upid',
flex: 1,
renderer: PVE.Utils.render_upid
},
{
header: "Status",
dataIndex: 'status',
width: 200,
renderer: function(value, metaData, record) {
if (record.data.pid) {
metaData.css = "x-grid-row-loading";
return "";
}
if (value == 'OK')
return 'OK';
// metaData.attr = 'style="color:red;"';
return "ERROR: " + value;
}
}
],
listeners: {
itemdblclick: run_task_viewer,
show: taskstore.startUpdate,
hide: taskstore.stopUpdate,
destroy: taskstore.stopUpdate
}
});
me.callParent();
}
});

View File

@ -1,111 +0,0 @@
Ext.define('PVE.dc.UserView', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveUserView'],
initComponent : function() {
var me = this;
var store = new Ext.data.Store({
model: Ext.define('pve-users', {
extend: 'Ext.data.Model',
fields: [
'userid', 'firstname', 'lastname' , 'email', 'comment',
{ type: 'boolean', name: 'enabled' },
{ type: 'date', dateFormat: 'timestamp', name: 'expire' },
],
idProperty: 'userid'
}),
proxy: {
type: 'pve',
url: "/api2/json/access/users"
},
sorters: {
property: 'userid',
order: 'DESC'
}
});
var render_expire = function(date) {
if (!date)
return 'never';
return Ext.Date.format(date, "Y-m-d");
};
var render_full_name = function(firstname, metaData, record) {
var first = firstname || '';
var last = record.data.lastname || '';
return first + " " + last;
};
var render_username = function(userid) {
return userid.match(/^([^@]+)/)[1];
};
var render_realm = function(userid) {
return userid.match(/@([^@]+)$/)[1];
};
Ext.apply(me, {
store: store,
stateful: false,
viewConfig: {
trackOver: false
},
columns: [
{
header: 'User name',
width: 200,
sortable: true,
renderer: render_username,
dataIndex: 'userid'
},
{
header: 'Realm',
width: 100,
sortable: true,
renderer: render_realm,
dataIndex: 'userid'
},
{
header: 'Enabled',
width: 80,
sortable: true,
dataIndex: 'enabled'
},
{
header: 'Expire',
width: 80,
sortable: true,
renderer: render_expire,
dataIndex: 'expire'
},
{
header: 'Name',
width: 150,
sortable: true,
renderer: render_full_name,
dataIndex: 'firstname'
},
{
id: 'comment',
header: 'Comment',
sortable: false,
dataIndex: 'comment',
flex: 1
}
],
listeners: {
show: function() {
store.load();
}
}
});
me.callParent();
}
});

View File

@ -1,31 +0,0 @@
Ext.define('PVE.form.BondModeSelector', {
extend: 'Ext.form.field.ComboBox',
alias: ['widget.bondModeSelector'],
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.ArrayStore', {
model: 'KeyValue',
data : [
['balance-rr', ''],
['active-backup', ''],
['balance-xor', ''],
['broadcast', ''],
['802.3ad', ''],
['balance-tlb', ''],
['balance-alb', ''],
]
});
Ext.apply(me, {
store: store,
queryMode: 'local',
editable: false,
displayField: 'key',
valueField: 'key'
});
me.callParent();
}
});

View File

@ -1,27 +0,0 @@
Ext.define('PVE.form.BusTypeSelector', {
extend: 'Ext.form.field.ComboBox',
alias: ['widget.PVE.form.BusTypeSelector'],
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.ArrayStore', {
model: 'KeyValue',
data : [
['ide', 'IDE'],
['virtio', 'VIRTIO'],
['scsi', 'SCSI']
]
});
Ext.apply(me, {
store: store,
queryMode: 'local',
editable: false,
displayField: 'value',
valueField: 'key'
});
me.callParent();
}
});

View File

@ -1,16 +0,0 @@
Ext.define('PVE.form.Checkbox', {
extend: 'Ext.form.field.Checkbox',
alias: ['widget.pvecheckbox'],
inputValue: '1',
// also accept integer 1 as true
setRawValue: function(value) {
var me = this;
if (value === 1)
value = true;
me.callParent([value]);
}
});

View File

@ -1,97 +0,0 @@
Ext.define('PVE.form.ComboGrid', {
extend: 'Ext.form.ComboBox',
requires: [
'Ext.grid.Panel',
'PVE.Utils'
],
alias: ['widget.PVE.form.ComboGrid'],
computeHeight: function() {
var me = this;
var lh = PVE.Utils.gridLineHeigh();
var count = me.store.getCount();
return (count > 10) ? 10*lh : 26+count*lh;
},
// copied from ComboBox
createPicker: function() {
var me = this,
picker,
menuCls = Ext.baseCSSPrefix + 'menu',
opts = Ext.apply({
selModel: {
mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
},
floating: true,
hidden: true,
ownerCt: me.ownerCt,
cls: me.el.up('.' + menuCls) ? menuCls : '',
store: me.store,
displayField: me.displayField,
focusOnToFront: false,
height: me.computeHeight(),
pageSize: me.pageSize
}, me.listConfig, me.defaultListConfig);
// NOTE: we simply use a grid panel
//picker = me.picker = Ext.create('Ext.view.BoundList', opts);
picker = me.picker = Ext.create('Ext.grid.Panel', opts);
// pass getNode() to the view
picker.getNode = function() {
picker.getView().getNode(arguments);
};
me.mon(picker, {
itemclick: me.onItemClick,
refresh: me.onListRefresh,
show: function() {
picker.setHeight(me.computeHeight());
},
scope: me
});
me.mon(picker.getSelectionModel(), {
selectionChange: me.onListSelectionChange,
scope: me
});
return picker;
},
initComponent: function() {
var me = this;
Ext.apply(me, {
queryMode: 'local',
editable: false,
matchFieldWidth: false
});
Ext.applyIf(me.listConfig, { width: 400 });
me.callParent();
me.store.on('beforeload', function() {
me.up('form').setLoading(true, true);
});
// hack: autoSelect does not work
me.store.on('load', function(store, r, success, o) {
if (success) {
var def = me.getValue();
if (!def || !store.findRecord(me.valueField, def)) {
var rec = me.store.first();
if (me.autoSelect && rec && rec.data) {
def = rec.data[me.valueField];
me.setValue(def);
} else {
me.setValue('');
}
}
}
me.up('form').setLoading(false);
});
}
});

View File

@ -1,27 +0,0 @@
Ext.define('PVE.form.DiskFormatSelector', {
extend: 'Ext.form.field.ComboBox',
alias: ['widget.PVE.form.DiskFormatSelector'],
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.ArrayStore', {
model: 'KeyValue',
data : [
['raw', 'Raw disk image (raw)'],
['qcow2', 'QEMU image format (qcow2)'],
['vmdk', 'VMware image format (vmdk)']
]
});
Ext.apply(me, {
store: store,
queryMode: 'local',
editable: false,
displayField: 'value',
valueField: 'key'
});
me.callParent();
}
});

View File

@ -1,85 +0,0 @@
Ext.define('PVE.form.FileSelector', {
extend: 'PVE.form.ComboGrid',
requires: [
'Ext.data.Store',
'PVE.RestProxy'
],
alias: ['widget.PVE.form.FileSelector'],
setStorage: function(storage, nodename) {
var me = this;
var change = false;
if (storage && (me.storage !== storage)) {
me.storage = storage;
change = true;
}
if (nodename && (me.nodename !== nodename)) {
me.nodename = nodename;
change = true;
}
if (!(me.storage && me.nodename && change))
return;
var url = '/api2/json/nodes/' + me.nodename + '/storage/' + me.storage;
if (me.storageContent)
url += '?content=' + me.storageContent;
me.store.setProxy({
type: 'pve',
url: url
});
me.store.load();
},
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.Store', {
fields: [ 'volid', 'format', 'size', 'used', 'vmid',
{ name: 'text',
convert: function(value, record) {
if (value)
return value;
return record.data.volid.replace(/^.*:.*\//,'');;
}
}],
});
Ext.apply(me, {
store: store,
allowBlank: false,
autoSelect: false,
valueField: 'volid',
displayField: 'text',
listConfig: {
columns: [
{
header: 'Name',
dataIndex: 'text',
hideable: false,
flex: 1
},
{
header: 'Format',
width: 60,
dataIndex: 'format'
},
{
header: 'Size',
width: 60,
dataIndex: 'size',
renderer: PVE.Utils.format_size
}
]
}
});
me.callParent();
me.setStorage(me.storage, me.nodename);
}
});

View File

@ -1,27 +0,0 @@
Ext.define('PVE.form.NetworkCardSelector', {
extend: 'Ext.form.field.ComboBox',
alias: ['widget.PVE.form.NetworkCardSelector'],
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.ArrayStore', {
model: 'KeyValue',
data : [
['rtl8139', 'Realtec RTL8139'],
['e1000', 'Intel E1000'],
['virtio', 'VirtIO (paravirtualized)']
]
});
Ext.apply(me, {
store: store,
queryMode: 'local',
editable: false,
displayField: 'value',
valueField: 'key'
});
me.callParent();
}
});

View File

@ -1,71 +0,0 @@
Ext.define('PVE.form.NodeSelector', {
extend: 'PVE.form.ComboGrid',
requires: [
'Ext.data.Store',
'PVE.RestProxy'
],
alias: ['widget.PVE.form.NodeSelector'],
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.Store', {
fields: [ 'name', 'cpu', 'maxcpu', 'mem', 'maxmem', 'uptime' ],
autoLoad: true,
proxy: {
type: 'pve',
url: '/api2/json/nodes'
},
autoDestory: true,
sorters: [
{
property : 'mem',
direction: 'DESC'
},
{
property : 'name',
direction: 'ASC'
}
]
});
Ext.apply(me, {
store: store,
allowBlank: false,
valueField: 'name',
displayField: 'name',
listConfig: {
columns: [
{
header: 'Node',
dataIndex: 'name',
hideable: false,
flex: 1
},
{
header: 'Memory usage',
renderer: PVE.Utils.render_mem_usage,
width: 100,
dataIndex: 'mem'
},
{
header: 'CPU usage',
renderer: PVE.Utils.render_cpu,
sortable: true,
width: 100,
dataIndex: 'cpu'
}
]
},
validator: function(value) {
var rec = me.store.findRecord(me.valueField, value);
if (rec && rec.data && Ext.isNumeric(rec.data.mem))
return true;
return "Node " + value + " seems to be offline!";
}
});
me.callParent();
}
});

View File

@ -1,67 +0,0 @@
Ext.define('PVE.form.RRDTypeSelector', {
extend: 'Ext.form.field.ComboBox',
requires: [
'Ext.state.Manager'
],
alias: ['widget.pveRRDTypeSelector'],
initComponent: function() {
var me = this;
var store = new Ext.data.ArrayStore({
fields: [ 'id', 'timeframe', 'cf', 'text' ],
data : [
[ 'hour', 'hour', 'AVERAGE', "Hour (average)" ],
[ 'hourmax', 'hour', 'MAX', "Hour (max)" ],
[ 'day', 'day', 'AVERAGE', "Day (average)" ],
[ 'daymax', 'day', 'MAX', "Day (max)" ],
[ 'week', 'week', 'AVERAGE', "Week (average)" ],
[ 'weekmax', 'week', 'MAX', "Week (max)" ],
[ 'month', 'month', 'AVERAGE', "Month (average)" ],
[ 'monthmax', 'month', 'MAX', "Month (max)" ],
[ 'year', 'year', 'AVERAGE', "Year (average)" ],
[ 'yearmax', 'year', 'MAX', "Year (max)" ],
]
});
Ext.apply(me, {
store: store,
displayField: 'text',
valueField: 'id',
editable: false,
queryMode: 'local',
value: 'hour',
getState: function() {
var ind = store.findExact('id', me.getValue());
var rec = store.getAt(ind);
if (!rec) return;
return {
id: rec.data.id,
timeframe: rec.data.timeframe,
cf: rec.data.cf
};
},
applyState : function(state) {
if (state && state.id) {
me.setValue(state.id);
}
},
stateEvents: [ 'select' ],
stateful: true,
id: 'pveRRDTypeSelection'
});
me.callParent();
var statechange = function(sp, key, value) {
if (key === me.id) {
me.applyState(value);
}
};
var sp = Ext.state.Manager.getProvider();
me.mon(sp, 'statechange', statechange, me);
}
});

View File

@ -1,61 +0,0 @@
Ext.define('PVE.form.RealmComboBox', {
extend: 'Ext.form.ComboBox',
requires: ['Ext.data.Store', 'PVE.RestProxy'],
alias: ['widget.pveRealmComboBox'],
initComponent: function() {
var me = this;
var stateid = 'pveloginrealm';
var realmstore = Ext.create('Ext.data.Store', {
model: 'pve-domains',
autoDestory: true
});
Ext.apply(me, {
fieldLabel: 'Realm',
name: 'realm',
store: realmstore,
queryMode: 'local',
allowBlank: false,
forceSelection: true,
autoSelect: false,
triggerAction: 'all',
valueField: 'realm',
displayField: 'comment',
getState: function() {
return { value: this.getValue() };
},
applyState : function(state) {
if (state && state.value) {
this.setValue(state.value);
}
},
stateEvents: [ 'select' ],
stateful: true,
id: stateid, // fixme: remove (Stateful does not work without)
stateID: stateid
});
me.callParent();
realmstore.load({
callback: function(r, o, success) {
if (success) {
var def = me.getValue();
if (!def || !realmstore.findRecord('realm', def)) {
if (r[0] && r[0].data)
def = r[0].data.realm;
Ext.each(r, function(record) {
if (record.data && record.data["default"])
def = record.data.realm;
});
}
if (def)
me.setValue(def)
}
}
});
}
});

View File

@ -1,75 +0,0 @@
Ext.define('PVE.form.StorageSelector', {
extend: 'PVE.form.ComboGrid',
requires: [
'Ext.data.Store',
'PVE.RestProxy'
],
alias: ['widget.PVE.form.StorageSelector'],
setNodename: function(nodename) {
var me = this;
if (!nodename || (me.nodename === nodename))
return;
me.nodename = nodename;
var url = '/api2/json/nodes/' + me.nodename + '/storage';
if (me.storageContent)
url += '?content=' + me.storageContent;
me.store.setProxy({
type: 'pve',
url: url
});
me.store.load();
},
initComponent: function() {
var me = this;
var store = Ext.create('Ext.data.Store', {
fields: [ 'storage', 'active', 'type', 'used', 'total' ],
autoDestory: true
});
Ext.apply(me, {
store: store,
allowBlank: false,
valueField: 'storage',
displayField: 'storage',
listConfig: {
columns: [
{
header: 'Name',
dataIndex: 'storage',
hideable: false,
flex: 1
},
{
header: 'Type',
width: 60,
dataIndex: 'type'
},
{
header: 'Used',
width: 60,
dataIndex: 'used',
renderer: PVE.Utils.format_size
},
{
header: 'Capacity',
width: 60,
dataIndex: 'total',
renderer: PVE.Utils.format_size
}
]
}
});
me.callParent();
me.setNodename(me.nodename);
}
});

View File

@ -1,35 +0,0 @@
Ext.define('PVE.form.Textfield', {
extend: 'Ext.form.field.Text',
alias: ['widget.pvetextfield'],
skipEmptyText: true,
deleteEmpty: false,
getSubmitData: function() {
var me = this,
data = null,
val;
if (!me.disabled && me.submitValue && !me.isFileUpload()) {
val = me.getSubmitValue();
if (val !== null) {
data = {};
data[me.getName()] = val;
} else if (me.deleteEmpty) {
data = {};
data['delete'] = me.getName();
}
}
return data;
},
getSubmitValue: function() {
var me = this;
var value = this.processRawValue(this.getRawValue());
if (value !== '')
return value;
return me.skipEmptyText ? null: value;
}
});

View File

@ -1,94 +0,0 @@
Ext.define('PVE.form.ViewSelector', {
extend: 'Ext.form.ComboBox',
requires: ['Ext.data.Store'],
alias: ['widget.pveViewSelector'],
initComponent: function() {
var me = this;
var default_views = {
server: {
text: 'Server View',
groups: ['node']
},
folder: {
text: 'Folder View',
groups: ['type']
},
storage: {
text: 'Storage View',
groups: ['node'],
filterfn: function(node) {
return node.data.type === 'storage';
}
}
};
var groupdef = [];
Ext.Object.each(default_views, function(viewname, value) {
groupdef.push([viewname, value.text]);
});
var store = Ext.create('Ext.data.Store', {
model: 'KeyValue',
proxy: {
type: 'memory',
reader: 'array'
},
data: groupdef,
autoload: true,
autoDestory: true
});
Ext.apply(me, {
hideLabel: true,
store: store,
value: groupdef[0][0],
editable: false,
queryMode: 'local',
allowBlank: false,
forceSelection: true,
autoSelect: false,
triggerAction: 'all',
valueField: 'key',
displayField: 'value',
getViewFilter: function() {
var view = me.getValue();
return Ext.apply({ id: view }, default_views[view] || default_views.server);
},
getState: function() {
return { value: me.getValue() };
},
applyState : function(state, doSelect) {
var view = me.getValue();
if (state && state.value && (view != state.value)) {
var record = store.findRecord('key', state.value);
if (record) {
me.setValue(state.value, true);
if (doSelect) {
me.fireEvent('select', me, [record]);
}
}
}
},
stateEvents: [ 'select' ],
stateful: true,
id: 'view'
});
me.callParent();
var statechange = function(sp, key, value) {
if (key === me.id) {
me.applyState(value, true);
}
};
var sp = Ext.state.Manager.getProvider();
me.mon(sp, 'statechange', statechange, me);
}
});

View File

@ -1,120 +0,0 @@
Ext.define('PVE.grid.ObjectGrid', {
extend: 'Ext.grid.GridPanel',
requires: [
'Ext.grid.*',
'PVE.data.ObjectStore'
],
alias: ['widget.pveObjectGrid'],
getObjectValue: function(key, defaultValue) {
var me = this;
var rec = me.store.getById(key);
if (rec)
return rec.data.value;
return defaultValue;
},
renderKey: function(key, metaData, record, rowIndex, colIndex, store) {
var me = this;
var rows = me.rows;
var rowdef = (rows && rows[key]) ? rows[key] : {};
return rowdef.header || key;
},
renderValue: function(value, metaData, record, rowIndex, colIndex, store) {
var me = this;
var rows = me.rows;
var key = record.data.key;
var rowdef = (rows && rows[key]) ? rows[key] : {};
var renderer = rowdef.renderer;
if (renderer)
return renderer(value, metaData, record, rowIndex, colIndex, store);
return value;
},
initComponent : function() {
var me = this;
var rows = me.rows;
if (!me.rstore) {
if (!me.url)
throw "no url specified";
me.rstore = Ext.create('PVE.data.ObjectStore', {
url: me.url,
interval: me.interval,
rows: me.rows
});
}
var rstore = me.rstore;
var store = Ext.create('PVE.data.DiffStore', { rstore: rstore });
if (rows) {
Ext.Object.each(rows, function(key, rowdef) {
if (Ext.isDefined(rowdef.defaultValue)) {
store.add({ key: key, value: rowdef.defaultValue });
} else if (rowdef.required) {
store.add({ key: key, value: undefined });
}
});
}
store.filters.add(new Ext.util.Filter({
filterFn: function(item) {
if (rows) {
var rowdef = rows[item.data.key];
if (!rowdef || (rowdef.visible === false)) {
return false;
}
}
return true;
}
}));
var load_count = 0;
me.mon(rstore, 'load', function(s, records, success) {
load_count++;
me.setLoading(false);
if (!success) {
me.setLoading("Data load error");
return;
}
});
Ext.applyIf(me, {
store: store,
hideHeaders: true,
stateful: false,
columns: [
{
header: 'Name',
width: me.cwidth1 || 100,
dataIndex: 'key',
renderer: me.renderKey
},
{
flex: 1,
header: 'Value',
dataIndex: 'value',
renderer: me.renderValue
}
]
});
me.on('afterlayout', function() {
if (!load_count)
me.setLoading(true);
});
me.callParent();
}
});

View File

@ -1,203 +0,0 @@
// fixme: remove this fix
// this hack is required for ExtJS 4.0.0
Ext.override(Ext.grid.feature.Chunking, {
attachEvents: function() {
var grid = this.view.up('gridpanel'),
scroller = grid.down('gridscroller[dock=right]');
if (scroller === null ) {
grid.on("afterlayout", this.attachEvents, this);
return;
}
scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
},
rowHeight: PVE.Utils.gridLineHeigh()
});
Ext.define('PVE.grid.ResourceGrid', {
extend: 'Ext.grid.GridPanel',
requires: [
'Ext.grid.*',
'Ext.grid.feature.Chunking',
'Ext.state.Manager',
'Ext.data.*',
'Ext.data.Store',
'Ext.util.*',
'PVE.Utils',
'PVE.data.ResourceStore'
],
alias: ['widget.pveResourceGrid'],
features: [ {ftype: 'chunking'}],
initComponent : function() {
var me = this;
var rstore = PVE.data.ResourceStore;
var sp = Ext.state.Manager.getProvider();
var coldef = rstore.defaultColums();
var store = Ext.create('Ext.data.Store', {
model: 'PVEResources',
sorters: [
{
property : 'type',
direction: 'ASC'
}
],
proxy: { type: 'memory' }
});
var textfilter = '';
var textfilter_match = function(item) {
var match = false;
Ext.each(['name', 'storage', 'node', 'type', 'text'], function(field) {
var v = item.data[field];
if (v !== undefined) {
v = v.toLowerCase();
if (v.indexOf(textfilter) >= 0) {
match = true;
return false;
}
}
});
return match;
};
var updateGrid = function() {
var filterfn = me.viewFilter ? me.viewFilter.filterfn : null;
//console.log("START GRID UPDATE " + me.viewFilter);
store.suspendEvents();
var nodeidx = {};
var gather_child_nodes = function(cn) {
var cs = cn.childNodes,
len = cs.length,
i = 0, n, res;
var orgnode = rstore.data.get(cn.data.id);
if (orgnode) {
if ((!filterfn || filterfn(cn)) &&
(!textfilter || textfilter_match(cn)))
nodeidx[cn.data.id] = orgnode;
}
for (; i < len; i++) {
gather_child_nodes(cs[i]);
}
};
gather_child_nodes(me.pveSelNode);
// remove vanished items
var rmlist = [];
store.each(function(olditem) {
var item = nodeidx[olditem.data.id];
if (!item) {
//console.log("GRID REM UID: " + olditem.data.id);
rmlist.push(olditem);
}
});
if (rmlist.length)
store.remove(rmlist);
// add new items
var addlist = [];
for (var key in nodeidx) {
if (!nodeidx.hasOwnProperty(key))
continue;
var item = nodeidx[key];
// getById() use find(), which is slow (ExtJS4 DP5)
//var olditem = store.getById(item.data.id);
var olditem = store.data.get(item.data.id);
if (!olditem) {
//console.log("GRID ADD UID: " + item.data.id);
var info = Ext.apply({}, item.data);
var child = Ext.ModelMgr.create(info, store.model, info.id);
addlist.push(item);
continue;
}
// try to detect changes
var changes = false;
store.model.prototype.fields.eachKey(function(field) {
if (field != 'id' && item.data[field] != olditem.data[field]) {
changes = true;
//console.log("changed item " + item.id + " " + field + " " + item.data[field] + " != " + olditem.data[field]);
olditem.beginEdit()
olditem.set(field, item.data[field]);
}
});
if (changes) {
olditem.endEdit(true)
olditem.commit(true);
}
};
if (addlist.length)
store.add(addlist);
store.sort();
store.resumeEvents();
store.fireEvent('datachanged', store);
//console.log("END GRID UPDATE");
};
var filter_task = new Ext.util.DelayedTask(function(){
updateGrid();
});
var load_cb = function() { updateGrid(); };
Ext.apply(me, {
title: 'Search',
store: store,
tbar: [
'->',
'Search:', ' ',
{
xtype: 'textfield',
width: 200,
value: textfilter,
enableKeyEvents: true,
listeners: {
keyup: function(field, e) {
var v = field.getValue();
textfilter = v;
filter_task.delay(500);
}
}
}
],
viewConfig: {
stripeRows: true,
trackOver: false
},
listeners: {
itemdblclick: function(v, record) {
var ws = me.up('pveStdWorkspace');
ws.selectById(record.data.id);
},
destroy: function() {
rstore.un("load", load_cb)
}
},
columns: coldef
});
me.callParent();
updateGrid();
rstore.on("load", load_cb);
}
});

View File

@ -1,34 +0,0 @@
Ext.override(Ext.view.Table, {
afterRender: function() {
var me = this;
me.callParent();
me.mon(me.el, {
scroll: me.fireBodyScroll,
scope: me
});
if (!me.featuresMC ||
(me.featuresMC.findIndex('ftype', 'selectable') < 0))
me.el.unselectable();
me.attachEventsForFeatures();
}
});
Ext.define('PVE.grid.SelectFeature', {
extend: 'Ext.grid.feature.Feature',
alias: 'feature.selectable',
mutateMetaRowTpl: function(metaRowTpl) {
var i,
ln = metaRowTpl.length;
for (i = 0; i < ln; i++) {
tpl = metaRowTpl[i];
tpl = tpl.replace(/x-grid-row/, 'x-grid-row x-selectable');
tpl = tpl.replace(/x-grid-cell-inner x-unselectable/g, 'x-grid-cell-inner');
tpl = tpl.replace(/unselectable="on"/g, '');
metaRowTpl[i] = tpl;
};
}
});

View File

@ -1,91 +0,0 @@
#!/usr/bin/perl -w
use strict;
use mod_perl2 '1.9922';
use Encode;
use CGI;
use PVE::pvecfg;
use PVE::JSONSchema;
use PVE::AccessControl;
use PVE::REST;
sub send_output {
my ($r, $data) = @_;
my $encdata = encode('UTF-8', $data);
$r->no_cache (1);
my $x = length ($encdata);
$r->content_type ("text/html;charset=UTF-8");
$r->headers_out->set ("Content-length", "$x");
$r->headers_out->set ("Pragma", "no-cache");
$r->print ($encdata);
}
# NOTE: Requests to this page are not authenticated
# so we must be very careful here
my $r = Apache2::RequestUtil->request();
my $username;
my $token = 'null';
if (my $cookie = $r->headers_in->{Cookie}) {
my $ticket = PVE::REST::extract_auth_cookie($cookie);
if (($username = PVE::AccessControl::verify_ticket($ticket, 1))) {
$token = PVE::AccessControl::assemble_csrf_prevention_token($username);
}
}
my $version = PVE::pvecfg::version() . "/" . PVE::pvecfg::repoid();
$username = '' if !$username;
my $cgi = CGI->new($r);
my %args = $cgi->Vars();
my $workspace = defined($args{console}) ?
"PVE.ConsoleWorkspace" : "PVE.StdWorkspace";
my $jssrc = <<_EOJS;
if (!PVE) PVE = {};
PVE.GUIVersion = '$version';
PVE.UserName = '$username';
PVE.CSRFPreventionToken = '$token';
Ext.require(['*', '$workspace']);
// we need this (the java applet ignores the zindex)
Ext.useShims = true;
Ext.History.fieldid = 'x-history-field';
Ext.onReady(function() { Ext.create('$workspace');});
_EOJS
$jssrc .= "";
my $page = <<_EOD;
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Proxmox Virtual Environment</title>
<link rel="stylesheet" type="text/css" href="/pve2/ext4/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="/pve2/css/ext-pve.css" />
<script type="text/javascript" src="/pve2/ext4/ext-all-debug.js"></script>
<script type="text/javascript" src="/pve2/ext4/pvemanagerlib.js"></script>
<script type="text/javascript">$jssrc</script>
</head>
<body>
<!-- Fields required for history management -->
<form id="history-form" class="x-hidden">
<input type="hidden" id="x-history-field"/>
</form>
</body>
</html>
_EOD
send_output ($r, $page);
exit (0);

View File

@ -1,56 +0,0 @@
Ext.define('PVE.node.Config', {
extend: 'PVE.panel.Config',
alias: 'widget.PVE.node.Config',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
Ext.apply(me, {
title: "Node '" + nodename + "'",
hstateid: 'nodetab',
items: [
{
title: 'Summary',
itemId: 'summary',
xtype: 'pveNodeSummary'
},
{
title: 'Services',
itemId: 'services',
xtype: 'pveNodeServiceView'
},
{
title: 'Network',
itemId: 'network',
xtype: 'pveNodeNetworkView'
},
{
title: 'DNS',
itemId: 'dns',
xtype: 'pveNodeDNSView',
},
{
title: 'Time',
itemId: 'time',
xtype: 'pveNodeTimeView'
},
{
title: 'Syslog',
itemId: 'syslog',
xtype: 'pveNodeSyslog'
},
{
title: 'Task History',
itemId: 'tasks',
xtype: 'pveNodeTasks'
}
]
});
me.callParent();
}
});

View File

@ -1,114 +0,0 @@
Ext.define('PVE.node.DNSEdit', {
extend: 'Ext.window.Window',
requires: [
'PVE.Utils'
],
alias: ['widget.pveNodeDNSEdit'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var formpanel = Ext.create('Ext.form.Panel', {
url: "/api2/extjs/nodes/" + nodename + "/dns",
method: 'PUT',
trackResetOnLoad: true,
bodyPadding: 10,
fieldDefaults: {
labelWidth: 130,
anchor: '100%'
},
items: [
{
xtype: 'textfield',
fieldLabel: 'Search domain',
name: 'search',
allowBlank: false
},
{
xtype: 'textfield',
fieldLabel: 'First DNS server',
vtype: 'IPAddress',
name: 'dns1'
},
{
xtype: 'textfield',
fieldLabel: 'Second DNS server',
vtype: 'IPAddress',
name: 'dns2'
},
{
xtype: 'textfield',
fieldLabel: 'Third DNS server',
vtype: 'IPAddress',
name: 'dns3'
}
]
});
var form = formpanel.getForm();
var submitBtn = Ext.create('Ext.Button', {
text: 'OK',
disabled: true,
handler: function() {
formpanel.submit({
success: function() {
me.close();
},
failure: function(form, action) {
Ext.Msg.alert('Error', PVE.Utils.extractFormActionError(action));
}
});
}
});
var resetBtn = Ext.create('Ext.Button', {
text: 'Reset',
disabled: true,
handler: function(){
form.reset();
}
});
var set_button_status = function() {
var valid = form.isValid();
var dirty = form.isDirty();
submitBtn.setDisabled(!(valid && dirty));
resetBtn.setDisabled(!dirty);
};
form.on('dirtychange', set_button_status);
form.on('validitychange', set_button_status);
formpanel.load({
method: 'GET',
failure: function(form, action) {
var msg = PVE.Utils.extractFormActionError(action);
Ext.Msg.alert("Load failed", msg, function() {
me.close();
});
}
});
Ext.applyIf(me, {
title: "Edit DNS settings",
modal: true,
width: 400,
height: 200,
layout: 'fit',
border: false,
items: formpanel,
buttons: [ submitBtn, resetBtn ]
});
me.callParent();
}
});

View File

@ -1,47 +0,0 @@
Ext.define('PVE.node.DNSView', {
extend: 'PVE.grid.ObjectGrid',
alias: ['widget.pveNodeDNSView'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var run_editor = function() {
var win = Ext.create('PVE.node.DNSEdit', {
pveSelNode: me.pveSelNode
});
win.show();
};
Ext.applyIf(me, {
url: "/api2/json/nodes/" + nodename + "/dns",
cwidth1: 130,
interval: 1000,
rows: {
search: { header: 'Search domain', required: true },
dns1: { header: 'First DNS server', required: true },
dns2: { header: 'Second DNS server' },
dns3: { header: 'Third DNS server' },
},
tbar: [
{
text: "Edit",
handler: run_editor
}
],
listeners: {
itemdblclick: run_editor
}
});
me.callParent();
me.on('show', me.rstore.startUpdate);
me.on('hide', me.rstore.stopUpdate);
me.on('destroy', me.rstore.stopUpdate);
}
});

View File

@ -1,218 +0,0 @@
Ext.define('PVE.node.NetworkEdit', {
extend: 'Ext.window.Window',
alias: ['widget.pveNodeNetworkEdit'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
if (!me.iftype)
throw "no network device type specified";
var create = !me.iface;
var title;
var iface_vtype;
if (create) {
if (me.iftype === 'bridge') {
title = "Create Bridge";
iface_vtype = 'BridgeName';
} else if (me.iftype === 'bond') {
title = "Create Bond";
iface_vtype = 'BondName';
} else
throw "can't create unknown device type";
} else {
title = "Edit network device '" + me.iface + "'";
}
var col2 = [
{
xtype: 'pvecheckbox',
fieldLabel: 'Autostart',
name: 'autostart',
uncheckedValue: 0,
checked: create ? true : undefined
}
];
if (me.iftype === 'bridge') {
col2.push({
xtype: 'textfield',
fieldLabel: 'Bridge ports',
name: 'bridge_ports'
});
} else if (me.iftype === 'bond') {
col2.push({
xtype: 'textfield',
fieldLabel: 'Slaves',
name: 'slaves'
});
col2.push({
xtype: 'bondModeSelector',
fieldLabel: 'Mode',
name: 'bond_mode',
value: create ? 'balance-rr' : undefined,
allowBlank: false
});
}
var url;
var method;
if (create) {
url = "/api2/extjs/nodes/" + nodename + "/network";
method = 'POST';
} else {
url = "/api2/extjs/nodes/" + nodename + "/network/" + me.iface;
method = 'PUT';
}
var formpanel = Ext.create('Ext.form.Panel', {
url: url,
method: method,
trackResetOnLoad: true,
bodyPadding: 10,
border: false,
fieldDefaults: {
labelWidth: 100,
anchor: '100%'
},
layout: 'column',
defaultType: 'container',
items: [
{
columnWidth: .5,
items: [
{
xtype: 'textfield',
fieldLabel: 'Name',
name: 'iface',
value: me.iface,
disabled: !create,
vtype: iface_vtype,
allowBlank: false
},
{
xtype: 'pvetextfield',
deleteEmpty: !create,
fieldLabel: 'IP address',
vtype: 'IPAddress',
name: 'address'
},
{
xtype: 'pvetextfield',
deleteEmpty: !create,
fieldLabel: 'Subnet mask',
vtype: 'IPAddress',
name: 'netmask',
validator: function(value) {
if (!me.items)
return true;
var address = me.down('field[name=address]').getValue();
if (value !== '') {
if (address === '')
return "Subnet mask requires option 'IP address'";
} else {
if (address !== '')
return "Option 'IP address' requires a subnet mask";
}
return true;
}
},
{
xtype: 'pvetextfield',
deleteEmpty: !create,
fieldLabel: 'Gateway',
vtype: 'IPAddress',
name: 'gateway'
}
]
},
{
columnWidth: .5,
items: col2
}
]
});
var form = formpanel.getForm();
var submitBtn = Ext.create('Ext.Button', {
text: 'OK',
disabled: true,
handler: function() {
formpanel.submit({
success: function() {
me.close();
},
failure: function(form, action) {
Ext.Msg.alert('Error', PVE.Utils.extractFormActionError(action));
}
});
}
});
var resetBtn = Ext.create('Ext.Button', {
text: 'Reset',
disabled: true,
handler: function(){
form.reset();
}
});
var set_button_status = function() {
var valid = form.isValid();
var dirty = form.isDirty();
submitBtn.setDisabled(!(valid && dirty));
resetBtn.setDisabled(!dirty);
};
form.on('dirtychange', set_button_status);
form.on('validitychange', set_button_status);
if (!create) {
formpanel.load({
url: "/api2/extjs/nodes/" + nodename + "/network/" + me.iface,
method: 'GET',
failure: function(form, action) {
var msg = PVE.Utils.extractFormActionError(action);
Ext.Msg.alert("Load failed", msg, function() {
me.close();
});
},
success: function(form, action) {
if (action.result.data.type !== me.iftype) {
var msg = "Got unexpected device type";
Ext.Msg.alert("Load failed", msg, function() {
me.close();
});
return;
}
}
});
}
Ext.applyIf(me, {
title: title,
modal: true,
width: 600,
height: 200,
layout: 'fit',
border: false,
items: formpanel,
buttons: [ submitBtn, resetBtn ]
});
if (create)
form.findField('iface').setValue(me.iface_default);
me.callParent();
}
});

View File

@ -1,282 +0,0 @@
Ext.define('PVE.node.NetworkView', {
extend: 'Ext.panel.Panel',
alias: ['widget.pveNodeNetworkView'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var rstore = Ext.create('PVE.data.UpdateStore', {
interval: 1000,
storeid: 'pve-networks',
model: Ext.define('pve-networks', {
extend: 'Ext.data.Model',
fields: [
'iface', 'type', 'active', 'autostart',
'bridge_ports', 'slaves', 'address',
'netmask', 'gateway'
],
idProperty: 'iface',
proxy: {
type: 'pve',
url: "/api2/json/nodes/" + nodename + "/network",
}
}),
sorters: [
{
property : 'iface',
direction: 'ASC'
}
]
});
var store = Ext.create('PVE.data.DiffStore', { rstore: rstore });
var view_changes = function() {
var changeitem = me.down('#changes');
PVE.Utils.API2Request({
url: '/nodes/' + nodename + '/network_changes',
failure: function(response, opts) {
changeitem.update('Error: ' + response.htmlStatus);
},
success: function(response, opts) {
var result = Ext.decode(response.responseText);
var data = result.data;
if (data === '')
data = "no changes"
changeitem.update("<pre>" + Ext.htmlEncode(data) + "</pre>");
}
});
};
var reload = function() {
rstore.load();
view_changes();
};
var run_editor = function() {
var grid = me.down('gridpanel');
var sm = grid.getSelectionModel();
var rec = sm.getLastSelected();
if (!rec)
return;
var win = Ext.create('PVE.node.NetworkEdit', {
pveSelNode: me.pveSelNode,
iface: rec.data.iface,
iftype: rec.data.type
});
win.show();
win.on('destroy', reload)
};
var edit_btn = new Ext.Button({
text: 'Edit',
disabled: true,
handler: run_editor
});
var del_btn = new Ext.Button({
text: 'Delete',
disabled: true,
handler: function(){
var grid = me.down('gridpanel');
var sm = grid.getSelectionModel();
var rec = sm.getLastSelected();
if (!rec)
return;
var iface = rec.data.iface;
me.setLoading(true, true);
PVE.Utils.API2Request({
url: '/nodes/' + nodename + '/network/' + iface,
method: 'DELETE',
callback: function() {
me.setLoading(false);
reload();
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
}
});
var set_button_status = function() {
var grid = me.down('gridpanel');
var sm = grid.getSelectionModel();
var rec = sm.getLastSelected();
edit_btn.setDisabled(!rec);
del_btn.setDisabled(!rec);
};
me.mon(rstore, 'load', function(s, records, success) {
if (!success) {
me.setLoading("Data load error");
return;
} else {
me.setLoading(false);
}
});
var render_ports = function(value, metaData, record) {
if (value === 'bridge')
return record.data.bridge_ports;
if (value === 'bond')
return record.data.slaves;
};
Ext.apply(me, {
layout: 'border',
tbar: [
{
text: 'Create',
menu: new Ext.menu.Menu({
items: [
{
text: 'Bridge',
handler: function() {
var next;
for (next = 0; next <= 9999; next++) {
if (!rstore.data.get('vmbr' + next))
break;
}
var win = Ext.create('PVE.node.NetworkEdit', {
pveSelNode: me.pveSelNode,
iftype: 'bridge',
iface_default: 'vmbr' + next
});
win.on('destroy', reload)
win.show();
}
},
{
text: 'Bond',
handler: function() {
var next;
for (next = 0; next <= 9999; next++) {
if (!rstore.data.get('bond' + next))
break;
}
var win = Ext.create('PVE.node.NetworkEdit', {
pveSelNode: me.pveSelNode,
iftype: 'bond',
iface_default: 'bond' + next
});
win.on('destroy', reload)
win.show();
}
}
]
})
}, ' ',
{
text: 'Revert changes',
handler: function() {
me.setLoading(true, true);
PVE.Utils.API2Request({
url: '/nodes/' + nodename + '/network_changes',
method: 'DELETE',
callback: function() {
me.setLoading(false);
reload();
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
}
},
edit_btn,
del_btn
],
items: [
{
xtype: 'gridpanel',
stateful: false,
store: store,
region: 'center',
border: false,
columns: [
{
header: 'Interface Name',
width: 100,
sortable: true,
dataIndex: 'iface'
},
{
xtype: 'booleancolumn',
header: 'Active',
width: 80,
sortable: true,
dataIndex: 'active',
trueText: 'Yes',
falseText: 'No',
undefinedText: 'No'
},
{
xtype: 'booleancolumn',
header: 'Autostart',
width: 80,
sortable: true,
dataIndex: 'autostart',
trueText: 'Yes',
falseText: 'No',
undefinedText: 'No'
},
{
header: 'Ports/Slaves',
dataIndex: 'type',
renderer: render_ports
},
{
header: 'IP address',
sortable: true,
dataIndex: 'address'
},
{
header: 'Subnet mask',
sortable: true,
dataIndex: 'netmask'
},
{
header: 'Gateway',
sortable: true,
dataIndex: 'gateway'
}
],
listeners: {
selectionchange: set_button_status,
itemdblclick: run_editor
}
},
{
border: false,
region: 'south',
autoScroll: true,
itemId: 'changes',
tbar: [
'Pending changes (please reboot to activate changes)'
],
split: true,
bodyPadding: 5,
flex: 0.6,
html: "no changes"
}
],
listeners: {
show: reload
}
});
me.callParent();
}
});

View File

@ -1,151 +0,0 @@
Ext.define('PVE.node.ServiceView', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveNodeServiceView'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var rstore = Ext.create('PVE.data.UpdateStore', {
interval: 1000,
storeid: 'pve-services',
model: Ext.define('pve-services', {
extend: 'Ext.data.Model',
fields: [ 'service', 'name', 'desc', 'state' ],
idProperty: 'service',
proxy: {
type: 'pve',
url: "/api2/json/nodes/" + nodename + "/services",
}
})
});
var store = Ext.create('PVE.data.DiffStore', { rstore: rstore });
var service_cmd = function(cmd) {
var sm = me.getSelectionModel();
var rec = sm.getLastSelected();
PVE.Utils.API2Request({
url: "/nodes/" + nodename + "/services/" + rec.data.service,
params: { command: cmd },
method: 'PUT',
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
me.loading = true;
},
success: function(response, opts) {
rstore.startUpdate();
}
});
};
var start_btn = new Ext.Button({
text: 'Start',
disabled: true,
handler: function(){
service_cmd("start");
}
});
var stop_btn = new Ext.Button({
text: 'Stop',
disabled: true,
handler: function(){
service_cmd("stop");
}
});
var restart_btn = new Ext.Button({
text: 'Restart',
disabled: true,
handler: function(){
service_cmd("restart");
}
});
var set_button_status = function() {
var sm = me.getSelectionModel();
var rec = sm.getLastSelected();
if (!rec) {
start_btn.disable();
stop_btn.disable();
restart_btn.disable();
return;
}
var service = rec.data.service;
var state = rec.data.state;
if (service == 'apache' ||
service == 'pvecluster' ||
service == 'pvedaemon') {
if (state == 'running') {
start_btn.disable();
restart_btn.enable();
} else {
start_btn.enable();
restart_btn.disable();
}
stop_btn.disable();
} else {
if (state == 'running') {
start_btn.disable();
restart_btn.enable();
stop_btn.enable();
} else {
start_btn.enable();
restart_btn.disable();
stop_btn.disable();
}
}
};
me.mon(store, 'datachanged', set_button_status);
me.mon(rstore, 'load', function(s, records, success) {
if (!success) {
me.setLoading("Data load error");
return;
} else {
me.setLoading(false);
}
});
Ext.apply(me, {
store: store,
stateful: false,
tbar: [ start_btn, stop_btn, restart_btn ],
columns: [
{
header: 'Name',
width: 100,
sortable: true,
dataIndex: 'name'
},
{
header: 'State',
width: 100,
sortable: true,
dataIndex: 'state'
},
{
header: 'Description',
dataIndex: 'desc',
flex: 1
}
],
listeners: {
selectionchange: set_button_status,
show: rstore.startUpdate,
hide: rstore.stopUpdate,
destroy: rstore.stopUpdate,
}
});
me.callParent();
}
});

View File

@ -1,50 +0,0 @@
Ext.define('PVE.node.StatusView', {
extend: 'PVE.grid.ObjectGrid',
alias: ['widget.pveNodeStatusView'],
initComponent : function() {
var me = this;
var render_cpuinfo = function(value) {
return value.cpus + " x " + value.model;
};
var render_loadavg = function(value) {
return value[0] + ", " + value[1] + ", " + value[2];
};
var render_cpu = function(value) {
var per = value * 100;
return per.toFixed(2) + "%";
};
var render_meminfo = function(value) {
var per = (value.used / value.total)*100;
var text = "<div>Total: " + PVE.Utils.format_size(value.total) + "</div>" +
"<div>Used: " + PVE.Utils.format_size(value.used) + "</div>";
return text;
};
var rows = {
uptime: { header: 'Uptime', required: true, renderer: PVE.Utils.format_duration_long },
loadavg: { header: 'Load average', required: true, renderer: render_loadavg },
cpuinfo: { header: 'CPUs', required: true, renderer: render_cpuinfo },
cpu: { header: 'CPU usage',required: true, renderer: render_cpu },
wait: { header: 'IO delay', required: true, renderer: render_cpu },
memory: { header: 'RAM usage', required: true, renderer: render_meminfo },
swap: { header: 'SWAP usage', required: true, renderer: render_meminfo },
rootfs: { header: 'HD space (root)', required: true, renderer: render_meminfo },
pveversion: { header: 'PVE Manager version', required: true,},
kversion: { header: 'Kernel version', required: true,}
};
Ext.applyIf(me, {
cwidth1: 150,
interval: 1000,
height: 286,
rows: rows
});
me.callParent();
}
});

View File

@ -1,139 +0,0 @@
Ext.define('PVE.node.Summary', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveNodeSummary',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
rstore = Ext.create('PVE.data.ObjectStore', {
url: "/api2/json/nodes/" + nodename + "/status",
interval: 1000
});
var node_command = function(cmd) {
me.setLoading(true, true);
PVE.Utils.API2Request({
params: { command: cmd },
url: '/nodes/' + nodename + '/status',
method: 'POST',
callback: function() {
me.setLoading(false);
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
};
var rrdurl = "/api2/png/nodes/" + nodename + "/rrd";
var tbar = Ext.create('Ext.toolbar.Toolbar', {
items: [
{
itemId: 'reboot',
text: 'Reboot',
handler: function() {
var msg = "Do you really want to reboot node '" + nodename + "'?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
node_command('reboot');
});
}
},
{
itemId: 'shutdown',
text: 'Shutdown',
handler: function() {
var msg = "Do you really want to shutdown node '" + nodename + "'?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
node_command('shutdown');
});
}
},
{
itemId: 'shell',
text: 'Shell',
handler: function() {
var url = Ext.urlEncode({
console: 'shell',
node: nodename
});
var nw = window.open("?" + url, '_blank',
"innerWidth=745,innerheight=427");
nw.focus();
}
}, '->',
{
xtype: 'pveRRDTypeSelector'
}
]
});
me.mon(rstore, 'load', function(s, records, success) {
var uptimerec = s.data.get('uptime');
var uptime = uptimerec ? uptimerec.data.value : false;
tbar.down('#reboot').setDisabled(!uptime);
tbar.down('#shutdown').setDisabled(!uptime);
tbar.down('#shell').setDisabled(!uptime);
});
Ext.apply(me, {
layout: {
type: 'table',
columns: 1
},
autoScroll: true,
bodyStyle: 'padding:10px',
defaults: {
style: 'padding-bottom:10px'
},
tbar: tbar,
items: [
{
title: 'Status',
xtype: 'pveNodeStatusView',
rstore: rstore,
width: 800
},
{
xtype: 'pveRRDView',
title: "CPU usage %",
datasource: 'cpu,iowait',
rrdurl: rrdurl
},
{
xtype: 'pveRRDView',
title: "Server load",
datasource: 'loadavg',
rrdurl: rrdurl
},
{
xtype: 'pveRRDView',
title: "Memory usage",
datasource: 'memtotal,memused',
rrdurl: rrdurl
},
{
xtype: 'pveRRDView',
title: "Network traffic",
datasource: 'netin,netout',
rrdurl: rrdurl
}
]
});
me.on('show', rstore.startUpdate);
me.on('hide', rstore.stopUpdate);
me.on('destroy', rstore.stopUpdate);
me.callParent();
}
});

View File

@ -1,47 +0,0 @@
Ext.define('PVE.node.Syslog', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveNodeSyslog'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var store = Ext.create('Ext.data.Store', {
pageSize: 500,
buffered: true,
model: 'pve-string-list',
proxy: {
type: 'pve',
startParam: 'start',
limitParam: 'limit',
url: "/api2/json/nodes/" + nodename + "/syslog"
}
});
Ext.apply(me, {
store: store,
features: [ {ftype: 'selectable'}],
stateful: false,
verticalScrollerType: 'paginggridscroller',
loadMask: true,
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
stripeRows: false
},
hideHeaders: true,
columns: [
{ header: "Text", dataIndex: 't', flex: 1 }
]
});
me.callParent();
store.guaranteeRange(0, store.pageSize - 1);
}
});

View File

@ -1,159 +0,0 @@
Ext.define('PVE.node.Tasks', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveNodeTasks'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var store = Ext.create('Ext.data.Store', {
pageSize: 500,
buffered: true,
remoteFilter: true,
model: 'pve-tasks',
proxy: {
type: 'pve',
startParam: 'start',
limitParam: 'limit',
url: "/api2/json/nodes/" + nodename + "/tasks"
},
});
var userfilter = '';
var filter_errors = 0;
// fixme: scroller update fails
// http://www.sencha.com/forum/showthread.php?133677-scroller-does-not-adjust-to-the-filtered-grid-data&p=602887
var reload_task = new Ext.util.DelayedTask(function() {
var params = {
errors: filter_errors
};
if (userfilter)
params.userfilter = userfilter;
store.proxy.extraParams = params;
store.filter();
});
var run_task_viewer = function() {
var sm = me.getSelectionModel();
var rec = sm.getLastSelected();
if (!rec)
return;
var win = Ext.create('PVE.window.TaskViewer', {
upid: rec.data.upid
});
win.show();
};
var view_btn = new Ext.Button({
text: 'View',
disabled: true,
handler: run_task_viewer
});
Ext.apply(me, {
store: store,
stateful: false,
verticalScrollerType: 'paginggridscroller',
loadMask: true,
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
stripeRows: false, // does not work with getRowClass()
getRowClass: function(record, index) {
var status = record.get('status');
if (status && status != 'OK')
return "x-form-invalid-field";
}
},
tbar: [
view_btn, '->', 'User:', ' ',
{
xtype: 'textfield',
width: 200,
value: userfilter,
enableKeyEvents: true,
listeners: {
keyup: function(field, e) {
userfilter = field.getValue();
reload_task.delay(500);
}
}
}, ' ', 'Only Errors:', ' ',
{
xtype: 'checkbox',
hideLabel: true,
checked: filter_errors,
listeners: {
change: function(field, checked) {
filter_errors = checked ? 1 : 0;
reload_task.delay(10);
}
}
}, ' '
],
sortableColumns: false,
columns: [
{
header: "Start Time", dataIndex: 'starttime',
width: 100,
renderer: function(value) {
return Ext.Date.format(value, "M d H:i:s");
}
},
{
header: "End Time", dataIndex: 'endtime',
width: 100,
renderer: function(value, metaData, record) {
return Ext.Date.format(value,"M d H:i:s");
}
},
{
header: "Node", dataIndex: 'node',
width: 100
},
{
header: "User", dataIndex: 'user',
width: 150
},
{
header: "Description", dataIndex: 'upid',
flex: 1,
renderer: PVE.Utils.render_upid
},
{
header: "Status", dataIndex: 'status',
width: 200,
renderer: function(value, metaData, record) {
if (value == 'OK')
return 'OK';
// metaData.attr = 'style="color:red;"';
return "ERROR: " + value;
}
}
],
listeners: {
itemdblclick: run_task_viewer,
selectionchange: function(v, selections) {
view_btn.setDisabled(!(selections && selections[0]));
},
show: function() { reload_task.delay(10); }
}
});
me.callParent();
store.guaranteeRange(0, store.pageSize - 1);
}
});

View File

@ -1,98 +0,0 @@
Ext.define('PVE.node.TimeEdit', {
extend: 'Ext.window.Window',
requires: ['PVE.data.TimezoneStore'],
alias: ['widget.pveNodeTimeEdit'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var formpanel = Ext.create('Ext.form.Panel', {
url: "/api2/extjs/nodes/" + nodename + "/time",
method: 'PUT',
trackResetOnLoad: true,
bodyPadding: 10,
fieldDefaults: {
labelWidth: 80,
anchor: '100%'
},
items: {
xtype: 'combo',
fieldLabel: 'Time zone',
name: 'timezone',
queryMode: 'local',
store: new PVE.data.TimezoneStore({autoDestory: true}),
valueField: 'zone',
displayField: 'zone',
triggerAction: 'all',
forceSelection: true,
editable: false,
allowBlank: false
}
});
var form = formpanel.getForm();
var submitBtn = Ext.create('Ext.Button', {
text: 'OK',
disabled: true,
handler: function() {
formpanel.submit({
success: function() {
me.close();
},
failure: function(form, action) {
Ext.Msg.alert('Error', PVE.Utils.extractFormActionError(action));
}
});
}
});
var resetBtn = Ext.create('Ext.Button', {
text: 'Reset',
disabled: true,
handler: function(){
form.reset();
}
});
var set_button_status = function() {
var valid = form.isValid();
var dirty = form.isDirty();
submitBtn.setDisabled(!(valid && dirty));
resetBtn.setDisabled(!dirty);
};
form.on('dirtychange', set_button_status);
form.on('validitychange', set_button_status);
formpanel.load({
method: 'GET',
failure: function(form, action) {
var msg = PVE.Utils.extractFormActionError(action);
Ext.Msg.alert("Load failed", msg, function() {
me.close();
});
}
});
Ext.applyIf(me, {
title: "Set time zone",
modal: true,
width: 400,
height: 110,
layout: 'fit',
border: false,
items: formpanel,
buttons: [ submitBtn, resetBtn ]
});
me.callParent();
}
});

View File

@ -1,57 +0,0 @@
Ext.define('PVE.node.TimeView', {
extend: 'PVE.grid.ObjectGrid',
alias: ['widget.pveNodeTimeView'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var tzoffset = (new Date()).getTimezoneOffset()*60000;
var renderlocaltime = function(value) {
var servertime = new Date((value * 1000) + tzoffset);
return Ext.Date.format(servertime, 'Y-m-d H:i:s');
};
var run_editor = function() {
var win = Ext.create('PVE.node.TimeEdit', {
pveSelNode: me.pveSelNode
});
win.show();
};
Ext.applyIf(me, {
url: "/api2/json/nodes/" + nodename + "/time",
cwidth1: 150,
interval: 1000,
rows: {
timezone: {
header: 'Time zone',
required: true,
},
localtime: {
header: 'Server time',
required: true,
renderer: renderlocaltime
}
},
tbar: [
{
text: "Edit",
handler: run_editor
}
],
listeners: {
itemdblclick: run_editor
}
});
me.callParent();
me.on('show', me.rstore.startUpdate);
me.on('hide', me.rstore.stopUpdate);
me.on('destroy', me.rstore.stopUpdate);
}
});

View File

@ -1,24 +0,0 @@
Ext.define('PVE.openvz.CreateWizard', {
extend: 'PVE.window.Wizard',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
title: 'Create new container',
items: [
{
title: 'Not implemented',
descr: 'Sorry, this fuctionality is not implelemnted',
layout: 'fit',
html: 'not implemented'
}
]
});
me.callParent();
}
});

View File

@ -1,85 +0,0 @@
Ext.define('PVE.panel.Config', {
extend: 'Ext.tab.Panel',
requires: [
'Ext.state.Manager',
'PVE.grid.ResourceGrid'
],
alias: 'widget.PVE.panel.Config',
initComponent: function() {
var me = this;
var stateid = me.hstateid;
var sp = Ext.state.Manager.getProvider();
var items = me.items || [];
me.items = null;
Ext.applyIf(me, {
title: me.pveSelNode.data.text,
showSearch: true,
defaults: {}
});
// pass rstore, pveSelNode and viewFilter to all children
Ext.apply(me.defaults, {
pveSelNode: me.pveSelNode,
viewFilter: me.viewFilter,
border: false
});
if (me.showSearch) {
items.unshift({
itemId: 'search',
xtype: 'pveResourceGrid'
});
}
Ext.apply(me, {
listeners: {
tabchange: function(tp, newcard, oldcard) {
var ntab = newcard.itemId;
// Note: '' is alias for first tab.
// First tab can be 'search' or something else
if (newcard.itemId === items[0].itemId)
ntab = '';
var state = { value: ntab };
if (stateid) {
sp.set(stateid, state);
}
}
},
items: items
});
if (stateid) {
var state = sp.get(stateid);
if (state && state.value) {
me.activeTab = state.value;
}
}
me.callParent();
me.items.get(0).fireEvent('show', me.items.get(0));
var statechange = function(sp, key, state) {
if (stateid && key === stateid) {
var atab = me.getActiveTab().itemId;
var ntab = state.value || items[0].itemId;
if (state && ntab && (atab != ntab)) {
me.setActiveTab(ntab);
}
}
};
if (stateid) {
sp.on('statechange', statechange);
me.on('destroy', function() {
sp.un('statechange', statechange);
});
}
}
});

View File

@ -1,89 +0,0 @@
Ext.define('PVE.panel.RRDView', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveRRDView',
initComponent : function() {
var me = this;
if (!me.timeframe)
me.timeframe = 'hour';
if (!me.rrdcffn)
me.rrdcffn = 'AVERAGE';
if (!me.datasource)
throw "no datasource specified";
if (!me.rrdurl)
throw "no rrdurl specified";
var datasource = me.datasource;
// fixme: dcindex??
var dcindex = 0;
var create_url = function() {
var url = me.rrdurl + "?ds=" + datasource +
"&timeframe=" + me.timeframe + "&cf=" + me.rrdcffn +
"&_dc=" + dcindex;
dcindex++;
return url;
}
var stateid = 'pveRRDTypeSelection';
Ext.apply(me, {
layout: 'fit',
html: {
tag: 'img',
width: 800,
height: 200,
src: create_url()
},
applyState : function(state) {
if (state && state.id) {
me.timeframe = state.timeframe;
me.rrdcffn = state.cf;
me.reload_task.delay(10);
}
}
});
me.callParent();
me.reload_task = new Ext.util.DelayedTask(function() {
if (me.rendered) {
try {
var html = {
tag: 'img',
width: 800,
height: 200,
src: create_url()
};
me.update(html);
} catch (e) {
// fixme:
console.log(e);
}
me.reload_task.delay(30000);
} else {
me.reload_task.delay(1000);
}
});
me.reload_task.delay(30000);
me.on('destroy', function() {
me.reload_task.cancel();
});
var sp = Ext.state.Manager.getProvider();
me.applyState(sp.get(stateid));
var state_change_fn = function(prov, key, value) {
if (key == stateid) {
me.applyState(value);
}
};
me.mon(sp, 'statechange', state_change_fn);
}
});

View File

@ -1,66 +0,0 @@
Ext.define('PVE.panel.StatusPanel', {
extend: 'Ext.tab.Panel',
requires: [
'Ext.state.Manager',
'PVE.dc.Log',
'PVE.dc.Tasks'
],
alias: 'widget.pveStatusPanel',
title: "Realtime logfile viewer",
tabPosition: 'bottom',
initComponent: function() {
var me = this;
var stateid = 'ltab';
var sp = Ext.state.Manager.getProvider();
var state = sp.get(stateid);
if (state && state.value) {
me.activeTab = state.value;
}
Ext.apply(me, {
listeners: {
tabchange: function() {
var atab = me.getActiveTab().itemId;
var state = { value: atab };
sp.set(stateid, state);
}
},
items: [
{
itemId: 'clog',
title: 'Cluster log',
xtype: 'pveClusterLog'
},
{
itemId: 'tasks',
title: 'Recent tasks',
xtype: 'pveClusterTasks'
}
]
});
me.callParent();
me.items.get(0).fireEvent('show', me.items.get(0));
var statechange = function(sp, key, state) {
if (key === stateid) {
var atab = me.getActiveTab().itemId;
var ntab = state.value;
if (state && ntab && (atab != ntab)) {
me.setActiveTab(ntab);
}
}
};
sp.on('statechange', statechange);
me.on('destroy', function() {
sp.un('statechange', statechange);
});
}
});

View File

@ -1,57 +0,0 @@
Ext.define('PVE.qemu.Config', {
extend: 'PVE.panel.Config',
alias: 'widget.PVE.qemu.Config',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var vmid = me.pveSelNode.data.vmid;
if (!vmid)
throw "no VM ID specified";
var vmname = me.pveSelNode.data.name;
var descr = vmname ? "'" + vmname + "' " : '';
Ext.apply(me, {
title: "Virtual machine " + descr + "'KVM " + vmid +
"' on node '" + nodename + "'",
hstateid: 'kvmtab',
items: [
{
title: 'Summary',
xtype: 'pveQemuSummary',
itemId: 'summary'
},
{
title: 'Hardware',
itemId: 'hardware',
xtype: 'PVE.qemu.HardwareView'
},
{
title: 'Options',
itemId: 'options',
html: 'options ' + vmid
},
{
xtype: 'pveKVMConsole',
title: 'Console',
itemId: 'console',
//disabled: true,
nodename: nodename,
vmid: vmid
},
{
title: 'Permissions',
itemId: 'permissions',
html: 'permissions ' + vmid
}
]
});
me.callParent();
}
});

View File

@ -1,429 +0,0 @@
Ext.define('PVE.qemu.CreateWizard', {
extend: 'PVE.window.Wizard',
requires: [
'Ext.form.*',
'PVE.data.ResourceStore'
],
initComponent: function() {
var me = this;
var nextvmid = PVE.data.ResourceStore.findNextVMID();
var summarystore = Ext.create('Ext.data.Store', {
model: 'KeyValue',
sorters: [
{
property : 'key',
direction: 'ASC'
}
]
});
var cdfilesel = Ext.create('PVE.form.FileSelector', {
name: 'cdimage',
storageContent: 'iso',
fieldLabel: 'ISO Image',
labelAlign: 'right',
allowBlank: false
});
var cdstoragesel = Ext.create('PVE.form.StorageSelector', {
name: 'cdstorage',
fieldLabel: 'Storage',
storageContent: 'iso',
labelAlign: 'right',
allowBlank: false,
listeners: {
change: function(f, value) {
cdfilesel.setStorage(value);
}
}
});
var hdstoragesel = Ext.create('PVE.form.StorageSelector', {
name: 'hdstorage',
fieldLabel: 'Storage',
labelAlign: 'right',
storageContent: 'images',
allowBlank: false
});
Ext.applyIf(me, {
title: 'Create new virtual machine',
items: [
{
xtype: 'inputpanel',
title: 'General',
items: [
{
xtype: 'PVE.form.NodeSelector',
name: 'nodename',
fieldLabel: 'Node',
allowBlank: false,
listeners: {
change: function(f, value) {
hdstoragesel.setNodename(value);
cdstoragesel.setNodename(value);
cdfilesel.setStorage(undefined, value);
}
}
},
{
xtype: 'numberfield',
name: 'vmid',
value: nextvmid,
minValue: 100,
maxValue: 999999999,
fieldLabel: 'VM ID',
allowBlank: false,
validator: function(value) {
if (!PVE.data.ResourceStore.findVMID(value))
return true;
return "This VM ID is already in use."
}
},
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'VM name',
allowBlank: true
}
],
onGetValues: function(values) {
if (!values.name)
delete values.name;
return values;
}
},
{
title: 'OS Type',
layout: 'fit',
items: {
xtype: 'radiogroup',
allowBlank: false,
layout: 'column',
defaultType: 'container',
items: [{
columnWidth: .5,
items: [
{
xtype: 'component',
html: 'Microsoft Windows',
cls:'x-form-check-group-label'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'win7',
boxLabel: 'Microsoft Windows 7/2008r2'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'w2k8',
boxLabel: 'Microsoft Windows Vista/2008'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'wxp',
boxLabel: 'Microsoft Windows XP/2003'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'w2k',
boxLabel: 'Microsoft Windows 2000'
}
]
},{
columnWidth: .5,
items: [
{
xtype: 'component',
html: 'Linux/Other',
cls:'x-form-check-group-label'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'l26',
boxLabel: 'Linux 2.6 Kernel'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'l24',
boxLabel: 'Linux 2.4 Kernel'
},
{
xtype: 'radiofield',
name: 'ostype',
inputValue: 'other',
boxLabel: 'Other'
}
]
}]
}
},
{
xtype: 'inputpanel',
title: 'Installation Media',
items: [
{
xtype: 'radiofield',
name: 'mediaType',
inputValue: 'iso',
boxLabel: 'Use CD/DVD disc image file (iso)',
checked: true,
listeners: {
change: function(f, value) {
me.down('field[name=cdstorage]').setDisabled(!value);
me.down('field[name=cdimage]').setDisabled(!value);
}
}
},
cdstoragesel,
cdfilesel,
{
xtype: 'radiofield',
name: 'mediaType',
inputValue: 'cdrom',
boxLabel: 'Use physical CD/DVD Drive'
},
{
xtype: 'radiofield',
name: 'mediaType',
inputValue: 'none',
boxLabel: 'Do not use any installation media'
}
],
onGetValues: function(values) {
if (values.mediaType === 'iso')
return { cdrom: values.cdimage };
if (values.mediaType === 'cdrom')
return { cdrom: 'cdrom' };
return { cdrom: 'none' };
}
},
{
xtype: 'inputpanel',
title: 'Harddisk',
items: [
{
xtype: 'radiofield',
name: 'hdType',
inputValue: 'image',
boxLabel: 'Create new disk image',
checked: true,
listeners: {
change: function(f, value) {
me.down('field[name=hdstorage]').setDisabled(!value);
me.down('field[name=disksize]').setDisabled(!value);
me.down('field[name=controller]').setDisabled(!value);
me.down('field[name=diskformat]').setDisabled(!value);
}
}
},
hdstoragesel,
{
xtype: 'numberfield',
name: 'disksize',
labelAlign: 'right',
minValue: 1,
maxValue: 128*1024,
value: 32,
fieldLabel: 'Disk size (GB)',
allowBlank: false
},
{
xtype: 'PVE.form.BusTypeSelector',
name: 'controller',
labelAlign: 'right',
fieldLabel: 'Controller',
value: 'ide',
allowBlank: false
},
{
xtype: 'PVE.form.DiskFormatSelector',
name: 'diskformat',
labelAlign: 'right',
fieldLabel: 'Image format',
value: 'raw',
allowBlank: false
},
{
xtype: 'radiofield',
name: 'hdType',
inputValue: 'none',
boxLabel: 'Do not attach a hard disk'
}
],
onGetValues: function(values) {
if (values.hdType === 'none')
return {};
var str = values.hdstorage + ':' + values.disksize +
',format=' + values.diskformat;
var busid = 0;
var key = values.controller + "" + busid;
var res = {};
res[key] = str;
return res;
}
},
{
title: 'CPU',
items: [
{
xtype: 'numberfield',
name: 'sockets',
minValue: 1,
maxValue: 4,
value: 1,
fieldLabel: 'Sockets',
allowBlank: false,
listeners: {
change: function(f, value) {
var sockets = me.down('field[name=sockets]').getValue();
var cores = me.down('field[name=cores]').getValue();
me.down('field[name=totalcores]').setValue(sockets*cores);
}
}
},
{
xtype: 'numberfield',
name: 'cores',
minValue: 1,
maxValue: 32,
value: 1,
fieldLabel: 'Cores',
allowBlank: false,
listeners: {
change: function(f, value) {
var sockets = me.down('field[name=sockets]').getValue();
var cores = me.down('field[name=cores]').getValue();
me.down('field[name=totalcores]').setValue(sockets*cores);
}
}
},
{
xtype: 'displayfield',
fieldLabel: 'Total cores',
name: 'totalcores',
value: 1
}
]
},
{
title: 'Memory',
items: [
{
xtype: 'numberfield',
name: 'memory',
minValue: 32,
maxValue: 128*1024,
value: 512,
step: 32,
fieldLabel: 'Memory (MB)',
allowBlank: false
}
]
},
{
xtype: 'inputpanel',
title: 'Network',
items: [
{
xtype: 'textfield',
name: 'bridge',
value: 'vmbr0',
fieldLabel: 'Bridge',
allowBlank: false
},
{
xtype: 'PVE.form.NetworkCardSelector',
name: 'netcard',
fieldLabel: 'Network card',
value: 'rtl8139',
allowBlank: false
},
{
xtype: 'textfield',
name: 'mac',
fieldLabel: 'MAC address',
allowBlank: true,
emptyText: 'auto'
}
],
onGetValues: function(values) {
var str = values.netcard;
if (values.mac)
str += '=' + values.mac;
str += ',bridge=' + values.bridge;
return { net0: str };
}
},
{
title: 'Confirm',
layout: 'fit',
items: [
{
title: 'Settings',
xtype: 'grid',
store: summarystore,
columns: [
{header: 'Key', width: 150, dataIndex: 'key'},
{header: 'Value', flex: 1, dataIndex: 'value'}
]
}
],
listeners: {
show: function(panel) {
var form = me.down('form').getForm();
var kv = me.getValues();
var data = [];
Ext.Object.each(kv, function(key, value) {
var html = Ext.htmlEncode(Ext.JSON.encode(value));
data.push({ key: key, value: value });
});
summarystore.removeAll();
summarystore.add(data);
summarystore.sort();
}
},
onSubmit: function() {
var kv = me.getValues();
var nodename = kv.nodename;
delete kv.nodename;
me.down('form').setLoading(true, true);
PVE.Utils.API2Request({
url: '/nodes/' + nodename + '/qemu',
method: 'POST',
params: kv,
callback: function() {
me.down('form').setLoading(false);
},
success: function(response){
me.close();
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
}
}
]
});
me.callParent();
}
});

View File

@ -1,114 +0,0 @@
Ext.define('PVE.qemu.HardwareView', {
extend: 'PVE.grid.ObjectGrid',
alias: ['widget.PVE.qemu.HardwareView'],
renderKey: function(key, metaData, record, rowIndex, colIndex, store) {
var me = this;
var rows = me.rows;
var rowdef = rows[key] || {};
if (rowdef.css) {
if (rowdef.css == 'pve-itype-icon-storage') {
if (record.data.value.match(/media=cdrom/)) {
metaData.css = 'pve-itype-icon-cdrom';
return 'CD/DVD';
} else {
metaData.css = rowdef.css;
return 'Hard Disk';
}
} else
metaData.css = rowdef.css;
}
return rowdef.header || key;
},
initComponent : function() {
var me = this;
var i;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var vmid = me.pveSelNode.data.vmid;
if (!vmid)
throw "no VM ID specified";
var rows = {
memory: {
header: 'Memory',
css: 'pve-itype-icon-memory',
renderer: function(value) {
return PVE.Utils.format_size(value*1024*1024);
}
},
sockets: {
header: 'Processors',
css: 'pve-itype-icon-processor',
defaultValue: 1,
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
var cores = (store.snapshot || store.data).get('cores');
return cores ? value * cores.data.value : value;
}
},
keyboard: {
header: 'Keyboard',
css: 'pve-itype-icon-keyboard',
defaultValue: 'default'
},
vga: {
header: 'Display',
css: 'pve-itype-icon-display',
defaultValue: 'default'
},
cores: {
header: 'Cores',
visible: false
}
};
for (i = 0; i < 4; i++) {
rows["ide" + i] = {
css: 'pve-itype-icon-storage',
header: 'Hard Disk (IDE)'
};
}
for (i = 0; i < 16; i++) {
rows["net" + i] = {
css: 'pve-itype-icon-network',
header: 'Network Adapter'
};
}
var run_editor = function() {
console.log("TEST EDIT");
me.rstore.load();
};
Ext.applyIf(me, {
url: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/config",
cwidth1: 150,
tbar: [
{
text: "Edit",
handler: run_editor
}
],
rows: rows,
listeners: {
itemdblclick: function() {
run_editor();
}
}
});
me.callParent();
me.on('show', function() {
me.rstore.load();
});
}
});

View File

@ -1,58 +0,0 @@
Ext.define('PVE.qemu.StatusView', {
extend: 'PVE.grid.ObjectGrid',
alias: ['widget.pveQemuStatusView'],
initComponent : function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var vmid = me.pveSelNode.data.vmid;
if (!vmid)
throw "no VM ID specified";
var render_cpu = function(value, metaData, record, rowIndex, colIndex, store) {
if (!me.getObjectValue('uptime'))
return '-';
var maxcpu = me.getObjectValue('cpus', 1);
if (!(Ext.isNumeric(value) && Ext.isNumeric(maxcpu) && (maxcpu >= 1)))
return '-'
var per = (value * 100) / maxcpu;
return per.toFixed(1) + '% of ' + maxcpu + (maxcpu > 1 ? 'CPUs' : 'CPU');
};
var render_mem = function(value, metaData, record, rowIndex, colIndex, store) {
var maxmem = me.getObjectValue('maxmem', 0);
var per = (value / maxmem)*100;
var text = "<div>Total: " + PVE.Utils.format_size(maxmem) + "</div>" +
"<div>Used: " + PVE.Utils.format_size(value) + "</div>";
return text;
};
var rows = {
name: { header: 'Name', defaultValue: 'no name specified' },
status: { header: 'Status', defaultValue: 'unknown' },
cpu: { header: 'CPU usage', required: true, renderer: render_cpu },
cpus: { visible: false },
mem: { header: 'Memory usage', required: true, renderer: render_mem },
maxmem: { visible: false },
uptime: { header: 'Uptime', required: true, renderer: PVE.Utils.render_uptime }
};
Ext.applyIf(me, {
url: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/status",
cwidth1: 150,
height: 145,
interval: 1000,
rows: rows
});
me.callParent();
}
});

View File

@ -1,203 +0,0 @@
Ext.define('PVE.qemu.Summary', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveQemuSummary',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var vmid = me.pveSelNode.data.vmid;
if (!vmid)
throw "no VM ID specified";
var statusview = Ext.create('PVE.qemu.StatusView', {
title: 'Status',
pveSelNode: me.pveSelNode,
width: 400
})
rstore = statusview.rstore;
var rrdurl = "/api2/png/nodes/" + nodename + "/qemu/" + vmid + "/rrd";
var vm_command = function(cmd) {
me.setLoading(true, true);
PVE.Utils.API2Request({
params: { command: cmd },
url: '/nodes/' + nodename + '/qemu/' + vmid + "/status",
method: 'PUT',
callback: function() {
me.setLoading(false);
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
};
var tbar = Ext.create('Ext.toolbar.Toolbar', {
items: [
{
itemId: 'start',
text: 'Start',
handler: function() {
vm_command('start');
}
},
{
itemId: 'stop',
text: 'Stop',
handler: function() {
var msg = "Do you really want to stop the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command("stop");
});
}
},
{
text: 'Reset',
itemId: 'reset',
handler: function() {
var msg = "Do you really want to reset the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command("reset");
});
}
},
{
itemId: 'shutdown',
text: 'Shutdown',
handler: function() {
var msg = "Do you really want to shutdown the VM?";
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
vm_command('shutdown');
});
}
},
{
itemId: 'remove',
text: 'Remove',
handler: function() {
var msg = 'Are you sure you want to remove VM ' +
vmid + '? This will permanently erase all VM data.';
Ext.Msg.confirm('Confirm', msg, function(btn) {
if (btn !== 'yes')
return;
me.setLoading(true, true);
PVE.Utils.API2Request({
url: '/nodes/' + nodename + '/qemu/' + vmid,
method: 'DELETE',
callback: function() {
me.setLoading(false);
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
});
}
},
{
itemId: 'console',
text: 'Console',
handler: function() {
var url = Ext.urlEncode({
console: 'kvm',
vmid: vmid,
node: nodename
});
var nw = window.open("?" + url, '_blank',
"innerWidth=745,innerheight=427");
nw.focus();
}
}, '->',
{
xtype: 'pveRRDTypeSelector'
}
]
});
me.mon(rstore, 'load', function(s, records, success) {
var statusrec = s.data.get('status');
var status = statusrec ? statusrec.data.value : 'unknown';
tbar.down('#start').setDisabled(status === 'running');
tbar.down('#reset').setDisabled(status !== 'running');
tbar.down('#shutdown').setDisabled(status !== 'running');
tbar.down('#stop').setDisabled(status === 'stopped');
tbar.down('#console').setDisabled(status !== 'running');
tbar.down('#remove').setDisabled(status !== 'stopped');
});
Ext.apply(me, {
tbar: tbar,
layout: {
type: 'table',
columns: 1
},
autoScroll: true,
bodyStyle: 'padding:10px',
defaults: {
style: 'padding-bottom:10px'
},
items: [
{
layout: {
type: 'hbox',
align: 'stretchmax'
},
width: 800,
border: false,
items: [
statusview,
{
title: 'Comments',
style: 'padding-left:10px',
pveSelNode: me.pveSelNode,
rstore: rstore,
html: "test",
width: 400
}
]
},
{
xtype: 'pveRRDView',
title: "CPU usage %",
pveSelNode: me.pveSelNode,
datasource: 'cpu',
rrdurl: rrdurl
},
{
xtype: 'pveRRDView',
title: "Memory usage",
pveSelNode: me.pveSelNode,
datasource: 'mem,maxmem',
rrdurl: rrdurl
},
{
xtype: 'pveRRDView',
title: "Network traffic",
pveSelNode: me.pveSelNode,
datasource: 'netin,netout',
rrdurl: rrdurl
}
]
});
me.on('show', rstore.startUpdate);
me.on('hide', rstore.stopUpdate);
me.on('destroy', rstore.stopUpdate);
me.callParent();
}
});

View File

@ -1,52 +0,0 @@
#!/usr/bin/perl -w
use strict;
use PVE::SafeSyslog;
use ModPerl::Util (); #for CORE::GLOBAL::exit
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();
use Apache2::Access;
use Apache2::Response;
use Apache2::Util;
use Apache2::ServerUtil ();
use Apache2::Connection ();
use Apache2::Log ();
use APR::Table ();
use ModPerl::Registry ();
use Apache2::Const -compile => ':common';
use APR::Const -compile => ':common';
initlog ('proxwww', 'daemon');
use PVE::pvecfg;
use PVE::REST;
use PVE::Cluster;
use PVE::INotify;
use PVE::RPCEnvironment;
sub childinit {
syslog ('info', "Starting new child $$");
PVE::INotify::inotify_init();
PVE::RPCEnvironment->init('pub');
PVE::Config::inotify_init();
}
sub childexit {
syslog ('info', "Finish child $$");
}
my $s = Apache2::ServerUtil->server;
$s->push_handlers(PerlChildInitHandler => \&childinit);
$s->push_handlers(PerlChildExitHandler => \&childexit);
1;

View File

@ -1,40 +0,0 @@
Ext.define('PVE.storage.Browser', {
extend: 'PVE.panel.Config',
alias: 'widget.PVE.storage.Browser',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename)
throw "no node name specified";
var storeid = me.pveSelNode.data.storage;
if (!storeid)
throw "no storage ID specified";
Ext.apply(me, {
title: "Storage '" + storeid + "'" + "' on node '" + nodename + "'",
hstateid: 'storagetab',
items: [
{
title: 'Summary',
//xtype: 'pveStorageSummary',
itemId: 'summary'
},
{
//xtype: 'pveStorageContent',
title: 'Content',
itemId: 'content'
},
{
title: 'Permissions',
itemId: 'permissions',
html: 'Permissions '
}
]
});
me.callParent();
}
});

View File

@ -1,347 +0,0 @@
Ext.define('PVE.tree.ResourceTree', {
extend: 'Ext.tree.TreePanel',
requires: ['Ext.tree.*',
'Ext.state.Manager',
'PVE.Utils',
'PVE.data.ResourceStore'],
alias: ['widget.pveResourceTree'],
statics: {
typeDefaults: {
node: {
iconCls: 'x-tree-node-server',
text: 'Node list'
},
storage: {
iconCls: 'x-tree-node-harddisk',
text: 'Storage list'
},
qemu: {
iconCls: 'x-tree-node-computer',
text: 'Virtual machines'
},
openvz: {
iconCls: 'x-tree-node-computer',
text: 'OpenVZ containers'
}
}
},
// private
nodeSortFn: function(node1, node2) {
var n1 = node1.data;
var n2 = node2.data;
if ((n1.groupbyid && n2.groupbyid) ||
!(n1.groupbyid || n2.groupbyid)) {
var tcmp;
var v1 = n1.type;
var v2 = n2.type;
if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0)
return tcmp;
// numeric compare for VM IDs
if (v1 === 'qemu' || v1 === 'openvz') {
v1 = n1.vmid;
v2 = n2.vmid;
if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0)
return tcmp;
}
return n1.text > n2.text ? 1 : (n1.text < n2.text ? -1 : 0);
} else if (n1.groupbyid) {
return -1;
} else if (n2.groupbyid) {
return 1;
}
},
// private: fast binary search
findInsertIndex: function(node, child, start, end) {
var me = this;
var diff = end - start;
var mid = start + (diff>>1);
if (diff <= 0)
return start;
var res = me.nodeSortFn(child, node.childNodes[mid]);
if (res <= 0)
return me.findInsertIndex(node, child, start, mid);
else
return me.findInsertIndex(node, child, mid + 1, end);
},
// private
addChildSorted: function(node, info) {
var me = this;
var statics = me.statics();
var defaults = statics.typeDefaults[info.type];
if (defaults && defaults.iconCls)
info.iconCls = defaults.iconCls;
if (info.groupbyid) {
info.text = info.groupbyid;
if (info.type === 'type') {
defaults = statics.typeDefaults[info.groupbyid];
if (defaults && defaults.text)
info.text = defaults.text;
}
}
var child = Ext.ModelMgr.create(info, 'PVETree', info.id);
var cs = node.childNodes;
var pos;
if (cs) {
var len = cs.length;
index = me.findInsertIndex(node, child, 0, len);
pos = cs[index];
}
//var expanded = node.isExpanded();
//if (expanded)
//node.collapse();
node.insertBefore(child, pos);
//if (expanded)
//node.expand();
return child;
},
// private
groupChild: function(node, info, groups, level) {
var me = this;
var groupby = groups[level];
var v = info[groupby];
if (v) {
var group = node.findChild('groupbyid', v);
if (!group) {
var groupinfo;
if (info.type === groupby) {
groupinfo = info;
} else {
groupinfo = {
type: groupby,
id : groupby + "/" + v
};
if (groupby !== 'type')
groupinfo[groupby] = v;
}
groupinfo.leaf = false;
groupinfo.groupbyid = v;
group = me.addChildSorted(node, groupinfo);
// fixme: remove when EXTJS has fixed those bugs?!
group.expand(); group.collapse();
}
if (info.type === groupby)
return group;
if (group)
return me.groupChild(group, info, groups, level + 1);
}
return me.addChildSorted(node, info);
},
initComponent : function() {
var me = this;
var rstore = PVE.data.ResourceStore;
var sp = Ext.state.Manager.getProvider();
if (!me.viewFilter)
me.viewFilter = {};
var pdata = {
dataIndex: {},
updateCount: 0
};
var store = Ext.create('Ext.data.TreeStore', {
model: 'PVETree',
root: {
expanded: true,
id: 'root',
text: "Datacenter"
}
});
var stateid = 'rid';
var updateTree = function() {
var tmp;
// fixme: suspend events ?
var rootnode = me.store.getRootNode();
// remember selected node (and all parents)
var sm = me.getSelectionModel();
var lastsel = sm.getLastSelected();
var parents = [];
var p = lastsel;
while(p && (p = p.parentNode))
parents.push(p);
var index = pdata.dataIndex;
var groups = me.viewFilter.groups || [];
var filterfn = me.viewFilter.filterfn;
// remove vanished or changed items
for (var key in index) {
if (!index.hasOwnProperty(key))
continue;
var olditem = index[key];
// getById() use find(), which is slow (ExtJS4 DP5)
//var item = rstore.getById(olditem.data.id);
var item = rstore.data.get(olditem.data.id);
var changed = false;
if (item) {
// test if any grouping attributes changed
for (var i = 0, len = groups.length; i < len; i++) {
var attr = groups[i];
if (item.data[attr] != olditem.data[attr]) {
//console.log("changed " + attr);
changed = true;
break;
}
}
// fixme: also test filterfn()?
}
if (!item || changed) {
//console.log("REM UID: " + key + " ITEM " + olditem.data.id);
delete index[key];
var parentNode = olditem.parentNode;
//var expanded = parentNode.isExpanded();
//if (expanded)
//parentNode.collapse();
parentNode.removeChild(olditem, true);
//if (expanded)
//parentNode.expand();
}
}
// add new items
rstore.each(function(item) {
var olditem = index[item.data.id];
if (olditem)
return;
if (filterfn && !filterfn(item))
return;
//console.log("ADD UID: " + item.data.id);
var info = Ext.apply({ leaf: true }, item.data);
var child = me.groupChild(rootnode, info, groups, 0);
if (child)
index[item.data.id] = child;
});
// select parent node is selection vanished
if (lastsel && !rootnode.findChild('id', lastsel.data.id, true)) {
lastsel = rootnode;
while (p = parents.shift()) {
if (tmp = rootnode.findChild('id', p.data.id, true)) {
lastsel = tmp;
break;
}
}
me.selectById(lastsel.data.id);
}
if (!pdata.updateCount) {
rootnode.collapse();
rootnode.expand();
me.applyState(sp.get(stateid));
}
pdata.updateCount++;
};
var statechange = function(sp, key, value) {
if (key === stateid) {
me.applyState(value);
}
};
sp.on('statechange', statechange);
Ext.apply(me, {
store: store,
//useArrows: true,
//rootVisible: false,
title: 'Resource Tree',
listeners: {
destroy: function() {
rstore.un("load", updateTree)
}
},
setViewFilter: function(view) {
me.viewFilter = view;
me.clearTree();
updateTree();
},
clearTree: function() {
pdata.updateCount = 0;
var rootnode = me.store.getRootNode();
rootnode.collapse();
rootnode.removeAll(true);
pdata.dataIndex = {};
me.getSelectionModel().deselectAll();
},
selectById: function(nodeid) {
var rootnode = me.store.getRootNode();
var sm = me.getSelectionModel();
var node;
if (nodeid === 'root')
node = rootnode;
else
node = rootnode.findChild('id', nodeid, true);
if (node) {
if (!sm.isSelected(node)) {
sm.select(node);
var cn = node;
while ((cn = cn.parentNode)) {
if (!cn.isExpanded())
cn.expand();
}
}
}
},
applyState : function(state) {
var sm = me.getSelectionModel();
if (state && state.value) {
me.selectById(state.value);
} else {
sm.deselectAll();
}
}
});
me.callParent();
var sm = me.getSelectionModel();
sm.on('select', function(sm, n) {
sp.set(stateid, { value: n.data.id});
});
rstore.on("load", updateTree);
rstore.startUpdate();
//rstore.stopUpdate();
}
});

View File

@ -1,116 +0,0 @@
Ext.define('PVE.window.LoginWindow', {
extend: 'Ext.window.Window',
requires: ['PVE.form.RealmComboBox'],
// private
onLogon: function() {
var me = this;
var form = me.getComponent(0).getForm();
if(form.isValid()){
me.el.mask('Please wait...', 'x-mask-loading');
form.submit({
failure: function(f, resp){
me.el.unmask();
Ext.MessageBox.alert('Failure', "Login failed. Please try again", function() {
var uf = form.findField('username');
uf.focus(true);
});
},
success: function(f, resp){
me.el.unmask();
var handler = me.handler || Ext.emptyFn;
handler.call(me, resp.result.data);
me.close();
}
});
}
},
initComponent: function() {
var me = this;
Ext.apply(me, {
width: 400,
height: 160,
modal: true,
border: false,
draggable: true,
closable: false,
resizable: false,
layout: 'fit',
title: 'Proxmox VE Login',
items: [{
xtype: 'form',
frame: true,
url: '/api2/extjs/access/ticket',
fieldDefaults: {
labelWidth: 70,
labelAlign : 'right',
},
defaults: {
anchor: '-5',
allowBlank: false
},
items: [
{
xtype: 'textfield',
fieldLabel: 'User name',
name: 'username',
blankText: "Enter your user name",
listeners: {
render: function(f) {
f.focus(true);
},
specialkey: function(f, e) {
if (e.getKey() === e.ENTER) {
var pf = me.query('textfield[name="password"]')[0];
if (pf.getValue()) {
me.onLogon();
} else {
pf.focus(false);
}
}
}
}
},
{
xtype: 'textfield',
inputType: 'password',
fieldLabel: 'Password',
name: 'password',
blankText:"Enter your password",
listeners: {
specialkey: function(field, e) {
if (e.getKey() === e.ENTER) {
me.onLogon();
}
}
}
},
{
xtype: 'pveRealmComboBox',
name: 'realm'
}
],
buttons: [
{
text: 'Login',
handler: function(){
me.onLogon();
}
}
]
}]
});
me.callParent();
}
});

View File

@ -1,156 +0,0 @@
Ext.define('PVE.window.TaskViewer', {
extend: 'Ext.window.Window',
requires: [
'PVE.Utils'
],
alias: 'widget.pveTaskViewer',
initComponent: function() {
var me = this;
if (!me.upid)
throw "no task specified";
var task = PVE.Utils.parse_task_upid(me.upid);
var rows = {
status: {
header: 'Status',
defaultValue: 'unknown'
},
type: {
header: 'Task type',
required: true
},
user: {
header: 'User name',
required: true
},
node: {
header: 'Node',
required: true
},
pid: {
header: 'Process ID',
required: true
},
starttime: {
header: 'Start time',
required: true,
renderer: PVE.Utils.render_timestamp
},
upid: {
header: 'Unique task ID'
}
};
var store = Ext.create('Ext.data.Store', {
model: 'pve-string-list',
pageSize: 200,
buffered: true,
proxy: {
type: 'pve',
startParam: 'start',
limitParam: 'limit',
url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/log"
}
});
var statstore = Ext.create('PVE.data.ObjectStore', {
url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/status",
interval: 1000,
rows: rows,
});
me.on('destroy', statstore.stopUpdate);
var stop_task = function() {
me.setLoading(true, true);
PVE.Utils.API2Request({
url: "/nodes/" + task.node + "/tasks/" + me.upid,
method: 'DELETE',
callback: function() {
me.setLoading(false);
},
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
};
var stop_btn1 = new Ext.Button({
text: 'Stop',
disabled: true,
handler: stop_task
});
var stop_btn2 = new Ext.Button({
text: 'Stop',
disabled: true,
handler: stop_task
});
var statgrid = Ext.create('PVE.grid.ObjectGrid', {
title: 'Status',
layout: 'fit',
tbar: [ stop_btn1 ],
rstore: statstore,
rows: rows,
border: false
});
me.mon(statstore, 'load', function() {
var status = statgrid.getObjectValue('status');
if (status === 'stopped')
statstore.stopUpdate();
stop_btn1.setDisabled(status !== 'running');
stop_btn2.setDisabled(status !== 'running');
});
statstore.startUpdate();
Ext.applyIf(me, {
title: "Task viewer: " + task.desc,
width: 800,
height: 400,
layout: 'fit',
modal: true,
bodyPadding: 5,
items: [{
xtype: 'tabpanel',
region: 'center',
items: [
{
title: 'Output',
tbar: [ stop_btn2 ],
border: false,
xtype: 'gridpanel',
features: [ {ftype: 'selectable'}],
store: store,
stateful: false,
//tbar: [ 'test' ],
verticalScrollerType: 'paginggridscroller',
loadMask: true,
disableSelection: true,
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
stripeRows: false
},
hideHeaders: true,
columns: [
//{ header: "Line", dataIndex: 'n', width: 50 },
{ header: "Text", dataIndex: 't', flex: 1 }
]
},
statgrid
]
}]
});
me.callParent();
store.guaranteeRange(0, store.pageSize - 1);
}
});

View File

@ -1,277 +0,0 @@
Ext.define('PVE.panel.InputPanel', {
extend: 'Ext.panel.Panel',
requires: [
'PVE.Utils'
],
alias: ['widget.inputpanel'],
getValues: function(dirtyOnly) {
var me = this;
if (Ext.isFunction(me.onGetValues))
dirtyOnly = false;
var values = {};
Ext.Array.each(me.query('[isFormField]'), function(field) {
if (!dirtyOnly || field.isDirty()) {
PVE.Utils.assemble_field_data(values, field.getSubmitData());
}
});
if (Ext.isFunction(me.onGetValues))
return me.onGetValues(values, dirtyOnly);
return values;
},
initComponent: function() {
var me = this;
Ext.applyIf(me, {
});
me.callParent();
}
});
Ext.define('PVE.window.Wizard', {
extend: 'Ext.window.Window',
requires: [
'PVE.Utils'
],
getValues: function(dirtyOnly) {
var me = this;
var values = {};
var form = me.down('form').getForm();
form.getFields().each(function(field) {
if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) {
PVE.Utils.assemble_field_data(values, field.getSubmitData());
}
});
Ext.Array.each(me.query('inputpanel'), function(panel) {
PVE.Utils.assemble_field_data(values, panel.getValues(dirtyOnly));
});
return values;
},
initComponent: function() {
var me = this;
var tabs = me.items || [];
delete me.items;
/*
* Items may have the following functions:
* validator(): per tab custom validation
* onSubmit(): submit handler
* onGetValues(): overwrite getValues results
*/
Ext.Array.each(tabs, function(tab) {
tab.disabled = true;
});
tabs[0].disabled = false;
var check_card = function(card) {
var valid = true;
var fields = card.query('field, fieldcontainer');
Ext.Array.each(fields, function(field) {
if (!field.isValid())
valid = false;
});
if (Ext.isFunction(card.validator))
return card.validator();
return valid;
};
var tbar = Ext.create('Ext.toolbar.Toolbar', {
ui: 'footer',
region: 'south',
margins: '0 5 5 5',
items: [
'->',
{
text: 'Back',
disabled: true,
itemId: 'back',
minWidth: 60,
handler: function() {
var tp = me.down('#wizcontent');
var atab = tp.getActiveTab();
var prev = tp.items.indexOf(atab) - 1;
if (prev < 0) {
return;
}
var ntab = tp.items.getAt(prev);
if (ntab) {
tp.setActiveTab(ntab);
}
}
},
{
text: 'Next',
disabled: true,
itemId: 'next',
minWidth: 60,
handler: function() {
var form = me.down('form').getForm();
var tp = me.down('#wizcontent');
var atab = tp.getActiveTab();
if (!check_card(atab))
return;
var next = tp.items.indexOf(atab) + 1;
var ntab = tp.items.getAt(next);
if (ntab) {
ntab.enable();
tp.setActiveTab(ntab);
}
}
},
{
text: 'Finish',
minWidth: 60,
hidden: true,
itemId: 'submit',
handler: function() {
var tp = me.down('#wizcontent');
var atab = tp.getActiveTab();
atab.onSubmit();
}
}
]
});
var display_header = function(newcard) {
var html = '<h1>' + newcard.title + '</h1>';
if (newcard.descr)
html += newcard.descr;
me.down('#header').update(html);
};
var disable_at = function(card) {
var tp = me.down('#wizcontent');
var idx = tp.items.indexOf(card);
for(;idx < tp.items.getCount();idx++) {
var nc = tp.items.getAt(idx);
if (nc)
nc.disable();
}
};
var tabchange = function(tp, newcard, oldcard) {
if (newcard.onSubmit) {
me.down('#next').setVisible(false);
me.down('#submit').setVisible(true);
} else {
me.down('#next').setVisible(true);
me.down('#submit').setVisible(false);
}
var valid = check_card(newcard);
me.down('#next').setDisabled(!valid);
me.down('#submit').setDisabled(!valid);
me.down('#back').setDisabled(tp.items.indexOf(newcard) == 0);
if (oldcard && !check_card(oldcard)) {
disable_at(oldcard);
}
var next = tp.items.indexOf(newcard) + 1;
var ntab = tp.items.getAt(next);
if (valid && ntab && !newcard.onSubmit) {
ntab.enable();
}
};
Ext.applyIf(me, {
width: 600,
height: 400,
modal: true,
border: false,
draggable: true,
closable: true,
resizable: false,
layout: 'border',
title: 'Proxmox VE Wizard',
items: [
{
// disabled for now - not really needed
hidden: true,
region: 'north',
itemId: 'header',
layout: 'fit',
margins: '5 5 0 5',
bodyPadding: 10,
html: ''
},
{
xtype: 'form',
region: 'center',
layout: 'fit',
border: false,
margins: '5 5 0 5',
fieldDefaults: {
labelWidth: 100,
width: 300
},
items: {
itemId: 'wizcontent',
xtype: 'tabpanel',
activeItem: 0,
bodyPadding: 10,
defaults: {
layout: 'vbox'
},
listeners: {
afterrender: function(tp) {
var atab = this.getActiveTab();
tabchange(tp, atab);
},
tabchange: function(tp, newcard, oldcard) {
display_header(newcard);
tabchange(tp, newcard, oldcard);
}
},
items: tabs
}
},
tbar
]
});
me.callParent();
display_header(tabs[0]);
Ext.Array.each(me.query('field'), function(field) {
field.on('validitychange', function(f) {
var tp = me.down('#wizcontent');
var atab = tp.getActiveTab();
var valid = check_card(atab);
me.down('#next').setDisabled(!valid);
me.down('#submit').setDisabled(!valid);
var next = tp.items.indexOf(atab) + 1;
var ntab = tp.items.getAt(next);
if (!valid) {
disable_at(ntab);
} else if (ntab && !atab.onSubmit) {
ntab.enable();
}
});
});
}
});

View File

@ -1,376 +0,0 @@
Ext.ns("PVE");
PVE.UserView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var store = new Ext.data.JsonStore({
url: "/api2/json/access/users",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [
'userid', 'firstname', 'lastname' , 'email', 'comment',
{ type: 'boolean', name: 'enabled' },
{ type: 'date', dateFormat: 'timestamp', name: 'expire' },
],
idProperty: 'userid',
sortInfo: { field: 'userid', order: 'DESC' }
});
var render_expire = function(date) {
if (!date)
return 'never';
return date.format("Y-m-d");
};
var render_full_name = function(firstname, metaData, record) {
var first = firstname || '';
var last = record.data.lastname || '';
return first + " " + last;
};
var render_username = function(userid) {
return userid.match(/^([^@]+)/)[1];
};
var render_realm = function(userid) {
return userid.match(/@([^@]+)$/)[1];
};
Ext.apply(self, {
store: store,
autoExpandColumn: 'comment',
stateful: false,
columns: [
{
header: 'User name',
width: 200,
sortable: true,
renderer: render_username,
dataIndex: 'userid'
},
{
header: 'Realm',
width: 100,
sortable: true,
renderer: render_realm,
dataIndex: 'userid'
},
{
header: 'Enabled',
width: 50,
sortable: true,
dataIndex: 'enabled'
},
{
header: 'Expire',
width: 80,
sortable: true,
renderer: render_expire,
dataIndex: 'expire'
},
{
header: 'Name',
width: 150,
sortable: true,
renderer: render_full_name,
dataIndex: 'firstname'
},
{
id: 'comment',
header: 'Comment',
sortable: false,
dataIndex: 'comment'
}
],
listeners: {
show: function() {
store.load();
}
}
});
PVE.UserView.superclass.initComponent.call(self);
}
});
Ext.reg('pveUserView', PVE.UserView);
PVE.GroupView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var store = new Ext.data.JsonStore({
url: "/api2/json/access/groups",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [ 'groupid', 'comment' ],
idProperty: 'groupid',
sortInfo: { field: 'groupid', order: 'DESC' }
});
Ext.apply(self, {
store: store,
autoExpandColumn: 'comment',
stateful: false,
columns: [
{
header: 'Group name',
width: 200,
sortable: true,
dataIndex: 'groupid'
},
{
id: 'comment',
header: 'Comment',
sortable: false,
dataIndex: 'comment'
}
],
listeners: {
show: function() {
store.load();
}
}
});
PVE.GroupView.superclass.initComponent.call(self);
}
});
Ext.reg('pveGroupView', PVE.GroupView);
PVE.RoleView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var store = new Ext.data.JsonStore({
url: "/api2/json/access/roles",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [ 'roleid', 'privs' ],
idProperty: 'roleid',
sortInfo: { field: 'roleid', order: 'DESC' }
});
var render_privs = function(value) {
if (!value)
return '-';
// allow word wrap
return '<div style="white-space:normal;">'
+ value.replace(/\,/g, ' ') + "</div>";
};
Ext.apply(self, {
store: store,
autoExpandColumn: 'privs',
stateful: false,
columns: [
{
header: 'Role name',
width: 150,
sortable: true,
dataIndex: 'roleid'
},
{
id: 'privs',
header: 'Privileges',
sortable: false,
renderer: render_privs,
dataIndex: 'privs'
}
],
listeners: {
show: function() {
store.load();
}
}
});
PVE.RoleView.superclass.initComponent.call(self);
}
});
Ext.reg('pveRoleView', PVE.RoleView);
PVE.ACLView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var store = new Ext.data.JsonStore({
url: "/api2/json/access/acl",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [ 'path', 'type', 'ugid', 'roleid',
{ name: 'propagate', type: 'boolean'} ],
sortInfo: { field: 'path', order: 'DESC' }
});
var render_ugid = function(ugid, metaData, record) {
if (record.data.type == 'group')
return '@' + ugid;
return ugid;
};
Ext.apply(self, {
store: store,
stateful: false,
columns: [
{
header: 'Path',
width: 200,
sortable: true,
dataIndex: 'path'
},
{
header: 'User/Group',
width: 200,
sortable: true,
renderer: render_ugid,
dataIndex: 'ugid'
},
{
header: 'Role',
width: 150,
sortable: true,
dataIndex: 'roleid'
},
{
header: 'Propagate',
width: 80,
sortable: true,
dataIndex: 'propagate'
}
],
listeners: {
show: function() {
store.load();
}
}
});
PVE.ACLView.superclass.initComponent.call(self);
}
});
Ext.reg('pveACLView', PVE.ACLView);
PVE.AuthView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var store = new Ext.data.JsonStore({
url: "/api2/json/access/domains",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [ 'realm', 'type', 'comment' ],
idProperty: 'realm',
sortInfo: { field: 'realm', order: 'DESC' }
});
Ext.apply(self, {
store: store,
autoExpandColumn: 'comment',
stateful: false,
columns: [
{
header: 'Realm',
width: 100,
sortable: true,
dataIndex: 'realm'
},
{
header: 'Type',
width: 100,
sortable: true,
dataIndex: 'type'
},
{
id: 'comment',
header: 'Comment',
sortable: false,
dataIndex: 'comment'
}
],
listeners: {
show: function() {
store.load();
}
}
});
PVE.AuthView.superclass.initComponent.call(self);
}
});
Ext.reg('pveAuthView', PVE.AuthView);
PVE.ClusterConfig = Ext.extend(PVE.ConfigPanel, {
initComponent : function() {
var self = this;
var clusterid = self.clusterid;
if (!clusterid)
throw "no cluster ID specified";
Ext.apply(self, {
title: "Cluster '" + clusterid + "'",
layout: 'fit',
border: false,
showSearch: true,
items: [
{
title: 'Summary',
id: 'summary',
html: 'summary ' + clusterid
},
{
title: 'Storage',
id: 'storage',
html: 'storage ' + clusterid
},
{
xtype: 'pveUserView',
title: 'Users',
id: 'users'
},
{
xtype: 'pveGroupView',
title: 'Groups',
id: 'groups'
},
{
xtype: 'pveACLView',
title: 'Permissions',
id: 'permissions',
},
{
xtype: 'pveRoleView',
title: 'Roles',
id: 'roles'
},
{
xtype: 'pveAuthView',
title: 'Authentication',
id: 'domains'
},
]
});
PVE.ClusterConfig.superclass.initComponent.call(self);
}
});
Ext.reg('pveClusterConfig', PVE.ClusterConfig);

View File

@ -1,56 +0,0 @@
Ext.ns("PVE");
PVE.ConfigPanel = Ext.extend(Ext.Panel, {
initComponent : function() {
var self = this;
var pveselnode = self.pveSelNode;
if (!self.xtype)
throw "no xtype specified";
var items = self.items || [];
self.items = null;
if (PVE.ConfigPanel.activeTab[self.xtype] === undefined) {
PVE.ConfigPanel.activeTab[self.xtype] = 0;
}
if (self.showSearch) {
items.unshift({
pveSelNode: pveselnode,
id: 'search',
layout: 'fit',
xtype: 'pveSearch'
});
} else {
if (PVE.ConfigPanel.activeTab[self.xtype] === 'search') {
PVE.ConfigPanel.activeTab[self.xtype] = 0;
}
}
var tabs = new Ext.TabPanel({
activeTab: PVE.ConfigPanel.activeTab[self.xtype],
border: false,
items: items,
listeners: {
tabchange: function(tab, item) {
var id = item.getId();
if (id)
PVE.ConfigPanel.activeTab[self.xtype] = id;
}
}
});
self.items = tabs;
PVE.ConfigPanel.superclass.initComponent.call(self);
}
});
PVE.ConfigPanel.activeTab = {};
Ext.reg('pveConfigPanel', PVE.ConfigPanel);

View File

@ -1,63 +0,0 @@
Ext.ns("PVE");
PVE.KVMConfig = Ext.extend(PVE.ConfigPanel, {
initComponent : function() {
var self = this;
var vmid = self.confdata.id;
var node = self.confdata.node || 'localhost';
if (!vmid)
throw "no vmid specified";
Ext.apply(self, {
title: "Virtual machine 'KVM " + vmid + " on node " + node + "'",
layout: 'fit',
border: false,
items: [
{
title: 'Summary',
id: 'summary',
tbar: [
{ text: 'Start'},
{ text: 'Stop'},
{ text: 'Reset'},
{ text: 'Shutdown'},
{ text: 'Remove'}
],
html: 'summary ' + vmid
},
{
title: 'Hardware',
id: 'hardware',
html: 'hardware ' + vmid
},
{
title: 'Options',
id: 'options',
html: 'options ' + vmid
},
{
xtype: 'pveConsole',
title: 'Console',
id: 'console',
vmid: vmid,
node: node,
border: false
},
{
title: 'Permissions',
id: 'permissions',
html: 'permissions ' + vmid
}
]
});
PVE.KVMConfig.superclass.initComponent.call(self);
}
});
Ext.reg('pveKVMConfig', PVE.KVMConfig);

View File

@ -1,53 +0,0 @@
include $(top_builddir)/common.mk
JSSRC= \
../ext/extjs/examples/ux/MultiSelect.js \
../ext/extjs/examples/ux/BufferView.js \
../ext/extjs/examples/ux/fileuploadfield/FileUploadField.js \
PVEUtils.js \
util/base64.js \
data/ObjectReader.js \
data/ObjectStore.js \
data/UpdateStore.js \
data/SearchStore.js \
grid/ObjectView.js \
PVECache.js \
StatusPanel.js \
Workspace.js \
window/ModalDialog.js \
window/LoginWindow.js \
form/StdForm.js \
form/ModifyDirStorage.js \
PVEFilter.js \
ResourceTree.js \
ConfigPanel.js \
PVEConsole.js \
KVMConfig.js \
NodeConfig.js \
StorageBrowser.js \
ClusterConfig.js \
PVESearch.js
pvemanagerlib.js: ${JSSRC}
cat ${JSSRC} >$@
pvelib_DATA = pvemanagerlib.js
pvelibdir = ${WWW_EXTDIR}
privatedir = ${WWW_BASEDIR}
private_SCRIPTS = \
startup.pl
managerdir = ${WWW_ROOTDIR}
manager_SCRIPTS = \
index.pl
install-data-hook:
chown -R www-data:www-data ${DESTDIR}/${privatedir}
chown -R www-data:www-data ${DESTDIR}/${managerdir}
chown -R www-data:www-data ${DESTDIR}/${pvelibdir}
clean-local:
-rm -rf *~ store/*~ pvemanagerlib.js

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
Ext.ns("PVE");
PVE.Cache = function() {
var defaults = {};
var pvecache = {
startUpdate: function() {
Ext.each(this.storelist, function(store) {
store.startUpdate();
});
},
// fixme: use a single store instead of three
// URl: /api2/json/cluster/index
nodestore: function(){
var fields = PVE.Utils.get_field_defaults(['name', 'storage', 'cpu', 'maxcpu',
'mem', 'maxmem', 'uptime']);
var store = new PVE.data.UpdateStore({
itype: 'node',
idProperty: 'name',
autoDestroy: false,
url: '/api2/json/nodes',
fields: fields
});
return store;
}(),
vmstore: function(){
var fields = PVE.Utils.get_field_defaults(['id', 'name', 'node', 'storage', 'cpu', 'maxcpu',
'mem', 'maxmem', 'disk', 'maxdisk', 'uptime']);
var store = new PVE.data.UpdateStore({
itype: 'vm',
idProperty: 'id',
autoDestroy: false,
url: '/api2/json/cluster/vms',
fields: fields
});
return store;
}(),
ststore: function(){
var fields = PVE.Utils.get_field_defaults(['name', 'storage', 'node', 'shared', 'disk', 'maxdisk']);
var store = new PVE.data.UpdateStore({
itype: 'storage',
idProperty: 'name',
autoDestroy: false,
url: '/api2/json/cluster/storage',
fields: fields
});
return store;
}(),
dummy: "ignore me"
};
pvecache.storelist = [
pvecache.nodestore,
pvecache.vmstore,
pvecache.ststore
];
pvecache.searchstore = new PVE.data.SearchStore({ storelist: pvecache.storelist });
return pvecache;
}();

View File

@ -1,325 +0,0 @@
Ext.ns("PVE");
PVE_vnc_console_event = function(appletid, action, err) {
//console.log("TESTINIT param1 " + appletid + " action " + action);
var el = Ext.get(appletid);
if (!el)
return;
if (action === "close") {
// el.remove();
} else if (action === "error") {
// console.log("TESTERROR: " + err);
// var compid = appletid.replace("-vncapp", "");
// var comp = Ext.getCmp(compid);
}
//Ext.get('mytestid').remove();
};
PVE.VNCConsole = Ext.extend(Ext.Panel, {
initComponent : function() {
var self = this;
var myid = self.id + "-vncapp";
self.appletID = myid;
//console.log("consoleid " + self.id);
var resize_window = function() {
//console.log("resize");
var applet = Ext.getDom(myid);
//console.log("resize " + myid + " " + applet);
// try again when dom element is available
if (!(applet && Ext.isFunction(applet.getPreferredSize)))
return resize_window.defer(1000, this);
var tbh = self.tbar.getHeight();
var ps = applet.getPreferredSize();
var aw = ps.width;
var ah = ps.height;
if (aw < 320) aw = 320;
if (ah < 200) ah = 200;
var oh;
var ow;
//console.log("size0 " + aw + " " + ah + " tbh " + tbh);
if (this.innerHeight) {
oh = this.innerHeight;
ow = this.innerWidth;
} else if (document.documentElement &&
document.documentElement.clientHeight) {
oh = document.documentElement.clientHeight;
ow = document.documentElement.clientWidth;
} else if (document.body) {
oh = document.body.clientHeight;
ow = document.body.clientWidth;
} else {
throw "can't get window size";
}
Ext.fly(applet).setSize(aw, ah + tbh);
var offsetw = aw - ow;
var offseth = ah + tbh - oh;
if (offsetw !== 0 || offseth !== 0) {
//console.log("try resize by " + offsetw + " " + offseth);
try { this.resizeBy(offsetw, offseth); } catch (e) {}
}
resize_window.defer(1000, this);
};
var box = new Ext.BoxComponent({
border: false,
html: ""
});
var resize_box = function() {
var applet = Ext.getDom(myid);
// try again when dom element is available
if (!(applet && Ext.isFunction(applet.getPreferredSize)))
return resize_box.defer(1000, this);
var ps = applet.getPreferredSize();
Ext.fly(applet).setSize(ps.width, ps.height);
resize_box.defer(1000, this);
};
var start_vnc_viewer = function(param) {
var cert = param.cert;
cert = cert.replace(/\n/g, "|");
box.update({
id: myid,
border: false,
tag: 'applet',
code: 'com.tigervnc.vncviewer.VncViewer',
archive: '/vncterm/VncViewer.jar',
// NOTE: set size to '100%' - else resize does not work
width: "100%",
height: "100%",
cn: [
{tag: 'param', name: 'id', value: myid},
{tag: 'param', name: 'PORT', value: param.port},
{tag: 'param', name: 'PASSWORD', value: param.ticket},
{tag: 'param', name: 'USERNAME', value: param.user},
{tag: 'param', name: 'Show Controls', value: 'No'},
{tag: 'param', name: 'Offer Relogin', value: 'No'},
{tag: 'param', name: 'PVECert', value: cert}
]
});
if (self.toplevel) {
resize_window.defer(1000, window);
} else {
resize_box.defer(1000, self);
}
};
self.reloadApplet = function() {
Ext.Ajax.request({
url: self.url,
params: self.params,
method: 'POST',
failure: function(response, opts) {
box.update("Error " + response.status + ": " + response.statusText);
},
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
start_vnc_viewer(obj.data);
}
});
};
self.on("show", function() { self.reloadApplet();});
self.on("hide", function() { box.update(""); });
Ext.apply(self, {
layout: 'fit',
border: false,
autoScroll: self.toplevel ? false : true,
items: box
});
PVE.VNCConsole.superclass.initComponent.call(self);
}
});
PVE.Console = Ext.extend(PVE.VNCConsole, {
initComponent : function() {
var self = this;
var vmid = self.vmid;
var node = self.node;
if (!vmid)
throw "no vmid specified";
if (!node)
throw "no node specified";
// Hint: we cant display html over the applet (applet z-index bug)
// So we need to use aller()/confirm() instead of Ext.Msg
var vm_command = function(cmd, reload_applet) {
Ext.Ajax.request({
url: "/api2/json/nodes/" + node + "/qemu/" + vmid + "/status",
params: { command: cmd },
method: 'PUT',
failure: function(response, opts) {
alert("Command '" + cmd + "' failed" +
"- error " + response.status + ": "
+ response.statusText);
},
success: function() {
if (reload_applet)
self.reloadApplet.defer(1000, self);
}
});
};
var tbar = [
{
text: 'Start',
handler: function() {
vm_command("start", 1);
}
}, '-',
{
text: 'Stop',
handler: function() {
if (confirm("Do you really want to stop the VM?"))
vm_command("stop");
}
}, '-',
{
text: 'Reset',
handler: function() {
if (confirm("Do you really want to reset the VM?"))
vm_command("reset");
}
}, '-',
{
text: 'Shutdown',
handler: function() {
// normally, the OS ask the user
//if (confirm("Do you really want to shut down the VM?"))
vm_command("shutdown");
}
}, '-',
{
text: 'Suspend',
handler: function() {
if (confirm("Do you really want to suspend the VM?"))
vm_command("suspend");
}
}, '-',
{
text: 'Resume',
handler: function() {
vm_command("resume");
}
},
'->',
{
text: 'Refresh',
handler: function() {
var applet = Ext.getDom(self.appletID);
applet.sendRefreshRequest();
}
}, '-',
{
text: 'Reload',
handler: function () { self.reloadApplet(); }
}, '-',
{
text: 'New Window',
handler: function() {
var url = Ext.urlEncode({
console: 'kvm',
vmid: vmid,
node: node
});
var nw = window.open("?" + url, '_blank',
"innerWidth=745,innerheight=427");
nw.focus();
}
}
];
Ext.apply(self, {
tbar: tbar,
url: "/api2/json/nodes/" + node + "/qemu/" + vmid + "/vncproxy",
method: 'POST'
});
PVE.Console.superclass.initComponent.call(self);
}
});
Ext.reg('pveConsole', PVE.Console);
PVE.newShellWindow = function(nodename) {
var url = Ext.urlEncode({
console: 'shell',
node: nodename
});
var nw = window.open("?" + url, '_blank', "innerWidth=745,innerheight=427");
nw.focus();
};
PVE.Shell = Ext.extend(PVE.VNCConsole, {
initComponent : function() {
var self = this;
var node = self.node;
if (!node)
throw "no node specified";
var tbar = [
'->',
{
text: 'Refresh',
handler: function() {
var applet = Ext.getDom(self.appletID);
applet.sendRefreshRequest();
}
}, '-',
{
text: 'Reload',
handler: function () { self.reloadApplet(); }
}, '-',
{
text: 'New Window',
handler: function() {
PVE.newShellWindow(node);
}
}
];
Ext.apply(self, {
tbar: tbar,
url: "/api2/json/nodes/" + node + "/vncshell"
});
PVE.Shell.superclass.initComponent.call(self);
}
});
Ext.reg('pveShell', PVE.Shell);

View File

@ -1,325 +0,0 @@
Ext.namespace('PVE');
PVE.FilterGrid = Ext.extend(Ext.grid.EditorGridPanel, {
constructor : function(config) {
config = config || {};
var store = new Ext.data.ArrayStore({
// store configs
autoDestroy: true,
idIndex: 0,
fields: [
{name: 'attrib', type: 'text'},
{name: 'cond', type: 'text'},
{name: 'value', type: 'text'}
]
//sortInfo: {field:'attrib', direction:'ASC'}
});
config.store = store;
config.autoExpandColumn = 2;
var comboRenderer = function(combo){
return function(value){
var record = combo.findRecord(combo.valueField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
var fields = PVE.Utils.getFields();
var attrib_list = [];
for (field in fields) {
var info = fields[field];
attrib_list.push([field, info.header]);
}
var attrib_combo = new Ext.form.ComboBox({
allowBlank: false,
store: attrib_list,
forceSelection: true,
triggerAction: 'all'
});
var cond_list = [
[ 'contains', 'Contains' ],
[ '==', 'is equal' ],
[ '!=', 'is not equal' ]
];
var cond_combo = new Ext.form.ComboBox({
allowBlank: false,
store: cond_list,
forceSelection: true,
triggerAction: 'all'
});
var cm = new Ext.grid.ColumnModel({
// specify any defaults for each column
defaults: {
sortable: true // columns are not sortable by default
},
columns: [
{
header: 'Attribute',
dataIndex: 'attrib',
width: 220,
renderer: comboRenderer(attrib_combo),
editor: attrib_combo
},
{
header: 'Condition',
dataIndex: 'cond',
width: 100,
renderer: comboRenderer(cond_combo),
editor: cond_combo
},
{
header: 'Value',
dataIndex: 'value',
//width: 220,
editor: new Ext.form.TextField({
allowBlank: false
})
}
]
});
Ext.apply(config, {
cm: cm,
sm: new Ext.grid.RowSelectionModel({
singleSelect:true
}),
view: new Ext.grid.GridView({
markDirty: false
}),
clicksToEdit: 1
});
PVE.FilterGrid.superclass.constructor.call(this, config);
}
});
PVE.Filter = Ext.extend(Ext.Window, {
constructor : function(config) {
var win = this;
var viewinfo = PVE.Utils.default_views[config.loadview || PVE.Utils.default_view];
var grid = new PVE.FilterGrid({ border: false });
var fields = PVE.Utils.getFields();
var combo_list = [];
var checkbox_list = [];
for (field in fields) {
var info = fields[field];
combo_list.push([field, info.header]);
var cb = {
boxLabel: info.header,
name: field
};
if (viewinfo.fields[field])
cb.checked = true;
checkbox_list.push(new Ext.form.Checkbox(cb));
}
combo_list.unshift(['-', "Remove this group"]);
var groupcbs = [];
var create_groupby_cb = function(config) {
var cb = Ext.apply (config || {}, {
store: combo_list,
triggerAction: 'all',
width: 100,
listeners: {
select: function(combo, rec) {
var value = rec.get(combo.valueField);
if (value == '-') {
for (var i = 0, len = groupcbs.length; i < len; i++) {
if (groupcbs[i] == combo) {
groupcbs.splice(i, 1);
break;
}
}
combo.destroy();
}
for (var i = 0, len = groupcbs.length; i < len; i++) {
var cb = groupcbs[i];
console.log("TEST " + i + " V = " + cb.getValue());
}
}
}
});
return new Ext.form.ComboBox(cb);
};
var viewlist = [];
for (var viewname in PVE.Utils.default_views) {
var btn = {
text: PVE.Utils.default_views[viewname].text,
itemId: viewname,
listeners: {
click: function(btn) {
console.log("load view " + btn.itemId);
}
}
};
viewlist.push(btn);
};
var tbar = new Ext.Toolbar({
items: [
{
text: 'Load',
menu: {
items: viewlist
}
},
'-',
{
text: 'Group by:',
listeners: {
click: function() {
if (groupcbs.length >= 3)
return;
for (var i = 0, len = groupcbs.length; i < len; i++) {
var cb = groupcbs[i];
if (!cb.getValue())
return;
}
var tbfill = tbar.findById('tbinsertpos');
var pos = tbar.items.indexOf(tbfill);
var cb = create_groupby_cb();
groupcbs.push(cb);
tbar.insertButton(pos, cb);
tbar.doLayout();
}
}
},
{
id: 'tbinsertpos',
xtype: 'tbfill'
},
{
text: 'Add Filter',
handler: function() {
// access the Record constructor through the grid's store
var store = grid.getStore();
var rec = store.recordType;
var p = new rec({ attrib: "Type" , cond: '==' });
grid.stopEditing();
store.insert(0, p);
grid.startEditing(0, 0);
}
},
'-',
{
text: 'Delete Filter',
handler: function() {
var store = grid.getStore();
grid.stopEditing();
var s = grid.getSelectionModel().getSelections();
for(var i = 0, r; r = s[i]; i++){
store.remove(r);
}
}
},
'-',
{
text: 'Show fields',
menu: {
xtype: 'menu',
plain: true,
items: {
xtype: 'checkboxgroup',
columns: 1,
items: checkbox_list
}
}
}
]
});
Ext.each(viewinfo.groups, function(group) {
var tbfill = tbar.findById('tbinsertpos');
var pos = tbar.items.indexOf(tbfill);
var cb = create_groupby_cb({ value: group});
groupcbs.push(cb);
tbar.insertButton(pos, cb);
});
var apply_settings = function() {
var groups = []
Ext.each(groupcbs, function(cb) {
var v = cb.getValue();
if (!v || v === '-')
return false;
groups.push(v);
});
var fields = {};
Ext.each(checkbox_list, function(cb) {
if (cb.checked)
fields[cb.name] = true;
});
win.fireEvent('changeview', 'custom', {
groups: groups,
fields: fields
});
};
Ext.apply(win, {
id: 'pvefilterwindow',
autoDestroy: true,
title: "Filter",
border: false,
width: 600,
height: 300,
layout: 'fit',
tbar: tbar,
stateful: false,
items: [
grid
],
buttons: [
{
text: 'Apply',
handler: apply_settings
},
{
text: 'OK',
handler: function() {
apply_settings();
win.close();
}
},
{
text: 'Cancel',
handler: function() {
win.close() }
}
]
});
PVE.Filter.superclass.constructor.call(this, config);
win.addEvents('changeview');
}
});
Ext.reg('pvefilter', PVE.Filter);

View File

@ -1,85 +0,0 @@
Ext.ns("PVE");
PVE.Search = Ext.extend(Ext.grid.GridPanel, {
initComponent : function() {
var n = this.pveSelNode;
var tree = n.getOwnerTree();
var viewname = tree.viewname;
//console.log("VIEW " + viewname);
var groupfilter = [];
while(n) {
//console.log("SELECT1 " + n.id + " ATTR " + n.attributes.itype + " = " + n.attributes.groupbyid);
if (n.attributes.groupbyid && n.attributes.itype)
groupfilter.unshift({ field: n.attributes.itype, value: n.attributes.groupbyid});
n = n.parentNode;
}
var store = PVE.Cache.searchstore;
store.setGroupFilter(viewname, groupfilter);
var textfilter = store.getTextFilter();
var coldef = PVE.Utils.get_column_defaults(viewname);
Ext.apply(this, {
title: 'Search',
store: PVE.Cache.searchstore,
border: false,
tbar: [
{
text: "Create VM"
}, '-',
{
text: "Create Container"
}, '-',
{
text: "Add Storage"
},
'->', 'Search:', ' ',
{
xtype: 'textfield',
width: 200,
value: textfilter,
enableKeyEvents: true,
listeners: {
keyup: function(field, e) {
var v = field.getValue();
PVE.Cache.searchstore.setTextFilter.defer(100, PVE.Cache.searchstore, [v]);
}
}
}
],
//trackMouseOver: false,
colModel: new Ext.grid.ColumnModel({
defaults: {
width: 200,
sortable: true
},
columns: coldef
}),
view: new Ext.ux.grid.BufferView({
//view: new Ext.grid.GridView({
rowHeight: 36,
// forceFit: true,
// render rows as they come into viewable area.
scrollDelay: false
}),
stateful: false,
stateId: 'pveseachgrid'
});
PVE.Search.superclass.initComponent.call(this);
}
});
Ext.reg('pveSearch', PVE.Search);

View File

@ -1,455 +0,0 @@
// avoid errors when running without development tools
if (typeof console == "undefined") {
var console = {
dir: function() {},
log: function() {}
};
}
Ext.ns("PVE");
Ext.Ajax.defaultHeaders = {
'Accept': 'application/json'
};
Ext.Ajax.on('beforerequest', function(conn, options) {
if (PVECSRFPreventionToken) {
if (!options.headers)
options.headers = {};
options.headers['CSRFPreventionToken'] = PVECSRFPreventionToken;
}
});
// do not send '_dc' parameter
Ext.Ajax.disableCaching = false;
Ext.Ajax.on('requestexception', function(conn, response, options) {
if (response.status == 401) {
PVE.Workspace.showLogin();
}
});
// custom Vtype for vtype:'IPAddress'
Ext.apply(Ext.form.VTypes, {
IPAddress: function(v) {
return /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(v);
},
IPAddressText: 'Must be a numeric IP address',
IPAddressMask: /[\d\.]/i
});
PVE.Utils = function() {
var log_severity_hash = {
0: "panic",
1: "alert",
2: "critical",
3: "error",
4: "warning",
5: "notice",
6: "info",
7: "debug"
};
var utils = {
authOK: function() {
return Ext.util.Cookies.get('PVEAuthCookie');
},
authClear: function() {
Ext.util.Cookies.clear("PVEAuthCookie");
},
format_size: function(size) {
var kb = size / 1024;
if (kb < 1024)
return kb.toFixed(0) + "KB";
var mb = size / (1024*1024);
if (mb < 1024)
return mb.toFixed(0) + "MB";
var gb = mb / 1024;
if (gb < 1024)
return gb.toFixed(2) + "GB";
var tb = gb / 1024;
return tb.toFixed(2) + "TB";
},
format_html_bar: function(per, text) {
return "<div class='pve-bar-wrap'>" + text + "<div class='pve-bar-border'>" +
"<div class='pve-bar-inner' style='width:" + per + "%;'></div>" +
"</div></div>";
},
format_cpu_bar: function(per1, per2, text) {
return "<div class='pve-bar-border'>" +
"<div class='pve-bar-inner' style='width:" + per1 + "%;'></div>" +
"<div class='pve-bar-inner2' style='width:" + per2 + "%;'></div>" +
"<div class='pve-bar-text'>" + text + "</div>" +
"</div>";
},
format_large_bar: function(per, text) {
if (!text)
text = per.toFixed(1) + "%";
return "<div class='pve-largebar-border'>" +
"<div class='pve-largebar-inner' style='width:" + per + "%;'></div>" +
"<div class='pve-largebar-text'>" + text + "</div>" +
"</div>";
},
format_duration_long: function(ut) {
var days = Math.floor(ut / 86400);
ut -= days*86400;
var hours = Math.floor(ut / 3600);
ut -= hours*3600;
var mins = Math.floor(ut / 60);
ut -= mins*60;
hours = "00" + hours;
hours = hours.substr(hours.length - 2);
mins = "00" + mins;
mins = mins.substr(mins.length - 2);
ut = "00" + ut;
ut = ut.substr(ut.length - 2);
if (days) {
var ds = days > 1 ? 'days' : 'day';
return days + ' ' + ds + ' ' +
hours + ':' + mins + ':' + ut;
} else {
return hours + ':' + mins + ':' + ut;
}
},
format_duration_short: function(ut) {
if (ut < 60)
return ut + 's';
if (ut < 3600) {
var mins = ut / 60;
return mins.toFixed(0) + 'm';
}
if (ut < 86400) {
var hours = ut / 3600;
return hours.toFixed(0) + 'h';
}
var days = ut / 86400;
return days.toFixed(0) + 'd';
},
format_storage_type: function(value) {
var desc = {
dir: 'Directory',
nfs: 'NFS',
lvm: 'LVM',
iscsi: 'iSCSI'
};
return desc[value] || 'unknown';
},
format_boolean: function(value) {
return value ? 'Yes' : 'No';
},
format_neg_boolean: function(value) {
return !value ? 'Yes' : 'No';
},
format_content_types: function(value) {
var cta = [];
Ext.each(value.split(','), function(ct) {
if (ct === 'images')
cta.push('Images');
if (ct === 'backup')
cta.push('Backups');
if (ct === 'vztmpl')
cta.push('Templates');
if (ct === 'iso')
cta.push('ISO');
});
return cta.join(', ');
},
render_serverity: function (value) {
return log_severity_hash[value] || value;
},
render_upid: function(value, metaData, record) {
var type = record.data.type;
var id = record.data.id;
if (type == 'vncproxy') {
return "VNC connection to VM " + id;
}
if (type == 'vncshell') {
return "VNC shell";
}
return value;
},
render_cpu: function(value, metaData, record, rowIndex, colIndex, store) {
var cpu = value;
var maxcpu = record.data.maxcpu;
if (cpu === undefined || maxcpu === undefined)
return ''
var per = (cpu * 100) / maxcpu;
return PVE.Utils.format_html_bar(per, per.toFixed(0) + '% of ' +
maxcpu + (maxcpu > 1 ? 'CPUs' : 'CPU'));
},
render_mem: function(value, metaData, record, rowIndex, colIndex, store) {
var mem = value;
var maxmem = record.data.maxmem;
if (record.data.itype == 'storage' || mem === undefined || maxmem === undefined)
return ''
return PVE.Utils.format_html_bar((mem * 100) / maxmem,
PVE.Utils.format_size(mem));
},
render_disk: function(value, metaData, record, rowIndex, colIndex, store) {
var disk = value;
var maxdisk = record.data.maxdisk;
if (disk === undefined || maxdisk === undefined)
return ''
return PVE.Utils.format_html_bar((disk * 100) / maxdisk,
PVE.Utils.format_size(disk));
},
render_itype: function(value, metaData, record, rowIndex, colIndex, store) {
var cls = 'pve-itype-icon-' + value;
return "<div class='" + cls + "'</div><div>" + value + "</div>";
},
render_uptime: function(value, metaData, record, rowIndex, colIndex, store) {
var uptime = value;
if (uptime === undefined)
return '';
if (uptime <= 0)
return '-';
return PVE.Utils.format_duration_long(uptime);
},
dummy: "ignore me"
};
var field_defaults = {
itype: {
header: 'Type',
type: 'text',
renderer: utils.render_itype,
width: 50
},
id: {
header: 'ID',
hidden: true,
type: 'text'
},
name: {
header: 'Name',
type: 'text'
},
disk: {
header: 'Disk',
type: 'integer',
renderer: utils.render_disk,
width: 60
},
maxdisk: {
header: 'maxdisk',
type:'integer',
hidden: true,
width: 60
},
mem: {
header: 'Memory',
type: 'integer',
renderer: utils.render_mem,
width: 60
},
maxmem: {
header: 'maxmem',
type:'integer',
hidden: true,
width: 60
},
cpu: {
header: 'CPU',
type:'float',
renderer: utils.render_cpu,
width: 85
},
maxcpu: {
header: 'maxcpu',
type:'integer',
hidden: true,
width: 60
},
uptime: {
header: 'Uptime',
type:'integer',
renderer: utils.render_uptime,
width: 110
},
node: {
header: 'Node',
type: 'text',
hidden: true,
width: 110
},
storage: {
header: 'Storage',
type: 'text',
hidden: true,
width: 110
},
shared: {
header: 'Shared',
type: 'boolean',
hidden: true,
width: 60
}
};
var visible_fields = function() {
var res = {};
for (field in field_defaults) {
if (!field_defaults[field].hidden)
res[field] = true;
}
return res;
}();
utils.getFields = function() {
return Ext.apply({}, field_defaults);
};
utils.base_fields = function() {
var res = [];
for (field in field_defaults) {
res.push(field);
}
return res;
}();
utils.get_field_defaults = function(fieldlist) {
var res = [];
Ext.each(fieldlist, function(field) {
var info = field_defaults[field];
if (!info)
throw "no such field '" + field + "'";
var fi = { name: field };
if (info.type)
fi.type = info.type;
res.push(fi);
});
return res;
};
utils.default_view = 'server';
utils.default_views = {
custom: {
text: 'Custom View',
fields: Ext.apply({}, visible_fields),
groups: []
},
folder: {
text: 'Folder View',
fields: Ext.apply({}, visible_fields),
groups: ['itype']
},
server: {
text: 'Server View',
fields: Ext.apply({}, visible_fields),
groups: ['node']
},
storage: {
text: 'Storage View',
fields: Ext.apply({}, visible_fields),
groups: ['node'],
filterfn: function(n, itype) {
return itype === 'storage';
}
}
};
utils.changeViewDefaults = function(view, viewinfo) {
console.log("change view defaults" + view);
utils.default_views[view].fields =
Ext.apply({}, viewinfo.fields);
utils.default_views[view].groups =
[].concat(viewinfo.groups);
};
utils.get_column_defaults = function(view) {
var res = [];
var viewinfo = utils.default_views[view];
for (field in field_defaults) {
var info = field_defaults[field];
var fi = { header: info.header, dataIndex: field };
if (info.renderer)
fi.renderer = info.renderer;
if (info.width)
fi.width = info.width;
if (!viewinfo.fields[field])
fi.hidden = true;
res.push(fi);
}
return res;
};
return utils;
}();

View File

@ -1,428 +0,0 @@
Ext.ns("PVE");
PVE.DynTreeNode = Ext.extend(Ext.tree.TreeNode, {
nodeSortFn: function(n1, n2) {
if ((n1.groupbyid && n2.groupbyid) ||
!(n1.groupbyid || n2.groupbyid)) {
var tcmp;
var v1 = n1.attributes.itype;
var v2 = n2.attributes.itype;
if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0)
return tcmp;
// var v1 = n1.text.length;
// var v2 = n2.text.length;
// if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0)
// return tcmp;
return n1.text > n2.text ? 1 : (n1.text < n2.text ? -1 : 0);
} else if (n1.groupbyid) {
return -1;
} else if (n2.groupbyid) {
return 1;
}
},
applyDefaults: function(info) {
var itype = info.itype;
if (itype === 'node') {
Ext.apply(info, {
cls: 'x-tree-node-server',
target: {
xtype: 'pveNodeConfig',
nodename: info.itemid
}
});
} else if (itype === 'storage') {
Ext.apply(info, {
cls: 'x-tree-node-harddisk',
target: {
xtype: 'pveStorageBrowser',
confdata: info.data
}
});
} else if (itype === 'vm') {
Ext.apply(info, {
cls: 'x-tree-node-computer',
target: {
xtype: 'pveKVMConfig',
confdata: info.data
}
});
} else {
Ext.apply(info, {
cls: 'x-tree-node-collapsed',
target: {
title: "Resources",
layout: 'fit',
border: false,
xtype: 'pveConfigPanel'
}
});
}
},
// fast binary search
findInsertIndex: function(n, start, end) {
var diff = end - start;
var mid = start + (diff>>1);
if (diff <= 0)
return start;
var res = this.nodeSortFn(n, this.childNodes[mid]);
if (res <= 0)
return this.findInsertIndex(n, start, mid);
else
return this.findInsertIndex(n, mid + 1, end);
},
addSorted: function(n) {
var cs = this.childNodes;
var len = cs.length;
var index = this.findInsertIndex(n, 0, len);
var pos = cs[index]
this.insertBefore(n, pos);
return;
},
groupChild: function(info, groups, level) {
var obj = this;
var groupby = groups[level];
var v = (groupby === 'itype') ? info.itype : info.data[groupby];
var add_group = function(nodeinfo, gbid) {
obj.applyDefaults(nodeinfo);
nodeinfo.leaf = false;
nodeinfo.groupbyid = gbid;
nodeinfo.target.showSearch = true;
var group = new PVE.DynTreeNode(nodeinfo);
obj.addSorted(group);
return group;
};
if (info.itype === groupby) {
var group = this.findChild('groupbyid', info.itemid);
if (group)
return group;
return add_group(info, info.itemid);
} else if (v) {
var group = this.findChild('groupbyid', v);
if (!group) {
var groupinfo = {
itype: groupby,
itemid: v,
text: v
};
group = add_group(groupinfo, v);
}
return group.groupChild(info, groups, level +1);
}
this.applyDefaults(info);
var child = new Ext.tree.TreeNode(info);
this.addSorted(child);
return child;
},
removeStaleGroups: function() {
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++) {
var child = cs[i];
if (!child)
continue;
if (!child.hasChildNodes()) {
if (child.groupbyid) {
child.remove(true);
}
} else {
child.removeStaleGroups();
}
};
},
constructor: function(config){
PVE.DynTreeNode.superclass.constructor.call(this, Ext.apply(this, config));
}
});
Ext.tree.TreePanel.nodeTypes.pvedyn = PVE.DynTreeNode;
PVE.ResourceTree = Ext.extend(Ext.tree.TreePanel, {
viewname: PVE.Utils.default_view,
initView: function(viewname) {
this.viewname = viewname;
},
setView: function(viewname) {
var tree = this;
tree.initView(viewname);
var sm = this.getSelectionModel();
var sel = sm.getSelectedNode();
var oldid;
if (sel) {
oldid = sel.id;
}
// make sure we do not show the search panel - for performance reasons
PVE.Workspace.setView(null);
var rootnode = this.getRootNode();
this.el.mask('Please wait...', 'x-mask-loading');
rootnode.collapse(false, false);
rootnode.removeAll(true);
this.data = {};
Ext.each(tree.storelist, function(store) {
tree.updateTree(store, store.itype);
});
rootnode.expand(false, false);
this.el.unmask();
if (oldid && this.data[oldid]) {
node = this.data[oldid].treenode;
if (node) {
this.selectNode(node);
return;
}
}
this.selectNode(rootnode);
},
updateTree: function(store, itype) {
var tree = this;
//console.log("update tree " + tree);
var groups = [].concat(PVE.Utils.default_views[this.viewname].groups);
var filterfn = PVE.Utils.default_views[this.viewname].filterfn;
var rootnode = tree.getRootNode();
if (!rootnode)
throw "no rootnode in tree";
// remove vanished or changed items
for (var uid in tree.data) {
var info = tree.data[uid];
if (!info)
continue;
if (info.itype !== itype)
continue;
var item = store.getById(info.itemid);
var changed = false;
if (item) {
// test if any grouping attributes changed
for (var i = 0, len = groups.length; i < len; i++) {
var attr = groups[i];
if (attr === 'itype') {
continue;
} else if (item.data[attr] != info.data[attr]) {
//console.log("changed");
changed = true;
break;
}
}
// fixme: also test filterfn()?
}
if (!item || changed) {
info.treenode.remove(); // fixme: destroy?
tree.data[uid] = null;
}
}
// add new items
store.each(function(item) {
var uid = itype + "." + item.id;
var olddata = tree.data[uid];
if (filterfn && !filterfn(item, itype)) {
return;
}
if (!olddata) {
var info = { data: {} };
Ext.apply(info.data, item.data);
Ext.apply(info, {
itype: itype,
id: uid,
text: item.id,
itemid: item.id,
leaf: true
});
var child = rootnode.groupChild(info, groups, 0);
if (child) {
info.treenode = child;
tree.data[uid] = info;
}
}
});
// this can cause unwanted ui updates
// remove groups with no children
// rootnode.removeStaleGroups();
},
selectNode: function(sel) {
sel.ensureVisible();
sel.select();
//console.log("SELECT " + sel.attributes.target);
var comp = { pveSelNode: sel };
Ext.apply(comp, sel.attributes.target);
PVE.Workspace.setView(comp);
},
initComponent: function() {
var tree = this;
var rootnode = new PVE.DynTreeNode({
expanded: true,
id: 'root',
text: "Datacenter 1",
cls: 'x-tree-node-collapsed',
target: {
xtype: 'pveClusterConfig',
clusterid: 'default'
}
});
tree.storelist = PVE.Cache.storelist;
var groupdef = [];
for (var viewname in PVE.Utils.default_views) {
groupdef.push([viewname, PVE.Utils.default_views[viewname].text]);
};
var viewcombo = new Ext.form.ComboBox({
width: 150,
allowBlank: false,
editable: false,
store: groupdef,
forceSelection: true,
triggerAction: 'all',
value: tree.viewname,
listeners: {
select: function(combo, record, index) {
tree.setView(combo.getValue());
}
},
getState: function() {
return { view: this.getValue() };
},
applyState : function(state) {
if (state && state.view) {
this.setValue(state.view);
tree.initView(state.view);
}
},
stateEvents: [ 'select' ],
stateful: true,
stateId: 'pvetreeviewselection'
});
Ext.apply(this, {
data: {},
width: 250,
title: 'Resource Tree',
autoScroll: true,
containerScroll: true,
rootVisible: true,
root: rootnode,
tbar: [
viewcombo,
'->', {
text: 'Filter',
handler: function() {
if (Ext.get('pvefilterwindow'))
return;
var w = new PVE.Filter({
loadview: tree.viewname,
listeners: {
changeview: function(view, viewinfo) {
PVE.Utils.changeViewDefaults(view, viewinfo);
viewcombo.setValue(view);
// fixme: save custom view
viewcombo.saveState();
tree.setView(view);
}
}
});
w.show();
}
}
],
listeners: {
click: function(n) {
tree.selectNode(n);
}
}
});
tree.initView(tree.viewname);
PVE.ResourceTree.superclass.initComponent.call(this);
Ext.each(tree.storelist, function(store) {
var update_store = function() {
tree.updateTree(store, store.itype);
};
store.on('load', update_store);
tree.on('destroy', function () {
store.un('load', update_store);
});
});
}
});
Ext.reg('pveResourceTree', PVE.ResourceTree);

View File

@ -1,210 +0,0 @@
Ext.ns("PVE");
PVE.LogViewer = Ext.extend(Ext.list.ListView, {
initComponent : function() {
var self = this;
var fields = [
{ name: 'time', type : 'date', dateFormat: 'timestamp' },
{ name: 'pri', type: 'int' },
{ name: 'pid', type: 'int' },
'node', 'user', 'tag', 'msg' ];
var logstore = new PVE.data.UpdateStore({
itype: 'log',
autoDestroy: true,
url: self.url,
fields: fields
});
Ext.apply(self, {
store: logstore,
startUpdate: function() { logstore.startUpdate(); },
stopUpdate: function() { logstore.stopUpdate(); },
columnSort: false,
columns: [
{ header: "Time", width: 0.10, dataIndex: 'time',
tpl: '{time:date("M d H:i:s")}'
},
{ header: "Node", width: 0.05, dataIndex: 'node' },
{ header: "Tag", width: 0.05, dataIndex: 'tag' },
{ header: "PID", width: 0.05, dataIndex: 'pid' },
{ header: "User", width: 0.05, dataIndex: 'user' },
{ header: "Severity", width: 0.05, dataIndex: 'pri',
tpl: '{[ PVE.Utils.render_serverity(values.pri) ]}'
},
{ header: "Message", dataIndex: 'msg' }
]});
var move_to_end = true;
logstore.on("load", function() {
if (move_to_end) {
move_to_end = false;
var count = logstore.getCount();
if (count) {
var item = self.getNode(count - 1);
if (item)
Ext.fly(item).scrollIntoView(self.innerBody.dom.parentNode);
}
}
});
PVE.LogViewer.superclass.initComponent.call(self);
}
});
PVE.ClusterTasks = Ext.extend(Ext.grid.GridPanel, {
initComponent : function() {
var self = this;
var fields = [
{ name: 'starttime', type : 'date', dateFormat: 'timestamp' },
{ name: 'endtime', type : 'date', dateFormat: 'timestamp' },
{ name: 'pid', type: 'int' },
'node', 'upid', 'user', 'status', 'type', 'id'];
// fixme: use/define a storage which append new values, but
// defer removing old values until a maximum numer of entries
// is reached
var taskstore = new PVE.data.UpdateStore({
itype: 'tasks',
autoDestroy: true,
url: '/api2/json/cluster/tasks',
idProperty: 'upid',
fields: fields
});
Ext.apply(self, {
store: taskstore,
border: false,
startUpdate: function() { taskstore.startUpdate(); },
stopUpdate: function() { taskstore.stopUpdate(); },
columnSort: false,
autoExpandColumn: 'status',
viewConfig: {
getRowClass: function(record, index) {
var status = record.get('status');
if (status && status != 'OK')
return "x-form-invalid";
}
},
columns: [
{ header: "Start Time", dataIndex: 'starttime',
width: 100,
renderer: function(value) { return value.format("M d H:i:s"); }
},
{ header: "End Time", dataIndex: 'endtime',
width: 100,
renderer: function(value, metaData, record) {
if (record.data.pid) {
metaData.css = "x-grid-row-loading";
return "";
}
return value.format("M d H:i:s");
}
},
{ header: "Node", dataIndex: 'node',
width: 100
},
{ header: "User", dataIndex: 'user',
width: 150
},
{ id: 'desc', header: "Description", dataIndex: 'upid',
width: 400,
renderer: PVE.Utils.render_upid
},
{ id: 'status', header: "Status", dataIndex: 'status',
width: 200,
renderer: function(value, metaData, record) {
if (record.data.pid) {
metaData.css = "x-grid-row-loading";
return "";
}
if (value == 'OK')
return 'OK';
// metaData.attr = 'style="color:red;"';
return "ERROR: " + value;
}
}
]});
PVE.ClusterTasks.superclass.initComponent.call(self);
}
});
PVE.StatusPanel = Ext.extend(Ext.Panel, {
initComponent : function() {
var self = this;
self.title = "Realtime logfile viewer";
self.layout = 'fit';
var syslogview = new PVE.LogViewer({
url: '/api2/json/nodes/localhost/syslog'
});
var cllogview = new PVE.LogViewer({
url: '/api2/json/cluster/log',
});
var tasklist = new PVE.ClusterTasks();
self.items = {
xtype: 'tabpanel',
border: false,
tabPosition: 'bottom',
activeTab: 0,
defaults: { layout: 'fit' },
items: [
{
title: 'Cluster Log',
items: cllogview,
listeners: {
show: function() {
cllogview.startUpdate();
},
hide: function() {
cllogview.stopUpdate();
}
}
},
{
title: 'System Log',
items: syslogview,
listeners: {
show: function() {
syslogview.startUpdate();
},
hide: function() {
syslogview.stopUpdate();
}
}
},
{
title: 'Task list',
items: tasklist,
listeners: {
show: function() {
tasklist.startUpdate();
},
hide: function() {
tasklist.stopUpdate();
}
}
}
]
};
PVE.StatusPanel.superclass.initComponent.call(self);
}
});
Ext.reg('pveStatusPanel', PVE.StatusPanel);

View File

@ -1,363 +0,0 @@
Ext.ns("PVE");
PVE.StorageContent = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
var storeid = self.confdata.storage;
var node = self.confdata.node || 'localhost';
if (!storeid)
throw "no storage id specified";
var ct = self.content_type;
var params = ct ? { content: ct } : null;
var store = new Ext.data.JsonStore({
url: "/api2/json/nodes/" + node + "/storage/" + storeid,
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
baseParams: params,
fields: [ 'format', 'size', 'volid' ]
});
Ext.apply(self, {
stateful: false,
store: store,
autoExpandColumn: 'volid',
tbar: [
'->',
{
xtype: 'form',
url: "/api2/htmljs/nodes/" + node + "/upload",
baseParams: { storage: storeid },
fileUpload: true,
height: 22,
border: false,
baseCls: 'plain',
items: {
xtype: 'fileuploadfield',
name: 'filename',
buttonOnly: true,
buttonText: 'Upload',
listeners: {
fileselected: function(field, v) {
self.el.mask('Please wait...', 'x-mask-loading');
var form = field.ownerCt.getForm();
//alert("selected " + v);
form.submit({
failure: function(f, resp){
self.el.unmask();
f.reset();
var msg = "Please try again";
if (resp.result && resp.result.message) {
msg = resp.result.message;
}
Ext.MessageBox.alert('Failure', "Upload failed. " + msg);
},
success: function(f, resp){
self.el.unmask();
f.reset();
Ext.MessageBox.alert('Failure', "Upload succesful");
}
});
}
}
}
}
],
columns: [
{
id: 'volid',
header: 'Name',
dataIndex: 'volid'
},
{
header: 'Format',
width: 100,
dataIndex: 'format'
},
{
header: 'Size',
width: 100,
renderer: PVE.Utils.format_size,
dataIndex: 'size'
}
],
listeners: {
show: function() {
store.load();
}
},
sm: new Ext.grid.RowSelectionModel({singleSelect:true})
});
PVE.StorageContent.superclass.initComponent.call(self);
}
});
Ext.reg('pveStorageContent', PVE.StorageContent);
PVE.StorageStatus = Ext.extend(PVE.grid.ObjectView, {
initComponent : function() {
var self = this;
var storeid = self.confdata.storage;
var node = self.confdata.node || 'localhost';
if (!storeid)
throw "no storage id specified";
var store = new PVE.data.ObjectStore({
url: "/api2/json/nodes/" + node + "/storage/",
baseParams: { storage: storeid },
method: 'GET',
restful: true, // use GET, not POST
autoDestroy: true,
rows: {
total: { header: 'Capacity' },
used: { header: 'Used' },
free: { header: 'Free' }
}
});
store.load();
Ext.apply(self, {
layout: 'fit',
tbar: [
"<b>Status", '->',
{
text: "Refresh",
handler: function() { store.load(); }
}
],
store: store
});
PVE.StorageStatus.superclass.initComponent.call(self);
}
});
PVE.StorageSummary = Ext.extend(Ext.Panel, {
initComponent : function() {
var self = this;
var storeid = self.confdata.storage;
var update_config = function() {
self.store.load();
};
Ext.apply(self, {
layout: 'hbox',
autoScroll: true,
layoutConfig: {
defaultMargins: "10 10 10 0",
align: 'stretchmax'
},
items: [
{
xtype: 'pveObjectView',
store: self.store,
margins: "10 10 10 10",
height: 200,
width: 300,
tbar: [
"<b>Configuration", "->",
{
text: "Edit",
handler: function() {
var form = new PVE.form.ModifyDirStorage({
confdata: self.confdata
});
var win = new PVE.window.ModalDialog({
title: "Modify Directory Storage",
items: form,
width: 400,
height: 300,
buttons: [
{
text: 'OK',
handler: function(){
form.submitHandler({
success: function() {
win.close();
update_config();
}
});
}
},{
text: 'Cancel',
handler: function(){
win.close();
update_config();
}
}
]
});
win.show();
}
}
]
//flex: 1,
},
new PVE.StorageStatus ({
confdata: self.confdata,
height: 200,
width: 300
})
]
});
PVE.StorageSummary.superclass.initComponent.call(self);
}
});
Ext.reg('pveStorageSummary', PVE.StorageSummary);
PVE.StorageBrowser = Ext.extend(PVE.ConfigPanel, {
initComponent : function() {
var self = this;
var node = self.confdata.node;
var storeid = self.confdata.storage;
var shared = self.confdata.shared;
if (!storeid)
throw "no storage ID specified";
if (!shared && !node)
throw "no node specified";
var title = "Storage '" + storeid + "'";
if (!shared)
title = title + " on node '" + node + "'";
var cond_view_comp = function(id, enable) {
var tabs = self.get(0);
var comp = self.findById(id);
if (!comp)
return;
if (enable) {
tabs.unhideTabStripItem(id);
} else {
var active = tabs.getActiveTab();
tabs.hideTabStripItem(id);
if (active) {
active = Ext.isObject(active) ? active.getId() : active;
if (active === id) {
tabs.setActiveTab(0);
}
}
}
};
var store = new PVE.data.ObjectStore({
url: "/api2/json/storage/" + storeid,
method: 'GET',
autoDestory: true,
rows: {
type: { header: 'Storage Type', renderer: PVE.Utils.format_storage_type },
path: { header: 'Path' },
shared: { header: 'Shared', renderer: PVE.Utils.format_boolean },
disable: { header: 'Disabled', renderer: PVE.Utils.format_boolean },
content: { header: 'Content', renderer: PVE.Utils.format_content_types }
}
});
var set_visible_tabs = function() {
var rec = store.getById('content');
if (!rec)
return;
var ct = rec.data.value || '';
var cthash = {};
Ext.each(ct.split(','), function(item) { cthash[item] = 1 });
cond_view_comp('images', cthash.images);
cond_view_comp('iso', cthash.iso);
cond_view_comp('vztmpl', cthash.vztmpl);
cond_view_comp('backup', cthash.backup);
};
store.on('load', set_visible_tabs);
Ext.apply(self, {
title: title,
layout: 'fit',
border: false,
defaults: {
border: false
},
items: [
{
title: 'Summary',
xtype: 'pveStorageSummary',
listeners: {
show: function() {
store.load();
}
},
confdata: self.confdata,
store: store,
id: 'status'
},
{
xtype: 'pveStorageContent',
confdata: self.confdata,
content_type: 'images',
title: 'Images',
id: 'images'
},
{
xtype: 'pveStorageContent',
confdata: self.confdata,
content_type: 'iso',
title: 'ISO',
id: 'iso'
},
{
xtype: 'pveStorageContent',
confdata: self.confdata,
content_type: 'vztmpl',
title: 'Templates',
id: 'vztmpl'
},
{
xtype: 'pveStorageContent',
confdata: self.confdata,
content_type: 'backup',
title: 'Backups',
id: 'backup'
},
{
title: 'Permissions',
id: 'permissions',
html: 'services '
}
]
});
PVE.StorageBrowser.superclass.initComponent.call(self);
}
});
Ext.reg('pveStorageBrowser', PVE.StorageBrowser);

View File

@ -1,136 +0,0 @@
Ext.ns("PVE");
PVE.Workspace = function() {
var viewport, content, login;
var defaultView = {
//xtype: "pveTestPanel",
title: 'Nothing selected',
border: false,
region:'center'
};
var buildDefaultView = function() {
PVE.Cache.startUpdate();
return new Ext.Panel({
layout: 'border',
border: false,
//frame: true,
tbar: [
'<img src="/images/proxmox_logo.png">',
'->',
{
text: 'Logout',
handler: PVE.Workspace.showLogin
}],
items: [
{
layout: 'fit',
region: 'center',
margins:'5 0 0 0',
items: defaultView
},
{
xtype: 'pveResourceTree',
region: 'west',
margins:'5 0 0 0',
split:true,
collapsible: true
},
{
xtype: 'pveStatusPanel',
region:'south',
margins:'0 0 0 0',
height: 200,
collapsible: true,
split:true
}
]
});
};
var buildContent = function() {
var href = window.location.href;
var hrefcomp = href.split('?', 2);
if (hrefcomp.length == 2) {
var param = Ext.urlDecode(hrefcomp[1]);
if (param.console !== undefined) {
if (param.console == "kvm") {
content = new PVE.Console({
vmid: param.vmid,
node: param.node,
toplevel: true
});
} else if (param.console == "shell") {
content = new PVE.Shell({
node: param.node,
toplevel: true
});
}
} else {
content = buildDefaultView();
}
} else {
content = buildDefaultView();
}
viewport.add(content);
viewport.doLayout();
content.show(); // fire 'show' for PVE.Console
};
var workspace = {
init: function() {
Ext.QuickTips.init();
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
viewport = new Ext.Viewport({ layout : 'fit' });
if (!PVE.Utils.authOK()) {
PVE.Workspace.showLogin();
} else {
buildContent();
}
},
setView: function(comp) {
if (!content) return;
if (!comp) comp = defaultView;
var cont = content.find("region", 'center')[0];
cont.removeAll(true);
cont.add(comp);
content.doLayout();
},
showLogin: function() {
PVE.Utils.authClear();
if (!login) {
login = new PVE.window.LoginWindow({
handler: function() {
if (!content)
buildContent();
login = null;
}
});
}
login.show();
},
dummy: "ignore me"
};
return workspace;
}();

View File

@ -1,57 +0,0 @@
Ext.ns("PVE.data");
/* A reader to store a single JSON Object (hash) into a storage.
* Also accepts an array containing a single hash.
* So it can read:
*
* example1: { data: "xyz" }
* example2: [ { data: "xyz" } ]
*/
PVE.data.ObjectReader = Ext.extend(Ext.data.JsonReader, {
constructor: function(config){
PVE.data.ObjectReader.superclass.constructor.call(this, Ext.apply(config, {
root: 'data',
idProperty: 'name',
fields: [
{name: 'name', type: 'text'},
{name: 'value', type: 'text'}
]
}));
this.rows = config.rows;
},
extractData : function(root, returnRecords) {
if (returnRecords !== true)
throw "not implemented";
if (Ext.isArray(root)) {
if (root.length == 1)
root = root[0];
else
root = {};
}
var Record = this.recordType;
var rs = [];
var rows = this.rows;
if (rows) {
Ext.iterate(rows, function(key, rowdef) {
var value = root[key];
if (Ext.isDefined(value)) {
var rec = new Record({ name: key, value: value }, key);
rs.push(rec);
}
});
} else {
Ext.iterate(root, function(key, value) {
var rec = new Record({ name: key, value: value }, key);
rs.push(rec);
});
}
return rs;
}
});

View File

@ -1,11 +0,0 @@
Ext.ns("PVE.data");
// a store for simple JSON Object (hash)
PVE.data.ObjectStore = Ext.extend(Ext.data.Store, {
constructor: function(config) {
PVE.data.ObjectStore.superclass.constructor.call(this, Ext.apply(config, {
reader: new PVE.data.ObjectReader(config)
}));
}
});

View File

@ -1,266 +0,0 @@
Ext.ns("PVE.data");
PVE.data.SearchStore = Ext.extend(Ext.data.Store, {
constructor: function(config) {
var self = this;
config = config || {};
if (!config.storelist)
throw "no storage list specified";
var text_filter = '';
var text_filter_fn = function(item) {
if (text_filter) {
var match = false;
Ext.each(['name', 'storage', 'node'], function(field) {
var v = item.data[field];
if (v !== undefined) {
v = v.toLowerCase();
if (v.indexOf(text_filter) >= 0) {
match = true;
return false;
}
}
});
return !match;
}
return false;
};
var item_filter_fn;
var group_filter = [];
var filterFn = function(item, itype) {
if (item_filter_fn && !item_filter_fn(item, itype)) {
return true;
}
for (var i = 0, len = group_filter.length; i < len; i++) {
var filter = group_filter[i];
var field = filter.field;
if (field === 'itype') {
if (itype != filter.value)
return true;
} else if (item.data[field] != filter.value)
return true;
}
return text_filter_fn(item);
};
var load_info = {};
var task_search = null;
var run_search_task = function(delay) {
if (!task_search) {
task_search = new Ext.util.DelayedTask(function() {
console.log("text filter " + text_filter);
self.suspendEvents();
self.removeAll();
Ext.each(config.storelist, function(store) {
self.initStore(store, store.itype);
});
self.applySort();
self.resumeEvents();
self.fireEvent('datachanged', self);
self.fireEvent('load', self);
});
}
task_search.delay(delay);
};
var basefields = PVE.Utils.base_fields;
var myfields = ['objectid', 'itype', 'itemid'].concat(basefields);;
var reader = new Ext.data.ArrayReader({
fields: myfields,
idIndex: 0
});
Ext.apply(config, {
reader: reader,
sortInfo: {
field: 'itype',
direction: 'DESC'
},
getTextFilter: function() {
return text_filter;
},
setTextFilter: function(text) {
if (text_filter === text)
return;
text_filter = text.toLowerCase();
run_search_task(200);
},
setGroupFilter: function(viewname, filterinfo) {
item_filter_fn = PVE.Utils.default_views[viewname].filterfn;
group_filter = filterinfo;
run_search_task(10);
},
createRec: function(item, uid, itype) {
var info = Ext.apply({}, item.data);
Ext.apply(info, {
itype: itype,
id: uid,
text: item.id,
itemid: item.id,
leaf: true
});
var rec = new self.reader.recordType(info, uid);
return rec;
},
initStore: function(basestore, itype) {
console.log("basestore init " + itype);
load_info[itype] = true;
basestore.each(function(item) {
if (filterFn(item, itype))
return true;
var uid = itype + "." + item.id;
//console.log("add item " + uid);
var rec = self.createRec(item, uid, itype);
self.add(rec);
});
},
updateStore: function(basestore, itype) {
//console.log("basestore load " + itype);
if (!load_info[itype]) {
//console.log("basestore first load " + itype);
self.suspendEvents();
self.initStore(basestore, itype);
self.applySort();
self.resumeEvents();
self.fireEvent('datachanged', self);
} else {
// update tree
//console.log("basestore update start");
self.suspendEvents();
// remove vanished or changed items
var rmlist = [];
self.each(function(item) {
if (item.data.itype !== itype)
return true;
var newitem = basestore.getById(item.data.itemid);
if (!newitem)
rmlist.push(item);
});
if (rmlist.length)
self.remove(rmlist); //fixme:
var addlist = [];
basestore.each(function(newitem) {
if (filterFn(newitem, itype))
return true;
var uid = itype + "." + newitem.id;
var item = self.getById(uid);
if (!item) {
//console.log("add item " + uid);
var rec = self.createRec(newitem, uid, itype);
addlist.push(rec);
} else {
var changes = false;
for (var i = 0, len = basefields.length; i < len; i++) {
field = basefields[i];
if (field != 'id' && item[field] != newitem.data[field]) {
item.beginEdit()
item.set(field,newitem.data[field]);
changes = true;
//item[field] = newitem.data[field];
}
};
if (changes)
item.commit(true);
}
});
if (addlist.length)
self.add(addlist);
self.applySort();
self.resumeEvents();
self.fireEvent('datachanged', self);
//console.log("basestore update end " + itype);
}
}
});
PVE.data.SearchStore.superclass.constructor.call(self, config);
Ext.each(config.storelist, function(store) {
var update_store = function() {
self.updateStore(store, store.itype);
};
store.on('load', update_store);
self.on('destroy', function () {
store.un('load', update_store);
});
});
}
});

View File

@ -1,99 +0,0 @@
Ext.ns("PVE.data");
// Serialize load (avoid too many parallel connections)
PVE.data.UpdateQueue = function() {
var queue = [];
var queue_idx = {};
var idle = true;
var start_update = function() {
if (!idle)
return;
var store = queue.shift();
if (!store)
return;
queue_idx[store.itype] = null;
idle = false;
store.load({
callback: function() {
idle = true;
start_update();
}
});
};
return {
queue: function(store) {
if (queue_idx[store.itype])
return;
queue_idx[store.itype] = store;
queue.push(store);
start_update();
}
};
}();
PVE.data.UpdateStore = Ext.extend(Ext.data.JsonStore, {
constructor: function(config) {
var self = this;
var load_task;
var run_load_task = function(delay) {
if (!load_task) {
load_task = new Ext.util.DelayedTask(function() {
PVE.data.UpdateQueue.queue(self);
});
}
load_task.delay(delay === undefined ? self.interval : delay);
};
config = config || {};
if (!config.interval)
config.interval = 3000;
if (!config.itype)
throw "no itype specifued";
Ext.apply(config, {
root: 'data',
startUpdate: function() {
run_load_task(10);
},
stopUpdate: function() {
if (!load_task)
return;
load_task.cancel();
},
listeners: {
beforeload: function() {
if (!PVE.Utils.authOK()) {
run_load_task(1000);
return false;
}
},
load: function() {
run_load_task();
},
exception: function() {
// fixme: what to do here ?
//console.log("got load expection");
run_load_task();
}
}
});
PVE.data.UpdateStore.superclass.constructor.call(self, config);
}
});

View File

@ -1,88 +0,0 @@
Ext.ns("PVE.form");
PVE.form.ModifyDirStorage = Ext.extend(PVE.form.StdForm, {
initComponent : function() {
var self = this;
var storeid = self.confdata.storage;
var cts = [['images', 'Images']];
if (storeid === 'local') {
cts.push(['vztmpl', 'OpenVZ Templates']);
cts.push(['iso', 'ISO']);
} else {
cts.push(['backup', 'Backup']);
}
var items = [
{
xtype: 'hidden',
name: 'digest'
},
{
xtype: 'textfield',
fieldLabel: 'Storage name',
name: 'storage',
value: storeid,
disabled: true
},
{
xtype: 'textfield',
fieldLabel: 'Directory',
name: 'path',
disabled: true
},
{
xtype: 'checkbox',
fieldLabel: 'Disabled',
inputValue: 1,
name: 'disable'
},
{
xtype: 'checkbox',
fieldLabel: 'Shared',
inputValue: 1,
name: 'shared'
},
{
xtype: storeid === 'local' ? 'multiselect' : 'combo',
forceSelection: true,
editable: false,
triggerAction: 'all',
fieldLabel: 'Content',
name: storeid === 'local' ? 'content' : 'hiddencontent',
mode: 'local',
style : 'margin-bottom:10px',// avoid scrolbars with Firefox
width: 150,
height: 'auto',
store: cts,
hiddenName: 'content'
}
];
// NOTE: If subclassing FormPanel, any configuration options for
// the BasicForm must be applied to initialConfig
Ext.apply(self, Ext.apply(self.initialConfig, {
url: "/api2/extjs/storage/" + storeid,
method: 'PUT',
items: {
layout: 'form',
defaults: { anchor: '-20' },
border: false,
items: items
}
}));
PVE.form.ModifyDirStorage.superclass.initComponent.call(self);
var form = self.getForm();
form.load({
url: "/api2/extjs/storage/" + storeid,
method: 'GET'
});
}
});

View File

@ -1,70 +0,0 @@
Ext.ns("PVE.form");
PVE.form.StdForm = Ext.extend(Ext.FormPanel, {
initComponent : function() {
var self = this;
// NOTE: If subclassing FormPanel, any configuration options for
// the BasicForm must be applied to initialConfig
Ext.apply(self, Ext.apply(self.initialConfig, {
bodyStyle: 'padding:5px',
autoScroll: true,
submitHandler: function(options) {
var form = self.getForm();
// NOTE: we add parameter for unset checkbox (because html
// does not sent them by default)
var params = {};
form.items.each(function(f) {
n = f.getName();
val = f.getValue();
xt = f.getXType();
if (xt === 'checkbox' && !val) {
params[n] = 0;
}
});
if(form.isValid()){
self.el.mask('Please wait...', 'x-mask-loading');
form.submit({
params: params,
failure: function(f, resp){
self.el.unmask();
if (Ext.isFunction(options.failure)) {
options.failure();
} else {
var msg = "Please try again";
if (resp.result && resp.result.message) {
msg = resp.result.message;
}
Ext.MessageBox.alert('Failure', msg);
}
},
success: function(f, resp){
self.el.unmask();
if (Ext.isFunction(options.success)) {
options.success();
} else {
Ext.MessageBox.alert('Success', "Submit successful");
}
}
});
} else {
if (Ext.isFunction(options.failure)) {
options.failure();
} else {
Ext.MessageBox.alert('Failure', "Verify failed");
}
}
}
}));
PVE.form.StdForm.superclass.initComponent.call(self);
}
});

View File

@ -1,86 +0,0 @@
Ext.ns("PVE.grid");
// a grid which displays 'load' exception messages inline
PVE.grid.StdGrid = Ext.extend(Ext.grid.GridPanel, {
initComponent : function() {
var self = this;
if (!self.store)
throw "no store specified";
PVE.grid.StdGrid.superclass.initComponent.call(self);
var display_exception = function(t, type, action, options, response, arg) {
var msg;
self.store.removeAll();
if (type == 'response') {
msg = "Error " + response.status + ": " + response.statusText;
} else {
msg = "Data load error";
}
self.getView().mainBody.update('<div class="x-form-invalid">' + msg + '</div>');
};
self.store.on('exception', display_exception);
self.on('beforedestroy', function() { self.store.un('exception', display_exception) });
}
});
// a special grid to display PVE.data.ObjectStore
PVE.grid.ObjectView = Ext.extend(PVE.grid.StdGrid, {
initComponent : function() {
var self = this;
if (!self.store)
throw "no store specified";
var rows = self.store.rows || {};
var render_key = function(key) {
var rowdef = rows[key] || {};
return rowdef.header|| key;
};
var render_value = function(value, metaData, record, rowIndex, colIndex, store) {
var key = record.data.name;
var rowdef = rows[key] || {};
var renderer = rowdef.renderer;
if (renderer)
return renderer(value, metaData, record, rowIndex, colIndex, store);
return value;
};
Ext.apply(self, {
hideHeaders: true,
stateful: false,
enableHdMenu: false,
autoExpandColumn: 'value',
columns: [
{
header: 'Name',
width: self.cwidth1,
dataIndex: 'name',
sortable: false,
renderer: render_key
},{
id: 'value',
header: 'Value',
dataIndex: 'value',
sortable: false,
renderer: render_value
}
],
sm: new Ext.grid.RowSelectionModel({singleSelect:true})
});
PVE.grid.ObjectView.superclass.initComponent.call(self);
}
});
Ext.reg('pveObjectView', PVE.grid.ObjectView);

View File

@ -1,89 +0,0 @@
#!/usr/bin/perl -w
use strict;
use mod_perl2 '1.9922';
use Encode;
use CGI;
use PVE::AccessControl;
use PVE::REST;
sub send_output {
my ($r, $data) = @_;
my $encdata = encode('UTF-8', $data);
$r->no_cache (1);
my $x = length ($encdata);
$r->content_type ("text/html;charset=UTF-8");
$r->headers_out->set ("Content-length", "$x");
$r->headers_out->set ("Pragma", "no-cache");
$r->print ($encdata);
}
# NOTE: Requests to this page are not authenticated
# so we must be very careful here
my $r = Apache2::RequestUtil->request();
my $token = 'null';
if (my $cookie = $r->headers_in->{Cookie}) {
my $ticket = PVE::REST::extract_auth_cookie($cookie);
if (PVE::AccessControl::verify_ticket($ticket, 1)) {
$token = PVE::AccessControl::assemble_csrf_prevention_token($ticket);
}
}
my $cgi = CGI->new($r);
my %args = $cgi->Vars();
my $console = $args{console};
my $title = "Proxmox Virtual Environment";
if (defined($console)) {
if ($console eq 'kvm' && $args{vmid}) {
my $name = "VM $args{vmid}"; # fixme: use real VM name
$title = "$name - Proxmox Console";
} elsif ($console eq 'shell' && $args{node}) {
$title = "node $args{node} - Proxmox Console";
}
}
my $jssrc = <<_EOJS;
PVECSRFPreventionToken = '$token';
Ext.onReady(PVE.Workspace.init, PVE.Workspace);
_EOJS
my $page = <<_EOD;
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title id='title'>$title</title>
<link rel="stylesheet" type="text/css" href="/ext/ext-all.css" />
<link rel="stylesheet" type="text/css" href="/css/ext-pve.css" />
<script type="text/javascript" src="/ext/ext-base-debug.js"></script>
<script type="text/javascript" src="/ext/ext-all-debug.js"></script>
<script type="text/javascript" src="/ext/pvemanagerlib.js"></script>
<script type="text/javascript">
Ext.BLANK_IMAGE_URL = '/images/default/s.gif';
</script>
<script type="text/javascript">$jssrc</script>
</head>
<body>
<!-- Fields required for history management -->
<form id="history-form" class="x-hidden">
<input type="hidden" id="x-history-field"/>
<iframe id="x-history-frame"></iframe>
</form>
</body>
</html>
_EOD
send_output ($r, $page);
exit (0);

View File

@ -1,52 +0,0 @@
#!/usr/bin/perl -w
use strict;
use PVE::SafeSyslog;
use ModPerl::Util (); #for CORE::GLOBAL::exit
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();
use Apache2::Access;
use Apache2::Response;
use Apache2::Util;
use Apache2::ServerUtil ();
use Apache2::Connection ();
use Apache2::Log ();
use APR::Table ();
use ModPerl::Registry ();
use Apache2::Const -compile => ':common';
use APR::Const -compile => ':common';
initlog ('proxwww', 'daemon');
use PVE::pvecfg;
use PVE::REST;
use PVE::Cluster;
use PVE::INotify;
use PVE::RPCEnvironment;
sub childinit {
syslog ('info', "Starting new child $$");
PVE::INotify::inotify_init();
PVE::RPCEnvironment->init('pub');
PVE::Config::inotify_init();
}
sub childexit {
syslog ('info', "Finish child $$");
}
my $s = Apache2::ServerUtil->server;
$s->push_handlers(PerlChildInitHandler => \&childinit);
$s->push_handlers(PerlChildExitHandler => \&childexit);
1;

View File

@ -1,52 +0,0 @@
// code from ExtJs Forum
Ext.util.base64 = {
base64s : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
encode: function(decStr){
if (typeof btoa === 'function') {
return btoa(decStr);
}
var base64s = this.base64s;
var bits;
var dual;
var i = 0;
var encOut = "";
while(decStr.length >= i + 3){
bits = (decStr.charCodeAt(i++) & 0xff) <<16 | (decStr.charCodeAt(i++) & 0xff) <<8 | decStr.charCodeAt(i++) & 0xff;
encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + base64s.charAt((bits & 0x00000fc0) >> 6) + base64s.charAt((bits & 0x0000003f));
}
if(decStr.length -i > 0 && decStr.length -i < 3){
dual = Boolean(decStr.length -i -1);
bits = ((decStr.charCodeAt(i++) & 0xff) <<16) | (dual ? (decStr.charCodeAt(i) & 0xff) <<8 : 0);
encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + (dual ? base64s.charAt((bits & 0x00000fc0) >>6) : '=') + '=';
}
return(encOut);
},
decode: function(encStr){
if (typeof atob === 'function') {
return atob(encStr);
}
var base64s = this.base64s;
var bits;
var decOut = "";
var i = 0;
for(; i<encStr.length; i += 4){
bits = (base64s.indexOf(encStr.charAt(i)) & 0xff) <<18 | (base64s.indexOf(encStr.charAt(i +1)) & 0xff) <<12 | (base64s.indexOf(encStr.charAt(i +2)) & 0xff) << 6 | base64s.indexOf(encStr.charAt(i +3)) & 0xff;
decOut += String.fromCharCode((bits & 0xff0000) >>16, (bits & 0xff00) >>8, bits & 0xff);
}
if(encStr.charCodeAt(i -2) == 61){
return(decOut.substring(0, decOut.length -2));
}
else if(encStr.charCodeAt(i -1) == 61){
return(decOut.substring(0, decOut.length -1));
}
else {
return(decOut);
}
}
};

View File

@ -1,168 +0,0 @@
Ext.ns("PVE.window");
PVE.window.LoginWindow = Ext.extend(Ext.Window, {
onLogon: function() {
var self = this;
var form = self.get(0).getForm();
if(form.isValid()){
self.el.mask('Please wait...', 'x-mask-loading');
form.submit({
failure: function(f, resp){
self.el.unmask();
Ext.MessageBox.alert('Failure', "Login failed. Please try again", function() {
var uf = form.findField('username');
uf.focus(true);
});
},
success: function(f, resp){
self.el.unmask();
if (resp.result && resp.result.data)
PVECSRFPreventionToken = resp.result.data.CSRFPreventionToken;
var handler = self.handler || Ext.emptyFn;
handler.call(self);
self.close();
}
});
}
},
initComponent: function() {
var self = this;
var realmstore = new Ext.data.JsonStore({
url: "/api2/json/access/domains",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
fields: [ 'realm', 'comment', 'default' ],
idProperty: 'realm',
sortInfo: { field: 'realm', order: 'DESC' }
});
var combo = new Ext.form.ComboBox({
fieldLabel: 'Realm',
hiddenName: 'realm',
store: realmstore,
mode: 'local',
allowBlank: false,
forceSelection: true,
autoSelect: false,
triggerAction: 'all',
valueField: 'realm',
displayField: 'comment',
getState: function() {
return { value: this.getValue() };
},
applyState : function(state) {
if (state && state.value) {
this.setValue(state.value);
}
},
stateEvents: [ 'select' ],
stateful: true,
stateId: 'pveloginrealm'
});
realmstore.load({
callback: function(r, o, success) {
if (success) {
var def = combo.getValue();
if (!def) {
if (r[0] && r[0].data)
def = r[0].data.realm;
Ext.each(r, function(record) {
if (record.data && record.data["default"])
def = record.data.realm;
});
}
if (def)
combo.setValue(def)
}
}
});
Ext.apply(self, {
width: 400,
height: 160,
modal: true,
border: false,
draggable: false,
closable: false,
resizable: false,
layout: 'fit',
title: 'PVE Manager Login',
items: [{
xtype: 'form',
frame: true,
url: '/api2/extjs/access/ticket',
labelWidth: 70,
labelAlign : 'right',
defaults: {
anchor: '-5',
allowBlank: false
},
items: [
{
xtype: 'textfield',
fieldLabel: 'User name',
name: 'username',
blankText:"Enter your user name",
listeners: {
render: function(f) {
f.focus(true, 500);
},
specialkey: function(f, e) {
var form = f.findParentByType("form").getForm();
if (e.getKey() === e.ENTER) {
var pf = form.findField('password');
if (pf.getValue()) {
self.onLogon();
} else {
pf.focus(false);
}
}
}
}
},
{
xtype: 'textfield',
inputType: 'password',
fieldLabel: 'Password',
name: 'password',
blankText:"Enter your password",
listeners: {
specialkey: function(field, e) {
if (e.getKey() === e.ENTER) {
self.onLogon();
}
}
}
},
combo
],
buttons: [
{
text: 'Login',
handler: function(){
self.onLogon();
}
}
]
}]
});
PVE.window.LoginWindow.superclass.initComponent.call(self);
}
});

View File

@ -1,20 +0,0 @@
Ext.ns("PVE.window");
PVE.window.ModalDialog = Ext.extend(Ext.Window, {
initComponent: function() {
var self = this;
//self.width = self.width || 800;
//self.height = self.height || 400;
Ext.apply(self, {
modal: true,
border: false,
layout: 'fit',
maximizable: true
});
PVE.window.ModalDialog.superclass.initComponent.call(self);
}
});