5
0
mirror of git://git.proxmox.com/git/pve-storage.git synced 2024-12-22 13:34:16 +03:00

imported from svn 'pve-storage/pve2'

This commit is contained in:
Dietmar Maurer 2011-08-23 07:43:03 +02:00
commit b6cf0a6659
15 changed files with 4207 additions and 0 deletions

293
ChangeLog Normal file
View File

@ -0,0 +1,293 @@
2011-08-18 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (iscsi_login): login to target, instead of
portal- to make it work when one portal is offline.
2011-08-15 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (parse_config): fix parser for files without
newline at eof
2011-08-12 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (scan_usb): imp.
2011-08-05 Proxmox Support Team <support@proxmox.com>
* changelog.Debian: increase release number to 2.0-4
* PVE/Storage.pm (iscsi_device_list): return numeric values for
channel/ID/LUN
2011-08-01 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (iscsi_test_portal): factor out code to test if
portal in online (use 2 seconds timeout).
(iscsi_discovery): test if portal is online using
iscsi_test_portal(). This avoids that we run int a timeout (iscsi
default timeout is 15 seconds, we now use 2 seconds)
(cluster_lock_storage): fix cfs_lock_file() arguments,
(lock_storage_config): use default timeout (10)
* PVE/API2/Storage/Config.pm: s/resolv_portal_dns/resolv_portal/
(delete) do not call deactivate_storage(), because we likely run
into timeouts.
* PVE/Storage.pm (resolv_portal_dns): remove duplicate (use resolv_portal instead)
(resolv_portal): use resolv_server()
* PVE/API2/Storage/Scan.pm: remove unneccessary call to resolv_portal_dns()
* PVE/Storage.pm (iscsi_login): use Net::Ping to check portal
availability (avoid long iscsi login timeouts)
(resolv_portal_dns): use resolv_server()
2011-07-29 Proxmox Support Team <support@proxmox.com>
* changelog.Debian: update version to 2.0-3
* PVE/API2/Storage/Config.pm: activate base storage before we try
to create the VG. Make 'nodes' optional.
2011-07-28 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (storage_check_node): check if storage is
available on a specific node.
(storage_check_enabled): check if storage is
available on the local node.
* PVE/API2/Storage/Config.pm (create): add 'nodes' options, do not
activate storage automatically.
* PVE/API2/Storage/Config.pm (update): add 'nodes' options, do not
activate storage automatically.
* pvesm (lock): removed - we do not use the central lock manager
anymore.
* PVE/Storage.pm (vdisk_alloc): use run_command() in order to get
better error messages.
2011-07-27 Proxmox Support Team <support@proxmox.com>
* PVE/API2/Storage/Config.pm (create): add option 'base'
2011-07-26 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (verify_portal_dns): new type
'pve-storage-portal-dns', which allows to use a DNS name.
(resolv_portal_dns): helper to convert portal with DNS name to IP address.
* PVE/API2/Storage/Config.pm: 'target' can be arbitrary string (we
do not check format for now)
* PVE/API2/Storage/Scan.pm (iscsiscan): rename 'server' to 'portal'
2010-11-08 Proxmox Support Team <support@proxmox.com>
* Storage.pm (iscsi_login): multipath fixes: try to log in to all
portals (backport from stable)
2010-10-28 Proxmox Support Team <support@proxmox.com>
* Storage.pm (iscsi_session_list): allow several sessions per
target (multipath)(backport from stable).
(iscsi_session_rescan): rescan all sessions (backport from stable)
2010-09-13 Proxmox Support Team <support@proxmox.com>
* Storage.pm (storage_info): cache VGs, mountdata and iSCSI
session list (backport from stable)
2010-05-06 Proxmox Support Team <support@proxmox.com>
* Storage.pm (storage_migrate): use --sparse and --whole-file,
this alsocreates sparse files (backport from stable)
2011-07-22 Proxmox Support Team <support@proxmox.com>
* PVE/API2/Storage/Scan.pm: split scan into three different
methods with divverent return values
2011-07-21 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (storage_info): do not list disabled storages
2011-05-06 Proxmox Support Team <support@proxmox.com>
* PVE/API2/Storage/Status.pm: impl. content filter
* PVE/Storage.pm (storage_info): include content type
2011-04-04 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (load_stable_scsi_paths): only load
/dev/disk/by-id once (avoid delays when we have many disks)
2011-03-09 Proxmox Support Team <support@proxmox.com>
* pvesm (status): report sizes like 'df'
* PVE/Storage.pm (file_size_info): allow to pass timeout
(important when NFS server is down)
(__activate_storage_full): avoid call to mkpath if not necessary
- avoid hang when NFS server is offline
(storage_info): return sizes in bytes
(storage_info): use PVE::Tools::df with timeout
(lvm_vgs): use '--units b' (report size in bytes)
(lvm_lvs): use '--units b' (report size in bytes)
(file_size_info): report size in bytes
* control.in (Depends): remove libfilesys-df-perl
2011-03-08 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm (__activate_storage_full): avoid to create empty
content config
2011-02-11 Proxmox Support Team <support@proxmox.com>
* PVE/API2/*: cleanup API Object hierarchiy
* PVE/API2/Storage.pm: removed (no longer needed)
2011-01-25 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm: use new cfs_read_file/cfs_write_file everywhere
(cluster filesystem support)
2010-11-08 Proxmox Support Team <support@proxmox.com>
* PVE/Storage.pm: moved hostname read/write to INotify.pm
2010-09-14 Proxmox Support Team <support@proxmox.com>
* pvesm: add/use 'verifyapi' command
* Storage.pm (storage_info): better caching - avoid timeout bug
with large number of VGs.
2010-09-07 Proxmox Support Team <support@proxmox.com>
* Storage.pm (parse_options): renamed from parse_options_new
2010-08-26 Proxmox Support Team <support@proxmox.com>
* Storage.pm (vdisk_list): return full volid instead of volume name.
(template_list): return full volid instead of volume name.
(foreach_volid): re-add, slightly modified
2010-08-25 Proxmox Support Team <support@proxmox.com>
* pvesm: use new PVE::CLIHandler
* PVE/API2/Storage.pm: create extra upload method, because this
have different 'proxy' requirements that normal 'create'
2010-08-24 Proxmox Support Team <support@proxmox.com>
* pvesm: use new PVE::RPCEnvironment
* PVE/API2/*.pm: remove $conn parameter everywhere
2010-08-19 Proxmox Support Team <support@proxmox.com>
* pvesm: more cleanups - use new API calls
2010-08-17 Proxmox Support Team <support@proxmox.com>
* API2::Storage.pm: moved from pve-manager
* split API::Storage into different files
2010-08-16 Proxmox Support Team <support@proxmox.com>
* Storage.pm (file_read_firstline): import from PVE::Tools
* Storage.pm: use new INotify class
* Storage.pm (lock_config): renamed to lock_storage_config, use
lock_file from PVE::Utils
* control.in (Depends): add libpve-common-perl
2010-07-16 Proxmox Support Team <support@proxmox.com>
* Storage.pm (parse_options): added ability to verify a
HASH (needed by REST API)
2010-01-25 Proxmox Support Team <support@proxmox.com>
* Storage.pm (parse_lvm_name, parse_storage_id, parse_volume_id):
fix regex (allow 2 character names)
2010-01-18 Proxmox Support Team <support@proxmox.com>
* Storage.pm (iscsi_device_list): fix for kernel 2.6.32
2009-10-29 Proxmox Support Team <support@proxmox.com>
* Storage.pm (parse_volume_id): ignore case.
2009-10-27 Proxmox Support Team <support@proxmox.com>
* Storage.pm (parse_volume_id): correctly parse storage id.
2009-10-19 Proxmox Support Team <support@proxmox.com>
* Storage.pm (storage_migrate): flush output.
2009-10-08 Proxmox Support Team <support@proxmox.com>
* Storage.pm (path): use parse_volume_id()
(template_list): list backup files too
2009-10-07 Proxmox Support Team <support@proxmox.com>
* Storage.pm (cluster_lock_storage): dont use ssh for local
request (master = localhost)
2009-09-18 Proxmox Support Team <support@proxmox.com>
* Storage.pm (storage_remove): do not remove storage which is used
as base for other storage.
2009-09-04 Proxmox Support Team <support@proxmox.com>
* Storage.pm (lvm_create_volume_group): don't set clustered flag
(vdisk_alloc): a better way to create unique disk names
2009-08-21 Proxmox Support Team <support@proxmox.com>
* Storage.pm (activate_storage_list): only call udevsettle when
there are events. openvz container start/stop sometimes increases
event counter, but deliver no events. So udevsettle simply
hangs. Above optimization eliminate that bug in 99%.
2009-08-20 Proxmox Support Team <support@proxmox.com>
* Storage.pm (cluster_lock_storage): implemented simply central
cluster lock manager.
2009-08-18 Proxmox Support Team <support@proxmox.com>
* Storage.pm (iscsi_session_rescan): do not rescan uscsi too often
(wait at leaset 10 seconds).
(parse_storage_id): allow captial letters.
2009-08-13 Proxmox Support Team <support@proxmox.com>
* Storage.pm: use arrays instead of hash to return lists (SOAP
compatibility)
(foreach_volid): new helper method
(storage_migrate): first try
2009-07-20 Proxmox Support Team <support@proxmox.com>
* Storage.pm (target_is_used): new function
2009-07-03 Proxmox Support Team <support@proxmox.com>
* Storage.pm (activate_storage_list): only call udev settle when
necessary (else it hangs sometimes)

71
Makefile Normal file
View File

@ -0,0 +1,71 @@
RELEASE=2.0
VERSION=2.0
PACKAGE=libpve-storage-perl
PKGREL=4
DESTDIR=
PREFIX=/usr
BINDIR=${PREFIX}/bin
SBINDIR=${PREFIX}/sbin
MANDIR=${PREFIX}/share/man
DOCDIR=${PREFIX}/share/doc
MAN1DIR=${MANDIR}/man1/
export PERLDIR=${PREFIX}/share/perl5
#ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH)
ARCH=all
DEB=${PACKAGE}_${VERSION}-${PKGREL}_${ARCH}.deb
all: ${DEB}
.PHONY: dinstall
dinstall: deb
dpkg -i ${DEB}
.PHONY: install
install:
install -d ${DESTDIR}${SBINDIR}
install -m 0755 pvesm ${DESTDIR}${SBINDIR}
make -C PVE install
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 ${DEB}:
rm -rf debian
mkdir debian
make DESTDIR=${CURDIR}/debian install
perl -I. ./pvesm verifyapi
install -d -m 0755 debian/DEBIAN
sed -e s/@@VERSION@@/${VERSION}/ -e s/@@PKGRELEASE@@/${PKGREL}/ -e s/@@ARCH@@/${ARCH}/ <control.in >debian/DEBIAN/control
install -D -m 0644 copyright debian/${DOCDIR}/${PACKAGE}/copyright
install -m 0644 changelog.Debian debian/${DOCDIR}/${PACKAGE}/
gzip -9 debian/${DOCDIR}/${PACKAGE}/changelog.Debian
install -m 0644 ChangeLog debian/${DOCDIR}/${PACKAGE}/changelog
gzip -9 debian/${DOCDIR}/${PACKAGE}/changelog
dpkg-deb --build debian
mv debian.deb ${DEB}
rm -rf debian
lintian ${DEB}
.PHONY: clean
clean:
rm -rf debian *.deb ${PACKAGE}-*.tar.gz dist
find . -name '*~' -exec rm {} ';'
.PHONY: distclean
distclean: clean
.PHONY: upload
upload: ${DEB}
umount /pve/${RELEASE}; mount /pve/${RELEASE} -o rw
mkdir -p /pve/${RELEASE}/extra
rm -f /pve/${RELEASE}/extra/${PACKAGE}_*.deb
rm -f /pve/${RELEASE}/extra/Packages*
cp ${DEB} /pve/${RELEASE}/extra
cd /pve/${RELEASE}/extra; dpkg-scanpackages . /dev/null > Packages; gzip -9c Packages > Packages.gz
umount /pve/${RELEASE}; mount /pve/${RELEASE} -o ro

5
PVE/API2/Makefile Normal file
View File

@ -0,0 +1,5 @@
.PHONY: install
install:
make -C Storage install

329
PVE/API2/Storage/Config.pm Executable file
View File

@ -0,0 +1,329 @@
package PVE::API2::Storage::Config;
use strict;
use warnings;
use PVE::SafeSyslog;
use PVE::Cluster qw(cfs_read_file cfs_write_file);
use PVE::Storage;
use HTTP::Status qw(:constants);
use Storable qw(dclone);
use PVE::JSONSchema qw(get_standard_option);
use Data::Dumper; # fixme: remove
use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
my @ctypes = qw(images vztmpl iso backup);
my $storage_type_enum = ['dir', 'nfs', 'lvm', 'iscsi'];
my $api_storage_config = sub {
my ($cfg, $storeid) = @_;
my $scfg = dclone(PVE::Storage::storage_config ($cfg, $storeid));
$scfg->{storage} = $storeid;
delete $scfg->{priority};
$scfg->{digest} = $cfg->{digest};
$scfg->{content} = PVE::Storage::content_hash_to_string($scfg->{content});
if ($scfg->{nodes}) {
$scfg->{nodes} = join(',', keys(%{$scfg->{nodes}}));
}
return $scfg;
};
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => "Storage index.",
parameters => {
additionalProperties => 0,
properties => {
type => {
description => "Only list storage of specific type",
type => 'string',
enum => $storage_type_enum,
optional => 1,
},
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => { storage => { type => 'string'} },
},
links => [ { rel => 'child', href => "{storage}" } ],
},
code => sub {
my ($param) = @_;
my $cfg = cfs_read_file("storage.cfg");
my @sids = PVE::Storage::storage_ids($cfg);
my $res = [];
foreach my $storeid (@sids) {
my $scfg = &$api_storage_config($cfg, $storeid);
next if $param->{type} && $param->{type} ne $scfg->{type};
push @$res, $scfg;
}
return $res;
}});
__PACKAGE__->register_method ({
name => 'read',
path => '{storage}',
method => 'GET',
description => "Read storage configuration.",
parameters => {
additionalProperties => 0,
properties => {
storage => get_standard_option('pve-storage-id'),
},
},
returns => {},
code => sub {
my ($param) = @_;
my $cfg = cfs_read_file("storage.cfg");
return &$api_storage_config($cfg, $param->{storage});
}});
__PACKAGE__->register_method ({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new storage.",
parameters => {
additionalProperties => 0,
properties => {
storage => get_standard_option('pve-storage-id'),
nodes => get_standard_option('pve-node-list', { optional => 1 }),
type => {
type => 'string',
enum => $storage_type_enum,
},
path => {
type => 'string', format => 'pve-storage-path',
optional => 1,
},
export => {
type => 'string', format => 'pve-storage-path',
optional => 1,
},
server => {
type => 'string', format => 'pve-storage-server',
optional => 1,
},
options => {
type => 'string', format => 'pve-storage-options',
optional => 1,
},
target => {
type => 'string',
optional => 1,
},
vgname => {
type => 'string', format => 'pve-storage-vgname',
optional => 1,
},
base => {
type => 'string', format => 'pve-volume-id',
optional => 1,
},
portal => {
type => 'string', format => 'pve-storage-portal-dns',
optional => 1,
},
content => {
type => 'string', format => 'pve-storage-content-list',
optional => 1,
},
disable => {
type => 'boolean',
optional => 1,
},
shared => {
type => 'boolean',
optional => 1,
},
'format' => {
type => 'string', format => 'pve-storage-format',
optional => 1,
},
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $type = $param->{type};
delete $param->{type};
my $storeid = $param->{storage};
delete $param->{storage};
if ($param->{portal}) {
$param->{portal} = PVE::Storage::resolv_portal($param->{portal});
}
my $opts = PVE::Storage::parse_options($storeid, $type, $param, 1);
PVE::Storage::lock_storage_config(
sub {
my $cfg = cfs_read_file('storage.cfg');
if (my $scfg = PVE::Storage::storage_config ($cfg, $storeid, 1)) {
die "storage ID '$storeid' already defined\n";
}
$cfg->{ids}->{$storeid} = $opts;
if ($type eq 'lvm' && $opts->{base}) {
my ($baseid, $volname) = PVE::Storage::parse_volume_id ($opts->{base});
my $basecfg = PVE::Storage::storage_config ($cfg, $baseid, 1);
die "base storage ID '$baseid' does not exist\n" if !$basecfg;
# we only support iscsi for now
if (!($basecfg->{type} eq 'iscsi')) {
die "unsupported base type '$basecfg->{type}'";
}
my $path = PVE::Storage::path ($cfg, $opts->{base});
PVE::Storage::activate_storage($cfg, $baseid);
PVE::Storage::lvm_create_volume_group ($path, $opts->{vgname}, $opts->{shared});
}
# try to activate if enabled on local node,
# we only do this to detect errors/problems sooner
if (PVE::Storage::storage_check_enabled($cfg, $storeid, undef, 1)) {
PVE::Storage::activate_storage($cfg, $storeid);
}
cfs_write_file('storage.cfg', $cfg);
}, "create storage failed");
}});
__PACKAGE__->register_method ({
name => 'update',
protected => 1,
path => '{storage}',
method => 'PUT',
description => "Update storage configuration.",
parameters => {
additionalProperties => 0,
properties => {
storage => get_standard_option('pve-storage-id'),
nodes => get_standard_option('pve-node-list', { optional => 1 }),
content => {
type => 'string', format => 'pve-storage-content-list',
optional => 1,
},
'format' => {
type => 'string', format => 'pve-storage-format',
optional => 1,
},
disable => {
type => 'boolean',
optional => 1,
},
shared => {
type => 'boolean',
optional => 1,
},
options => {
type => 'string', format => 'pve-storage-options',
optional => 1,
},
digest => {
type => 'string',
optional => 1,
}
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $storeid = $param->{storage};
delete($param->{storage});
my $digest = $param->{digest};
delete($param->{digest});
PVE::Storage::lock_storage_config(
sub {
my $cfg = cfs_read_file('storage.cfg');
PVE::Storage::assert_if_modified ($cfg, $digest);
my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
my $opts = PVE::Storage::parse_options($storeid, $scfg->{type}, $param);
foreach my $k (%$opts) {
$scfg->{$k} = $opts->{$k};
}
cfs_write_file('storage.cfg', $cfg);
}, "update storage failed");
return undef;
}});
__PACKAGE__->register_method ({
name => 'delete',
protected => 1,
path => '{storage}', # /storage/config/{storage}
method => 'DELETE',
description => "Delete storage configuration.",
parameters => {
additionalProperties => 0,
properties => {
storage => get_standard_option('pve-storage-id'),
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $storeid = $param->{storage};
delete($param->{storage});
PVE::Storage::lock_storage_config(
sub {
my $cfg = cfs_read_file('storage.cfg');
die "can't remove storage - storage is used as base of another storage\n"
if PVE::Storage::storage_is_used ($cfg, $storeid);
delete ($cfg->{ids}->{$storeid});
cfs_write_file('storage.cfg', $cfg);
}, "delete storage failed");
return undef;
}});
1;

257
PVE/API2/Storage/Content.pm Normal file
View File

@ -0,0 +1,257 @@
package PVE::API2::Storage::Content;
use strict;
use warnings;
use PVE::SafeSyslog;
use PVE::Cluster qw(cfs_read_file);
use PVE::Storage;
use PVE::INotify;
use PVE::Exception qw(raise_param_exc);
use PVE::RPCEnvironment;
use PVE::RESTHandler;
use PVE::JSONSchema qw(get_standard_option);
use base qw(PVE::RESTHandler);
my @ctypes = qw(images vztmpl iso backup);
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => "List storage content.",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
content => {
description => "Only list content of this type.",
type => 'string', format => 'pve-storage-content',
optional => 1,
},
vmid => get_standard_option
('pve-vmid', {
description => "Only list images for this VM",
optional => 1,
}),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
volid => {
type => 'string'
}
},
},
links => [ { rel => 'child', href => "{volid}" } ],
},
code => sub {
my ($param) = @_;
my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
my $storeid = $param->{storage};
my $cfg = cfs_read_file("storage.cfg");
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, $param->{vmid});
} elsif ($ct eq 'iso') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'iso')
if !$param->{vmid};
} elsif ($ct eq 'vztmpl') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'vztmpl')
if !$param->{vmid};
} elsif ($ct eq 'backup') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'backup')
if !$param->{vmid};
}
next if !$data || !$data->{$storeid};
foreach my $item (@{$data->{$storeid}}) {
push @$res, $item;
}
}
return $res;
}});
__PACKAGE__->register_method ({
name => 'create',
path => '',
method => 'POST',
description => "Allocate disk images.",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
filename => {
description => "The name of the file to create/upload.",
type => 'string',
},
vmid => get_standard_option('pve-vmid', { description => "Specify owner VM" } ),
size => {
description => "Size in kilobyte (1024 bytes). Optional suffixes 'M' (megabyte, 1024K) and 'G' (gigabyte, 1024M)",
type => 'string',
pattern => '\d+[MG]?',
},
'format' => {
type => 'string',
enum => ['raw', 'qcow2'],
requires => 'size',
optional => 1,
},
},
},
returns => {
description => "Volume identifier",
type => 'string',
},
code => sub {
my ($param) = @_;
my $storeid = $param->{storage};
my $name = $param->{filename};
my $sizestr = $param->{size};
my $size;
if ($sizestr =~ m/^\d+$/) {
$size = $sizestr;
} elsif ($sizestr =~ m/^(\d+)M$/) {
$size = $1 * 1024;
} elsif ($sizestr =~ m/^(\d+)G$/) {
$size = $1 * 1024 * 1024;
} else {
raise_param_exc({ size => "unable to parse size '$sizestr'" });
}
# extract FORMAT from name
if ($name =~ m/\.(raw|qcow2)$/) {
my $fmt = $1;
raise_param_exc({ format => "different storage formats ($param->{format} != $fmt)" })
if $param->{format} && $param->{format} ne $fmt;
$param->{format} = $fmt;
}
my $cfg = cfs_read_file('storage.cfg');
my $volid = PVE::Storage::vdisk_alloc ($cfg, $storeid, $param->{vmid},
$param->{format},
$name, $size);
return $volid;
}});
# we allow to pass volume names (without storage prefix) if the storage
# is specified as separate parameter.
my $real_volume_id = sub {
my ($storeid, $volume) = @_;
my $volid;
if ($volume =~ m/:/) {
eval {
my ($sid, $volname) = PVE::Storage::parse_volume_id ($volume);
raise_param_exc({ storage => "storage ID missmatch" })
if $storeid && $sid ne $storeid;
$volid = $volume;
};
raise_param_exc({ volume => $@}) if $@;
} else {
raise_param_exc({ volume => "no storage speficied - incomplete volume ID" })
if !$storeid;
$volid = "$storeid:$volume";
}
return $volid;
};
__PACKAGE__->register_method ({
name => 'info',
path => '{volume}',
method => 'GET',
description => "Get volume attributes",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id', { optional => 1 }),
volume => {
description => "Volume identifier",
type => 'string',
},
},
},
returns => { type => 'object' },
code => sub {
my ($param) = @_;
my $volid = &$real_volume_id($param->{storage}, $param->{volume});
my $cfg = cfs_read_file('storage.cfg');
my $path = PVE::Storage::path($cfg, $volid);
my ($size, $format, $used) = PVE::Storage::file_size_info ($path);
# fixme: return more attributes?
return {
path => $path,
size => $size,
used => $used,
};
}});
__PACKAGE__->register_method ({
name => 'delete',
path => '{volume}',
method => 'DELETE',
description => "Delete volume",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id', { optional => 1}),
volume => {
description => "Volume identifier",
type => 'string',
},
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $volid = &$real_volume_id($param->{storage}, $param->{volume});
my $cfg = cfs_read_file('storage.cfg');
PVE::Storage::vdisk_free ($cfg, $volid);
return undef;
}});
1;

View File

@ -0,0 +1,6 @@
SOURCES= Content.pm Status.pm Config.pm Scan.pm
.PHONY: install
install:
for i in ${SOURCES}; do install -D -m 0644 $$i ${DESTDIR}${PERLDIR}/PVE/API2/Storage/$$i; done

190
PVE/API2/Storage/Scan.pm Normal file
View File

@ -0,0 +1,190 @@
package PVE::API2::Storage::Scan;
use strict;
use warnings;
use PVE::SafeSyslog;
use PVE::Storage;
use HTTP::Status qw(:constants);
use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => "Index of available scan methods",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => { method => { type => 'string'} },
},
links => [ { rel => 'child', href => "{method}" } ],
},
code => sub {
my ($param) = @_;
my $res = [
{ method => 'lvm' },
{ method => 'iscsi' },
{ method => 'nfs' },
{ method => 'usb' },
];
return $res;
}});
__PACKAGE__->register_method ({
name => 'nfsscan',
path => 'nfs',
method => 'GET',
description => "Scan remote NFS server.",
protected => 1,
proxyto => "node",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
server => { type => 'string', format => 'pve-storage-server' },
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
path => { type => 'string'},
options => { type => 'string'},
},
},
},
code => sub {
my ($param) = @_;
my $server = $param->{server};
my $res = PVE::Storage::scan_nfs($server);
my $data = [];
foreach my $k (keys %$res) {
push @$data, { path => $k, options => $res->{$k} };
}
return $data;
}});
__PACKAGE__->register_method ({
name => 'iscsiscan',
path => 'iscsi',
method => 'GET',
description => "Scan remote iSCSI server.",
protected => 1,
proxyto => "node",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
portal => { type => 'string', format => 'pve-storage-portal-dns' },
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
target => { type => 'string'},
portal => { type => 'string'},
},
},
},
code => sub {
my ($param) = @_;
my $res = PVE::Storage::scan_iscsi($param->{portal});
my $data = [];
foreach my $k (keys %$res) {
push @$data, { target => $k, portal => join(',', @{$res->{$k}}) };
}
return $data;
}});
__PACKAGE__->register_method ({
name => 'lvmscan',
path => 'lvm',
method => 'GET',
description => "List local LVM volume groups.",
protected => 1,
proxyto => "node",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
vg => { type => 'string'},
},
},
},
code => sub {
my ($param) = @_;
my $res = PVE::Storage::lvm_vgs();
return PVE::RESTHandler::hash_to_array($res, 'vg');
}});
__PACKAGE__->register_method ({
name => 'usbscan',
path => 'usb',
method => 'GET',
description => "List local USB devices.",
protected => 1,
proxyto => "node",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
busnum => { type => 'integer'},
devnum => { type => 'integer'},
port => { type => 'integer'},
usbpath => { type => 'string', optional => 1},
level => { type => 'integer'},
class => { type => 'integer'},
vendid => { type => 'string'},
prodid => { type => 'string'},
speed => { type => 'string'},
product => { type => 'string', optional => 1 },
serial => { type => 'string', optional => 1 },
manufacturer => { type => 'string', optional => 1 },
},
},
},
code => sub {
my ($param) = @_;
return PVE::Storage::scan_usb();
}});
1;

228
PVE/API2/Storage/Status.pm Normal file
View File

@ -0,0 +1,228 @@
package PVE::API2::Storage::Status;
use strict;
use warnings;
use PVE::Cluster qw(cfs_read_file);
use PVE::Storage;
use PVE::API2::Storage::Content;
use PVE::RESTHandler;
use PVE::RPCEnvironment;
use PVE::JSONSchema qw(get_standard_option);
use PVE::Exception qw(raise_param_exc);
use base qw(PVE::RESTHandler);
__PACKAGE__->register_method ({
subclass => "PVE::API2::Storage::Content",
# set fragment delimiter (no subdirs) - we need that, because volume
# IDs may contain a slash '/'
fragmentDelimiter => '',
path => '{storage}/content',
});
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => "Get status for all datastores.",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option
('pve-storage-id', {
description => "Only list status for specified storage",
optional => 1,
}),
content => {
description => "Only list stores which support this content type.",
type => 'string', format => 'pve-storage-content',
optional => 1,
},
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => { storage => { type => 'string' } },
},
links => [ { rel => 'child', href => "{storage}" } ],
},
code => sub {
my ($param) = @_;
my $cfg = cfs_read_file("storage.cfg");
my $info = PVE::Storage::storage_info($cfg, $param->{content});
if ($param->{storage}) {
my $data = $info->{$param->{storage}};
raise_param_exc({ storage => "No such storage." })
if !defined($data);
$data->{storage} = $param->{storage};
return [ $data ];
}
return PVE::RESTHandler::hash_to_array($info, 'storage');
}});
__PACKAGE__->register_method ({
name => 'diridx',
path => '{storage}',
method => 'GET',
description => "",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
subdir => { type => 'string' },
},
},
links => [ { rel => 'child', href => "{subdir}" } ],
},
code => sub {
my ($param) = @_;
my $res = [
{ subdir => 'status' },
{ subdir => 'content' },
{ subdir => 'rrd' },
{ subdir => 'rrddata' },
];
return $res;
}});
__PACKAGE__->register_method ({
name => 'read_status',
path => '{storage}/status',
method => 'GET',
description => "Read storage status.",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
},
},
returns => {
type => "object",
properties => {},
},
code => sub {
my ($param) = @_;
my $cfg = cfs_read_file("storage.cfg");
my $info = PVE::Storage::storage_info($cfg, $param->{content});
my $data = $info->{$param->{storage}};
raise_param_exc({ storage => "No such storage." })
if !defined($data);
return $data;
}});
__PACKAGE__->register_method ({
name => 'rrd',
path => '{storage}/rrd',
method => 'GET',
description => "Read storage RRD statistics (returns PNG).",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
timeframe => {
description => "Specify the time frame you are interested in.",
type => 'string',
enum => [ 'hour', 'day', 'week', 'month', 'year' ],
},
ds => {
description => "The list of datasources you want to display.",
type => 'string', format => 'pve-configid-list',
},
cf => {
description => "The RRD consolidation function",
type => 'string',
enum => [ 'AVERAGE', 'MAX' ],
optional => 1,
},
},
},
returns => {
type => "object",
properties => {
filename => { type => 'string' },
},
},
code => sub {
my ($param) = @_;
return PVE::Cluster::create_rrd_graph(
"pve2-storage/$param->{node}/$param->{storage}",
$param->{timeframe}, $param->{ds}, $param->{cf});
}});
__PACKAGE__->register_method ({
name => 'rrddata',
path => '{storage}/rrddata',
method => 'GET',
description => "Read storage RRD statistics.",
protected => 1,
proxyto => 'node',
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
storage => get_standard_option('pve-storage-id'),
timeframe => {
description => "Specify the time frame you are interested in.",
type => 'string',
enum => [ 'hour', 'day', 'week', 'month', 'year' ],
},
cf => {
description => "The RRD consolidation function",
type => 'string',
enum => [ 'AVERAGE', 'MAX' ],
optional => 1,
},
},
},
returns => {
type => "array",
items => {
type => "object",
properties => {},
},
},
code => sub {
my ($param) = @_;
return PVE::Cluster::create_rrd_data(
"pve2-storage/$param->{node}/$param->{storage}",
$param->{timeframe}, $param->{cf});
}});
1;

6
PVE/Makefile Normal file
View File

@ -0,0 +1,6 @@
.PHONY: install
install:
install -D -m 0644 Storage.pm ${DESTDIR}${PERLDIR}/PVE/Storage.pm
make -C API2 install

2360
PVE/Storage.pm Executable file

File diff suppressed because it is too large Load Diff

74
README Normal file
View File

@ -0,0 +1,74 @@
STORAGE Design:
===============
pool: ability to create more than one volume
- directory (NFS server, local dir)
- LVM group
- physical disk (partitions) ??
- ISCSI volume pools ??
- qemu base image ??
a pool can support several formats (raw, qcow2, vmdk, ...)
volume: can be used for VM storage
- block device
- file (raw, qcow2, ...)
- ISCSI LUN
A pool is either shared of local. The resulting volume
inherits that property.
lvs --separator , --noheadings --units b --unbuffered --nosuffix --options "lv_name,uuid,devices,seg_size,vg_extent_size"
pvs --noheadings -o pv_name,vg_name
vgs --separator : --noheadings --units b --unbuffered --nosuffix --options "vg_size,vg_free" VGNAME
What about ISO/template storage?
Storage Configuration:
======================
/etc/pve/storage.shared
/etc/pve/storage.local
oder
/etc/pve/storage.config
mit node attribute for jeden pool.
jedes volume kann einen owner haben (VMID)??
Aus einem pool werden volumes generiert. Jedes volume is einer VMID zugeordnet, entweder
üder den Pfad im filesystem:
$PATH/images/$VMID/xyz.qcow2
oder über lvm tags:
pve-vm-$vmid
Namen müssen pro storage 'unique' sein, daher werden folgende namen verwendet:
vm-$VMID-disk-XXX.$EXT
Nur mit einzigartigen namem kann man kurze storage-id generieren.
store1:vm-100-disk-5
Configuration format:
pool: <POOL_ID>
type <dir|vg>

85
changelog.Debian Normal file
View File

@ -0,0 +1,85 @@
libpve-storage-perl (2.0-4) unstable; urgency=low
* return numeric values for channel/ID/LUN
-- Proxmox Support Team <support@proxmox.com> Fri, 05 Aug 2011 08:46:58 +0200
libpve-storage-perl (2.0-3) unstable; urgency=low
* implemented node restrictions (storage can be restricted to specific
nodes - i.e. DRBD)
-- Proxmox Support Team <support@proxmox.com> Fri, 29 Jul 2011 08:55:11 +0200
libpve-storage-perl (2.0-2) unstable; urgency=low
* backport fixes (multipath, cache) from stable
-- Proxmox Support Team <support@proxmox.com> Mon, 25 Jul 2011 07:02:06 +0200
libpve-storage-perl (2.0-1) unstable; urgency=low
* change copyright to AGPL
-- Proxmox Support Team <support@proxmox.com> Thu, 19 Aug 2010 10:15:46 +0200
libpve-storage-perl (1.0-10) unstable; urgency=low
* fix used space compute
-- Proxmox Support Team <support@proxmox.com> Thu, 11 Feb 2010 10:48:58 +0100
libpve-storage-perl (1.0-9) unstable; urgency=low
* also query used space as suggested by Slavio
-- Proxmox Support Team <support@proxmox.com> Thu, 04 Feb 2010 08:57:02 +0100
libpve-storage-perl (1.0-8) unstable; urgency=low
* also list vmdk files
-- Proxmox Support Team <support@proxmox.com> Mon, 25 Jan 2010 11:52:43 +0100
libpve-storage-perl (1.0-7) unstable; urgency=low
* fix iscsi device detection on kernel 2.6.32
-- Proxmox Support Team <support@proxmox.com> Mon, 18 Jan 2010 13:37:24 +0100
libpve-storage-perl (1.0-6) unstable; urgency=low
* fix bug in parse_volume_id (ignore case)
-- Proxmox Support Team <support@proxmox.com> Thu, 29 Oct 2009 09:22:37 +0100
libpve-storage-perl (1.0-5) unstable; urgency=low
* fix bug in parse_volume_id
-- Proxmox Support Team <support@proxmox.com> Tue, 27 Oct 2009 10:45:49 +0100
libpve-storage-perl (1.0-4) unstable; urgency=low
* new functions to list backup files
-- Proxmox Support Team <support@proxmox.com> Thu, 08 Oct 2009 13:34:45 +0200
libpve-storage-perl (1.0-3) unstable; urgency=low
* new install/delete template functions
-- Proxmox Support Team <support@proxmox.com> Wed, 07 Oct 2009 08:29:55 +0200
libpve-storage-perl (1.0-2) unstable; urgency=low
* do not remove storage which is used as base for other storage.
-- Proxmox Support Team <support@proxmox.com> Fri, 18 Sep 2009 08:05:32 +0200
libpve-storage-perl (1.0-1) unstable; urgency=low
* initial package
-- Proxmox Support Team <support@proxmox.com> Fri, 20 Mar 2009 11:13:19 +0100

9
control.in Normal file
View File

@ -0,0 +1,9 @@
Package: libpve-storage-perl
Version: @@VERSION@@-@@PKGRELEASE@@
Section: perl
Priority: optional
Architecture: @@ARCH@@
Depends: perl (>= 5.6.0-16), nfs-common, udev, libpve-common-perl
Maintainer: Proxmox Support Team <support@proxmox.com>
Description: Proxmox VE storage management library
This package contains the storage management library used by Proxmox VE.

16
copyright Normal file
View File

@ -0,0 +1,16 @@
Copyright (C) 2010 Proxmox Server Solutions GmbH
This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

278
pvesm Executable file
View File

@ -0,0 +1,278 @@
#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use Fcntl ':flock';
use File::Path;
use PVE::SafeSyslog;
use PVE::Cluster;
use PVE::INotify;
use PVE::RPCEnvironment;
use PVE::Storage;
use PVE::API2::Storage::Config;
use PVE::API2::Storage::Content;
use PVE::API2::Storage::Status;
use PVE::API2::Storage::Scan;
use PVE::JSONSchema qw(get_standard_option);
use PVE::CLIHandler;
use base qw(PVE::CLIHandler);
$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
initlog ('pvesm');
die "please run as root\n" if $> != 0;
PVE::INotify::inotify_init();
my $rpcenv = PVE::RPCEnvironment->init('cli');
$rpcenv->init_request();
$rpcenv->set_language($ENV{LANG});
$rpcenv->set_user('root@pam');
__PACKAGE__->register_method ({
name => 'path',
path => 'path',
method => 'GET',
description => "Get filesystem path for specified volume",
parameters => {
additionalProperties => 0,
properties => {
volume => {
description => "Volume identifier",
type => 'string', format => 'pve-volume-id',
},
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $cfg = PVE::Storage::config();
my $path = PVE::Storage::path ($cfg, $param->{volume});
print "$path\n";
return undef;
}});
my $print_content = sub {
my ($list) = @_;
my $maxlenname = 0;
foreach my $info (@$list) {
my $volid = $info->{volid};
my $sidlen = length ($volid);
$maxlenname = $sidlen if $sidlen > $maxlenname;
}
foreach my $info (@$list) {
next if !$info->{vmid};
my $volid = $info->{volid};
printf "%-${maxlenname}s %5s %10d %d\n", $volid,
$info->{format}, $info->{size}, $info->{vmid};
}
foreach my $info (sort { $a->{format} cmp $b->{format} } @$list) {
next if $info->{vmid};
my $volid = $info->{volid};
printf "%-${maxlenname}s %5s %10d\n", $volid,
$info->{format}, $info->{size};
}
};
my $print_status = sub {
my $res = shift;
my $maxlen = 0;
foreach my $res (@$res) {
my $storeid = $res->{storage};
$maxlen = length ($storeid) if length ($storeid) > $maxlen;
}
$maxlen+=1;
foreach my $res (sort { $a->{storage} cmp $b->{storage} } @$res) {
my $storeid = $res->{storage};
my $sum = $res->{used} + $res->{avail};
my $per = $sum ? (0.5 + ($res->{used}*100)/$sum) : 100;
printf "%-${maxlen}s %5s %1d %15d %15d %15d %.2f%%\n", $storeid,
$res->{type}, $res->{active},
$res->{total}/1024, $res->{used}/1024, $res->{avail}/1024, $per;
}
};
my $nodename = PVE::INotify::nodename();
my $cmddef = {
add => [ "PVE::API2::Storage::Config", 'create', ['storage'] ],
set => [ "PVE::API2::Storage::Config", 'update', ['storage'] ],
remove => [ "PVE::API2::Storage::Config", 'delete', ['storage'] ],
status => [ "PVE::API2::Storage::Status", 'index', [],
{ node => $nodename }, $print_status ],
list => [ "PVE::API2::Storage::Content", 'index', ['storage'],
{ node => $nodename }, $print_content ],
alloc => [ "PVE::API2::Storage::Content", 'create', ['storage', 'vmid', 'filename', 'size'],
{ node => $nodename }, sub {
my $volid = shift;
print "sucessfuly created '$volid'\n";
}],
free => [ "PVE::API2::Storage::Content", 'delete', ['volume'],
{ node => $nodename } ],
nfsscan => [ "PVE::API2::Storage::Scan", 'nfsscan', ['server'],
{ node => $nodename }, sub {
my $res = shift;
my $maxlen = 0;
foreach my $rec (@$res) {
my $len = length ($rec->{path});
$maxlen = $len if $len > $maxlen;
}
foreach my $rec (@$res) {
printf "%-${maxlen}s %s\n", $rec->{path}, $rec->{options};
}
}],
iscsiscan => [ "PVE::API2::Storage::Scan", 'iscsiscan', ['server'],
{ node => $nodename }, sub {
my $res = shift;
my $maxlen = 0;
foreach my $rec (@$res) {
my $len = length ($rec->{target});
$maxlen = $len if $len > $maxlen;
}
foreach my $rec (@$res) {
printf "%-${maxlen}s %s\n", $rec->{target}, $rec->{portal};
}
}],
lvmscan => [ "PVE::API2::Storage::Scan", 'lvmscan', [],
{ node => $nodename }, sub {
my $res = shift;
foreach my $rec (@$res) {
printf "$rec->{vg}\n";
}
}],
path => [ __PACKAGE__, 'path', ['volume']],
};
my $cmd = shift;
if ($cmd && $cmd eq 'verifyapi') {
PVE::RESTHandler::validate_method_schemas();
exit 0;
}
PVE::CLIHandler::handle_cmd($cmddef, "pvesm", $cmd, \@ARGV);
exit 0;
__END__
=head1 NAME
pvesm - PVE Storage Manager
=head1 SYNOPSIS
pvesm <COMMAND> [OPTIONS]
# scan iscsi host for available targets
pvesm scan iscsi <HOST[:PORT]>
# scan nfs server for available exports
pvesm scan nfs <HOST>
# add storage pools
pvesm add <STORAGE_ID> <TYPE> <OPTIONS>
pvesm add <STORAGE_ID> dir --path <PATH>
pvesm add <STORAGE_ID> nfs --path <PATH> --server <SERVER> --export <EXPORT>
pvesm add <STORAGE_ID> lvm --vgname <VGNAME>
pvesm add <STORAGE_ID> iscsi --portal <HOST[:PORT]> --target <TARGET>
# disable storage pools
pvesm set <STORAGE_ID> --disable 1
# enable storage pools
pvesm set <STORAGE_ID> --disable 0
# change/set storage options
pvesm set <STORAGE_ID> <OPTIONS>
pvesm set <STORAGE_ID> --shared 1
pvesm set local --format qcow2
pvesm set <STORAGE_ID> --content iso
# remove storage pools - does not delete any data
pvesm remove <STORAGE_ID>
# add single devices??
# alloc volumes
pvesm alloc <STORAGE_ID> <VMID> <name> <size> [--format <raw|qcow2>]
# alloc 4G volume in local storage - use auto generated name
pvesm alloc local <VMID> '' 4G
# free volumes (warning: destroy/deletes all volume data)
pvesm free <VOLUME_ID>
# list storage status
pvesm status
# list storage contents
pvesm list <STORAGE_ID> [--vmid <VMID>]
# list volumes allocated by VMID
pvesm list <STORAGE_ID> --vmid <VMID>
# list iso images
pvesm list <STORAGE_ID> --iso
# list openvz templates
pvesm list <STORAGE_ID> --vztmpl
# show filesystem path for a volume
pvesm path <VOLUME_ID>
# import disks ??
=head1 DESCRIPTION
=head2 Storage pools
Each storage pool is uniquely identified by its <STORAGE_ID>.
=head3 Storage content
A storage can support several content types, for example virtual disk
images, cdrom iso images, openvz templates or openvz root directories
(C<images>, C<iso>, C<vztmpl>, C<rootdir>).
=head2 Volumes
A volume is identified by the <STORAGE_ID>, followed by a storage type
dependent volume name, separated by colon. A valid <VOLUME_ID> looks like:
local:230/example-image.raw
local:iso/debian-501-amd64-netinst.iso
local:vztmpl/debian-5.0-joomla_1.5.9-1_i386.tar.gz
iscsi-storage:0.0.2.scsi-14f504e46494c4500494b5042546d2d646744372d31616d61
To get the filesystem path for a <VOLUME_ID> use:
pvesm path <VOLUME_ID>