diff --git a/scstadmin/Changes b/scstadmin/Changes index 3f50be1f9..436859205 100644 --- a/scstadmin/Changes +++ b/scstadmin/Changes @@ -25,4 +25,7 @@ Changes since 0.9.6-pre2: - Added additional error messaging to scstadmin - Changed SCST/SCST.pm to look for vdisk/vdisk instead of vdisk/type for valid device handler types. +- Fixed applyConfiguration() to remove entries before adding new ones. +- Fixed changes and differences counts +- Added intelligence around virtual/physical/performance type devices - Minor bug fixes diff --git a/scstadmin/SCST/SCST.pm b/scstadmin/SCST/SCST.pm index c947a8f2f..789ba5c59 100644 --- a/scstadmin/SCST/SCST.pm +++ b/scstadmin/SCST/SCST.pm @@ -24,6 +24,7 @@ my $_SCST_TAPE_IO_ = $_SCST_DIR_.'/dev_tape/dev_tape'; my $_SCST_TAPEP_IO_ = $_SCST_DIR_.'/dev_tape_perf/dev_tape_perf'; my $_SCST_VDISK_IO_ = $_SCST_DIR_.'/vdisk/vdisk'; my $_SCST_VCDROM_IO_ = $_SCST_DIR_.'/vcdrom/vcdrom'; +my $_SCST_PROCESSOR_IO_ = $_SCST_DIR_.'/dev_processor/dev_processor'; my $_SCST_GROUPS_DIR_ = $_SCST_DIR_.'/groups'; my $_SCST_SGV_STATS_ = $_SCST_DIR_.'/sgv'; my $_SCST_SESSIONS_ = $_SCST_DIR_.'/sessions'; @@ -37,18 +38,24 @@ my @_AVAILABLE_OPTIONS_ = ('WRITE_THROUGH', 'O_DIRECT', 'READ_ONLY', use vars qw(@ISA @EXPORT $VERSION $CDROM_TYPE $CHANGER_TYPE $DISK_TYPE $VDISK_TYPE $VCDROM_TYPE $DISKPERF_TYPE $MODISK_TYPE $MODISKPERF_TYPE $TAPE_TYPE - $TAPEPERF_TYPE); + $TAPEPERF_TYPE $PROCESSOR_TYPE $IOTYPE_PHYSICAL $IOTYPE_VIRTUAL + $IOTYPE_PERFORMANCE); -$CDROM_TYPE = 1; -$CHANGER_TYPE = 2; -$DISK_TYPE = 3; -$VDISK_TYPE = 4; -$VCDROM_TYPE = 5; -$DISKPERF_TYPE = 6; -$MODISK_TYPE = 7; -$MODISKPERF_TYPE = 8; -$TAPE_TYPE = 9; -$TAPEPERF_TYPE = 10; +$CDROM_TYPE = 1; +$CHANGER_TYPE = 2; +$DISK_TYPE = 3; +$VDISK_TYPE = 4; +$VCDROM_TYPE = 5; +$DISKPERF_TYPE = 6; +$MODISK_TYPE = 7; +$MODISKPERF_TYPE = 8; +$TAPE_TYPE = 9; +$TAPEPERF_TYPE = 10; +$PROCESSOR_TYPE = 11; + +$IOTYPE_PHYSICAL = 100; +$IOTYPE_VIRTUAL = 101; +$IOTYPE_PERFORMANCE = 102; $VERSION = 0.6.1; @@ -65,7 +72,8 @@ my %_IO_MAP_ = ($CDROM_TYPE => $_SCST_CDROM_IO_, $MODISK_TYPE => $_SCST_MODISK_IO_, $MODISKPERF_TYPE => $_SCST_MODISKP_IO_, $TAPE_TYPE => $_SCST_TAPE_IO_, - $TAPEPERF_TYPE => $_SCST_TAPEP_IO_); + $TAPEPERF_TYPE => $_SCST_TAPEP_IO_, + $PROCESSOR_TYPE => $_SCST_PROCESSOR_IO_); my %_TYPE_MAP_ = ('dev_cdrom' => $CDROM_TYPE, 'dev_changer' => $CHANGER_TYPE, @@ -76,7 +84,20 @@ my %_TYPE_MAP_ = ('dev_cdrom' => $CDROM_TYPE, 'dev_modisk' => $MODISK_TYPE, 'dev_modisk_perf' => $MODISKPERF_TYPE, 'dev_tape' => $TAPE_TYPE, - 'dev_tape_perf' => $TAPEPERF_TYPE); + 'dev_tape_perf' => $TAPEPERF_TYPE, + 'dev_processor' => $PROCESSOR_TYPE); + +my %_IO_TYPES_ = ($CDROM_TYPE => $IOTYPE_PHYSICAL, + $CHANGER_TYPE => $IOTYPE_PHYSICAL, + $DISK_TYPE => $IOTYPE_PHYSICAL, + $VDISK_TYPE => $IOTYPE_VIRTUAL, + $VCDROM_TYPE => $IOTYPE_VIRTUAL, + $DISKPERF_TYPE => $IOTYPE_PERFORMANCE, + $MODISK_TYPE => $IOTYPE_PHYSICAL, + $MODISKPERF_TYPE => $IOTYPE_PERFORMANCE, + $TAPE_TYPE => $IOTYPE_PHYSICAL, + $TAPEPERF_TYPE => $IOTYPE_PERFORMANCE, + $PROCESSOR_TYPE => $IOTYPE_PHYSICAL); sub new { my $this = shift; @@ -370,6 +391,20 @@ sub handlerDeviceExists { return $FALSE; } +sub handlerType { + my $self = shift; + my $handler = shift; + + my $type = $_IO_TYPES_{$handler}; + + if (!$type) { + $self->{'error'} = "handlerType(): Handler type for handler $handler not defined"; + return undef; + } + + return $type; +} + sub openDevice { my $self = shift; my $handler = shift; @@ -614,7 +649,7 @@ sub handlers { foreach my $entry (readdir($dirHandle)) { next if (($entry eq '.') || ($entry eq '..')); - if ((-d $_SCST_DIR_.'/'.$entry ) && (-f $_SCST_DIR_.'/'.$entry.'/'.$entry)) { + if ((-d $_SCST_DIR_.'/'.$entry ) && (-f $_SCST_DIR_.'/'.$entry.'/type')) { push @handlers, $_TYPE_MAP_{$entry} if ($_TYPE_MAP_{$entry}); } } @@ -1040,6 +1075,18 @@ Arguments: (int) $handler, (string) $device Returns: (boolean) $deviceExists +=item SCST::SCST->handlerType(); + +Return the handler type for the specified handler. Handler types are: + + SCST::SCST::IOTYPE_PHYSICAL + SCST::SCST::IOTYPE_VIRTUAL + SCST::SCST::IOTYPE_PERFORMANCE + +Arguments: (int) $handler + +Returns: (int) $handler_type + =item SCST::SCST->openDevice(); Opens an already existing specified device for the specified device handler. diff --git a/scstadmin/scstadmin b/scstadmin/scstadmin index 57d98ade8..f1ef0e9f7 100755 --- a/scstadmin/scstadmin +++ b/scstadmin/scstadmin @@ -119,7 +119,18 @@ my %_HANDLER_MAP_ = ('cdrom' => $SCST::SCST::CDROM_TYPE, 'modisk' => $SCST::SCST::MODISK_TYPE, 'modisk_perf' => $SCST::SCST::MODISKPERF_TYPE, 'tape' => $SCST::SCST::TAPE_TYPE, - 'tape_perf' => $SCST::SCST::TAPEPERF_TYPE); + 'tape_perf' => $SCST::SCST::TAPEPERF_TYPE, + 'processor' => $SCST::SCST::PROCESSOR_TYPE, + # Add in the dev_ names as well + 'dev_cdrom' => $SCST::SCST::CDROM_TYPE, + 'dev_changer' => $SCST::SCST::CHANGER_TYPE, + 'dev_disk' => $SCST::SCST::DISK_TYPE, + 'dev_disk_perf' => $SCST::SCST::DISKPERF_TYPE, + 'dev_modisk' => $SCST::SCST::MODISK_TYPE, + 'dev_modisk_perf' => $SCST::SCST::MODISKPERF_TYPE, + 'dev_tape' => $SCST::SCST::TAPE_TYPE, + 'dev_tape_perf' => $SCST::SCST::TAPEPERF_TYPE, + 'dev_processor' => $SCST::SCST::PROCESSOR_TYPE); my %_REVERSE_MAP_ = ($SCST::SCST::CDROM_TYPE => 'cdrom', $SCST::SCST::CHANGER_TYPE => 'changer', @@ -130,7 +141,12 @@ my %_REVERSE_MAP_ = ($SCST::SCST::CDROM_TYPE => 'cdrom', $SCST::SCST::MODISK_TYPE => 'modisk', $SCST::SCST::MODISKPERF_TYPE => 'modisk_perf', $SCST::SCST::TAPE_TYPE => 'tape', - $SCST::SCST::TAPEPERF_TYPE => 'tape_perf'); + $SCST::SCST::TAPEPERF_TYPE => 'tape_perf', + $SCST::SCST::PROCESSOR_TYPE => 'processor'); + +my %_HANDLER_TYPE_MAP_ = ($SCST::SCST::IOTYPE_PHYSICAL => 'physical', + $SCST::SCST::IOTYPE_VIRTUAL => 'virtual', + $SCST::SCST::IOTYPE_PERFORMANCE => 'performance'); $SIG{INT} = \&commitSuicide; @@ -458,6 +474,8 @@ sub writeConfiguration { # Device information foreach my $handler (sort keys %HANDLERS) { + next if ($SCST->handlerType($handler) != $SCST::SCST::IOTYPE_VIRTUAL); + print $io "[HANDLER ".$_REVERSE_MAP_{$handler}."]\n"; print $io "#DEVICE ,,,\n"; @@ -538,130 +556,68 @@ sub applyConfiguration { my %used_users; my %used_assignments; - print "Applying configurations additions..\n" if (!$check); - print "\n"; - - # Open new devices and assign them to handlers.. + # Cache device/handler configuration foreach my $entry (keys %{$$config{'HANDLER'}}) { - if (!$HANDLERS{$_HANDLER_MAP_{$entry}}) { - print "\t-> WARNING: Handler '$entry' does not exist.\n"; - $errs += 1; - next; - } - foreach my $device (@{$$config{'HANDLER'}->{$entry}->{'DEVICE'}}) { - my($vname, $path, $options, $blocksize) = split(/\,/, $device); + my($vname, undef) = split(/\,/, $device, 2); $vname = cleanupString($vname); - $path = cleanupString($path); - - $options =~ s/\s+//; $options =~ s/\|/,/; - $used_devs{$vname} = $entry; - - next if (defined($$DEVICES{$vname})); - - $changes++; - - if ($check) { - print "\t-> New device '$entry:$vname' at path '$path', options '$options', blocksize $blocksize.\n"; - $$DEVICES{$vname} = $_HANDLER_MAP_{$entry}; - } else { - $errs += addDevice($entry, $vname, $path, $options, $blocksize); - } } } - # Create new groups and add users.. + # Cache user/group configuration foreach my $group (keys %{$$config{'GROUP'}}) { - if (!defined($GROUPS{$group})) { - $changes++; - - if ($check) { - print "\t-> New group definition '$group.'\n"; - $GROUPS{$group}++; - } else { - $errs += addGroup($group); - } - } - foreach my $user (@{$$config{'GROUP'}->{$group}->{'USER'}}) { $used_users{$group}->{$user}++; - - if (!defined($USERS{$group}->{$user})) { - $changes++; - - if ($check) { - print "\t-> New user definition '$user' for group '$group'.\n"; - $USERS{$group}->{$user}++; - } else { - $errs += addUser($group, $user); - } - } } } - # Assign new devices to groups.. + # Cache device association configuration foreach my $group (keys %{$$config{'ASSIGNMENT'}}) { - if (!defined($GROUPS{$group})) { - print "\t-> WARNING: Unable to assign to non-existant group '$group'.\n"; - $errs += 1; - next; - } - foreach my $device (@{$$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) { my($vname, $lun) = split(/\,/, $device); $vname = cleanupString($vname); - $lun = cleanupString($lun); - - $used_assignments{$group}->{$vname}++; - - my $_assignments = $ASSIGNMENTS{$group}; - next if (defined($$_assignments{$vname})); - - $changes++; - - if ($check) { - $lun = 'auto' if (!defined($lun)); - print "\t-> New device assignment for '$vname' to group '$group' at LUN $lun.\n"; - } else { - $errs += assignDevice($group, $vname, $lun); - } + $used_assignments{$group}->{$vname} = $lun; } } # If -ForceConfig is used, check for configurations which we've deleted but are still active. if ($force || $check) { - readCurrentConfig() if (!$check); - # Associations foreach my $group (sort keys %ASSIGNMENTS) { - if (!defined($used_assignments{$group})) { - print "\t-force: Group $group has no associations in saved configuration"; + if (!defined($used_assignments{$group}) && (keys %{$ASSIGNMENTS{$group}})) { + print "\tWARNING: Group $group has no associations in saved configuration"; if (!$check) { print ", clearing all associations.\n"; - $errs += clearDevices($group); + if (clearDevices($group)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } else { my $_assignments = $ASSIGNMENTS{$group}; foreach my $device (sort keys %{$_assignments}) { if (!defined($used_assignments{$group}->{$device})) { - print "\t-force: Device $device is not associated with group ". + print "\tWARNING: Device $device is not associated with group ". "$group in saved configuration"; if (!$check) { print ", releasing.\n"; - $errs += releaseDevice($group, $device); + if (releaseDevice($group, $device)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } } } @@ -670,31 +626,42 @@ sub applyConfiguration { # Users & Groups foreach my $group (sort keys %USERS) { if (!defined($used_users{$group})) { - print "\t-force: Group $group does not exist in saved configuration"; + print "\tWARNING: Group $group does not exist in saved configuration"; if (!$check) { print ", removing.\n"; - $errs += clearUsers($group); - $errs += removeGroup($group); + if (clearUsers($group)) { + $errs++; + } else { + $changes++; + } + + if (removeGroup($group)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } else { foreach my $user (sort keys %{$USERS{$group}}) { if (!defined($used_users{$group}->{$user})) { - print "\t-force: User $user is not defined as part of group $group ". + print "\WARNING: User $user is not defined as part of group $group ". "in saved configuration"; if (!$check) { print ", removing.\n"; - $errs += removeUser($group, $user); + if (removeUser($group, $user)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } } } @@ -702,28 +669,33 @@ sub applyConfiguration { # Devices foreach my $device (sort keys %{$DEVICES}) { + next if ($SCST->handlerType($$DEVICES{$device}) != $SCST::SCST::IOTYPE_VIRTUAL); + if ($$DEVICES{$device} && !defined($used_devs{$device})) { - # Device gone, but is it still assigned tp a group? + # Device gone, but is it still assigned to a group? my $isAssigned = $FALSE; foreach my $group (sort keys %used_assignments) { if (defined($used_assignments{$group}->{$device})) { - print "\t-force: WARNING: Device $device is not defined in saved configuration, ". + print "\tWARNING: Device $device is not defined in saved configuration, ". "however, it is still assigned to group $group! Ignoring removal.\n"; $isAssigned = $TRUE; } } if (!$isAssigned) { - print "\t-force: Device $device is not defined in saved configuration"; + print "\tWARNING: Device $device is not defined in saved configuration"; if (!$check) { print ", removing.\n"; - $errs += removeDevice($device); + if (removeDevice($device)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } } else { # Handler change @@ -731,16 +703,86 @@ sub applyConfiguration { my $handler = $used_devs{$device}; if ($HANDLERS{$_HANDLER_MAP_{$handler}}) { - print "\t-force: Device $device changes handler to $handler"; + print "\tWARNING: Device $device changes handler to $handler"; if (!$check) { print ", changing.\n"; - $errs += assignDeviceToHandler($device, $handler); - + if (assignDeviceToHandler($device, $handler)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } + } + } + } + } + } + print "Applying configurations additions..\n" if (!$check); + print "\n"; + + readCurrentConfig() if ($force); + + foreach my $vname (keys %used_devs) { + my $_handler = $used_devs{$vname}; + + if (!$HANDLERS{$_HANDLER_MAP_{$_handler}}) { + print "\t-> WARNING: Handler '$_handler' does not exist.\n"; + $errs += 1; + next; + } + + foreach my $device (@{$$config{'HANDLER'}->{$_handler}->{'DEVICE'}}) { + my(undef, $path, $options, $blocksize) = split(/\,/, $device); + $path = cleanupString($path); + $options =~ s/\s+//; $options =~ s/\|/,/; + + next if (defined($$DEVICES{$vname})); + + if ($check) { + print "\t-> New device '$_handler:$vname' at path '$path', options '$options', blocksize $blocksize.\n"; + $$DEVICES{$vname} = $_HANDLER_MAP_{$_handler}; + $changes++; + } else { + if (addDevice($_handler, $vname, $path, $options, $blocksize)) { + $errs++; + } else { + $changes++; + } + } + } + } + + # Create new groups and add users.. + foreach my $group (keys %used_users) { + if (!defined($GROUPS{$group})) { + if ($check) { + print "\t-> New group definition '$group.'\n"; + $GROUPS{$group}++; + $changes++; + } else { + if (addGroup($group)) { + $errs++; + } else { + $changes++; + } + } + } + + foreach my $user (keys %{$used_users{$group}}) { + if (!defined($USERS{$group}->{$user})) { + if ($check) { + print "\t-> New user definition '$user' for group '$group'.\n"; + $USERS{$group}->{$user}++; + $changes++; + } else { + if (addUser($group, $user)) { + $errs++; + } else { $changes++; } } @@ -748,6 +790,33 @@ sub applyConfiguration { } } + # Assign new devices to groups.. + foreach my $group (keys %used_assignments) { + if (!defined($GROUPS{$group})) { + print "\t-> WARNING: Unable to assign to non-existant group '$group'.\n"; + $errs += 1; + next; + } + + foreach my $vname (keys %{$used_assignments{$group}}) { + my $lun = $used_assignments{$group}->{$vname}; + my $_assignments = $ASSIGNMENTS{$group}; + next if (defined($$_assignments{$vname})); + + if ($check) { + $lun = 'auto' if (!defined($lun)); + print "\t-> New device assignment for '$vname' to group '$group' at LUN $lun.\n"; + $changes++; + } else { + if (assignDevice($group, $vname, $lun)) { + $errs++; + } else { + $changes++; + } + } + } + } + # Enable/Disable configured targets foreach my $type (keys %{$$config{'TARGETS'}}) { my $enable; @@ -775,17 +844,20 @@ sub applyConfiguration { if (!$enable && targetEnabled($target)) { if ($force || $check) { - print "\t-force: Target mode for '$target' is currently enabled, ". + print "\tWARNING: Target mode for '$target' is currently enabled, ". "however configuration file wants it disabled"; if (!$check) { print ", disabling.\n"; - $errs += enableTarget($target, $enable); + if (enableTarget($target, $enable)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } } else { print "\t-> Target '$target' is enabled in configuration file, ". @@ -793,12 +865,15 @@ sub applyConfiguration { if (!$check) { print ", enabling.\n"; - $errs += enableTarget($target, $enable); + if (enableTarget($target, $enable)) { + $errs++; + } else { + $changes++; + } } else { print ".\n"; + $changes++; } - - $changes++; } } } @@ -830,6 +905,7 @@ sub clearConfiguration { print "\nRemoving all handler devices:\n\n"; foreach my $device (keys %{$DEVICES}) { + next if ($SCST->handlerType($$DEVICES{$device}) != $SCST::SCST::IOTYPE_VIRTUAL); $errs += removeDevice($_REVERSE_MAP_{$$DEVICES{$device}}, $device); } @@ -871,6 +947,21 @@ sub addDevice { $options =~ s/\,/ /; my $_handler = $_HANDLER_MAP_{$handler}; + my $htype = $SCST->handlerType($_handler); + + if (!$htype) { + print "WARNING: Internal error occured: ".$SCST->errorString()."\n"; + return $TRUE; + } + + if ($htype != $SCST::SCST::IOTYPE_VIRTUAL) { + my $typeString = $_HANDLER_TYPE_MAP_{$htype}; + my $validType = $_HANDLER_TYPE_MAP_{$SCST::SCST::IOTYPE_VIRTUAL}; + print "WARNING: Handler $handler of type $typeString is incapable of ". + "opening/closing devices. Valid handlers are:\n". + validHandlerTypes($SCST::SCST::IOTYPE_VIRTUAL)."\n"; + return $TRUE; + } if (defined($$DEVICES{$device})) { print "WARNING: Device '$device' already defined.\n"; @@ -895,6 +986,21 @@ sub removeDevice { my $device = shift; my $_handler = $_HANDLER_MAP_{$handler}; + my $htype = $SCST->handlerType($_handler); + + if (!$htype) { + print "WARNING: Internal error occured: ".$SCST->errorString()."\n"; + return $TRUE; + } + + if ($htype != $SCST::SCST::IOTYPE_VIRTUAL) { + my $typeString = $_HANDLER_TYPE_MAP_{$htype}; + my $validType = $_HANDLER_TYPE_MAP_{$SCST::SCST::IOTYPE_VIRTUAL}; + print "WARNING: Handler $handler of type $typeString is incapable of ". + "opening/closing devices. Valid handlers are:\n". + validHandlerTypes($SCST::SCST::IOTYPE_VIRTUAL)."\n"; + return $TRUE; + } if (!defined($$DEVICES{$device})) { print "WARNING: Device '$device' not defined.\n"; @@ -1289,6 +1395,17 @@ sub unformatTarget { return $target; } +sub validHandlerTypes { + my $type = shift; + my $buffer = "\n"; + + foreach my $handler (keys %_REVERSE_MAP_) { + $buffer .= "\t".$_REVERSE_MAP_{$handler}."\n" if ($SCST->handlerType($handler) == $type); + } + + return $buffer; +} + # If we have an unread error from SCST, exit immediately sub immediateExit { my $error = shift;