This Plugin use as template the NFSpluigin. We do only support smbversion 2 and 3. Version 3 is default and must override through the config. --- PVE/Storage/CIFSPlugin.pm | 215 ++++++++++++++++++++++++++++++++++++++++++++++ PVE/Storage/Makefile | 2 +- 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 PVE/Storage/CIFSPlugin.pm
diff --git a/PVE/Storage/CIFSPlugin.pm b/PVE/Storage/CIFSPlugin.pm new file mode 100644 index 0000000..5cf8509 --- /dev/null +++ b/PVE/Storage/CIFSPlugin.pm @@ -0,0 +1,215 @@ +package PVE::Storage::CIFSPlugin; + +use strict; +use warnings; +use Net::IP; +use PVE::Tools qw(run_command); +use PVE::ProcFSTools; +use File::Path; +use PVE::Storage::Plugin; +use PVE::JSONSchema qw(get_standard_option); + +use base qw(PVE::Storage::Plugin); + +# CIFS helper functions + +sub cifs_is_mounted { + my ($server, $share, $mountpoint, $mountdata) = @_; + + $server = "[$server]" if Net::IP::ip_is_ipv6($server); + my $source = "//${server}/$share"; + $mountdata = PVE::ProcFSTools::parse_proc_mounts() if !$mountdata; + + return $mountpoint if grep { + $_->[2] =~ /^cifs/ && + $_->[0] =~ m|^\Q$source\E/?$| && + $_->[1] eq $mountpoint + } @$mountdata; + return undef; +} + +sub get_cred_file { + my ($storeid) = @_; + + my $cred_file = '/etc/pve/priv/'.$storeid.'.cred'; + + if (-e $cred_file) { + return $cred_file; + } + return undef; +} + +sub cifs_mount { + my ($server, $share, $mountpoint, $storeid, $smbver, $user, $domain) = @_; + + $server = "[$server]" if Net::IP::ip_is_ipv6($server); + my $source = "//${server}/$share"; + + my $cmd = ['/bin/mount', '-t', 'cifs', $source, $mountpoint, '-o', 'soft', '-o']; + + if (my $cred_file = get_cred_file($storeid)) { + push @$cmd, "username=$user", '-o', "credentials=$cred_file"; + push @$cmd, '-o', "domain=$domain" if defined($domain); + } else { + push @$cmd, 'guest,username=guest'; + } + + push @$cmd, '-o', defined($smbver) ? "vers=$smbver" : "vers=3.0"; + + run_command($cmd, errmsg => "mount error"); +} + +# Configuration + +sub type { + return 'cifs'; +} + +sub plugindata { + return { + content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, + backup => 1}, { images => 1 }], + format => [ { raw => 1, qcow2 => 1, vmdk => 1 } , 'raw' ], + }; +} + +sub properties { + return { + share => { + description => "CIFS share.", + type => 'string', + }, + password => { + description => "Password for CIFS share.", + type => 'string', + maxLength => 256, + }, + domain => { + description => "CIFS domain.", + type => 'string', + optional => 1, + maxLength => 256, + }, + smbversion => { + description => "", + type => 'string', + optional => 1, + }, + }; +} + +sub options { + return { + path => { fixed => 1 }, + server => { fixed => 1 }, + share => { fixed => 1 }, + nodes => { optional => 1 }, + disable => { optional => 1 }, + maxfiles => { optional => 1 }, + content => { optional => 1 }, + format => { optional => 1 }, + username => { optional => 1 }, + password => { optional => 1}, + domain => { optional => 1}, + smbversion => { optional => 1}, + }; +} + + +sub check_config { + my ($class, $sectionId, $config, $create, $skipSchemaCheck) = @_; + + $config->{path} = "/mnt/pve/$sectionId" if $create && !$config->{path}; + + return $class->SUPER::check_config($sectionId, $config, $create, $skipSchemaCheck); +} + +# Storage implementation + +sub status { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts() + if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server}; + my $share = $scfg->{share}; + + return undef + if !cifs_is_mounted($server, $share, $path, $cache->{mountdata}); + + return $class->SUPER::status($storeid, $scfg, $cache); +} + +sub activate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts() + if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server}; + my $share = $scfg->{share}; + + if (!cifs_is_mounted($server, $share, $path, $cache->{mountdata})) { + + mkpath $path; + + die "unable to activate storage '$storeid' - " . + "directory '$path' does not exist\n" if ! -d $path; + + cifs_mount($server, $share, $path, $storeid, $scfg->{smbversion}, + $scfg->{username}, $scfg->{domain}); + } + + $class->SUPER::activate_storage($storeid, $scfg, $cache); +} + +sub deactivate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = PVE::ProcFSTools::parse_proc_mounts() + if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server}; + my $share = $scfg->{share}; + + if (cifs_is_mounted($server, $share, $path, $cache->{mountdata})) { + my $cmd = ['/bin/umount', $path]; + run_command($cmd, errmsg => 'umount error'); + } +} + +sub check_connection { + my ($class, $storeid, $scfg) = @_; + + my $server = $scfg->{server}; + + my $cmd = ['/usr/bin/smbclient', '-L', $server, '-d', '0', '-m']; + + push @$cmd, $scfg->{smbversion} ? "smb".int($scfg->{smbversion}) : 'smb3'; + + if (my $cred_file = get_cred_file($storeid)) { + push @$cmd, '-U', $scfg->{username}, '-A', $cred_file; + push @$cmd, '-W', $scfg->{domain} if defined($scfg->{domain}); + } else { + push @$cmd, '-U', 'Guest','-N'; + } + + my $out_str; + eval { + run_command($cmd, timeout => 2, outfunc => sub {$out_str .= shift;}, + errfunc => sub {}); + }; + + if (my $err = $@) { + die "$out_str\n" if ($out_str =~ m/NT_STATUS_ACCESS_DENIED/); + return 0; + } + + return 1; +} + +1; diff --git a/PVE/Storage/Makefile b/PVE/Storage/Makefile index b924f21..7b168fa 100644 --- a/PVE/Storage/Makefile +++ b/PVE/Storage/Makefile @@ -1,4 +1,4 @@ -SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm RBDPlugin.pm SheepdogPlugin.pm ISCSIDirectPlugin.pm GlusterfsPlugin.pm ZFSPoolPlugin.pm ZFSPlugin.pm DRBDPlugin.pm LvmThinPlugin.pm +SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm CIFSPlugin.pm ISCSIPlugin.pm RBDPlugin.pm SheepdogPlugin.pm ISCSIDirectPlugin.pm GlusterfsPlugin.pm ZFSPoolPlugin.pm ZFSPlugin.pm DRBDPlugin.pm LvmThinPlugin.pm .PHONY: install install: -- 2.11.0 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel