[pve-devel] r5022 - pve-storage/pve2
svn-commits at proxmox.com
svn-commits at proxmox.com
Tue Aug 17 09:08:31 CEST 2010
Author: dietmar
Date: 2010-08-17 07:08:31 +0000 (Tue, 17 Aug 2010)
New Revision: 5022
Added:
pve-storage/pve2/API2Storage.pm
Modified:
pve-storage/pve2/ChangeLog
pve-storage/pve2/Makefile
Log:
* API2::Storage.pm: moved from pve-manager
Added: pve-storage/pve2/API2Storage.pm
===================================================================
--- pve-storage/pve2/API2Storage.pm (rev 0)
+++ pve-storage/pve2/API2Storage.pm 2010-08-17 07:08:31 UTC (rev 5022)
@@ -0,0 +1,572 @@
+package PVE::API2::Storage;
+
+# fixme: split things into different files?
+
+# /storage/config GET whole config, CREATE storage
+# /storage/config/{storeid}/ GET/SET storage config
+
+# /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
+
+
+# iso/*.iso
+# vztmpl/*.tgz
+# backup/*.tar
+# images/{vmid}/*.qcow2
+# images/vm-100-test1
+
+use strict;
+use warnings;
+
+use PVE::SafeSyslog;
+use PVE::Inotify qw(read_file write_file);;
+use PVE::Storage;
+use HTTP::Status qw(:constants);
+
+use Data::Dumper; # fixme: remove
+
+use PVE::RESTHandler;
+
+use base qw(PVE::RESTHandler);
+
+my @ctypes = qw(images vztmpl iso backup);
+
+__PACKAGE__->register_method ({
+ name => 'index',
+ path => '', # /storage/
+ method => 'GET',
+ description => "Storage index.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { subdir => { type => 'string'} },
+ },
+ links => [ { rel => 'child', href => "{subdir}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $res = [
+ { subdir => 'config' },
+ { subdir => 'status' },
+ { subdir => 'content' },
+ { subdir => 'index' },
+ { subdir => 'scan' },
+ ];
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'read_config',
+ path => 'config/{storage}',
+ method => 'GET',
+ description => "Read storage configuration.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ storage => { type => 'string' },
+ },
+ },
+ returns => {},
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cfg = read_file ("storagecfg");
+
+ my $scfg = PVE::Storage::storage_config ($cfg, $param->{storage});
+
+ $scfg->{digest} = $cfg->{digest};
+ $scfg->{time} = time(); # fixme: remove
+
+ my @cta;
+ foreach my $ct (keys %{$scfg->{content}}) {
+ push @cta, $ct if $scfg->{content}->{$ct};
+ }
+
+ $scfg->{content} = join(',', @cta);
+
+ return $scfg;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'update_config',
+ protected => 1,
+ path => 'config/{storage}',
+ method => 'PUT',
+ description => "Update storage configuration.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ storage => {
+ type => 'string',
+ },
+ path => {
+ type => 'string',
+ optional => 1,
+ },
+ content => {
+ type => 'string',
+ optional => 1,
+ },
+ disable => {
+ type => 'boolean',
+ optional => 1,
+ },
+ shared => {
+ type => 'boolean',
+ optional => 1,
+ },
+ digest => {
+ type => 'string',
+ optional => 1,
+ }
+ },
+ },
+ returns => { type => 'null' },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $storeid = $param->{storage};
+ delete($param->{storage});
+
+ my $digest = $param->{digest};
+ delete($param->{digest});
+
+ PVE::Storage::storage_set($storeid, $param, $digest);
+
+ return undef;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'list_storage_config',
+ path => 'config', # /storage/config
+ method => 'GET',
+ description => "Storage index.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { storage => { type => 'string'} },
+ },
+ links => [ { rel => 'child', href => "{storage}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cfg = read_file ("storagecfg");
+
+ my @sids = PVE::Storage::storage_ids ($cfg);
+
+ my $res = [];
+ foreach my $storeid (@sids) {
+ my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
+ $scfg->{storage} = $storeid;
+ push @$res, $scfg;
+ }
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'scan_index',
+ path => 'scan',
+ method => 'GET',
+ description => "Index of available scan methods",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { method => { type => 'string'} },
+ },
+ links => [ { rel => 'child', href => "{method}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $res = [
+ { method => 'lvm' },
+ { method => 'iscsi' },
+ { method => 'nfs' },
+ ];
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'scan_server',
+ path => 'scan/{method}',
+ method => 'GET',
+ description => "Scan remote storage server.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ method => {
+ type => 'string',
+ enum => [ 'lvm', 'nfs', 'iscsi' ],
+ }
+ },
+ },
+ returns => {},
+ code => sub {
+ my ($conn, $param) = @_;
+
+ return [];
+ }});
+
+# fixme: move to somewhere else
+__PACKAGE__->register_method ({
+ name => 'cluster_index',
+ path => 'index',
+ method => 'GET',
+ description => "Cluster wide storage status.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+# links => [ { rel => 'child', href => "{storage}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $nodes = [ 'node-0', 'node-1', 'node-2', 'node-3' ]; # fixme: use the real list
+
+ my $cfg = 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',
+ # /storage/(status|content)
+ path => '{subdir}',
+ method => 'GET',
+ description => "List storage nodes.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ subdir => {
+ type => 'string',
+ enum => [ 'status', 'content' ],
+ },
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { node => { type => 'string' } },
+ },
+ links => [ { rel => 'child', href => "{node}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ # fixme: use the real list
+ my $nodes = [
+ { node => 'node-0'},
+ { node => 'node-1'},
+ { node => 'node-2'},
+ { node => 'node-3'},
+ ];
+
+ return $nodes;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'list_store_ids',
+ # /storage/content/{node}/
+ path => 'content/{node}',
+ method => 'GET',
+ description => "List storage IDs.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => {
+ type => 'string',
+ },
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { storage => { type => 'string' } },
+ },
+ links => [ { rel => 'child', href => "{storage}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cfg = read_file ("storagecfg");
+
+ my $node = $param->{node};
+
+ # fixme: verify node (node exists)?
+
+ my @sids = PVE::Storage::storage_ids ($cfg);
+
+ my $res = [];
+ foreach my $storeid (@sids) {
+ # fixme: check if storeage exists on node ?
+ push @$res, { storage => $storeid };
+ }
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'list_content',
+ protected => 1,
+ # /storage/content/{nodeid}/{storeid}
+ path => 'content/{node}/{storage}',
+ method => 'GET',
+ description => "List storage content.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => {
+ type => 'string',
+ },
+ storage => {
+ type => 'string',
+ },
+ content => {
+ type => 'string',
+ enum => [ @ctypes ],
+ optional => 1,
+ }
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ volname => {
+ type => 'string'
+ }
+ },
+ },
+ links => [ { rel => 'child', href => "{volname}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
+
+ my $node = $param->{node};
+ my $storeid = $param->{storage};
+
+ # fixme: verify $node
+
+ my $cfg = read_file ("storagecfg");
+
+ my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
+
+ my $res = [];
+ foreach my $ct (@$cts) {
+ my $data;
+ if ($ct eq 'images') {
+ $data = PVE::Storage::vdisk_list ($cfg, $storeid);
+ } elsif ($ct eq 'iso') {
+ $data = PVE::Storage::template_list ($cfg, $storeid, 'iso');
+ } elsif ($ct eq 'vztmpl') {
+ $data = PVE::Storage::template_list ($cfg, $storeid, 'vztmpl');
+ } elsif ($ct eq 'backup') {
+ $data = PVE::Storage::template_list ($cfg, $storeid, 'backup');
+ }
+
+ next if !$data || !$data->{$storeid};
+
+ foreach my $item (@{$data->{$storeid}}) {
+ push @$res, $item;
+ }
+ }
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'upload_content',
+ # /storage/content/{nodeid}/{storeid}
+ path => 'content/{node}/{storage}',
+ method => 'POST',
+ description => "Upload content.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => {
+ type => 'string',
+ },
+ storage => {
+ type => 'string',
+ },
+ upload => {
+ type => 'string',
+ },
+ },
+ },
+ returns => { type => 'null' },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
+
+ my $node = $param->{node};
+ my $storeid = $param->{storage};
+ my $filename = $param->{upload};
+ my $fh = CGI::upload('upload') || die "unable to get file handle\n";
+
+ syslog ('info', "UPLOAD $filename to $node $storeid");
+
+ die "upload not implemented\n";
+
+ my $buffer = "";
+ my $tmpname = "/tmp/proxmox_upload-$$.bin";
+
+ eval {
+ open FILE, ">$tmpname" || die "can't open temporary file '$tmpname' - $!\n";
+ while (read($fh, $buffer, 32768)) {
+ die "write failed - $!" unless print FILE $buffer;
+ }
+ close FILE || die " can't close temporary file '$tmpname' - $!\n";
+ };
+ my $err = $@;
+
+ if ($err) {
+ unlink $tmpname;
+ die $err;
+ }
+
+ unlink $tmpname; # fixme: proxy to local host import
+
+ return undef;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'list_status',
+ protected => 1,
+ # /storage/status/{nodeid}
+ path => 'status/{node}',
+ method => 'GET',
+ description => "Get status for all datastores.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => {
+ type => 'string',
+ }
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => { storage => { type => 'string' } },
+ },
+ links => [ { rel => 'child', href => "{storage}" } ],
+ },
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
+
+ my $node = $param->{node};
+
+ # fixme: verify $node
+
+ my $cfg = read_file ("storagecfg");
+
+ # fixme: connect to correct node
+
+ my $info = PVE::Storage::storage_info ($cfg);
+
+ return PVE::RESTHandler::hash_to_array($info, 'storage');
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'get_status',
+ protected => 1,
+ # /storage/status/{nodeid}/{storeid}
+ path => 'status/{node}/{storage}',
+ method => 'GET',
+ description => "Get status for specific datastore.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => {
+ type => 'string',
+ },
+ storage => {
+ type => 'string',
+ },
+ },
+ },
+ returns => {},
+ code => sub {
+ my ($conn, $param) = @_;
+
+ my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
+
+ my $node = $param->{node};
+ my $storeid = $param->{storage};
+
+ # fixme: verify $node
+
+ my $cfg = read_file ("storagecfg");
+
+ # fixme: connect to correct node
+
+ my $info = PVE::Storage::storage_info ($cfg);
+
+ return $info->{$storeid};
+ }});
+
+1;
Modified: pve-storage/pve2/ChangeLog
===================================================================
--- pve-storage/pve2/ChangeLog 2010-08-16 12:19:16 UTC (rev 5021)
+++ pve-storage/pve2/ChangeLog 2010-08-17 07:08:31 UTC (rev 5022)
@@ -1,3 +1,7 @@
+2010-08-17 Proxmox Support Team <support at proxmox.com>
+
+ * API2::Storage.pm: moved from pve-manager
+
2010-08-16 Proxmox Support Team <support at proxmox.com>
* Storage.pm (file_read_firstline): import from PVE::Tools
Modified: pve-storage/pve2/Makefile
===================================================================
--- pve-storage/pve2/Makefile 2010-08-16 12:19:16 UTC (rev 5021)
+++ pve-storage/pve2/Makefile 2010-08-17 07:08:31 UTC (rev 5022)
@@ -24,15 +24,16 @@
dinstall: deb
dpkg -i ${DEB}
-install: pvesm Storage.pm
+install: pvesm Storage.pm API2Storage.pm
install -d ${DESTDIR}${SBINDIR}
install -m 0755 pvesm ${DESTDIR}${SBINDIR}
install -D -m 0644 Storage.pm ${DESTDIR}${PERLDIR}/PVE/Storage.pm
+ install -D -m 0644 API2Storage.pm ${DESTDIR}${PERLDIR}/PVE/API2/Storage.pm
install -d ${DESTDIR}/usr/share/man/man1
pod2man -n pvesm -s 1 -r "proxmox 1.0" -c "Proxmox Documentation" <pvesm | gzip -9 > ${DESTDIR}/usr/share/man/man1/pvesm.1.gz
.PHONY: deb
-deb ${DEB}: pvesm Storage.pm control.in copyright changelog.Debian ChangeLog
+deb ${DEB}: pvesm Storage.pm API2Storage.pm control.in copyright changelog.Debian ChangeLog
rm -rf debian
mkdir debian
make DESTDIR=debian install
More information about the pve-devel
mailing list