File Coverage

blib/lib/Device/WWN/EMC/Symmetrix.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Device::WWN::EMC::Symmetrix;
2 2     2   218672 use strict; use warnings;
  2     2   4  
  2         59  
  2         9  
  2         4  
  2         88  
3             our $VERSION = '1.01';
4 2     2   769 use Moose;
  0            
  0            
5             extends 'Device::WWN';
6             use Sub::Exporter -setup => {
7             exports => [qw(
8             wwn_to_serial_and_port
9             serial_and_port_to_wwn
10             is_valid_port_number
11             )]
12             };
13             use Device::WWN::Carp;
14              
15             has '+wwn' => (
16             lazy => 1,
17             default => sub {
18             my $self = shift;
19             croak "Can't generate WWN without serial number"
20             unless $self->has_serial_number;
21             croak "Can't generate WWN without port"
22             unless $self->has_port;
23             return serial_and_port_to_wwn( $self->serial_number, $self->port );
24             },
25             );
26              
27             sub accept_wwn {
28             my ( $self, $wwn ) = @_;
29             return $wwn =~ /^5006048/;
30             }
31              
32             has 'serial_number' => (
33             is => 'rw',
34             isa => 'Str',
35             lazy_build => 1,
36             trigger => sub {
37             my ( $self, $val ) = @_;
38             if ( length $val != 9 ) { croak "serial_number must be 9 digits" }
39             if ( $val =~ /\D/ ) { croak "serial_number must contain only digits" }
40             },
41             );
42             sub _build_serial_number {
43             my $self = shift;
44             my ( $serial, $port ) = wwn_to_serial_and_port( $self->normalized );
45             return $serial;
46             }
47              
48             has 'port' => (
49             is => 'rw',
50             isa => 'Str',
51             lazy_build => 1,
52             );
53             sub _build_port {
54             my $self = shift;
55             my ( $serial, $port ) = wwn_to_serial_and_port( $self->normalized );
56             return $port;
57             }
58              
59             sub wwn_to_serial_and_port {
60             my $wwn = Device::WWN::normalize_wwn( shift );
61             local $_ = $wwn;
62             s/^5006048// || croak "$wwn is not an EMC Symmetrix WWN";
63              
64             my @names = qw( AA BA AB BB );
65              
66             # last character is the port number
67             s/([a-f0-9])$//i || croak "Invalid WWN '$wwn'";
68             my $num = hex( $1 ) + 1;
69              
70             my $binary = unpack( "B*", pack( "H*", $_ ) );
71             $binary =~ s/(\d\d)$// or croak "Invalid WWN '$wwn'";
72             my $let = $names[ oct( '0b'.$1 ) ];
73              
74             my $serial = oct( '0b'.$binary );
75             return ( $serial, sprintf( '%02d%2s', $num, $let ) );
76             }
77              
78             sub serial_and_port_to_wwn {
79             my ( $serial, $port ) = @_;
80             croak "Serial number must be 9 digits" unless length( $serial ) == 9;
81             croak "Serial number must be all numeric" if $serial =~ /\D/;
82             $port =~ /^(\d+)([AB]{1,2})$/i or croak "Invalid port";
83             my %names = qw( AA 00 BA 01 AB 10 BB 11 A 00 B 01 );
84             croak "Invalid port '$port'" unless is_valid_port_number( $1 );
85             my $num = sprintf( '%x', $1 - 1 );
86             my $let = $names{ uc $2 } || croak "Invalid port '$port'";
87              
88             my $binary = sprintf( '%b', $serial );
89             $binary =~ s/(\d\d)$// or croak "Invalid serial number '$serial'";
90             $let = sprintf( '%x', oct( '0b'.$1.$let ) );
91              
92             return '5006048'.sprintf( '%x', oct( '0b'.$binary ) ).$let.$num;
93             }
94              
95             sub is_valid_port_number {
96             my $n = shift;
97             return 0 if $n < 1 || $n > 16;
98             return 0 if $n == 2;
99             return 0 if ( $n >= 7 && $n <= 10 );
100             return 1;
101             }
102              
103             sub _build_naa { return '5' }
104             sub _build_oui { return Device::OUI->new( '006048' ) }
105              
106             no Moose;
107             __PACKAGE__->meta->make_immutable;
108             1;
109              
110             =head1 NAME
111              
112             Device::WWN::EMC::Symmetrix - Device::WWN subclass for EMC Symmetrix WWNs
113              
114             =head1 DESCRIPTION
115              
116             This is a L<Device::WWN> subclass that handles WWNs from EMC Symmetrix storage
117             arrays.
118              
119             See L<Device::WWN|Device::WWN> for more information.
120              
121             =head1 METHODS
122              
123             =head2 accept_wwn( $wwn )
124              
125             This is called as a class method by L<Device::WWN> and returns a true value
126             if the WWN provided can be handled by this subclass.
127              
128             =head1 FUNCTIONS
129              
130             Although this module is entirely object oriented, there are a handful of
131             utility functions that you can import from this module if you find a need
132             for them. Nothing is exported by default, so if you want to import any of
133             them you need to say so explicitly:
134              
135             use Device::WWN qw( ... );
136              
137             You can get all of them by importing the ':all' tag:
138              
139             use Device::WWN ':all';
140              
141             The exporting is handled by L<Sub::Exporter|Sub::Exporter>.
142              
143             =head2 wwn_to_serial_and_port( $wwn )
144              
145             Given a Symmetrix WWN, returns the serial number and port.
146              
147             =head2 serial_and_port_to_wwn( $serial, $port )
148              
149             Given a serial number and port, returns the appropriate WWN.
150              
151             =head2 is_valid_port_number( $port_number );
152              
153             Given a port number (just the numeric part) returns true if it is a valid
154             port number.
155              
156             Valid Symmetrix Port Numbers:
157             Model Valid Ports
158             3330 03,14,15,16
159             3400/3830 01,04,05,12,13,16
160             3700/3930 03,04,05,06,11,12,13,14
161              
162             =head1 MODULE HOME PAGE
163              
164             The home page of this module is
165             L<http://www.jasonkohles.com/software/device-wwn>. This is where you can
166             always find the latest version, development versions, and bug reports. You
167             will also find a link there to report bugs.
168              
169             =head1 SEE ALSO
170              
171             L<Device::WWN|Device::WWN>
172              
173             L<http://www.jasonkohles.com/software/device-wwn>
174              
175             =head1 AUTHOR
176              
177             Jason Kohles C<< <email@jasonkohles.com> >>
178              
179             L<http://www.jasonkohles.com>
180              
181             =head1 COPYRIGHT AND LICENSE
182              
183             Copyright 2008, 2009 Jason Kohles
184              
185             This program is free software; you can redistribute it and/or modify it
186             under the same terms as Perl itself.
187              
188             =cut
189