[pve-devel] r4901 - in pve-manager/pve2: bin lib/PVE lib/PVE/API2 www/manager www/manager/util
svn-commits at proxmox.com
svn-commits at proxmox.com
Thu Jul 15 11:57:39 CEST 2010
Author: dietmar
Date: 2010-07-15 09:57:39 +0000 (Thu, 15 Jul 2010)
New Revision: 4901
Added:
pve-manager/pve2/www/manager/util/
pve-manager/pve2/www/manager/util/base64.js
Modified:
pve-manager/pve2/bin/pvesh
pve-manager/pve2/lib/PVE/API2.pm
pve-manager/pve2/lib/PVE/API2/Storage.pm
pve-manager/pve2/lib/PVE/RESTHandler.pm
pve-manager/pve2/www/manager/Makefile.am
pve-manager/pve2/www/manager/StorageBrowser.js
Log:
improve storage api
Modified: pve-manager/pve2/bin/pvesh
===================================================================
--- pve-manager/pve2/bin/pvesh 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/bin/pvesh 2010-07-15 09:57:39 UTC (rev 4901)
@@ -68,6 +68,8 @@
my $msg = $res->{message} || status_message($status);
+ chomp($msg);
+
warn "$status $msg\n";
return if $nodata;
Modified: pve-manager/pve2/lib/PVE/API2/Storage.pm
===================================================================
--- pve-manager/pve2/lib/PVE/API2/Storage.pm 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/lib/PVE/API2/Storage.pm 2010-07-15 09:57:39 UTC (rev 4901)
@@ -5,14 +5,17 @@
# /storage/config GET whole config, CREATE storage
# /storage/config/{storeid}/ GET/SET storage config
-# /storage/status/{node}/{storeid}/state GET/SET state (activate/disable)
+# /storage/status/{node}/ GET/SET status list
+# /storage/status/{node}/{storeid} GET/SET state (activate/disable)
+# /storage/content/{node}/{storeid}/ list/upload content
+# /storage/content/{node}/{storeid}/{volname} DELETE content
+
+
# /storage/scan/lvm list volume groups
# /storage/scan/nfs list nfs exports
# /storage/scan/iscsi list iscsi exports
-# /storage/content/{storeid}/{node} list/upload content
-# /storage/content/{storeid}/{node}/{volname} DELETE content
# iso/*.iso
# vztmpl/*.tgz
@@ -134,7 +137,7 @@
name => 'scan_index',
match_re => [ 'scan' ],
method => 'GET',
- description => "Index of available svan methods",
+ description => "Index of available scan methods",
parameters => {
additionalProperties => 0,
properties => {},
@@ -177,9 +180,59 @@
return [];
};
+# fixme: move to somewhere else
__PACKAGE__->register_method ({
+ name => 'cluster_index',
+ match_re => [ 'index'],
+ method => 'GET',
+ description => "Cluster wide storage status.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+# links => [ { rel => 'child', href => "{storage}" } ],
+ },
+});
+sub cluster_index {
+ my ($conn, $resp, $param) = @_;
+
+ my $nodes = [ 'node-0', 'node-1', 'node-2', 'node-3' ]; # fixme: use the real list
+
+ my $cfg = PVE::Config::read_file ("storagecfg");
+
+ my @sids = PVE::Storage::storage_ids ($cfg);
+
+ my $res = [];
+ foreach my $storeid (@sids) {
+ my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
+ if ($scfg->{shared}) {
+ my $data = { name => $storeid, storage => $storeid, type => $scfg->{type}, shared => 1};
+ push @$res, $data;
+ } else {
+ # we create a entry for each node
+ foreach my $node (@$nodes) {
+ my $data = { name => "$storeid ($node)", storage => $storeid, node => $node,
+ type => $scfg->{type}, shared => 0};
+ push @$res, $data;
+ }
+ }
+ }
+
+ # $resp->{digest} = $cfg->{digest}; # fixme: how do we handle that
+
+ return $res;
+}
+
+__PACKAGE__->register_method ({
name => 'list_nodes',
- match_re => [ '(status|content)' ], # /storage/(status|content)
+ # /storage/(status|content)
+ match_re => [ '(status|content)' ],
method => 'GET',
description => "List storage nodes.",
parameters => {
@@ -200,11 +253,8 @@
sub list_nodes {
my ($conn, $resp, $param) = @_;
- my ($storeid) = $conn->{rel_uri} =~ m|/([^/]+)$|;
-
- # fixme: check if storeid exists on node
-
- my $nodes = [ # fixme: use the real list
+ # fixme: use the real list
+ my $nodes = [
{ node => 'node-0'},
{ node => 'node-1'},
{ node => 'node-2'},
@@ -215,12 +265,12 @@
}
-# fixme: move to somewhere else
__PACKAGE__->register_method ({
- name => 'cluster_index',
- match_re => [ 'index'],
+ name => 'list_store_ids',
+ # /storage/content/{node}/
+ match_re => [ 'content' , '\S+'],
method => 'GET',
- description => "Cluster wide storage status.",
+ description => "List storage IDs.",
parameters => {
additionalProperties => 0,
properties => {},
@@ -229,45 +279,39 @@
type => 'array',
items => {
type => "object",
- properties => {},
+ properties => { storage => { type => 'string' } },
},
-# links => [ { rel => 'child', href => "{storage}" } ],
+ links => [
+ { rel => 'child', href => "{storage}" },
+ ],
},
});
-sub cluster_index {
- my ($conn, $resp, $param) = @_;
+sub list_store_ids {
+ my ($conn, $resp, $param) = @_;
- my $nodes = [ 'node-0', 'node-1', 'node-2', 'node-3' ]; # fixme: use the real list
-
my $cfg = PVE::Config::read_file ("storagecfg");
+ my ($nodeid) = $conn->{rel_uri} =~ m|/([^/]+)$|;
+
+ # fixme: verify nodeid (node exists)?
+
my @sids = PVE::Storage::storage_ids ($cfg);
my $res = [];
foreach my $storeid (@sids) {
- my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
- if ($scfg->{shared}) {
- my $data = { name => $storeid, storage => $storeid, type => $scfg->{type}, shared => 1};
- push @$res, $data;
- } else {
- # we create a entry for each node
- foreach my $node (@$nodes) {
- my $data = { name => "$storeid ($node)", storage => $storeid, node => $node,
- type => $scfg->{type}, shared => 0};
- push @$res, $data;
- }
- }
+ # fixme: check if storeage exists on node ?
+ push @$res, { storage => $storeid };
}
- # $resp->{digest} = $cfg->{digest}; # fixme: how do we handle that
-
return $res;
}
+
__PACKAGE__->register_method ({
name => 'list_content',
protected => 1,
- match_re => [ 'content', '\S+', '\S+' ], # /storage/content/{storeid}/{nodeid}
+ # /storage/content/{nodeid}/{storeid}
+ match_re => [ 'content', '\S+', '\S+' ],
method => 'GET',
description => "List storage content.",
parameters => {
@@ -296,7 +340,7 @@
my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
- my ($storeid, $nodeid) = $conn->{rel_uri} =~ m!/([^/]+)/([^/]+)$!;
+ my ($nodeid, $storeid) = $conn->{rel_uri} =~ m!/([^/]+)/([^/]+)$!;
# fixme: verify $node
@@ -330,15 +374,26 @@
__PACKAGE__->register_method ({
name => 'list_status',
protected => 1,
- match_re => [ 'status', '\S+' ], # /storage/status/{nodeid}
+ # /storage/status/{nodeid}
+ match_re => [ 'status', '\S+' ],
method => 'GET',
- description => "Get storage status.",
+ description => "Get status for all datastores.",
parameters => {
additionalProperties => 0,
properties => {},
},
- returns => {},
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { storage => { type => 'string' } },
+ },
+ links => [
+ { rel => 'child', href => "{storage}" },
+ ],
+ },
});
+
sub list_status {
my ($conn, $resp, $param) = @_;
@@ -346,15 +401,49 @@
my ($nodeid) = $conn->{rel_uri} =~ m!/([^/]+)$!;
- # fixme: verify $node
+ # fixme: verify $nodeid
my $cfg = PVE::Config::read_file ("storagecfg");
+ # fixme: connect to correct node
+
my $info = PVE::Storage::storage_info ($cfg);
- return $info;
+ return PVE::RESTHandler::hash_to_array($info, 'storage');
}
+__PACKAGE__->register_method ({
+ name => 'get_status',
+ protected => 1,
+ # /storage/status/{nodeid}/{storeid}
+ match_re => [ 'status', '\S+', '\S+' ],
+ method => 'GET',
+ description => "Get status for specific datastore.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {},
+});
+sub get_status {
+ my ($conn, $resp, $param) = @_;
+ my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
+
+ my ($nodeid, $storeid) = $conn->{rel_uri} =~ m!/([^/]+)/([^/]+)$!;
+
+ # fixme: verify $nodeid
+
+ my $cfg = PVE::Config::read_file ("storagecfg");
+
+ # fixme: connect to correct node
+
+ my $info = PVE::Storage::storage_info ($cfg);
+
+ return $info->{$storeid};
+}
+
+
+
1;
Modified: pve-manager/pve2/lib/PVE/API2.pm
===================================================================
--- pve-manager/pve2/lib/PVE/API2.pm 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/lib/PVE/API2.pm 2010-07-15 09:57:39 UTC (rev 4901)
@@ -8,6 +8,12 @@
use base qw(PVE::RESTHandler);
+# preload classes
+use PVE::API2::VM;
+use PVE::API2::Cluster;
+use PVE::API2::Storage;
+use PVE::API2::AccessControl;
+
__PACKAGE__->register_method ({
subclass => "PVE::API2::VM",
match_re => [ 'vms' ],
Modified: pve-manager/pve2/lib/PVE/RESTHandler.pm
===================================================================
--- pve-manager/pve2/lib/PVE/RESTHandler.pm 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/lib/PVE/RESTHandler.pm 2010-07-15 09:57:39 UTC (rev 4901)
@@ -138,7 +138,6 @@
$resp->{status} = HTTP_INTERNAL_SERVER_ERROR;
$resp->{errors} = $res->{errors};
- print Dumper($resp);
return $resp->{status};
}
}
@@ -146,4 +145,20 @@
return $resp->{status};
}
+# utility methods
+# note: this modifies the original hash by adding the id property
+sub hash_to_array {
+ my ($hash, $idprop) = @_;
+
+ my $res = [];
+ return $res if !$hash;
+
+ foreach my $k (keys %$hash) {
+ $hash->{$k}->{$idprop} = $k;
+ push @$res, $hash->{$k};
+ }
+
+ return $res;
+}
+
1;
Modified: pve-manager/pve2/www/manager/Makefile.am
===================================================================
--- pve-manager/pve2/www/manager/Makefile.am 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/www/manager/Makefile.am 2010-07-15 09:57:39 UTC (rev 4901)
@@ -4,6 +4,7 @@
../ext/extjs/examples/ux/MultiSelect.js \
../ext/extjs/examples/ux/BufferView.js \
PVEUtils.js \
+ util/base64.js \
data/ObjectReader.js \
data/ObjectStore.js \
data/UpdateStore.js \
Modified: pve-manager/pve2/www/manager/StorageBrowser.js
===================================================================
--- pve-manager/pve2/www/manager/StorageBrowser.js 2010-07-14 12:33:41 UTC (rev 4900)
+++ pve-manager/pve2/www/manager/StorageBrowser.js 2010-07-15 09:57:39 UTC (rev 4901)
@@ -1,19 +1,48 @@
Ext.ns("PVE");
-PVE.StorageStatus = Ext.extend(Ext.Panel, {
+PVE.StorageStatus = Ext.extend(PVE.grid.ObjectView, {
initComponent : function() {
var self = this;
+ var storeid = self.confdata.storage;
+ var node = self.confdata.node;
+
+ if (!storeid)
+ throw "no storage id specified";
+
+ if (!node)
+ throw "no node specified";
+
+ var smid = Ext.util.base64.encode("storage.status." + node + '.' + storeid);
+ var store = Ext.StoreMgr.lookup(smid);
+
+ if (!store) {
+ store = new PVE.data.ObjectStore({
+ url: "/api2/json/storage/status/" + node + "/" + storeid,
+ method: 'GET',
+ id: smid,
+ simpleSelect: true,
+ rows: {
+ total: { header: 'Capacity' },
+ used: { header: 'Used' },
+ free: { header: 'Free' }
+ }
+ });
+ }
+
+ store.load();
+
Ext.apply(self, {
layout: 'fit',
tbar: [
"<b>Status", '->',
{
- text: "Refresh"
+ text: "Refresh",
+ handler: function() { store.load(); }
}
],
- html: "data2345"
+ store: store
});
PVE.StorageStatus.superclass.initComponent.call(self);
@@ -91,6 +120,10 @@
//flex: 1,
},
new PVE.StorageStatus ({
+ confdata: {
+ storage: self.confdata.storage,
+ node: self.confdata.node || 'localhost'
+ },
width: 300
})
]
@@ -143,7 +176,7 @@
}
};
- var smid = "storage.config." + storeid;
+ var smid = Ext.util.base64.encode("storage.config." + storeid);
var store = Ext.StoreMgr.lookup(smid);
var set_visible_tabs = function() {
@@ -175,10 +208,6 @@
});
}
- store.on('load', set_visible_tabs);
-
- store.load();
-
Ext.apply(self, {
title: title,
layout: 'fit',
@@ -224,6 +253,10 @@
]
});
+ store.on('load', set_visible_tabs);
+
+ store.load();
+
PVE.StorageBrowser.superclass.initComponent.call(self);
self.on('destroy', function () {
Added: pve-manager/pve2/www/manager/util/base64.js
===================================================================
--- pve-manager/pve2/www/manager/util/base64.js (rev 0)
+++ pve-manager/pve2/www/manager/util/base64.js 2010-07-15 09:57:39 UTC (rev 4901)
@@ -0,0 +1,52 @@
+
+// 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);
+ }
+ }
+
+};
More information about the pve-devel
mailing list