+ my $vg = $scfg->{vgname};
+
+ # we only deactivate snapshot volumes
+ if ($snapname) {
+ my $snapvol = "snap_${volname}_$snapname";
+ my $cmd = ['/sbin/lvchange', '-an', "$vg/$snapvol"];
+ run_command($cmd, errmsg => "deactivate_volume '$vg/$snapvol' error");
+ } elsif ($volname =~ /^base-/) {
+ my $cmd = ['/sbin/lvchange', '-an', "$vg/$volname"];
+ run_command($cmd, errmsg => "deactivate_volume '$vg/$volname' error");
+ } else {
+ # other volumes are kept active
+ }
+}
+
+sub clone_image {
+ my ($class, $scfg, $storeid, $volname, $vmid, $snap) = @_;
+
+ my $vg = $scfg->{vgname};
+
+ my $lv;
+
+ if ($snap) {
+ $lv = "$vg/snap_${volname}_$snap";
+ } else {
+ my ($vtype, undef, undef, undef, undef, $isBase, $format) =
+ $class->parse_volname($volname);
+
+ die "clone_image only works on base images\n" if !$isBase;
+
+ $lv = "$vg/$volname";
+ }
+
+ my $name = $class->find_free_diskname($storeid, $scfg, $vmid);
+
+ my $cmd = ['/sbin/lvcreate', '-n', $name, '-prw', '-kn', '-s', $lv];
+ run_command($cmd, errmsg => "clone image '$lv' error");
+
+ return $name;
+}
+
+sub create_base {
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
+ $class->parse_volname($volname);
+
+ die "create_base not possible with base image\n" if $isBase;
+
+ my $vg = $scfg->{vgname};
+ my $lvs = PVE::Storage::LVMPlugin::lvm_list_volumes($vg);
+
+ if (my $dat = $lvs->{$vg}) {
+ # to avoid confusion, reject if we find volume snapshots
+ foreach my $lv (keys %$dat) {
+ die "unable to create base volume - found snaphost '$lv'\n"
+ if $lv =~ m/^snap_${volname}_(\w+)$/;
+ }
+ }
+
+ my $newname = $name;
+ $newname =~ s/^vm-/base-/;
+
+ my $cmd = ['/sbin/lvrename', $vg, $volname, $newname];
+ run_command($cmd, errmsg => "lvrename '$vg/$volname' => '$vg/$newname' error");
+
+ # set inactive, read-only and activationskip flags
+ $cmd = ['/sbin/lvchange', '-an', '-pr', '-ky', "$vg/$newname"];
+ eval { run_command($cmd); };
+ warn $@ if $@;
+
+ my $newvolname = $newname;
+
+ return $newvolname;