mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-20 14:16:31 +00:00
- Error out if a target doesn't exist to prevent removing potentially good running config. - Be sure to remove luns and initiators before the group they're in. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1820 d57e44dd-8a1f-0410-8b47-8ef2f437770f
3080 lines
82 KiB
Perl
Executable File
3080 lines
82 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_attr : List add attributes for SCST.
|
|
-list_hnd_attr <hndlr> : List all attributes for a given handler.
|
|
-list_dev_attr <device> : List all attributes for a given device.
|
|
-list_drv_attr <driver> : List all attributes for a given driver.
|
|
-list_tgt_attr <target> : List all attributes for a given driver/target.
|
|
-driver <driver>
|
|
-list_lun_attr <lun> : List all attributes for a driver/target/lun.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-list_ini_attr <ini> : List all attributes for a driver/target/initiator
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
|
|
-list_sessions : List all current initiator sessions.
|
|
|
|
Set Operations
|
|
-set_scst_attr : Sets SCST attribute(s) <p> to value <v>.
|
|
-attributes <p=v,...>
|
|
-set_hnd_attr <hndlr> : Sets handler attribute(s) <p> to value <v>.
|
|
-attributes <p=v,...>
|
|
-set_dev_attr <device> : Sets device attributes(s) <p> to value <v>.
|
|
-attributes <p=v,...>
|
|
-set_drv_attr <driver> : Sets driver attribute(s) <p> to value <v>.
|
|
-attributes <p=v,...>
|
|
-set_tgt_attr <target> : Sets target attribute(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-attributes <p=v,...>
|
|
-set_lun_attr <lun> : Sets LUN attribute(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-attributes <p=v,...>
|
|
-set_ini_attr <ini> : Sets initiator attribute(s) <p> to value <v>.
|
|
-driver <driver>
|
|
-target <target>
|
|
-group <group>
|
|
-attributes <p=v,...>
|
|
|
|
Device Operations
|
|
-open_dev <device> : Adds a new device using handler <handler>.
|
|
-handler <handler>
|
|
-attributes <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>
|
|
-attributes <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>
|
|
-attributes <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
|
|
-nonkey : When writing a configuration file, store non-key
|
|
attributes as well.
|
|
-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 \
|
|
-attributes filename=/vdisks/disk01.dsk,read_only
|
|
|
|
Setting the T10 Device ID of a device
|
|
scstadmin -set_dev_attr 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 -attributes 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 $listScstAttr;
|
|
my $listHandlerAttr;
|
|
my $listDeviceAttr;
|
|
my $listDriverAttr;
|
|
my $listTargetAttr;
|
|
my $listLunAttr;
|
|
my $listInitiatorAttr;
|
|
|
|
my $setScstAttr;
|
|
my $setHandlerAttr;
|
|
my $setDeviceAttr;
|
|
my $setDriverAttr;
|
|
my $setTargetAttr;
|
|
my $setLunAttr;
|
|
my $setInitiatorAttr;
|
|
|
|
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 $attributes;
|
|
|
|
my $driver;
|
|
my $target;
|
|
my $group;
|
|
my $to;
|
|
my $device;
|
|
|
|
my $nonkey;
|
|
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_attr' => \$listScstAttr,
|
|
'list_hnd_attr=s' => \$listHandlerAttr,
|
|
'list_dev_attr=s' => \$listDeviceAttr,
|
|
'list_drv_attr=s' => \$listDriverAttr,
|
|
'list_tgt_attr=s' => \$listTargetAttr,
|
|
'list_lun_attr=s' => \$listLunAttr,
|
|
'list_ini_attr=s' => \$listInitiatorAttr,
|
|
|
|
'set_scst_attr' => \$setScstAttr,
|
|
'set_hnd_attr=s' => \$setHandlerAttr,
|
|
'set_dev_attr=s' => \$setDeviceAttr,
|
|
'set_drv_attr=s' => \$setDriverAttr,
|
|
'set_tgt_attr=s' => \$setTargetAttr,
|
|
'set_lun_attr=s' => \$setLunAttr,
|
|
'set_ini_attr=s' => \$setInitiatorAttr,
|
|
|
|
'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,
|
|
'attributes=s' => \$attributes,
|
|
|
|
'driver=s' => \$driver,
|
|
'target=s' => \$target,
|
|
'group=s' => \$group,
|
|
'to=s' => \$to,
|
|
'device=s' => \$device,
|
|
|
|
'nonkey' => \$nonkey,
|
|
'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));
|
|
$listScstAttr = TRUE if (defined($listScstAttr));
|
|
$setScstAttr = TRUE if (defined($setScstAttr));
|
|
$nonkey = TRUE if (defined($nonkey));
|
|
|
|
my $query_mode = defined($listHandler) || defined($listDevice) || defined($listDriver) ||
|
|
defined($listTarget) || defined($listGroup) || defined($listSessions) || defined($listScstAttr) ||
|
|
defined($listHandlerAttr) || defined($listDeviceAttr) || defined($listDriverAttr) ||
|
|
defined($listTargetAttr) || defined($listLunAttr) || defined($listInitiatorAttr);
|
|
|
|
my $set_mode = defined($setScstAttr) + defined($setHandlerAttr) + defined($setDeviceAttr) +
|
|
defined($setDriverAttr) + defined($setTargetAttr) + defined($setLunAttr) + defined($setInitiatorAttr);
|
|
|
|
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 ($listTargetAttr && !$driver) {
|
|
print "Please specify -driver with -list_tgt_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($listLunAttr && (!$driver || !$target || !$group)) {
|
|
print "Please specify -driver -target and -group with -list_lun_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($listInitiatorAttr && (!$driver || !$target || !$group)) {
|
|
print "Please specify -driver -target and -group with -list_ini_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setScstAttr && !$attributes) {
|
|
print "Please specify -attributes with -set_scst_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setHandlerAttr && !$attributes) {
|
|
print "Please specify -attributes with -set_hnd_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDeviceAttr && !$attributes) {
|
|
print "Please specify -attributes with -set_dev_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDriverAttr && !$attributes) {
|
|
print "Please specify -attributes with -set_drv_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setTargetAttr && (!$driver || !$attributes)) {
|
|
print "Please specify -driver and -attributes with -set_tgt_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setLunAttr && (!$driver || !$target || !$group || !$attributes)) {
|
|
print "Please specify -driver -target -group and -attributes with -set_lun_attr.\n";
|
|
usage();
|
|
}
|
|
|
|
if ($setDeviceAttr && (!$driver || !$target || !$group || !$attributes)) {
|
|
print "Please specify -driver -target -group and -attributes with -set_ini_attr.\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();
|
|
}
|
|
|
|
if ($nonkey && !defined($writeConfig)) {
|
|
print "Option -nonkey ignored since -writeConfig was not specified.\n";
|
|
}
|
|
|
|
$applyConfig = $_DEF_CONFIG_ if (defined($applyConfig) && !$applyConfig);
|
|
$checkConfig = $_DEF_CONFIG_ if (defined($checkConfig) && !$checkConfig);
|
|
|
|
my %_attributes;
|
|
if ($attributes) {
|
|
foreach my $attribute (split(/\,/, $attributes)) {
|
|
my $value;
|
|
|
|
if ($attribute =~ /\=/) {
|
|
$value = TRUE;
|
|
} else {
|
|
($attribute, $value) = split(/\=/, $attribute, 2);
|
|
}
|
|
|
|
$_attributes{$attribute} = $value;
|
|
}
|
|
}
|
|
|
|
return ($applyConfig, $clearConfig, $writeConfig, $checkConfig,
|
|
$listScstAttr, $listHandler, $listDevice, $listDriver, $listTarget, $listGroup,
|
|
$listSessions, $listHandlerAttr, $listDeviceAttr, $listDriverAttr, $listTargetAttr,
|
|
$listLunAttr, $listInitiatorAttr, $setScstAttr, $setHandlerAttr, $setDeviceAttr,
|
|
$setDriverAttr, $setTargetAttr, $setLunAttr, $setInitiatorAttr,
|
|
$openDev, $closeDev, $resyncDev,
|
|
$addGroup, $removeGroup,
|
|
$addInitiator, $removeInitiator, $moveInitiator, $clearInitiators,
|
|
$addLun, $removeLun, $replaceLun, $clearLuns,
|
|
$enableTarget, $disableTarget, $issueLip,
|
|
$handler, \%_attributes,
|
|
$driver, $target, $group, $to, $device,
|
|
$nonkey, $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,
|
|
$listScstAttr, $listHandler, $listDevice, $listDriver, $listTarget, $listGroup,
|
|
$listSessions, $listHandlerAttr, $listDeviceAttr, $listDriverAttr, $listTargetAttr,
|
|
$listLunAttr, $listInitiatorAttr, $setScstAttr, $setHandlerAttr, $setDeviceAttr,
|
|
$setDriverAttr, $setTargetAttr, $setLunAttr, $setInitiatorAttr,
|
|
$openDev, $closeDev, $resyncDev,
|
|
$addGroup, $removeGroup,
|
|
$addInitiator, $removeInitiator, $moveInitiator, $clearInitiators,
|
|
$addLun, $removeLun, $replaceLun, $clearLuns,
|
|
$enableTarget, $disableTarget, $issueLip,
|
|
$handler, $attributes,
|
|
$driver, $target, $group, $to, $device,
|
|
$nonkey, $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, $nonkey);
|
|
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;
|
|
};
|
|
$listScstAttr && do {
|
|
$rc = listScstAttr();
|
|
$all_good = TRUE;
|
|
};
|
|
$listHandlerAttr && do {
|
|
$rc = listHandlerAttributes($listHandlerAttr);
|
|
$all_good = TRUE;
|
|
};
|
|
$listDeviceAttr && do {
|
|
$rc = listDeviceAttributes($listDeviceAttr);
|
|
$all_good = TRUE;
|
|
};
|
|
$listDriverAttr && do {
|
|
$rc = listDriverAttributes($listHandlerAttr);
|
|
$all_good = TRUE;
|
|
};
|
|
$listTargetAttr && do {
|
|
$rc = listTargetAttributes($listTargetAttr, $driver);
|
|
$all_good = TRUE;
|
|
};
|
|
$listLunAttr && do {
|
|
$rc = listLunAttributes($listLunAttr, $driver, $target, $group);
|
|
$all_good = TRUE;
|
|
};
|
|
$listInitiatorAttr && do {
|
|
$rc = listInitiatorAttributes($listInitiatorAttr, $driver, $target, $group);
|
|
$all_good = TRUE;
|
|
};
|
|
$setScstAttr && do {
|
|
$rc = setScstAttributes($attributes);
|
|
last SWITCH;
|
|
};
|
|
$setHandlerAttr && do {
|
|
$rc = setHandlerAttributes($setHandlerAttr, $attributes);
|
|
last SWITCH;
|
|
};
|
|
$setDeviceAttr && do {
|
|
$rc = setDeviceAttributes($setDeviceAttr, $attributes);
|
|
last SWITCH;
|
|
};
|
|
$setDriverAttr && do {
|
|
$rc = setDriverAttributes($setDriverAttr, $attributes, FALSE);
|
|
last SWITCH;
|
|
};
|
|
$setTargetAttr && do {
|
|
$rc = setTargetAttributes($setTargetAttr, $driver, $attributes, FALSE);
|
|
last SWITCH;
|
|
};
|
|
$setLunAttr && do {
|
|
$rc = setLunAttributes($setLunAttr, $driver, $target, $attributes, $group);
|
|
last SWITCH;
|
|
};
|
|
$setInitiatorAttr && do {
|
|
$rc = setInitiatorAttributes($setInitiatorAttr, $driver, $target, $group, $attributes);
|
|
last SWITCH;
|
|
};
|
|
$openDev && do {
|
|
$rc = openDevice($openDev, $handler, $attributes);
|
|
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, $attributes, $group);
|
|
last SWITCH;
|
|
};
|
|
$removeLun && do {
|
|
$rc = removeLun($removeLun, $driver, $target, $device, $group);
|
|
last SWITCH;
|
|
};
|
|
$replaceLun && do {
|
|
$rc = replaceLun($replaceLun, $driver, $target, $group, $device, $attributes);
|
|
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 "\nCollecting 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}->{'GROUPS'}->{$group}->{'INITIATORS'} =
|
|
$SCST->initiators($driver, $target, $group);
|
|
immediateExit($SCST->errorString());
|
|
$CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'}->{$group}->{'LUNS'} =
|
|
$SCST->luns($driver, $target, $group);
|
|
immediateExit($SCST->errorString());
|
|
}
|
|
}
|
|
}
|
|
|
|
print "done.\n\n";
|
|
}
|
|
|
|
sub writeConfiguration {
|
|
my $file = shift;
|
|
my $nonkey = 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 $attributes = $SCST->scstAttributes();
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!$$attributes{$attribute}->{'static'}) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (@{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
print $io "\t$attribute $value\n"
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
} else {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
print $io "$attribute $value\n"
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
}
|
|
}
|
|
|
|
print $io "\n";
|
|
|
|
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
|
|
my $handler_buff;
|
|
my $handler_buff_nk;
|
|
|
|
my $handler_attrs = $SCST->deviceCreateAttributes($handler);
|
|
$attributes = $SCST->handlerAttributes($handler);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!$$attributes{$attribute}->{'static'}) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (@{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$handler_buff .= "\t$attribute $value\n" if (defined($value));
|
|
}
|
|
} elsif (($attribute eq 'enabled') || $nonkey) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if ($attribute eq 'enabled') {
|
|
$handler_buff .= "\t$attribute $value\n" if (defined($value));
|
|
} else {
|
|
$handler_buff_nk .= "\t$attribute $value\n" if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
my $devices = $CURRENT{'handler'}->{$handler};
|
|
|
|
my $device_buff;
|
|
foreach my $device (@{$devices}) {
|
|
$device_buff .= "\tDEVICE $device";
|
|
|
|
$attributes = $SCST->deviceAttributes($device);
|
|
|
|
my $attribute_buff;
|
|
my $attribute_buff_nk;
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!defined($$handler_attrs{$attribute})) {
|
|
if (!$$attributes{$attribute}->{'static'}) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (@{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$attribute_buff .= "\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attribute eq 'enabled') || $nonkey) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if ($attribute eq 'enabled') {
|
|
$attribute_buff .= "\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$attribute_buff_nk .= "\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$attribute_buff .= "\n" if ($attribute_buff);
|
|
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
|
|
|
|
if (!defined($$attributes{'scsi_device'})) {
|
|
my $create_buff;
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (defined($$handler_attrs{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$create_buff .= "\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
# Shouldn't be any non-key create attributes
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($create_buff) {
|
|
$attribute_buff .= "\t\tCREATE_ATTRIBUTES {\n";
|
|
$attribute_buff .= $create_buff;
|
|
$attribute_buff .= "\t\t}\n";
|
|
}
|
|
}
|
|
|
|
if ($attribute_buff_nk) {
|
|
$attribute_buff .= "\t\t# Non-key attributes\n";
|
|
$attribute_buff .= $attribute_buff_nk;
|
|
}
|
|
|
|
$attribute_buff =~ s/\n+$/\n/;
|
|
|
|
if ($attribute_buff) {
|
|
$device_buff .= " {\n";
|
|
$device_buff .= $attribute_buff;
|
|
$device_buff .= "\t}\n\n";
|
|
} else {
|
|
$device_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
$device_buff =~ s/\n+$/\n/;
|
|
|
|
$handler_buff .= $device_buff;
|
|
|
|
if ($handler_buff_nk) {
|
|
$handler_buff .= "\t# Non-key attributes\n";
|
|
$handler_buff .= $handler_buff_nk;
|
|
}
|
|
|
|
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 $drv_attrs = $SCST->driverAttributes($driver);
|
|
|
|
my $drv_attr_buff;
|
|
my $drv_attr_buff_nk;
|
|
foreach my $attr (keys %{$drv_attrs}) {
|
|
next if ($$drv_attrs{$attr}->{'static'});
|
|
next if ($$drv_attrs{$attr}->{'set'});
|
|
|
|
if (defined($$drv_attrs{$attr}->{'keys'})) {
|
|
foreach my $key (keys %{$$drv_attrs{$attr}->{'keys'}}) {
|
|
my $value = $$drv_attrs{$attr}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$drv_attr_buff .= "\t$attr $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attr eq 'enabled') || $nonkey) {
|
|
my $value = $$drv_attrs{$attr}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ /\s/);
|
|
if ($attr eq 'enabled') {
|
|
$drv_attr_buff .= "\t$attr $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$drv_attr_buff_nk .= "\t$attr $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
|
|
$drv_attr_buff .= "\n" if ($drv_attr_buff);
|
|
$drv_attr_buff_nk .= "\n" if ($drv_attr_buff_nk);
|
|
|
|
my $targets = $CURRENT{'assign'}->{$driver};
|
|
|
|
my $target_buff;
|
|
foreach my $target (sort keys %{$targets}) {
|
|
$target_buff .= "\tTARGET $target";
|
|
|
|
my $tgt_attrs = $SCST->targetAttributes($driver, $target);
|
|
|
|
my $attribute_buff;
|
|
my $attribute_buff_nk;
|
|
foreach my $attr (keys %{$tgt_attrs}) {
|
|
next if ($$tgt_attrs{$attr}->{'static'});
|
|
next if ($$tgt_attrs{$attr}->{'set'});
|
|
|
|
if (defined($$tgt_attrs{$attr}->{'keys'})) {
|
|
foreach my $key (keys %{$$tgt_attrs{$attr}->{'keys'}}) {
|
|
my $value = $$tgt_attrs{$attr}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$attribute_buff .= "\t\t$attr $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attr eq 'enabled') || $nonkey) {
|
|
my $value = $$tgt_attrs{$attr}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ /\s/);
|
|
if ($attr eq 'enabled') {
|
|
$attribute_buff .= "\t\t$attr $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$attribute_buff_nk .= "\t\t$attr $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
|
|
$attribute_buff .= "\n" if ($attribute_buff);
|
|
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
|
|
|
|
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUNS'};
|
|
my $lun_attrs = $SCST->lunCreateAttributes($driver, $target);
|
|
|
|
my $t_lun_buff;
|
|
foreach my $lun (sort numerically keys %{$luns}) {
|
|
my $lun_dev = $$luns{$lun};
|
|
|
|
$t_lun_buff .= "\t\tLUN $lun $lun_dev";
|
|
|
|
$attributes = $SCST->lunAttributes($driver, $target, $lun);
|
|
|
|
my $l_attribute_buff;
|
|
my $l_attribute_buff_nk;
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!$$attributes{$attribute}->{'static'} ||
|
|
defined($$lun_attrs{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$l_attribute_buff .= "\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attribute eq 'enabled') || $nonkey) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if (defined($$lun_attrs{$attribute})) {
|
|
$l_attribute_buff .= "\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} elsif ($attribute eq 'enabled') {
|
|
$l_attribute_buff .= "\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$l_attribute_buff_nk .= "\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($l_attribute_buff_nk) {
|
|
$l_attribute_buff .= "\t\t\t\t# Non-key attributes\n";
|
|
$l_attribute_buff .= $l_attribute_buff_nk;
|
|
}
|
|
|
|
if ($l_attribute_buff) {
|
|
$t_lun_buff .= " {\n";
|
|
$t_lun_buff .= $l_attribute_buff;
|
|
$t_lun_buff .= "\t\t}\n\n";
|
|
} else {
|
|
$t_lun_buff .= "\n";
|
|
}
|
|
}
|
|
my $groups = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'};
|
|
|
|
my $group_buff;
|
|
foreach my $group (sort keys %{$groups}) {
|
|
my $lun_attrs = $SCST->lunCreateAttributes($driver, $target, $group);
|
|
my $ini_attrs = $SCST->initiatorCreateAttributes($driver, $target, $group);
|
|
|
|
$group_buff .= "\t\tGROUP $group";
|
|
|
|
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'}->{$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";
|
|
|
|
$attributes = $SCST->lunAttributes($driver, $target, $lun, $group);
|
|
|
|
my $l_attribute_buff;
|
|
my $l_attribute_buff_nk;
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!$$attributes{$attribute}->{'static'} ||
|
|
defined($$lun_attrs{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$l_attribute_buff .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attribute eq 'enabled') || $nonkey) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if (defined($$lun_attrs{$attribute})) {
|
|
$l_attribute_buff .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} elsif ($attribute eq 'enabled') {
|
|
$l_attribute_buff .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$l_attribute_buff_nk .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($l_attribute_buff_nk) {
|
|
$l_attribute_buff .= "\t\t\t\t# Non-key attributes\n";
|
|
$l_attribute_buff .= $l_attribute_buff_nk;
|
|
}
|
|
|
|
if ($l_attribute_buff) {
|
|
$lun_buff .= " {\n";
|
|
$lun_buff .= $l_attribute_buff;
|
|
$lun_buff .= "\t\t\t}\n\n";
|
|
} else {
|
|
$lun_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'}->{$group}->{'INITIATORS'};
|
|
|
|
my $init_buff;
|
|
foreach my $init (@{$inits}) {
|
|
$init_buff .= "\t\t\tINITIATOR $init";
|
|
|
|
$attributes = $SCST->initiatorAttributes($driver, $target, $group, $init);
|
|
|
|
my $i_attribute_buff;
|
|
my $i_attribute_buff_nk;
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
next if (defined($$attributes{$attribute}->{'set'}));
|
|
|
|
if (!$$attributes{$attribute}->{'static'} ||
|
|
defined($$ini_attrs{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
$i_attribute_buff .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
} elsif (($attribute eq 'enabled') || $nonkey) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
$value = "\"$value\"" if ($value =~ / /);
|
|
if ($attribute eq 'enabled') {
|
|
$i_attribute_buff .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
} else {
|
|
$i_attribute_buff_nk .= "\t\t\t\t$attribute $value\n"
|
|
if (defined($value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($i_attribute_buff_nk) {
|
|
$i_attribute_buff .= "\t\t\t\t# Non-key attributes\n";
|
|
$i_attribute_buff .= $i_attribute_buff_nk;
|
|
}
|
|
|
|
if ($i_attribute_buff) {
|
|
$init_buff .= " {\n";
|
|
$init_buff .= i_$attribute_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);
|
|
$group_buff =~ s/\n+$/\n/;
|
|
|
|
if ($attribute_buff_nk) {
|
|
$attribute_buff .= "\t\t# Non-key attributes\n";
|
|
$attribute_buff .= $attribute_buff_nk;
|
|
}
|
|
|
|
if ($attribute_buff || $t_lun_buff || $group_buff ) {
|
|
$target_buff .= " {\n";
|
|
|
|
$target_buff .= $attribute_buff;
|
|
$target_buff .= $t_lun_buff;
|
|
$target_buff .= $group_buff;
|
|
|
|
$target_buff =~ s/\n\n$/\n/;
|
|
$target_buff .= "\t}\n\n";
|
|
} else {
|
|
$target_buff .= "\n";
|
|
}
|
|
}
|
|
|
|
if ($drv_attr_buff_nk) {
|
|
$drv_attr_buff .= "\t# Non-key attributes\n";
|
|
$drv_attr_buff .= $drv_attr_buff_nk;
|
|
}
|
|
|
|
$driver_buff .= $drv_attr_buff;
|
|
$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-> FATAL: Target '$target' for driver '$driver' ".
|
|
"does not exist.\n" if (!$SCST->driverIsVirtualCapable($driver));
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
my %cdevices;
|
|
|
|
foreach my $handler (sort keys %{$$CONFIG{'HANDLER'}}) {
|
|
foreach my $device (sort keys %{$$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}}) {
|
|
# Since some people may get confused with how to open
|
|
# a vcdrom, we'll support having '/dev/cdrom' instead of just 'cdrom'.
|
|
if ($device =~ /^\/dev\//) {
|
|
my $_device = $device;
|
|
$_device =~ s/^\/dev\///o;
|
|
my $tree = $$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}->{$device};
|
|
print "\t-> WARNING: Device '$device' configured for handler '$handler' may ".
|
|
"not contain the full /dev path, please change to '$_device'.\n";
|
|
delete $$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}->{$device};
|
|
$$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}->{$_device} = $tree;
|
|
} elsif ($device =~ /\//) {
|
|
print "\t-> FATAL: Device '$device' configured for handler '$handler' may not ".
|
|
"contain character '/'.\n";
|
|
return TRUE;
|
|
}
|
|
|
|
$cdevices{$device}++;
|
|
}
|
|
}
|
|
|
|
foreach my $driver (keys %{$$CONFIG{'TARGET_DRIVER'}}) {
|
|
foreach my $target (keys %{$$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}}) {
|
|
my $tgt = $$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target};
|
|
|
|
if (defined($$tgt{'LUN'})) {
|
|
foreach my $lun (keys %{$$tgt{'LUN'}}) {
|
|
foreach my $device (keys %{$$tgt{'LUN'}->{$lun}}) {
|
|
if (!defined($cdevices{$device})) {
|
|
print "\t-> WARNING: Device '$device' associated with driver/target ".
|
|
"'$driver/$target' at LUN $lun is not defined within configuration, ".
|
|
"removing it.\n";
|
|
delete $$tgt{'LUN'}->{$lun};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (defined($$tgt{'GROUP'})) {
|
|
foreach my $group (keys %{$$tgt{'GROUP'}}) {
|
|
if (defined($$tgt{'GROUP'}->{$group}->{'LUN'})) {
|
|
foreach my $lun (keys %{$$tgt{'GROUP'}->{$group}->{'LUN'}}) {
|
|
foreach my $device (keys %{$$tgt{'GROUP'}->{$group}->{'LUN'}->{$lun}}) {
|
|
if (!defined($cdevices{$device})) {
|
|
print "\t-> WARNING: Device '$device' associated with ".
|
|
"driver/target '$driver/$target' at LUN $lun is not ".
|
|
"defined within configuration, removing it.\n";
|
|
delete $$tgt{'GROUP'}->{$group}->{'LUN'}->{$lun};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
sub applyConfiguration {
|
|
my $file = shift;
|
|
my $force = shift;
|
|
|
|
$CONFIG = readConfig($file) if (!$CONFIG);
|
|
|
|
# Apply config deletions
|
|
if ($force) {
|
|
applyConfigAssignments($CONFIG, $force, TRUE);
|
|
readWorkingConfig();
|
|
}
|
|
|
|
# Apply config additions
|
|
applyConfigDevices($CONFIG, $force);
|
|
applyConfigAssignments($CONFIG, $force);
|
|
|
|
# And SCST attributes..
|
|
my %_attributes;
|
|
foreach my $item (keys %{$CONFIG}) {
|
|
next if ($item eq 'HANDLER');
|
|
next if ($item eq 'TARGET_DRIVER');
|
|
$_attributes{$item} = $$CONFIG{$item};
|
|
}
|
|
|
|
my $attributes = configToAttr(\%_attributes);
|
|
|
|
setScstAttributes($attributes);
|
|
}
|
|
|
|
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 $attributes = $SCST->deviceAttributes($device);
|
|
|
|
next if (defined($$attributes{'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 $attributes = configToAttr($$devices{$device}->{'CREATE_ATTRIBUTES'});
|
|
openDevice($device, $handler, $attributes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub applyConfigAssignments {
|
|
my $config = shift;
|
|
my $deletions = shift;
|
|
my $only_del = 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'}->{$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}->{'GROUPS'}}) {
|
|
next if ($group eq 'LUNS');
|
|
|
|
my $luns = $$assignments{$driver}->{$target}->{'GROUPS'}->{$group}->{'LUNS'};
|
|
my $inits = $$assignments{$driver}->{$target}->{'GROUPS'}->{$group}->{'INITIATORS'};
|
|
|
|
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'}->{$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'}->{$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";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return if ($only_del);
|
|
|
|
$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 %_attributes;
|
|
foreach my $item (keys %{$$assignments{$driver}}) {
|
|
if ($item eq 'TARGET') {
|
|
applyTargetAssignments($driver, $$assignments{$driver}->{$item},
|
|
$deletions);
|
|
} else {
|
|
$_attributes{$item} = $$assignments{$driver}->{$item};
|
|
}
|
|
|
|
}
|
|
|
|
my $attributes = configToAttr(\%_attributes);
|
|
|
|
setDriverAttributes($driver, $attributes, $deletions) if (scalar keys %{$attributes});
|
|
}
|
|
}
|
|
|
|
sub applyTargetAssignments {
|
|
my $driver = shift;
|
|
my $targets = shift;
|
|
my $deletions = shift;
|
|
|
|
foreach my $target (sort keys %{$targets}) {
|
|
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
|
|
if (!$SCST->driverIsVirtualCapable($driver)) {
|
|
immediateExit("Target '$target' for driver '$driver' does not exist.");
|
|
} else {
|
|
# TODO: Add $attributes
|
|
print "-> Creating target '$target' for driver '$driver': ";
|
|
my $rc = $SCST->addVirtualTarget($driver, $target);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
}
|
|
|
|
my %_attributes;
|
|
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 {
|
|
$_attributes{$item} = $$targets{$target}->{$item};
|
|
}
|
|
}
|
|
|
|
my $attributes = configToAttr(\%_attributes);
|
|
|
|
setTargetAttributes($target, $driver, $attributes, $deletions);
|
|
}
|
|
}
|
|
|
|
sub applyGroupAssignments {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $groups = shift;
|
|
|
|
foreach my $group (sort keys %{$groups}) {
|
|
if (!defined($CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'}->{$group})) {
|
|
addGroup($group, $driver, $target);
|
|
}
|
|
|
|
|
|
my %_attributes;
|
|
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 {
|
|
$_attributes{$item} = $$groups{$group}->{$item};
|
|
}
|
|
}
|
|
|
|
my $attributes = configToAttr(\%_attributes);
|
|
|
|
setGroupAttributes($target, $driver, $group, $attributes);
|
|
}
|
|
}
|
|
|
|
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}->{'GROUPS'}->{$group}->{'LUNS'};
|
|
} else {
|
|
$c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUNS'};
|
|
}
|
|
|
|
foreach my $lun (sort keys %{$luns}) {
|
|
if (!defined($$c_luns{$lun})) {
|
|
if ((scalar keys %{$$luns{$lun}}) > 1) {
|
|
immediateExit("Invalid configuration encountered. ".
|
|
"Driver/target/group/lun $driver/$target/$group/$lun ".
|
|
"has multiple devices assigned.");
|
|
}
|
|
|
|
foreach my $device (sort keys %{$$luns{$lun}}) {
|
|
my $attributes = configToAttr($$luns{$lun}->{$device});
|
|
addLun($lun, $driver, $target, $device, $attributes, $group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub applyInitiatorAssignments {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $initiators = shift;
|
|
|
|
my $c_inits = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUPS'}->{$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}->{'GROUPS'}}) {
|
|
clearInitiators($driver, $target, $group);
|
|
clearLuns($driver, $target, $group);
|
|
removeGroup($group, $driver, $target, $force);
|
|
}
|
|
|
|
clearLuns($driver, $target);
|
|
removeTargetDynamicAttributes($driver, $target);
|
|
if ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL) {
|
|
removeVirtualTarget($driver, $target);
|
|
}
|
|
}
|
|
|
|
removeDriverDynamicAttributes($driver);
|
|
}
|
|
|
|
my $handlers = $CURRENT{'handler'};
|
|
|
|
foreach my $handler (sort keys %{$handlers}) {
|
|
foreach my $device (@{$$handlers{$handler}}) {
|
|
my $attributes = $SCST->deviceAttributes($device);
|
|
if (!defined($$attributes{'scsi_device'})) {
|
|
closeDevice($device, $handler, $force);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Todo - check return code
|
|
# TODO: should we disable all target drivers as well?
|
|
}
|
|
|
|
sub removeVirtualTarget {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
|
|
print "-> Removing virtual target '$target' from driver '$driver': ";
|
|
my $rc = $SCST->removeVirtualTarget($driver, $target);
|
|
print "done.\n";
|
|
|
|
# Todo - check return code
|
|
}
|
|
|
|
####################################################################
|
|
|
|
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 $attributes = shift;
|
|
|
|
$attributes = $SCST->deviceAttributes($device) if (!$attributes);
|
|
|
|
if (keys %{$$attributes{'exported'}}) {
|
|
my $exported = $$attributes{'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 listScstAttributes {
|
|
}
|
|
|
|
sub listHandlerAttributes {
|
|
my $handler = shift;
|
|
|
|
}
|
|
|
|
sub listDeviceAttributes {
|
|
my $device = shift;
|
|
my $l_attr;
|
|
my $l_val;
|
|
|
|
my $attributes = $SCST->deviceAttributes($device);
|
|
immediateExit($SCST->errorString());
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
|
|
next if (ref($value));
|
|
|
|
$l_attr = length($attribute) if (length($attribute) > $l_attr);
|
|
$l_val = length($value) if (length($value) > $l_val);
|
|
}
|
|
|
|
print "Attributes for device '$device':\n\n";
|
|
|
|
printf("\t%-*s %-*s %-5s\n", $l_attr, 'Attribute', $l_val, 'Value', 'Static');
|
|
print "\t";
|
|
for (my $x = 0; $x < ($l_attr + $l_val + 8); $x++) {
|
|
print "-";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
my $value = $$attributes{$attribute}->{'value'};
|
|
my $static = $$attributes{$attribute}->{'static'};
|
|
|
|
next if (ref($value));
|
|
$value = '-' if (!defined($value));
|
|
$static = ($static ? 'Yes' : 'No');
|
|
|
|
printf("\t%-*s %-*s %-5s\n", $l_attr, $attribute, $l_val, $value, $static);
|
|
}
|
|
}
|
|
|
|
sub listDriverAttributes {
|
|
my $driver = shift;
|
|
|
|
}
|
|
|
|
sub listTargetAttributes {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
|
|
}
|
|
|
|
sub listLunAttributes {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
}
|
|
|
|
sub listInitiatorAttributes {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub setScstAttributes {
|
|
my $attributes = shift;
|
|
|
|
my $_attributes = $SCST->scstAttributes();
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
next if ($$_attributes{$attribute}->{'value'} eq $value);
|
|
|
|
print "-> Setting SCST attribute '$attribute' to '$value': ";
|
|
|
|
my $rc = $SCST->setScstAttribute($attribute, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: SCST lacks the settable ".
|
|
"attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setHandlerAttributes {
|
|
my $handler = shift;
|
|
my $attributes = shift;
|
|
|
|
my $_attributes = $SCST->handlerAttributes($handler);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
print "-> Setting handler attribute '$attribute' to '$value' for handler '$handler': ";
|
|
|
|
my $rc = $SCST->setHandlerAttribute($handler, $attribute, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Handler '$handler' lacks the settable ".
|
|
"attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setDeviceAttributes {
|
|
my $device = shift;
|
|
my $attributes = shift;
|
|
|
|
my $_attributes = $SCST->deviceAttributes($device);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
next if ($$_attributes{$attribute}->{'value'} eq $value);
|
|
|
|
print "-> Setting device attribute '$attribute' to value '$value' for device '$device': ";
|
|
|
|
my $rc = $SCST->setDeviceAttribute($device, $attribute, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Device '$device' lacks the settable ".
|
|
"attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setDriverAttribute {
|
|
my $driver = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
print "-> Setting driver attribute '$attribute' to value '$value' for driver '$driver': ";
|
|
my $rc = $SCST->setDriverAttribute($driver, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
return $rc;
|
|
}
|
|
|
|
sub setDriverAttributes {
|
|
my $driver = shift;
|
|
my $attributes = shift;
|
|
my $deletions = shift;
|
|
my %toset;
|
|
my %existing;
|
|
|
|
my $driverCap = $SCST->driverIsVirtualCapable($driver);
|
|
my $_attributes = $SCST->driverAttributes($driver);
|
|
|
|
# build caches for easier matching
|
|
foreach my $attribute (keys %{$attributes}) {
|
|
if (ref($$attributes{$attribute}) eq 'ARRAY') {
|
|
foreach my $value (@{$$attributes{$attribute}}) {
|
|
$toset{$attribute}->{$value} = FALSE;
|
|
}
|
|
} else {
|
|
$toset{$attribute}->{$$attributes{$attribute}} = FALSE;
|
|
}
|
|
}
|
|
|
|
foreach my $attribute (keys %{$_attributes}) {
|
|
next if ($$_attributes{$attribute}->{'static'});
|
|
|
|
if (defined($$_attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$_attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$_attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$existing{$attribute}->{$value} = FALSE
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
} else {
|
|
my $value = $$_attributes{$attribute}->{'value'};
|
|
$existing{$attribute}->{$value} = FALSE
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
}
|
|
|
|
# add/change
|
|
foreach my $attribute (keys %toset) {
|
|
foreach my $value (keys %{$toset{$attribute}}) {
|
|
if (!defined($existing{$attribute}) &&
|
|
$driverCap && !$SCST->checkDriverDynamicAttributes($driver, $attribute)) {
|
|
addDriverDynamicAttribute($driver, $attribute, $value);
|
|
next;
|
|
}
|
|
|
|
# already set, move on
|
|
if (defined($existing{$attribute}->{$value})) {
|
|
$existing{$attribute}->{$value} = TRUE;
|
|
next;
|
|
}
|
|
|
|
# Set the existing attribute
|
|
if ($driverCap && !$SCST->checkDriverDynamicAttributes($driver, $attribute)) {
|
|
addDriverDynamicAttribute($driver, $attribute, $value);
|
|
} else {
|
|
setDriverAttribute($driver, $attribute, $value);
|
|
}
|
|
|
|
$existing{$attribute}->{$value} = TRUE;
|
|
}
|
|
}
|
|
|
|
foreach my $attribute (keys %existing) {
|
|
next if (!$driverCap || $SCST->checkDriverDynamicAttributes($driver, $attribute));
|
|
|
|
foreach my $value (keys %{$existing{$attribute}}) {
|
|
if (!$existing{$attribute}->{$value}) {
|
|
if ($deletions) {
|
|
removeDriverDynamicAttribute($driver, $attribute, $value);
|
|
} else {
|
|
print "-> Driver dynamic attribute '$attribute' with value '$value' ".
|
|
"is not in configuration. Use -force to remove it.\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub addDriverDynamicAttribute {
|
|
my $driver = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
print "-> Attempting to add driver attribute '$attribute' with value '$value' for driver '$driver': ";
|
|
my $rc = $SCST->addDriverDynamicAttribute($driver, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub removeDriverDynamicAttribute {
|
|
my $driver = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
return if (!$SCST->driverIsVirtualCapable($driver));
|
|
|
|
print "-> Removing dynamic attribute '$attribute' with value '$value' for driver '$driver': ";
|
|
my $rc = $SCST->removeDriverDynamicAttribute($driver, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub setTargetAttribute {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
print "-> Setting target attribute '$attribute' to value '$value' for ".
|
|
"driver/target '$driver/$target': ";
|
|
my $rc = $SCST->setTargetAttribute($driver, $target, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub setTargetAttributes {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
my $attributes = shift;
|
|
my $deletions = shift;
|
|
my %toset;
|
|
my %existing;
|
|
|
|
my $driverCap = $SCST->driverIsVirtualCapable($driver);
|
|
|
|
my $_attributes = $SCST->targetAttributes($driver, $target);
|
|
|
|
# build caches for easier matching
|
|
foreach my $attribute (keys %{$attributes}) {
|
|
if (ref($$attributes{$attribute}) eq 'ARRAY') {
|
|
foreach my $value (@{$$attributes{$attribute}}) {
|
|
$toset{$attribute}->{$value} = FALSE;
|
|
}
|
|
} else {
|
|
$toset{$attribute}->{$$attributes{$attribute}} = FALSE;
|
|
}
|
|
}
|
|
|
|
foreach my $attribute (keys %{$_attributes}) {
|
|
next if ($$_attributes{$attribute}->{'static'});
|
|
|
|
if (defined($$_attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$_attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$_attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
$existing{$attribute}->{$value} = FALSE
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
} else {
|
|
my $value = $$_attributes{$attribute}->{'value'};
|
|
$existing{$attribute}->{$value} = FALSE
|
|
if (defined($value) && ($value ne ''));
|
|
}
|
|
}
|
|
|
|
# add/change
|
|
foreach my $attribute (keys %toset) {
|
|
foreach my $value (keys %{$toset{$attribute}}) {
|
|
if (!defined($existing{$attribute}) &&
|
|
$driverCap && !$SCST->checkTargetDynamicAttributes($driver, $attribute)) {
|
|
addTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
next;
|
|
}
|
|
|
|
# already set, move on
|
|
if (defined($existing{$attribute}->{$value})) {
|
|
$existing{$attribute}->{$value} = TRUE;
|
|
next;
|
|
}
|
|
|
|
# Set the existing attribute
|
|
if ($driverCap && !$SCST->checkTargetDynamicAttributes($driver, $attribute)) {
|
|
addTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
} else {
|
|
setTargetAttribute($target, $driver, $attribute, $value);
|
|
}
|
|
|
|
$existing{$attribute}->{$value} = TRUE;
|
|
}
|
|
}
|
|
|
|
foreach my $attribute (keys %existing) {
|
|
next if (!$driverCap || $SCST->checkTargetDynamicAttributes($driver, $attribute));
|
|
|
|
foreach my $value (keys %{$existing{$attribute}}) {
|
|
if (!$existing{$attribute}->{$value}) {
|
|
if ($deletions) {
|
|
removeTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
} else {
|
|
print "-> Target dynamic attribute '$attribute' with value '$value' ".
|
|
"is not in configuration. Use -force to remove it.\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub addTargetDynamicAttribute {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
print "-> Attempting to add driver attribute '$attribute' with value '$value' ".
|
|
"for driver/target '$driver/$target': ";
|
|
my $rc = $SCST->addTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub removeTargetDynamicAttribute {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $attribute = shift;
|
|
my $value = shift;
|
|
|
|
return if (!$SCST->driverIsVirtualCapable($driver));
|
|
|
|
print "-> Removing dynamic attribute '$attribute' with value '$value' for driver/target '$driver/$target': ";
|
|
my $rc = $SCST->removeTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub setGroupAttributes {
|
|
my $target = shift;
|
|
my $driver = shift;
|
|
my $group = shift;
|
|
my $attributes = shift;
|
|
|
|
my $_attributes = $SCST->groupAttributes($driver, $target, $group);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
next if ($$_attributes{$attribute}->{'value'} eq $value);
|
|
|
|
print "-> Setting group attribute '$attribute' to value '$value' for ".
|
|
"driver/target/group '$driver/$target/$group': ";
|
|
|
|
my $rc = $SCST->setGroupAttribute($driver, $target, $group, $attribute, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver/target/group '$driver/$target/$group' lacks the settable ".
|
|
"attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setLunAttributes {
|
|
my $lun = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $attributes = shift;
|
|
my $group = shift;
|
|
|
|
my $_attributes = $SCST->lunAttributes($driver, $target, $lun, $group);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
next if ($$_attributes{$attribute}->{'value'} eq $value);
|
|
|
|
print "-> Setting LUN attribute '$attribute' to value '$value' for ".
|
|
"driver/target/group/lun '$driver/$target/$group/$lun': ";
|
|
|
|
my $rc = $SCST->setLunAttribute($driver, $target, $lun, $attribute, $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 ".
|
|
"attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
sub setInitiatorAttributes {
|
|
my $initiator = shift;
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
my $group = shift;
|
|
my $attributes = shift;
|
|
|
|
my $_attributes = $SCST->initiatorAttributes($driver, $target, $group, $initiator);
|
|
|
|
foreach my $attribute (sort keys %{$attributes}) {
|
|
if (defined($$_attributes{$attribute}) &&
|
|
!$$_attributes{$attribute}->{'static'}) {
|
|
my $value = $$attributes{$attribute};
|
|
|
|
next if ($$_attributes{$attribute}->{'value'} eq $value);
|
|
|
|
print "-> Setting initiator attribute '$attribute' to value '$value' for ".
|
|
"driver/target/group/initiator '$driver/$target/$group/$initiator': ";
|
|
|
|
my $rc = $SCST->setInitiatorAttribute($driver, $target, $group, $initiator,
|
|
$attribute, $value);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
} else {
|
|
print "-> WARNING: Driver/target/group/initiator '$driver/$target/$group/$initiator' ".
|
|
"lacks the settable attribute '$attribute', ignoring.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
####################################################################
|
|
|
|
sub openDevice {
|
|
my $device = shift;
|
|
my $handler = shift;
|
|
my $attributes = shift;
|
|
|
|
print "-> Opening device '$device' using handler '$handler': ";
|
|
|
|
my $rc = $SCST->openDevice($handler, $device, $attributes);
|
|
|
|
print "done.\n";
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
|
|
sub closeDevice {
|
|
my $device = shift;
|
|
my $handler = shift;
|
|
my $force = shift;
|
|
|
|
my $attributes = $SCST->deviceAttributes($device);
|
|
|
|
return if (defined($$attributes{'scsi_device'}));
|
|
|
|
if (!$force) {
|
|
if (keys %{$$attributes{'exported'}}) {
|
|
listExported($device, $attributes);
|
|
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 %attributes = ('resync_size', 1);
|
|
|
|
setDeviceAttributes($device, \%attributes);
|
|
}
|
|
|
|
####################################################################
|
|
|
|
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 $attributes = 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, $attributes, $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 $attributes = 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, $attributes);
|
|
|
|
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 removeDriverDynamicAttributes {
|
|
my $driver = shift;
|
|
|
|
return if (!$SCST->driverIsVirtualCapable($driver));
|
|
|
|
print "-> Removing all dynamic attributes from driver '$driver': ";
|
|
|
|
my $attributes = $SCST->driverAttributes($driver);
|
|
my $dynamic = $SCST->driverDynamicAttributes($driver);
|
|
|
|
foreach my $attribute (keys %{$attributes}) {
|
|
if (defined($$dynamic{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
my $rc = $SCST->removeDriverDynamicAttribute($driver, $attribute, $value);
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
print "done.\n";
|
|
}
|
|
|
|
sub removeTargetDynamicAttributes {
|
|
my $driver = shift;
|
|
my $target = shift;
|
|
|
|
return if (!$SCST->driverIsVirtualCapable($driver));
|
|
|
|
print "-> Removing all dynamic attributes from driver/target '$driver/$target': ";
|
|
|
|
my $attributes = $SCST->targetAttributes($driver, $target);
|
|
my $dynamic = $SCST->targetDynamicAttributes($driver);
|
|
|
|
foreach my $attribute (keys %{$attributes}) {
|
|
if (defined($$dynamic{$attribute})) {
|
|
if (defined($$attributes{$attribute}->{'keys'})) {
|
|
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
|
|
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
|
|
my $rc = $SCST->removeTargetDynamicAttribute($driver, $target, $attribute, $value);
|
|
|
|
immediateExit($SCST->errorString($rc)) if ($rc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
print "done.\n";
|
|
}
|
|
|
|
####################################################################
|
|
|
|
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 $attribute;
|
|
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 $attribute = @elements[0];
|
|
my $value = @elements[1];
|
|
my $value2 = @elements[2];
|
|
|
|
if (defined($attribute) && defined($value) && defined($value2)) {
|
|
$$hash{$attribute}->{$value}->{$value2} = $child;
|
|
} elsif (defined($attribute) && defined($value)) {
|
|
$$hash{$attribute}->{$value} = $child;
|
|
} elsif (defined($attribute)) {
|
|
$$hash{$attribute} = $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($attribute, $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}->{$attribute}}, $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 configToAttr {
|
|
my $config = shift;
|
|
my %attributes;
|
|
|
|
foreach my $attr (keys %{$config}) {
|
|
if ((keys %{$$config{$attr}}) > 1) {
|
|
foreach my $value (keys %{$$config{$attr}}) {
|
|
push @{$attributes{$attr}}, $value if (defined($value) &&
|
|
($value ne ''));
|
|
}
|
|
} else {
|
|
foreach my $value (keys %{$$config{$attr}}) {
|
|
if (keys %{$$config{$attr}->{$value}}) {
|
|
immediateExit("Invalid configuration encountered. ".
|
|
"Attribute '$attr' has an invalid value.");
|
|
}
|
|
|
|
$attributes{$attr} = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return \%attributes;
|
|
}
|
|
|
|
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;
|
|
}
|