- Fixed applyConfiguration() to remove entries before adding new ones.
authormgandalf <mgandalf@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 21 Jun 2007 17:24:12 +0000 (17:24 +0000)
committermgandalf <mgandalf@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 21 Jun 2007 17:24:12 +0000 (17:24 +0000)
- Fixed changes and differences counts
- Added intelligence around virtual/physical/performance type devices

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@132 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scstadmin/Changes
scstadmin/SCST/SCST.pm
scstadmin/scstadmin

index 3f50be1..4368592 100644 (file)
@@ -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
index c947a8f..789ba5c 100644 (file)
@@ -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);
-
-$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;
+            $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;
+$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.
index 57d98ad..f1ef0e9 100755 (executable)
@@ -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 <vdisk name>,<device path>,<options>,<block size>\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;