X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FOyster%2FProvision%2FRackspace.pm;h=10f92fd41cd93561cdad81f7d8db5de96985d32f;hb=355db0c8c7f54f982795764a045fb2debeda0ec4;hp=0ede957dc29388321d5fd3ccdbddd82b7db25031;hpb=10d26b8dcd7ce5a0a6ecdb76e2ac361964f272b2;p=p5sagit%2FOyster.git diff --git a/lib/Oyster/Provision/Rackspace.pm b/lib/Oyster/Provision/Rackspace.pm index 0ede957..10f92fd 100644 --- a/lib/Oyster/Provision/Rackspace.pm +++ b/lib/Oyster/Provision/Rackspace.pm @@ -1,18 +1,92 @@ package Oyster::Provision::Rackspace; use Moose::Role; +use Carp; +use Net::RackSpace::CloudServers; +use Net::RackSpace::CloudServers::Server; +use MIME::Base64; requires 'config'; +has 'api_username' => ( is => 'ro', isa => 'Str', required => 1, lazy_build => 1); +sub _build_api_username { + return $ENV{CLOUDSERVERS_USER} if exists $ENV{CLOUDSERVERS_USER}; + confess "Need api_username or CLOUDSERVERS_USER in environment"; +} + +has 'api_password' => ( is => 'ro', isa => 'Str', required => 1, lazy_build => 1); +sub _build_api_password { + return $ENV{CLOUDSERVERS_KEY} if exists $ENV{CLOUDSERVERS_KEY}; + confess "Need api_password or CLOUDSERVERS_KEY in environment"; +} + +has '_rs' => ( is => 'rw', isa => 'Net::RackSpace::CloudServers', default => sub { + my $self = shift; + my $rs = Net::RackSpace::CloudServers->new( + user => $self->api_username, + key => $self->api_password, + ); + $rs; +}); + sub create { my $self = shift; - $self->config(); + # Do nothing if the server named $self->name already exists + return if scalar grep { $_->name eq $self->name } $self->_rs->get_server(); + + # Check the ssh pub key exists and is <10K + confess "SSH pubkey needs to exist" if !-f $self->pub_ssh; + my $pub_ssh = do { + local $/=undef; + open my $fh, '<', $self->pub_ssh or die "Cannot open ", $self->pub_ssh, ": $!"; + my $_data = <$fh>; + close $fh or die "Cannot close ", $self->pub_ssh, ": $!"; + $_data; + }; + confess "SSH pubkey needs to be < 10KiB" if length $pub_ssh > 10*1024; + + # Build the server + my $server = Net::RackSpace::CloudServers::Server->new( + cloudservers => $self->_rs, + name => $self->name, + flavorid => $self->size, + imageid => $self->image, + personality => [ + { + path => $self->pub_ssh, + contents => encode_base64($pub_ssh), + }, + ], + ); + my $newserver = $server->create_server; + warn "Server root password: ", $newserver->adminpass, "\n"; + + do { + $|=1; + my @tmpservers = $self->_rs->get_server_detail(); + $server = ( grep { $_->name eq $self->name } @tmpservers )[0]; + print "\rServer status: ", ($server->status || '?'), " progress: ", ($server->progress || '?'); + if ( ( $server->status // '' ) ne 'ACTIVE' ) { + print " sleeping.."; + sleep 2; + } + } while ( ( $server->status // '' ) ne 'ACTIVE' ); + + warn "Server public IP is: @{$server->public_address}\n"; + + # Connect to server and execute installation routines? + # Use Net::SSH? } sub delete { my $self = shift; - $self->config(); + # Die if the server named $self->name already exists + my ($server) = grep { $_->name eq $self->name } $self->_rs->get_server(); + confess "No such server: ", $self->name if !$server; + + # Goodbye cruel user! + $server->delete_server(); } sub resize { @@ -39,6 +113,18 @@ The following are required to instantiate a backend: =over +=item api_username + +The rackspace API username, or C<$ENV{RACKSPACE_USER}> will be used if that is +not given + +=item password + +This is your rackspace API Key + +The rackspace API key, or C<$ENV{RACKSPACE_KEY}> will be used if that is not +given + =item name The name of your new/existing rackspace server.