Files
scst/scstadmin/scstadmin.sysfs
Mark Buechler 2fe68c6554 - Finish up handling LUNs outside of groups. This should now
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
2010-06-01 18:25:45 +00:00

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;
}