[pve-devel] Custom storage plugins API

Alexander Schmid alex at modula-shop-systems.de
Fri Jan 13 10:55:58 CET 2017

Am 13.01.17 um 10:44 schrieb Dietmar Maurer:
>> I also extended ZFSPlugin to allow access to Snapshots (via zfs snapshot
>> + clone + iSCISI Target on the Clone) and cloning from Snapshots (via
>> send/rcv on a clone). Therefore i had some minor changes in
>> QemuServer.pm to allow this. Any chance these could be taken into one of
>> the next releases ?
> A first step would be to send the code to list (else nobody known what
> you really talk about).
Currently, i only changed qemu_img_convert to allow sort of delegation 
to the storage-plugin. See comments.

This would let the storage-plugin jump-in, in my case zfs send/rcv is 
used in favour of qemu-img convert as it's much faster.

Not sure about the call of deactivate_volume in the end and if it might 
break other storage implementations.

I needed it to do some cleanup on the iscsi-targets that were temporary 
created on the snap.

sub qemu_img_convert {
     my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) 
= @_;

     my $storecfg = PVE::Storage::config();
     my ($src_storeid, $src_volname) = 
PVE::Storage::parse_volume_id($src_volid, 1);
     my ($dst_storeid, $dst_volname) = 
PVE::Storage::parse_volume_id($dst_volid, 1);

     if ($src_storeid && $dst_storeid) {

     PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);

     my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
     my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);

     my $src_format = qemu_img_format($src_scfg, $src_volname);
     my $dst_format = qemu_img_format($dst_scfg, $dst_volname);

     my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
     my $dst_path = PVE::Storage::path($storecfg, $dst_volid);

     #BEGIN addition
     my $src_storage_plugin = 
     my $dst_storage_plugin = 

     # in many cases the storage may have a better idea how to convert:
     # if src and dst format is the same
     # and src_storeid is dst_storeid
     # and the storage has the feature
     # and the feature is implemented as volume_copy / volume_snapshot_copy
     # let the storage do the work as it quite sure is faster
     if ( $src_format eq $dst_format ) {
         if( $src_storeid eq $dst_storeid ) {
             # this is the same storage
             # and storage is capable of materializing snaps
             if( $snapname ) {
                 my $canCopySnap = 
PVE::Storage::volume_has_feature($storecfg, 'copy', $src_volid, 
$snapname, undef) && $src_storage_plugin->can('volume_snapshot_copy');
                 if( $canCopySnap ) {
                     print "delegate to storage plugin 
volume_snapshot_copy (snap $snapname)\n";
$src_storage_plugin->volume_snapshot_copy($src_scfg, $src_volname, 
$snapname, $dst_volname);

$src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, 
$src_volname, $snapname);

                     return 1;

             my $canCopyVolume = 
PVE::Storage::volume_has_feature($storecfg, 'copy', $src_volid, undef, 
undef) && $src_storage_plugin->can('volume_copy');
             if ( $canCopyVolume ) {
                 print "delegate to storage plugin: volume_copy (base)\n";
$src_volname, $dst_volname);

$src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, 
$src_volname, $snapname);

                 return 1;
     #END addition

     my $cmd = [];
     push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
     push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
     push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
     if ($is_zero_initialized) {
         push @$cmd, "zeroinit:$dst_path";
     } else {
         push @$cmd, $dst_path;

     my $parser = sub {
         my $line = shift;
         if($line =~ m/\((\S+)\/100\%\)/){
         my $percent = $1;
         my $transferred = int($size * $percent / 100);
         my $remaining = $size - $transferred;

         print "transferred: $transferred bytes remaining: $remaining 
bytes total: $size bytes progression: $percent %\n";


     eval  { run_command($cmd, timeout => undef, outfunc => $parser); };
     my $err = $@;

     # added: deactivate the src-volume, even on failure
     # this can be safely called as qemu_img_convert is never called on 
a running volume (that is not a snap)
     $src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, 
$src_volname, $snapname);

     die "copy failed: $err" if $err;


More information about the pve-devel mailing list