use strict;
use warnings;
use IO::File;
+use Net::IP;
use File::Path;
use PVE::Tools qw(run_command);
+use PVE::ProcFSTools;
use PVE::Storage::Plugin;
use PVE::JSONSchema qw(get_standard_option);
# NFS helper functions
-sub read_proc_mounts {
-
- local $/; # enable slurp mode
-
- my $data = "";
- if (my $fd = IO::File->new("/proc/mounts", "r")) {
- $data = <$fd>;
- close ($fd);
- }
-
- return $data;
-}
-
sub nfs_is_mounted {
my ($server, $export, $mountpoint, $mountdata) = @_;
+ $server = "[$server]" if Net::IP::ip_is_ipv6($server);
my $source = "$server:$export";
- $mountdata = read_proc_mounts() if !$mountdata;
-
- if ($mountdata =~ m|^$source/?\s$mountpoint\snfs|m) {
- return $mountpoint;
- }
-
+ $mountdata = PVE::ProcFSTools::parse_proc_mounts() if !$mountdata;
+ return $mountpoint if grep {
+ $_->[2] =~ /^nfs/ &&
+ $_->[0] =~ m|^\Q$source\E/?$| &&
+ $_->[1] eq $mountpoint
+ } @$mountdata;
return undef;
}
sub nfs_mount {
my ($server, $export, $mountpoint, $options) = @_;
+ $server = "[$server]" if Net::IP::ip_is_ipv6($server);
my $source = "$server:$export";
my $cmd = ['/bin/mount', '-t', 'nfs', $source, $mountpoint];
sub plugindata {
return {
- content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, backup => 1},
+ content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, backup => 1, snippets => 1 },
{ images => 1 }],
format => [ { raw => 1, qcow2 => 1, vmdk => 1 } , 'raw' ],
};
path => { fixed => 1 },
server => { fixed => 1 },
export => { fixed => 1 },
- nodes => { optional => 1 },
+ nodes => { optional => 1 },
disable => { optional => 1 },
- maxfiles => { optional => 1 },
+ maxfiles => { optional => 1 },
+ 'prune-backups' => { optional => 1 },
options => { optional => 1 },
content => { optional => 1 },
format => { optional => 1 },
+ mkdir => { optional => 1 },
+ bwlimit => { optional => 1 },
};
}
sub status {
my ($class, $storeid, $scfg, $cache) = @_;
- $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata};
+ $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts()
+ if !$cache->{mountdata};
my $path = $scfg->{path};
my $server = $scfg->{server};
sub activate_storage {
my ($class, $storeid, $scfg, $cache) = @_;
- $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata};
+ $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts()
+ if !$cache->{mountdata};
my $path = $scfg->{path};
my $server = $scfg->{server};
# NOTE: only call mkpath when not mounted (avoid hang
# when NFS server is offline
- mkpath $path;
+ mkpath $path if !(defined($scfg->{mkdir}) && !$scfg->{mkdir});
die "unable to activate storage '$storeid' - " .
"directory '$path' does not exist\n" if ! -d $path;
sub deactivate_storage {
my ($class, $storeid, $scfg, $cache) = @_;
- $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata};
+ $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts()
+ if !$cache->{mountdata};
my $path = $scfg->{path};
my $server = $scfg->{server};
my ($class, $storeid, $scfg) = @_;
my $server = $scfg->{server};
- my $p = Net::Ping->new();
- return $p->ping($server, 2);
+ my $cmd = ['/sbin/showmount', '--no-headers', '--exports', $server];
+
+ eval {
+ run_command($cmd, timeout => 2, outfunc => sub {}, errfunc => sub {});
+ };
+ if (my $err = $@) {
+ return 0;
+ }
+
+ return 1;
}
+
1;