Signed-off-by: Pablo Ruiz García <pablo.r...@gmail.com> --- PVE/Storage/LunCmd/Comstar.pm | 102 ------- PVE/Storage/LunCmd/Iet.pm | 478 --------------------------------- PVE/Storage/LunCmd/Istgt.pm | 580 ----------------------------------------- PVE/Storage/LunCmd/Makefile | 5 - PVE/Storage/Makefile | 1 - 5 files changed, 0 insertions(+), 1166 deletions(-) delete mode 100644 PVE/Storage/LunCmd/Comstar.pm delete mode 100644 PVE/Storage/LunCmd/Iet.pm delete mode 100644 PVE/Storage/LunCmd/Istgt.pm delete mode 100644 PVE/Storage/LunCmd/Makefile
diff --git a/PVE/Storage/LunCmd/Comstar.pm b/PVE/Storage/LunCmd/Comstar.pm deleted file mode 100644 index 45ad6a5..0000000 --- a/PVE/Storage/LunCmd/Comstar.pm +++ /dev/null @@ -1,102 +0,0 @@ -package PVE::Storage::LunCmd::Comstar; - -use strict; -use warnings; -use Digest::MD5 qw(md5_hex); -use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach); -use Data::Dumper; - -my @ssh_opts = ('-o', 'BatchMode=yes'); -my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts); -my $id_rsa_path = '/etc/pve/priv/zfs'; - -my $get_lun_cmd_map = sub { - my ($method) = @_; - - my $stmfadmcmd = "/usr/sbin/stmfadm"; - my $sbdadmcmd = "/usr/sbin/sbdadm"; - - my $cmdmap = { - create_lu => { cmd => $stmfadmcmd, method => 'create-lu' }, - delete_lu => { cmd => $stmfadmcmd, method => 'delete-lu' }, - import_lu => { cmd => $stmfadmcmd, method => 'import-lu' }, - modify_lu => { cmd => $stmfadmcmd, method => 'modify-lu' }, - add_view => { cmd => $stmfadmcmd, method => 'add-view' }, - list_view => { cmd => $stmfadmcmd, method => 'list-view' }, - list_lu => { cmd => $sbdadmcmd, method => 'list-lu' }, - }; - - die "unknown command '$method'" unless exists $cmdmap->{$method}; - - return $cmdmap->{$method}; -}; - -sub get_base { - return '/dev/zvol/rdsk'; -} - -sub run_lun_command { - my ($scfg, $timeout, $method, @params) = @_; - - my $msg = ''; - my $luncmd; - my $target; - my $guid; - $timeout = 10 if !$timeout; - - my $output = sub { - my $line = shift; - $msg .= "$line\n"; - }; - - if ($method eq 'create_lu') { - my $prefix = '600144f'; - my $digest = md5_hex($params[0]); - $digest =~ /(\w{7}(.*))/; - $guid = "$prefix$2"; - @params = ('-p', 'wcd=false', '-p', "guid=$guid", @params); - } elsif ($method eq 'modify_lu') { - @params = ('-s', @params); - } elsif ($method eq 'list_view') { - @params = ('-l', @params); - } elsif ($method eq 'list_lu') { - $guid = $params[0]; - @params = undef; - } - - my $cmdmap = $get_lun_cmd_map->($method); - $luncmd = $cmdmap->{cmd}; - my $lunmethod = $cmdmap->{method}; - - $target = 'root@' . $scfg->{portal}; - - my $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $luncmd, $lunmethod, @params]; - - run_command($cmd, outfunc => $output, timeout => $timeout); - - if ($method eq 'list_view') { - my @lines = split /\n/, $msg; - $msg = undef; - foreach my $line (@lines) { - if ($line =~ /^\s*LUN\s*:\s*(\d+)$/) { - $msg = $1; - last; - } - } - } elsif ($method eq 'list_lu') { - my $object = $guid; - my @lines = split /\n/, $msg; - $msg = undef; - foreach my $line (@lines) { - if ($line =~ /(\w+)\s+\d+\s+$object$/) { - $msg = $1; - last; - } - } - } elsif ($method eq 'create_lu') { - $msg = $guid; - } - - return $msg; -} - diff --git a/PVE/Storage/LunCmd/Iet.pm b/PVE/Storage/LunCmd/Iet.pm deleted file mode 100644 index 98c062b..0000000 --- a/PVE/Storage/LunCmd/Iet.pm +++ /dev/null @@ -1,478 +0,0 @@ -package PVE::Storage::LunCmd::Iet; - -# iscsi storage running Debian -# 1) apt-get install iscsitarget iscsitarget-dkms -# 2) Create target like (/etc/iet/ietd.conf): -# Target iqn.2001-04.com.example:tank -# Alias tank -# 3) Activate daemon (/etc/default/iscsitarget) -# ISCSITARGET_ENABLE=true -# 4) service iscsitarget start -# -# On one of the proxmox nodes: -# 1) Login as root -# 2) ssh-copy-id <ip_of_iscsi_storage> - -use strict; -use warnings; -use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach); -use Data::Dumper; - -sub get_base; - -# A logical unit can max have 16864 LUNs -# http://manpages.ubuntu.com/manpages/precise/man5/ietd.conf.5.html -my $MAX_LUNS = 16864; - -my $CONFIG_FILE = '/etc/iet/ietd.conf'; -my $DAEMON = '/usr/sbin/ietadm'; -my $SETTINGS = undef; -my $CONFIG = undef; -my $OLD_CONFIG = undef; - -my @ssh_opts = ('-o', 'BatchMode=yes'); -my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts); -my @scp_cmd = ('/usr/bin/scp', @ssh_opts); -my $id_rsa_path = '/etc/pve/priv/zfs'; -my $ietadm = '/usr/sbin/ietadm'; - -my $execute_command = sub { - my ($scfg, $exec, $timeout, $method, @params) = @_; - - my $msg = ''; - my $err = undef; - my $target; - my $cmd; - my $res = (); - - $timeout = 10 if !$timeout; - - my $output = sub { - my $line = shift; - $msg .= "$line\n"; - }; - - my $errfunc = sub { - my $line = shift; - $err .= "$line"; - }; - - $target = 'root@' . $scfg->{portal}; - - if ($exec eq 'scp') { - $cmd = [@scp_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $method, "$target:$params[0]"]; - } else { - $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $method, @params]; - } - - eval { - run_command($cmd, outfunc => $output, errfunc => $errfunc, timeout => $timeout); - }; - if ($@) { - $res = { - result => 0, - msg => $err, - } - } else { - $res = { - result => 1, - msg => $msg, - } - } - - return $res; -}; - -my $read_config = sub { - my ($scfg, $timeout) = @_; - - my $msg = ''; - my $err = undef; - my $luncmd = 'cat'; - my $target; - $timeout = 10 if !$timeout; - - my $output = sub { - my $line = shift; - $msg .= "$line\n"; - }; - - my $errfunc = sub { - my $line = shift; - $err .= "$line"; - }; - - $target = 'root@' . $scfg->{portal}; - - my $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $luncmd, $CONFIG_FILE]; - eval { - run_command($cmd, outfunc => $output, errfunc => $errfunc, timeout => $timeout); - }; - if ($@) { - die $err if ($err !~ /No such file or directory/); - die "No configuration found. Install iet on $scfg->{portal}" if $msg eq ''; - } - - return $msg; -}; - -my $get_config = sub { - my ($scfg) = @_; - my @conf = undef; - - my $config = $read_config->($scfg, undef); - die "Missing config file" unless $config; - - $OLD_CONFIG = $config; - - return $config; -}; - -my $parser = sub { - my ($scfg) = @_; - - my $line = 0; - - my $base = get_base; - my $config = $get_config->($scfg); - my @cfgfile = split "\n", $config; - - my $cfg_target = 0; - foreach (@cfgfile) { - $line++; - if ($_ =~ /^\s*Target\s*([\w\-\:\.]+)\s*$/) { - if ($1 eq $scfg->{target} && ! $cfg_target) { - # start colect info - die "$line: Parse error [$_]" if $SETTINGS; - $SETTINGS->{target} = $1; - $cfg_target = 1; - } elsif ($1 eq $scfg->{target} && $cfg_target) { - die "$line: Parse error [$_]"; - } elsif ($cfg_target) { - $cfg_target = 0; - $CONFIG .= "$_\n"; - } else { - $CONFIG .= "$_\n"; - } - } else { - if ($cfg_target) { - $SETTINGS->{text} .= "$_\n"; - next if ($_ =~ /^\s*#/ || ! $_); - my $option = $_; - if ($_ =~ /^(\w+)\s*#/) { - $option = $1; - } - if ($option =~ /^\s*(\w+)\s+(\w+)\s*$/) { - if ($1 eq 'Lun') { - die "$line: Parse error [$_]"; - } - $SETTINGS->{$1} = $2; - } elsif ($option =~ /^\s*(\w+)\s+(\d+)\s+([\w\-\/=,]+)\s*$/) { - die "$line: Parse error [$option]" unless ($1 eq 'Lun'); - my $conf = undef; - my $num = $2; - my @lun = split ',', $3; - die "$line: Parse error [$option]" unless (scalar(@lun) > 1); - foreach (@lun) { - my @lun_opt = split '=', $_; - die "$line: Parse error [$option]" unless (scalar(@lun_opt) == 2); - $conf->{$lun_opt[0]} = $lun_opt[1]; - } - if ($conf->{Path} && $conf->{Path} =~ /^$base\/$scfg->{pool}\/([\w\-]+)$/) { - $conf->{include} = 1; - } else { - $conf->{include} = 0; - } - $conf->{lun} = $num; - push @{$SETTINGS->{luns}}, $conf; - } else { - die "$line: Parse error [$option]"; - } - } else { - $CONFIG .= "$_\n"; - } - } - } - $CONFIG =~ s/^\s+|\s+$|"\s*//g; -}; - -my $update_config = sub { - my ($scfg) = @_; - my $file = "/tmp/config$$"; - my $config = ''; - - while ((my $option, my $value) = each(%$SETTINGS)) { - next if ($option eq 'include' || $option eq 'luns' || $option eq 'Path' || $option eq 'text' || $option eq 'used'); - if ($option eq 'target') { - $config = "\n\nTarget " . $SETTINGS->{target} . "\n" . $config; - } else { - $config .= "\t$option\t\t\t$value\n"; - } - } - foreach my $lun (@{$SETTINGS->{luns}}) { - my $lun_opt = ''; - while ((my $option, my $value) = each(%$lun)) { - next if ($option eq 'include' || $option eq 'lun' || $option eq 'Path'); - if ($lun_opt eq '') { - $lun_opt = $option . '=' . $value; - } else { - $lun_opt .= ',' . $option . '=' . $value; - } - } - $config .= "\tLun $lun->{lun} Path=$lun->{Path},$lun_opt\n"; - } - open(my $fh, '>', $file) or die "Could not open file '$file' $!"; - - print $fh $CONFIG; - print $fh $config; - close $fh; - - my @params = ($CONFIG_FILE); - my $res = $execute_command->($scfg, 'scp', undef, $file, @params); - unlink $file; - - die $res->{msg} unless $res->{result}; -}; - -my $get_target_tid = sub { - my ($scfg) = @_; - my $proc = '/proc/net/iet/volume'; - my $tid = undef; - - my @params = ($proc); - my $res = $execute_command->($scfg, 'ssh', undef, 'cat', @params); - die $res->{msg} unless $res->{result}; - my @cfg = split "\n", $res->{msg}; - - foreach (@cfg) { - if ($_ =~ /^\s*tid:(\d+)\s+name:([\w\-\:\.]+)\s*$/) { - if ($2 && $2 eq $scfg->{target}) { - $tid = $1; - last; - } - } - } - - return $tid; -}; - -my $get_lu_name = sub { - my $used = (); - my $i; - - if (! exists $SETTINGS->{used}) { - for ($i = 0; $i < $MAX_LUNS; $i++) { - $used->{$i} = 0; - } - foreach my $lun (@{$SETTINGS->{luns}}) { - $used->{$lun->{lun}} = 1; - } - $SETTINGS->{used} = $used; - } - - $used = $SETTINGS->{used}; - for ($i = 0; $i < $MAX_LUNS; $i++) { - last unless $used->{$i}; - } - $SETTINGS->{used}->{$i} = 1; - - return $i; -}; - -my $init_lu_name = sub { - my $used = (); - - if (! exists($SETTINGS->{used})) { - for (my $i = 0; $i < $MAX_LUNS; $i++) { - $used->{$i} = 0; - } - $SETTINGS->{used} = $used; - } - foreach my $lun (@{$SETTINGS->{luns}}) { - $SETTINGS->{used}->{$lun->{lun}} = 1; - } -}; - -my $free_lu_name = sub { - my ($lu_name) = @_; - my $new; - - foreach my $lun (@{$SETTINGS->{luns}}) { - if ($lun->{lun} != $lu_name) { - push @$new, $lun; - } - } - - $SETTINGS->{luns} = $new; - $SETTINGS->{used}->{$lu_name} = 0; -}; - -my $make_lun = sub { - my ($scfg, $path) = @_; - - die 'Maximum number of LUNs per target is 16384' if scalar @{$SETTINGS->{luns}} >= $MAX_LUNS; - - my $lun = $get_lu_name->(); - my $conf = { - lun => $lun, - Path => $path, - Type => 'blockio', - include => 1, - }; - push @{$SETTINGS->{luns}}, $conf; - - return $conf; -}; - -my $list_view = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $lun = undef; - - my $object = $params[0]; - foreach my $lun (@{$SETTINGS->{luns}}) { - next unless $lun->{include} == 1; - if ($lun->{Path} =~ /^$object$/) { - return $lun->{lun} if (defined($lun->{lun})); - die "$lun->{Path}: Missing LUN"; - } - } - - return $lun; -}; - -my $list_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $name = undef; - - my $object = $params[0]; - foreach my $lun (@{$SETTINGS->{luns}}) { - next unless $lun->{include} == 1; - if ($lun->{Path} =~ /^$object$/) { - return $lun->{Path}; - } - } - - return $name; -}; - -my $create_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - - if ($list_lun->($scfg, $timeout, $method, @params)) { - die "$params[0]: LUN exists"; - } - my $lun = $params[0]; - $lun = $make_lun->($scfg, $lun); - my $tid = $get_target_tid->($scfg); - $update_config->($scfg); - - my $path = "Path=$lun->{Path},Type=$lun->{Type}"; - - @params = ('--op', 'new', "--tid=$tid", "--lun=$lun->{lun}", '--params', $path); - my $res = $execute_command->($scfg, 'ssh', $timeout, $ietadm, @params); - do { - $free_lu_name->($lun->{lun}); - $update_config->($scfg); - die $res->{msg}; - } unless $res->{result}; - - return $res->{msg}; -}; - -my $delete_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $res = {msg => undef}; - - my $path = $params[0]; - my $tid = $get_target_tid->($scfg); - - foreach my $lun (@{$SETTINGS->{luns}}) { - if ($lun->{Path} eq $path) { - @params = ('--op', 'delete', "--tid=$tid", "--lun=$lun->{lun}"); - $res = $execute_command->($scfg, 'ssh', $timeout, $ietadm, @params); - if ($res->{result}) { - $free_lu_name->($lun->{lun}); - $update_config->($scfg); - last; - } else { - die $res->{msg}; - } - } - } - - return $res->{msg}; -}; - -my $import_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - - return $create_lun->($scfg, $timeout, $method, @params); -}; - -my $modify_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $lun; - my $res; - - my $path = $params[1]; - my $tid = $get_target_tid->($scfg); - - foreach my $cfg (@{$SETTINGS->{luns}}) { - if ($cfg->{Path} eq $path) { - $lun = $cfg; - last; - } - } - - @params = ('--op', 'delete', "--tid=$tid", "--lun=$lun->{lun}"); - $res = $execute_command->($scfg, 'ssh', $timeout, $ietadm, @params); - die $res->{msg} unless $res->{result}; - - $path = "Path=$lun->{Path},Type=$lun->{Type}"; - @params = ('--op', 'new', "--tid=$tid", "--lun=$lun->{lun}", '--params', $path); - $res = $execute_command->($scfg, 'ssh', $timeout, $ietadm, @params); - die $res->{msg} unless $res->{result}; - - return $res->{msg}; -}; - -my $add_view = sub { - my ($scfg, $timeout, $method, @params) = @_; - - return ''; -}; - -my $get_lun_cmd_map = sub { - my ($method) = @_; - - my $cmdmap = { - create_lu => { cmd => $create_lun }, - delete_lu => { cmd => $delete_lun }, - import_lu => { cmd => $import_lun }, - modify_lu => { cmd => $modify_lun }, - add_view => { cmd => $add_view }, - list_view => { cmd => $list_view }, - list_lu => { cmd => $list_lun }, - }; - - die "unknown command '$method'" unless exists $cmdmap->{$method}; - - return $cmdmap->{$method}; -}; - -sub run_lun_command { - my ($scfg, $timeout, $method, @params) = @_; - - $parser->($scfg) unless $SETTINGS; - my $cmdmap = $get_lun_cmd_map->($method); - my $msg = $cmdmap->{cmd}->($scfg, $timeout, $method, @params); - - return $msg; -} - -sub get_base { - return '/dev'; -} - -1; - diff --git a/PVE/Storage/LunCmd/Istgt.pm b/PVE/Storage/LunCmd/Istgt.pm deleted file mode 100644 index 9bbdfa0..0000000 --- a/PVE/Storage/LunCmd/Istgt.pm +++ /dev/null @@ -1,580 +0,0 @@ -package PVE::Storage::LunCmd::Istgt; - -# TODO -# Create initial target and LUN if target is missing ? -# Create and use list of free LUNs - -use strict; -use warnings; -use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach); -use Data::Dumper; - -my @CONFIG_FILES = ( - '/usr/local/etc/istgt/istgt.conf', # FreeBSD, FreeNAS - '/var/etc/iscsi/istgt.conf' # NAS4Free -); -my @DAEMONS = ( - '/usr/local/etc/rc.d/istgt', # FreeBSD, FreeNAS - '/var/etc/rc.d/istgt' # NAS4Free -); - -# A logical unit can max have 63 LUNs -# https://code.google.com/p/istgt/source/browse/src/istgt_lu.h#39 -my $MAX_LUNS = 64; - -my $CONFIG_FILE = undef; -my $DAEMON = undef; -my $SETTINGS = undef; -my $CONFIG = undef; -my $OLD_CONFIG = undef; - -my @ssh_opts = ('-o', 'BatchMode=yes'); -my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts); -my @scp_cmd = ('/usr/bin/scp', @ssh_opts); -my $id_rsa_path = '/etc/pve/priv/zfs'; - -#Current SIGHUP reload limitations (http://www.peach.ne.jp/archives/istgt/): -# -# The parameters other than PG, IG, and LU are not reloaded by SIGHUP. -# LU connected by the initiator can't be reloaded by SIGHUP. -# PG and IG mapped to LU can't be deleted by SIGHUP. -# If you delete an active LU, all connections of the LU are closed by SIGHUP. -# Updating IG is not affected until the next login. -# -# FreeBSD -# 1. Alt-F2 to change to native shell (zfsguru) -# 2. pw mod user root -w yes (change password for root to root) -# 3. vi /etc/ssh/sshd_config -# 4. uncomment PermitRootLogin yes -# 5. change PasswordAuthentication no to PasswordAuthentication yes -# 5. /etc/rc.d/sshd restart -# 6. On one of the proxmox nodes login as root and run: ssh-copy-id ip_freebsd_host -# 7. vi /etc/ssh/sshd_config -# 8. comment PermitRootLogin yes -# 9. change PasswordAuthentication yes to PasswordAuthentication no -# 10. /etc/rc.d/sshd restart -# 11. Reset passwd -> pw mod user root -w no -# 12. Alt-Ctrl-F1 to return to zfsguru shell (zfsguru) - -sub get_base; -sub run_lun_command; - -my $read_config = sub { - my ($scfg, $timeout, $method) = @_; - - my $msg = ''; - my $err = undef; - my $luncmd = 'cat'; - my $target; - $timeout = 10 if !$timeout; - - my $output = sub { - my $line = shift; - $msg .= "$line\n"; - }; - - my $errfunc = sub { - my $line = shift; - $err .= "$line"; - }; - - $target = 'root@' . $scfg->{portal}; - - my $daemon = 0; - foreach my $config (@CONFIG_FILES) { - $err = undef; - my $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $luncmd, $config]; - eval { - run_command($cmd, outfunc => $output, errfunc => $errfunc, timeout => $timeout); - }; - do { - $err = undef; - $DAEMON = $DAEMONS[$daemon]; - $CONFIG_FILE = $config; - last; - } unless $@; - $daemon++; - } - die $err if ($err && $err !~ /No such file or directory/); - die "No configuration found. Install istgt on $scfg->{portal}" if $msg eq ''; - - return $msg; -}; - -my $get_config = sub { - my ($scfg) = @_; - my @conf = undef; - - my $config = $read_config->($scfg, undef, 'get_config'); - die "Missing config file" unless $config; - - $OLD_CONFIG = $config; - - return $config; -}; - -my $parse_size = sub { - my ($text) = @_; - - return 0 if !$text; - - if ($text =~ m/^(\d+(\.\d+)?)([TGMK]B)?$/) { - my ($size, $reminder, $unit) = ($1, $2, $3); - return $size if !$unit; - if ($unit eq 'KB') { - $size *= 1024; - } elsif ($unit eq 'MB') { - $size *= 1024*1024; - } elsif ($unit eq 'GB') { - $size *= 1024*1024*1024; - } elsif ($unit eq 'TB') { - $size *= 1024*1024*1024*1024; - } - if ($reminder) { - $size = ceil($size); - } - return $size; - } elsif ($text =~ /^auto$/i) { - return 'AUTO'; - } else { - return 0; - } -}; - -my $size_with_unit = sub { - my ($size, $n) = (shift, 0); - - return '0KB' if !$size; - - return $size if $size eq 'AUTO'; - - if ($size =~ m/^\d+$/) { - ++$n and $size /= 1024 until $size < 1024; - if ($size =~ /\./) { - return sprintf "%.2f%s", $size, ( qw[bytes KB MB GB TB] )[ $n ]; - } else { - return sprintf "%d%s", $size, ( qw[bytes KB MB GB TB] )[ $n ]; - } - } - die "$size: Not a number"; -}; - -my $lun_dumper = sub { - my ($lun) = @_; - my $config = ''; - - $config .= "\n[$lun]\n"; - $config .= 'TargetName ' . $SETTINGS->{$lun}->{TargetName} . "\n"; - $config .= 'Mapping ' . $SETTINGS->{$lun}->{Mapping} . "\n"; - $config .= 'AuthGroup ' . $SETTINGS->{$lun}->{AuthGroup} . "\n"; - $config .= 'UnitType ' . $SETTINGS->{$lun}->{UnitType} . "\n"; - $config .= 'QueueDepth ' . $SETTINGS->{$lun}->{QueueDepth} . "\n"; - - foreach my $conf (@{$SETTINGS->{$lun}->{luns}}) { - $config .= "$conf->{lun} Storage " . $conf->{Storage}; - $config .= ' ' . $size_with_unit->($conf->{Size}) . "\n"; - } - $config .= "\n"; - - return $config; -}; - -my $get_lu_name = sub { - my ($target) = @_; - my $used = (); - my $i; - - if (! exists $SETTINGS->{$target}->{used}) { - for ($i = 0; $i < $MAX_LUNS; $i++) { - $used->{$i} = 0; - } - foreach my $lun (@{$SETTINGS->{$target}->{luns}}) { - $lun->{lun} =~ /^LUN(\d+)$/; - $used->{$1} = 1; - } - $SETTINGS->{$target}->{used} = $used; - } - - $used = $SETTINGS->{$target}->{used}; - for ($i = 0; $i < $MAX_LUNS; $i++) { - last unless $used->{$i}; - } - $SETTINGS->{$target}->{used}->{$i} = 1; - - return "LUN$i"; -}; - -my $init_lu_name = sub { - my ($target) = @_; - my $used = (); - - if (! exists($SETTINGS->{$target}->{used})) { - for (my $i = 0; $i < $MAX_LUNS; $i++) { - $used->{$i} = 0; - } - $SETTINGS->{$target}->{used} = $used; - } - foreach my $lun (@{$SETTINGS->{$target}->{luns}}) { - $lun->{lun} =~ /^LUN(\d+)$/; - $SETTINGS->{$target}->{used}->{$1} = 1; - } -}; - -my $free_lu_name = sub { - my ($target, $lu_name) = @_; - - $lu_name =~ /^LUN(\d+)$/; - $SETTINGS->{$target}->{used}->{$1} = 0; -}; - -my $make_lun = sub { - my ($path) = @_; - - my $target = $SETTINGS->{current}; - die 'Maximum number of LUNs per target is 63' if scalar @{$SETTINGS->{$target}->{luns}} >= $MAX_LUNS; - - my $lun = $get_lu_name->($target); - my $conf = { - lun => $lun, - Storage => $path, - Size => 'AUTO', - }; - push @{$SETTINGS->{$target}->{luns}}, $conf; - - return $conf->{lun}; -}; - -my $parser = sub { - my ($scfg) = @_; - - my $lun = undef; - my $line = 0; - - my $config = $get_config->($scfg); - my @cfgfile = split "\n", $config; - - foreach (@cfgfile) { - $line++; - if ($_ =~ /^\s*\[(PortalGroup\d+)\]\s*/) { - $lun = undef; - $SETTINGS->{$1} = (); - } elsif ($_ =~ /^\s*\[(InitiatorGroup\d+)\]\s*/) { - $lun = undef; - $SETTINGS->{$1} = (); - } elsif ($_ =~ /^\s*PidFile\s+"?([\w\/\.]+)"?\s*/) { - $lun = undef; - $SETTINGS->{pidfile} = $1; - } elsif ($_ =~ /^\s*NodeBase\s+"?([\w\-\.]+)"?\s*/) { - $lun = undef; - $SETTINGS->{nodebase} = $1; - } elsif ($_ =~ /^\s*\[(LogicalUnit\d+)\]\s*/) { - $lun = $1; - $SETTINGS->{$lun} = (); - $SETTINGS->{targets}++; - } elsif ($lun) { - next if (($_ =~ /^\s*#/) || ($_ =~ /^\s*$/)); - if ($_ =~ /^\s*(\w+)\s+(.+)\s*/) { - #next if $2 =~ /^Option.*/; - $SETTINGS->{$lun}->{$1} = $2; - $SETTINGS->{$lun}->{$1} =~ s/^\s+|\s+$|"\s*//g; - } else { - die "$line: parse error [$_]"; - } - } - $CONFIG .= "$_\n" unless $lun; - } - - $CONFIG =~ s/\n$//; - die "$scfg->{target}: Target not found" unless $SETTINGS->{targets}; - my $max = $SETTINGS->{targets}; - my $base = get_base; - - for (my $i = 1; $i <= $max; $i++) { - my $target = $SETTINGS->{nodebase}.':'.$SETTINGS->{"LogicalUnit$i"}->{TargetName}; - if ($target eq $scfg->{target}) { - my $lu = (); - while ((my $key, my $val) = each(%{$SETTINGS->{"LogicalUnit$i"}})) { - if ($key =~ /^LUN\d+/) { - if ($val =~ /^Storage\s+([\w\/\-]+)\s+(\w+)/) { - my $storage = $1; - my $size = $parse_size->($2); - my $conf = undef; - if ($storage =~ /^$base\/$scfg->{pool}\/([\w\-]+)$/) { - $conf = { - lun => $key, - Storage => $storage, - Size => $size, - }; - } - push @$lu, $conf if $conf; - } - delete $SETTINGS->{"LogicalUnit$i"}->{$key}; - } - } - $SETTINGS->{"LogicalUnit$i"}->{luns} = $lu; - $SETTINGS->{current} = "LogicalUnit$i"; - $init_lu_name->("LogicalUnit$i"); - } else { - $CONFIG .= $lun_dumper->("LogicalUnit$i"); - delete $SETTINGS->{"LogicalUnit$i"}; - $SETTINGS->{targets}--; - } - } - die "$scfg->{target}: Target not found" unless $SETTINGS->{targets} > 0; -}; - -my $list_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $name = undef; - - my $object = $params[0]; - for my $key (keys %$SETTINGS) { - next unless $key =~ /^LogicalUnit\d+$/; - foreach my $lun (@{$SETTINGS->{$key}->{luns}}) { - if ($lun->{Storage} =~ /^$object$/) { - return $lun->{Storage}; - } - } - } - - return $name; -}; - -my $create_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $res = (); - my $file = "/tmp/config$$"; - - if ($list_lun->($scfg, $timeout, $method, @params)) { - die "$params[0]: LUN exists"; - } - my $lun = $params[0]; - $lun = $make_lun->($lun); - my $config = $lun_dumper->($SETTINGS->{current}); - open(my $fh, '>', $file) or die "Could not open file '$file' $!"; - - print $fh $CONFIG; - print $fh $config; - close $fh; - @params = ($CONFIG_FILE); - $res = { - cmd => 'scp', - method => $file, - params => \@params, - msg => $lun, - post_exe => sub { - unlink $file; - }, - }; - - return $res; -}; - -my $delete_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $res = (); - my $file = "/tmp/config$$"; - - my $target = $SETTINGS->{current}; - my $luns = (); - - foreach my $conf (@{$SETTINGS->{$target}->{luns}}) { - if ($conf->{Storage} =~ /^$params[0]$/) { - $free_lu_name->($target, $conf->{lun}); - } else { - push @$luns, $conf; - } - } - $SETTINGS->{$target}->{luns} = $luns; - - my $config = $lun_dumper->($SETTINGS->{current}); - open(my $fh, '>', $file) or die "Could not open file '$file' $!"; - - print $fh $CONFIG; - print $fh $config; - close $fh; - @params = ($CONFIG_FILE); - $res = { - cmd => 'scp', - method => $file, - params => \@params, - post_exe => sub { - unlink $file; - run_lun_command($scfg, undef, 'add_view', 'restart'); - }, - }; - - return $res; -}; - -my $import_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - - my $res = $create_lun->($scfg, $timeout, $method, @params); - - return $res; -}; - -my $add_view = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $cmdmap; - - if (@params && $params[0] eq 'restart') { - @params = ('restart', '1>&2', '>', '/dev/null'); - $cmdmap = { - cmd => 'ssh', - method => $DAEMON, - params => \@params, - }; - } else { - @params = ('-HUP', '$(cat '. "$SETTINGS->{pidfile})"); - $cmdmap = { - cmd => 'ssh', - method => 'kill', - params => \@params, - }; - } - - return $cmdmap; -}; - -my $modify_lun = sub { - my ($scfg, $timeout, $method, @params) = @_; - - # Current SIGHUP reload limitations - # LU connected by the initiator can't be reloaded by SIGHUP. - # Until above limitation persists modifying a LUN will require - # a restart of the daemon breaking all current connections - #die 'Modify a connected LUN is not currently supported by istgt'; - @params = ('restart', @params); - - return $add_view->($scfg, $timeout, $method, @params); -}; - -my $list_view = sub { - my ($scfg, $timeout, $method, @params) = @_; - my $lun = undef; - - my $object = $params[0]; - for my $key (keys %$SETTINGS) { - next unless $key =~ /^LogicalUnit\d+$/; - foreach my $lun (@{$SETTINGS->{$key}->{luns}}) { - if ($lun->{Storage} =~ /^$object$/) { - if ($lun->{lun} =~ /^LUN(\d+)/) { - return $1; - } - die "$lun->{Storage}: Missing LUN"; - } - } - } - - return $lun; -}; - -my $get_lun_cmd_map = sub { - my ($method) = @_; - - my $cmdmap = { - create_lu => { cmd => $create_lun }, - delete_lu => { cmd => $delete_lun }, - import_lu => { cmd => $import_lun }, - modify_lu => { cmd => $modify_lun }, - add_view => { cmd => $add_view }, - list_view => { cmd => $list_view }, - list_lu => { cmd => $list_lun }, - }; - - die "unknown command '$method'" unless exists $cmdmap->{$method}; - - return $cmdmap->{$method}; -}; - -sub run_lun_command { - my ($scfg, $timeout, $method, @params) = @_; - - my $msg = ''; - my $luncmd; - my $target; - my $cmd; - my $res; - $timeout = 10 if !$timeout; - my $is_add_view = 0; - - my $output = sub { - my $line = shift; - $msg .= "$line\n"; - }; - - $target = 'root@' . $scfg->{portal}; - - $parser->($scfg) unless $SETTINGS; - my $cmdmap = $get_lun_cmd_map->($method); - if ($method eq 'add_view') { - $is_add_view = 1 ; - $timeout = 15; - } - if (ref $cmdmap->{cmd} eq 'CODE') { - $res = $cmdmap->{cmd}->($scfg, $timeout, $method, @params); - if (ref $res) { - $method = $res->{method}; - @params = @{$res->{params}}; - if ($res->{cmd} eq 'scp') { - $cmd = [@scp_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $method, "$target:$params[0]"]; - } else { - $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $method, @params]; - } - } else { - return $res; - } - } else { - $luncmd = $cmdmap->{cmd}; - $method = $cmdmap->{method}; - $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target, $luncmd, $method, @params]; - } - - eval { - run_command($cmd, outfunc => $output, timeout => $timeout); - }; - if ($@ && $is_add_view) { - my $err = $@; - if ($OLD_CONFIG) { - my $err1 = undef; - my $file = "/tmp/config$$"; - open(my $fh, '>', $file) or die "Could not open file '$file' $!"; - print $fh $OLD_CONFIG; - close $fh; - $cmd = [@scp_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $file, $CONFIG_FILE]; - eval { - run_command($cmd, outfunc => $output, timeout => $timeout); - }; - $err1 = $@ if $@; - unlink $file; - die "$err\n$err1" if $err1; - eval { - run_lun_command($scfg, undef, 'add_view', 'restart'); - }; - die "$err\n$@" if ($@); - } - die $err; - } elsif ($@) { - die $@; - } elsif ($is_add_view) { - $OLD_CONFIG = undef; - } - - if ($res->{post_exe} && ref $res->{post_exe} eq 'CODE') { - $res->{post_exe}->(); - } - - if ($res->{msg}) { - $msg = $res->{msg}; - } - - return $msg; -} - -sub get_base { - return '/dev/zvol'; -} - -1; diff --git a/PVE/Storage/LunCmd/Makefile b/PVE/Storage/LunCmd/Makefile deleted file mode 100644 index b959255..0000000 --- a/PVE/Storage/LunCmd/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES=Comstar.pm Istgt.pm Iet.pm - -.PHONY: install -install: - for i in ${SOURCES}; do install -D -m 0644 $$i ${DESTDIR}${PERLDIR}/PVE/Storage/LunCmd/$$i; done diff --git a/PVE/Storage/Makefile b/PVE/Storage/Makefile index 919c486..818c98a 100644 --- a/PVE/Storage/Makefile +++ b/PVE/Storage/Makefile @@ -3,4 +3,3 @@ SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm RBDPlugi .PHONY: install install: for i in ${SOURCES}; do install -D -m 0644 $$i ${DESTDIR}${PERLDIR}/PVE/Storage/$$i; done - make -C LunCmd install -- 1.7.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel