mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 13:11:27 +00:00
work with iscsi (and any driver/target which supports not using ini_groups). - Add support for creating/deleting targets. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1732 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2552 lines
65 KiB
Perl
Executable File
2552 lines
65 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
$Version = 'SCST Configurator v2.0.0';
|
|
|
|
# Configures SCST
|
|
#
|
|
# Author: Mark R. Buechler
|
|
# License: GPLv2
|
|
# Copyright (c) 2005-2010 Mark R. Buechler
|
|
|
|
sub usage
|
|
{
|
|
die <<"EndUsage";
|
|
$Version
|
|
|
|
Usage:
|
|
General Operations
|
|
-config <config> : Configure SCST given the specified <file>.
|
|
-clear_config : Clear all SCST configuration.
|
|
-write_config <file> : Writes the current configuration out <file>.
|
|
-check_config <file> : Checks the saved configuration in <file>.
|
|
|
|
Query Operations
|
|
-list_handler [<hndlr>] : List all available handlers or specific <hndlr>.
|
|
-list_device [<device>] : List all open devices or specific <device>.
|
|
-list_driver [<driver>] : List all available drivers or specific <driver>.
|
|
-list_target [<target>] : List all available targets or specific <target>.
|
|
[-driver <driver>]
|
|
-list_group [<group>] : List all configured groups, or specific <group>.
|
|
[-driver <driver>]
|
|
[-target <target>]
|
|
|
|
-list_scst_parm : List add parameters for SCST.
|
|
-list_hnd_parm <hndlr> : List all parameters for a given handler.
|
|
-list_dev_parm <device> : List all parameters for a given device.
|
|
-list_drv_parm <driver> : List all parameters for a given driver.
|
|
-list_tgt_parm <target> : List all parameters for a given driver/target.
|
|
-driver <driver>
|
|
-list_lun_parm <lun> : List all parameters for a driver/target/lun.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-list_ini_parm <ini> : List all parms for a driver/target/initiator.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
|
|
-list_sessions : List all current initiator sessions.
|
|
|
|
Set Operations
|
|
-set_scst_parm : Sets SCST parameter(s) <p> to value <v>.
|
|
-parameters <p=v,...>
|
|
-set_hnd_parm <hndlr> : Sets handler parameter(s) <p> to value <v>.
|
|
-parameters <p=v,...>
|
|
-set_dev_parm <device> : Sets device parameters(s) <p> to value <v>.
|
|
-parameters <p=v,...>
|
|
-set_drv_parm <driver> : Sets driver parameter(s) <p> to value <v>.
|
|
-parameters <p=v,...>
|
|
-set_tgt_parm <target> : Sets target parameter(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-parameters <p=v,...>
|
|
-set_lun_parm <lun> : Sets LUN parameter(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-parameters <p=v,...>
|
|
-set_ini_parm <ini> : Sets initiator parameter(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-parameters <p=v,...>
|
|
|
|
Device Operations
|
|
-open_dev <device> : Adds a new device using handler <handler>.
|
|
-handler <handler>
|
|
-parameters <p=v,...>
|
|
-resync_dev <device> : Resync the device size with the initiator(s).
|
|
-close_dev <device> : Closes a device belonging to handler <handler>.
|
|
-handler <handler>
|
|
|
|
Group Operations
|
|
-add_group <group> : Add a group to a given driver & target.
|
|
-driver <driver>
|
|
-target <target>
|
|
-remove_group <group> : Remove a group from a given driver & target.
|
|
-driver <driver>
|
|
-target <target>
|
|
|
|
Initiator Operations
|
|
-add_init <init> : Adds an initiator to a group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-remove_init <user> : Removes an initiator from a group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-move_init <init> : Moves an initiator from one group to another.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group 1>
|
|
-to <group 2>
|
|
-clear_inits : Clear all initiators from a given group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
|
|
Target LUN Operations
|
|
-add_lun <lun> : Adds a given device to a group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-device <device>
|
|
-parameters <p=v,...>
|
|
-remove_lun <lun> : Remove a LUN from a group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-replace_lun <lun> : Replaces a LUN's device with a different one.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-device <device>
|
|
-parameters <p=v,...>
|
|
-clear_luns : Clear all LUNs within a group.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
|
|
Target Driver Operations
|
|
-enable_target <t> : Enable target mode for a given driver & target.
|
|
-driver <driver>
|
|
-disable_target <t> : Disable target mode for a given driver & target.
|
|
-driver <driver>
|
|
-issue_lip : Issue LIP on all target-enabled FC fabrics.
|
|
|
|
Options
|
|
-force : Force all configuration changes,
|
|
even deletions (DANGER!).
|
|
-noprompt : Do not prompt or pause. Use with caution!
|
|
|
|
Debugging (limited support)
|
|
-debug : Debug mode - don\'t do anything destructive.
|
|
|
|
Examples:
|
|
Open a new device:
|
|
scstadmin -open_dev DISK01 -handler vdisk_fileio \
|
|
-parameters filename=/vdisks/disk01.dsk,read_only
|
|
|
|
Setting the T10 Device ID of a device
|
|
scstadmin -set_dev_parm DISK01 -options t10_dev_id=0x2345
|
|
|
|
Create a new security group:
|
|
scstadmin -add_group HOST01 -driver qla2x00t \
|
|
-target 50:06:0B:00:00:39:71:78
|
|
|
|
Rename a security group:
|
|
scstadmin -rename_group HOST01 -to SERVER01 -driver qla2x00t \
|
|
-target 50:06:0B:00:00:39:71:78
|
|
|
|
Add a LUN to a group:
|
|
scstadmin -add_lun 1 -driver qla2x00t -target 50:06:0B:00:00:39:71:78 \
|
|
-group HOST01 -device DISK01 -parameters read_only=1
|
|
|
|
Enable target mode for fibre card specifying its WWN
|
|
scstadmin -enable_target 50:06:0B:00:00:39:71:78 -driver qla2x00t
|
|
|
|
Tell all initiators to rescan LUNs:
|
|
scstadmin -issue_lip
|
|
|
|
EndUsage
|
|
}
|
|
|
|
use SCST::SCST 0.9.0;
|
|
use Getopt::Long;
|
|
use IO::File;
|
|
use IO::Dir;
|
|
use POSIX;
|
|
use strict;
|
|
|
|
my $_DEF_CONFIG_ = '/etc/scst.conf';
|
|
|
|
use constant {
|
|
TRUE => 1,
|
|
FALSE => 0,
|
|
|
|
DEF_CONFIG => '/etc/scst.conf',
|
|
MAX_LUNS => 255,
|
|
};
|
|
|
|
my $SCST;
|
|
my $CONFIG;
|
|
my $_DEBUG_;
|
|
|
|
my %CURRENT;
|
|
|
|
$SIG{INT} = \&commitSuicide;
|
|
|
|
use vars qw($Version);
|
|
|
|
&main();
|
|
|
|
sub getArgs {
|
|
my $applyConfig;
|
|
my $clearConfig;
|
|
my $writeConfig;
|
|
my $checkConfig;
|
|
|
|
my $listHandler;
|
|
my $listDevice;
|
|
my $listDriver;
|
|
my $listTarget;
|
|
my $listGroup;
|
|
my $listSessions;
|
|
|
|
my $listScstParm;
|
|
my $listHandlerParm;
|
|
my $listDeviceParm;
|
|
my $listDriverParm;
|
|
my $listTargetParm;
|
|
my $listLunParm;
|
|
my $listInitiatorParm;
|
|
|
|
my $setScstParm;
|
|
my $setHandlerParm;
|
|
my $setDeviceParm;
|
|
my $setDriverParm;
|
|
my $setTargetParm;
|
|
my $setLunParm;
|
|
my $setInitiatorParm;
|
|
|
|
my $openDev;
|
|
my $closeDev;
|
|
my $resyncDev;
|
|
|
|
my $addGroup;
|
|
my $removeGroup;
|
|
|
|
my $addInitiator;
|
|
my $removeInitiator;
|
|
my $moveInitiator;
|
|
my $clearInitiators;
|
|
|
|
my $addLun;
|
|
my $removeLun;
|
|
my $replaceLun;
|
|
my $clearLuns;
|
|
|
|
my $enableTarget;
|
|
my $disableTarget;
|
|
my $issueLip;
|
|
|
|
my $handler;
|
|
my $parameters;
|
|
|
|
my $driver;
|
|
my $target;
|
|
my $group;
|
|
my $to;
|
|
my $device;
|
|
|
|
my $noprompt;
|
|
my $force;
|
|
|
|
my $p = new Getopt::Long::Parser;
|
|
|
|
if (!$p->getoptions('config:s' => \$applyConfig,
|
|
'clear_config' => \$clearConfig,
|
|
'write_config=s' => \$writeConfig,
|
|
'check_config:s' => \$checkConfig,
|
|
|
|
'list_handler:s' => \$listHandler,
|
|
'list_device:s' => \$listDevice,
|
|
'list_driver:s' => \$listDriver,
|
|
'list_target:s' => \$listTarget,
|
|
'list_group:s' => \$listGroup,
|
|
'list_sessions' => \$listSessions,
|
|
|
|
'list_scst_parm' => \$listScstParm,
|
|
'list_hnd_parm=s' => \$listHandlerParm,
|
|
'list_dev_parm=s' => \$listDeviceParm,
|
|
'list_drv_parm=s' => \$listDriverParm,
|
|
'list_tgt_parm=s' => \$listTargetParm,
|
|
'list_lun_parm=s' => \$listLunParm,
|
|
'list_ini_parm=s' => \$listInitiatorParm,
|
|
|
|
'set_scst_parm' => \$setScstParm,
|
|
'set_hnd_parm=s' => \$setHandlerParm,
|
|
'set_dev_parm=s' => \$setDeviceParm,
|
|
'set_drv_parm=s' => \$setDriverParm,
|
|
'set_tgt_parm=s' => \$setTargetParm,
|
|
'set_lun_parm=s' => \$setLunParm,
|
|
'set_ini_parm=s' => \$setInitiatorParm,
|
|
|
|
'open_dev=s' => \$openDev,
|
|
'close_dev=s' => \$closeDev,
|
|
'resync_dev=s' => \$resyncDev,
|
|
|
|
'add_group=s' => \$addGroup,
|
|
'remove_group=s' => \$removeGroup,
|
|
|
|
'add_init=s' => \$addInitiator,
|
|
'remove_init=s' => \$removeInitiator,
|
|
'move_init=s' => \$moveInitiator,
|
|
'clear_inits' => \$clearInitiators,
|
|
|
|
'add_lun=s' => \$addLun,
|
|
'remove_lun=s' => \$removeLun,
|
|
'replace_lun=s' => \$replaceLun,
|
|
'clear_luns=s' => \$clearLuns,
|
|
|
|
'enable_target=s' => \$enableTarget,
|
|
'disable_target=s' => \$disableTarget,
|
|
'issue_lip' => \$issueLip,
|
|
|
|
'handler=s' => \$handler,
|
|
'parameters=s' => \$parameters,
|
|
|
|
'driver=s' => \$driver,
|
|
'target=s' => \$target,
|
|
'group=s' => \$group,
|
|
'to=s' => \$to,
|
|
'device=s' => \$device,
|
|
|
|
'noprompt' => \$noprompt,
|
|
'force' => \$force,
|
|
'debug' => \$_DEBUG_)) {
|
|
usage();
|
|
}
|
|
|
|
$_DEBUG_ = TRUE if (defined($_DEBUG_));
|
|
|
|
$force = TRUE if (defined($force));
|
|
$noprompt = TRUE if (defined($noprompt));
|
|
$clearInitiators = TRUE if (defined($clearInitiators));
|
|
$clearLuns = TRUE if (defined($clearLuns));
|
|
$issueLip = TRUE if (defined($issueLip));
|
|
$listSessions = TRUE if (defined($listSessions));
|
|
$listScstParm = TRUE if (defined($listScstParm));
|
|
$setScstParm = TRUE if (defined($setScstParm));
|
|
|
|
my $query_mode = defined($listHandler) || defined($listDevice) || defined($listDriver) ||
|
|
defined($listTarget) || defined($listGroup) || defined($listSessions) || defined($listScstParm) ||
|
|
defined($listHandlerParm) || defined($listDeviceParm) || defined($listDriverParm) ||
|
|
defined($listTargetParm) || defined($listLunParm) || defined($listInitiatorParm);
|
|
|
|
my $set_mode = defined($setScstParm) + defined($setHandlerParm) + defined($setDeviceParm) +
|
|
defined($setDriverParm) + defined($setTargetParm) + defined($setLunParm) + defined($setInitiatorParm);
|
|
|
|
my $op_mode = defined($clearConfig) + defined($writeConfig) + defined($checkConfig) +
|
|
defined($openDev) + defined($closeDev) + defined($addGroup) + defined($removeGroup) +
|
|
defined($addInitiator) + defined($removeInitiator) + defined($clearInitiators) +
|
|
defined($addLun) + defined($removeLun) + defined($replaceLun) + defined($clearLuns) +
|
|
defined($enableTarget) + defined($disableTarget) + defined($issueLip);
|
|
|
|
if (($query_mode + $set_mode + $op_mode) > 1) {
|
|
print "Please specify only one non-query operation at a time.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($clearConfig && !$force) {
|
|
print "Please specify -force with -clear_config.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($listTargetParm && !$driver) {
|
|
print "Please specify -driver with -list_tgt_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($listLunParm && (!$driver || !$target || !$group)) {
|
|
print "Please specify -driver -target and -group with -list_lun_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($listInitiatorParm && (!$driver || !$target || !$group)) {
|
|
print "Please specify -driver -target and -group with -list_ini_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setScstParm && !$parameters) {
|
|
print "Please specify -parameters with -set_scst_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setHandlerParm && !$parameters) {
|
|
print "Please specify -parameters with -set_hnd_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDeviceParm && !$parameters) {
|
|
print "Please specify -parameters with -set_dev_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDriverParm && !$parameters) {
|
|
print "Please specify -parameters with -set_drv_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setTargetParm && (!$driver || !$parameters)) {
|
|
print "Please specify -driver and -parameters with -set_tgt_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setLunParm && (!$driver || !$target || !$group || !$parameters)) {
|
|
print "Please specify -driver -target -group and -parameters with -set_lun_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDeviceParm && (!$driver || !$target || !$group || !$parameters)) {
|
|
print "Please specify -driver -target -group and -parameters with -set_ini_parm.\n";
|
|
usage();
|
|
}
|
|
|
|
if (($openDev || $closeDev) && !$handler) {
|
|
print "Please specify -handler with -open_dev/-close_dev.\n";
|
|
usage();
|
|
}
|
|
|
|
if (($addGroup || $removeGroup) && (!$driver || !$target)) {
|
|
print "Please specify -driver and -target with -add_group/-remove_group.\n";
|
|
usage();
|
|
}
|
|
|
|
if (($addInitiator || $removeInitiator || $clearInitiators) &&
|
|
(!$target || !$driver || !$group)) {
|
|
print "Please specify -driver -target and -group with ".
|
|
"-add_init/-remove_init/-clear_inits.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($moveInitiator && (!$driver || !$target || !$group || !$to)) {
|
|
print "Please specify -driver -target -group and -to with -move_init.\n";
|
|
usage();
|
|
}
|
|
|
|
if (($addLun || $replaceLun || $removeLun) && (!$driver || !$target || !$group || !$device)) {
|
|
print "Please specify -driver -target -group and -device with -add_lun/-replace_lun.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($clearLuns && (!$driver || !$target || !$group)) {
|
|
print "Please specify -driver -target and -group with -remove_lun/-clear_luns.\n";
|
|
usage();
|
|
}
|
|
|
|
$applyConfig = $_DEF_CONFIG_ if (defined($applyConfig) && !$applyConfig);
|
|
$checkConfig = $_DEF_CONFIG_ if (defined($checkConfig) && !$checkConfig);
|
|
|
|
my %_parameters;
|
|
if ($parameters) {
|
|
foreach my $parameter (split(/\,/, $parameters)) {
|
|
my $value;
|
|
|
|
if ($parameter =~ /\=/) {
|
|
$value = TRUE;
|
|
} else {
|
|
($parameter, $value) = split(/\=/, $parameter, 2);
|
|
}
|
|
|
|
$_parameters{$parameter} = $value;
|
|
}
|
|
}
|
|
|
|
return ($applyConfig, $clearConfig, $writeConfig, $checkConfig,
|
|
$listScstParm, $listHandler, $listDevice, $listDriver, $listTarget, $listGroup,
|
|
$listSessions, $listHandlerParm, $listDeviceParm, $listDriverParm, $listTargetParm,
|
|
$listLunParm, $listInitiatorParm, $setScstParm, $setHandlerParm, $setDeviceParm,
|
|
$setDriverParm, $setTargetParm, $setLunParm, $setInitiatorParm,
|
|
$openDev, $closeDev, $resyncDev,
|
|
$addGroup, $removeGroup,
|
|
$addInitiator, $removeInitiator, $moveInitiator, $clearInitiators,
|
|
$addLun, $removeLun, $replaceLun, $clearLuns,
|
|
$enableTarget, $disableTarget, $issueLip,
|
|
$handler, \%_parameters,
|
|
$driver, $target, $group, $to, $device,
|
|
$noprompt, $force);
|
|
}
|
|
|
|
sub main {
|
|
my $rc;
|
|
|
|
STDOUT->autoflush(1);
|
|
|
|
# We need to run as root
|
|
if ( $> ) {die("This program must run as root.\n");}
|
|
|
|
my ($applyConfig, $clearConfig, $writeConfig, $checkConfig,
|
|
$listScstParm, $listHandler, $listDevice, $listDriver, $listTarget, $listGroup,
|
|
$listSessions, $listHandlerParm, $listDeviceParm, $listDriverParm, $listTargetParm,
|
|
$listLunParm, $listInitiatorParm, $setScstParm, $setHandlerParm, $setDeviceParm,
|
|
$setDriverParm, $setTargetParm, $setLunParm, $setInitiatorParm,
|
|
$openDev, $closeDev, $resyncDev,
|
|
$addGroup, $removeGroup,
|
|
$addInitiator, $removeInitiator, $moveInitiator, $clearInitiators,
|
|
$addLun, $removeLun, $replaceLun, $clearLuns,
|
|
$enableTarget, $disableTarget, $issueLip,
|
|
$handler, $parameters,
|
|
$driver, $target, $group, $to, $device,
|
|
$noprompt, $force) = getArgs();
|
|
|
|
$SCST = new SCST::SCST($_DEBUG_);
|
|
|
|
readWorkingConfig();
|
|
|
|
my $all_good;
|
|
|
|
SWITCH: {
|
|
$applyConfig && do {
|
|
$rc = checkConfiguration($applyConfig);
|
|
immediateExit("Configuration has errors, aborting.") if ($rc);
|
|
$rc = applyConfiguration($applyConfig, $force);
|
|
last SWITCH;
|
|
};
|
|
$checkConfig && do {
|
|
$rc = checkConfiguration($checkConfig);
|
|
last SWITCH;
|
|
};
|
|
$writeConfig && do {
|
|
$rc = writeConfiguration($writeConfig);
|
|
last SWITCH;
|
|
};
|
|
$clearConfig && do {
|
|
$rc = clearConfiguration($noprompt, $force);
|
|
last SWITCH;
|
|
};
|
|
defined($listHandler) && do {
|
|
$rc = listHandlers($listHandler);
|
|
$all_good = TRUE;
|
|
};
|
|
defined($listDevice) && do {
|
|
$rc = listDevices($listDevice);
|
|
$all_good = TRUE;
|
|
};
|
|
defined($listDriver) && do {
|
|
$rc = listDrivers($listDriver);
|
|
$all_good = TRUE;
|
|
};
|
|
defined($listTarget) && do {
|
|
$rc = listTargets($listTarget, $driver);
|
|
$all_good = TRUE;
|
|
};
|
|
defined($listGroup) && do {
|
|
$rc = listGroups($listGroup, $driver, $target);
|
|
$all_good = TRUE;
|
|
};
|
|
$listSessions && do {
|
|
$rc = listSessions();
|
|
$all_good = TRUE;
|
|
};
|
|
$listScstParm && do {
|
|
$rc = listScstParm();
|
|
$all_good = TRUE;
|
|
};
|
|
$listHandlerParm && do {
|
|
$rc = listHandlerParameters($listHandlerParm);
|
|
$all_good = TRUE;
|
|
};
|
|
$listDeviceParm && do {
|
|
$rc = listDeviceParameters($listDeviceParm);
|
|
$all_good = TRUE;
|
|
};
|
|
$listDriverParm && do {
|
|
$rc = listDriverParameters($listHandlerParm);
|
|
$all_good = TRUE;
|
|
};
|
|
$listTargetParm && do {
|
|
$rc = listTargetParameters($listTargetParm, $driver);
|
|
$all_good = TRUE;
|
|
};
|
|
$listLunParm && do {
|
|
$rc = listLunParameters($listLunParm, $driver, $target, $group);
|
|
$all_good = TRUE;
|
|
};
|
|
$listInitiatorParm && do {
|
|
$rc = listInitiatorParameters($listInitiatorParm, $driver, $target, $group);
|
|
$all_good = TRUE;
|
|
};
|
|
$setScstParm && do {
|
|
$rc = setScstParameters($parameters);
|
|
last SWITCH;
|
|
};
|
|
$setHandlerParm && do {
|
|
$rc = setHandlerParameters($setHandlerParm, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$setDeviceParm && do {
|
|
$rc = setDeviceParameters($setDeviceParm, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$setDriverParm && do {
|
|
$rc = setDriverParameters($setDriverParm, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$setTargetParm && do {
|
|
$rc = setTargetParameters($setTargetParm, $driver, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$setLunParm && do {
|
|
$rc = setLunParameters($setLunParm, $driver, $target, $parameters, $group);
|
|
last SWITCH;
|
|
};
|
|
$setInitiatorParm && do {
|
|
$rc = setInitiatorParameters($setInitiatorParm, $driver, $target, $group, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$openDev && do {
|
|
$rc = openDevice($openDev, $handler, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$closeDev && do {
|
|
$rc = closeDevice($closeDev, $handler, $force);
|
|
last SWITCH;
|
|
};
|
|
$resyncDev && do {
|
|
$rc = resyncDevice($resyncDev);
|
|
last SWITCH;
|
|
};
|
|
$addGroup && do {
|
|
$rc = addGroup($addGroup, $driver, $target);
|
|
last SWITCH;
|
|
};
|
|
$removeGroup && do {
|
|
$rc = removeGroup($removeGroup, $driver, $target, $force);
|
|
last SWITCH;
|
|
};
|
|
$addInitiator && do {
|
|
$rc = addInitiator($addInitiator, $driver, $target, $group);
|
|
last SWITCH;
|
|
};
|
|
$removeInitiator && do {
|
|
$rc = removeInitiator($removeInitiator, $driver, $target, $group);
|
|
last SWITCH;
|
|
};
|
|
$moveInitiator && do {
|
|
$rc = moveInitiator($moveInitiator, $driver, $target, $group, $to);
|
|
last SWITCH;
|
|
};
|
|
$clearInitiators && do {
|
|
$rc = clearInitiators($driver, $target, $group);
|
|
last SWITCH;
|
|
};
|
|
$addLun && do {
|
|
$rc = addLun($addLun, $driver, $target, $device, $parameters, $group);
|
|
last SWITCH;
|
|
};
|
|
$removeLun && do {
|
|
$rc = removeLun($removeLun, $driver, $target, $device, $group);
|
|
last SWITCH;
|
|
};
|
|
$replaceLun && do {
|
|
$rc = replaceLun($replaceLun, $driver, $target, $group, $device, $parameters);
|
|
last SWITCH;
|
|
};
|
|
$clearLuns && do {
|
|
$rc = clearLuns($driver, $target, $group);
|
|
last SWITCH;
|
|
};
|
|
$enableTarget && do {
|
|
$rc = enableTarget($enableTarget);
|
|
last SWITCH;
|
|
};
|
|
$disableTarget && do {
|
|
$rc = disableTarget($disableTarget);
|
|
last SWITCH;
|
|
};
|
|
$issueLip && do {
|
|
$rc = issueLip();
|
|
last SWITCH;
|
|
};
|
|
|
|
if (!$all_good) {
|
|
print "No valid operations specified.\n";
|
|
usage();
|
|
exit TRUE;
|
|
}
|
|
}
|
|
|
|
print "\nAll done.\n";
|
|
|
|
exit $rc;
|
|
}
|
|
|
|
sub readWorkingConfig {
|
|
print "Collecting current configuration: ";
|
|
|
|
%CURRENT = ();
|
|
|
|
# Get current handlers/devices
|
|
|
|
my $handlers = $SCST->handlers();
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $handler (@{$handlers}) {
|
|
my $devices = $SCST->devicesByHandler($handler);
|
|
immediateExit($SCST->errorString());
|
|
$CURRENT{'handler'}->{$handler} = $devices;
|
|
}
|
|
|
|
# Get current assignments
|
|
|
|
my $drivers = $SCST->drivers();
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $driver (@{$drivers}) {
|
|
my %empty;
|
|
$CURRENT{'assign'}->{$driver} = \%empty;
|
|
my $targets = $SCST->targets($driver);
|
|
immediateExit($SCST->errorString());
|
|
foreach my $target (@{$targets}) {
|
|
my %empty;
|
|
$CURRENT{'assign'}->{$driver}->{$target} = \%empty;
|
|
|
|
my $luns = $SCST->luns($driver, $target);
|
|
$CURRENT{'assign'}->{$driver}->{$target}->{'LUNS'} = $luns if (defined($luns));
|
|
|
|
my $groups = $SCST->groups($driver, $target);
|
|
immediateExit($SCST->errorString());
|
|
foreach my $group (@{$groups}) {
|
|
$CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'INITIATORS'} =
|
|
$SCST->initiators($driver, $target, $group);
|
|
immediateExit($SCST->errorString());
|
|
$CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'LUNS'} =
|
|
$SCST->luns($driver, $target, $group);
|
|
immediateExit($SCST->errorString());
|
|
}
|
|
}
|
|
}
|
|
|
|
print "done.\n\n";
|
|
}
|
|
|
|
sub writeConfiguration {
|
|
my $file = shift;
|
|
|
|
if (-f $file) {
|
|
if (!unlink $file) {
|
|
print "Failed to save current configuration, specified ".
|
|
"file exists and cannot be deleted.\n";
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
my $io = new IO::File $file, O_CREAT|O_WRONLY;
|
|
|
|
if (!$io) {
|
|
print "Failed to save configuration to file '$file': $!\n";
|
|
return 1;
|
|
}
|
|
|
|
print "Writing current configuration to file '$file'.. ";
|
|
|
|
print $io "# Automatically generated by $Version.\n\n";
|
|
|
|
my $parameters = $SCST->scstParameters();
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (!$$parameters{$parameter}->{'static'}) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
print $io "$parameter $value\n" if (defined($value));
|
|
}
|
|
}
|
|
|
|
print $io "\n";
|
|
|
|
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
|
|
my $handler_buff;
|
|
|
|
my $handler_params = $SCST->deviceCreateParameters($handler);
|
|
|
|
$parameters = $SCST->handlerParameters($handler);
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (!$$parameters{$parameter}->{'static'}) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$handler_buff .= "\t$parameter $value\n" if (defined($value));
|
|
}
|
|
}
|
|
|
|
my $devices = $CURRENT{'handler'}->{$handler};
|
|
|
|
my $device_buff;
|
|
foreach my $device (@{$devices}) {
|
|
$device_buff .= "\tDEVICE $device";
|
|
|
|
$parameters = $SCST->deviceParameters($device);
|
|
|
|
my $parameter_buff;
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (!defined($$handler_params{$parameter})) {
|
|
if (!$$parameters{$parameter}->{'static'}) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if (defined($value)) {
|
|
$parameter_buff .= "\t\t$parameter $value\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$parameter_buff .= "\n" if ($parameter_buff);
|
|
|
|
if (!defined($$parameters{'scsi_device'})) {
|
|
$parameter_buff .= "\t\tCREATE_ATTRIBUTES {\n";
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (defined($$handler_params{$parameter})) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$parameter_buff .= "\t\t\t$parameter $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
|
|
$parameter_buff .= "\t\t}\n";
|
|
}
|
|
|
|
if ($parameter_buff) {
|
|
$device_buff .= " {\n";
|
|
$device_buff .= $parameter_buff;
|
|
$device_buff .= "\t}\n\n";
|
|
} else {
|
|
$device_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
$device_buff =~ s/\n+$/\n/;
|
|
|
|
$handler_buff .= $device_buff;
|
|
|
|
if ($handler_buff) {
|
|
print $io "HANDLER $handler {\n";
|
|
print $io $handler_buff;
|
|
print $io "}\n\n";
|
|
}
|
|
}
|
|
|
|
foreach my $driver (sort keys %{$CURRENT{'assign'}}) {
|
|
my $driver_buff;
|
|
|
|
my $targets = $CURRENT{'assign'}->{$driver};
|
|
|
|
my $target_buff;
|
|
foreach my $target (sort keys %{$targets}) {
|
|
$target_buff .= "\tTARGET $target";
|
|
|
|
my $tgt_params = $SCST->targetParameters($driver, $target);
|
|
|
|
my $parameter_buff;
|
|
foreach my $parm (keys %{$tgt_params}) {
|
|
next if ($$tgt_params{$parm}->{'static'});
|
|
next if ($$tgt_params{$parm}->{'set'});
|
|
|
|
my $value = $$tgt_params{$parm}->{'value'};
|
|
|
|
next if (!defined($value));
|
|
|
|
$value = "\"$value\"" if ($value =~ /\s/);
|
|
|
|
$parameter_buff .= "\t\t$parm $value\n";
|
|
}
|
|
|
|
$parameter_buff .= "\n" if ($parameter_buff);
|
|
|
|
my $groups = $CURRENT{'assign'}->{$driver}->{$target};
|
|
|
|
my $group_buff;
|
|
foreach my $group (sort keys %{$groups}) {
|
|
my $lun_params = $SCST->lunCreateParameters($driver, $target, $group);
|
|
my $ini_params = $SCST->initiatorCreateParameters($driver, $target, $group);
|
|
|
|
$group_buff .= "\t\tGROUP $group";
|
|
|
|
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'LUNS'};
|
|
|
|
my $lun_buff;
|
|
foreach my $lun (sort numerically keys %{$luns}) {
|
|
my $lun_dev = $$luns{$lun};
|
|
|
|
$lun_buff .= "\t\t\tLUN $lun $lun_dev";
|
|
|
|
$parameters = $SCST->lunParameters($driver, $target, $lun, $group);
|
|
|
|
my $parameter_buff;
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (!$$parameters{$parameter}->{'static'} ||
|
|
defined($$lun_params{$parameter})) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$parameter_buff .= "\t\t\t\t$parameter $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
|
|
if ($parameter_buff) {
|
|
$lun_buff .= " {\n";
|
|
$lun_buff .= $parameter_buff;
|
|
$lun_buff .= "\t\t\t}\n\n";
|
|
} else {
|
|
$lun_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'INITIATORS'};
|
|
|
|
my $init_buff;
|
|
foreach my $init (@{$inits}) {
|
|
$init_buff .= "\t\t\tINITIATOR $init";
|
|
|
|
$parameters = $SCST->initiatorParameters($driver, $target, $group, $init);
|
|
|
|
my $parameter_buff;
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
next if (defined($$parameters{$parameter}->{'set'}));
|
|
|
|
if (!$$parameters{$parameter}->{'static'} ||
|
|
defined($$ini_params{$parameter})) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$parameter_buff .= "\t\t\t\t$parameter $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
|
|
if ($parameter_buff) {
|
|
$init_buff .= " {\n";
|
|
$init_buff .= $parameter_buff;
|
|
$init_buff .= "\t\t\t}\n";
|
|
} else {
|
|
$init_buff .= "\n";
|
|
}
|
|
|
|
$init_buff .= "\n";
|
|
}
|
|
|
|
$init_buff =~ s/\n\n$/\n/;
|
|
|
|
if ($lun_buff || $init_buff) {
|
|
$group_buff .= " {\n";
|
|
|
|
if ($lun_buff) {
|
|
$group_buff .= $lun_buff;
|
|
}
|
|
|
|
if ($init_buff) {
|
|
$group_buff .= $init_buff;
|
|
}
|
|
|
|
$group_buff =~ s/\n\n$/\n/;
|
|
$group_buff .= "\t\t}\n\n";
|
|
}
|
|
|
|
$group_buff .= "\n";
|
|
$group_buff =~ s/\n\n$/\n/;
|
|
}
|
|
|
|
$group_buff .= "\n" if ($group_buff);
|
|
|
|
if ($parameter_buff || $group_buff ) {
|
|
$target_buff .= " {\n";
|
|
|
|
if ($parameter_buff) {
|
|
$target_buff .= $parameter_buff;
|
|
}
|
|
|
|
if ($group_buff) {
|
|
$target_buff .= $group_buff;
|
|
}
|
|
|
|
$target_buff =~ s/\n\n$/\n/;
|
|
$target_buff .= "\t}\n\n";
|
|
} else {
|
|
$target_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
$driver_buff .= $target_buff;
|
|
$driver_buff =~ s/\n\n$/\n/;
|
|
|
|
if ($driver_buff) {
|
|
print $io "TARGET_DRIVER $driver {\n";
|
|
print $io $driver_buff;
|
|
print $io "}\n\n";
|
|
}
|
|
}
|
|
|
|
close $io;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
sub checkConfiguration {
|
|
my $file = shift;
|
|
my $no_drivers;
|
|
my $no_handlers;
|
|
|
|
print "-> Checking configuration file '$file' for errors.\n";
|
|
|
|
$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" if ($SCST->driverIsStatic($driver));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
use Data::Dumper;
|
|
#print Dumper($CONFIG);
|
|
#print Dumper(\%CURRENT);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
sub applyConfiguration {
|
|
my $file = shift;
|
|
my $force = shift;
|
|
|
|
$CONFIG = readConfig($file) if (!$CONFIG);
|
|
|
|
# Apply config deletions
|
|
if ($force) {
|
|
applyConfigAssignments($CONFIG, $force);
|
|
applyConfigDevices($CONFIG, $force);
|
|
|
|
readWorkingConfig();
|
|
}
|
|
|
|
# Apply config additions
|
|
applyConfigDevices($CONFIG, FALSE);
|
|
applyConfigAssignments($CONFIG, FALSE);
|
|
|
|
# And SCST parameters..
|
|
my %_parameters;
|
|
foreach my $item (keys %{$CONFIG}) {
|
|
next if ($item eq 'HANDLER');
|
|
next if ($item eq 'TARGET_DRIVER');
|
|
$_parameters{$item} = $$CONFIG{$item};
|
|
}
|
|
|
|
my $parameters = configToParm(\%_parameters);
|
|
|
|
setScstParameters($parameters);
|
|
}
|
|
|
|
sub applyConfigDevices {
|
|
my $config = shift;
|
|
my $deletions = shift;
|
|
|
|
my $handlers = $CURRENT{'handler'};
|
|
|
|
foreach my $handler (keys %{$handlers}) {
|
|
foreach my $device (@{$$handlers{$handler}}) {
|
|
if (!defined($$config{'HANDLER'}) ||
|
|
!defined($$config{'HANDLER'}->{$handler}) ||
|
|
!defined($$config{'HANDLER'}->{$handler}->{'DEVICE'}) ||
|
|
!defined($$config{'HANDLER'}->{$handler}->{'DEVICE'}->{$device})) {
|
|
|
|
my $parameters = $SCST->deviceParameters($device);
|
|
|
|
next if (defined($$parameters{'scsi_device'}));
|
|
|
|
if ($deletions) {
|
|
closeDevice($device, $handler, $deletions);
|
|
} else {
|
|
print "\t-> Device '$device' is not in configuration. Use -force to close it.\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$handlers = $$config{'HANDLER'};
|
|
|
|
foreach my $handler (sort keys %{$handlers}) {
|
|
if (defined($$handlers{$handler}->{'DEVICE'})) {
|
|
my $devices = $$handlers{$handler}->{'DEVICE'};
|
|
|
|
foreach my $device (sort keys %{$devices}) {
|
|
next if (handlerHasDevice($handler, $device));
|
|
|
|
my $parameters = configToParm($$devices{$device}->{'CREATE_ATTRIBUTES'});
|
|
openDevice($device, $handler, $parameters);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub applyConfigAssignments {
|
|
my $config = shift;
|
|
my $deletions = shift;
|
|
|
|
my $assignments = $CURRENT{'assign'};
|
|
|
|
foreach my $driver (keys %{$assignments}) {
|
|
foreach my $target (keys %{$$assignments{$driver}}) {
|
|
my $luns = $$assignments{$driver}->{$target}->{'LUNS'};
|
|
my $def_group = $$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target};
|
|
|
|
foreach my $lun (keys %{$luns}) {
|
|
my $device = $$luns{$lun};
|
|
|
|
if (!defined($$def_group{'LUN'}) ||
|
|
!defined($$def_group{'LUN'}->{$lun}) ||
|
|
!defined($$def_group{'LUN'}->{$lun}->{$device})) {
|
|
if ($deletions) {
|
|
removeLun($lun, $driver, $target, $device);
|
|
} else {
|
|
print "\t-> Device '$device' at LUN '$lun' is not in configuration ".
|
|
"for driver/target '$driver/$target'. ".
|
|
"Use -force to remove it.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach my $group (keys %{$$assignments{$driver}->{$target}}) {
|
|
next if ($group eq 'LUNS');
|
|
|
|
my $luns = $$assignments{$driver}->{$target}->{$group}->{'LUNS'};
|
|
my $inits = $$assignments{$driver}->{$target}->{$group}->{'INITIATORS'};
|
|
|
|
if (!defined($$config{'TARGET_DRIVER'}) ||
|
|
!defined($$config{'TARGET_DRIVER'}->{$driver}) ||
|
|
!defined($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}) ||
|
|
!defined($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}) ||
|
|
!defined($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}) ||
|
|
!defined($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group})) {
|
|
if ($deletions) {
|
|
removeGroup($group, $driver, $target);
|
|
} else {
|
|
print "\t-> Group '$group' is not in configuration. Use -force to remove.\n";
|
|
}
|
|
|
|
next;
|
|
}
|
|
|
|
my $def_group = $$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group};
|
|
|
|
foreach my $lun (keys %{$luns}) {
|
|
my $device = $$luns{$lun};
|
|
|
|
if (!defined($$def_group{'LUN'}) ||
|
|
!defined($$def_group{'LUN'}->{$lun}) ||
|
|
!defined($$def_group{'LUN'}->{$lun}->{$device})) {
|
|
if ($deletions) {
|
|
removeLun($lun, $driver, $target, $device, $group);
|
|
} else {
|
|
print "\t-> Device '$device' at LUN '$lun' is not in configuration ".
|
|
"for driver/target/group '$driver/$target/$group'. ".
|
|
"Use -force to remove it.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach my $init (@{$inits}) {
|
|
if (!defined($$def_group{'INITIATOR'}) ||
|
|
!defined($$def_group{'INITIATOR'}->{$init})) {
|
|
if ($deletions) {
|
|
removeInitiator($init, $driver, $target, $group);
|
|
} else {
|
|
print "\t-> Initiator '$init' is not in configuration ".
|
|
"for driver/target/group '$driver/$target/$group'. ".
|
|
"Use -force to remove it.\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$assignments = $$config{'TARGET_DRIVER'};
|
|
|
|
foreach my $driver (sort keys %{$assignments}) {
|
|
if (!defined($CURRENT{'assign'}->{$driver})) {
|
|
immediateExit("Target driver '$driver' is not loaded or available.");
|
|
}
|
|
|
|
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);
|
|
|
|
setDriverParameters($driver, $parameters);
|
|
}
|
|
}
|
|
}
|
|
|
|
sub applyTargetAssignments {
|
|
my $driver = shift;
|
|
my $targets = shift;
|
|
|
|
foreach my $target (sort keys %{$targets}) {
|
|
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
|
|
if ($SCST->driverIsStatic($driver)) {
|
|
immediateExit("Target '$target' for driver '$driver' does not exist.");
|
|
} else {
|
|
# TODO: Add $parameters
|
|
print "-> Creating target '$target' for driver '$driver': ";
|
|
my $rc = $SCST->addTarget($driver, $target);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
}
|
|
|
|
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, undef, $$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;
|
|
|
|
if ($group) {
|
|
$c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{$group}->{'LUNS'};
|
|
} else {
|
|
$c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUNS'};
|
|
}
|
|
#use Data::Dumper;
|
|
#print Dumper(\%CURRENT);
|
|
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, $device, $parameters, $group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
sub clearConfiguration {
|
|
my $noprompt = shift;
|
|
my $force = shift;
|
|
|
|
my $assignments = $CURRENT{'assign'};
|
|
|
|
foreach my $driver (sort keys %{$assignments}) {
|
|
foreach my $target (sort keys %{$$assignments{$driver}}) {
|
|
foreach my $group (sort keys %{$$assignments{$driver}->{$target}}) {
|
|
clearInitiators($driver, $target, $group);
|
|
clearLuns($driver, $target, $group);
|
|
removeGroup($group, $driver, $target, $force);
|
|
}
|
|
}
|
|
}
|
|
|
|
my $handlers = $CURRENT{'handler'};
|
|
|
|
foreach my $handler (sort keys %{$handlers}) {
|
|
foreach my $device (@{$$handlers{$handler}}) {
|
|
my $parameters = $SCST->deviceParameters($device);
|
|
if (!defined($$parameters{'scsi_device'})) {
|
|
closeDevice($device, $handler, $force);
|
|
}
|
|
}
|
|
}
|
|
|
|
# TODO: should we disable all target drivers as well?
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub listHandlers {
|
|
my $handler = shift;
|
|
|
|
return listHandler($handler) if ($handler);
|
|
|
|
my $handlers = $SCST->handlers();
|
|
|
|
my $l_handler;
|
|
foreach my $handler (@{$handlers}) {
|
|
$l_handler = length($handler) if ($l_handler < length($handler));
|
|
}
|
|
|
|
print "\tHandler\n";
|
|
print "\t";
|
|
for (my $x = 0; $x < $l_handler; $x++) {
|
|
print "-";
|
|
};
|
|
print "\n";
|
|
|
|
foreach my $handler (@{$handlers}) {
|
|
print "\t$handler\n";
|
|
}
|
|
}
|
|
|
|
sub listHandler {
|
|
my $handler = shift;
|
|
|
|
my $devices = $SCST->devicesByHandler($handler);
|
|
|
|
if ($#{$devices} > -1) {
|
|
my $l_device;
|
|
foreach my $device (@{$devices}) {
|
|
$l_device = length($device) if ($l_device < length($device));
|
|
}
|
|
|
|
printf("\t%-*s %-*s\n", length($handler), 'Handler', $l_device, 'Device');
|
|
print "\t";
|
|
for (my $x = 0; $x < (length($handler) + $l_device + 2); $x++) {
|
|
print "-";
|
|
};
|
|
print "\n";
|
|
|
|
my $first = TRUE;
|
|
foreach my $device (@{$devices}) {
|
|
if ($first) {
|
|
printf("\t%-*s %-*s\n", length($handler), $handler, $l_device, $device);
|
|
$first = FALSE;
|
|
} else {
|
|
printf("\t%-*s %-*s\n", length($handler), '', $l_device, $device);
|
|
}
|
|
}
|
|
} else {
|
|
print "\t(handler '$handler' has no assigned devices)\n";
|
|
}
|
|
}
|
|
|
|
sub listDevices {
|
|
my $device = shift;
|
|
|
|
listDevice($device) if ($device);
|
|
|
|
}
|
|
|
|
sub listDevice {
|
|
my $device = shift;
|
|
|
|
}
|
|
|
|
sub listDrivers {
|
|
my $driver = shift;
|
|
|
|
return listTargets(undef, $driver) if ($driver);
|
|
|
|
my $drivers = $SCST->drivers();
|
|
|
|
my $l_driver;
|
|
foreach my $driver (@{$drivers}) {
|
|
$l_driver = length($driver) if ($l_driver < length($driver));
|
|
}
|
|
|
|
print "\tDriver\n";
|
|
print "\t";
|
|
for (my $x = 0; $x < $l_driver; $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $driver (@{$drivers}) {
|
|
print "\t$driver\n";
|
|
}
|
|
}
|
|
|
|
sub listTargets {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
|
|
return listGroups(undef, $driver, $target) if ($target && $driver);
|
|
|
|
my $drivers = $SCST->drivers();
|
|
|
|
my $l_driver;
|
|
my $l_target;
|
|
foreach my $driver (@{$drivers}) {
|
|
$l_driver = length($driver) if ($l_driver < length($driver));
|
|
|
|
my $targets = $SCST->targets($driver);
|
|
|
|
foreach my $target (@{$targets}) {
|
|
$l_target = length($target) if ($l_target < length($target));
|
|
}
|
|
}
|
|
|
|
printf("\t%-*s %-*s\n", $l_driver, 'Driver', $l_target, 'Target');
|
|
print "\t";
|
|
for (my $x = 0; $x < ($l_driver + $l_target + 1); $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
my %p;
|
|
|
|
foreach my $driver (@{$drivers}) {
|
|
my $targets = $SCST->targets($driver);
|
|
|
|
foreach my $target (@{$targets}) {
|
|
if (!defined($p{$driver})) {
|
|
printf("\t%-*s %-*s\n", $l_driver, $driver, $l_target, $target);
|
|
$p{$driver}++;
|
|
} else {
|
|
printf("\t%-*s %-*s\n", $l_driver, '', $l_target, $target);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub listSessions {
|
|
|
|
}
|
|
|
|
sub listGroup {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $luns = shift;
|
|
my $initiators = shift;
|
|
|
|
$luns = $SCST->luns($driver, $target, $group) if (!$luns);
|
|
$initiators = $SCST->initiators($driver, $target, $group) if (!$initiators);
|
|
|
|
if ((keys %{$luns}) || ($#{$initiators} > -1)) {
|
|
my $l_device;
|
|
my $l_initiator;
|
|
|
|
foreach my $lun (keys %{$luns}) {
|
|
$l_device = length($$luns{$lun}) if (length($$luns{$lun}) > $l_device);
|
|
}
|
|
|
|
foreach my $initiator (@{$initiators}) {
|
|
$l_initiator = length($initiator) if (length($initiator) > $l_initiator);
|
|
}
|
|
|
|
print "Assigned LUNs:\n\n";
|
|
|
|
if (keys %{$luns}) {
|
|
printf("\t%-4s %-*s\n", 'LUN', $l_device, 'Device');
|
|
print "\t";
|
|
for (my $x = 0; $x < ($l_device + 5); $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $lun (sort keys %{$luns}) {
|
|
my $device = $$luns{$lun};
|
|
|
|
printf("\t%-4s %-*s\n", $lun, $l_device, $$luns{$lun});
|
|
}
|
|
} else {
|
|
print "\t(none)\n";
|
|
}
|
|
|
|
print "\nAssigned Initiators:\n\n";
|
|
|
|
if ($#{$initiators} > -1) {
|
|
print "\tInitiator\n";
|
|
print "\t";
|
|
for (my $x = 0; $x < $l_initiator; $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $initiator (@{$initiators}) {
|
|
print "\t$initiator\n";
|
|
}
|
|
} else {
|
|
print "\t(none)\n";
|
|
}
|
|
} else {
|
|
print "Group '$group' has no associated LUNs or initiators.\n";
|
|
}
|
|
|
|
}
|
|
|
|
sub listGroups {
|
|
my $group = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
|
|
if ($group && $driver && $target) {
|
|
return listGroup($driver, $target, $group);
|
|
}
|
|
|
|
my $drivers = $SCST->drivers();
|
|
|
|
foreach my $driver (@{$drivers}) {
|
|
my $targets = $SCST->targets($driver);
|
|
foreach my $target (@{$targets}) {
|
|
my $groups = $SCST->groups($driver, $target);
|
|
foreach my $group (@{$groups}) {
|
|
print "Driver: $driver\n";
|
|
print "Target: $target\n";
|
|
print "Group : $group\n\n";
|
|
|
|
listGroup($driver, $target, $group);
|
|
|
|
print "\n\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub listExported {
|
|
my $device = shift;
|
|
my $parameters = shift;
|
|
|
|
$parameters = $SCST->deviceParameters($device) if (!$parameters);
|
|
|
|
if (keys %{$$parameters{'exported'}}) {
|
|
my $exported = $$parameters{'exported'}->{'value'};
|
|
|
|
my $l_driver;
|
|
my $l_target;
|
|
my $l_group;
|
|
|
|
foreach my $driver (keys %{$exported}) {
|
|
$l_driver = length($driver)
|
|
if (length($driver) > $l_driver);
|
|
|
|
foreach my $target (keys %{$$exported{$driver}}) {
|
|
$l_target = length($target)
|
|
if (length($target) > $l_target);
|
|
|
|
foreach my $group (keys %{$$exported{$driver}->{$target}}) {
|
|
$l_group = length($group)
|
|
if (length($group) > $l_group);
|
|
}
|
|
}
|
|
}
|
|
|
|
print "Device '$device' is currently in use by the following:\n\n";
|
|
printf("\t%-*s %-*s %-*s %-4s\n", $l_driver, 'Driver', $l_target, 'Target',
|
|
$l_group, 'Group', 'Lun');
|
|
print "\t";
|
|
for (my $x = 0; $x < ($l_driver + $l_target + $l_group + 5); $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $driver (sort keys %{$exported}) {
|
|
foreach my $target (sort keys %{$$exported{$driver}}) {
|
|
foreach my $group (sort keys %{$$exported{$driver}->{$target}}) {
|
|
my $lun = $$exported{$driver}->{$target}->{$group};
|
|
printf("\t%-*s %-*s %-*s %-4s\n", $l_driver, $driver,
|
|
$l_target, $target, $l_group, $group, $lun);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
print "Device '$device' is not currently in use by any group.\n";
|
|
}
|
|
}
|
|
|
|
sub listScstParameters {
|
|
}
|
|
|
|
sub listHandlerParameters {
|
|
my $handler = shift;
|
|
|
|
}
|
|
|
|
sub listDeviceParameters {
|
|
my $device = shift;
|
|
my $l_parm;
|
|
my $l_val;
|
|
|
|
my $parameters = $SCST->deviceParameters($device);
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
|
|
next if (ref($value));
|
|
|
|
$l_parm = length($parameter) if (length($parameter) > $l_parm);
|
|
$l_val = length($value) if (length($value) > $l_val);
|
|
}
|
|
|
|
print "Parameters for device '$device':\n\n";
|
|
|
|
printf("\t%-*s %-*s %-5s\n", $l_parm, 'Parameter', $l_val, 'Value', 'Static');
|
|
print "\t";
|
|
for (my $x = 0; $x < ($l_parm + $l_val + 8); $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
my $value = $$parameters{$parameter}->{'value'};
|
|
my $static = $$parameters{$parameter}->{'static'};
|
|
|
|
next if (ref($value));
|
|
$value = '-' if (!defined($value));
|
|
$static = ($static ? 'Yes' : 'No');
|
|
|
|
printf("\t%-*s %-*s %-5s\n", $l_parm, $parameter, $l_val, $value, $static);
|
|
}
|
|
}
|
|
|
|
sub listDriverParameters {
|
|
my $driver = shift;
|
|
|
|
}
|
|
|
|
sub listTargetParameters {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
|
|
}
|
|
|
|
sub listLunParameters {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
}
|
|
|
|
sub listInitiatorParameters {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub setScstParameters {
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->scstParameters();
|
|
|
|
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 SCST parameter '$parameter' to '$value': ";
|
|
|
|
my $rc = $SCST->setScstParameter($parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: SCST lacks the settable ".
|
|
"paraneter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setHandlerParameters {
|
|
my $handler = shift;
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->handlerParameters($handler);
|
|
|
|
foreach my $parameter (sort keys %{$parameters}) {
|
|
if (defined($$_parameters{$parameter}) &&
|
|
!$$_parameters{$parameter}->{'static'}) {
|
|
my $value = $$parameters{$parameter};
|
|
|
|
print "-> Setting handler parameter '$parameter' to '$value' for handler '$handler': ";
|
|
|
|
my $rc = $SCST->setHandlerParameter($handler, $parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Handler '$handler' lacks the settable ".
|
|
"parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setDeviceParameters {
|
|
my $device = shift;
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->deviceParameters($device);
|
|
|
|
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 device parameter '$parameter' to value '$value' for device '$device': ";
|
|
|
|
my $rc = $SCST->setDeviceParameter($device, $parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Device '$device' lacks the settable ".
|
|
"parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setDriverParameters {
|
|
my $driver = shift;
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->driverParameters($driver);
|
|
|
|
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 driver parameter '$parameter' to value '$value' for driver '$driver': ";
|
|
|
|
my $rc = $SCST->setDriverParameter($driver, $parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver '$driver' lacks the settable ".
|
|
"parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setTargetParameters {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->targetParameters($driver, $target);
|
|
|
|
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 target parameter '$parameter' to value '$value' for ".
|
|
"driver/target '$driver/$target': ";
|
|
|
|
my $rc = $SCST->setTargetParameter($driver, $target, $parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver/target '$driver/$target' lacks the settable ".
|
|
"parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
my $target = shift;
|
|
my $parameters = shift;
|
|
my $group = shift;
|
|
|
|
my $_parameters = $SCST->lunParameters($driver, $target, $lun, $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 LUN parameter '$parameter' to value '$value' for ".
|
|
"driver/target/group/lun '$driver/$target/$group/$lun': ";
|
|
|
|
my $rc = $SCST->setLunParameter($driver, $target, $lun, $parameter, $value, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver/target/group/lun '$driver/$target/$group/$lun' lacks the settable ".
|
|
"parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setInitiatorParameters {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $parameters = shift;
|
|
|
|
my $_parameters = $SCST->initiatorParameters($driver, $target, $group, $initiator);
|
|
|
|
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 initiator parameter '$parameter' to value '$value' for ".
|
|
"driver/target/group/initiator '$driver/$target/$group/$initiator': ";
|
|
|
|
my $rc = $SCST->setInitiatorParameter($driver, $target, $group, $initiator,
|
|
$parameter, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver/target/group/initiator '$driver/$target/$group/$initiator' ".
|
|
"lacks the settable parameter '$parameter', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub openDevice {
|
|
my $device = shift;
|
|
my $handler = shift;
|
|
my $parameters = shift;
|
|
|
|
print "-> Opening device '$device' using handler '$handler': ";
|
|
|
|
my $rc = $SCST->openDevice($handler, $device, $parameters);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub closeDevice {
|
|
my $device = shift;
|
|
my $handler = shift;
|
|
my $force = shift;
|
|
|
|
my $parameters = $SCST->deviceParameters($device);
|
|
|
|
return if (defined($$parameters{'scsi_device'}));
|
|
|
|
if (!$force) {
|
|
if (keys %{$$parameters{'exported'}}) {
|
|
listExported($device, $parameters);
|
|
immediateExit("Device '$device' still in use, aborting. ".
|
|
"Use -force to override.");
|
|
}
|
|
}
|
|
|
|
print "-> Closing device '$device' using handler '$handler': ";
|
|
|
|
my $rc = $SCST->closeDevice($handler, $device);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub resyncDevice {
|
|
my $device = shift;
|
|
my $rc = FALSE;
|
|
|
|
my %parameters = ('resync_size', 1);
|
|
|
|
setDeviceParameters($device, \%parameters);
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub addGroup {
|
|
my $group = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
|
|
print "-> Adding new group '$group' to driver/target '$driver/$target': ";
|
|
|
|
my $rc = $SCST->addGroup($driver, $target, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub removeGroup {
|
|
my $group = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $force = shift;
|
|
|
|
if (!$force) {
|
|
my $luns = $SCST->luns($driver, $target, $group);
|
|
my $initiators = $SCST->initiators($driver, $target, $group);
|
|
|
|
if ((keys %{$luns}) || ($#{$initiators} > -1)) {
|
|
listGroup($driver, $target, $group, $luns, $initiators);
|
|
immediateExit("Group is still in use, aborting. Use -force to override.");
|
|
}
|
|
}
|
|
|
|
print "-> Removing group '$group' from driver/target '$driver/$target': ";
|
|
|
|
my $rc = $SCST->removeGroup($driver, $target, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub addInitiator {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
print "-> Adding new initiator '$initiator' to driver/target/group ".
|
|
"'$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->addInitiator($driver, $target, $group, $initiator);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub removeInitiator {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
print "-> Removing initiator '$initiator' from driver/target/group ".
|
|
"'$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->removeInitiator($driver, $target, $group, $initiator);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub moveInitiator {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $to = shift;
|
|
|
|
print "-> Moving initiator '$initiator' from group '$group' to group '$to': ";
|
|
|
|
my $rc = $SCST->moveInitiator($driver, $target, $group, $to, $initiator);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub clearInitiators {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
print "-> Removing all initiators driver/target/group '$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->clearInitiators($driver, $target, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub addLun {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $device = shift;
|
|
my $parameters = shift;
|
|
my $group = shift;
|
|
|
|
if ($group) {
|
|
print "-> Adding device '$device' at LUN $lun to driver/target/group ".
|
|
"'$driver/$target/$group': ";
|
|
} else {
|
|
print "-> Adding device '$device' at LUN $lun to driver/target ".
|
|
"'$driver/$target': ";
|
|
}
|
|
|
|
my $rc = $SCST->addLun($driver, $target, $device, $lun, $parameters, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub removeLun {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $device = shift;
|
|
my $group = shift;
|
|
|
|
if ($group) {
|
|
print "-> Removing device '$device' at LUN $lun from driver/target/group ".
|
|
"'$driver/$target/$group': ";
|
|
} else {
|
|
print "-> Removing device '$device' at LUN $lun from driver/target ".
|
|
"'$driver/$target': ";
|
|
}
|
|
|
|
my $rc = $SCST->removeLun($driver, $target, $device, $lun, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub replaceLun {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $device = shift;
|
|
my $parameters = shift;
|
|
|
|
print "-> Replacing device '$device' at LUN $lun with device '$device' ".
|
|
"in driver/target/group '$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->replaceLun($driver, $target, $group, $lun, $device, $parameters);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub clearLuns {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
print "-> Removing all LUNs from driver/target/group '$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->clearLuns($driver, $target, $group);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub enableTarget {
|
|
my $target = shift;
|
|
|
|
}
|
|
|
|
sub disableTarget {
|
|
my $target = shift;
|
|
|
|
}
|
|
|
|
sub issueLip {
|
|
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub readConfig {
|
|
my $file = shift;
|
|
my $buffer;
|
|
my @stanza;
|
|
my $level;
|
|
|
|
my $io = new IO::File $file, O_RDONLY;
|
|
|
|
immediateExit("Unable to open configuration file '$file': $!")
|
|
if (!$io);
|
|
|
|
while (my $line = <$io>) {
|
|
my($test, undef) = split(/\#/, $line, 2);
|
|
if ($test =~ /\[(.*)\s+.*\]/) {
|
|
my $parm = $1;
|
|
|
|
if (($parm eq 'HANDLER') || ($parm eq 'GROUP') ||
|
|
($parm eq 'ASSIGNMENT')) {
|
|
print "\nWARNING: Using a deprecated configuration file. ".
|
|
"I will attempt to convert it for you. ".
|
|
"Please note, groups will ONLY be configured for targets set as 'enable' ".
|
|
"within your old configuration file.\n\n".
|
|
"Please save your new configuration with -write_config and review.\n\n";
|
|
|
|
return readOldConfig($file);
|
|
}
|
|
}
|
|
|
|
$buffer .= $line;
|
|
}
|
|
|
|
my @buff_a;
|
|
@buff_a = split(//, $buffer);
|
|
|
|
return parseStanza(\@buff_a);
|
|
}
|
|
|
|
sub parseStanza {
|
|
my $buffer = shift;
|
|
my $line;
|
|
my %hash;
|
|
my $parameter;
|
|
my $value;
|
|
my $value2;
|
|
my $quoted;
|
|
|
|
while ($#{$buffer} > -1) {
|
|
my $char = shift @{$buffer};
|
|
|
|
if ($char eq '{') {
|
|
my $child = parseStanza($buffer);
|
|
|
|
if ($line) {
|
|
parseLine($line, \%hash, $child);
|
|
$line = undef;
|
|
}
|
|
|
|
next;
|
|
}
|
|
|
|
return \%hash if ($char eq '}');
|
|
|
|
if ($char eq "\n") {
|
|
my %empty;
|
|
parseLine($line, \%hash, \%empty);
|
|
$line = undef;
|
|
} else {
|
|
$line .= $char;
|
|
}
|
|
}
|
|
|
|
return \%hash;
|
|
}
|
|
|
|
sub parseLine {
|
|
my $line = shift;
|
|
my $hash = shift;
|
|
my $child = shift;
|
|
|
|
($line, undef) = split(/\#/, $line, 2);
|
|
return if ($line =~ /^\s*$/);
|
|
|
|
$line =~ s/^\s+//; $line =~ s/\s+$//;
|
|
|
|
my @elements;
|
|
while ($line =~ m/"([^"\\]*(\\.[^"\\]*)*)"|([^\s]+)/g) {
|
|
push @elements, defined($1) ? $1:$3;
|
|
}
|
|
|
|
my $parameter = @elements[0];
|
|
my $value = @elements[1];
|
|
my $value2 = @elements[2];
|
|
|
|
if (defined($parameter) && defined($value) && defined($value2)) {
|
|
$$hash{$parameter}->{$value}->{$value2} = $child;
|
|
} elsif (defined($parameter) && defined($value)) {
|
|
$$hash{$parameter}->{$value} = $child;
|
|
} elsif (defined($parameter)) {
|
|
$$hash{$parameter} = $child;
|
|
}
|
|
}
|
|
|
|
sub readOldConfig {
|
|
my $confile = shift;
|
|
my $ignoreError = shift;
|
|
my %config;
|
|
my $section;
|
|
my $last_section;
|
|
my $arg;
|
|
my $last_arg;
|
|
my %empty;
|
|
|
|
my $io = new IO::File $confile, O_RDONLY;
|
|
|
|
if (!$io) {
|
|
return undef if ($ignoreError);
|
|
|
|
die("FATAL: Unable to open specified configuration file $confile: $!\n");
|
|
}
|
|
|
|
while (my $line = <$io>) {
|
|
($line, undef) = split(/\#/, $line, 2);
|
|
$line =~ s/^\s+//; $line =~ s/\s+$//;
|
|
|
|
if ($line =~ /^\[(.*)\]$/) {
|
|
($section, $arg) = split(/\s+/, $1, 2);
|
|
|
|
$arg = 'default' if ($section eq 'OPTIONS');
|
|
|
|
if ($last_arg && ($last_arg ne $arg) &&
|
|
!defined($config{$last_section}->{$last_arg})) {
|
|
$config{$last_section}->{$last_arg} = \%empty;
|
|
}
|
|
|
|
$last_arg = $arg;
|
|
$last_section = $section;
|
|
} elsif ($section && $arg && $line) {
|
|
my($parameter, $value) = split(/\s+/, $line, 2);
|
|
|
|
if ($section eq 'OPTIONS') {
|
|
$value = TRUE if (($value == 1) ||
|
|
($value =~ /^TRUE$/i) ||
|
|
($value =~ /^YES$/i));
|
|
$value = FALSE if (($value == 0) ||
|
|
($value =~ /^FALSE$/i) ||
|
|
($value =~ /^NO$/i));
|
|
}
|
|
|
|
push @{$config{$section}->{$arg}->{$parameter}}, $value;
|
|
}
|
|
}
|
|
|
|
close $io;
|
|
|
|
# Convert to our new format
|
|
my %new;
|
|
|
|
my %o_converts = ('WRITE_THROUGH' => 'write_through',
|
|
'WT' => 'write_through',
|
|
'READ_ONLY' => 'read_only',
|
|
'RO' => 'read_only',
|
|
'NV_CACHE' => 'nv_cache',
|
|
'NV' => 'nv_cache',
|
|
'REMOVABLE' => 'removable',
|
|
'RM' => 'removable');
|
|
|
|
foreach my $handler (keys %{$config{'HANDLER'}}) {
|
|
foreach my $device (@{$config{'HANDLER'}->{$handler}->{'DEVICE'}}) {
|
|
my($device, $path, $options, $bsize, $t10) = split(/\,/, $device);
|
|
|
|
my $_handler = $handler;
|
|
|
|
foreach my $option (split(/\|/, $options)) {
|
|
if (($option eq 'NULLIO') || ($option eq 'NIO')) {
|
|
$_handler = 'vdisk_nullio' if ($_handler eq 'vdisk');
|
|
} elsif (($option eq 'BLOCKIO') || ($option eq 'BIO')) {
|
|
$_handler = 'vdisk_blockio' if ($_handler eq 'vdisk');
|
|
}
|
|
}
|
|
|
|
if ($_handler eq 'vdisk') {
|
|
$_handler = 'vdisk_fileio';
|
|
}
|
|
|
|
foreach my $option (split(/\|/, $options)) {
|
|
if (defined($o_converts{$option})) {
|
|
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'CREATE_ATTRIBUTES'}->{$o_converts{$option}}->{'1'}} = ();
|
|
}
|
|
}
|
|
|
|
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'t10_dev_id'}->{$t10}} = ()
|
|
if ($t10);
|
|
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'CREATE_ATTRIBUTES'}->{'filename'}->{$path}} = ()
|
|
if ($path);
|
|
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'CREATE_ATTRIBUTES'}->{'blocksize'}->{$bsize}} = ()
|
|
if ($bsize);
|
|
}
|
|
}
|
|
|
|
foreach my $wwn (@{$config{'TARGETS'}->{'enable'}->{'HOST'}}) {
|
|
my $target = formatTarget($wwn);
|
|
|
|
my $driver = findTargetDriver($target);
|
|
|
|
if ($driver) {
|
|
%{$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'enabled'}->{'1'}} = ();
|
|
|
|
foreach my $group (keys %{$config{'GROUP'}}) {
|
|
%{$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}} = ();
|
|
if (defined($config{'GROUP'}->{$group}->{'USER'})) {
|
|
foreach my $user (@{$config{'GROUP'}->{$group}->{'USER'}}) {
|
|
%{$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'INITIATOR'}->{$user}} = ();
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach my $group (keys %{$config{'ASSIGNMENT'}}) {
|
|
foreach my $device (@{$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) {
|
|
my($device, $lun) = split(/\,/, $device);
|
|
%{$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'LUN'}->{$lun}->{$device}} = ();
|
|
}
|
|
}
|
|
} else {
|
|
immediateExit("Unable to determine target driver information for target '$wwn'. ".
|
|
"Please ensure this target driver is loaded.");
|
|
}
|
|
}
|
|
|
|
return \%new;
|
|
}
|
|
|
|
sub findTargetDriver {
|
|
my $target = shift;
|
|
|
|
foreach my $driver (keys %{$CURRENT{'assign'}}) {
|
|
foreach my $_target (keys %{$CURRENT{'assign'}->{$driver}}) {
|
|
$_target =~ tr/A-Z/a-z/;
|
|
|
|
return $driver if ($_target eq $target);
|
|
}
|
|
}
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub formatTarget {
|
|
my $target = shift;
|
|
|
|
if ($target =~ /^0x/) {
|
|
$target =~ s/^0x//;
|
|
my($o1, $o2, $o3, $o4, $o5, $o6, $o7, $o8) = unpack("A2A2A2A2A2A2A2A2", $target);
|
|
$target = "$o1:$o2:$o3:$o4:$o5:$o6:$o7:$o8";
|
|
}
|
|
|
|
$target =~ tr/A-Z/a-z/;
|
|
|
|
return $target;
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub handlerHasDevice {
|
|
my $handler = shift;
|
|
my $device = shift;
|
|
|
|
return FALSE if (!defined($CURRENT{'handler'}->{$handler}));
|
|
|
|
foreach my $_device (@{$CURRENT{'handler'}->{$handler}}) {
|
|
return TRUE if ($_device eq $device);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
sub groupHasInitiator {
|
|
my $initiators = shift;
|
|
my $initiator = shift;
|
|
|
|
foreach my $_initiator (@{$initiators}) {
|
|
return TRUE if ($_initiator eq $initiator);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
sub configToParm {
|
|
my $config = shift;
|
|
my %parameters;
|
|
|
|
foreach my $parm (keys %{$config}) {
|
|
if ((keys %{$$config{$parm}}) > 1) {
|
|
immediateExit("Invalid configuration encountered. ".
|
|
"Parameter '$parm' has multiple values!");
|
|
}
|
|
|
|
foreach my $value (keys %{$$config{$parm}}) {
|
|
if (keys %{$$config{$parm}->{$value}}) {
|
|
immediateExit("Invalid configuration encountered. ".
|
|
"Parameter '$parm' has an invalid value.");
|
|
}
|
|
|
|
$parameters{$parm} = $value;
|
|
}
|
|
}
|
|
|
|
return \%parameters;
|
|
}
|
|
|
|
sub numerically {
|
|
$a <=> $b;
|
|
}
|
|
|
|
####################################################################
|
|
|
|
# If we have an unread error from SCST, exit immediately
|
|
sub immediateExit {
|
|
my $error = shift;
|
|
|
|
return if (!$error);
|
|
|
|
print "\n\nFATAL: Received the following error:\n\n\t";
|
|
print "$error\n\n";
|
|
|
|
exit 1;
|
|
}
|
|
|
|
# Hey! Stop that!
|
|
sub commitSuicide {
|
|
print "\n\nAborting immediately.\n";
|
|
exit 1;
|
|
}
|