]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/Plugin.pm
Include new storage function volume_snapshot_list.
[pve-storage.git] / PVE / Storage / Plugin.pm
index d65bd11c974d5bccd1078e66e5d72cf3d7b5e417..641ab045a8b85581f6e8b8b72b93f8d4b2c24027 100644 (file)
@@ -24,7 +24,8 @@ my $defaultData = {
            { completion => \&PVE::Storage::complete_storage }),
        nodes => get_standard_option('pve-node-list', { optional => 1 }),
        content => {
-           description => "Allowed content types. Note: value 'rootdir' is used for Containers, and value 'images' for KVM-Qemu VM's.\n",
+           description => "Allowed content types.\n\nNOTE: the value " .
+               "'rootdir' is used for Containers, and value 'images' for VMs.\n",
            type => 'string', format => 'pve-storage-content-list',
            optional => 1,
            completion => \&PVE::Storage::complete_content_type,
@@ -46,7 +47,7 @@ my $defaultData = {
            optional => 1,
        },
        'format' => {
-           description => "Default Image format.",
+           description => "Default image format.",
            type => 'string', format => 'pve-storage-format',
            optional => 1,
        },
@@ -117,6 +118,18 @@ sub verify_server {
     return $server;
 }
 
+PVE::JSONSchema::register_format('pve-storage-vgname', \&parse_lvm_name);
+sub parse_lvm_name {
+    my ($name, $noerr) = @_;
+
+    if ($name !~ m/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i) {
+       return undef if $noerr;
+       die "lvm name '$name' contains illegal characters\n";
+    }
+
+    return $name;
+}
+
 # fixme: do we need this
 #PVE::JSONSchema::register_format('pve-storage-portal', \&verify_portal);
 #sub verify_portal {
@@ -223,7 +236,8 @@ sub decode_value {
 
        foreach my $c (PVE::Tools::split_list($value)) {
            if (!$valid_content->{$c}) {
-               die "storage does not support content type '$c'\n";
+               warn "storage does not support content type '$c'\n";
+               next;
            }
            $res->{$c} = 1;
        }
@@ -237,7 +251,8 @@ sub decode_value {
        my $valid_formats = $def->{format}->[0];
 
        if (!$valid_formats->{$value}) {
-           die "storage does not support format '$value'\n";
+           warn "storage does not support format '$value'\n";
+           next;
        }
 
        return $value;
@@ -429,7 +444,7 @@ sub create_base {
     my ($class, $storeid, $scfg, $volname) = @_;
 
     # this only works for file based storage types
-    die "storage definintion has no path\n" if !$scfg->{path};
+    die "storage definition has no path\n" if !$scfg->{path};
 
     my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
        $class->parse_volname($volname);
@@ -559,7 +574,11 @@ sub alloc_image {
        # only allow this if size = 0, so that user knows what he is doing
        die "storage does not support subvol quotas\n" if $size != 0;
        
-       (mkdir $path) || die "unable to create subvol '$path' - $!\n";
+       my $old_umask = umask(0022);
+       my $err;
+       mkdir($path) or $err = "unable to create subvol '$path' - $!\n";
+       umask $old_umask;
+       die $err if $err;
     } else {
        my $cmd = ['/usr/bin/qemu-img', 'create'];
 
@@ -578,7 +597,13 @@ sub free_image {
 
     my $path = $class->filesystem_path($scfg, $volname);
 
-    if ($format eq 'subvol') {
+    if ($isBase) {
+       # try to remove immutable flag
+       eval { run_command(['/usr/bin/chattr', '-i', $path]); };
+       warn $@ if $@;
+    }
+
+    if (defined($format) && ($format eq 'subvol')) {
        File::Path::remove_tree($path);
     } else {
     
@@ -587,12 +612,6 @@ sub free_image {
            return undef;
        }
 
-       if ($isBase) {
-           # try to remove immutable flag
-           eval { run_command(['/usr/bin/chattr', '-i', $path]); };
-           warn $@ if $@;
-       }
-
        unlink($path) || die "unlink '$path' failed - $!\n";
     }
     
@@ -655,7 +674,9 @@ sub volume_resize {
 
     my $path = $class->filesystem_path($scfg, $volname);
 
-    my $cmd = ['/usr/bin/qemu-img', 'resize', $path , $size];
+    my $format = ($class->parse_volname($volname))[6];
+
+    my $cmd = ['/usr/bin/qemu-img', 'resize', '-f', $format, $path , $size];
 
     run_command($cmd, timeout => 10);
 
@@ -676,6 +697,14 @@ sub volume_snapshot {
     return undef;
 }
 
+sub volume_send {
+    my ($class, $scfg, $storeid, $volname, $ip, $snap,
+       $incremental_snap, $verbose, $limit, $target_path) = @_;
+
+    # implement in subclass
+    die "Volume_send is not implemented for $class";
+}
+
 sub volume_rollback_is_possible {
     my ($class, $scfg, $storeid, $volname, $snap) = @_; 
 
@@ -724,6 +753,8 @@ sub volume_has_feature {
        copy => { base => {qcow2 => 1, raw => 1, vmdk => 1},
                  current => {qcow2 => 1, raw => 1, vmdk => 1},
                  snap => {qcow2 => 1} },
+       sparseinit => { base => {qcow2 => 1, raw => 1, vmdk => 1},
+                       current => {qcow2 => 1, raw => 1, vmdk => 1} },
     };
 
     my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
@@ -801,6 +832,15 @@ sub status {
     return ($res->{total}, $res->{avail}, $res->{used}, 1);
 }
 
+sub volume_snapshot_list {
+    my ($class, $scfg, $storeid, $volname, $prefix, $ip) = @_;
+
+    # implement in subclass
+    die "Volume_snapshot_list is not implemented for $class";
+
+    # retrun an empty array if dataset does not exist.
+}
+
 sub activate_storage {
     my ($class, $storeid, $scfg, $cache) = @_;
 
@@ -811,6 +851,8 @@ sub activate_storage {
     die "unable to activate storage '$storeid' - " .
        "directory '$path' does not exist\n" if ! -d $path;
 
+    return if defined($scfg->{mkdir}) && !$scfg->{mkdir};
+
     if (defined($scfg->{content})) {
        foreach my $vtype (keys %$vtype_subdirs) {
            # OpenVZMigrate uses backup (dump) dir