File Coverage

blib/lib/NBU/Robot.pm
Criterion Covered Total %
statement 25 181 13.8
branch 0 70 0.0
condition 0 15 0.0
subroutine 7 27 25.9
pod 0 20 0.0
total 32 313 10.2


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2002 Paul Winkeler. All Rights Reserved.
3             # This program is free software; you may redistribute it and/or modify it under
4             # the same terms as Perl itself.
5             #
6             package NBU::Robot;
7              
8 1     1   8 use strict;
  1         3  
  1         45  
9 1     1   5 use Carp;
  1         3  
  1         87  
10              
11             BEGIN {
12 1     1   7 use Exporter ();
  1         8  
  1         27  
13 1     1   6 use AutoLoader qw(AUTOLOAD);
  1         3  
  1         9  
14 1     1   41 use vars qw(%robotLevel);
  1         2  
  1         64  
15 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD);
  1         2  
  1         180  
16 1     1   3 $VERSION = do { my @r=(q$Revision: 1.23 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
  1         7  
  1         9  
17 1         17 @ISA = qw();
18 1         8 @EXPORT = qw(%robotLevel);
19 1         5 @EXPORT_OK = qw();
20 1         2112 %EXPORT_TAGS = qw();
21             }
22              
23             my @farm;
24              
25             my %robotTypes = (
26             1 => 'ACS',
27             2 => 'TS8',
28             3 => 'TC8',
29             5 => 'ODL',
30             6 => 'TL8',
31             7 => 'TL4',
32             8 => 'TLD',
33             9 => 'TC4',
34             10 => 'TSD',
35             11 => 'TSH',
36             12 => 'TLH',
37             13 => 'TLM',
38             17 => 'LMF',
39             0 => '-',
40             );
41              
42             #
43             # new(robot-number, robot-type [, robot-host-name])
44             sub new {
45 0     0 0   my $Class = shift;
46 0           my $robot = {};
47              
48              
49 0 0         if (@_) {
50 0           my $id = shift;
51              
52 0           my $type = shift;
53 0 0         if ($type =~ /^[\d]+$/) {
54 0 0 0       if (!exists($robotTypes{$type}) || ($type == 0)) {
55 0           return undef;
56             }
57             else {
58 0           $type = $robotTypes{$type};
59             }
60             }
61             else {
62 0 0         return undef if ($type eq "-");
63             }
64              
65 0 0         if ($farm[$id]) {
66 0           $robot = $farm[$id];
67             }
68             else {
69 0           bless $robot, $Class;
70 0           $robot->{ID} = $id;
71 0           $farm[$id] = $robot;
72              
73 0           $robot->{DEVICEPATH} = undef;
74 0           $robot->{MAILSLOTSIZE} = 14;
75 0           $robot->{SLOTS} = {};
76 0           $robot->{DRIVES} = [];
77 0           $robot->{KNOWNTO} = [];
78 0           $robot->{TYPE} = $type;
79             }
80             }
81              
82 0           return $robot;
83             }
84              
85             sub populate {
86 0     0 0   my $self = shift;
87              
88 0           my $lastSlot;
89              
90 0           my $type = $self->type;
91 0           $type =~ tr/A-Z/a-z/;
92              
93 0 0         if (!defined($self->host)) {
94 0           $lastSlot = 0;
95             }
96             else {
97 0           my $pipe = NBU->cmd("vmcheckxxx ".
98             " -rt $type".
99             " -rn ".$self->id.
100             " -rh ".$self->host->name.
101             " -list |");
102              
103 0 0 0       if ($self->host->NBUVersion eq "3.2.0") {
    0 0        
      0        
104 0           while (<$pipe>) {
105 0 0         if (/^Slot = [\s]*([\d]+), Barcode = ([\S]+)$/) {
    0          
106 0 0         if (defined(my $volume = NBU::Media->byBarcode($2))) {
107 0           $self->insert($1, $volume);
108             }
109             else {
110 0           print STDERR "Unknown barcode $2 in slot $1 of robot ".$self->id."\n";
111 0           $self->empty($1);
112             }
113 0           $lastSlot = $1;
114             }
115             elsif (/^Slot = [\s]*([\d]+), /) {
116 0           $self->empty($1);
117 0           $lastSlot = $1;
118             }
119             else {
120 0           print STDERR "Ignoring $_";
121             }
122             }
123             }
124             elsif (($self->host->NBUVersion eq "3.4.0")
125             || ($self->host->NBUVersion eq "4.5.0")
126             || ($self->host->NBUVersion eq "5.1.0")
127             || ($self->host->NBUVersion eq "6.5.0")
128             ) {
129 0           while (<$pipe>) {
130 0 0         last if (/^===/);
131             }
132 0           while (<$pipe>) {
133 0 0         if (/^[\s]*([\d]+)[\s]+[\S]+[\s]+([\S]+)/) {
    0          
134 0 0         if (defined(my $volume = NBU::Media->byBarcode($2))) {
135 0           $self->insert($1, $volume);
136             }
137             else {
138 0           print STDERR "Unknown barcode $2 in slot $1 of robot ".$self->id."\n";
139 0           $self->empty($1);
140             }
141 0           $lastSlot = $1;
142             }
143             elsif (/^[\s]*([\d]+)[\s]+No/) {
144 0           $self->empty($1);
145 0           $lastSlot = $1;
146             }
147             else {
148 0           print STDERR "Ignoring $_";
149             }
150             }
151             }
152             else {
153 0           print STDERR "Unknown NetBackup version \"".$self->host->NBUVersion."\"\n";
154 0           $lastSlot = 0;
155             }
156             }
157              
158 0 0         $self->{CAPACITY} = defined($lastSlot) ? $lastSlot : 0;
159             }
160              
161             sub byID {
162 0     0 0   my $class = shift;
163 0           my $id = shift;
164              
165 0           return $farm[$id];
166             }
167              
168             sub id {
169 0     0 0   my $self = shift;
170              
171 0           return $self->{ID};
172             }
173              
174             sub type {
175 0     0 0   my $self = shift;
176              
177 0 0         $self->loadRobotDetail if (!defined($self->{DETAILED}));
178 0 0         if (@_) {
179 0           $self->{TYPE} = shift;
180             }
181 0           return $self->{TYPE};
182             }
183              
184             sub host {
185 0     0 0   my $self = shift;
186              
187 0 0         $self->loadRobotDetail if (!defined($self->{DETAILED}));
188 0 0         if (@_) {
189 0           $self->{CONTROLHOST} = shift;
190             }
191 0           return $self->{CONTROLHOST};
192             }
193              
194             sub voldbHost {
195 0     0 0   my $self = shift;
196              
197 0 0         $self->loadRobotDetail if (!defined($self->{DETAILED}));
198 0 0         if (@_) {
199 0           $self->{VOLDBHOST} = shift;
200             }
201 0           return $self->{VOLDBHOST};
202             }
203              
204             sub controlDrive {
205 0     0 0   my $self = shift;
206 0           my $drive = shift;
207              
208              
209 0           my $driveList = $self->{DRIVES};
210 0           push @$driveList, $drive;
211              
212 0           return $drive;
213             }
214              
215             sub drives {
216 0     0 0   my $self = shift;
217              
218 0           my $driveList = $self->{DRIVES};
219 0           return @$driveList;
220             }
221              
222             #
223             # Robots are accessed through storage units. Every time a new robotic
224             # storage unit is defined, the robot in question is informed of this by
225             # a call to the known method.
226             # Without arguments a list of storage units using the robot is returned.
227             sub known {
228 0     0 0   my $self = shift;
229              
230 0           my $stuList = $self->{KNOWNTO};
231 0 0         if (@_) {
232 0           my $stu = shift;
233 0           push @$stuList, $stu;
234             }
235 0           return @$stuList;
236             }
237              
238             sub insert {
239 0     0 0   my $self = shift;
240 0           my $slotList = $self->{SLOTS};
241 0           my ($position, $volume) = @_;
242              
243 0 0         if (exists($$slotList{$position})) {
244 0 0         if ($$slotList{$position} != $volume) {
245 0           print STDERR "Slot $position in ".$self->id." already filled; no room for ".$volume->id."\n";
246             }
247             else {
248             }
249             }
250             else {
251 0           $$slotList{$position} = $volume;
252             }
253 0           return $$slotList{$position};
254             }
255              
256             sub empty {
257 0     0 0   my $self = shift;
258 0           my $slotList = $self->{SLOTS};
259 0           my $position = shift;
260              
261 0 0         if (exists($$slotList{$position})) {
262 0           my $volume = $$slotList{$position};
263 0           delete $$slotList{$position};
264              
265 0           $volume->robot(undef);
266 0           $volume->slot(undef);
267             }
268              
269 0           return undef;
270             }
271              
272             sub nextEmptySlot {
273 0     0 0   my $self = shift;
274 0           my $slotList = $self->{SLOTS};
275              
276 0           for my $s (1..$self->capacity) {
277 0 0         return $s if (!exists($$slotList{$s}));
278             }
279 0           return undef;
280             }
281              
282             sub slot {
283 0     0 0   my $self = shift;
284 0           my $slotList = $self->{SLOTS};
285 0           my $position = shift;
286            
287              
288 0 0         if (@_) {
289 0           my $volume = shift;
290 0           return $self->insert($position, $volume);
291             }
292 0           return $$slotList{$position};
293             }
294              
295             sub capacity {
296 0     0 0   my $self = shift;
297              
298 0 0         if (!defined($self->{CAPACITY})) {
299 0           $self->populate;
300             }
301              
302 0           return $self->{CAPACITY};
303             }
304              
305             sub slotList {
306 0     0 0   my $self = shift;
307 0           my $slotList = $self->{SLOTS};
308 0           my @list;
309              
310             #
311             # Undefined or unreachable robots have no capacity thus
312             # should result in completely empty lists
313 0 0         if (my $lastSlot = $self->capacity) {
314             # slot 0 is not used but PERL arrays default to 0 based indexing...
315 0           push @list, undef;
316 0           for my $s (1..$lastSlot) {
317 0           push @list, $$slotList{$s};
318             }
319             }
320              
321 0           return @list;
322             }
323              
324             sub mediaList {
325 0     0 0   my $self = shift;
326 0           my $slotList = $self->{SLOTS};
327              
328 0           return (values %$slotList);
329             }
330              
331             sub farm {
332 0     0 0   my $Class = shift;
333              
334 0           return (@farm);
335             }
336              
337             sub updateInventory {
338 0     0 0   my $self = shift;
339 0           my $importCAP = shift;
340              
341 0 0 0       NBU->cmd("vmupdate "." -rt ".$self->type." -rn ".$self->id." -rh ".$self->host->name
342             ." -use_barcode_rules"
343             .((defined($importCAP) && $importCAP) ? " -empty_ie" : "")
344             , 0);
345              
346 0           $self->populate;
347             }
348              
349             1;
350              
351             #
352             # Try to get more detail on this robot.
353             # If the host to query is not specified, first look to the robot's
354             # host or else the local master server for this information
355             sub loadRobotDetail {
356 0     0 0   my $self = shift;
357 0           my $server = shift;
358              
359 0 0         if (!defined($server)) {
360 0           my @masters = NBU->masters; $server = $masters[0];
  0            
361             }
362              
363 0           my $pipe = NBU->cmd("vmglob -h ".$server->name." -listall -java |");
364 0           while (<$pipe>) {
365 0 0         next unless (/VMGLOB... robot /);
366 0           chop;
367              
368 0           my($key, $d, $number, $serial, $host, $voldbHostName, $robotNumber, $na1, $type, $na2, $flags,
369             $wwName, $wwNameType, $inquiry, $libraryName, $vendorName, $controlHostName) =
370             split;
371              
372             # Any media server with drives controlled by this robot will generate an entry for this robot
373             # However, we only care about the entry from the host which is the controlling host.
374 0 0         next unless ($controlHostName eq "-");
375              
376 0 0         if (my $robot = NBU::Robot->byID($robotNumber)) {
377 0           $robot->{SERIALNUMBER} = $serial;
378 0           $robot->{VOLDBHOST} = NBU::Host->new($voldbHostName);
379 0           $robot->{CONTROLHOST} = NBU::Host->new($host);
380              
381 0           $robot->{DETAILED} = 1;
382             }
383             }
384 0           $self->{DETAILED} = 1;
385             }
386              
387             __END__