StorageDisplay

 view release on metacpan or  search on metacpan

lib/StorageDisplay/Collect.pm  view on Meta::CPAN

    my $self = shift;
    my $collector = shift;

    die "$collector not a StorageDisplay::Collect::Collector"
        if not $collector->isa("StorageDisplay::Collect::Collector");

    push @{$self->{_attr_collectors}}, $collector;
    foreach my $cn ($collector->provides) {
        if (exists($self->{_attr_collectors_by_provide}->{$cn})) {
            die "$cn provided by both ".$collector->module." and ".
                $self->{_attr_collectors_by_provide}->{$cn}->module;
        }
        $self->{_attr_collectors_by_provide}->{$cn} = $collector;
    }
}

sub open_cmd_pipe {
    my $self = shift;
    return $self->cmdreader->open_cmd_pipe(@_);
}

sub open_cmd_pipe_root {
    my $self = shift;
    return $self->cmdreader->open_cmd_pipe_root(@_);
}

sub open_file {
    my $self = shift;
    return $self->cmdreader->open_file(@_);
}

sub has_file {
    my $self = shift;
    return $self->cmdreader->has_file(@_);
}

sub cmdreader {
    my $self = shift;
    return $self->{_attr_cmdreader};
}

my @collectors;

sub new {
    my $class = shift;
    my $reader = shift // 'Local';

    if (ref($reader) eq '') {
        my $fullreadername = 'StorageDisplay::Collect::CMD::'.$reader;
        $reader = $fullreadername->new(@_);
    }

    my $self = {
        _attr_cmdreader => $reader,
        _attr_collectors => [],
        _attr_collectors_by_provide => {},
    };

    bless $self, $class;

    foreach my $cdata (@collectors) {
        my $cn = $cdata->{name};
        $cn->new($cdata, $self);
    }
    return $self;
}

sub registerCollectorModule {
    my $class = shift;
    my $collector = shift;

    #my $collector = caller 0;
    #print STDERR "Registering $collector from ".(caller 0)."\n";
    my $info = { name => $collector, @_ };
    foreach my $entry (qw(provides requires)) {
        next if not exists($info->{$entry});
        if (ref($info->{$entry}) eq "") {
            $info->{$entry} = [ $info->{$entry} ];
        }
    }
    push @collectors, $info;
}

# Main collect function
#
# It will iterate on the collectors, respecting dependencies.
sub collect {
    my $self = shift;
    my $req = shift;
    my $infos = {};

    $infos = $self->cmdreader->data_init($infos);

    # 0/undef : not computed
    # 1 : computed
    # 2 : computing
    # 3 : N/A
    my $collector_state = {};

    my $load;
    $load = sub {
        my $col = shift;
        $collector_state->{$_} = 2 for $col->provides;
        foreach my $cname ($col->requires) {
            #print STDERR "  preloading $cname\n";
            my $state = $collector_state->{$cname};
            if (not defined($state)) {
                my $collector = $self->collector($cname);
                die "E: No $cname collector available for ".$col->module."\n"
                    if not defined($collector);
                $load->($collector);
            } elsif ($collector_state->{$cname} == 1) {
                next
            } else {
                die "Loop in collectors requires ($cname required in $col->name)";
            }
        }
        # are files present?
        my @missing_files =
            grep {
                not $self->has_file($_);
            } $col->depends('files');
        if (scalar(@missing_files)) {

lib/StorageDisplay/Collect.pm  view on Meta::CPAN

    return @devs;
}

sub parse {
    my $parser = shift;
    my $closure = shift;
    my $res = shift // {};

}

my %name = (
    'Size (in MB)' => 'size-mb',
    'Volume ID' => 'id',
    'Volume wwid' => 'wwid',
    'Status of volume' => 'status',
    );

sub collect {
    my $self = shift;
    my $infos = shift;
    my $dh;
    my $lsi={};

    my @devs=$self->select($infos);


    my $parse_section = sub {
        my $self = shift;
        my $line = shift;
        if ($line eq 'Controller information') {
            #$self->push_new_section->($parse_controller, $closure_controller);
        } elsif ($line eq 'IR Volume information') {
            #return (1, $parse_volumes);
        } elsif ($line eq 'Physical device information') {
            #return (1, $parse_phydev);
        } elsif ($line eq 'Enclosure information') {
            #return (1, $parse_phydev);
        } elsif ($line =~ /SAS2IRCU:/) {
            if ($line eq 'SAS2IRCU: Command DISPLAY Completed Successfully.'
                or $line eq 'SAS2IRCU: Utility Completed Successfully.') {
            } else {
                print STDERR "W: sas2ircu: $line\n";
            }
        } else {
            #if (scalar(keys %$l) != 0) {
            #    print  STDERR "W: sas2ircu: unknown line: $line\n";
            #}
        }
        return 1;
    };


    foreach my $dev (@devs) {
        $dh=$self->open_cmd_pipe_root('sas2ircu', $dev, 'DISPLAY');
        my $l={};
        my $state = 0;
        my $wwid = {};
        my $guid = {};

        my $data = undef;
        my $secdata = undef;

        my $closure=sub {} ;
        my $subclosure=sub {} ;
        while(defined(my $line=<$dh>)) {
            chomp($line);
            next if $line =~ /^[\s-]*$/;
            if ($line =~ /^(Controller) information$/
                || $line =~ /^(Enclosure) information$/) {
                my $section = lc($1);
                $subclosure->($data);
                $closure->($data);
                $data = {};
                $subclosure = sub {};
                $closure = sub {
                    my $curdata = shift;
                    if (exists($l->{$section})) {
                        print STDERR "E: sas2ircu: duplicate section: $line\n";
                    }
                    $l->{$section}=$curdata;
                    return {};
                };
                $state=10;
            } elsif ($line =~ /^IR (Volume) information$/
                     || $line =~ /^Physical (device) information$/) {
                my $section = lc($1).'s';
                $subclosure->($data);
                $closure->($data);
                $secdata=[];
                $subclosure = sub { };
                $closure=sub {
                    my $data = shift;
                    if (exists($l->{$section})) {
                        print STDERR "E: sas2ircu: duplicate section: $line\n";
                    }
                    $l->{$section}=$secdata;
                    return
                };
            } elsif ($line =~ /^IR volume ([^\s])+$/) {
                my $name = $1;
                $subclosure->($data);
                $data = {
                    name => $name,
                };
                $subclosure = sub {
                    my $data = shift;
                    push @$secdata, $data;
                };
            } elsif ($line =~ /^Device is a Hard disk$/) {
                $subclosure->($data);
                $data = {};
                $subclosure = sub {
                    my $data = shift;
                    push @$secdata, $data;
                };
            } elsif ($line =~ /^Initiator at ID .*$/) {
            } elsif ($line =~ /^SAS2IRCU: .* Completed Successfully.$/) {
            } elsif ($line =~ /^[^\s]/) {
                if ($state != 0) {
                    print STDERR "W: sas2ircu: unknown line: $line\n";
                }
            } elsif ($line =~ /^\s+([^\s][^:]*[^\s])\s*:\s+([^\s].*)$/) {
                my $k = $1;
                my $v = $2;
                if ($k =~ m,^PHY\[([^\]]+)\] Enclosure#/Slot#,) {
                    my $phy=$1;
                    my ($e, $s) = split(':', $v);
                    $data->{PHY}->{$phy} = { enclosure => $e, slot => $s };
                    next;
                } elsif ($k eq 'Size (in MB)/(in sectors)') {
                    my ($s1, $s2) = split('/', $v);
                    $data->{'size-mb'}=$s1;
                    $data->{'size-s'}=$s2;
                    $data->{'size'}=$s2 * 512;
                    next;
                }
                $k = $name{$k} // $k;
                $k =~ s/\s*[#]//;
                $k = lc($k);
                $k =~ s/\s+/-/g;
                if ($k eq 'guid') {
                    $guid->{$v}=1;
                } elsif ($k eq 'wwid') {
                    $wwid->{$v}=1;
                }
                $data->{$k}=$v;
            }
        }
        $subclosure->($data);
        $closure->($data);
        close $dh;
        $dh=$self->open_cmd_pipe(qw(find /sys/devices -name sas_address));
        my @lines=<$dh>;
        for my $line (sort @lines) {
            chomp($line);
            my $dh2 = $self->open_file($line)
                or die "Cannot open $line: $!\n";
            my $addr=<$dh2>;
            close $dh2;
            chomp($addr);
            $addr =~ s/^0x//;
            if (defined($wwid->{$addr})) {
                my $dir = $line;
                $dir =~ s/sas_address/block/;
                my $dh3 = $self->open_cmd_pipe('ls', '-1', $dir);
                my @dirs=<$dh3>;
                close($dh3);
                if (scalar(@dirs) != 1) {
                    print STDERR "E: sas2ircu: bad number of block devices for $addr\n";
                } else {
                    chomp($l->{wwid}->{$addr} = $dirs[0]);
                }
            }
        }



( run in 0.935 second using v1.01-cache-2.11-cpan-df04353d9ac )