[pve-devel] [PATCH storage 02/11] Add CIFS Storage Plugin.

Wolfgang Link w.link at proxmox.com
Tue Mar 13 15:11:02 CET 2018


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





More information about the pve-devel mailing list