[pve-devel] [PATCH ZFSPlugin] Add support for creating LXC via this storage type. Only support for Comstar based LUNs currently.

Michael Rasmussen mir at datanom.net
Mon Oct 24 18:10:02 CEST 2016


Signed-off-by: Michael Rasmussen <mir at datanom.net>
---
 PVE/Storage/ZFSPlugin.pm | 209 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 203 insertions(+), 6 deletions(-)

diff --git a/PVE/Storage/ZFSPlugin.pm b/PVE/Storage/ZFSPlugin.pm
index ca25402..f4203c6 100644
--- a/PVE/Storage/ZFSPlugin.pm
+++ b/PVE/Storage/ZFSPlugin.pm
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use IO::File;
 use POSIX;
-use PVE::Tools qw(run_command);
+use PVE::Tools qw(run_command dir_glob_foreach);
 use PVE::Storage::ZFSPoolPlugin;
 use PVE::RPCEnvironment;
 
@@ -13,7 +13,6 @@ use PVE::Storage::LunCmd::Comstar;
 use PVE::Storage::LunCmd::Istgt;
 use PVE::Storage::LunCmd::Iet;
 
-
 my @ssh_opts = ('-o', 'BatchMode=yes');
 my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts);
 my $id_rsa_path = '/etc/pve/priv/zfs';
@@ -155,6 +154,151 @@ sub zfs_get_lun_number {
     return $class->zfs_request($scfg, undef, 'list_view', $guid);
 }
 
+sub os_request {
+	my ($cmd, $noerr, $timeout) = @_;
+
+	$timeout = PVE::RPCEnvironment::is_worker() ? 60*60 : 5 if !$timeout;
+	$noerr = 0 if !$noerr;
+
+    my $text = '';
+
+    my $output = sub {
+        my $line = shift;
+        $text .= "$line\n";
+    };
+
+   	my $exit_code = run_command($cmd, noerr => $noerr, errfunc => $output, outfunc => $output, timeout => $timeout);
+
+    return wantarray ? ($exit_code, $text) : $text;
+}
+
+sub bail_out {
+	my ($class, $storeid, $scfg, $volname, $err) = @_;
+	
+	$class->free_image($storeid, $scfg, $volname);
+	die $err;
+}
+
+sub disk_by_path {
+	my ($scfg, $lun) = @_;
+
+	my $path = "/dev/disk/by-path/ip-$scfg->{portal}:3260-iscsi-$scfg->{target}-lun-$lun";
+
+	return $path;
+}
+
+sub build_lun_list {
+	my ($scfg, $sid) = @_;
+
+	my $luns = {};
+	my $text = '';
+	my $exit = 0;
+
+	eval {
+		($exit, $text) = os_request("iscsiadm -m session -r $sid -P3", 1);
+	};
+	if ($@) {
+		# An exist code of 22 means no active session otherwise an error
+		if ($exit != 22) {
+			die "$@";
+		}
+	}
+	if ($text =~ /.*Host Number:\s*(\d+)\s+State:\s+running(.*)/s) {
+    	my $host = $1;
+    	for (split /^/, $2) {
+        	next unless /Channel\s+(\d+)\s+Id\s+(\d+)\s+Lun:\s+(\d+)/;
+        	$luns->{$3} = "$host:".int($1).":$2:$3";
+    	}
+	}
+
+	return $luns;
+}
+
+sub get_sid {
+	my ($scfg) = @_;
+	my $sid = -1;
+	my $text = '';
+	my $exit = 0;
+	
+	eval {
+		($exit, $text) = os_request("iscsiadm -m node -T $scfg->{target} -p $scfg->{portal} -s", 1);
+	};
+	if ($@) {
+		# An exist code of 21 or 22 means no active session otherwise an error
+		if ($exit != 21 || $exit != 22) {
+			die "$@";
+		}
+	}
+	if ($text =~ /.*\[sid\:\s*(\d+),\s*.*/) {
+		$sid = $1;
+	}
+
+	return $sid;
+}
+
+sub deactivate_luns {
+	# $luns contains a hash of luns to keep
+	my ($scfg, $luns) = @_;
+
+	$luns = {} if !$luns;
+	my $sid;
+	my $list = {};
+
+	eval {		
+		$sid = get_sid($scfg);
+	};
+	die "$@" if @$;
+	return if $sid < 0;
+
+	eval {
+		$list = build_lun_list($scfg, $sid);
+
+		foreach my $key (keys %$list) {
+			next if exists($luns->{$key});
+			os_request("echo 1 > /sys/bus/scsi/devices/$list->{$key}/delete");
+		}
+	};
+	die "$@" if @$;
+}
+
+sub get_active_luns {
+	my ($class, $storeid, $scfg, $volname) = @_;
+
+	my $sid = 0;
+	my $luns = {};
+
+	eval {
+		$sid = get_sid($scfg);
+	};
+	if ($@) {
+		bail_out($class, $storeid, $scfg, $volname, $@);
+	}
+	if ($sid < 0) {
+		# We have no active sessions so make one
+		eval {
+			os_request("iscsiadm -m node -T $scfg->{target} -p $scfg->{portal} --login");
+			$sid = get_sid($scfg);
+		};
+		if ($@) {
+			bail_out($class, $storeid, $scfg, $volname, $@);
+		}
+		# Since no session existed prior to this call deactivate all LUN's found
+		deactivate_luns($scfg);
+	}
+	if ($sid >= 0) {
+		eval {
+			$luns = build_lun_list($scfg, $sid);
+		};
+		if ($@) {
+			bail_out($class, $storeid, $scfg, $volname, $@);
+		}
+	} else {
+		bail_out($class, $storeid, $scfg, $volname, "Missing iscsi session");
+	}
+
+	return $luns;
+}
+
 # Configuration
 
 sub type {
@@ -163,7 +307,7 @@ sub type {
 
 sub plugindata {
     return {
-	content => [ {images => 1}, { images => 1 }],
+	content => [ { images => 1, rootdir => 1 }, { images => 1, rootdir => 1 }],
     };
 }
 
@@ -224,7 +368,11 @@ sub path {
     my $guid = $class->zfs_get_lu_name($scfg, $name);
     my $lun = $class->zfs_get_lun_number($scfg, $guid);
 
-    my $path = "iscsi://$portal/$target/$lun";
+	my $path = disk_by_path($scfg, $lun);
+
+	if (! -l "$path") {
+		$path = "iscsi://$portal/$target/$lun";
+	}
 
     return ($path, $vmid, $vtype);
 }
@@ -374,10 +522,44 @@ sub deactivate_storage {
     return 1;
 }
 
+# Procedure for activating a LXC volume:
+#
+# if session does not exist
+#	login to target
+#	deactivate all luns in session
+# get list of active luns
+# get lun number to activate
+# make list of our luns (active + new lun)
+# rescan session
+# deactivate all luns except our luns
+#
+# Procedure for deactivating a LXC volume:
+# if session exists
+# 	get lun number to deactivate
+#	deactivate lun
+#
 sub activate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
 
-    die "unable to activate snapshot from remote zfs storage" if $snapname;
+    die "mode failure - unable to activate snapshot from remote zfs storage" if $snapname;
+
+	my $active_luns = get_active_luns($class, $storeid, $scfg, $volname);
+
+    my ($vtype, $name, $vmid) = $class->parse_volname($volname);
+    my $guid = $class->zfs_get_lu_name($scfg, $name);
+    my $lun = $class->zfs_get_lun_number($scfg, $guid);
+	$active_luns->{$lun} = "0:0:0:$lun";
+
+	eval {
+		my $sid = get_sid($scfg);
+		if ($sid >= 0) {
+			os_request("iscsiadm -m session -r $sid -R");
+			deactivate_luns($scfg, $active_luns);
+		}
+	};
+	if ($@) {
+		bail_out($class, $storeid, $scfg, $volname, $@);
+	}
 
     return 1;
 }
@@ -385,7 +567,22 @@ sub activate_volume {
 sub deactivate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
 
-    die "unable to deactivate snapshot from remote zfs storage" if $snapname;
+    die "mode failure - unable to deactivate snapshot from remote zfs storage" if $snapname;
+
+	my $active_luns = get_active_luns($class, $storeid, $scfg, $volname);
+    my ($vtype, $name, $vmid) = $class->parse_volname($volname);
+    my $guid = $class->zfs_get_lu_name($scfg, $name);
+    my $lun = $class->zfs_get_lun_number($scfg, $guid);
+	delete $active_luns->{$lun};
+
+	eval {
+		my $sid = get_sid($scfg);
+		if ($sid >= 0) {
+			os_request("iscsiadm -m session -r $sid -R");
+			deactivate_luns($scfg, $active_luns);
+		}
+	};
+	die $@ if $@;
 
     return 1;
 }
-- 
2.1.4


----

This mail was virus scanned and spam checked before delivery.
This mail is also DKIM signed. See header dkim-signature.




More information about the pve-devel mailing list