- Split out apply config into parts to allow for luns (or other sections) to

exist outside of ini_groups - necessary for virtual targets.
- Added a few more methods (incomplete) for handing virtual targets.
- Started work on the check config code.



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1700 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Mark Buechler
2010-05-18 19:59:09 +00:00
parent 71f069f9db
commit 8ed236d49f
2 changed files with 548 additions and 51 deletions

View File

@@ -43,6 +43,9 @@ SCST_C_PARAMETER_STATIC => 8,
SCST_C_SETPARAM_FAIL => 9,
SCST_C_HND_NO_HANDLER => 10,
SCST_C_HND_BAD_PARAMETERS => 17,
SCST_C_HND_PARAMETER_STATIC => 18,
SCST_C_HND_SETPARAM_FAIL => 19,
SCST_C_DEV_NO_DEVICE => 20,
SCST_C_DEV_EXISTS => 21,
@@ -53,11 +56,17 @@ SCST_C_DEV_PARAMETER_STATIC => 28,
SCST_C_DEV_SETPARAM_FAIL => 29,
SCST_C_DRV_NO_DRIVER => 30,
SCST_C_DRV_STATIC => 31,
SCST_C_DRV_SETATTR_FAIL => 34,
SCST_C_DRV_BAD_PARAMETERS => 37,
SCST_C_DRV_PARAMETER_STATIC => 38,
SCST_C_DRV_SETPARAM_FAIL => 39,
SCST_C_TGT_NO_TARGET => 40,
SCST_C_TGT_EXISTS => 41,
SCST_C_TGT_ADD_FAIL => 42,
SCST_C_TGT_REM_FAIL => 43,
SCST_C_TGT_SETATTR_FAIL => 44,
SCST_C_TGT_BAD_PARAMETERS => 47,
SCST_C_TGT_PARAMETER_STATIC => 48,
SCST_C_TGT_SETPARAM_FAIL => 49,
@@ -72,6 +81,9 @@ SCST_C_GRP_LUN_EXISTS => 61,
SCST_C_GRP_ADD_LUN_FAIL => 62,
SCST_C_GRP_REM_LUN_FAIL => 63,
SCST_C_GRP_CLR_LUN_FAIL => 65,
SCST_C_GRP_BAD_PARAMETERS => 67,
SCST_C_GRP_PARAMETER_STATIC => 68,
SCST_C_GRP_SETPARAM_FAIL => 69,
SCST_C_GRP_NO_INI => 70,
SCST_C_GRP_INI_EXISTS => 71,
@@ -98,6 +110,9 @@ my %VERBOSE_ERROR = (
(SCST_C_SETPARAM_FAIL) => 'Failed to set a SCST parameter. See "demsg" for more information.',
(SCST_C_HND_NO_HANDLER) => 'No such handler exists.',
(SCST_C_HND_BAD_PARAMETERS) => 'Bad parameters given for handler.',
(SCST_C_HND_PARAMETER_STATIC) => 'Handler parameter given is static.',
(SCST_C_HND_SETPARAM_FAIL) => 'Failed to set handler parameter. See "dmesg" for more information.',
(SCST_C_DEV_NO_DEVICE) => 'No such device exists.',
(SCST_C_DEV_EXISTS) => 'Device already exists.',
@@ -108,11 +123,15 @@ my %VERBOSE_ERROR = (
(SCST_C_DEV_SETPARAM_FAIL) => 'Failed to set device parameter. See "dmesg" for more information.',
(SCST_C_DRV_NO_DRIVER) => 'No such driver exists.',
(SCST_C_DRV_STATIC) => 'Driver is incapable of dynamically adding/removing targets.',
(SCST_C_DRV_BAD_PARAMETERS) => 'Bad parameters given for driver.',
(SCST_C_DRV_PARAMETER_STATIC) => 'Driver parameter specified is static.',
(SCST_C_DRV_SETPARAM_FAIL) => 'Failed to set driver parameter. See "dmesg" for more information.',
(SCST_C_TGT_NO_TARGET) => 'No such target exists.',
(SCST_C_TGT_EXISTS) => 'Target already exists.',
(SCST_C_TGT_ADD_FAIL) => 'Failed to add target. See "dmesg" for more information.',
(SCST_C_TGT_REM_FAIL) => 'Failed to remove target. See "dmesg" for more information.',
(SCST_C_TGT_BAD_PARAMETERS) => 'Bad parameters given for target.',
(SCST_C_TGT_PARAMETER_STATIC) => 'Target parameter specified is static.',
(SCST_C_TGT_SETPARAM_FAIL) => 'Failed to set target parameter. See "dmesg" for more information.',
@@ -127,6 +146,9 @@ my %VERBOSE_ERROR = (
(SCST_C_GRP_ADD_LUN_FAIL) => 'Failed to add LUN. See "dmesg" for more information.',
(SCST_C_GRP_REM_LUN_FAIL) => 'Failed to remove LUN. See "dmesg" for more information.',
(SCST_C_GRP_CLR_LUN_FAIL) => 'Failed to clear LUNs from group. See "dmesg" for more information.',
(SCST_C_GRP_BAD_PARAMETERS) => 'Bad parameters given for group.',
(SCST_C_GRP_PARAMETER_STATIC) => 'Group parameter specified is static.',
(SCST_C_GRP_SETPARAM_FAIL) => 'Failed to set group parameter. See "dmesg" for more information.',
(SCST_C_GRP_NO_INI) => 'No such initiator exists.',
(SCST_C_GRP_INI_EXISTS) => 'Initiator already exists.',
@@ -401,7 +423,7 @@ sub initiators {
}
if ($self->groupExists($driver, $target, $group) != TRUE) {
$self->{'err_string'} = "initiators(): Group '$group' does not exists";
$self->{'err_string'} = "initiators(): Group '$group' does not exist";
return undef;
}
@@ -443,7 +465,7 @@ sub luns {
}
if ($self->groupExists($driver, $target, $group) != TRUE) {
$self->{'err_string'} = "initiators(): Group '$group' does not exists";
$self->{'err_string'} = "initiators(): Group '$group' does not exist";
return undef;
}
@@ -507,6 +529,24 @@ sub driverExists {
return FALSE;
}
sub addDriverAttribute {
my $self = shift;
my $driver = shift;
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
return SCST_C_DRV_STATIC if ($self->driverIsStatic($driver));
my $path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, SCST_MGMT_IO);
my $io = new IO::File $path, O_WRONLY;
return SCST_C_TGT_ADD_FAIL if (!$io);
}
sub targetExists {
my $self = shift;
my $driver = shift;
@@ -530,6 +570,110 @@ sub targetExists {
return FALSE;
}
sub driverIsStatic {
my $self = shift;
my $driver = shift;
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
my $path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, SCST_MGMT_IO);
my $io = new IO::File $path, O_WRONLY;
return TRUE if (!$io);
return FALSE;
}
sub addTarget {
my $self = shift;
my $driver = shift;
my $target = shift;
my $parameters = shift;
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
$rc = $self->targetExists($driver, $target);
return SCST_C_TGT_EXISTS if (!$rc);
return $rc if ($rc > 1);
return SCST_C_DRV_STATIC if ($self->driverIsStatic($driver));
$rc = $self->checkTargetCreateParameters($driver, $target, $parameters);
return SCST_C_TGT_BAD_PARAMETERS if ($rc == TRUE);
return $rc if ($rc > 1);
my $path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, SCST_MGMT_IO);
my $io = new IO::File $path, O_WRONLY;
return SCST_C_TGT_ADD_FAIL if (!$io);
my $o_string;
foreach my $parameter (keys %{$parameters}) {
my $value = $$parameters{$parameter};
$o_string .= "$parameter=$value; ";
}
$o_string =~ s/\s$//;
my $cmd = "add_target $target $o_string\n";
my $bytes;
if ($self->{'debug'}) {
print "DBG($$): $path -> $cmd\n";
} else {
$bytes = syswrite($io, $cmd, length($cmd));
}
close $io;
return FALSE if ($self->{'debug'} || $bytes);
return SCST_C_TGT_ADD_FAIL;
}
sub addTargetAttribute {
}
sub removeTarget {
my $self = shift;
my $driver = shift;
my $target = shift;
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
$rc = $self->targetExists($driver, $target);
return SCST_C_TGT_NO_TARGET if (!$rc);
return $rc if ($rc > 1);
return SCST_C_DRV_STATIC if ($self->driverIsStatic($driver));
my $path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, SCST_MGMT_IO);
my $io = new IO::File $path, O_WRONLY;
return SCST_C_TGT_REM_FAIL if (!$io);
my $cmd = "del_target $target\n";
my $bytes;
if ($self->{'debug'}) {
print "DBG($$): $path -> $cmd\n";
} else {
$bytes = syswrite($io, $cmd, length($cmd));
}
close $io;
return FALSE if ($self->{'debug'} || $bytes);
return SCST_C_TGT_REM_FAIL;
}
sub groupExists {
my $self = shift;
my $driver = shift;
@@ -1451,6 +1595,123 @@ sub setTargetParameter {
return SCST_C_TGT_SETPARAM_FAIL;
}
sub groupParameters {
my $self = shift;
my $driver = shift;
my $target = shift;
my $group = shift;
my %parameters;
if ($self->driverExists($driver) != TRUE) {
$self->{'err_string'} = "groupParameters(): Driver '$driver' is not available";
return undef;
}
if ($self->targetExists($driver, $target) != TRUE) {
$self->{'err_string'} = "groupParameters(): Target '$target' is not available";
return undef;
}
if ($self->groupExists($driver, $target, $group) != TRUE) {
$self->{'err_string'} = "groupParameters(): Group '$group' does not exist";
return undef;
}
my $pHandle = new IO::Handle;
my $_path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, $target, SCST_GROUPS, $group);
if (!(opendir $pHandle, $_path)) {
$self->{'err_string'} = "groupParameters(): Unable to read directory '$_path': $!";
return undef;
}
foreach my $parameter (readdir($pHandle)) {
next if (($parameter eq '.') || ($parameter eq '..'));
my $pPath = mkpath(SCST_ROOT, SCST_TARGETS, $driver, $target, SCST_GROUPS,
$group, $parameter);
my $mode = (stat($pPath))[2];
if (-d $pPath) {
# Skip directories
} else {
if (!(($mode & S_IRUSR) >> 6)) {
$parameters{$parameter}->{'static'} = FALSE;
$parameters{$parameter}->{'value'} = undef;
} else {
my $is_static;
if (($mode & S_IWUSR) >> 6) {
$is_static = FALSE;
} else {
$is_static = TRUE;
}
my $io = new IO::File $pPath, O_RDONLY;
if (!$io) {
$self->{'err_string'} = "groupParameters(): Unable to read ".
"group parameter '$parameter': $!";
return undef;
}
my $value = <$io>;
chomp $value;
$parameters{$parameter}->{'static'} = $is_static;
$parameters{$parameter}->{'value'} = $value;
}
}
}
return \%parameters;
}
sub setGroupParameter {
my $self = shift;
my $driver = shift;
my $target = shift;
my $group = shift;
my $parameter = shift;
my $value = shift;
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
$rc = $self->targetExists($driver, $target);
return SCST_C_TGT_NO_TARGET if (!$rc);
return $rc if ($rc > 1);
$rc = $self->groupExists($driver, $target, $group);
return SCST_C_GRP_NO_GROUP if (!$rc);
return $rc if ($rc > 1);
return TRUE if (!defined($parameter) || !defined($value));
my $parameters = $self->groupParameters($driver, $target, $group);
return SCST_C_GRP_BAD_PARAMETERS if (!defined($$parameters{$parameter}));
return SCST_C_GRP_PARAMETER_STATIC if ($$parameters{$parameter}->{'static'});
my $path = mkpath(SCST_ROOT, SCST_TARGETS, $driver, $target, SCST_GROUPS,
$group, $parameter);
my $io = new IO::File $path, O_WRONLY;
return SCST_C_GRP_SETPARAM_FAIL if (!$io);
my $bytes;
if ($self->{'debug'}) {
print "DBG($$): $path -> $parameter = $value\n";
} else {
$bytes = syswrite($io, $value, length($value));
}
close $io;
return FALSE if ($self->{'debug'} || $bytes);
return SCST_C_GRP_SETPARAM_FAIL;
}
sub lunParameters {
my $self = shift;
my $driver = shift;
@@ -1470,7 +1731,7 @@ sub lunParameters {
}
if ($self->groupExists($driver, $target, $group) != TRUE) {
$self->{'err_string'} = "lunParameters(): Group '$group' does not exists";
$self->{'err_string'} = "lunParameters(): Group '$group' does not exist";
return undef;
}
@@ -1608,7 +1869,7 @@ sub initiatorParameters {
}
if ($self->groupExists($driver, $target, $group) != TRUE) {
$self->{'err_string'} = "initiatorParameters(): Group '$group' does not exists";
$self->{'err_string'} = "initiatorParameters(): Group '$group' does not exist";
return undef;
}
@@ -1758,6 +2019,43 @@ sub handlerExists {
return FALSE;
}
sub setHandlerParameter {
my $self = shift;
my $handler = shift;
my $parameter = shift;
my $value = shift;
my $rc = $self->handlerExists($handler);
return SCST_C_HND_NO_HANDLER if (!$rc);
return $rc if ($rc > 1);
return TRUE if (!defined($parameter) || !defined($value));
my $parameters = $self->handlerParameters($handler);
return SCST_C_HND_BAD_PARAMETERS if (!defined($$parameters{$parameter}));
return SCST_C_HND_PARAMETER_STATIC if ($$parameters{$parameter}->{'static'});
my $path = mkpath(SCST_ROOT, SCST_HANDLERS, $handler, $parameter);
my $io = new IO::File $path, O_WRONLY;
return SCST_C_HND_SETPARAM_FAIL if (!$io);
my $bytes;
if ($self->{'debug'}) {
print "DBG($$): $path -> $parameter = $value\n";
} else {
$bytes = syswrite($io, $value, length($value));
}
close $io;
return FALSE if ($self->{'debug'} || $bytes);
return SCST_C_HND_SETPARAM_FAIL;
}
sub handlerParameters {
my $self = shift;
my $handler = shift;
@@ -2052,6 +2350,68 @@ sub setDeviceParameter {
return SCST_C_DEV_SETPARAM_FAIL;
}
sub checkTargetCreateParameters {
my $self = shift;
my $driver = shift;
my $check = shift;
return FALSE if (!defined($check));
my $rc = $self->driverExists($driver);
return SCST_C_DRV_NO_DRIVER if (!$rc);
return $rc if ($rc > 1);
my $available = $self->targetCreateParameters($driver);
return SCST_C_FATAL_ERROR if (!defined($available));
foreach my $parameter (keys %{$check}) {
if (!defined($$available{$parameter})) {
return TRUE;
}
}
return FALSE;
}
sub targetCreateParameters {
my $self = shift;
my $driver = shift;
my $available;
my %parameters;
if ($self->driverExists($driver) != TRUE) {
$self->{'err_string'} = "targetCreateParameters(): Driver '$driver' ".
"is not available";
return undef;
}
my $io = new IO::File mkpath(SCST_ROOT, SCST_TARGETS, $driver, SCST_MGMT_IO), O_RDONLY;
if (!$io) {
$self->{'err_string'} = "targetCreateParameters(): Unable to open driver mgmt ".
"interface for driver '$driver': $!";
return undef;
}
while (my $in = <$io>) {
if ($in =~ /^The following parameters available\:/) {
(undef, $available) = split(/\:/, $in, 2);
$available =~ s/\.$//;
}
}
if ($available) {
foreach my $parameter (split(/\,/, $available)) {
$parameter =~ s/^\s+//;
$parameter =~ s/\s+$//;
$parameters{$parameter} = '';
}
}
return \%parameters;
}
sub enableTarget {
my $self = shift;
my $driver = shift;

View File

@@ -1000,10 +1000,61 @@ sub writeConfiguration {
sub checkConfiguration {
my $file = shift;
my $no_drivers;
my $no_handlers;
print "-> Checking configuration file '$file' for errors.\n";
$CONFIG = readConfig($file);
$CONFIG = readConfig($file) if (!$CONFIG);
# Check for a minimum sane configuration
if (!defined($$CONFIG{'TARGET_DRIVER'}) ||
!(scalar keys %{$$CONFIG{'TARGET_DRIVER'}})) {
print "\t-> WARNING: No TARGET_DRIVER section defined. ".
"No target drivers will be configured.\n";
$no_drivers = TRUE;
}
if (!defined($$CONFIG{'HANDLER'}) ||
!(scalar keys %{$$CONFIG{'HANDLER'}})) {
print "\t-> WARNING: No HANDLER section defined. ".
"Only physical media will be configured for targets.\n";
$no_handlers = TRUE;
}
if ($no_drivers && $no_handlers) {
immediateExit("No target drivers or handlers defined, aborting!");
}
if (!$no_drivers) {
foreach my $driver (keys %{$$CONFIG{'TARGET_DRIVER'}}) {
my $no_targets;
if (!defined($CURRENT{'assign'}->{$driver})) {
print "\t-> WARNING: Target driver '$driver' is not loaded or available.\n";
next;
}
if (!defined($$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}) ||
!(scalar keys %{$$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}})) {
print "\t-> WARNING: Driver '$driver' has no configured targets.\n";
$no_targets = TRUE;
}
if (!$no_targets) {
foreach my $target (keys %{$$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
print "\t-> WARNING: Target '$target' for driver '$driver' ".
"does not exist.\n";
}
}
}
}
}
use Data::Dumper;
#print Dumper($CONFIG);
#print Dumper(\%CURRENT);
return FALSE;
}
@@ -1149,56 +1200,112 @@ sub applyConfigAssignments {
immediateExit("Target driver '$driver' is not loaded or available.");
}
my $targets = $$assignments{$driver}->{'TARGET'};
foreach my $target (sort keys %{$targets}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
immediateExit("Target '$target' for driver '$driver' does not exist.");
}
my $groups = $$targets{$target}->{'GROUP'};
foreach my $group (sort keys %{$groups}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target}->{$group})) {
addGroup($group, $driver, $target);
}
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'INITIATORS'};
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'LUNS'};
if (defined($$groups{$group}->{'LUN'})) {
foreach my $lun (sort keys %{$$groups{$group}->{'LUN'}}) {
if (!defined($$luns{$lun})) {
if ((keys %{$$groups{$group}->{'LUN'}->{$lun}}) > 1) {
immediateExit("Invalid configuration encountered. ".
"Driver/target/group/lun $driver/$target/$group/$lun ".
"has multiple devices assigned.");
}
foreach my $device (sort keys %{$$groups{$group}->{'LUN'}->{$lun}}) {
my $parameters = configToParm($$groups{$group}->{'LUN'}->{$lun}->{$device});
addLun($lun, $driver, $target, $group, $device, $parameters);
}
}
}
}
if (defined($$groups{$group}->{'INITIATOR'})) {
foreach my $initiator (sort keys %{$$groups{$group}->{'INITIATOR'}}) {
if (!groupHasInitiator($inits, $initiator)) {
addInitiator($initiator, $driver, $target, $group);
}
}
}
}
my %_parameters;
foreach my $item (keys %{$$targets{$target}}) {
next if ($item eq 'GROUP');
$_parameters{$item} = $$targets{$target}->{$item};
my %_parameters;
foreach my $item (keys %{$$assignments{$driver}}) {
if ($item eq 'TARGET') {
applyTargetAssignments($driver, $$assignments{$driver}->{$item});
} else {
$_parameters{$item} = $$assignments{$driver}->{$item};
}
my $parameters = configToParm(\%_parameters);
setTargetParameters($target, $driver, $parameters);
setDriverParameters($driver, $parameters);
}
}
}
sub applyTargetAssignments {
my $driver = shift;
my $targets = shift;
foreach my $target (sort keys %{$targets}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
immediateExit("Target '$target' for driver '$driver' does not exist.");
}
my %_parameters;
foreach my $item (keys %{$$targets{$target}}) {
if ($item eq 'GROUP') {
applyGroupAssignments($driver, $target, $$targets{$target}->{$item});
} elsif ($item eq 'LUN') {
applyLunAssignments($driver, $target, $$targets{$target}->{$item});
} else {
$_parameters{$item} = $$targets{$target}->{$item};
}
}
my $parameters = configToParm(\%_parameters);
setTargetParameters($target, $driver, $parameters);
}
}
sub applyGroupAssignments {
my $driver = shift;
my $target = shift;
my $groups = shift;
foreach my $group (sort keys %{$groups}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target}->{$group})) {
addGroup($group, $driver, $target);
}
my %_parameters;
foreach my $item (keys %{$$groups{$group}}) {
if ($item eq 'LUN') {
applyLunAssignments($driver, $target, $group,
$$groups{$group}->{$item});
} elsif ($item eq 'INITIATOR') {
applyInitiatorAssignments($driver, $target, $group,
$$groups{$group}->{$item});
} else {
$_parameters{$item} = $$groups{$group}->{$item};
}
}
my $parameters = configToParm(\%_parameters);
setGroupParameters($target, $driver, $group, $parameters);
}
}
sub applyLunAssignments {
my $driver = shift;
my $target = shift;
my $group = shift;
my $luns = shift;
my $c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'LUNS'};
foreach my $lun (sort keys %{$luns}) {
if (!defined($$c_luns{$lun})) {
if ((scalar keys %{$$luns{$lun}}) > 1) {
immediateExit("Invalid configuration encountered. ".
"Driver/target/group/lun $driver/$target/$group/$lun ".
"has multiple devices assigned.");
}
foreach my $device (sort keys %{$$luns{$lun}}) {
my $parameters = configToParm($$luns{$lun}->{$device});
addLun($lun, $driver, $target, $group, $device, $parameters);
}
}
}
}
sub applyInitiatorAssignments {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiators = shift;
my $c_inits = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'INITIATORS'};
foreach my $initiator (sort keys %{$initiators}) {
if (!groupHasInitiator($c_inits, $initiator)) {
addInitiator($initiator, $driver, $target, $group);
}
}
}
@@ -1725,6 +1832,36 @@ sub setTargetParameters {
}
}
sub setGroupParameters {
my $target = shift;
my $driver = shift;
my $group = shift;
my $parameters = shift;
my $_parameters = $SCST->groupParameters($driver, $target, $group);
foreach my $parameter (sort keys %{$parameters}) {
if (defined($$_parameters{$parameter}) &&
!$$_parameters{$parameter}->{'static'}) {
my $value = $$parameters{$parameter};
next if ($$_parameters{$parameter}->{'value'} eq $value);
print "-> Setting group parameter '$parameter' to value '$value' for ".
"driver/target/group '$driver/$target/$group': ";
my $rc = $SCST->setGroupParameter($driver, $target, $group, $parameter, $value);
print "done.\n";
immediateExit($SCST->errorString($rc)) if ($rc);
} else {
print "-> WARNING: Driver/target/group '$driver/$target/$group' lacks the settable ".
"parameter '$parameter', ignoring.\n";
}
}
}
sub setLunParameters {
my $lun = shift;
my $driver = shift;