blob: 83c60893a8ab093656387f9757c9f7863e44642b [file] [log] [blame]
#!/usr/bin/perl
use strict;
use warnings;
my $Version = 'SCST Configurator v3.7.0';
# Configures SCST
#
# Author: Mark R. Buechler
# License: GPLv2
# Copyright (c) 2005-2011 Mark R. Buechler
# Copyright (C) 2011-2019 Bart Van Assche <bvanassche@acm.org>
sub usage
{
print <<"EndUsage";
$Version
Usage:
-h, -help, --help : Show this information.
General Operations
-config <file> : Configure SCST given the specified <file>.
-check_config <file> : Checks the saved configuration <file>.
-write_config <file> : Writes the current configuration to <file>.
-clear_config : Clear all SCST configuration.
-clear_act_config : Clear SCST - but leaves targets enabled.
-act_peer_config <file> : Writes what we think our peers config should be (if it remains passive) to <file>
-peer_quick_config <file> : Writes what we think our peers config should be (if it became active) to <file>
Query Operations
-list_handler [<hndlr>] : List all available handlers or specific <hndlr>.
-list_device [<device>] : List all open devices or specific <device>.
-list_dgrp [<dgrp>] : List all device groups or specific <dgrp>.
-list_tgrp [<tgrp>] : List all target groups within a device group.
[-dev_group <dgrp>]
-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 Attribute Operations
-list_scst_attr : List all 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_dgrp_attr <dgrp> : List all attributes for a given device group.
-list_tgrp_attr <tgrp> : List all attributes for a device group/target.
-dev_group <dgrp>
-list_ttgt_attr <tgt> : List all attributes for a target group target.
-dev_group <dgrp>
-tgt_group <tgrp>
-list_tgt_attr <target> : List all attributes for a given driver/target.
-driver <driver>
-list_grp_attr <group> : List all attributes for a given group.
-driver <driver>
-target <target>
-list_lun_attr <lun> : List all attributes for a driver/target/lun.
-driver <driver>
-target <target>
[-group <group>]
-list_init_attr <init> : List all attributes for a driver/target/initiator
-driver <driver>
-target <target>
-group <group>
-list_sessions : List all current initiator sessions.
Set Attribute 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_dgrp_attr <dgrp> : Sets device group attribute(s) <p> to value <v>.
-attributes <p=v,...>
-set_tgrp_attr <tgrp> : Sets device group/target attribute(s)
<p> to value <v>.
-dev_group <dgrp>
-attributes <p=v,...>
-set_ttgt_attr <tgt> : Set target group target attribute(s)
<p> to value <v>.
-dev_group <dgrp>
-tgt_group <tgrp>
-attributes <p=v,...>
-set_tgt_attr <target> : Sets target attribute(s) <p> to value <v>.
-driver <driver>
-attributes <p=v,...>
-set_grp_attr <group> : Sets group attribute(s) <p> to value <v>.
-driver <driver>
-target <target>
-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_init_attr <init> : Sets initiator attribute(s) <p> to value <v>.
-driver <driver>
-target <target>
-group <group>
-attributes <p=v,...>
Add Dynamic Attribute Operations
-add_drv_attr <driver> : Adds driver attribute(s) <p> with value <v>.
-attributes <p=v,...>
-add_tgt_attr <target> : Adds target attribute(s) <p> with value <v>.
-driver <driver>
-attributes <p=v,...>
Remove Dynamic Attribute Operations
-rem_drv_attr <driver> : Remove driver attribute(s) <p> with value <v>.
-attributes <p=v,...>
-rem_tgt_attr <target> : Remove target attribute(s) <p> with value <v>.
-driver <driver>
-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>
Device Group Operations
-add_dgrp <dgrp> : Add device group <dgrp>.
-rem_dgrp <dgrp> : Remove device group <dgrp>.
-add_dgrp_dev <device>
-dev_group <dgroup> : Add device <device> to device group <dgrp>.
-rem_dgrp_dev <device>
-dev_group <dgroup> : Remove device <device> from device group <dgrp>.
-add_tgrp <tgrp>
-tgt_group <tgrp> : Add target group <tgrp> to device group <dgrp>.
-rem_tgrp <tgrp>
-dev_group <dgrp> : Remove target group <tgrp> from device group.
-add_tgrp_tgt <tgt> : Add target <tgt> to specified target group.
-dev_group <dgrp>
-tgt_group <tgrp>
-rem_tgrp_tgt <tgt> : Remove target <tgt> from specified target group.
-dev_group <dgrp>
-tgt_group <tgrp>
Target Operations
-add_target <target> : Add a dynamic target to a capable driver.
-driver <driver>
-rem_target <target> : Remove a dynamic target from a driver.
-driver <driver>
Group Operations
-add_group <group> : Add a group to a given driver & target.
-driver <driver>
-target <target>
-rem_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>
-rem_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,...>
-rem_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 [<t>]
[-driver <driver>] : Issue a LIP for a specific driver/target or for
all drivers and targets.
-lip : Issue a LIP after having applied FC
configuration changes.
-no_lip : Don\'t automatically issue a LIP after having
applied FC configuration changes.
Options
-nonkey : When writing a config file or listing attributes,
store/print non-key attributes as well.
-force : Force all configuration changes,
even deletions (DANGER!).
-noprompt : Do not prompt or pause. Use with caution!
-cont_on_err : Continue after an error occurred.
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 -attributes t10_dev_id=0x2345
Create a new security group:
scstadmin -add_group HOST01 -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
EndUsage
}
use Cwd qw(abs_path);
use File::Basename;
use File::Spec;
BEGIN {
my $site_lib = '%INSTALLSITELIB%';
if ($site_lib =~ '^%') {
my $scstadmindir = dirname(abs_path($0));
$site_lib = File::Spec->catdir($scstadmindir, "scst-1.0.0",
"blib", "lib");
}
unshift(@INC, $site_lib);
}
use SCST::SCST 1.0.0;
use Data::Dumper;
use Getopt::Long;
use IO::File;
use IO::Dir;
use POSIX;
my $_DEF_CONFIG_ = '/etc/scst.conf';
use constant {
TRUE => 1,
FALSE => 0,
DEF_CONFIG => '/etc/scst.conf',
};
my $SCST;
my $CONFIG;
my $CONFIGFILE;
my $_DEBUG_;
my $_NOPROMPT_;
my $_CONT_ON_ERR_;
my $CLUSTERID;
my $MYNAME;
my $MYWWPN1;
my $MYWWPN2;
my $MYWWPN3;
my $MYWWPN4;
my $PEERNAME;
my $PEERWWPN1;
my $PEERWWPN2;
my $PEERWWPN3;
my $PEERWWPN4;
my $PEERBBSID;
my %CURRENT;
$SIG{INT} = \&commitSuicide;
$SIG{TERM} = \&commitSuicide;
use vars qw($Version);
&main();
sub getArgs {
my $applyConfig;
my $clearConfig;
my $writeConfig;
my $checkConfig;
my $clearActConfig;
my $writePeerConfig;
my $clusterid;
my $myname;
my $mywwpn1;
my $mywwpn2;
my $mywwpn3;
my $mywwpn4;
my $peername;
my $peerwwpn1;
my $peerwwpn2;
my $peerwwpn3;
my $peerwwpn4;
my $peerbbsid;
my $peerQuickConfig;
# my $clusterid;
# my $myname;
# my $mywwpn1;
# my $mywwpn2;
# my $mywwpn3;
# my $mywwpn4;
# my $peername;
# my $peerwwpn1;
# my $peerwwpn2;
# my $peerwwpn3;
# my $peerwwpn4;
# my $peerbbsid;
my $listHandler;
my $listDevice;
my $listDeviceGroup;
my $listTargetGroup;
my $listDriver;
my $listTarget;
my $listGroup;
my $listSessions;
my $listScstAttr;
my $listHandlerAttr;
my $listDeviceAttr;
my $listDeviceGroupAttr;
my $listTargetGroupAttr;
my $listTargetGroupTargetAttr;
my $listGroupAttr;
my $listDriverAttr;
my $listTargetAttr;
my $listLunAttr;
my $listInitiatorAttr;
my $setScstAttr;
my $setHandlerAttr;
my $setDeviceAttr;
my $setDeviceGroupAttr;
my $setTargetGroupAttr;
my $setTargetGroupTargetAttr;
my $setDriverAttr;
my $setTargetAttr;
my $setGroupAttr;
my $setLunAttr;
my $setInitiatorAttr;
my $addDriverAttr;
my $addTargetAttr;
my $remDriverAttr;
my $remTargetAttr;
my $openDev;
my $closeDev;
my $resyncDev;
my $addDevGroup;
my $removeDevGroup;
my $addDevGroupDevice;
my $removeDevGroupDevice;
my $addTargetGroup;
my $removeTargetGroup;
my $addTargetGroupTarget;
my $removeTargetGroupTarget;
my $addTarget;
my $removeTarget;
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 $lip;
my $noLip;
my $handler;
my $attributes;
my $driver;
my $target;
my $group;
my $to;
my $device;
my $deviceGroup;
my $targetGroup;
my $show_usage;
my $nonkey;
my $force;
my $dumpAttrs;
my $p = new Getopt::Long::Parser;
if (!$p->getoptions('config:s' => \$applyConfig,
'clear_config' => \$clearConfig,
'write_config=s' => \$writeConfig,
'check_config:s' => \$checkConfig,
'clear_act_config' => \$clearActConfig,
'act_peer_config:s' => \$writePeerConfig,
'cluster_id:s' => \$clusterid,
'my_name:s' => \$myname,
'my_wwpn1:s' => \$mywwpn1,
'my_wwpn2:s' => \$mywwpn2,
'my_wwpn3:s' => \$mywwpn3,
'my_wwpn4:s' => \$mywwpn4,
'peer_name:s' => \$peername,
'peer_wwpn1:s' => \$peerwwpn1,
'peer_wwpn2:s' => \$peerwwpn2,
'peer_wwpn3:s' => \$peerwwpn3,
'peer_wwpn4:s' => \$peerwwpn4,
'peer_bbsid:s' => \$peerbbsid,
'peer_quick_config:s' => \$peerQuickConfig,
'cluster_id:s' => \$clusterid,
'my_name:s' => \$myname,
'my_wwpn1:s' => \$mywwpn1,
'my_wwpn2:s' => \$mywwpn2,
'my_wwpn3:s' => \$mywwpn3,
'my_wwpn4:s' => \$mywwpn4,
'peer_name:s' => \$peername,
'peer_wwpn1:s' => \$peerwwpn1,
'peer_wwpn2:s' => \$peerwwpn2,
'peer_wwpn3:s' => \$peerwwpn3,
'peer_wwpn4:s' => \$peerwwpn4,
'peer_bbsid:s' => \$peerbbsid,
'list_handler:s' => \$listHandler,
'list_device:s' => \$listDevice,
'list_dgrp:s' => \$listDeviceGroup,
'list_tgrp:s' => \$listTargetGroup,
'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_dgrp_attr=s' => \$listDeviceGroupAttr,
'list_tgrp_attr=s' => \$listTargetGroupAttr,
'list_ttgt_attr=s' => \$listTargetGroupTargetAttr,
'list_drv_attr=s' => \$listDriverAttr,
'list_tgt_attr=s' => \$listTargetAttr,
'list_grp_attr=s' => \$listGroupAttr,
'list_lun_attr=s' => \$listLunAttr,
'list_init_attr=s' => \$listInitiatorAttr,
'set_scst_attr' => \$setScstAttr,
'set_hnd_attr=s' => \$setHandlerAttr,
'set_dev_attr=s' => \$setDeviceAttr,
'set_dgrp_attr=s' => \$setDeviceGroupAttr,
'set_tgrp_attr=s' => \$setTargetGroupAttr,
'set_ttgt_attr=s' => \$setTargetGroupTargetAttr,
'set_drv_attr=s' => \$setDriverAttr,
'set_tgt_attr=s' => \$setTargetAttr,
'set_grp_attr=s' => \$setGroupAttr,
'set_lun_attr=s' => \$setLunAttr,
'set_init_attr=s' => \$setInitiatorAttr,
'add_drv_attr=s' => \$addDriverAttr,
'add_tgt_attr=s' => \$addTargetAttr,
'rem_drv_attr=s' => \$remDriverAttr,
'rem_tgt_attr=s' => \$remTargetAttr,
'open_dev=s' => \$openDev,
'close_dev=s' => \$closeDev,
'resync_dev=s' => \$resyncDev,
'add_dgrp=s' => \$addDevGroup,
'rem_dgrp=s' => \$removeDevGroup,
'add_dgrp_dev=s' => \$addDevGroupDevice,
'rem_dgrp_dev=s' => \$removeDevGroupDevice,
'add_tgrp=s' => \$addTargetGroup,
'rem_tgrp=s' => \$removeTargetGroup,
'add_tgrp_tgt=s' => \$addTargetGroupTarget,
'rem_tgrp_tgt=s' => \$removeTargetGroupTarget,
'add_target=s' => \$addTarget,
'rem_target=s' => \$removeTarget,
'add_group=s' => \$addGroup,
'rem_group=s' => \$removeGroup,
'add_init=s' => \$addInitiator,
'rem_init=s' => \$removeInitiator,
'move_init=s' => \$moveInitiator,
'clear_inits' => \$clearInitiators,
'add_lun=s' => \$addLun,
'rem_lun=s' => \$removeLun,
'replace_lun=s' => \$replaceLun,
'clear_luns' => \$clearLuns,
'enable_target=s' => \$enableTarget,
'disable_target=s' => \$disableTarget,
'issue_lip:s' => \$issueLip,
'lip' => \$lip,
'no_lip' => \$noLip,
'handler=s' => \$handler,
'attributes=s' => \$attributes,
'driver=s' => \$driver,
'target=s' => \$target,
'group=s' => \$group,
'to=s' => \$to,
'device=s' => \$device,
'dev_group=s' => \$deviceGroup,
'tgt_group=s' => \$targetGroup,
'h' => \$show_usage,
'help' => \$show_usage,
'nonkey' => \$nonkey,
'noprompt' => \$_NOPROMPT_,
'cont_on_err' => \$_CONT_ON_ERR_,
'force' => \$force,
'dumpAttrs' => \$dumpAttrs,
'debug' => \$_DEBUG_))
{
exit 1;
}
if (defined($show_usage)) {
usage();
exit 0;
}
$_DEBUG_ = TRUE if (defined($_DEBUG_));
$_NOPROMPT_ = TRUE if (defined($_NOPROMPT_));
$_CONT_ON_ERR_ = TRUE if (defined($_CONT_ON_ERR_));
$force = TRUE if (defined($force));
$nonkey = TRUE if (defined($nonkey));
$lip = TRUE if (defined($lip));
$noLip = TRUE if (defined($noLip));
my $query_mode = defined($listHandler) || defined($listDevice) || defined($listDeviceGroup) || defined($listTargetGroup) ||
defined($listDriver) || defined($listTarget) || defined($listGroup) || defined($listSessions) ||
defined($listScstAttr) || defined($listHandlerAttr) || defined($listDeviceAttr) || defined($listDriverAttr) ||
defined($listTargetAttr) || defined($listGroupAttr) || defined($listLunAttr) || defined($listInitiatorAttr) ||
defined($listDeviceGroupAttr) || defined($listTargetGroupAttr) || defined($listTargetGroupTargetAttr);
my $set_mode = defined($setScstAttr) + defined($setHandlerAttr) + defined($setDeviceAttr) +
defined($setDriverAttr) + defined($setTargetAttr) + defined($setGroupAttr) +
defined($setLunAttr) + defined($setInitiatorAttr) + defined($setDeviceGroupAttr) +
defined($setTargetGroupAttr) + defined($setTargetGroupTargetAttr);
my $op_mode = defined($clearConfig) + defined($writeConfig) + defined($checkConfig) +
defined($clearActConfig) + defined($writePeerConfig) + defined($peerQuickConfig) +
defined($openDev) + defined($closeDev) + defined($addDevGroup) + defined($removeDevGroup) +
defined($addTargetGroup) + defined($removeTargetGroup) +
defined($addTargetGroupTarget) + defined($removeTargetGroupTarget) +
defined($addGroup) + defined($removeGroup) + defined($addDevGroupDevice) + defined($removeDevGroupDevice) +
defined($addInitiator) + defined($removeInitiator) + defined($clearInitiators) +
defined($addDriverAttr) + defined($addTargetAttr) + defined($remDriverAttr) + defined($remTargetAttr) +
defined($addTarget) + defined($removeTarget) +
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";
exit 1;
}
if (defined($clearConfig) && !$force) {
print "Please specify -force with -clear_config.\n";
exit 1;
}
if (defined($clearActConfig) && !$force) {
print "Please specify -force with -clear_act_config.\n";
exit 1;
}
if (defined($listTargetGroup) && !defined($deviceGroup)) {
print "Please specify -dev_group with -list_tgrp.\n";
exit 1;
}
if (defined($listTargetAttr) && !defined($driver)) {
print "Please specify -driver with -list_tgt_attr.\n";
exit 1;
}
if (defined($listGroupAttr) && (!defined($driver) || !defined($target))) {
print "Please specify -driver, -target and group with -list_grp_attr.\n";
exit 1;
}
if (defined($listLunAttr) && (!defined($driver) || !defined($target))) {
print "Please specify -driver and -target with -list_lun_attr.\n";
exit 1;
}
if (defined($listInitiatorAttr) && (!defined($driver) || !defined($target) || !defined($group))) {
print "Please specify -driver, -target and -group with -list_init_attr.\n";
exit 1;
}
if (defined($listTargetGroupAttr) && !defined($deviceGroup)) {
print "Please specify -dev_group with -list_tgrp_attr.\n";
exit 1;
}
if (defined($listTargetGroupTargetAttr) && (!defined($deviceGroup) || !defined($targetGroup))) {
print "Please specify -dev_group and -tgt_group with -list_ttgt_attr.\n";
exit 1;
}
if (defined($setScstAttr) && !defined($attributes)) {
print "Please specify -attributes with -set_scst_attr.\n";
exit 1;
}
if (defined($setHandlerAttr) && !defined($attributes)) {
print "Please specify -attributes with -set_hnd_attr.\n";
exit 1;
}
if (defined($setDeviceAttr) && !defined($attributes)) {
print "Please specify -attributes with -set_dev_attr.\n";
exit 1;
}
if (defined($setDeviceGroupAttr) && !defined($attributes)) {
print "Please specify -attributes with -set_dgrp_attr.\n";
exit 1;
}
if (defined($setTargetGroupAttr) && (!defined($deviceGroup) || !defined($attributes))) {
print "Please specify -dev_group and -attributes with -set_tgrp_attr.\n";
exit 1;
}
if (defined($setTargetGroupTargetAttr) && (!defined($deviceGroup) || !defined($targetGroup) || !defined($attributes))) {
print "Please specify -dev_group -tgt_group and -attributes with -set_ttgt_attr.\n";
exit 1;
}
if (defined($setDriverAttr) && !defined($attributes)) {
print "Please specify -attributes with -set_drv_attr.\n";
exit 1;
}
if (defined($setTargetAttr) && (!defined($driver) || !defined($attributes))) {
print "Please specify -driver and -attributes with -set_tgt_attr.\n";
exit 1;
}
if (defined($setGroupAttr) && (!defined($driver) || !defined($target) || !defined($attributes))) {
print "Please specify -driver -target and -attributes with -set_grp_attr.\n";
exit 1;
}
if (defined($setLunAttr) &&
(!defined($driver) || !defined($target) || !defined($attributes))) {
print "Please specify -driver -target -group and -attributes with -set_lun_attr.\n";
exit 1;
}
if (defined($setInitiatorAttr) &&
(!defined($driver) || !defined($target) || !defined($group) || !defined($attributes))) {
print "Please specify -driver -target -group and -attributes with -set_init_attr.\n";
exit 1;
}
if (defined($addDriverAttr) && !defined($attributes)) {
print "Please specify -attributes with -add_drv_attr.\n";
exit 1;
}
if (defined($addTargetAttr) &&
(!defined($driver) || !defined($attributes))) {
print "Please specify -driver and -attributes with -add_tgt_attr.\n";
exit 1;
}
if (defined($remDriverAttr) && !defined($attributes)) {
print "Please specify -attributes with -rem_drv_attr.\n";
exit 1;
}
if (defined($remTargetAttr) &&
(!defined($driver) || !defined($attributes))) {
print "Please specify -driver and -attributes with -rem_tgt_attr.\n";
exit 1;
}
if ((defined($openDev) || defined($closeDev)) && !defined($handler)) {
print "Please specify -handler with -open_dev/-close_dev.\n";
exit 1;
}
if (defined($addTarget) && !defined($driver)) {
print "Please specify -driver with -add_target.\n";
exit 1;
}
if (defined($removeTarget) && !defined($driver)) {
print "Please specify -driver with -rem_target.\n";
exit 1;
}
if ((defined($addGroup) || defined($removeGroup)) &&
(!defined($driver) || !defined($target))) {
print "Please specify -driver and -target with -add_group/-rem_group.\n";
exit 1;
}
if ((defined($addInitiator) || defined($removeInitiator) || defined($clearInitiators)) &&
(!defined($target) || !defined($driver) || !defined($group))) {
print "Please specify -driver -target and -group with ".
"-add_init/-rem_init/-clear_inits.\n";
exit 1;
}
if (defined($moveInitiator) &&
(!defined($driver) || !defined($target) || !defined($group) || !defined($to))) {
print "Please specify -driver -target -group and -to with -move_init.\n";
exit 1;
}
if ((defined($addLun) || defined($replaceLun)) &&
(!defined($driver) || !defined($target) || !defined($device))) {
print "Please specify -driver -target and -device with -add_lun/-replace_lun.\n";
exit 1;
}
if ((defined($clearLuns) || defined($removeLun)) && (!defined($driver) || !defined($target))) {
print "Please specify -driver and -target with -rem_lun/-clear_luns.\n";
exit 1;
}
if ((defined($addDevGroupDevice) || defined($removeDevGroupDevice)) && !defined($deviceGroup)) {
print "Please specify -dev_group with -add_dgrp_dev/-rem_dgrp_dev.\n";
exit 1;
}
if ((defined($addTargetGroup) || defined($removeTargetGroup)) && !defined($deviceGroup)) {
print "Please specify -dev_group with -add_tgrp/-rem_tgrp.\n";
exit 1;
}
if ((defined($addTargetGroupTarget) || defined($removeTargetGroupTarget)) &&
(!defined($deviceGroup) || !defined($targetGroup))) {
print "Please specify -dev_group and -tgt_group with -add_tgrp_tgt/-rem_tgrp_tgt.\n";
exit 1;
}
$applyConfig = $_DEF_CONFIG_ if (defined($applyConfig) && ($applyConfig eq ''));
$checkConfig = $_DEF_CONFIG_ if (defined($checkConfig) && ($checkConfig eq ''));
my %_attributes;
if ($attributes) {
foreach my $attribute (split(/\,/, $attributes)) {
my $value;
if ($attribute !~ /\=/) {
$value = TRUE;
} else {
($attribute, $value) = split(/\=/, $attribute, 2);
}
$_attributes{$attribute} = $value;
}
}
my %args = (
applyConfig => $applyConfig,
clearConfig => $clearConfig,
writeConfig => $writeConfig,
checkConfig => $checkConfig,
clearActConfig => $clearActConfig,
writePeerConfig => $writePeerConfig,
clusterid => $clusterid,
myname => $myname,
mywwpn1 => $mywwpn1,
mywwpn2 => $mywwpn2,
mywwpn3 => $mywwpn3,
mywwpn4 => $mywwpn4,
peername => $peername,
peerwwpn1 => $peerwwpn1,
peerwwpn2 => $peerwwpn2,
peerwwpn3 => $peerwwpn3,
peerwwpn4 => $peerwwpn4,
peerbbsid => $peerbbsid,
peerQuickConfig => $peerQuickConfig,
clusterid => $clusterid,
myname => $myname,
mywwpn1 => $mywwpn1,
mywwpn2 => $mywwpn2,
mywwpn3 => $mywwpn3,
mywwpn4 => $mywwpn4,
peername => $peername,
peerwwpn1 => $peerwwpn1,
peerwwpn2 => $peerwwpn2,
peerwwpn3 => $peerwwpn3,
peerwwpn4 => $peerwwpn4,
peerbbsid => $peerbbsid,
listScstAttr => $listScstAttr,
listHandler => $listHandler,
listDevice => $listDevice,
listDeviceGroup => $listDeviceGroup,
listTargetGroup => $listTargetGroup,
listDriver => $listDriver,
listTarget => $listTarget,
listGroup => $listGroup,
listSessions => $listSessions,
listHandlerAttr => $listHandlerAttr,
listDeviceAttr => $listDeviceAttr,
listDriverAttr => $listDriverAttr,
listTargetAttr => $listTargetAttr,
listDeviceGroupAttr => $listDeviceGroupAttr,
listTargetGroupAttr => $listTargetGroupAttr,
listTargetGroupTargetAttr => $listTargetGroupTargetAttr,
listGroupAttr => $listGroupAttr,
listLunAttr => $listLunAttr,
listInitiatorAttr => $listInitiatorAttr,
setScstAttr => $setScstAttr,
setHandlerAttr => $setHandlerAttr,
setDeviceAttr => $setDeviceAttr,
setDriverAttr => $setDriverAttr,
setTargetAttr => $setTargetAttr,
setGroupAttr => $setGroupAttr,
setLunAttr => $setLunAttr,
setInitiatorAttr => $setInitiatorAttr,
setDeviceGroupAttr => $setDeviceGroupAttr,
setTargetGroupAttr => $setTargetGroupAttr,
setTargetGroupTargetAttr => $setTargetGroupTargetAttr,
addDriverAttr => $addDriverAttr,
addTargetAttr => $addTargetAttr,
remDriverAttr => $remDriverAttr,
remTargetAttr => $remTargetAttr,
openDev => $openDev,
closeDev => $closeDev,
resyncDev => $resyncDev,
addDevGroup => $addDevGroup,
removeDevGroup => $removeDevGroup,
addDevGroupDevice => $addDevGroupDevice,
removeDevGroupDevice => $removeDevGroupDevice,
addTargetGroup => $addTargetGroup,
removeTargetGroup => $removeTargetGroup,
addTargetGroupTarget => $addTargetGroupTarget,
removeTargetGroupTarget => $removeTargetGroupTarget,
addTarget => $addTarget,
removeTarget => $removeTarget,
addGroup => $addGroup,
removeGroup => $removeGroup,
addInitiator => $addInitiator,
removeInitiator => $removeInitiator,
moveInitiator => $moveInitiator,
clearInitiators => $clearInitiators,
addLun => $addLun,
removeLun => $removeLun,
replaceLun => $replaceLun,
clearLuns => $clearLuns,
enableTarget => $enableTarget,
disableTarget => $disableTarget,
issueLip => $issueLip,
lip => $lip,
noLip => $noLip,
handler => $handler,
attributes => \%_attributes,
driver => $driver,
target => $target,
group => $group,
to => $to,
device => $device,
deviceGroup => $deviceGroup,
targetGroup => $targetGroup,
nonkey => $nonkey,
force => $force,
dumpAttrs => $dumpAttrs,
);
return \%args;
}
sub main {
STDOUT->autoflush(1);
# We need to run as root
if ( $> ) {die("This program must run as root.\n");}
my $args = getArgs();
my $applyConfig = $args->{applyConfig};
my $clearConfig = $args->{clearConfig};
my $writeConfig = $args->{writeConfig};
my $checkConfig = $args->{checkConfig};
my $clearActConfig = $args->{clearActConfig};
my $writePeerConfig = $args->{writePeerConfig};
my $clusterid = $args->{clusterid};
my $myname = $args->{myname};
my $mywwpn1 = $args->{mywwpn1};
my $mywwpn2 = $args->{mywwpn2};
my $mywwpn3 = $args->{mywwpn3};
my $mywwpn4 = $args->{mywwpn4};
my $peername = $args->{peername};
my $peerwwpn1 = $args->{peerwwpn1};
my $peerwwpn2 = $args->{peerwwpn2};
my $peerwwpn3 = $args->{peerwwpn3};
my $peerwwpn4 = $args->{peerwwpn4};
my $peerbbsid = $args->{peerbbsid};
my $peerQuickConfig = $args->{peerQuickConfig};
# my $clusterid = $args->{clusterid};
# my $myname = $args->{myname};
# my $mywwpn1 = $args->{mywwpn1};
# my $mywwpn2 = $args->{mywwpn2};
# my $mywwpn3 = $args->{mywwpn3};
# my $mywwpn4 = $args->{mywwpn4};
# my $peername = $args->{peername};
# my $peerwwpn1 = $args->{peerwwpn1};
# my $peerwwpn2 = $args->{peerwwpn2};
# my $peerwwpn3 = $args->{peerwwpn3};
# my $peerwwpn4 = $args->{peerwwpn4};
# my $peerbbsid = $args->{peerbbsid};
my $listScstAttr = $args->{listScstAttr};
my $listHandler = $args->{listHandler};
my $listDevice = $args->{listDevice};
my $listDeviceGroup = $args->{listDeviceGroup};
my $listTargetGroup = $args->{listTargetGroup};
my $listDriver = $args->{listDriver};
my $listTarget = $args->{listTarget};
my $listGroup = $args->{listGroup};
my $listSessions = $args->{listSessions};
my $listHandlerAttr = $args->{listHandlerAttr};
my $listDeviceAttr = $args->{listDeviceAttr};
my $listDriverAttr = $args->{listDriverAttr};
my $listTargetAttr = $args->{listTargetAttr};
my $listDeviceGroupAttr = $args->{listDeviceGroupAttr};
my $listTargetGroupAttr = $args->{listTargetGroupAttr};
my $listTargetGroupTargetAttr = $args->{listTargetGroupTargetAttr};
my $listGroupAttr = $args->{listGroupAttr};
my $listLunAttr = $args->{listLunAttr};
my $listInitiatorAttr = $args->{listInitiatorAttr};
my $setScstAttr = $args->{setScstAttr};
my $setHandlerAttr = $args->{setHandlerAttr};
my $setDeviceAttr = $args->{setDeviceAttr};
my $setDriverAttr = $args->{setDriverAttr};
my $setTargetAttr = $args->{setTargetAttr};
my $setGroupAttr = $args->{setGroupAttr};
my $setLunAttr = $args->{setLunAttr};
my $setInitiatorAttr = $args->{setInitiatorAttr};
my $setDeviceGroupAttr = $args->{setDeviceGroupAttr};
my $setTargetGroupAttr = $args->{setTargetGroupAttr};
my $setTargetGroupTargetAttr = $args->{setTargetGroupTargetAttr};
my $addDriverAttr = $args->{addDriverAttr};
my $addTargetAttr = $args->{addTargetAttr};
my $remDriverAttr = $args->{remDriverAttr};
my $remTargetAttr = $args->{remTargetAttr};
my $openDev = $args->{openDev};
my $closeDev = $args->{closeDev};
my $resyncDev = $args->{resyncDev};
my $addDevGroup = $args->{addDevGroup};
my $removeDevGroup = $args->{removeDevGroup};
my $addDevGroupDevice = $args->{addDevGroupDevice};
my $removeDevGroupDevice = $args->{removeDevGroupDevice};
my $addTargetGroup = $args->{addTargetGroup};
my $removeTargetGroup = $args->{removeTargetGroup};
my $addTargetGroupTarget = $args->{addTargetGroupTarget};
my $removeTargetGroupTarget = $args->{removeTargetGroupTarget};
my $addTarget = $args->{addTarget};
my $removeTarget = $args->{removeTarget};
my $addGroup = $args->{addGroup};
my $removeGroup = $args->{removeGroup};
my $addInitiator = $args->{addInitiator};
my $removeInitiator = $args->{removeInitiator};
my $moveInitiator = $args->{moveInitiator};
my $clearInitiators = $args->{clearInitiators};
my $addLun = $args->{addLun};
my $removeLun = $args->{removeLun};
my $replaceLun = $args->{replaceLun};
my $clearLuns = $args->{clearLuns};
my $enableTarget = $args->{enableTarget};
my $disableTarget = $args->{disableTarget};
my $issueLip = $args->{issueLip};
my $lip = $args->{lip};
my $noLip = $args->{noLip};
my $handler = $args->{handler};
my $attributes = $args->{attributes};
my $driver = $args->{driver};
my $target = $args->{target};
my $group = $args->{group};
my $to = $args->{to};
my $device = $args->{device};
my $deviceGroup = $args->{deviceGroup};
my $targetGroup = $args->{targetGroup};
my $nonkey = $args->{nonkey};
my $force = $args->{force};
my $dumpAttrs = $args->{dumpAttrs};
$SCST = new SCST::SCST($_DEBUG_);
my $rc = readWorkingConfig($force);
exit $rc if ($rc);
my $all_good;
SWITCH: {
defined($applyConfig) && do {
$CONFIGFILE = $applyConfig;
$rc = checkConfiguration();
condExit("Configuration has errors, aborting.") if ($rc);
last if ($force && prompt());
my $changes = applyConfiguration($force);
$rc = issueLip() if ($changes && $lip);
last SWITCH;
};
defined($checkConfig) && do {
$CONFIGFILE = $checkConfig;
$rc = checkConfiguration();
last SWITCH;
};
defined($writeConfig) && do {
$CONFIGFILE = $writeConfig;
$rc = writeConfiguration($nonkey);
last SWITCH;
};
defined($clearConfig) && do {
last if (prompt());
$rc = clearConfiguration();
$rc = issueLip() if (!$rc && $lip);
last SWITCH;
};
defined($writePeerConfig) && do {
$CONFIGFILE = $writePeerConfig;
$CLUSTERID = $clusterid;
$MYNAME = $myname;
$PEERNAME = $peername;
$PEERWWPN1 = $peerwwpn1;
$PEERWWPN2 = $peerwwpn2;
$PEERWWPN3 = $peerwwpn3;
$PEERWWPN4 = $peerwwpn4;
$PEERBBSID = $peerbbsid;
$MYWWPN1 = $mywwpn1;
$MYWWPN2 = $mywwpn2;
$MYWWPN3 = $mywwpn3;
$MYWWPN4 = $mywwpn4;
$rc = writePeerConfiguration($nonkey);
last SWITCH;
};
defined($peerQuickConfig) && do {
$CONFIGFILE = $peerQuickConfig;
$CLUSTERID = $clusterid;
$MYNAME = $myname;
$PEERNAME = $peername;
$PEERWWPN1 = $peerwwpn1;
$PEERWWPN2 = $peerwwpn2;
$PEERWWPN3 = $peerwwpn3;
$PEERWWPN4 = $peerwwpn4;
$PEERBBSID = $peerbbsid;
$MYWWPN1 = $mywwpn1;
$MYWWPN2 = $mywwpn2;
$MYWWPN3 = $mywwpn3;
$MYWWPN4 = $mywwpn4;
$rc = peerQuickConfiguration($nonkey);
last SWITCH;
};
defined($clearActConfig) && do {
last if (prompt());
$rc = clearActifioConfig();
$rc = issueLip() if (!$rc && $lip);
last SWITCH;
};
defined($listHandler) && do {
$rc = listHandlers($listHandler);
$all_good = TRUE;
};
defined($listDevice) && do {
$rc = listDevices($listDevice, $nonkey);
$all_good = TRUE;
};
defined($listDeviceGroup) && do {
$rc = listDeviceGroups($listDeviceGroup);
$all_good = TRUE;
};
defined($listTargetGroup) && do {
$rc = listTargetGroups($deviceGroup, $listTargetGroup);
$all_good = TRUE;
};
defined($listDriver) && do {
$rc = listDrivers($listDriver);
$all_good = TRUE;
};
defined($listTarget) && do {
$rc = listTargets($driver, $listTarget);
$all_good = TRUE;
};
defined($listGroup) && do {
$rc = listGroups($driver, $target, $listGroup);
$all_good = TRUE;
};
defined($listSessions) && do {
$rc = listSessions();
$all_good = TRUE;
};
defined($listScstAttr) && do {
$rc = listScstAttributes($nonkey);
$all_good = TRUE;
};
defined($listHandlerAttr) && do {
$rc = listHandlerAttributes($listHandlerAttr, $nonkey);
$all_good = TRUE;
};
defined($listDeviceAttr) && do {
$rc = listDevice($listDeviceAttr, $nonkey);
$all_good = TRUE;
};
defined($listDriverAttr) && do {
$rc = listDriverAttributes($listDriverAttr, $nonkey);
$all_good = TRUE;
};
defined($listTargetAttr) && do {
$rc = listTargetAttributes($driver, $listTargetAttr, $nonkey);
$all_good = TRUE;
};
defined($listGroupAttr) && do {
$rc = listGroupAttributes($driver, $target, $listGroupAttr, $nonkey);
$all_good = TRUE;
};
defined($listLunAttr) && do {
$rc = listLunAttributes($driver, $target, $group, $listLunAttr, $nonkey);
$all_good = TRUE;
};
defined($listInitiatorAttr) && do {
$rc = listInitiatorAttributes($driver, $target, $group, $listInitiatorAttr, $nonkey);
$all_good = TRUE;
};
defined($listDeviceGroupAttr) && do {
$rc = listDeviceGroupAttributes($listDeviceGroupAttr, $nonkey);
$all_good = TRUE;
};
defined($listTargetGroupAttr) && do {
$rc = listTargetGroupAttributes($deviceGroup, $listTargetGroupAttr, $nonkey);
$all_good = TRUE;
};
defined($listTargetGroupTargetAttr) && do {
$rc = listTargetGroupTargetAttributes($deviceGroup, $targetGroup, $listTargetGroupTargetAttr, $nonkey);
$all_good = TRUE;
};
defined($setScstAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setScstAttributes($attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setHandlerAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setHandlerAttributes($setHandlerAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setDeviceAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setDeviceAttributes($setDeviceAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setDriverAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setDriverAttributes($setDriverAttr, $attributes, FALSE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setTargetAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setTargetAttributes($driver, $setTargetAttr, $attributes, FALSE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setGroupAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setGroupAttributes(undef, $driver, $target, $setGroupAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setLunAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setLunAttributes($driver, $target, $setLunAttr, $attributes, $group, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setInitiatorAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setInitiatorAttributes($driver, $target, $group, $setInitiatorAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setDeviceGroupAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setDeviceGroupAttributes($setDeviceGroupAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setTargetGroupAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setTargetGroupAttributes($deviceGroup, $setTargetGroupAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($setTargetGroupTargetAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
my $changes = setTargetGroupTargetAttributes($deviceGroup, $targetGroup, $setTargetGroupTargetAttr, $attributes, TRUE);
print "\t-> Done, $changes change(s) made.\n";
last SWITCH;
};
defined($addDriverAttr) && do {
print "\n-> Making requested changes.\n";
$rc = addDriverDynamicAttributes($addDriverAttr, $attributes);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($addTargetAttr) && do {
print "\n-> Making requested changes.\n";
$rc = addTargetDynamicAttributes($driver, $addTargetAttr, $attributes);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($remDriverAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeDriverDynamicAttributes($remDriverAttr, $attributes);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($remTargetAttr) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeTargetDynamicAttributes($driver, $remTargetAttr, $attributes);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($openDev) && do {
print "\n-> Making requested changes.\n";
$rc = openDevice($handler, $openDev, $attributes);
print "\t-> Done.\n";
last SWITCH;
};
defined($closeDev) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = closeDevice($handler, $closeDev, $force);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($resyncDev) && do {
print "\n-> Making requested changes.\n";
$rc = resyncDevice($resyncDev);
$rc = issueLip() if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($addDevGroup) && do {
print "\n-> Making requested changes.\n";
$rc = addDeviceGroup($addDevGroup);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeDevGroup) && do {
print "\n-> Making requested changes.\n";
$rc = removeDeviceGroup($removeDevGroup, $force);
print "\t-> Done.\n";
last SWITCH;
};
defined($addDevGroupDevice) && do {
print "\n-> Making requested changes.\n";
$rc = addDeviceGroupDevice($deviceGroup, $addDevGroupDevice);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeDevGroupDevice) && do {
print "\n-> Making requested changes.\n";
$rc = removeDeviceGroupDevice($deviceGroup, $removeDevGroupDevice, $force);
print "\t-> Done.\n";
last SWITCH;
};
defined($addTargetGroup) && do {
print "\n-> Making requested changes.\n";
$rc = addTargetGroup($deviceGroup, $addTargetGroup);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeTargetGroup) && do {
print "\n-> Making requested changes.\n";
$rc = removeTargetGroup($deviceGroup, $removeTargetGroup, $force);
print "\t-> Done.\n";
last SWITCH;
};
defined($addTargetGroupTarget) && do {
print "\n-> Making requested changes.\n";
$rc = addTargetGroupTarget($deviceGroup, $targetGroup, $addTargetGroupTarget);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeTargetGroupTarget) && do {
print "\n-> Making requested changes.\n";
$rc = removeTargetGroupTarget($deviceGroup, $targetGroup, $removeTargetGroupTarget, $force);
print "\t-> Done.\n";
last SWITCH;
};
defined($addTarget) && do {
print "\n-> Making requested changes.\n";
$rc = addVirtualTarget($driver, $addTarget, $attributes);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeTarget) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeVirtualTarget($driver, $removeTarget);
$rc = issueLip($driver) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($addGroup) && do {
print "\n-> Making requested changes.\n";
$rc = addGroup($driver, $target, $addGroup);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeGroup) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeGroup($driver, $target, $removeGroup, $force);
print "\t-> Done.\n";
last SWITCH;
};
defined($addInitiator) && do {
print "\n-> Making requested changes.\n";
$rc = addInitiator($driver, $target, $group, $addInitiator);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeInitiator) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeInitiator($driver, $target, $group, $removeInitiator);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($moveInitiator) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = moveInitiator($driver, $target, $group, $moveInitiator, $to);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($clearInitiators) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = clearInitiators($driver, $target, $group);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($addLun) && do {
print "\n-> Making requested changes.\n";
$rc = addLun($driver, $target, $device, $addLun, $attributes, $group);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($removeLun) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = removeLun($driver, $target, $removeLun, $group);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($replaceLun) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = replaceLun($driver, $target, $group, $replaceLun, $device, $attributes);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($clearLuns) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = clearLuns($driver, $target, $group);
$rc = issueLip($driver, $target) if (!$rc && $lip);
print "\t-> Done.\n";
last SWITCH;
};
defined($enableTarget) && do {
print "\n-> Making requested changes.\n";
$rc = enableTarget($driver, $enableTarget);
print "\t-> Done.\n";
last SWITCH;
};
defined($disableTarget) && do {
last if (prompt());
print "\n-> Making requested changes.\n";
$rc = disableTarget($driver, $disableTarget);
print "\t-> Done.\n";
last SWITCH;
};
defined($issueLip) && do {
print "\n-> Making requested changes.\n";
$rc = issueLip($driver, $issueLip, TRUE) if (!$noLip);
print "\t-> Done.\n";
last SWITCH;
};
defined($dumpAttrs) && do {
print "SCST attributes:\n";
print Dumper($SCST->scstAttributes());
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
my $devices = $CURRENT{'handler'}->{$handler};
foreach my $device (sort @{$devices}) {
print "Device $device attributes:\n";
print Dumper($SCST->deviceAttributes($device));
}
}
last SWITCH;
};
if (!$all_good) {
print "No valid operations specified.\n";
exit 1;
}
}
issueWarning($SCST->errorString($rc)) if ($rc);
print "\nAll done.\n";
exit $rc;
}
sub readWorkingConfig {
my $force = shift;
my $errorString;
print "\nCollecting current configuration: ";
%CURRENT = ();
# Get current handlers/devices
my $handlers;
($handlers, $errorString) = $SCST->handlers();
immediateExit($errorString);
foreach my $handler (@{$handlers}) {
my $devices;
($devices, $errorString) = $SCST->devicesByHandler($handler);
immediateExit($errorString);
$CURRENT{'handler'}->{$handler} = $devices;
}
# Get current assignments
my $drivers;
($drivers, $errorString) = $SCST->drivers();
immediateExit($errorString);
foreach my $driver (@{$drivers}) {
my %empty;
$CURRENT{'assign'}->{$driver} = \%empty;
my $targets;
($targets, $errorString) = $SCST->targets($driver);
immediateExit($errorString);
foreach my $target (@{$targets}) {
my %empty;
$CURRENT{'assign'}->{$driver}->{$target} = \%empty;
my $luns;
($luns, $errorString) = $SCST->luns($driver, $target);
$CURRENT{'assign'}->{$driver}->{$target}->{'LUN'} = $luns if (defined($luns));
my $groups;
($groups, $errorString) = $SCST->groups($driver, $target);
immediateExit($errorString);
foreach my $group (@{$groups}) {
my $initiators;
($initiators, $errorString) = $SCST->initiators($driver, $target, $group);
immediateExit($errorString);
$CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'} = $initiators;
($luns, $errorString) = $SCST->luns($driver, $target, $group);
$CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'} = $luns;
immediateExit($errorString);
}
}
}
my $dgroups;
($dgroups, $errorString) = $SCST->deviceGroups();
immediateExit($errorString);
foreach my $dgroup (@{$dgroups}) {
my $dgd;
($dgd, $errorString) = $SCST->deviceGroupDevices($dgroup);
immediateExit($errorString);
$CURRENT{'dgroups'}->{$dgroup}->{'devices'} = $dgd;
my $tgroups;
($tgroups, $errorString) = $SCST->targetGroups($dgroup);
immediateExit($errorString);
foreach my $tgroup (@{$tgroups}) {
my $tgt;
($tgt, $errorString) = $SCST->targetGroupTargets($dgroup, $tgroup);
$CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'} = $tgt;
}
}
print "done.\n\n";
# Perform some basic checks
# Check for initiators belonging to more than one group
foreach my $driver (keys %{$CURRENT{'assign'}}) {
foreach my $target (keys %{$CURRENT{'assign'}->{$driver}}) {
my $current = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
my %seen_init;
foreach my $group (keys %{$current}) {
my $initiators = $$current{$group}->{'INITIATORS'};
foreach my $init (@{$initiators}) {
if (defined($seen_init{$init})) {
if (!$force) {
print "\t-> FATAL: Initiator '$init' belongs to more than one groups ".
"for driver/target '$driver/target', aborting. Use -force to override.\n";
return TRUE;
}
}
$seen_init{$init}++;
}
}
}
}
return FALSE;
}
# Older Perl versions complain if the argument of length() is undefined. Hence
# this function that checks whether its arguments are defined and not empty.
sub valid {
return $SCST->valid(@_);
}
# Escape metacharacters (space, backslash and hash sign).
sub escapeMeta {
my $value = shift;
$value =~ s/([\\\#])/\\$1/g;
if ($value =~ / /) {
$value = "\"$value\"";
}
return $value;
}
# Serialize key attributes.
# $prefix: output prefix, e.g. "\t\t".
# $attributes: reference to a hash with attributes and their values.
# $attr_filter: if specified, reference to a hash with the names of which
# (static) attributes to serialize.
sub serializeKeyAttr {
my $prefix = shift;
my $attributes = shift;
my $attr_filter = shift;
my $result = "";
foreach my $attribute (sort keys %{$attributes}) {
next if defined($$attributes{$attribute}->{'set'});
next if ($$attributes{$attribute}->{'static'} &&
!(defined($attr_filter)
&& defined($$attr_filter{$attribute})));
if (defined($$attributes{$attribute}->{'keys'})) {
my @values;
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
my $value =
$$attributes{$attribute}->{'keys'}->{$key}->{'value'};
# $value = undef means that the attribute is write-only.
push (@values, $value) if (defined($value));
}
foreach my $value (sort @values) {
$result .= "$prefix$attribute " . escapeMeta($value) . "\n";
}
} elsif ($attribute eq 'enabled' || $attribute eq 'hw_target' || $attribute eq 'size' || $attribute eq 'size_mb') {
my $value = $$attributes{$attribute}->{'value'};
$result .= "$prefix$attribute $value\n";
}
}
return $result;
}
# Serialize non-key attributes.
# $prefix: output prefix, e.g. "\t\t".
# $attributes: reference to a hash with attributes and their values.
# $attr_filter: if specified, reference to a hash with the names of which
# (static) attributes to serialize.
sub serializeNkAttr {
my $prefix = shift;
my $attributes = shift;
my $attr_filter = shift;
my $result = "";
foreach my $attribute (sort keys %{$attributes}) {
if (!defined($$attributes{$attribute}->{'set'})
&& (!$$attributes{$attribute}->{'static'}
|| defined($attr_filter)
&& defined($$attr_filter{$attribute}))
&& !defined($$attributes{$attribute}->{'keys'})
&& $attribute ne 'dif_checks_failed'
&& $attribute ne 'enabled'
&& $attribute ne 'hw_target') {
my $value = $$attributes{$attribute}->{'value'};
# $value = undef means that the attribute is write-only.
if (defined($value)) {
$result .= "$prefix$attribute " . escapeMeta($value) . "\n";
}
}
}
return $result;
}
# Return TRUE if and only if $1 is an SCST pass-through device.
sub isPassthroughDev {
my $dev = shift;
my $pt = FALSE;
my $errorString;
foreach my $handler (keys %{$CURRENT{'handler'}}) {
my $ha;
($ha, $errorString) = $SCST->handlerAttributes($handler);
next if (defined($ha->{'mgmt'}) &&
$ha->{'mgmt'} !~ 'echo "add_device H:C:I:L"');
my @devs = @{$CURRENT{'handler'}->{$handler}};
for my $i (0 .. $#devs) {
if ($dev eq $devs[$i]) {
$pt = TRUE;
last;
}
}
last if $pt;
}
}
#***********************************************************************************************
# Returns 0 upon success and 1 upon error.
sub writePeerConfiguration {
my $nonkey = shift;
my $errorString;
my $io = new IO::File $CONFIGFILE, O_CREAT|O_WRONLY|O_TRUNC;
if (!$io) {
print "Failed to save configuration to file '$CONFIGFILE': $!\n";
return 1;
}
print "Writing current configuration to file '$CONFIGFILE'.. ";
print $io "# Automatically generated by $Version.\n\n";
{
my ($attributes, $errorString) = $SCST->scstAttributes();
immediateExit($errorString);
print $io serializeKeyAttr("", $attributes);
if ($nonkey) {
my $nk = serializeNkAttr("", $attributes);
if ($nk) {
print $io "# Non-key attributes\n";
print $io $nk;
}
}
print $io "\n";
}
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
my $handler_buff;
my $handler_buff_nk;
my $handler_attrs;
my $attributes;
($handler_attrs, $errorString) = $SCST->deviceCreateAttributes($handler);
($attributes, $errorString) = $SCST->handlerAttributes($handler);
$handler_buff = serializeKeyAttr("\t", $attributes);
$handler_buff_nk = serializeNkAttr("\t", $attributes) if ($nonkey);
my $devices = $CURRENT{'handler'}->{$handler};
my $device_buff;
foreach my $device (sort @{$devices}) {
my ($attributes, $errorString) = $SCST->deviceAttributes($device);
if ($handler eq 'vdisk_fileio') {
if ($device eq 'disk00') {
$attributes->{naa_id}->{keys}->{0}->{value} = "0x638a95f000000${CLUSTERID}00000$PEERBBSID";
} else {
next; ###For now skip fileio devices, they break the remote config
}
}
$device_buff .= "\tDEVICE $device";
if ($handler eq 'vdisk_blockio') {
$attributes->{active}->{keys}->{0}->{value} = "0";
}
my $attribute_buff;
my $attribute_buff_nk;
$attribute_buff = serializeKeyAttr("\t\t", $attributes, $handler_attrs);
$attribute_buff_nk = serializeNkAttr("\t\t", $attributes, $handler_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
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;
my $drv_attr_buff = "";
my $drv_attr_buff_nk = "";
($drv_attrs, $errorString) = $SCST->driverAttributes($driver);
$drv_attr_buff = serializeKeyAttr("\t", $drv_attrs);
$drv_attr_buff_nk = serializeNkAttr("\t", $drv_attrs) if ($nonkey);
$drv_attr_buff .= "\n" if ($drv_attr_buff);
$drv_attr_buff_nk .= "\n" if ($drv_attr_buff_nk);
my $targets = $CURRENT{'assign'}->{$driver};
my ($tgt_attrs, $errorString) = $SCST->targetCreateAttributes($driver);
my $target_buff;
use Data::Dumper;
#warn Dumper ($attributes, $handler_attrs, $handler);
#warn Dumper ($handler_attrs);
foreach my $target (sort keys %{$targets}) {
if ($target eq $MYWWPN1) {
$target_buff .= "\tTARGET $PEERWWPN1";
} elsif ($target eq $MYWWPN2) {
$target_buff .= "\tTARGET $PEERWWPN2";
} elsif ($target eq $MYWWPN3) {
$target_buff .= "\tTARGET $PEERWWPN3";
} elsif ($target eq $MYWWPN4) {
$target_buff .= "\tTARGET $PEERWWPN4";
} else {
$target_buff .= "\tTARGET $target";
}
my $attributes;
my $attribute_buff = "";
my $attribute_buff_nk = "";
($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
if (defined($$attributes{'hw_target'}) &&
($$attributes{'hw_target'}->{'value'} == TRUE)) {
$attribute_buff = "\t\tHW_TARGET\n\n";
}
$attribute_buff .= serializeKeyAttr("\t\t", $attributes, $tgt_attrs);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes, $tgt_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'};
my ($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target);
my $t_lun_buff;
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
# Do not save copy_manager LUN definitions
# for LUNs associated with an SCST device
# handler.
next if ($driver eq 'copy_manager' &&
isPassthroughDev($lun_dev));
$t_lun_buff .= "\t\tLUN $lun $lun_dev";
my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun);
my $l_attribute_buff =
serializeKeyAttr("\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk =
serializeNkAttr("\t\t\t",
$attributes,
$lun_attrs) if ($nonkey);
if ($l_attribute_buff_nk) {
$l_attribute_buff .= "\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";
}
}
$t_lun_buff .= "\n" if ($t_lun_buff);
$t_lun_buff =~ s/\n+$/\n\n/;
my $groups = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
my $group_buff;
foreach my $group (sort keys %{$groups}) {
my $lun_attrs;
my $ini_attrs;
($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group);
($ini_attrs, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group);
$group_buff .= "\t\tGROUP $group";
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'};
my $lun_buff;
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
$lun_buff .= "\t\t\tLUN $lun $lun_dev";
my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
my $l_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$lun_attrs)
if ($nonkey);
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";
} else {
$lun_buff .= "\n";
}
}
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'};
my $init_buff;
foreach my $init (sort @{$inits}) {
$init_buff .= "\n\t\t\tINITIATOR " . escapeMeta($init);
my ($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $init);
my $i_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$ini_attrs);
my $i_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$ini_attrs)
if ($nonkey);
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";
}
}
my $grp_attributes;
($grp_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group);
my $g_attribute_buff
= serializeKeyAttr("\t\t\t",
$grp_attributes);
my $g_attribute_buff_nk
= serializeNkAttr("\t\t\t",
$grp_attributes)
if ($nonkey);
if ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk) {
$group_buff .= " {\n";
$group_buff .= $lun_buff;
$group_buff .= $init_buff;
}
if ($g_attribute_buff_nk) {
$g_attribute_buff .= "\n" if ($g_attribute_buff);
$g_attribute_buff .= "\t\t\t# Non-key attributes\n";
$g_attribute_buff .= $g_attribute_buff_nk;
}
if ($g_attribute_buff) {
$group_buff .= "\n";
$group_buff .= $g_attribute_buff;
}
if ($group_buff && ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk)) {
$group_buff .= "\t\t}\n\n";
$group_buff =~ s/\n+$/\n/;
}
$group_buff .= "\n" if ($group_buff);
}
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";
if($driver eq 'iscsi') {
print $io "\tenabled 1\n";
} elsif ($driver eq 'copy_manager') {
print $io "\tTARGET copy_manager_tgt\n";;
} else {
print $io $driver_buff;
}
print $io "}\n\n";
}
}
my $dga;
($dga, $errorString) = $SCST->aluaAttributes();
my $dga_buff = serializeKeyAttr("\t", $dga);
my $dga_buff_nk = serializeNkAttr("\t", $dga) if ($nonkey);
if ($dga_buff_nk) {
$dga_buff .= "\t# Non-key attributes\n";
$dga_buff .= $dga_buff_nk;
}
if ($dga_buff) {
print $io "ALUA {\n";
print $io $dga_buff;
print $io "}\n\n";
}
foreach my $dgroup (sort keys %{$CURRENT{'dgroups'}}) {
my $dgroup_buff;
my ($dgroup_attrs, $errorString) = $SCST->deviceGroupAttributes($dgroup);
my $dgrp_attr_buff;
my $dgrp_attr_buff_nk;
$dgrp_attr_buff = serializeKeyAttr("\t", $dgroup_attrs);
$dgrp_attr_buff_nk = serializeNkAttr("\t", $dgroup_attrs) if ($nonkey);
$dgrp_attr_buff .= "\n" if ($dgrp_attr_buff);
$dgrp_attr_buff_nk .= "\n" if ($dgrp_attr_buff_nk);
my $devices_buff;
my $devices = $CURRENT{'dgroups'}->{$dgroup}->{'devices'};
foreach my $device (sort @{$devices}) {
$devices_buff .= "\tDEVICE $device\n";
}
$devices_buff .= "\n" if ($devices_buff);
my $tgroups = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'};
my $tgroup_buff;
foreach my $tgroup (sort keys %{$tgroups}) {
$tgroup_buff .= "\tTARGET_GROUP $tgroup";
my ($attributes, $errorString) = $SCST->targetGroupAttributes($dgroup, $tgroup);
my $attribute_buff;
my $attribute_buff_nk;
$attribute_buff .= serializeKeyAttr("\t\t", $attributes);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $tgts = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'};
my $tgt_buff;
if ($tgroup eq $PEERNAME) {
$tgt_buff .= "\t\tTARGET $PEERWWPN1\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN2\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN3\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN4\n";
}
if ($attribute_buff_nk) {
$attribute_buff .= "\t\t# Non-key attributes\n";
$attribute_buff .= $attribute_buff_nk;
}
if ($attribute_buff || $tgt_buff) {
$tgroup_buff .= " {\n";
$tgroup_buff .= $attribute_buff;
$tgroup_buff .= $tgt_buff;
$tgroup_buff =~ s/\n\n$/\n/;
$tgroup_buff .= "\t}\n\n";
} else {
$tgroup_buff .= "\n";
}
}
if ($dgrp_attr_buff_nk) {
$dgrp_attr_buff .= "\t# Non-key attributes\n";
$dgrp_attr_buff .= $dgrp_attr_buff_nk;
}
$dgroup_buff .= $dgrp_attr_buff;
$dgroup_buff .= $devices_buff;
$dgroup_buff .= $tgroup_buff;
$dgroup_buff =~ s/\n\n$/\n/;
if ($dgroup_buff) {
print $io "DEVICE_GROUP $dgroup {\n";
print $io $dgroup_buff;
print $io "}\n\n";
}
}
$io->flush;
$io->sync;
close $io;
return 0;
}
#***********************************************************************************************
# Returns 0 upon success and 1 upon error.
sub peerQuickConfiguration {
my $nonkey = shift;
my $errorString;
my $io = new IO::File $CONFIGFILE, O_CREAT|O_WRONLY|O_TRUNC;
if (!$io) {
print "Failed to save configuration to file '$CONFIGFILE': $!\n";
return 1;
}
print "Writing current configuration to file '$CONFIGFILE'.. ";
print $io "# Automatically generated by $Version.\n\n";
{
my ($attributes, $errorString) = $SCST->scstAttributes();
immediateExit($errorString);
print $io serializeKeyAttr("", $attributes);
if ($nonkey) {
my $nk = serializeNkAttr("", $attributes);
if ($nk) {
print $io "# Non-key attributes\n";
print $io $nk;
}
}
print $io "\n";
}
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
my $handler_buff = "";
my $handler_buff_nk = "";
my $handler_attrs;
my $attributes;
($handler_attrs, $errorString) = $SCST->deviceCreateAttributes($handler);
($attributes, $errorString) = $SCST->handlerAttributes($handler);
$handler_buff = serializeKeyAttr("\t", $attributes);
$handler_buff_nk = serializeNkAttr("\t", $attributes) if ($nonkey);
my $devices = $CURRENT{'handler'}->{$handler};
my $device_buff;
foreach my $device (sort @{$devices}) {
my ($attributes, $errorString) = $SCST->deviceAttributes($device);
if ($handler eq 'vdisk_fileio') {
if ($device eq 'disk00') {
$attributes->{naa_id}->{keys}->{0}->{value} = "0x638a95f000000${CLUSTERID}00000$PEERBBSID";
} else {
next; ###For now skip fileio devices, they break the remote config
}
}
$device_buff .= "\tDEVICE $device";
my $attribute_buff;
my $attribute_buff_nk;
$attribute_buff = serializeKeyAttr("\t\t", $attributes, $handler_attrs);
$attribute_buff_nk = serializeNkAttr("\t\t", $attributes, $handler_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
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;
my $drv_attr_buff = "";
my $drv_attr_buff_nk = "";
($drv_attrs, $errorString) = $SCST->driverAttributes($driver);
$drv_attr_buff = serializeKeyAttr("\t", $drv_attrs);
$drv_attr_buff_nk = serializeNkAttr("\t", $drv_attrs) if ($nonkey);
$drv_attr_buff .= "\n" if ($drv_attr_buff);
$drv_attr_buff_nk .= "\n" if ($drv_attr_buff_nk);
my $targets = $CURRENT{'assign'}->{$driver};
my ($tgt_attrs, $errorString) = $SCST->targetCreateAttributes($driver);
my $target_buff;
foreach my $target (sort keys %{$targets}) {
if ($target eq $MYWWPN1) {
$target_buff .= "\tTARGET $PEERWWPN1";
} elsif ($target eq $MYWWPN2) {
$target_buff .= "\tTARGET $PEERWWPN2";
} elsif ($target eq $MYWWPN3) {
$target_buff .= "\tTARGET $PEERWWPN3";
} elsif ($target eq $MYWWPN4) {
$target_buff .= "\tTARGET $PEERWWPN4";
} else {
$target_buff .= "\tTARGET $target";
}
my $attributes;
my $attribute_buff = "";
my $attribute_buff_nk = "";
($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
if (defined($$attributes{'hw_target'}) &&
($$attributes{'hw_target'}->{'value'} == TRUE)) {
$attribute_buff = "\t\tHW_TARGET\n\n";
}
$attribute_buff .= serializeKeyAttr("\t\t", $attributes, $tgt_attrs);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes, $tgt_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'};
my ($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target);
my $t_lun_buff;
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
# Do not save copy_manager LUN definitions
# for LUNs associated with an SCST device
# handler.
next if ($driver eq 'copy_manager' &&
isPassthroughDev($lun_dev));
$t_lun_buff .= "\t\tLUN $lun $lun_dev";
my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun);
my $l_attribute_buff =
serializeKeyAttr("\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk =
serializeNkAttr("\t\t\t",
$attributes,
$lun_attrs) if ($nonkey);
if ($l_attribute_buff_nk) {
$l_attribute_buff .= "\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";
}
}
$t_lun_buff .= "\n" if ($t_lun_buff);
$t_lun_buff =~ s/\n+$/\n\n/;
my $groups = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
my $group_buff;
foreach my $group (sort keys %{$groups}) {
my $lun_attrs;
my $ini_attrs;
($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group);
($ini_attrs, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group);
$group_buff .= "\t\tGROUP $group";
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'};
my $lun_buff;
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
$lun_buff .= "\t\t\tLUN $lun $lun_dev";
my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
my $l_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$lun_attrs)
if ($nonkey);
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";
} else {
$lun_buff .= "\n";
}
}
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'};
my $init_buff;
foreach my $init (sort @{$inits}) {
$init_buff .= "\n\t\t\tINITIATOR " . escapeMeta($init);
my ($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $init);
my $i_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$ini_attrs);
my $i_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$ini_attrs)
if ($nonkey);
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";
}
}
my $grp_attributes;
($grp_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group);
my $g_attribute_buff
= serializeKeyAttr("\t\t\t",
$grp_attributes);
my $g_attribute_buff_nk
= serializeNkAttr("\t\t\t",
$grp_attributes)
if ($nonkey);
if ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk) {
$group_buff .= " {\n";
$group_buff .= $lun_buff;
$group_buff .= $init_buff;
}
if ($g_attribute_buff_nk) {
$g_attribute_buff .= "\n" if ($g_attribute_buff);
$g_attribute_buff .= "\t\t\t# Non-key attributes\n";
$g_attribute_buff .= $g_attribute_buff_nk;
}
if ($g_attribute_buff) {
$group_buff .= "\n";
$group_buff .= $g_attribute_buff;
}
if ($group_buff && ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk)) {
$group_buff .= "\t\t}\n\n";
$group_buff =~ s/\n+$/\n/;
}
$group_buff .= "\n" if ($group_buff);
}
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";
if($driver eq 'copy_manager') {
print $io "\tTARGET copy_manager_tgt\n";;
} else {
print $io $driver_buff;
}
print $io "}\n\n";
}
}
my $dga;
($dga, $errorString) = $SCST->aluaAttributes();
my $dga_buff = serializeKeyAttr("\t", $dga);
my $dga_buff_nk = serializeNkAttr("\t", $dga) if ($nonkey);
if ($dga_buff_nk) {
$dga_buff .= "\t# Non-key attributes\n";
$dga_buff .= $dga_buff_nk;
}
if ($dga_buff) {
print $io "ALUA {\n";
print $io $dga_buff;
print $io "}\n\n";
}
foreach my $dgroup (sort keys %{$CURRENT{'dgroups'}}) {
my $dgroup_buff;
my ($dgroup_attrs, $errorString) = $SCST->deviceGroupAttributes($dgroup);
my $dgrp_attr_buff;
my $dgrp_attr_buff_nk;
$dgrp_attr_buff = serializeKeyAttr("\t", $dgroup_attrs);
$dgrp_attr_buff_nk = serializeNkAttr("\t", $dgroup_attrs) if ($nonkey);
$dgrp_attr_buff .= "\n" if ($dgrp_attr_buff);
$dgrp_attr_buff_nk .= "\n" if ($dgrp_attr_buff_nk);
my $devices_buff;
my $devices = $CURRENT{'dgroups'}->{$dgroup}->{'devices'};
foreach my $device (sort @{$devices}) {
$devices_buff .= "\tDEVICE $device\n";
}
$devices_buff .= "\n" if ($devices_buff);
my $tgroups = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'};
my $tgroup_buff;
foreach my $tgroup (sort keys %{$tgroups}) {
$tgroup_buff .= "\tTARGET_GROUP $tgroup";
my ($attributes, $errorString) = $SCST->targetGroupAttributes($dgroup, $tgroup);
my $attribute_buff;
my $attribute_buff_nk;
if ($tgroup eq $PEERNAME) {
$attributes->{state}->{keys}->{0}->{value} = "active";
}
if ($tgroup eq $MYNAME)
{
$attributes->{state}->{keys}->{0}->{value} = "standby";
}
$attribute_buff .= serializeKeyAttr("\t\t", $attributes);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $tgts = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'};
my $tgt_buff;
if ($tgroup eq $PEERNAME) {
$tgt_buff .= "\t\tTARGET $PEERWWPN1\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN2\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN3\n";
$tgt_buff .= "\t\tTARGET $PEERWWPN4\n";
}
if ($attribute_buff_nk) {
$attribute_buff .= "\t\t# Non-key attributes\n";
$attribute_buff .= $attribute_buff_nk;
}
if ($attribute_buff || $tgt_buff) {
$tgroup_buff .= " {\n";
$tgroup_buff .= $attribute_buff;
$tgroup_buff .= $tgt_buff;
$tgroup_buff =~ s/\n\n$/\n/;
$tgroup_buff .= "\t}\n\n";
} else {
$tgroup_buff .= "\n";
}
}
if ($dgrp_attr_buff_nk) {
$dgrp_attr_buff .= "\t# Non-key attributes\n";
$dgrp_attr_buff .= $dgrp_attr_buff_nk;
}
$dgroup_buff .= $dgrp_attr_buff;
$dgroup_buff .= $devices_buff;
$dgroup_buff .= $tgroup_buff;
$dgroup_buff =~ s/\n\n$/\n/;
if ($dgroup_buff) {
print $io "DEVICE_GROUP $dgroup {\n";
print $io $dgroup_buff;
print $io "}\n\n";
}
}
$io->flush;
$io->sync;
close $io;
return 0;
}
#***********************************************************************************************
# Returns 0 upon success and 1 upen error.
sub writeConfiguration {
my $nonkey = shift;
my $errorString;
my $io = new IO::File $CONFIGFILE, O_CREAT|O_WRONLY|O_TRUNC;
if (!$io) {
print "Failed to save configuration to file '$CONFIGFILE': $!\n";
return 1;
}
print "Writing current configuration to file '$CONFIGFILE'.. ";
print $io "# Automatically generated by $Version.\n\n";
{
my $attributes;
($attributes, $errorString) = $SCST->scstAttributes();
immediateExit($errorString);
print $io serializeKeyAttr("", $attributes);
if ($nonkey) {
my $nk = serializeNkAttr("", $attributes);
if ($nk) {
print $io "# Non-key attributes\n";
print $io $nk;
}
}
print $io "\n";
}
foreach my $handler (sort keys %{$CURRENT{'handler'}}) {
my $handler_buff = "";
my $handler_buff_nk = "";
my $handler_attrs;
my $attributes;
($handler_attrs, $errorString) = $SCST->deviceCreateAttributes($handler);
($attributes, $errorString) = $SCST->handlerAttributes($handler);
$handler_buff = serializeKeyAttr("\t", $attributes);
$handler_buff_nk = serializeNkAttr("\t", $attributes) if ($nonkey);
my $devices = $CURRENT{'handler'}->{$handler};
my $device_buff = "";
foreach my $device (sort @{$devices}) {
$device_buff .= "\tDEVICE $device";
my $attributes;
my $attribute_buff = "";
my $attribute_buff_nk = "";
($attributes, $errorString) = $SCST->deviceAttributes($device);
$attribute_buff = serializeKeyAttr("\t\t", $attributes, $handler_attrs);
$attribute_buff_nk = serializeNkAttr("\t\t", $attributes, $handler_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
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;
my $drv_attr_buff = "";
my $drv_attr_buff_nk = "";
($drv_attrs, $errorString) = $SCST->driverAttributes($driver);
$drv_attr_buff = serializeKeyAttr("\t", $drv_attrs);
$drv_attr_buff_nk = serializeNkAttr("\t", $drv_attrs) if ($nonkey);
$drv_attr_buff .= "\n" if ($drv_attr_buff);
$drv_attr_buff_nk .= "\n" if ($drv_attr_buff_nk);
my $targets = $CURRENT{'assign'}->{$driver};
my $tgt_attrs;
($tgt_attrs, $errorString) = $SCST->targetCreateAttributes($driver);
my $target_buff = "";
foreach my $target (sort keys %{$targets}) {
$target_buff .= "\tTARGET $target";
my $attributes;
my $attribute_buff = "";
my $attribute_buff_nk = "";
($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
if (defined($$attributes{'hw_target'}) &&
($$attributes{'hw_target'}->{'value'} == TRUE)) {
$attribute_buff = "\t\tHW_TARGET\n\n";
}
$attribute_buff .= serializeKeyAttr("\t\t", $attributes, $tgt_attrs);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes, $tgt_attrs) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'};
my $lun_attrs;
($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target);
my $t_lun_buff = "";
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
# Do not save copy_manager LUN definitions
# for LUNs associated with an SCST device
# handler.
next if ($driver eq 'copy_manager' &&
isPassthroughDev($lun_dev));
$t_lun_buff .= "\t\tLUN $lun $lun_dev";
my $attributes;
($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun);
my $l_attribute_buff =
serializeKeyAttr("\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk =
serializeNkAttr("\t\t\t",
$attributes,
$lun_attrs) if ($nonkey);
if ($l_attribute_buff_nk) {
$l_attribute_buff .= "\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";
}
}
$t_lun_buff .= "\n" if ($t_lun_buff);
$t_lun_buff =~ s/\n+$/\n\n/;
my $groups = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
my $group_buff = "";
foreach my $group (sort keys %{$groups}) {
my $lun_attrs;
my $ini_attrs;
($lun_attrs, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group);
($ini_attrs, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group);
$group_buff .= "\t\tGROUP $group";
my $luns = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'};
my $lun_buff = "";
foreach my $lun (sort numerically keys %{$luns}) {
my $lun_dev = $$luns{$lun};
$lun_buff .= "\t\t\tLUN $lun $lun_dev";
my $attributes;
($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
my $l_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$lun_attrs);
my $l_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$lun_attrs)
if ($nonkey);
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";
} else {
$lun_buff .= "\n";
}
}
my $inits = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'INITIATORS'};
my $init_buff = "";
foreach my $init (sort @{$inits}) {
$init_buff .= "\n\t\t\tINITIATOR " . escapeMeta($init);
my $attributes;
($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $init);
my $i_attribute_buff
= serializeKeyAttr("\t\t\t\t",
$attributes,
$ini_attrs);
my $i_attribute_buff_nk
= serializeNkAttr("\t\t\t\t",
$attributes,
$ini_attrs)
if ($nonkey);
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";
}
}
my $grp_attributes;
($grp_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group);
my $g_attribute_buff
= serializeKeyAttr("\t\t\t",
$grp_attributes);
my $g_attribute_buff_nk
= serializeNkAttr("\t\t\t",
$grp_attributes)
if ($nonkey);
if ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk) {
$group_buff .= " {\n";
$group_buff .= $lun_buff;
$group_buff .= $init_buff;
}
if ($g_attribute_buff_nk) {
$g_attribute_buff .= "\n" if ($g_attribute_buff);
$g_attribute_buff .= "\t\t\t# Non-key attributes\n";
$g_attribute_buff .= $g_attribute_buff_nk;
}
if ($g_attribute_buff) {
$group_buff .= "\n";
$group_buff .= $g_attribute_buff;
}
if ($group_buff && ($lun_buff || $init_buff ||
$g_attribute_buff || $g_attribute_buff_nk)) {
$group_buff .= "\t\t}\n\n";
$group_buff =~ s/\n+$/\n/;
}
$group_buff .= "\n" if ($group_buff);
}
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";
}
}
my $dga;
($dga, $errorString) = $SCST->aluaAttributes();
my $dga_buff = serializeKeyAttr("\t", $dga);
my $dga_buff_nk = serializeNkAttr("\t", $dga) if ($nonkey);
if ($dga_buff_nk) {
$dga_buff .= "\t# Non-key attributes\n";
$dga_buff .= $dga_buff_nk;
}
if ($dga_buff) {
print $io "ALUA {\n";
print $io $dga_buff;
print $io "}\n\n";
}
foreach my $dgroup (sort keys %{$CURRENT{'dgroups'}}) {
my $dgroup_buff = "";
my $dgroup_attrs;
my $dgrp_attr_buff = "";
my $dgrp_attr_buff_nk = "";
($dgroup_attrs, $errorString) = $SCST->deviceGroupAttributes($dgroup);
$dgrp_attr_buff = serializeKeyAttr("\t", $dgroup_attrs);
$dgrp_attr_buff_nk = serializeNkAttr("\t", $dgroup_attrs) if ($nonkey);
$dgrp_attr_buff .= "\n" if ($dgrp_attr_buff);
$dgrp_attr_buff_nk .= "\n" if ($dgrp_attr_buff_nk);
my $devices_buff = "";
my $devices = $CURRENT{'dgroups'}->{$dgroup}->{'devices'};
foreach my $device (sort @{$devices}) {
$devices_buff .= "\tDEVICE $device\n";
}
$devices_buff .= "\n" if ($devices_buff);
my $tgroups = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'};
my $tgroup_buff = "";
foreach my $tgroup (sort keys %{$tgroups}) {
$tgroup_buff .= "\tTARGET_GROUP $tgroup";
my $attributes;
my $attribute_buff = "";
my $attribute_buff_nk = "";
($attributes, $errorString) = $SCST->targetGroupAttributes($dgroup, $tgroup);
$attribute_buff .= serializeKeyAttr("\t\t", $attributes);
$attribute_buff_nk .= serializeNkAttr("\t\t", $attributes) if ($nonkey);
$attribute_buff .= "\n" if ($attribute_buff);
$attribute_buff_nk .= "\n" if ($attribute_buff_nk);
my $tgts = $CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'};
my $tgt_buff = "";
foreach my $tgt (@{$tgts}) {
$tgt_buff .= "\t\tTARGET $tgt";
my $tgt_attrs;
($tgt_attrs, $errorString) = $SCST->targetGroupTargetAttributes($dgroup, $tgroup, $tgt);
my $t_attribute_buff
= serializeKeyAttr("\t\t\t", $tgt_attrs);
my $t_attribute_buff_nk
= serializeNkAttr("\t\t\t", $tgt_attrs) if ($nonkey);
if ($t_attribute_buff_nk) {
$t_attribute_buff .= "\t\t\t# Non-key attributes\n";
$t_attribute_buff .= $t_attribute_buff_nk;
}
if ($t_attribute_buff) {
$tgt_buff .= " {\n";
$tgt_buff .= $t_attribute_buff;
$tgt_buff .= "\t\t}\n";
} else {
$tgt_buff .= "\n";
}
}
if ($attribute_buff_nk) {
$attribute_buff .= "\t\t# Non-key attributes\n";
$attribute_buff .= $attribute_buff_nk;
}
if ($attribute_buff || $tgt_buff) {
$tgroup_buff .= " {\n";
$tgroup_buff .= $attribute_buff;
$tgroup_buff .= $tgt_buff;
$tgroup_buff =~ s/\n\n$/\n/;
$tgroup_buff .= "\t}\n\n";
} else {
$tgroup_buff .= "\n";
}
}
if ($dgrp_attr_buff_nk) {
$dgrp_attr_buff .= "\t# Non-key attributes\n";
$dgrp_attr_buff .= $dgrp_attr_buff_nk;
}
$dgroup_buff .= $dgrp_attr_buff;
$dgroup_buff .= $devices_buff;
$dgroup_buff .= $tgroup_buff;
$dgroup_buff =~ s/\n\n$/\n/;
if ($dgroup_buff) {
print $io "DEVICE_GROUP $dgroup {\n";
print $io $dgroup_buff;
print $io "}\n\n";
}
}
$io->flush;
$io->sync;
close $io;
return 0;
}
sub checkConfiguration {
my $no_drivers;
my $no_handlers;
my $warnings = 0;
my $errors = 0;
print "-> Checking configuration file '$CONFIGFILE' for errors.\n";
readConfigFile() if (!$CONFIG);
if (!scalar keys %{$CONFIG}) {
print "-> WARNING: Configuration is empty or unreadable, aborting.\n\n";
exit 0;
}
# 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\n";
$no_drivers = TRUE;
$warnings++;
}
if (!defined($$CONFIG{'HANDLER'}) ||
!(scalar keys %{$$CONFIG{'HANDLER'}})) {
print "\t-> WARNING: No HANDLER section defined. ".
"Only physical media will be configured for targets.\n\n";
$no_handlers = TRUE;
$warnings++;
}
if ($no_drivers && $no_handlers) {
print "FATAL: No target drivers or handlers defined, aborting!\n";
$errors++;
}
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\n";
$warnings++;
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\n";
$warnings++;
$no_targets = TRUE;
}
if (!$no_targets) {
foreach my $target (keys %{$$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}}) {
my $groups = $$CONFIG{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'};
my %seen_init;
foreach my $group (keys %{$groups}) {
foreach my $initiator (keys %{$$groups{$group}->{'INITIATOR'}}) {
if (defined($seen_init{$initiator})) {
print "\t-> FATAL: Initiator '$initiator' belongs to more than one group.\n".
"\t Initiators can only belong to one group at a time for a given target.\n";
$errors++;
}
$seen_init{$initiator}++;
}
}
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
if (!$SCST->driverIsVirtualCapable($driver)) {
print "\t-> FATAL: Target '$target' for driver '$driver' ".
"does not exist.\n";
$errors++;
}
}
}
}
}
}
my %cdevices;
foreach my $handler (sort keys %{$$CONFIG{'HANDLER'}}) {
if (!$SCST->handlerExists($handler)) {
print "\t-> WARNING: No such handler '$handler' available, ignoring.\n";
delete $$CONFIG{'HANDLER'}->{$handler};
$warnings++;
next;
}
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\n";
delete $$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}->{$device};
$$CONFIG{'HANDLER'}->{$handler}->{'DEVICE'}->{$_device} = $tree;
$warnings++;
} elsif ($device =~ /\//) {
print "\t-> FATAL: Device '$device' configured for handler '$handler' may not ".
"contain character '/'.\n";
$errors++;
}
$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\n";
delete $$tgt{'LUN'}->{$lun};
$warnings++;
}
}
}
if ($driver ne 'copy_manager' && !defined($$tgt{'LUN'}->{'0'})) {
print "\t-> WARNING: No LUN 0 defined for driver/target '$driver/$target'. ".
"Many initiators require a LUN 0 to be defined.\n\n";
$warnings++;
}
}
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\n";
delete $$tgt{'GROUP'}->{$group}->{'LUN'}->{$lun};
$warnings++;
}
}
}
if (!defined($$tgt{'GROUP'}->{$group}->{'LUN'}->{'0'})) {
print "\t-> WARNING: No LUN 0 defined for driver/target/group '$driver/$target/$group'. ".
"Many initiators require a LUN 0 to be defined.\n\n";
$warnings++;
}
}
}
}
}
}
foreach my $dgroup (keys %{$$CONFIG{'DEVICE_GROUP'}}) {
foreach my $device (keys %{$$CONFIG{'DEVICE_GROUP'}->{$dgroup}->{'DEVICE'}}) {
if (!defined($cdevices{$device})) {
print "\t-> WARNING: Device '$device' associated with device group '$dgroup' ".
"is not defined within configuration, removing it.\n\n";
delete $$CONFIG{'DEVICE_GROUP'}->{$dgroup}->{'DEVICE'}->{$device};
$warnings++;
}
}
}
if ($errors) {
print "\t-> Done, $errors errors found.\n";
return TRUE;
}
print "\t-> Done, $warnings warnings found.\n\n";
return FALSE;
}
sub applyConfiguration {
my $force = shift;
my $changes = 0;
readConfigFile() if (!$CONFIG);
print "-> Applying configuration.\n";
# Apply config deletions
if ($force) {
$changes += applyConfigAssignments($CONFIG, $force, TRUE);
my $rc = readWorkingConfig($force);
exit $rc if ($rc);
}
# Apply config additions
$changes += applyConfigDevices($CONFIG, $force);
$changes += applyConfigAssignments($CONFIG, $force);
$changes += applyConfigAlua($CONFIG, $force);
$changes += applyConfigDeviceGroups($CONFIG, $force);
$changes += applyConfigEnableTargets($CONFIG, $force);
$changes += applyConfigEnableDrivers($CONFIG, $force);
# And SCST attributes..
my %_attributes;
foreach my $item (keys %{$CONFIG}) {
next if ($item eq 'HANDLER');
next if ($item eq 'TARGET_DRIVER');
next if ($item eq 'ALUA');
next if ($item eq 'DEVICE_GROUP');
$_attributes{$item} = $$CONFIG{$item};
}
my $attributes = configToAttr(\%_attributes);
$changes += setScstAttributes($attributes);
print "\t-> Done, $changes change(s) made.\n";
return $changes;
}
sub applyConfigDevices {
my $config = shift;
my $deletions = shift;
my $changes = 0;
my $errorString;
my $handlers = $CURRENT{'handler'};
foreach my $handler (keys %{$handlers}) {
foreach my $device (@{$$handlers{$handler}}) {
if (!defined($$config{'HANDLER'}->{$handler}->{'DEVICE'}->{$device})) {
my $attributes;
($attributes, $errorString) = $SCST->deviceAttributes($device);
if ($deletions) {
closeDevice($handler, $device, $deletions);
$changes++;
} 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}) {
my %_attributes;
my %_cattributes;
foreach my $item (keys %{$$devices{$device}}) {
$_attributes{$item} = $$devices{$device}->{$item};
}
my $attributes = configToAttr(\%_attributes);
my $create_attrs = configToAttr(\%_attributes);
my $possible;
($possible, $errorString) = $SCST->deviceCreateAttributes($handler);
condExit($errorString);
filterCreateAttributes($possible, $create_attrs, FALSE);
filterCreateAttributes($possible, $attributes, TRUE);
if (handlerHasDevice($handler, $device)) {
my $old_create_attrs;
($old_create_attrs, $errorString) = $SCST->deviceAttributes($device);
condExit($errorString);
filterCreateAttributes($possible, $old_create_attrs, FALSE);
if (compareToKeyAttribute($create_attrs, $old_create_attrs)) {
print "\t-> Device '$device' is configured differently.\n";
if ($deletions) {
print "\t -> Closing and re-opening with new attributes.\n";
closeDevice($handler, $device, $deletions);
openDevice($handler, $device, $create_attrs);
$changes += 2;
my $rc = readWorkingConfig($deletions);
exit $rc if ($rc);
} else {
print "\t -> Use -force to re-open device with new attributes. ".
"NOTE: This will disrupt all initiators using this device.\n";
}
}
if (scalar keys %{$attributes}) {
$changes += setDeviceAttributes($device, $attributes, FALSE);
}
next;
}
openDevice($handler, $device, $create_attrs);
$changes++;
if (scalar keys %{$attributes}) {
$changes += setDeviceAttributes($device, $attributes, $deletions);
}
}
}
my %_attributes;
foreach my $item (keys %{$$handlers{$handler}}) {
next if ($item eq 'DEVICE');
$_attributes{$item} = $$handlers{$handler}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if (scalar keys %{$attributes}) {
$changes += setHandlerAttributes($handler, $attributes, $deletions);
}
}
return $changes;
}
sub applyConfigAssignments {
my $config = shift;
my $deletions = shift;
my $only_del = shift;
my $changes = 0;
my $errorString;
my $assignments = $CURRENT{'assign'};
foreach my $driver (keys %{$assignments}) {
foreach my $target (keys %{$$assignments{$driver}}) {
my $luns = $$assignments{$driver}->{$target}->{'LUN'};
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($driver, $target, $lun);
$changes++;
} elsif ($driver ne 'copy_manager') {
print "\t-> Device '$device' at LUN '$lun' is not in configuration ".
"for driver/target '$driver/$target'. ".
"Use -force to remove it.\n";
}
} else {
my $c_attrs = configToAttr($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'LUN'}->{$lun}->{$device});
my $o_attrs;
($o_attrs, $errorString) = $SCST->lunAttributes($driver, $target, $lun);
condExit($errorString);
my $possible;
($possible, $errorString) = $SCST->lunCreateAttributes($driver, $target);
condExit($errorString);
filterCreateAttributes($possible, $c_attrs, FALSE);
if (compareToKeyAttribute($c_attrs, $o_attrs)) {
print "\t-> Assigned device '$device' in target '$target' at ".
"LUN '$lun' is configured differently.\n";
if ($deletions) {
print "\t -> Re-assigning device with new attributes.\n";
removeLun($driver, $target, $lun);
addLun($driver, $target, $device, $lun, $c_attrs);
$changes += 2;
} else {
print "\t -> Use -force to re-assign device with new attributes. ".
"NOTE: This will disrupt all initiators using this device.\n";
}
}
}
}
foreach my $group (keys %{$$assignments{$driver}->{$target}->{'GROUP'}}) {
my $luns = $$assignments{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'};
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($driver, $target, $lun, $group);
$changes++;
} 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";
}
} else {
my $c_attrs = configToAttr($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'LUN'}->{$lun}->{$device});
my $o_attrs;
($o_attrs, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
condExit($errorString);
my $possible;
($possible, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group);
condExit($errorString);
filterCreateAttributes($possible, $c_attrs, FALSE);
if (compareToKeyAttribute($c_attrs, $o_attrs)) {
print "\t-> Assigned device '$device' in group '$group' ".
"at LUN '$lun' is configured differently.\n";
if ($deletions) {
print "\t -> Re-assigning device with new attributes.\n";
removeLun($driver, $target, $lun, $group);
addLun($driver, $target, $device, $lun, $c_attrs, $group);
$changes += 2;
} else {
print "\t -> Use -force to re-assign device with new attributes. ".
"NOTE: This will disrupt all initiators using this device.\n";
}
}
}
}
if (!defined($$config{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group})) {
if ($deletions) {
removeGroup($driver, $target,
$group, TRUE);
$changes++;
} else {
print "\t-> Group '$group' is not in configuration. Use -force to remove.\n";
}
next;
}
}
}
}
return $changes if ($only_del);
$assignments = $$config{'TARGET_DRIVER'};
foreach my $driver (sort keys %{$assignments}) {
if (!defined($CURRENT{'assign'}->{$driver})) {
condExit("Target driver '$driver' is not loaded or available.");
}
my %_attributes;
foreach my $item (keys %{$$assignments{$driver}}) {
if ($item eq 'TARGET') {
$changes += applyTargetAssignments($driver, $$assignments{$driver}->{$item},
$deletions);
} elsif ($item ne 'enabled') {
# Enabling a driver happens in applyConfigEnableDrivers()
$_attributes{$item} = $$assignments{$driver}->{$item};
}
}
my $attributes = configToAttr(\%_attributes);
if (scalar keys %{$attributes}) {
$changes += setDriverAttributes($driver, $attributes, $deletions);
}
}
return $changes;
}
sub applyConfigEnableDrivers {
my $config = shift;
my $deletions = shift;
my $changes = 0;
my $errorString;
my $assignments = $$config{'TARGET_DRIVER'};
foreach my $driver (sort keys %{$assignments}) {
my %_attributes;
foreach my $item (keys %{$$assignments{$driver}}) {
if ($item eq 'enabled') {
$_attributes{$item} = $$assignments{$driver}->{$item};
}
}
my $attributes = configToAttr(\%_attributes);
my $d_attributes;
($d_attributes, $errorString) = $SCST->driverAttributes($driver);
if (defined($$d_attributes{'enabled'}) &&
($$d_attributes{'enabled'}->{'value'} != $$attributes{'enabled'})) {
setDriverAttribute($driver, 'enabled', $$attributes{'enabled'});
$changes++;
}
}
return $changes;
}
sub applyConfigAlua {
my $config = shift;
my $deletions = shift;
my $alua_attr = $$config{'ALUA'};
my %_attributes;
foreach my $item (keys %{$alua_attr}) {
$_attributes{$item} = $alua_attr->{$item};
}
my $attributes = configToAttr(\%_attributes);
return setAluaAttributes($attributes);
}
sub applyConfigDeviceGroups {
my $config = shift;
my $deletions = shift;
my $changes = 0;
my $dgroups = $CURRENT{'dgroups'};
foreach my $dgroup (keys %{$dgroups}) {
if (!defined($$config{'DEVICE_GROUP'}->{$dgroup})) {
if ($deletions) {
removeDeviceGroup($dgroup, TRUE);
$changes++;
} else {
print "\t-> Device Group '$dgroup' is not in configuration. Use -force to remove.\n";
}
} else {
my $devices = $CURRENT{'dgroups'}->{$dgroup}->{'devices'};
foreach my $device (@{$devices}) {
if (!defined($$config{'DEVICE_GROUP'}->{$dgroup}->{'DEVICE'}->{$device})) {
if ($deletions) {
removeDeviceGroupDevice($dgroup, $device);
$changes++;
} else {
print "\t-> Device '$device' within device group '$dgroup' is not in configuration. Use -force to remove.\n";
}
}
}
foreach my $tgroup (keys %{$$dgroups{$dgroup}->{'tgroups'}}) {
if (!defined($$config{'DEVICE_GROUP'}->{$dgroup}->{'TARGET_GROUP'}->{$tgroup})) {
if ($deletions) {
removeTargetGroup($dgroup, $tgroup, TRUE);
$changes++;
} else {
print "\t-> Target Group '$dgroup/$tgroup' is not in configuration. Use -force to remove.\n";
}
} else {
my $tgts = $$dgroups{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'};
foreach my $tgt (@{$tgts}) {
if (!defined($$config{'DEVICE_GROUP'}->{$dgroup}->{'TARGET_GROUP'}->{$tgroup}->{'TARGET'}->{$tgt})) {
if ($deletions) {
removeTargetGroupTarget($dgroup, $tgroup, $tgt);
$changes++;
} else {
print "\t-> Target '$dgroup/$tgroup/$tgt' is not in configuration. Use -force to remove.\n";
}
}
}
}
}
}
}
$dgroups = $$config{'DEVICE_GROUP'};
foreach my $dgroup (sort keys %{$dgroups}) {
if (!defined($CURRENT{'dgroups'}->{$dgroup})) {
addDeviceGroup($dgroup);
$changes++;
}
my $devices = $$dgroups{$dgroup}->{'DEVICE'};
foreach my $device (sort keys %{$devices}) {
if (!deviceGroupHasDevice($dgroup, $device)) {
addDeviceGroupDevice($dgroup, $device);
$changes++;
}
}
my $tgroups = $$dgroups{$dgroup}->{'TARGET_GROUP'};
foreach my $tgroup (sort keys %{$tgroups}) {
if (!defined($CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup})) {
addTargetGroup($dgroup, $tgroup);
$changes++;
}
my $tgts = $$tgroups{$tgroup}->{'TARGET'};
foreach my $tgt (keys %{$tgts}) {
if (!arrayHasValue($CURRENT{'dgroups'}->{$dgroup}->{'tgroups'}->{$tgroup}->{'targets'}, $tgt)) {
addTargetGroupTarget($dgroup, $tgroup, $tgt);
$changes++;
}
my %_attributes;
foreach my $item (keys %{$$tgts{$tgt}}) {
$_attributes{$item} = $$tgts{$tgt}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if (scalar keys %{$attributes}) {
$changes += setTargetGroupTargetAttributes($dgroup, $tgroup, $tgt, $attributes);
}
}
my %_attributes;
foreach my $item (keys %{$$tgroups{$tgroup}}) {
next if ($item eq 'TARGET');
$_attributes{$item} = $$tgroups{$tgroup}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if (scalar keys %{$attributes}) {
$changes += setTargetGroupAttributes($dgroup, $tgroup, $attributes);
}
}
my %_attributes;
foreach my $item (keys %{$$dgroups{$dgroup}}) {
next if ($item eq 'TARGET_GROUP');
next if ($item eq 'DEVICE');
$_attributes{$item} = $$dgroups{$dgroup}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if (scalar keys %{$attributes}) {
$changes += setDeviceGroupAttributes($dgroup, $attributes);
}
}
return $changes;
}
sub applyInitiatorAssignments {
my $driver = shift;
my $target = shift;
my $groups = shift;
my $deletions = shift;
my %configured;
my %running;
my $changes = 0;
my $current = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
foreach my $group (keys %{$current}) {
my $initiators = $$current{$group}->{'INITIATORS'};
foreach my $init (@{$initiators}) {
$running{$init} = $group;
}
}
foreach my $group (keys %{$groups}) {
my $initiators = $$groups{$group}->{'INITIATOR'};
foreach my $init (keys %{$initiators}) {
$configured{$init} = $group;
}
}
foreach my $init (keys %running) {
if (!defined($configured{$init})) {
my $group = $running{$init};
if ($deletions) {
removeInitiator($driver, $target, $group, $init);
$changes++;
} else {
print "\t-> Initiator '$init' is not in configuration ".
"for driver/target/group '$driver/$target/$group'. ".
"Use -force to remove it.\n";
}
} else {
if ($configured{$init} ne $running{$init}) {
if ($deletions) {
moveInitiator($driver, $target, $running{$init}, $init, $configured{$init});
$changes++;
} else {
print "\t-> Initiator '$init' is moving to group '".
$configured{$init}."' from group '".$running{$init}."'. ".
"Use -force to move it.\n";
}
}
}
}
foreach my $init (keys %configured) {
if (!defined($running{$init})) {
addInitiator($driver, $target, $configured{$init}, $init);
$changes++;
}
}
return $changes;
}
sub applyTargetAssignments {
my $driver = shift;
my $targets = shift;
my $deletions = shift;
my $changes = 0;
foreach my $target (keys %{$CURRENT{'assign'}->{$driver}}) {
if (!defined($$targets{$target})) {
my $isVirtual = ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL);
if ($deletions && $isVirtual) {
my $rc = removeVirtualTarget($driver, $target);
condExit($SCST->errorString($rc));
$changes++;
} else {
print "\t-> Virtual target '$target' for driver '$driver' is not in configuration. ".
"Use -force to remove it.\n";
}
}
}
my $possible;
my ($is_virtual, $errorString) = $SCST->driverIsVirtualCapable($driver);
if ($is_virtual) {
($possible, $errorString) = $SCST->targetCreateAttributes($driver);
}
foreach my $target (sort keys %{$targets}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target})) {
if (!$is_virtual) {
condExit("Target '$target' for driver '$driver' does not exist.");
} else {
my %_attributes;
foreach my $item (keys %{$$targets{$target}}) {
next if ($item eq 'GROUP');
next if ($item eq 'LUN');
$_attributes{$item} = $$targets{$target}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if (defined($$attributes{'HW_TARGET'})) {
condExit("Hardware target '$target' for driver '$driver' does not exist.");
}
filterCreateAttributes($possible, $attributes, FALSE);
my $rc = addVirtualTarget($driver, $target, $attributes);
condExit($SCST->errorString($rc));
$changes++ if (!$rc);
}
}
# Apply attribute changes first in case we want a different address method applied
my %_attributes;
foreach my $item (keys %{$$targets{$target}}) {
# Handle enabled attribute last
next if (($item eq 'GROUP') || ($item eq 'LUN') || ($item eq 'enabled'));
$_attributes{$item} = $$targets{$target}->{$item};
}
my $attributes = configToAttr(\%_attributes);
if ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL) {
filterCreateAttributes($possible, $attributes, TRUE);
}
$changes += setTargetAttributes($driver, $target, $attributes, $deletions);
foreach my $item (keys %{$$targets{$target}}) {
if ($item eq 'GROUP') {
$changes += applyGroupAssignments($driver, $target, $$targets{$target}->{$item});
$changes += applyInitiatorAssignments($driver, $target, $$targets{$target}->{$item}, $deletions);
} elsif ($item eq 'LUN') {
$changes += applyLunAssignments($driver, $target, undef, $$targets{$target}->{$item});
}
}
}
return $changes;
}
sub applyConfigEnableTargets {
my $config = shift;
my $deletions = shift;
my $changes = 0;
my $errorString;
my $assignments = $$config{'TARGET_DRIVER'};
foreach my $driver (sort keys %{$assignments}) {
foreach my $driver_item (keys %{$$assignments{$driver}}) {
next if ($driver_item ne 'TARGET');
my $targets = $$assignments{$driver}->{$driver_item};
foreach my $target (sort keys %{$targets}) {
my %_attributes = ();
foreach my $target_item (keys %{$$targets{$target}}) {
if ($target_item eq 'enabled') {
$_attributes{$target_item} = $$targets{$target}->{$target_item};
}
}
my $attributes = configToAttr(\%_attributes);
my $t_attributes;
($t_attributes, $errorString) = $SCST->targetAttributes($driver, $target);
if (defined($$t_attributes{'enabled'}) &&
($$t_attributes{'enabled'}->{'value'} != $$attributes{'enabled'})) {
setTargetAttribute($driver, $target, 'enabled', $$attributes{'enabled'});
$changes++;
}
}
}
}
return $changes;
}
sub applyGroupAssignments {
my $driver = shift;
my $target = shift;
my $groups = shift;
my $changes = 0;
foreach my $group (sort keys %{$groups}) {
if (!defined($CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group})) {
addGroup($driver, $target, $group);
$changes++;
}
my %_attributes;
foreach my $item (keys %{$$groups{$group}}) {
if ($item eq 'LUN') {
$changes += applyLunAssignments($driver, $target, $group,
$$groups{$group}->{$item});
} elsif ($item eq 'INITIATOR') {
next;
} else {
$_attributes{$item} = $$groups{$group}->{$item};
}
}
my $attributes = configToAttr(\%_attributes);
$changes += setGroupAttributes(undef, $driver, $target, $group, $attributes);
}
return $changes;
}
sub applyLunAssignments {
my $driver = shift;
my $target = shift;
my $group = shift;
my $luns = shift;
my $c_luns;
my $changes = 0;
if (defined($group)) {
$c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'}->{$group}->{'LUN'};
} else {
$c_luns = $CURRENT{'assign'}->{$driver}->{$target}->{'LUN'};
}
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($driver, $target, $device, $lun, $attributes, $group);
$changes++;
}
}
}
return $changes;
}
sub filterCreateAttributes {
my $creates = shift;
my $attrs = shift;
my $keep = shift;
foreach my $attribute (keys %{$attrs}) {
my $good = defined($$creates{$attribute}) ? TRUE : FALSE;
if (($keep && $good) || (!$keep && !$good)) {
delete $$attrs{$attribute};
}
}
}
sub compareToKeyAttribute {
my $first = shift;
my $second = shift;
foreach my $attr (keys %{$first}) {
if (defined($$second{$attr}->{'keys'})) {
next if (!defined($$second{$attr}->{'keys'}->{'0'}->{'value'}) && ($$first{$attr} == 0));
return TRUE if ($$first{$attr} ne $$second{$attr}->{'keys'}->{'0'}->{'value'});
} else {
next if (!defined($$second{$attr}->{'value'}) && ($$first{$attr} == 0));
return TRUE if ($$first{$attr} ne $$second{$attr}->{'value'});
}
}
foreach my $attr (keys %{$second}) {
if (defined($$second{$attr}->{'keys'}) && !defined($$first{$attr})) {
return TRUE;
}
}
return FALSE;
}
sub clearActifioConfig{
my $dgroups = $CURRENT{'dgroups'};
my $assignments = $CURRENT{'assign'};
print "-> Clearing running configuration, but leaving targets enabled.\n";
print "\t-> Configuration cleared.\n";
foreach my $dgroup (sort keys %{$dgroups}) {
foreach my $tgroup (sort keys %{$$dgroups{$dgroup}->{'tgroups'}}) {
removeTargetGroup($dgroup, $tgroup, TRUE);
}
foreach my $device (@{$$dgroups{$dgroup}->{'devices'}}) {
removeDeviceGroupDevice($dgroup, $device, TRUE);
}
removeDeviceGroup($dgroup, TRUE);
}
foreach my $driver (sort keys %{$assignments}) {
foreach my $target (sort keys %{$$assignments{$driver}}) {
foreach my $group (sort keys %{$$assignments{$driver}->{$target}->{'GROUP'}}) {
clearInitiators($driver, $target, $group);
clearLuns($driver, $target, $group);
removeGroup($driver, $target, $group, TRUE);
}
clearLuns($driver, $target);
removeTargetDynamicAttributes($driver, $target);
if ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL) {
my $rc = removeVirtualTarget($driver, $target);
issueWarning($SCST->errorString($rc)) if ($rc);
}
}
clearDriverDynamicAttributes($driver);
}
my $handlers = $CURRENT{'handler'};
foreach my $handler (sort keys %{$handlers}) {
foreach my $device (@{$$handlers{$handler}}) {
my ($attributes, $errorString) = $SCST->deviceAttributes($device);
closeDevice($handler, $device, TRUE);
}
}
# Todo - check return code
my ($drivers, $errorString) = $SCST->drivers();
foreach my $driver (@{$drivers}) {
my ($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
# disableTarget($driver, $target);
}
# disableDriver($driver);
}
print "\t-> Configuration cleared.\n";
return FALSE
}
sub clearConfiguration {
my $dgroups = $CURRENT{'dgroups'};
my $assignments = $CURRENT{'assign'};
my $errorString;
print "-> Clearing running configuration.\n";
foreach my $dgroup (sort keys %{$dgroups}) {
foreach my $tgroup (sort keys %{$$dgroups{$dgroup}->{'tgroups'}}) {
removeTargetGroup($dgroup, $tgroup, TRUE);
}
foreach my $device (@{$$dgroups{$dgroup}->{'devices'}}) {
removeDeviceGroupDevice($dgroup, $device, TRUE);
}
removeDeviceGroup($dgroup, TRUE);
}
foreach my $driver (sort keys %{$assignments}) {
foreach my $target (sort keys %{$$assignments{$driver}}) {
foreach my $group (sort keys %{$$assignments{$driver}->{$target}->{'GROUP'}}) {
clearInitiators($driver, $target, $group);
clearLuns($driver, $target, $group);
removeGroup($driver, $target, $group, TRUE);
}
clearLuns($driver, $target);
removeTargetDynamicAttributes($driver, $target);
if ($SCST->targetType($driver, $target) == $SCST::SCST::TGT_TYPE_VIRTUAL) {
my $rc = removeVirtualTarget($driver, $target);
issueWarning($SCST->errorString($rc)) if ($rc);
}
}
clearDriverDynamicAttributes($driver);
}
my $handlers = $CURRENT{'handler'};
foreach my $handler (sort keys %{$handlers}) {
foreach my $device (@{$$handlers{$handler}}) {
my $attributes;
($attributes, $errorString) = $SCST->deviceAttributes($device);
closeDevice($handler, $device, TRUE);
}
}
# Todo - check return code
my $drivers;
($drivers, $errorString) = $SCST->drivers();
foreach my $driver (@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
disableTarget($driver, $target);
}
disableDriver($driver);
}
print "\t-> Configuration cleared.\n";
return FALSE;
}
sub addVirtualTarget {
my $driver = shift;
my $target = shift;
my $attributes = shift;
my $errorString;
my $targets;
# Enable all hardware targets before creating virtual ones
($targets, $errorString) = $SCST->targets($driver);
foreach my $_target (@{$targets}) {
my $attributes;
($attributes, $errorString) = $SCST->targetAttributes($driver, $_target);
if (defined($$attributes{'hw_target'}) &&
!$$attributes{'enabled'}->{'value'}) {
enableTarget($driver, $_target);
}
}
print "\t-> Creating target '$target' for driver '$driver': ";
my $rc = $SCST->addVirtualTarget($driver, $target, $attributes);
print "done.\n";
return $rc;
}
sub removeVirtualTarget {
my $driver = shift;
my $target = shift;
print "\t-> Removing virtual target '$target' from driver '$driver': ";
my $rc = $SCST->removeVirtualTarget($driver, $target);
print "done.\n";
return $rc;
}
####################################################################
sub listHandlers {
my $handler = shift;
return listHandler($handler) if ($handler);
my ($handlers, $errorString) = $SCST->handlers();
my $l_handler = 0;
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";
}
return FALSE;
}
sub listHandler {
my $handler = shift;
my %toprint;
my $got_handler = valid($handler);
my ($handlers, $errorString) = $SCST->handlers();
my $l_device = 0;
my $l_handler = 0;
foreach my $_handler (@{$handlers}) {
$handler = $_handler if (!$got_handler);
if ($handler eq $_handler) {
$toprint{$handler}++;
$l_handler = length($handler) if ($l_handler < length($handler));
my $devices;
($devices, $errorString) = $SCST->devicesByHandler($handler);
if ($#{$devices} == -1) {
push @{$devices}, '-';
}
foreach my $device (@{$devices}) {
$l_device = length($device) if ($l_device < length($device));
}
}
}
if (scalar keys %toprint) {
printf("\t%-*s %-*s\n", $l_handler, 'Handler', $l_device, 'Device');
print "\t";
for (my $x = 0; $x < ($l_handler + $l_device + 5); $x++) {
print "-";
};
print "\n";
foreach my $handler (sort keys %toprint) {
my $devices;
my $first = TRUE;
($devices, $errorString) = $SCST->devicesByHandler($handler);
if ($#{$devices} == -1) {
push @{$devices}, '-';
}
foreach my $device (sort @{$devices}) {
if ($first) {
printf("\t%-*s %-*s\n", $l_handler, $handler, $l_device, $device);
$first = FALSE;
} else {
printf("\t%-*s %-*s\n", $l_handler, '', $l_device, $device);
}
}
}
} else {
print "No such handler '$handler' found.\n";
}
return FALSE;
}
sub listDevices {
my $device = shift;
my $nonkey = shift;
return listDevice($device, $nonkey) if (valid($device));
return listHandler();
}
sub listDevice {
my $device = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->deviceAttributes($device);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such device '$device' exists.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
sub listDeviceGroups {
my $group = shift;
my $showall = shift;
return listDeviceGroup($group) if (valid($group));
my ($groups, $errorString) = $SCST->deviceGroups();
my $l_group = 0;
foreach my $group (@{$groups}) {
$l_group = length($group) if ($l_group < length($group));
}
$l_group = 12 if ($l_group < 12);
print "\tDevice Group\n";
print "\t";
for (my $x = 0; $x < $l_group; $x++) {
print "-";
}
print "\n";
foreach my $group (@{$groups}) {
print "\t$group\n\n";
listTargetGroups($group, undef, TRUE) if ($showall);
}
return FALSE;
}
sub listDeviceGroup {
my $group = shift;
my $errorString;
my $devices;
my $l_device = 0;
($devices, $errorString) = $SCST->deviceGroupDevices($group);
foreach my $device (@{$devices}) {
$l_device = length($device) if ($l_device < length($device));
}
$l_device = 7 if ($l_device < 6);
print "\tDevices\n";
print "\t";
for (my $x = 0; $x < $l_device; $x++) {
print "-";
}
print "\n";
foreach my $device (@{$devices}) {
print "\t$device\n";
}
my $tgroups;
my $l_tgroup = 0;
($tgroups, $errorString) = $SCST->targetGroups($group);
foreach my $tgroup (@{$tgroups}) {
$l_tgroup = length($tgroup) if ($l_tgroup < length($tgroup));
}
$l_tgroup = 12 if ($l_tgroup < 12);
print "\n\tTarget Groups\n";
print "\t";
for (my $x = 0; $x < $l_tgroup; $x++) {
print "-";
}
print "\n";
foreach my $tgroup (@{$tgroups}) {
print "\t$tgroup\n";
}
return FALSE;
}
sub listTargetGroups {
my $group = shift;
my $tgroup = shift;
my $indent = shift;
return listDeviceGroups(undef, TRUE) if (!valid($group));
return listTargetGroup($group, $tgroup) if (valid($tgroup));
my ($tgroups, $errorString) = $SCST->targetGroups($group);
my $l_tgroup = 0;
foreach my $tgroup (@{$tgroups}) {
$l_tgroup = length($tgroup) if ($l_tgroup < length($tgroup));
}
$l_tgroup = 12 if ($l_tgroup < 12);
print "\n";
print "\t" if ($indent);
print "\tTarget Groups\n";
print "\t";
print "\t" if ($indent);
for (my $x = 0; $x < $l_tgroup; $x++) {
print "-";
}
print "\n";
foreach my $tgroup (@{$tgroups}) {
print "\t" if ($indent);
print "\t$tgroup\n";
}
return FALSE;
}
sub listTargetGroup {
my $group = shift;
my $tgroup = shift;
my ($targets, $errorString) = $SCST->targetGroupTargets($group, $tgroup);
my $l_tgt = 0;
foreach my $tgt (@{$targets}) {
$l_tgt = length($tgt) if ($l_tgt < length($tgt));
}
$l_tgt = 7 if ($l_tgt < 7);
print "\tTargets\n";
print "\t";
for (my $x = 0; $x < $l_tgt; $x++) {
print "-";
}
print "\n";
foreach my $tgt (@{$targets}) {
print "\t$tgt\n";
}
return FALSE;
}
sub listDeviceGroupDevices {
my $group = shift;
my $device = shift;
return listDevice($device) if ($device);
my ($devices, $errorString) = $SCST->deviceGroupDevices($group);
my $l_device = 0;
foreach my $device (@{$devices}) {
$l_device = length($device) if ($l_device < length($device));
}
$l_device = 7 if ($l_device < 7);
print "\tDevices\n";
print "\t";
for (my $x = 0; $x < $l_device; $x++) {
print "-";
}
print "\n";
foreach my $device (@{$devices}) {
print "\t$device\n";
}
return FALSE;
}
sub listDrivers {
my $driver = shift;
return listTargets($driver, undef) if (valid($driver));
my ($drivers, $errorString) = $SCST->drivers();
my $l_driver = 0;
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";
}
return FALSE;
}
sub listTargets {
my $driver = shift;
my $target = shift;
my %toprint;
return listGroups($driver, $target, undef) if (valid($target, $driver));
my $got_driver = valid($driver);
my ($drivers, $errorString) = $SCST->drivers();
my $l_driver = 0;
my $l_target = 0;
foreach my $_driver (@{$drivers}) {
$driver = $_driver if (!$got_driver);
if ($driver eq $_driver) {
$toprint{$driver}++;
$l_driver = length($driver) if ($l_driver < length($driver));
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
$l_target = length($target) if ($l_target < length($target));
}
}
}
if (scalar(keys %toprint)) {
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 (sort keys %toprint) {
my $targets;
($targets, $errorString) = $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);
}
}
}
} else {
print "No such driver '$driver' exists.\n";
}
return FALSE;
}
sub listSessions {
my ($drivers, $errorString) = $SCST->drivers();
foreach my $driver (@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
my $had_sessions = FALSE;
my $sessions;
print "Driver/Target: $driver/$target\n\n";
($sessions, $errorString) = $SCST->sessions($driver, $target);
foreach my $session (keys %{$sessions}) {
print "\tSession: $session\n\n";
my %attributes = ( );
foreach my $attr (keys %{$$sessions{$session}}) {
if ($attr eq 'luns') {
foreach my $lun (keys %{$$sessions{$session}->{'luns'}}) {
$attributes{"LUN $lun"}->{'value'} =
$$sessions{$session}->{'luns'}->{$lun};
}
} else {
$attributes{$attr}->{'value'} = $$sessions{$session}->{$attr}->{'value'};
}
}
listAttributes(\%attributes, TRUE);
print "\n";
$had_sessions = TRUE;
}
if (!$had_sessions) {
print "\t(no sessions)\n\n";
}
}
}
return FALSE;
}
sub listGroup {
my $driver = shift;
my $target = shift;
my $group = shift;
my $luns = shift;
my $initiators = shift;
my $errorString;
($luns, $errorString) = $SCST->luns($driver, $target, $group) if (!$luns);
if (!valid($initiators) && valid($group)) {
($initiators, $errorString) = $SCST->initiators($driver, $target, $group);
return TRUE if issueWarning($errorString);
}
if ((keys %{$luns}) || ($#{$initiators} > -1)) {
my $l_device = 0;
foreach my $lun (keys %{$luns}) {
$l_device = length($$luns{$lun}) if (length($$luns{$lun}) > $l_device);
}
my $l_initiator = 0;
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";
}
if (valid($group)) {
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 {
if (valid($group)) {
print "Group '$group' has no associated LUNs or initiators.\n";
} else {
print "Driver/target '$driver/$target' has no associated LUNs.\n";
}
}
return FALSE;
}
sub listGroups {
my $driver = shift;
my $target = shift;
my $group = shift;
my $found = FALSE;
if (valid($group, $driver, $target)) {
return listGroup($driver, $target, $group);
}
my $got_group = $group;
my $got_target = $target;
my $got_driver = $driver;
my ($drivers, $errorString) = $SCST->drivers();
foreach my $_driver (@{$drivers}) {
$driver = $_driver if (!$got_driver);
if ($driver eq $_driver) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $_target (@{$targets}) {
$target = $_target if (!$got_target);
if ($target eq $_target) {
$found++;
print "Driver: $driver\n";
print "Target: $target\n\n";
listGroup($driver, $target, undef);
print "\n";
my $groups;
($groups, $errorString) = $SCST->groups($driver, $target);
foreach my $_group (@{$groups}) {
$group = $_group if (!$got_group);
if ($group eq $_group) {
print "Group: $group\n\n";
listGroup($driver, $target, $group);
print "\n\n";
}
}
}
}
}
}
if (!$found) {
if ($got_driver && $got_target) {
print "Driver/target '$driver/$target' not found\n";
} elsif (!$got_target) {
print "Driver '$driver' not found.\n";
} else {
print "Target '$target' not found.\n";
}
}
return FALSE;
}
sub listExported {
my $device = shift;
my $attributes = shift;
my $exported = $$attributes{'exported'}->{'value'};
my $l_driver = length('Driver');
my $l_target = length('Target');
my $l_group = length('Group');
my $fmt = "\t%-*s %-*s %-*s %-4s\n";
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($fmt, $l_driver, 'Driver', $l_target, 'Target',
$l_group, 'Group', 'Lun');
printf($fmt, $l_driver, join("", "-" x $l_driver),
$l_target, join("", "-" x $l_target),
$l_group, join("", "-" x $l_group), join("", "-" x 4));
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($fmt, $l_driver, $driver, $l_target,
$target, $l_group, $group, $lun);
}
}
}
}
sub listAttributes {
my $attributes = shift;
my $nonkey = shift;
my $l_attr = 9;
my $l_value = 5;
foreach my $attribute (keys %{$attributes}) {
if (defined($$attributes{$attribute}->{'keys'})) {
$l_attr = length($attribute) if ($l_attr < length($attribute));
foreach my $key (keys %{$$attributes{$attribute}->{'keys'}}) {
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
$l_value = length($value) if ($l_value < length($value));
}
} elsif ($nonkey) {
$l_attr = length($attribute) if ($l_attr < length($attribute));
my $value = $$attributes{$attribute}->{'value'};
if (($attribute eq 'trace_level') && $value) {
foreach my $level (split(/\|/, $value)) {
$level =~ s/^\s+//; $level =~ s/\s+$//;
$l_value = length($level) if ($l_value < length($level));
}
next;
}
$l_value = length($value) if ($l_value < length($value));
}
}
printf("\t%-*s %-*s %-*s %-*s\n", $l_attr, 'Attribute',
$l_value, 'Value', 9, 'Writable', 3, 'KEY');
print "\t";
for (my $x = 0; $x < ($l_attr + $l_value + 27); $x++) {
print "-";
};
print "\n";
my $found = FALSE;
foreach my $attribute (sort keys %{$attributes}) {
my $first = TRUE;
if (defined($$attributes{$attribute}->{'keys'})) {
foreach my $key (sort keys %{$$attributes{$attribute}->{'keys'}}) {
my $value = $$attributes{$attribute}->{'keys'}->{$key}->{'value'};
my $static = ($$attributes{$attribute}->{'static'}) ? 'No' : 'Yes';
$value = '<not set>' if ($value eq '');
if ($first) {
printf("\t%-*s %-*s %-*s %-*s\n",
$l_attr, $attribute, $l_value, $value, 9, $static, 3, 'Yes');
$first = FALSE;
} else {
printf("\t%-*s %-*s %-*s %-*s\n",
$l_attr, '', $l_value, $value, 9, $static, 3, 'Yes');
}
$found++;
}
} elsif ($nonkey) {
my $value = $$attributes{$attribute}->{'value'};
my $static = ($$attributes{$attribute}->{'static'}) ? 'No' : 'Yes';
if (($attribute eq 'trace_level') && $value) {
foreach my $level (split(/\|/, $value)) {
$level =~ s/^\s+//; $level =~ s/\s+$//;
if ($first) {
printf("\t%-*s %-*s %-*s %-*s\n",
$l_attr, $attribute, $l_value, $level, 9, $static, 3, 'No');
$first = FALSE;
} else {
printf("\t%-*s %-*s %-*s %-*s\n",
$l_attr, '', $l_value, $level, 9, $static, 3, 'No');
}
$found++;
}
next;
}
next if ((ref($value) eq 'HASH') || (ref($value) eq 'ARRAY'));
$value = '<n/a>' if (!defined($value));
$value = '<not set>' if ($value eq '');
printf("\t%-*s %-*s %-*s %-*s\n",
$l_attr, $attribute, $l_value, $value, 9, $static, 3, 'No');
$found++;
}
}
if (!$found) {
print "\t(none)\n";
}
if ($nonkey && defined($$attributes{'trace_level'})) {
my $found = FALSE;
print "\n\tPossible trace levels:\n".
"\t (use trace_level=\"add <level>\", none, all or default to set):\n";
my $count = 0;
foreach my $entry (@{$$attributes{'trace_level'}->{'set'}}) {
print "\t\t" if (!$count);
print "$entry, ";
$count++;
if ($count == 5) {
print "\n";
$count = 0;
}
}
print "\n";
}
return FALSE;
}
sub listScstAttributes {
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->scstAttributes();
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "FATAL: Unable to get a list of SCST attributes! Please make sure SCST is loaded.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
sub listHandlerAttributes {
my $handler = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->handlerAttributes($handler);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such handler '$handler' found.\n";
return;
}
my $rc = listAttributes($attributes, $nonkey);
return $rc if $rc;
($attributes, $errorString) = $SCST->deviceCreateAttributes($handler);
return TRUE if issueWarning($errorString);
return TRUE if (!scalar keys %{$attributes});
print "\n\tDevice CREATE attributes available\n";
print "\t----------------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
return FALSE;
}
sub listDriverAttributes {
my $driver = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->driverAttributes($driver);
return TRUE if issueWarning($errorString);
my $rc = listAttributes($attributes, $nonkey);
return $rc if ($rc);
if ($SCST->driverIsVirtualCapable($driver)) {
($attributes, $errorString) = $SCST->driverDynamicAttributes($driver);
return TRUE if issueWarning($errorString);
if (scalar keys %{$attributes}) {
print "\n\tDynamic attributes available\n";
print "\t----------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
}
my $attributes;
($attributes, $errorString) = $SCST->targetCreateAttributes($driver);
return TRUE if issueWarning($errorString);
return TRUE if (!scalar keys %{$attributes});
print "\n\tTarget CREATE attributes available:\n";
print "\t-----------------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
}
return FALSE;
}
sub listTargetAttributes {
my $driver = shift;
my $target = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such driver/target '$driver/$target' found.\n";
return;
}
my $rc = listAttributes($attributes, $nonkey);
return $rc if $rc;
if ($SCST->driverIsVirtualCapable($driver)) {
($attributes, $errorString) = $SCST->targetDynamicAttributes($driver);
return TRUE if issueWarning($errorString);
if (scalar keys %{$attributes}) {
print "\n\tDynamic attributes available\n";
print "\t----------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
}
}
($attributes, $errorString) = $SCST->lunCreateAttributes($driver, $target);
return TRUE if issueWarning($errorString);
return TRUE if (!scalar keys %{$attributes});
print "\n\tLUN CREATE attributes available\n";
print "\t-------------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
return FALSE;
}
sub listGroupAttributes {
my $driver = shift;
my $target = shift;
my $group = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such driver/target/group '$driver/$target/$group' found.\n";
return;
}
my $rc = listAttributes($attributes, $nonkey);
return $rc if $rc;
($attributes, $errorString) = $SCST->lunCreateAttributes($driver, $target, $group);
return TRUE if issueWarning($errorString);
return TRUE if (!scalar keys %{$attributes});
print "\n\tLUN CREATE attributes available\n";
print "\t-------------------------------\n";
foreach my $attribute (sort keys %{$attributes}) {
print "\t$attribute\n";
}
($attributes, $errorString) = $SCST->initiatorCreateAttributes($driver, $target, $group);
return TRUE if issueWarning($errorString);
return TRUE if (!scalar keys %{$attributes});
print "\n\tInitiator CREATE attributes available\n";
print "\t-------------------------------------\n";
foreach my $attribute (keys %{$attributes}) {
print "\t$attribute\n";
}
return FALSE;
}
sub listLunAttributes {
my $driver = shift;
my $target = shift;
my $group = shift;
my $lun = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
if (valid($group)) {
print "No such driver/target/group/lun '$driver/$target/$group/$lun' found.\n";
} else {
print "No such driver/target/lun '$driver/$target/$lun' found.\n";
}
return;
}
return listAttributes($attributes, $nonkey);
}
sub listInitiatorAttributes {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $initiator);
# As if writing, initiators didn't have attributes. This will
# allow us to support it in the future.
if ($errorString =~ /Not a directory/) {
print "Initiators do not (yet) have attributes.\n";
return;
}
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such driver/target/group/initiator '$driver/$target/$group/$initiator' found.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
sub listDeviceGroupAttributes {
my $group = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->deviceGroupAttributes($group);
return TRUE if issueWarning($errorString);
# Special case - as of writing, device group attributes didn't exist.
if (!scalar(keys %{$attributes})) {
print "No such device group '$group' found or device group as no attributes.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
sub listTargetGroupAttributes {
my $group = shift;
my $tgroup = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->targetGroupAttributes($group, $tgroup);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such device group/target group '$group/$tgroup' found.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
sub listTargetGroupTargetAttributes {
my $group = shift;
my $tgroup = shift;
my $tgt = shift;
my $nonkey = shift;
my ($attributes, $errorString) = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt, TRUE);
return TRUE if issueWarning($errorString);
if (!scalar(keys %{$attributes})) {
print "No such device group/target group/target '$group/$tgroup/$tgt' found.\n";
return;
}
return listAttributes($attributes, $nonkey);
}
####################################################################
sub setScstAttribute {
shift;
shift;
shift;
shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting SCST attribute '$attribute' to value '$value': ";
my $rc = $SCST->setScstAttribute($attribute, $value);
print "done.\n";
return $rc;
}
sub setScstAttributes {
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: SCST lacks the settable attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->scstAttributes();
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, undef, undef, $attributes,
$_attributes, $error, \&setScstAttribute, $showset);
}
sub setDeviceAttribute {
shift;
shift;
shift;
my $device = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting device attribute '$attribute' to value '$value' for device '$device': ";
my $rc = $SCST->setDeviceAttribute($device, $attribute, $value);
print "done.\n";
return $rc;
}
sub setDeviceAttributes {
my $device = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Device '$device' lacks the settable ".
"attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->deviceAttributes($device);
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, undef, $device, $attributes,
$_attributes, $error, \&setDeviceAttribute, $showset);
}
sub setHandlerAttribute {
shift;
shift;
shift;
my $handler = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting handler attribute '$attribute' to value '$value' for handler '$handler': ";
my $rc = $SCST->setHandlerAttribute($handler, $attribute, $value);
print "done.\n";
return $rc;
}
sub setHandlerAttributes {
my $handler = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Handler '$handler' lacks the settable ".
"attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->handlerAttributes($handler);
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, undef, $handler, $attributes,
$_attributes, $error, \&setHandlerAttribute, $showset);
}
sub setGroupAttribute {
shift;
my $driver = shift;
my $target = shift;
my $group = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting group attribute '$attribute' to value '$value' for group '$group': ";
my $rc = $SCST->setGroupAttribute($driver, $target, $group, $attribute, $value);
print "done.\n";
return $rc;
}
sub setGroupAttributes {
shift;
my $driver = shift;
my $target = shift;
my $group = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Driver/target/group '$driver/$target/$group' lacks the settable ".
"attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->groupAttributes($driver, $target, $group);
return TRUE if issueWarning($errorString);
return setAttributes(undef, $driver, $target, $group, $attributes,
$_attributes, $error, \&setGroupAttribute, $showset);
}
sub setLunAttribute {
my $driver = shift;
my $target = shift;
my $lun = shift;
my $group = shift;
my $attribute = shift;
my $value = shift;
if ($group) {
print "\t-> Setting LUN attribute '$attribute' to value '$value' for ".
"driver/target/group/LUN '$driver/$target/$group/$lun': ";
} else {
print "\t-> Setting LUN attribute '$attribute' to value '$value' for ".
"driver/target/LUN '$driver/$target/$lun': ";
}
my $rc = $SCST->setLunAttribute($driver, $target, $lun, $attribute, $value, $group);
print "done.\n";
return $rc;
}
sub setLunAttributes {
my $driver = shift;
my $target = shift;
my $lun = shift;
my $attributes = shift;
my $group = shift;
my $showset = shift;
my $error;
if ($group) {
$error = "\t-> WARNING: Driver/target/group/LUN '$driver/$target/$group/$lun' ".
"lacks the settable attribute '%s', ignoring.\n\n";
} else {
$error = "\t-> WARNING: Driver/target/LUN '$driver/$target/$lun' lacks the settable ".
"attribute '%s', ignoring.\n\n";
}
my ($_attributes, $errorString) = $SCST->lunAttributes($driver, $target, $lun, $group);
return TRUE if issueWarning($errorString);
return setAttributes($driver, $target, $lun, $group, $attributes,
$_attributes, $error, \&setLunAttribute, $showset);
}
sub setInitiatorAttribute {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
my $attribute = shift;
my $value = shift;
print "\t-> 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";
return $rc;
}
sub setInitiatorAttributes {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
my $attributes = shift;
my $showset = shift;
my ($_attributes, $errorString) = $SCST->initiatorAttributes($driver, $target, $group, $initiator);
return TRUE if issueWarning($errorString);
# As if writing, initiators didn't have attributes. This will
# allow us to support it in the future.
if ($errorString =~ /Not a directory/) {
print "Initiators do not (yet) have attributes.\n";
return;
}
my $error = "\t-> WARNING: Driver/target/group/initiator '$driver/$target/$group/$initiator' ".
"lacks the settable attribute '%s', ignoring.\n\n";
return setAttributes($driver, $target, $group, $initiator, $attributes,
$_attributes, $error, \&setInitiatorAttribute, $showset);
}
sub setAluaAttributes {
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: no settable ALUA attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->aluaAttributes();
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, undef, undef, $attributes,
$_attributes, $error, \&setAluaAttribute, $showset);
}
sub setAluaAttribute {
shift;
shift;
shift;
shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting ALUA attribute '$attribute' to value '$value': ";
my $rc = $SCST->setAluaAttribute($attribute, $value);
print "done.\n";
return $rc;
}
sub setDeviceGroupAttributes {
my $group = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Device Group '$group' lacks the settable attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->deviceGroupAttributes($group);
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, undef, $group, $attributes,
$_attributes, $error, \&setDeviceGroupAttribute, $showset);
}
sub setDeviceGroupAttribute {
shift;
shift;
shift;
my $group = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting Device Group attribute '$attribute' to value '$value' for ".
"device group '$group': ";
my $rc = $SCST->setDeviceGroupAttribute($group, $attribute, $value);
print "done.\n";
return $rc;
}
sub setTargetGroupAttributes {
my $group = shift;
my $tgroup = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Target Group '$group/$tgroup' lacks the settable attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->targetGroupAttributes($group, $tgroup);
return TRUE if issueWarning($errorString);
return setAttributes(undef, undef, $group, $tgroup, $attributes,
$_attributes, $error, \&setTargetGroupAttribute, $showset);
}
sub setTargetGroupAttribute {
shift;
shift;
my $group = shift;
my $tgroup = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting Target Group attribute '$attribute' to value '$value' for ".
"target group '$group/$tgroup': ";
my $rc = $SCST->setTargetGroupAttribute($group, $tgroup, $attribute, $value);
print "done.\n";
return $rc;
}
sub setTargetGroupTargetAttributes {
my $group = shift;
my $tgroup = shift;
my $tgt = shift;
my $attributes = shift;
my $showset = shift;
my $error = "\t-> WARNING: Target '$group/$tgroup/$tgt' lacks the settable attribute '%s', ignoring.\n\n";
my ($_attributes, $errorString) = $SCST->targetGroupTargetAttributes($group, $tgroup, $tgt, TRUE);
return TRUE if issueWarning($errorString);
return setAttributes(undef, $group, $tgroup, $tgt, $attributes,
$_attributes, $error, \&setTargetGroupTargetAttribute, $showset);
}
sub setTargetGroupTargetAttribute {
shift;
my $group = shift;
my $tgroup = shift;
my $tgt = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Setting target attribute '$attribute' to value '$value' for ".
"target '$group/$tgroup/$tgt': ";
my $rc = $SCST->setTargetGroupTargetAttribute($group, $tgroup, $tgt, $attribute, $value);
print "done.\n";
return $rc;
}
# Sets any non-dynamic attributes
sub setAttributes {
my $level1 = shift;
my $level2 = shift;
my $level3 = shift;
my $level4 = shift;
my $attributes = shift;
my $_attributes = shift;
my $error = shift;
my $callback = shift;
my $showset = shift;
my %toset;
my $changes = 0;
# build caches for easier matching
foreach my $attribute (keys %{$attributes}) {
if (ref($$attributes{$attribute}) eq 'ARRAY') {
foreach my $value (@{$$attributes{$attribute}}) {
$toset{$attribute}->{$value}++;
}
} else {
$toset{$attribute}->{$$attributes{$attribute}}++;
}
}
my $existing = cacheAttributes($_attributes);
foreach my $attribute (keys %toset) {
foreach my $value (keys %{$toset{$attribute}}) {
if (!defined($$existing{$attribute})) {
print sprintf($error, $attribute);
next;
}
# already set, move on
if (defined($$existing{$attribute}->{$value})) {
print "\t-> Attribute '$attribute' already set to value '$value', ignoring.\n"
if ($showset);
next;
}
# Set the existing attribute
my $rc = $callback->($level1, $level2, $level3, $level4, $attribute, $value);
issueWarning($SCST->errorString($rc)) if ($rc);
$changes++ if (!$rc);
}
}
return $changes;
}
sub setDriverAttribute {
my $driver = shift;
my $attribute = shift;
my $value = shift;
if ($attribute eq 'enabled') {
my $onoff = $value ? 'Enabling' : 'Disabling';
print "\t-> $onoff driver '$driver': ";
} else {
print "\t-> 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 $changes = 0;
my $driverCap = $SCST->driverIsVirtualCapable($driver);
my ($_attributes, $errorString) = $SCST->driverAttributes($driver);
return 0 if issueWarning($errorString);
# 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;
}
}
my $existing = cacheAttributes($_attributes);
# 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);
$changes++;
next;
} elsif (!defined($$existing{$attribute})) {
print "\t-> WARNING: Driver '$driver' lacks the settable attribute ".
"'$attribute', ignoring.\n\n";
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);
$changes++;
} else {
my $rc = setDriverAttribute($driver, $attribute, $value);
issueWarning($SCST->errorString($rc)) if ($rc);
}
$$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);
$changes++;
} else {
print "\t-> Driver dynamic attribute '$attribute' with value '$value' ".
"is not in configuration. Use -force to remove it.\n";
}
}
}
}
return $changes;
}
sub addDriverDynamicAttributes {
my $driver = shift;
my $attributes = shift;
my ($_attributes, $errorString) = $SCST->driverAttributes($driver);
return TRUE if issueWarning($errorString);
my $existing = cacheAttributes($_attributes);
foreach my $attribute (keys %{$attributes}) {
if (defined($$existing{$attribute}->{$$attributes{$attribute}})) {
my $value = $$attributes{$attribute};
print "\t-> Attribute/value '$attribute/$value' already exists for driver '$driver'.\n";
next;
}
addDriverDynamicAttribute($driver, $attribute, $$attributes{$attribute});
}
return FALSE;
}
sub addDriverDynamicAttribute {
my $driver = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Adding driver attribute '$attribute' with value '$value' for driver '$driver': ";
my $rc = $SCST->addDriverDynamicAttribute($driver, $attribute, $value);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeDriverDynamicAttributes {
my $driver = shift;
my $attributes = shift;
my ($_attributes, $errorString) = $SCST->driverAttributes($driver);
return TRUE if issueWarning($errorString);
my $existing = cacheAttributes($_attributes);
foreach my $attribute (keys %{$attributes}) {
if (!defined($$existing{$attribute}->{$$attributes{$attribute}})) {
my $value = $$attributes{$attribute};
print "\t-> Attribute/value '$attribute/$value' doesn't exist for driver '$driver'.\n";
next;
}
removeDriverDynamicAttribute($driver, $attribute, $$attributes{$attribute});
}
return FALSE;
}
sub removeDriverDynamicAttribute {
my $driver = shift;
my $attribute = shift;
my $value = shift;
return TRUE if (!$SCST->driverIsVirtualCapable($driver));
print "\t-> Removing dynamic attribute '$attribute' with value '$value' for driver '$driver': ";
my $rc = $SCST->removeDriverDynamicAttribute($driver, $attribute, $value);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub setTargetAttribute {
my $driver = shift;
my $target = shift;
my $attribute = shift;
my $value = shift;
if ($attribute eq 'enabled') {
my $onoff = $value ? 'Enabling' : 'Disabling';
print "\t-> $onoff driver/target '$driver/$target': ";
} else {
print "\t-> Setting target attribute '$attribute' to value '$value' for ".
"driver/target '$driver/$target': ";
}
my $rc = $SCST->setTargetAttribute($driver, $target, $attribute, $value);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub setTargetAttributes {
my $driver = shift;
my $target = shift;
my $attributes = shift;
my $deletions = shift;
my %toset;
my $changes = 0;
my $driverCap = $SCST->driverIsVirtualCapable($driver);
my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target);
return 0 if issueWarning($errorString);
# 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;
}
}
my $existing = cacheAttributes($_attributes);
# add/change
foreach my $attribute (keys %toset) {
foreach my $value (keys %{$toset{$attribute}}) {
next if ($attribute eq 'HW_TARGET');
if (!defined($$existing{$attribute}) &&
$driverCap && !$SCST->checkTargetDynamicAttributes($driver, $attribute)) {
addTargetDynamicAttribute($driver, $target, $attribute, $value);
$changes++;
next;
} elsif (!defined($$existing{$attribute})) {
print "\t-> WARNING: Driver/target '$driver/$target' lacks the settable attribute ".
"'$attribute', ignoring.\n\n";
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);
$changes++;
} else {
my $rc = setTargetAttribute($driver, $target, $attribute, $value);
issueWarning($SCST->errorString($rc)) if ($rc);
$changes++ if (!$rc);
}
$$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);
$changes++;
} else {
print "\t-> Target dynamic attribute '$attribute' with value '$value' ".
"is not in configuration. Use -force to remove it.\n";
}
}
}
}
return $changes;
}
sub addTargetDynamicAttributes {
my $driver = shift;
my $target = shift;
my $attributes = shift;
my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target);
return TRUE if issueWarning($errorString);
my $existing = cacheAttributes($_attributes);
foreach my $attribute (keys %{$attributes}) {
if (defined($$existing{$attribute}->{$$attributes{$attribute}})) {
my $value = $$attributes{$attribute};
print "\t-> Attribute/value '$attribute/$value' already exists for driver/target ".
"'$driver/$target'.\n";
next;
}
addTargetDynamicAttribute($driver, $target, $attribute, $$attributes{$attribute});
}
return FALSE;
}
sub addTargetDynamicAttribute {
my $driver = shift;
my $target = shift;
my $attribute = shift;
my $value = shift;
print "\t-> Adding target attribute '$attribute' with value '$value' ".
"for driver/target '$driver/$target': ";
my $rc = $SCST->addTargetDynamicAttribute($driver, $target, $attribute, $value);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeTargetDynamicAttributes {
my $driver = shift;
my $target = shift;
my $attributes = shift;
my ($_attributes, $errorString) = $SCST->targetAttributes($driver, $target);
return TRUE if issueWarning($errorString);
my $existing = cacheAttributes($_attributes);
foreach my $attribute (keys %{$attributes}) {
if (!defined($$existing{$attribute}->{$$attributes{$attribute}})) {
my $value = $$attributes{$attribute};
print "\t-> Attribute/value '$attribute/$value' doesn't exist for driver/target ".
"'$driver/$target'.\n";
next;
}
removeTargetDynamicAttribute($driver, $target, $attribute, $$attributes{$attribute});
}
return FALSE;
}
sub removeTargetDynamicAttribute {
my $driver = shift;
my $target = shift;
my $attribute = shift;
my $value = shift;
return TRUE if (!$SCST->driverIsVirtualCapable($driver));
print "\t-> Removing dynamic attribute '$attribute' with value '$value' for driver/target '$driver/$target': ";
my $rc = $SCST->removeTargetDynamicAttribute($driver, $target, $attribute, $value);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
####################################################################
sub openDevice {
my $handler = shift;
my $device = shift;
my $attributes = shift;
print "\t-> Opening device '$device' using handler '$handler': ";
my $rc = $SCST->openDevice($handler, $device, $attributes);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub closeDevice {
my $handler = shift;
my $device = shift;
my $force = shift;
my ($attributes, $errorString) = $SCST->deviceAttributes($device);
if (!$force) {
if (keys %{$$attributes{'exported'}}) {
listExported($device, $attributes);
immediateExit("Device '$device' still in use, aborting. ".
"Use -force to override.");
}
}
print "\t-> Closing device '$device' using handler '$handler': ";
my $rc = $SCST->closeDevice($handler, $device);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub resyncDevice {
my $device = shift;
my %attributes = ('resync_size', 1);
return setDeviceAttributes($device, \%attributes);
}
####################################################################
sub addDeviceGroup {
my $group = shift;
print "\t-> Adding new device group '$group': ";
my $rc = $SCST->addDeviceGroup($group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub addTargetGroup {
my $group = shift;
my $tgroup = shift;
print "\t-> Adding new target group '$tgroup' to device group '$group': ";
my $rc = $SCST->addTargetGroup($group, $tgroup);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub addTargetGroupTarget {
my $group = shift;
my $tgroup = shift;
my $tgt = shift;
print "\t-> Adding new target group/target '$tgroup/$tgt' to device group '$group': ";
my $rc = $SCST->addTargetGroupTarget($group, $tgroup, $tgt);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeDeviceGroup {
my $group = shift;
my $force = shift;
my $errorString;
if (!$force) {
my $devices;
my $tgroups;
($devices, $errorString) = $SCST->deviceGroupDevices($group);
($tgroups, $errorString) = $SCST->targetGroups($group);
if (($#{$devices} > -1) || ($#{$tgroups} > -1)) {
print "\n";
listDeviceGroup($group);
immediateExit("Device group is still in use, aborting. Use -force to override.");
}
}
print "\t-> Removing device group '$group': ";
my $rc = $SCST->removeDeviceGroup($group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeTargetGroup {
my $group = shift;
my $tgroup = shift;
my $force = shift;
my $errorString;
if (!$force) {
my $tgts;
($tgts, $errorString) = $SCST->targetGroupTargets($group, $tgroup);
if ($#{$tgts} > -1) {
print "\n";
listTargetGroup($group, $tgroup);
immediateExit("Target group is still in use, aborting. Use -force to override.");
}
}
print "\t-> Removing target group '$tgroup' from device group '$group': ";
my $rc = $SCST->removeTargetGroup($group, $tgroup);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeTargetGroupTarget {
my $group = shift;
my $tgroup = shift;
my $tgt = shift;
my $force = shift;
print "\t-> Removing target group/target '$tgroup/$tgt' from device group '$group': ";
my $rc = $SCST->removeTargetGroupTarget($group, $tgroup, $tgt);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub addDeviceGroupDevice {
my $group = shift;
my $device = shift;
print "\t-> Adding new device group/device '$group/$device': ";
my $rc = $SCST->addDeviceGroupDevice($group, $device);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeDeviceGroupDevice {
my $group = shift;
my $device = shift;
my $force = shift;
my $errorString;
if (!$force) {
my $found = FALSE;
my $tgroups;
($tgroups, $errorString) = $SCST->targetGroups($group);
foreach my $tgroup (@{$tgroups}) {
my $targets;
($targets, $errorString) = $SCST->targetGroupTargets($group, $tgroup);
if ($#{$targets} > -1) {
print "\n";
listTargetGroup($group, $tgroup);
$found = TRUE;
}
}
if ($found) {
immediateExit("Device may still be in use, aborting. Use -force to override.");
}
}
print "\t-> Removing device '$device' from target group '$group': ";
my $rc = $SCST->removeDeviceGroupDevice($group, $device);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
####################################################################
sub addGroup {
my $driver = shift;
my $target = shift;
my $group = shift;
# Don't try to add it if we just established it already exists
return FALSE if exists $CURRENT{assign}->{$driver}->{$target}->{GROUP}->{$group};
print "\t-> Adding new group '$group' to driver/target '$driver/$target': ";
my $rc = $SCST->addGroup($driver, $target, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeGroup {
my $driver = shift;
my $target = shift;
my $group = shift;
my $force = shift;
my $errorString;
if (!$force) {
my $luns;
my $initiators;
($luns, $errorString) = $SCST->luns($driver, $target, $group);
($initiators, $errorString) = $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 "\t-> Removing group '$group' from driver/target '$driver/$target': ";
my $rc = $SCST->removeGroup($driver, $target, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
####################################################################
sub addInitiator {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
my $current = $CURRENT{'assign'}->{$driver}->{$target}->{'GROUP'};
foreach my $group (keys %{$current}) {
my $initiators = $$current{$group}->{'INITIATORS'};
foreach my $init (@{$initiators}) {
if ($init eq $initiator) {
print "\t-> Initiator '$initiator' already belongs to group '$group' ".
"for driver/target '$driver/target', ignoring.\n";
return;
}
}
}
print "\t-> Adding new initiator '$initiator' to driver/target/group ".
"'$driver/$target/$group': ";
my $rc = $SCST->addInitiator($driver, $target, $group, $initiator);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeInitiator {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
print "\t-> Removing initiator '$initiator' from driver/target/group ".
"'$driver/$target/$group': ";
my $rc = $SCST->removeInitiator($driver, $target, $group, $initiator);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub moveInitiator {
my $driver = shift;
my $target = shift;
my $group = shift;
my $initiator = shift;
my $to = shift;
print "\t-> Moving initiator '$initiator' from group '$group' to group '$to': ";
my $rc = $SCST->moveInitiator($driver, $target, $group, $to, $initiator);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub clearInitiators {
my $driver = shift;
my $target = shift;
my $group = shift;
print "\t-> Removing all initiators driver/target/group '$driver/$target/$group': ";
my $rc = $SCST->clearInitiators($driver, $target, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
####################################################################
sub addLun {
my $driver = shift;
my $target = shift;
my $device = shift;
my $lun = shift;
my $attributes = shift;
my $group = shift;
# Do not complain about existing LUNs.
if (
$SCST->lunExists($driver, $target, $lun, $group)) {
return FALSE;
}
if (valid($group)) {
print "\t-> Adding device '$device' at LUN $lun to driver/target/group ".
"'$driver/$target/$group': ";
} else {
print "\t-> Adding device '$device' at LUN $lun to driver/target ".
"'$driver/$target': ";
}
my $rc = $SCST->addLun($driver, $target, $device, $lun, $attributes, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub removeLun {
my $driver = shift;
my $target = shift;
my $lun = shift;
my $group = shift;
if ($group) {
print "\t-> Removing LUN $lun from driver/target/group ".
"'$driver/$target/$group': ";
} else {
print "\t-> Removing LUN $lun from driver/target ".
"'$driver/$target': ";
}
my $rc = $SCST->removeLun($driver, $target, $lun, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub replaceLun {
my $driver = shift;
my $target = shift;
my $group = shift;
my $lun = shift;
my $device = shift;
my $attributes = shift;
print "\t-> Replacing device at LUN $lun with device '$device' ".
"in driver/target/group '$driver/$target/$group': ";
my $rc = $SCST->replaceLun($driver, $target, $lun, $device, $attributes, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub clearLuns {
my $driver = shift;
my $target = shift;
my $group = shift;
if ($group) {
print "\t-> Removing all LUNs from driver/target/group '$driver/$target/$group': ";
} else {
print "\t-> Removing all LUNs from driver/target '$driver/$target': ";
}
my $rc = $SCST->clearLuns($driver, $target, $group);
print "done.\n";
condExit($SCST->errorString($rc));
return FALSE;
}
sub clearDriverDynamicAttributes {
my $driver = shift;
my $errorString;
return TRUE if (!$SCST->driverIsVirtualCapable($driver));
print "\t-> Removing all dynamic attributes from driver '$driver': ";
my $attributes;
my $dynamic;
($attributes, $errorString) = $SCST->driverAttributes($driver);
($dynamic, $errorString) = $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);
condExit($SCST->errorString($rc));
}
}
}
}
print "done.\n";
return FALSE;
}
sub clearTargetDynamicAttributes {
my $driver = shift;
my $target = shift;
my $errorString;
return TRUE if (!$SCST->driverIsVirtualCapable($driver));
print "\t-> Removing all dynamic attributes from driver/target '$driver/$target': ";
my $attributes;
my $dynamic;
($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
($dynamic, $errorString) = $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);
condExit($SCST->errorString($rc));
}
}
}
}
print "done.\n";
return FALSE;
}
####################################################################
sub enableTarget {
my $driver = shift;
my $target = shift;
my %attributes = ('enabled', 1);
setTargetAttributes($driver, $target, \%attributes);
return FALSE;
}
sub disableTarget {
my $driver = shift;
my $target = shift;
my %attributes = ('enabled', 0);
setTargetAttributes($driver, $target, \%attributes);
return FALSE;
}
sub enableDriver {
my $driver = shift;
my %attributes = ('enabled', 1);
my ($attrs, $errorString) = $SCST->driverAttributes($driver);
return TRUE if (!defined($$attrs{'enabled'}));
return setDriverAttributes($driver, \%attributes);
}
sub disableDriver {
my $driver = shift;
my %attributes = ('enabled', 0);
my ($attrs, $errorString) = $SCST->driverAttributes($driver);
return TRUE if (!defined($$attrs{'enabled'}));
return setDriverAttributes($driver, \%attributes);
}
sub issueLip {
my $driver = shift;
my $target = shift;
my $warn = shift;
my $errorString;
if (valid($driver, $target)) {
return _issueLip($driver, $target, $warn);
} else {
my $drivers;
($drivers, $errorString) = $SCST->drivers();
foreach my $driver(@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
my $rc = _issueLip($driver, $target, $warn);
return $rc if ($rc);
}
}
}
return FALSE;
}
sub _issueLip {
my $driver = shift;
my $target = shift;
my $warn = shift;
my $rc = FALSE;
my ($attributes, $errorString) = $SCST->targetAttributes($driver, $target);
my $dir = new IO::Handle;
my $host = $$attributes{'host'}->{'value'};
my $ldir = $SCST->SCST_TARGETS_DIR."/$driver/$target/";
if (!(opendir $dir, $ldir)) {
$ldir = $SCST->SCST_TARGETS_DIR."/$driver/$target/";
if (!(opendir $dir, $ldir)) {
print "\t-> Driver/target is not a fibre channel target, ignoring.\n";
return FALSE;
}
}
my $lip = $ldir.'/issue_lip';
if (-w $lip) {
my $io = new IO::File $lip, O_WRONLY;
print "WARNING: Failed to open file '$lip' for writing.\n"
if (!$io);
print "\t-> Issuing LIP on fibre channel driver/target '$driver/$target' ($host): ";
my $bytes = syswrite($io, 1, 1);
print "done.\n";
if (!$bytes) {
print "WARNING: Failed to issue LIP on driver/target '$driver/$target'.\n";
$rc = TRUE;
}
close $io;
} else {
print "Fibre channel driver/target '$driver/$target' lacks the ability to ".
"issue LIPs, ignoring.\n";
}
close $dir;
return $rc;
}
####################################################################
sub readConfigFile {
my $buffer;
my @stanza;
my $level;
my $io = new IO::File $CONFIGFILE, O_RDONLY;
immediateExit("Unable to open configuration file '$CONFIGFILE': $!")
if (!$io);
while (my $line = <$io>) {
$line =~ s/^\#.*//;
$line =~ s/[^\\]\#.*//;
if ($line =~ /\[(.*)\s+.*\]/) {
my $parm = $1;
if (($parm eq 'HANDLER') || ($parm eq 'GROUP') ||
($parm eq 'ASSIGNMENT')) {
print "\nNOTE: Using a deprecated configuration file. ".
"I will attempt to convert it for you.\n\n";
return readOldConfigFile();
}
}
$line =~ s/\\(.)/$1/g;
$buffer .= $line;
}
my @buff_a;
@buff_a = split(//, $buffer);
$CONFIG = parseStanza(\@buff_a);
return FALSE;
}
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;
if ($line) {
parseLine($line, \%hash, \%empty);
$line = undef;
}
} else {
$line .= $char;
}
}
return \%hash;
}
sub parseLine {
my $line = shift;
my $hash = shift;
my $child = shift;
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 readOldConfigFile {
my $ignoreError = shift;
my %config;
my $section;
my $last_section;
my $arg;
my $last_arg;
my %empty;
my $io = new IO::File $CONFIGFILE, O_RDONLY;
if (!$io) {
return undef if ($ignoreError);
die("FATAL: Unable to open specified configuration file 'CONFIGFILE': $!\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}->{$o_converts{$option}}->{'1'}} = ();
}
}
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'t10_dev_id'}->{$t10}} = ()
if ($t10);
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'filename'}->{$path}} = ()
if ($path);
%{$new{'HANDLER'}->{$_handler}->{'DEVICE'}->{$device}->{'blocksize'}->{$bsize}} = ()
if ($bsize);
}
}
my ($drivers, $errorString) = $SCST->drivers();
my %added_targets;
# Handle default groups
foreach my $group (keys %{$config{'ASSIGNMENT'}}) {
next if ($group !~ /^Default/);
if ($group eq 'Default') { # Add to all targets
foreach my $device (@{$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) {
my($device, $lun) = split(/\,/, $device);
foreach my $driver (@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'LUN'}->{$lun}->{$device} = {};
}
}
}
} else {
my $group_t = $group;
$group_t =~ s/^Default\_//;
my $found_t = FALSE;
# Find the associated target
foreach my $driver (@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
if ($target eq $group_t) {
foreach my $device (@{$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) {
my($device, $lun) = split(/\,/, $device);
$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'LUN'}->{$lun}->{$device} = {};
}
$found_t = TRUE;
}
}
}
if (!$found_t) {
print "NOTE: Unable to find target $group. I will add this target to ".
"all drivers capable of creating targets.\n";
foreach my $driver (@{$drivers}) {
if ($SCST->driverIsVirtualCapable($driver)) {
foreach my $device (@{$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) {
my($device, $lun) = split(/\,/, $device);
$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$group_t}->{'LUN'}->{$lun}->{$device} = {};
$added_targets{$driver}->{$group_t} = TRUE;
}
}
}
}
}
}
my $has_enabled = FALSE;
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'}} = ();
addAllGroupsToTarget(\%config, \%new, $driver, $target);
$has_enabled = TRUE;
} else {
condExit("Unable to determine target driver information for target '$wwn'. ".
"Please ensure this target driver is loaded.");
}
}
if (!$has_enabled) {
print "NOTE: No targets set to 'enable' within your configuration file. Please be sure to ".
"save write your configuration with -write_config and review it carefully.\n\n";
# Fill in with known targets, all disabled.
foreach my $driver (@{$drivers}) {
my $targets;
($targets, $errorString) = $SCST->targets($driver);
foreach my $target (@{$targets}) {
addAllGroupsToTarget(\%config, \%new, $driver, $target);
}
}
# As well for any created targets
foreach my $driver (keys %added_targets) {
foreach my $target (keys %{$added_targets{$driver}}) {
addAllGroupsToTarget(\%config, \%new, $driver, $target);
}
}
}
# Fix drivers 'enabled' attributes
foreach my $driver (keys %{$new{'TARGET_DRIVER'}}) {
next if ($driver =~ /^qla/);
my $attributes;
($attributes, $errorString) = $SCST->driverAttributes($driver);
if (defined($$attributes{'enabled'})) {
$new{'TARGET_DRIVER'}->{$driver}->{'enabled'}->{'1'} = {};
}
foreach my $target (keys %{$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}}) {
next if (defined($new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{'enabled'}));
$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'enabled'}->{'1'} = {};
}
}
$CONFIG = \%new;
}
sub addAllGroupsToTarget {
my $config = shift;
my $new = shift;
my $driver = shift;
my $target = shift;
foreach my $group (keys %{$$config{'GROUP'}}) {
if (defined($$config{'GROUP'}->{$group}->{'USER'})) {
%{$$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}} = ();
foreach my $user (@{$$config{'GROUP'}->{$group}->{'USER'}}) {
%{$$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'INITIATOR'}->{$user}} = ();
}
}
}
foreach my $group (keys %{$$config{'ASSIGNMENT'}}) {
next if ($group =~ /^Default/);
foreach my $device (@{$$config{'ASSIGNMENT'}->{$group}->{'DEVICE'}}) {
my($device, $lun) = split(/\,/, $device);
%{$$new{'TARGET_DRIVER'}->{$driver}->{'TARGET'}->{$target}->{'GROUP'}->{$group}->{'LUN'}->{$lun}->{$device}} = ();
}
}
return FALSE;
}
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 deviceGroupHasDevice {
my $group = shift;
my $device = shift;
return FALSE if (!defined($CURRENT{'dgroups'}->{$group}));
foreach my $_device (@{$CURRENT{'dgroups'}->{$group}->{'devices'}}) {
return TRUE if ($_device eq $device);
}
return FALSE;
}
sub arrayHasValue {
my $array = shift;
my $value = shift;
foreach my $item (@{$array}) {
return TRUE if ($item eq $value);
}
return FALSE;
}
sub configToAttr {
my $config = shift;
my %attributes = ( );
foreach my $attr (keys %{$config}) {
if (!scalar keys %{$$config{$attr}}) {
$attributes{$attr} = '';
} elsif ((keys %{$$config{$attr}}) > 1) {
foreach my $value (keys %{$$config{$attr}}) {
push @{$attributes{$attr}}, $value;
}
} 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 cacheAttributes {
my $attributes = shift;
my %cache;
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'};
$cache{$attribute}->{$value} = FALSE;
}
} else {
my $value = $$attributes{$attribute}->{'value'};
# Write-only attributes (e.g. abort_isp) do not have
# a value.
$value = "" if (!defined($value));
$cache{$attribute}->{$value} = FALSE;
}
}
return \%cache;
}
sub numerically {
$a <=> $b;
}
####################################################################
# If we have an unread error from SCST, exit immediately
sub immediateExit {
my $error = shift;
return FALSE if (!$error);
print "\n\nFATAL: Received the following error:\n\n\t";
print "$error\n\n";
exit 1;
}
# If an error occurred, exit if -cont_on_err has not been specified.
sub condExit {
my $error = shift;
if (!$error) {
;
} elsif ($_CONT_ON_ERR_) {
print "$error\n";
} else {
immediateExit($error);
}
}
sub issueWarning {
my $error = shift;
return FALSE if (!$error);
print "\n\nWARNING: Received the following error:\n\n\t";
print "$error\n\n";
return TRUE;
}
sub prompt {
return FALSE if ($_NOPROMPT_);
print "Performing this action may result in lost or corrupt data, ".
"are you sure you wish to continue (y/[n]) ? ";
my $answer = <STDIN>;
if (defined($answer) &&
(($answer =~ /^y$/i) || ($answer =~ /^yes$/i))) {
return FALSE;
}
print "Aborting action.\n";
return TRUE;
}
# Hey! Stop that!
sub commitSuicide {
print "\n\nAborting immediately.\n";
exit 1;
}
# Local Variables:
# mode: perl
# perl-indent-level: 8
# indent-tabs-mode: t
# End: