X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FCLI%2Fpvesm.pm;h=8af4e7fd46bcac53aedfc52ffe187547f1a2d249;hb=5259593842329645e1ebce58e480b0fea0d001ec;hp=771c8810c3ee8cb66113ed50d532bd11861d7538;hpb=668f6d9faffb3b6da8b1957eb3f2c3711dd35e98;p=pve-storage.git diff --git a/PVE/CLI/pvesm.pm b/PVE/CLI/pvesm.pm index 771c881..8af4e7f 100755 --- a/PVE/CLI/pvesm.pm +++ b/PVE/CLI/pvesm.pm @@ -21,8 +21,14 @@ use PVE::CLIHandler; use base qw(PVE::CLIHandler); +my $KNOWN_EXPORT_FORMATS = ['zfs']; + my $nodename = PVE::INotify::nodename(); +sub setup_environment { + PVE::RPCEnvironment->setup_default_cli_env(); +} + __PACKAGE__->register_method ({ name => 'path', path => 'path', @@ -53,6 +59,43 @@ __PACKAGE__->register_method ({ }}); +__PACKAGE__->register_method ({ + name => 'extractconfig', + path => 'extractconfig', + method => 'GET', + description => "Extract configuration from vzdump backup archive.", + permissions => { + description => "The user needs 'VM.Backup' permissions on the backed up guest ID, and 'Datastore.AllocateSpace' on the backup storage.", + user => 'all', + }, + protected => 1, + parameters => { + additionalProperties => 0, + properties => { + volume => { + description => "Volume identifier", + type => 'string', + completion => \&PVE::Storage::complete_volume, + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + my $volume = $param->{volume}; + + my $rpcenv = PVE::RPCEnvironment::get(); + my $authuser = $rpcenv->get_user(); + + my $storage_cfg = PVE::Storage::config(); + PVE::Storage::check_volume_access($rpcenv, $authuser, $storage_cfg, undef, $volume); + + my $config_raw = PVE::Storage::extract_vzdump_config($storage_cfg, $volume); + + print "$config_raw\n"; + return; + }}); + my $print_content = sub { my ($list) = @_; @@ -103,6 +146,152 @@ my $print_status = sub { } }; +__PACKAGE__->register_method ({ + name => 'export', + path => 'export', + method => 'GET', + description => "Export a volume.", + protected => 1, + parameters => { + additionalProperties => 0, + properties => { + volume => { + description => "Volume identifier", + type => 'string', + completion => \&PVE::Storage::complete_volume, + }, + format => { + description => "Export stream format", + type => 'string', + enum => $KNOWN_EXPORT_FORMATS, + }, + filename => { + description => "Destination file name", + type => 'string', + }, + base => { + description => "Snapshot to start an incremental stream from", + type => 'string', + pattern => qr/[a-z0-9_\-]{1,40}/, + maxLength => 40, + optional => 1, + }, + snapshot => { + description => "Snapshot to export", + type => 'string', + pattern => qr/[a-z0-9_\-]{1,40}/, + maxLength => 40, + optional => 1, + }, + 'with-snapshots' => { + description => + "Whether to include intermediate snapshots in the stream", + type => 'boolean', + optional => 1, + default => 0, + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $filename = $param->{filename}; + + my $outfh; + if ($filename eq '-') { + $outfh = \*STDOUT; + } else { + open($outfh, '>', $filename) + or die "open($filename): $!\n"; + } + + eval { + my $cfg = PVE::Storage::config(); + PVE::Storage::volume_export($cfg, $outfh, $param->{volume}, $param->{format}, + $param->{snapshot}, $param->{base}, $param->{'with-snapshots'}); + }; + my $err = $@; + if ($filename ne '-') { + close($outfh); + unlink($filename) if $err; + } + die $err if $err; + return; + } +}); + +__PACKAGE__->register_method ({ + name => 'import', + path => 'import', + method => 'PUT', + description => "Import a volume.", + protected => 1, + parameters => { + additionalProperties => 0, + properties => { + volume => { + description => "Volume identifier", + type => 'string', + completion => \&PVE::Storage::complete_volume, + }, + format => { + description => "Import stream format", + type => 'string', + enum => $KNOWN_EXPORT_FORMATS, + }, + filename => { + description => "Source file name", + type => 'string', + }, + base => { + description => "Base snapshot of an incremental stream", + type => 'string', + pattern => qr/[a-z0-9_\-]{1,40}/, + maxLength => 40, + optional => 1, + }, + 'with-snapshots' => { + description => + "Whether the stream includes intermediate snapshots", + type => 'boolean', + optional => 1, + default => 0, + }, + 'delete-snapshot' => { + description => "A snapshot to delete on success", + type => 'string', + pattern => qr/[a-z0-9_\-]{1,80}/, + maxLength => 80, + optional => 1, + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $filename = $param->{filename}; + + my $infh; + if ($filename eq '-') { + $infh = \*STDIN; + } else { + open($infh, '<', $filename) + or die "open($filename): $!\n"; + } + + my $cfg = PVE::Storage::config(); + my $volume = $param->{volume}; + my $delete = $param->{'delete-snapshot'}; + PVE::Storage::volume_import($cfg, $infh, $volume, $param->{format}, + $param->{base}, $param->{'with-snapshots'}); + PVE::Storage::volume_snapshot_delete($cfg, $volume, $delete) + if defined($delete); + return; + } +}); + our $cmddef = { add => [ "PVE::API2::Storage::Config", 'create', ['type', 'storage'] ], set => [ "PVE::API2::Storage::Config", 'update', ['storage'] ], @@ -114,7 +303,7 @@ our $cmddef = { alloc => [ "PVE::API2::Storage::Content", 'create', ['storage', 'vmid', 'filename', 'size'], { node => $nodename }, sub { my $volid = shift; - print "sucessfuly created '$volid'\n"; + print "successfully created '$volid'\n"; }], free => [ "PVE::API2::Storage::Content", 'delete', ['volume'], { node => $nodename } ], @@ -175,105 +364,9 @@ our $cmddef = { } }], path => [ __PACKAGE__, 'path', ['volume']], + extractconfig => [__PACKAGE__, 'extractconfig', ['volume']], + export => [ __PACKAGE__, 'export', ['volume', 'format', 'filename']], + import => [ __PACKAGE__, 'import', ['volume', 'format', 'filename']], }; 1; - -__END__ - -=head1 NAME - -pvesm - PVE Storage Manager - -=head1 SYNOPSIS - -=include synopsis - -=head1 DESCRIPTION - -=head2 Storage pools - -Each storage pool is uniquely identified by its . - -=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, C, C, C). - -=head2 Volumes - -A volume is identified by the , followed by a storage type -dependent volume name, separated by colon. A valid 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 use: - - pvesm path - - -=head1 EXAMPLES - - # scan iscsi host for available targets - pvesm iscsiscan -portal - - # scan nfs server for available exports - pvesm nfsscan - - # add storage pools - pvesm add - pvesm add dir --path - pvesm add nfs --path --server --export - pvesm add lvm --vgname - pvesm add iscsi --portal --target - - # disable storage pools - pvesm set --disable 1 - - # enable storage pools - pvesm set --disable 0 - - # change/set storage options - pvesm set - pvesm set --shared 1 - pvesm set local --format qcow2 - pvesm set --content iso - - # remove storage pools - does not delete any data - pvesm remove - - # alloc volumes - pvesm alloc [--format ] - - # alloc 4G volume in local storage - use auto generated name - pvesm alloc local '' 4G - - # free volumes (warning: destroy/deletes all volume data) - pvesm free - - # list storage status - pvesm status - - # list storage contents - pvesm list [--vmid ] - - # list volumes allocated by VMID - pvesm list --vmid - - # list iso images - pvesm list --iso - - # list openvz templates - pvesm list --vztmpl - - # show filesystem path for a volume - pvesm path - -=include pve_copyright