GBrowse
view release on metacpan or search on metacpan
lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm view on Meta::CPAN
eval {$self->ec2} or croak $@;
$self->log_info("Monitoring load at intervals of $poll sec\n");
while (sleep $poll) {
last if $killed;
my $load = $self->get_load();
$self->log_debug("Current load: $load req/s\n");
$self->adjust_instances($load);
$self->update_requests();
}
$self->log_info('Normal termination');
}
sub stop_daemon {
my $self = shift;
my $pid = $self->pid;
if (!$pid && (my $pidfile = $self->pidfile)) {
my $fh = IO::File->new($pidfile) or croak "No PID file; is daemon runnning?";
$pid = $fh->getline;
chomp($pid);
$fh->close;
}
unlink $self->pidfile if -e $self->pidfile;
kill TERM=>$pid if defined $pid;
}
#######################
# configuration
######################
sub conf_file {shift->{conf_file}}
sub load_table {
return shift->{options}{'LOAD TABLE'};
}
sub option {
my $self = shift;
my ($stanza,$option) = @_;
return $self->{options}{uc $stanza}{$option};
}
# given load, returns two element list of min_instances, max_instances
sub slaves_wanted {
my $self = shift;
my $load = shift;
my $lt = $self->load_table or croak 'no load table!';
my ($min,$max) = (0,0);
for my $l (sort {$a<=>$b} keys %$lt) {
($min,$max) = @{$lt->{$l}} if $load >= $l;
}
return ($min,$max);
}
sub slave_instance_type { shift->option('SLAVE','instance_type') || 'm1.large' }
sub slave_spot_bid { shift->option('SLAVE','spot_bid') || 0.08 }
sub slave_ports { my $p = shift->option('SLAVE','ports');
my @p = split /\s+/,$p;
return @p ? @p : (8101); }
sub slave_endpoint {
my $self = shift;
if ($self->running_as_instance) {
my $zone = $self->{instance_metadata}->endpoint;
return $zone;
} else {
my $region = $self->option('SLAVE','region') || 'us-east-1';
return "http://ec2.$region.amazonaws.com";
}
}
sub slave_zone {
my $self = shift;
if ($self->running_as_instance) {
return $self->{instance_metadata}->availabilityZone;
} else {
$self->option('SLAVE','availability_zone');
}
}
sub slave_image_id {
my $self = shift;
if ($self->running_as_instance) {
return $self->{instance_metadata}->imageId;
} else {
$self->option('SLAVE','image_id');
}
}
sub slave_data_snapshots {
my $self = shift;
return split /\s+/,$self->option('SLAVE','data_snapshots');
}
sub slave_block_device_mapping {
my $self = shift;
my $image = $self->ec2->describe_images($self->slave_image_id)
or die "Could not find image ",$self->slave_image_id;
my $root = $image->rootDeviceName;
my @root = grep {$_->deviceName eq $root} $image->blockDeviceMapping;
my @snaps = $self->slave_data_snapshots;
my @bdm;
DEVICE:
for my $major ('g'..'z') {
for my $minor (1..15) {
my $snap = shift @snaps or last DEVICE;
push @bdm,"/dev/sd${major}${minor}=${snap}::true";
}
}
return [@root,@bdm];
}
sub slave_subnet {
my $self = shift;
if ($self->running_as_instance) {
return eval {(values %{$self->{instance_metadata}->interfaces})[0]{subnetId}};
} else {
$self->option('SLAVE','subnet');
}
}
sub slave_ssh_key {
my $self = shift;
my $key = $self->ssh_key;
$key ||= $self->option('SLAVE','ssh_key');
return $key;
}
sub slave_security_group {
my $self = shift;
my $sg = $self->{slave_security_group};
return $sg if $sg;
my $ec2 = $self->ec2;
$sg = eval {$ec2->describe_security_groups(-name => "GBROWSE_SLAVE_$$")};
$sg ||= $ec2->create_security_group(-name => "GBROWSE_SLAVE_$$",
-description => 'Temporary security group for slave communications');
my $ip = $self->running_as_instance ? $self->internal_ip : $self->master_ip;
$self->log_debug(
$sg->authorize_incoming(-protocol => 'tcp',
-port => $_,
-source_ip => "$ip/32")
) foreach $self->slave_ports;
$self->log_debug(
$sg->authorize_incoming(-protocol => 'tcp',
-port => 22,
-source_ip=> "$ip/32"))
if $self->slave_ssh_key;
$sg->update or croak $ec2->error_str;
return $self->{slave_security_group} = $sg;
}
sub ec2 {
my $self = shift;
# create a new ec2 each time because security credentials may expire
my @credentials = $self->ec2_credentials;
return $self->{ec2} = VM::EC2->new(-endpoint => $self->slave_endpoint,
-raise_error => 1,
@credentials);
}
sub internal_ip {
my $self = shift;
return unless $self->running_as_instance;
return $self->{instance_metadata}->privateIpAddress;
}
sub master_security_group {
my $self = shift;
return unless $self->running_as_instance;
my $sg = ($self->{instance_metadata}->securityGroups)[0];
$sg =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
return $sg;
}
sub master_ip {
my $self = shift;
my $ip = $self->option('MASTER','external_ip');
$ip ||= $self->_get_external_ip;
return $ip;
}
# poll interval in seconds
sub master_poll {
my $self = shift;
my $pi = $self->option('MASTER','poll_interval');
return $pi * 60;
}
sub master_server_status_url {
my $self = shift;
return $self->option('MASTER','server_status_url')
|| 'http://localhost/server-status';
}
sub running_as_instance {
my $self = shift;
return -e '/var/lib/cloud/data/previous-instance-id'
&& head('http://169.254.169.254');
}
# update conf file with new snapshot images
sub update_data_snapshots {
my $self = shift;
my @snapshot_ids = @_;
my $timestamp = 'synchronized with local filesystem on '.localtime;
my $conf_file = $self->conf_file;
my ($user,$group) = (stat($conf_file))[4,5];
open my $in,'<',$conf_file or die "Couldn't open $conf_file: $!";
open my $out,'>',"$conf_file.new" or die "Couldn't open $conf_file: $!";
while (<$in>) {
chomp;
s/^(data_snapshots\s*=).*/$1 @snapshot_ids # $timestamp/;
print $out "$_\n";
}
close $in;
( run in 1.790 second using v1.01-cache-2.11-cpan-5a3173703d6 )