On 01/19/2012 01:37 AM, Roger Deschner wrote:
Pay attention to the fact that typically rmtN, mtN, and TSM driveN device numbers will be different. Make sure the serial numbers in TSM Q DRIVE F=D are correct.
... This, a whole bunch. I'll drop a few scripts here I use to automate the process. First, I've got a file which associates TSM drive names with serial numbers. In my scripts it's referenced as '/var/tsm/base/etc/device-correspondence.csv', but of course you can store it anywhere. It looks like this: DRIVE0,000007892730,460,new DRIVE1,000007892835,470,new DRIVE2,000007892870,480,new The third field there is me keeping track of how the 3494 sees the drive. Useful to communicate with SE, who'll tell you that "drive 300 had an intervention". My scripts only use the first two fields; unfinished plans, et. alia. Then I've got the attached script 'tape-config', which looks at all of your tape devices and ties them, through the serial number, to your TSM drive label. It drops a bunch of files in ".", each one of which holds all the lsdev output for devices attached to that serial. The last step is the attached script 'tape-paths', which takes all the collected devices, and then dumps path updates (or if you tell it to, defines) to stdout. It expects to be run in the directory where you collected tape-config. Its output looks something like this: root@tsm4 tapes-2011-12 # ./tape-paths -server foo -define define path foo DRIVE9 srct=server destt=drive libr=3592lib device=/dev/rmt8 define path foo DRIVE6 srct=server destt=drive libr=3592lib device=/dev/rmt4 define path foo DRIVE8 srct=server destt=drive libr=3592lib device=/dev/rmt9 [...] or root@tsm4 tapes-2011-12 # ./tape-paths -server foo update path foo DRIVE9 srct=server destt=drive libr=3592lib device=/dev/rmt8 update path foo DRIVE6 srct=server destt=drive libr=3592lib device=/dev/rmt4 update path foo DRIVE8 srct=server destt=drive libr=3592lib device=/dev/rmt9 [...] .... All in all, it's sufficiently easy that I approach even broad renumbering and fabric changes with equanimity. We recently split our fiber into two independant fabrics, and I basically: + set all drives offline. + recabled the last few links. + rmdev -d -l every rmt device + cfgmgr + instAtape -a to get multipath data in place + run tape-config and then at the bash prompt: # for server in int ext glmail01 glmail02 whole list of servers; \ tape-paths -server $server which gives output you can just paste into your library manager. - Allen S. Rout
#!/usr/local/bin/perl use FileHandle; use Data::Dumper; my $verbose =1; my $in = new FileHandle; my $drives = {}; my $out = {}; $in->open("/var/tsm/base/etc/device-correspondence.csv"); while (<$in>) { # print; chomp; my ($tsm,$sn) = split(/,/); $drives->{$sn} = $tsm; } # print Dumper($drives); $in->open("/usr/sbin/lscfg | grep rmt |"); while (<$in>) { my ($junk,$rmt,@junk) = split; # print $rmt,"\n"; my (@tape) = `/usr/sbin/lscfg -vl $rmt`; my ($snline) = grep{/Serial Number\.+(\d+)$/} @tape; # print $snline; my ($sn) = $snline =~ /Serial Number\.+(\d+)$/; my $drive = $drives->{$sn}; $verbose && print "$rmt:\tNew entry for '$drive'\n"; $out->{$sn} = new FileHandle(">./serial-$sn-$drive") unless defined($out->{$sn}); $out->{$sn}->print(@tape); $out->{$sn}->print( `/usr/sbin/lsdev -l $rmt` ); }
#!/usr/local/bin/perl use FileHandle; use Data::Dumper; use Getopt::Long; my $verbose =1; my $in = new FileHandle; my $drives = {}; my $rmts = {}; my $define = undef; my $server = []; my @servers; my $script = 0; my $libr="3592lib"; $result = GetOptions ( "verbose" => \$verbose, "server=s" => $server, "define!" => \$define, "script!" => \$script, ); if ($#{$server} > -1 ) {@servers = @{$server} ;} else {@servers = ( "CTRL" ) } my $out = {}; $in->open("/var/tsm/base/etc/device-correspondence.csv"); while (<$in>) { # print; chomp; my ($tsm,$sn,$lib) = split(/,/); $drives->{$sn} = { 'TSM' => $tsm, 'LIB' => $lib, }; } $in->close; $in->open("/usr/sbin/lsdev -Cc tape|"); while (<$in>) { chomp; # print; my ($rmt,$stat,$loc,@crap) = split(/\s+/); my @junk = split(/-/,$loc); $rmts->{$rmt} = { "pri" => pop(@junk) }; } # print Dumper($rmts); foreach $drive (keys %$drives) { my @lines = `/usr/local/bin/grep rmt ./serial-$drive-*`; my $pri = ""; foreach $line (@lines) { my ($crap,$dev,@crap) = split(/\s+/,$line); my $p = $rmts->{$dev}->{"pri"}; if ($p eq "PRI") { if ($pri ne "") { die "Multiple primay devices for '$drive' ??" } $pri = $dev; } } if ($pri eq "") { die "No primary device for '$drive' ??" } # print "$drive: $pri \n"; $drives->{$drive}->{pri} = $pri; } # print Dumper($drives); if (0) { foreach $drive ( keys %$drives) { print sprintf("select distinct source_name as %s from paths where destination_name = '%s' and device!='/dev/%s'\n", $drives->{$drive}->{TSM}, $drives->{$drive}->{TSM}, $drives->{$drive}->{pri} ); } exit 1; } if ($script) { # setting up a script. my $host = `/usr/bin/hostname`; chomp($host); print " /* Tape paths from $host */\n"; foreach $drive ( keys %$drives ) { my $op = ( $define?"define":"update"); print sprintf("%s path \$1 %s srct=server destt=drive libr=%s device=/dev/%s \n", $op, $drives->{$drive}->{TSM}, $libr, $drives->{$drive}->{pri} ); } } else { # Doing an interactive run... foreach $server (@servers) { foreach $drive ( keys %$drives ) { my $op = ( $define?"define":"update"); print sprintf("%s path %s %s srct=server destt=drive libr=%s device=/dev/%s \n", $op, $server, $drives->{$drive}->{TSM}, $libr, $drives->{$drive}->{pri} ); } } }