App-Diskd
view release on metacpan or search on metacpan
lib/App/Diskd.pm view on Meta::CPAN
this_ip => $ip,
temp_disk_list => [],
disks_by_ip => { $ip => {} },
update_time => {},
}, $class;
}
sub our_ip { (shift)->{this_ip} }
# We update local disk info in two phases, first creating a list to
# store them, then inserting the list into the live data all at once.
# This is so that we can handle disks being detached from the system
# between runs of blkid.
sub add_our_disk_info {
my ($self,$uuid,$label,$device) = @_;
my $listref = $self->{temp_disk_list};
# As a mnemonic for the order below, remember that UUIDs are more
# unique than labels, which in turn are more unique than device
# filenames.
push @$listref, [$uuid,$label,$device];
}
sub commit_our_disk_info {
my $self = shift;
my $ip = $self->{this_ip};
#warn "comitting new blkid data with " . (0+ @{$self->{temp_disk_list}}) .
# " entries\n";
$self->{update_time}->{$ip} = time();
$self->{disks_by_ip}->{$ip} = $self->{temp_disk_list};
$self->{temp_disk_list} = [];
# TODO: update "last seen" structures for each disk with a label/uuid.
# for each structure, map the label/uuid to [ip, timestamp] info.
}
sub known_hosts {
my $self = shift;
return keys %{$self->{disks_by_ip}};
}
sub disks_by_host {
my ($self,$host) = @_;
#warn "looking up host $host";
return undef unless exists $self->{disks_by_ip}->{$host};
return $self->{disks_by_ip}->{$host};
}
#
# The routines used to pack and unpack a list of disks for
# transmission could take any form, really. The key things to consider
# are that (a) arbitrary spoofed data can't result in us introducing
# security issues (so solutions that involve eval'ing the packed data
# are out, unless we validate that the data is in the expected form)
# and (b) we take into consideration quoting issues (such as not using
# spaces as separators, since they may appear in disk labels). As it
# happens, YAML can solve both of these problems for us. It may not
# make best use of space, but at least it's quick and easy to
# implement.
#
use YAML::XS;
# assume that we don't need to pack any disk list except our own
sub pack_our_disk_list {
my $self = shift;
my $ip = $self->{this_ip};
return Dump $self->{disks_by_ip}->{$ip};
}
# unpack incoming list of lists
sub unpack_disk_list {
my ($self,$host,$yaml) = @_;
my $ip = $self->{this_ip};
# We shouldn't get here if the calling routine is doing its job right
if ($host eq $ip) {
warn "Fatal: caller requested unpack disk list with our IP address";
return undef;
}
my $objref = Load $yaml;
# Do some basic type checking on the unpacked object. We expect an
# array of arrays.
unless (ref($objref) eq "ARRAY") {
warn "unpacked disk list is not an ARRAY";
return undef;
for (@$objref) {
unless (ref($_) eq "ARRAY") {
warn "unpacked disk element is not an ARRAY";
return undef;
}
}
}
$self->{update_time}->{$host} = time();
return $self->{disks_by_ip}->{$host} = $objref;
}
#
# The remaining packages are used simply to achieve a clean separation
# between different POE sessions and to encapsulate related methods
# without having to worry about namespace issues (like ensuring event
# names and handler routines are unique across all sessions). As a
# consequence of having distinct sessions for each program area, when
# we need to have inter-session communication, we need to use POE's
# post method. An alias is also used to identify each of the sessions.
#
( run in 3.301 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )