]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/ISCSIPlugin.pm
pbs: allow setting up a master key
[pve-storage.git] / PVE / Storage / ISCSIPlugin.pm
index aef8675ffb6d53f12482178ea131df1788fca35e..f2694ba7e66df66d93ff8e3b68a914b382761433 100644 (file)
@@ -2,12 +2,14 @@ package PVE::Storage::ISCSIPlugin;
 
 use strict;
 use warnings;
+
 use File::stat;
 use IO::Dir;
 use IO::File;
-use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach $IPV4RE $IPV6RE);
-use PVE::Storage::Plugin;
+
 use PVE::JSONSchema qw(get_standard_option);
+use PVE::Storage::Plugin;
+use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach $IPV4RE $IPV6RE);
 
 use base qw(PVE::Storage::Plugin);
 
@@ -43,11 +45,11 @@ sub iscsi_session_list {
     eval {
        run_command($cmd, errmsg => 'iscsi session scan failed', outfunc => sub {
            my $line = shift;
-           
+
            if ($line =~ m/^tcp:\s+\[(\S+)\]\s+\S+\s+(\S+)(\s+\S+)?\s*$/) {
                my ($session, $target) = ($1, $2);
                # there can be several sessions per target (multipath)
-               push @{$res->{$target}}, $session;   
+               push @{$res->{$target}}, $session;
            }
        });
     };
@@ -71,7 +73,7 @@ sub iscsi_discovery {
 
     check_iscsi_support ();
 
-    my $cmd = [$ISCSIADM, '--mode', 'discovery', '--type', 'sendtargets', 
+    my $cmd = [$ISCSIADM, '--mode', 'discovery', '--type', 'sendtargets',
               '--portal', $portal];
 
     my $res = {};
@@ -149,11 +151,11 @@ sub load_stable_scsi_paths {
     my $stabledir = "/dev/disk/by-id";
 
     if (my $dh = IO::Dir->new($stabledir)) {
-       while (defined(my $tmp = $dh->read)) {
+       foreach my $tmp (sort $dh->read) {
            # exclude filenames with part in name (same disk but partitions)
-           # use only filenames with scsi(with multipath i have the same device 
+           # use only filenames with scsi(with multipath i have the same device
           # with dm-uuid-mpath , dm-name and scsi in name)
-           if($tmp !~ m/-part\d+$/ && $tmp =~ m/^scsi-/) {
+           if($tmp !~ m/-part\d+$/ && ($tmp =~ m/^scsi-/ || $tmp =~ m/^dm-uuid-mpath-/)) {
                  my $path = "$stabledir/$tmp";
                  my $bdevdest = readlink($path);
                 if ($bdevdest && $bdevdest =~ m|^../../([^/]+)|) {
@@ -197,8 +199,8 @@ sub iscsi_device_list {
            }
            return if !$bdev;
 
-           #check multipath           
-           if (-d "/sys/block/$bdev/holders") { 
+           #check multipath
+           if (-d "/sys/block/$bdev/holders") {
                my $multipathdev = dir_glob_regex("/sys/block/$bdev/holders", '[A-Za-z]\S*');
                $bdev = $multipathdev if $multipathdev;
            }
@@ -212,15 +214,15 @@ sub iscsi_device_list {
            my $volid = "$channel.$id.$lun.$blockdev";
 
            $res->{$target}->{$volid} = {
-               'format' => 'raw', 
-               'size' => int($size * 512), 
+               'format' => 'raw',
+               'size' => int($size * 512),
                'vmid' => 0, # not assigned to any vm
                'channel' => int($channel),
                'id' => int($id),
                'lun' => int($lun),
            };
 
-           #print "TEST: $target $session $host,$bus,$tg,$lun $blockdev\n"; 
+           #print "TEST: $target $session $host,$bus,$tg,$lun $blockdev\n";
        });
 
     });
@@ -237,6 +239,7 @@ sub type {
 sub plugindata {
     return {
        content => [ {images => 1, none => 1}, { images => 1 }],
+       select_existing => 1,
     };
 }
 
@@ -260,6 +263,7 @@ sub options {
         nodes => { optional => 1},
        disable => { optional => 1},
        content => { optional => 1},
+       bwlimit => { optional => 1 },
     };
 }
 
@@ -281,7 +285,7 @@ sub filesystem_path {
     die "snapshot is not possible on iscsi storage\n" if defined($snapname);
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
-    
+
     my $path = "/dev/disk/by-id/$name";
 
     return wantarray ? ($path, $vmid, $vtype) : $path;
@@ -311,6 +315,20 @@ sub free_image {
     die "can't free space in iscsi storage\n";
 }
 
+# list all luns regardless of set content_types, since we need it for
+# listing in the gui and we can only have images anyway
+sub list_volumes {
+    my ($class, $storeid, $scfg, $vmid, $content_types) = @_;
+
+    my $res = $class->list_images($storeid, $scfg, $vmid);
+
+    for my $item (@$res) {
+       $item->{content} = 'images'; # we only have images
+    }
+
+    return $res;
+}
+
 sub list_images {
     my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
 
@@ -346,12 +364,17 @@ sub list_images {
     return $res;
 }
 
+sub iscsi_session {
+    my ($cache, $target) = @_;
+    $cache->{iscsi_sessions} = iscsi_session_list() if !$cache->{iscsi_sessions};
+    return $cache->{iscsi_sessions}->{$target};
+}
+
 sub status {
     my ($class, $storeid, $scfg, $cache) = @_;
 
-    $cache->{iscsi_sessions} = iscsi_session_list() if !$cache->{iscsi_sessions};
-
-    my $active = defined($cache->{iscsi_sessions}->{$scfg->{target}});
+    my $session = iscsi_session($cache, $scfg->{target});
+    my $active = defined($session) ? 1 : 0;
 
     return (0, 0, 0, $active);
 }
@@ -361,15 +384,14 @@ sub activate_storage {
 
     return if !check_iscsi_support(1);
 
-    $cache->{iscsi_sessions} = iscsi_session_list() if !$cache->{iscsi_sessions};
+    my $session = iscsi_session($cache, $scfg->{target});
 
-    my $iscsi_sess = $cache->{iscsi_sessions}->{$scfg->{target}};
-    if (!defined ($iscsi_sess)) {
+    if (!defined ($session)) {
        eval { iscsi_login($scfg->{target}, $scfg->{portal}); };
        warn $@ if $@;
     } else {
        # make sure we get all devices
-       iscsi_session_rescan($iscsi_sess);
+       iscsi_session_rescan($session);
     }
 }
 
@@ -378,11 +400,7 @@ sub deactivate_storage {
 
     return if !check_iscsi_support(1);
 
-    $cache->{iscsi_sessions} = iscsi_session_list() if !$cache->{iscsi_sessions};
-
-    my $iscsi_sess = $cache->{iscsi_sessions}->{$scfg->{target}};
-
-    if (defined ($iscsi_sess)) {
+    if (defined(iscsi_session($cache, $scfg->{target}))) {
        iscsi_logout($scfg->{target}, $scfg->{portal});
     }
 }