]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/ISCSIPlugin.pm
Don't remove and recreate lun when changing a volume
[pve-storage.git] / PVE / Storage / ISCSIPlugin.pm
index ef88143a800cc13e7b49cbb8b4b4fc0ac7430d7f..131ffa0f87003c4dbe8318ebda41bc85ed81e512 100644 (file)
@@ -5,10 +5,9 @@ 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);
+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 Net::Ping;
 
 use base qw(PVE::Storage::Plugin);
 
@@ -41,16 +40,20 @@ sub iscsi_session_list {
 
     my $res = {};
 
-    run_command($cmd, outfunc => sub {
-       my $line = shift;
-
-       if ($line =~ m/^tcp:\s+\[(\S+)\]\s+\S+\s+(\S+)\s*$/) {
-           my ($session, $target) = ($1, $2);
-           # there can be several sessions per target (multipath)
-           push @{$res->{$target}}, $session;
-
-       }
-    });
+    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;   
+           }
+       });
+    };
+    if (my $err = $@) {
+       die $err if $err !~ m/: No active sessions.$/i;
+    }
 
     return $res;
 }
@@ -58,10 +61,9 @@ sub iscsi_session_list {
 sub iscsi_test_portal {
     my ($portal) = @_;
 
-    my ($server, $port) = split(':', $portal);
-    my $p = Net::Ping->new("tcp", 2);
-    $p->port_number($port || 3260);
-    return $p->ping($server);
+    my ($server, $port) = PVE::Tools::parse_host_and_port($portal);
+    return 0 if !$server;
+    return PVE::Network::tcp_ping($server, $port || 3260, 2);
 }
 
 sub iscsi_discovery {
@@ -79,7 +81,7 @@ sub iscsi_discovery {
     run_command($cmd, outfunc => sub {
        my $line = shift;
 
-       if ($line =~ m/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+)\,\S+\s+(\S+)\s*$/) {
+       if ($line =~ m/^((?:$IPV4RE|\[$IPV6RE\]):\d+)\,\S+\s+(\S+)\s*$/) {
            my $portal = $1;
            my $target = $2;
            # one target can have more than one portal (multipath).
@@ -134,7 +136,7 @@ sub iscsi_session_rescan {
     }
 
     foreach my $session (@$session_list) {
-       my $cmd = [$ISCSIADM, '--mode', 'session', '-r', $session, '-R'];
+       my $cmd = [$ISCSIADM, '--mode', 'session', '--sid', $session, '--rescan'];
        eval { run_command($cmd, outfunc => sub {}); };
        warn $@ if $@;
     }
@@ -235,6 +237,7 @@ sub type {
 sub plugindata {
     return {
        content => [ {images => 1, none => 1}, { images => 1 }],
+       select_existing => 1,
     };
 }
 
@@ -258,6 +261,7 @@ sub options {
         nodes => { optional => 1},
        disable => { optional => 1},
        content => { optional => 1},
+       bwlimit => { optional => 1 },
     };
 }
 
@@ -267,14 +271,16 @@ sub parse_volname {
     my ($class, $volname) = @_;
 
     if ($volname =~ m!^\d+\.\d+\.\d+\.(\S+)$!) {
-       return ('images', $1, undef);
+       return ('images', $1, undef, undef, undef, undef, 'raw');
     }
 
     die "unable to parse iscsi volume name '$volname'\n";
 }
 
-sub path {
-    my ($class, $scfg, $volname) = @_;
+sub filesystem_path {
+    my ($class, $scfg, $volname, $snapname) = @_;
+
+    die "snapshot is not possible on iscsi storage\n" if defined($snapname);
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
     
@@ -283,6 +289,18 @@ sub path {
     return wantarray ? ($path, $vmid, $vtype) : $path;
 }
 
+sub create_base {
+    my ($class, $storeid, $scfg, $volname) = @_;
+
+    die "can't create base images in iscsi storage\n";
+}
+
+sub clone_image {
+    my ($class, $scfg, $storeid, $volname, $vmid, $snap) = @_;
+
+    die "can't clone images in iscsi storage\n";
+}
+
 sub alloc_image {
     my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
 
@@ -290,7 +308,7 @@ sub alloc_image {
 }
 
 sub free_image {
-    my ($class, $storeid, $scfg, $volname) = @_;
+    my ($class, $storeid, $scfg, $volname, $isBase) = @_;
 
     die "can't free space in iscsi storage\n";
 }
@@ -378,4 +396,31 @@ sub check_connection {
     return iscsi_test_portal($portal);
 }
 
+sub volume_resize {
+    my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
+    die "volume resize is not possible on iscsi device";
+}
+
+sub volume_has_feature {
+    my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
+
+    my $features = {
+       copy => { current => 1},
+    };
+
+    my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
+       $class->parse_volname($volname);
+
+    my $key = undef;
+    if($snapname){
+       $key = 'snap';
+    }else{
+       $key =  $isBase ? 'base' : 'current';
+    }
+    return 1 if $features->{$feature}->{$key};
+
+    return undef;
+}
+
+
 1;