]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/ISCSIPlugin.pm
fixup error messages when getting file size info
[pve-storage.git] / PVE / Storage / ISCSIPlugin.pm
diff --git a/PVE/Storage/ISCSIPlugin.pm b/PVE/Storage/ISCSIPlugin.pm
deleted file mode 100644 (file)
index e76ccbf..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-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);
-use PVE::Storage::Plugin;
-use PVE::JSONSchema qw(get_standard_option);
-use Net::Ping;
-
-use base qw(PVE::Storage::Plugin);
-
-# iscsi helper function
-
-my $ISCSIADM = '/usr/bin/iscsiadm';
-$ISCSIADM = undef if ! -X $ISCSIADM;
-
-sub check_iscsi_support {
-    my $noerr = shift;
-
-    if (!$ISCSIADM) {
-       my $msg = "no iscsi support - please install open-iscsi";
-       if ($noerr) {
-           warn "warning: $msg\n";
-           return 0;
-       }
-
-       die "error: $msg\n";
-    }
-
-    return 1;
-}
-
-sub iscsi_session_list {
-
-    check_iscsi_support ();
-
-    my $cmd = [$ISCSIADM, '--mode', 'session'];
-
-    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;
-
-       }
-    });
-
-    return $res;
-}
-
-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);
-}
-
-sub iscsi_discovery {
-    my ($portal) = @_;
-
-    check_iscsi_support ();
-
-    my $cmd = [$ISCSIADM, '--mode', 'discovery', '--type', 'sendtargets', 
-              '--portal', $portal];
-
-    my $res = {};
-
-    return $res if !iscsi_test_portal($portal); # fixme: raise exception here?
-
-    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*$/) {
-           my $portal = $1;
-           my $target = $2;
-           # one target can have more than one portal (multipath).
-           push @{$res->{$target}}, $portal;
-       }
-    });
-
-    return $res;
-}
-
-sub iscsi_login {
-    my ($target, $portal_in) = @_;
-
-    check_iscsi_support ();
-
-    eval { iscsi_discovery ($portal_in); };
-    warn $@ if $@;
-
-    my $cmd = [$ISCSIADM, '--mode', 'node', '--targetname',  $target, '--login'];
-    run_command($cmd);
-}
-
-sub iscsi_logout {
-    my ($target, $portal) = @_;
-
-    check_iscsi_support ();
-
-    my $cmd = [$ISCSIADM, '--mode', 'node', '--targetname', $target, '--logout'];
-    run_command($cmd);
-}
-
-my $rescan_filename = "/var/run/pve-iscsi-rescan.lock";
-
-sub iscsi_session_rescan {
-    my $session_list = shift;
-
-    check_iscsi_support();
-
-    my $rstat = stat($rescan_filename);
-
-    if (!$rstat) {
-       if (my $fh = IO::File->new($rescan_filename, "a")) {
-           utime undef, undef, $fh;
-           close($fh);
-       }
-    } else {
-       my $atime = $rstat->atime;
-       my $tdiff = time() - $atime;
-       # avoid frequent rescans
-       return if !($tdiff < 0 || $tdiff > 10);
-       utime undef, undef, $rescan_filename;
-    }
-
-    foreach my $session (@$session_list) {
-       my $cmd = [$ISCSIADM, '--mode', 'session', '-r', $session, '-R'];
-       eval { run_command($cmd, outfunc => sub {}); };
-       warn $@ if $@;
-    }
-}
-
-sub load_stable_scsi_paths {
-
-    my $stable_paths = {};
-
-    my $stabledir = "/dev/disk/by-id";
-
-    if (my $dh = IO::Dir->new($stabledir)) {
-       while (defined(my $tmp = $dh->read)) {
-           # exclude filenames with part in name (same disk but partitions)
-           # 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-/) {
-                 my $path = "$stabledir/$tmp";
-                 my $bdevdest = readlink($path);
-                if ($bdevdest && $bdevdest =~ m|^../../([^/]+)|) {
-                    $stable_paths->{$1}=$tmp;
-                }
-          }
-       }
-       $dh->close;
-    }
-    return $stable_paths;
-}
-
-sub iscsi_device_list {
-
-    my $res = {};
-
-    my $dirname = '/sys/class/iscsi_session';
-
-    my $stable_paths = load_stable_scsi_paths();
-
-    dir_glob_foreach($dirname, 'session(\d+)', sub {
-       my ($ent, $session) = @_;
-
-       my $target = file_read_firstline("$dirname/$ent/targetname");
-       return if !$target;
-
-       my (undef, $host) = dir_glob_regex("$dirname/$ent/device", 'target(\d+):.*');
-       return if !defined($host);
-
-       dir_glob_foreach("/sys/bus/scsi/devices", "$host:" . '(\d+):(\d+):(\d+)', sub {
-           my ($tmp, $channel, $id, $lun) = @_;
-
-           my $type = file_read_firstline("/sys/bus/scsi/devices/$tmp/type");
-           return if !defined($type) || $type ne '0'; # list disks only
-
-           my $bdev;
-           if (-d "/sys/bus/scsi/devices/$tmp/block") { # newer kernels
-               (undef, $bdev) = dir_glob_regex("/sys/bus/scsi/devices/$tmp/block/", '([A-Za-z]\S*)');
-           } else {
-               (undef, $bdev) = dir_glob_regex("/sys/bus/scsi/devices/$tmp", 'block:(\S+)');
-           }
-           return if !$bdev;
-
-           #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;
-           }
-
-           my $blockdev = $stable_paths->{$bdev};
-           return if !$blockdev;
-
-           my $size = file_read_firstline("/sys/block/$bdev/size");
-           return if !$size;
-
-           my $volid = "$channel.$id.$lun.$blockdev";
-
-           $res->{$target}->{$volid} = {
-               '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"; 
-       });
-
-    });
-
-    return $res;
-}
-
-# Configuration
-
-sub type {
-    return 'iscsi';
-}
-
-sub plugindata {
-    return {
-       content => [ {images => 1, none => 1}, { images => 1 }],
-    };
-}
-
-sub properties {
-    return {
-       target => {
-           description => "iSCSI target.",
-           type => 'string',
-       },
-       portal => {
-           description => "iSCSI portal (IP or DNS name with optional port).",
-           type => 'string', format => 'pve-storage-portal-dns',
-       },
-    };
-}
-
-sub options {
-    return {
-        portal => { fixed => 1 },
-        target => { fixed => 1 },
-        nodes => { optional => 1},
-       disable => { optional => 1},
-       content => { optional => 1},
-    };
-}
-
-# Storage implementation
-
-sub parse_volname {
-    my ($class, $volname) = @_;
-
-    if ($volname =~ m!^\d+\.\d+\.\d+\.(\S+)$!) {
-       return ('images', $1, undef);
-    }
-
-    die "unable to parse iscsi volume name '$volname'\n";
-}
-
-sub path {
-    my ($class, $scfg, $volname) = @_;
-
-    my ($vtype, $name, $vmid) = $class->parse_volname($volname);
-    
-    my $path = "/dev/disk/by-id/$name";
-
-    return ($path, $vmid, $vtype);
-}
-
-sub alloc_image {
-    my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
-
-    die "can't allocate space in iscsi storage\n";
-}
-
-sub free_image {
-    my ($class, $storeid, $scfg, $volname) = @_;
-
-    die "can't free space in iscsi storage\n";
-}
-
-sub list_images {
-    my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
-
-    my $res = [];
-
-    $cache->{iscsi_devices} = iscsi_device_list() if !$cache->{iscsi_devices};
-
-    # we have no owner for iscsi devices
-
-    my $target = $scfg->{target};
-
-    if (my $dat = $cache->{iscsi_devices}->{$target}) {
-
-       foreach my $volname (keys %$dat) {
-
-           my $volid = "$storeid:$volname";
-
-           if ($vollist) {
-               my $found = grep { $_ eq $volid } @$vollist;
-               next if !$found;
-           } else {
-               # we have no owner for iscsi devices
-               next if defined($vmid);
-           }
-
-           my $info = $dat->{$volname};
-           $info->{volid} = $volid;
-
-           push @$res, $info;
-       }
-    }
-
-    return $res;
-}
-
-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}});
-
-    return (0, 0, 0, $active);
-}
-
-sub activate_storage {
-    my ($class, $storeid, $scfg, $cache) = @_;
-
-    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)) {
-       eval { iscsi_login($scfg->{target}, $scfg->{portal}); };
-       warn $@ if $@;
-    } else {
-       # make sure we get all devices
-       iscsi_session_rescan($iscsi_sess);
-    }
-}
-
-sub deactivate_storage {
-    my ($class, $storeid, $scfg, $cache) = @_;
-
-    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)) {
-       iscsi_logout($scfg->{target}, $scfg->{portal});
-    }
-}
-
-1;