view release on metacpan or search on metacpan
dan/oncall/bin/cal view on Meta::CPAN
$0 name [--zone timezone] [--level number] \
[--year year] [--month month] [--grep regex]
=cut
my %o = MYDan::Util::OptConf->load()
->get( qw( year=i month=s zone=s level=i grep=s ) )->dump;
my $dt = DateTime->now()->set_time_zone( $o{zone} ||= $MYDan::Oncall::LTZ )
->set( day => 1, map { $_ => 0 } qw( hour minute second ) );
my ( $year, $month, $grep, %busy ) = @o{ qw( year month grep ) };
if ( $year ) { $dt->set( year => $year < 1000 ? $year += 2000 : $year ) }
else { $year = $dt->year }
if ( $month )
{
if ( $month !~ /^\d+$/ )
{
for ( 0 .. $#MON )
{
dan/oncall/bin/cal view on Meta::CPAN
my $policy = MYDan::Oncall::Policy->new( "$o{data}/$ARGV[0]" );
my @level = 1 .. ( $o{level} || 3 );
my $end = $dt->clone->add( months => 1 )->epoch;
for ( my ( $now, $then ) = $dt->epoch; $now < $end; $now = $then )
{
my ( $month, $day ) = map { $dt->$_ } qw( month day );
$then = $dt->add( days => 1 )->epoch;
$policy->set( $now, $then );
$busy{$month}{$day} = 1 if grep { $_->{item} =~ $grep }
map { values %{ $policy->list( $_ ) } } @level;
}
}
MYDan::Oncall::Calendar->new( $year, %busy )->print( $month );
exit 0;
lib/MYDan/Util/MIO/CMD.pm view on Meta::CPAN
Returns HASH of HASH of nodes. First level is indexed by type
( I<stdout>, I<stderr>, or I<error> ). Second level is indexed by message.
=cut
sub run
{
local $| = 1;
my $self = shift;
my @node = keys %$self;
my ( $run, $ext, %run, %result, %busy ) = ( 1, "$Script.$$", %RUN, @_ );
my ( $max, $timeout, $interchange ) = @run{ qw( max timeout interchange ) };
my $input = defined $run{input} ? $run{input} : -t STDIN ? '' : <STDIN>;
$SIG{INT} = $SIG{TERM} = sub
{
print STDERR "killed\n";
$run = 0;
};
for ( my $time = time; $run && ( @node || %busy ); )
{
$run = 0 if time - $time > $timeout;
while ( @node && keys %busy < $max )
{
my $node = shift @node;
my $log = "/tmp/$node.$ext";
my $cmd = $self->{$node};
my @cmd = map { my $t = $_; $t =~ s/$interchange/$node/g; $t } @$cmd;
if ( $run{noop} )
{
print join ' ', @cmd, "\n";
next;
}
print "$node started.\n" if $run{verbose};
if ( my $pid = fork() ) { $busy{$pid} = [ $log, $node ]; next }
open STDOUT, ">>$log";
open STDERR, ">>$log";
exec sprintf join ' ', @cmd;
exit 0;
}
for ( keys %busy )
{
my $pid = waitpid( -1, WNOHANG );
next if $pid <= 0;
my $stat = $? >> 8;
my ( $log, $node ) = @{ delete $busy{$pid} };
print "$node done.\n" if $run{verbose};
tie my @log, 'Tie::File', $log,recsep => "\n";
my $tmp = join "\n", @log;
$tmp =~ s/$node/$interchange/g if $run{xx};
push @{ $result{output}{ join "\n", $tmp, "--- $stat", '' } }, $node;
unlink $log;
}
}
kill 9, keys %busy;
push @{ $result{output}{killed} }, map{ $busy{$_}[1]}keys %busy;
push @{ $result{output}{norun} }, @node;
unlink glob "/tmp/*.$ext";
unlink $input if $input && -f $input;
return wantarray ? %result : \%result;
}
1;
lib/MYDan/Util/MIO/SSH.pm view on Meta::CPAN
user : ( default logname ) connect as user
pass : password
=cut
sub run
{
local $/ = "\n";
my $self = shift;
my @node = keys %$self;
my ( $run, %run, %result, %busy ) = ( 1, %RUN, @_ );
my ( $ext, $prompt ) = ( "$Script.$$", 'password:' );
my ( $max, $timeout, $user, $sudo, $pass, $input ) =
@run{ qw( max timeout user sudo pass input ) };
my $percent = MYDan::Util::Percent->new( scalar @node, 'run ..' );
$SIG{INT} = $SIG{TERM} = sub
{
print STDERR "killed\n";
$run = 0;
};
my %hosts = MYDan::Util::Hosts->new()->match( @node );
my $p = MYDan::Util::Proxy->new( "$MYDan::PATH/etc/util/conf/proxy" );
do
{
while ( @node && keys %busy < $max )
{
my $node = shift @node;
my $cmd = $self->{$node};
my $log = "/tmp/$node.$ext";
my %x = $p->search( $hosts{$node} );
my $ssh = $user ? "$SSH -l $user $hosts{$node} " : "$SSH $hosts{$node} ";
$ssh.= " -o ProxyCommand='nc -X 5 -x $x{$hosts{$node}} %h %p' " if $x{$hosts{$node}};
if( @$cmd )
{
$ssh .= join ' ',
$sudo ? map { "sudo -p '$prompt' -u $sudo $_" } @$cmd : @$cmd;
}
else { $ssh .= " < $input"; }
if ( $run{noop} ) { warn "$ssh\n"; next }
if ( my $pid = fork() ) { $busy{$pid} = [ $log, $node ]; next }
my ( $exp, %expect ) = Expect->new();
if( $pass->{$node} && ref $pass->{$node} )
{
%expect = %{$pass->{$node}};
for( keys %expect )
{
next unless $expect{$_} =~ /googlecode\s*:\s*(\w+)/;
$expect{$_} = Authen::OATH->new->totp( decode_base32( $1 ));
lib/MYDan/Util/MIO/SSH.pm view on Meta::CPAN
if ( $exp->spawn( $ssh ) )
{
$exp->expect( $timeout,
map{ my $v = $expect{$_};[ qr/$_/ => sub { $exp->send( "$v\n" ); exp_continue; } ] }keys %expect
);
}
exit 0;
}
for ( keys %busy )
{
my $pid = waitpid( -1, WNOHANG );
next if $pid <= 0;
my $stat = $? >> 8;
next unless my $data = delete $busy{$pid};
$percent->add()->print() if $run{verbose};
my ( $log, $node ) = @$data;
tie my @log, 'Tie::File', $log;
my @i = grep { $log[$_] =~ /$prompt/ } 0 .. $#log;
splice @log, 0, $i[-1] + 1 if @i;
unless( $ENV{MYDan_DEBUG} )
lib/MYDan/Util/MIO/SSH.pm view on Meta::CPAN
@log = grep { $_ !~ m{Warning: Permanently added .+ to the list of known hosts\.}m } @log;
@log = grep { $_ !~ m{Pseudo-terminal will not be allocated because stdin is not a terminal\.}m } @log;
pop @log if @log && $log[-1] =~ /^Last login: .*\d+:\d+:\d+/;
}
my $end = $input ? '' : "--- $stat\n";
push @{ $result{output}{ join "\n", @log, $end } }, $node if @log;
unlink $log;
}
}
while $run && ( @node || %busy );
kill 9, keys %busy;
push @{ $result{output}{killed} }, map{ $busy{$_}[1]}keys %busy;
push @{ $result{output}{norun} }, @node;
unlink glob "/tmp/*.$ext";
unlink $input if $input && -f $input;
return wantarray ? %result : \%result;
}
1;
lib/MYDan/Util/MIO/TCP.pm view on Meta::CPAN
=cut
sub run
{
confess "poll: $!" unless my $poll = IO::Poll->new();
local $| = 1;
local $/ = undef;
my $self = shift;
my @node = keys %$self;
my ( %run, %result, %buffer, %busy ) = ( %RUN, @_ );
my ( $log, $max, $timeout, $input ) = @run{ qw( log max timeout input ) };
$input ||= -t STDIN ? '' : <STDIN>;
for ( my $time = time; @node || $poll->handles; )
{
if ( time - $time > $timeout ) ## timeout
{
for my $sock ( keys %busy )
{
$poll->remove( $sock );
eval { $sock->shutdown( 2 ) };
push @{ $result{error}{timeout} }, delete $busy{$sock};
}
print $log "timeout!\n";
last;
}
while ( @node && keys %busy < $max )
{
my $node = shift @node;
my %inet =
(
PeerAddr => $node, Blocking => 0, Timeout => $timeout,
Proto => 'tcp', Type => SOCK_STREAM,
);
my $sock = $self->{$node}
? IO::Socket::INET->new( %inet )
: IO::Socket::UNIX->new( %inet );
unless ( $sock )
{
push @{ $result{error}{ "socket: $!" } }, $node;
next;
}
$poll->mask( $sock => POLLIN | POLLOUT );
$busy{$sock} = $node;
print $log "$node started.\n" if $run{verbose};
}
$poll->poll( $MAX{period} );
for my $sock ( $poll->handles( POLLIN ) ) ## read
{
my $buffer; $sock->recv( $buffer, $MAX{buffer} );
$buffer{$sock} .= $buffer;
}
for my $sock ( $poll->handles( POLLOUT ) ) ## write
{
$sock->send( $input ) if defined $input;
$poll->mask( $sock, $poll->mask( $sock ) & ~POLLOUT );
eval { $sock->shutdown( 1 ) };
}
for my $sock ( $poll->handles( POLLHUP ) ) ## done
{
my $node = delete $busy{$sock};
push @{ $result{mesg}{ delete $buffer{$sock} } }, $node;
$poll->remove( $sock );
eval { $sock->shutdown( 0 ) };
print $log "$node done.\n" if $run{verbose};
}
}
push @{ $result{error}{'not run'} }, @node if @node;
return wantarray ? %result : \%result;
lib/MYDan/Util/MIO/UDP.pm view on Meta::CPAN
=cut
sub run
{
confess "poll: $!" unless my $poll = IO::Poll->new();
local $| = 1;
local $/ = undef;
my $self = shift;
my @node = keys %$self;
my ( %run, %result, %busy ) = ( resp => 1, %RUN, @_ );
my ( $log, $max, $timeout, $input, $resp ) =
@run{ qw( log max timeout input resp ) };
$input ||= -t STDIN ? '' : <STDIN>;
for ( my $time = time; @node || $poll->handles; )
{
if ( time - $time > $timeout ) ## timeout
{
for my $sock ( keys %busy )
{
$poll->remove( $sock );
eval { $sock->shutdown( 2 ) };
push @{ $result{error}{timeout} }, delete $busy{$sock};
}
print $log "timeout!\n";
last;
}
while ( @node && keys %busy < $max )
{
my $node = shift @node;
my %inet =
(
PeerAddr => $node, Blocking => 0, Timeout => $timeout,
Proto => 'udp', Type => SOCK_DGRAM,
);
my $sock = $self->{$node}
? IO::Socket::INET->new( %inet )
lib/MYDan/Util/MIO/UDP.pm view on Meta::CPAN
push @{ $result{error}{ "socket: $!" } }, $node;
next;
}
$sock->send( $input ) if defined $input;
print $log "$node started.\n" if $run{verbose};
if ( $resp )
{
$poll->mask( $sock => POLLIN );
$busy{$sock} = $node;
}
else
{
eval { $sock->shutdown( 2 ) };
print $log "$node done.\n" if $run{verbose};
}
}
next unless $resp;
$poll->poll( $MAX{period} );
for my $sock ( $poll->handles( POLLIN ) ) ## read
{
my $buffer; $sock->recv( $buffer, $MAX{buffer} );
my $node = delete $busy{$sock};
push @{ $result{mesg}{$buffer} }, $node;
$poll->remove( $sock );
eval { $sock->shutdown( 2 ) };
print $log "$node done.\n" if $run{verbose};
}
}
push @{ $result{error}{'not run'} }, @node if @node;
return wantarray ? %result : \%result;
lib/MYDan/Util/Phasic.pm view on Meta::CPAN
{
my ( $h, $i ) = $w8queue[1]->dequeue( 2 );
$w8{$h} = $i; $count --;
last unless $count;
}
my %src = map { $_ => $w8{$_} } @{ $self->{src} };
my %dst = map { $_ => $w8{$_} } @{ $self->{dst} };
my %quiesce = map { $_ => 1 } @{ $self->{quiesce} };
my ( %multi, %busy, %err ) = map{ $_ => $MULTI }keys %src;
for ( my $now = time; %dst || %busy; sleep $POLL )
{
while ( $queue[1]->pending() )
{
my ( $src, $dst, $ok, $info ) = $queue[1]->dequeue_nb( 4 );
delete @busy{ $src, $dst };
$multi{$src} ++ if defined $src{$src};
$src{$src} = $w8{$src} unless $quiesce{$src};
if ( $ok )
{
unless( $quiesce{$dst} )
{
$src{$dst} = $w8{$dst};
lib/MYDan/Util/Phasic.pm view on Meta::CPAN
}
if ( $timeout && time - $now > $timeout )
{
map{
unless( defined $multi{$_} )
{
$err{$_} = $retry +1;
$log->say( "$_: timeout" );
}
}keys %busy, keys %dst; last;
}
elsif ( %src && %dst )
{
my $dst = ( keys %dst )[ int( rand time ) % 2 ? -1 : 0 ];
my $w8 = $busy{$dst} = delete $dst{$dst};
my %dist = map { $_ => abs( $w8{$_} - $w8 ) }keys %src;
my $src = ( sort { $dist{$a} <=> $dist{$b} } keys %dist )[0];
$busy{$src} = delete $src{$src};
$log->say( "$src => $dst: RSYNC" );
$queue[0]->enqueue( $src, $dst );
}
elsif( $MULTI && %dst && ( scalar keys %dst ) > $split )
{
next unless my @multi = grep{ $multi{$_} > 0 }keys %multi;
my $dst = ( keys %dst )[ int( rand time ) % 2 ? -1 : 0 ];
my $w8 = $busy{$dst} = delete $dst{$dst};
my %dist = map { $_ => abs( $w8{$_} - $w8 ) }@multi;
my $src = ( sort { $dist{$a} <=> $dist{$b} } keys %dist )[0];
$multi{$src} --;
$log->say( "$src => $dst: MULTI" );
$queue[0]->enqueue( $src, $dst );
}
}
$self->{failed} = [ grep { $err{$_} > $retry } keys %err ];
lib/MYDan/VSSH.pm view on Meta::CPAN
{
my ( $class, %self ) = @_;
$self{config} = +{};
bless \%self, ref $class || $class;
}
sub run
{
my ( $this, %run, %busy ) = ( shift, %RUN, @_ );
my $history = MYDan::VSSH::History->new();
my $execute = MYDan::VSSH::Execute->new( node => $this->{node} );
my $print = MYDan::VSSH::Print->new();
$print->welcome();
my $audit = $run{audit};
my $c = scalar @{$this->{node}};
while ( 1 )
{