1 package Oyster::Provision::Rackspace;
3 use Net::RackSpace::CloudServers;
4 use Net::RackSpace::CloudServers::Server;
7 # TODO http://failverse.com/manually-creating-a-cloud-server-from-a-cloud-files-image/
8 # in order to use an already created image to build the server, a la EC2 way
12 has 'api_username' => ( is => 'ro', isa => 'Str', required => 1, lazy => 1, default => sub {
14 return $ENV{CLOUDSERVERS_USER} if exists $ENV{CLOUDSERVERS_USER};
15 return $self->config->{api_username}
16 or die "Need api_username or CLOUDSERVERS_USER in environment";
19 has 'api_password' => ( is => 'ro', isa => 'Str', required => 1, lazy => 1, default => sub {
21 return $ENV{CLOUDSERVERS_KEY} if exists $ENV{CLOUDSERVERS_KEY};
22 return $self->config->{api_password}
23 or die "Need api_password or CLOUDSERVERS_KEY in environment";
26 has '_rs' => ( is => 'rw', isa => 'Net::RackSpace::CloudServers', lazy => 1, default => sub {
29 Net::RackSpace::CloudServers->new(
30 user => $self->api_username,
31 key => $self->api_password,
36 "Could not instantiate a backend connection to RackSpace CloudServers.\n",
37 "Check the api_username and api_password on the configuration file\n";
45 die "Rackspace Provisioning backend requires a server name\n" if !defined $self->name;
47 # Do nothing if the server named $self->name already exists
48 return if scalar grep { $_->name eq $self->name } $self->_rs->get_server();
50 # Validate size and image
52 die "Rackspace Provisioning backend requires a server image\n" if !defined $self->image;
53 my @allowed_images = $self->_rs->get_image();
54 my $image_id = $self->image;
55 if ( !scalar grep { $_->{id} eq $image_id } @allowed_images ) {
56 die "Rackspace Provisioning backend requires a valid image id\nValid images:\n",
57 (map { sprintf("id %-10s -- %s\n", $_->{id}, $_->{name}) } @allowed_images),
61 die "Rackspace Provisioning backend requires a server size\n" if !defined $self->size;
62 my @allowed_flavors = $self->_rs->get_flavor();
63 my $flavor_id = $self->size;
64 if ( !scalar grep { $_->{id} eq $flavor_id } @allowed_flavors ) {
65 die "Rackspace Provisioning backend requires a valid size id\nValid flavors:\n",
66 (map { sprintf("id %-10s -- %s\n", $_->{id}, $_->{name}) } @allowed_flavors),
71 # Check the ssh pub key exists and is <10K
72 die "SSH pubkey needs to exist" if !-f $self->pub_ssh;
75 open my $fh, '<', $self->pub_ssh or die "Cannot open ", $self->pub_ssh, ": $!";
77 close $fh or die "Cannot close ", $self->pub_ssh, ": $!";
80 die "SSH pubkey needs to be < 10KiB" if length $pub_ssh > 10*1024;
83 my $server = Net::RackSpace::CloudServers::Server->new(
84 cloudservers => $self->_rs,
86 flavorid => $self->size,
87 imageid => $self->image,
90 path => '/root/.ssh/authorized_keys',
91 contents => encode_base64($pub_ssh),
95 my $newserver = $server->create_server;
96 warn "Server root password: ", $newserver->adminpass, "\n";
100 my @tmpservers = $self->_rs->get_server_detail();
101 $server = ( grep { $_->name eq $self->name } @tmpservers )[0];
102 print "\rServer status: ", ($server->status || '?'), " progress: ", ($server->progress || '?');
103 if ( ( $server->status // '' ) ne 'ACTIVE' ) {
107 } while ( ( $server->status // '' ) ne 'ACTIVE' );
109 warn "Server public IP is: @{$server->public_address}\n";
111 # Connect to server and execute installation routines?
118 # Die if the server named $self->name already exists
119 my ($server) = grep { $_->name eq $self->name } $self->_rs->get_server();
120 die "No such server: ", $self->name if !$server;
122 # Goodbye cruel user!
123 $server->delete_server();
138 Oyster::Provision::Rackspace -- Provision your Oyster on Rackspace
142 Use the Rackspace backend on your Oyster configuration file
144 =head1 REQUIRED PARAMETERS
146 The following are required to instantiate a backend:
152 The rackspace API username, or C<$ENV{RACKSPACE_USER}> will be used if that is
157 This is your rackspace API Key
159 The rackspace API key, or C<$ENV{RACKSPACE_KEY}> will be used if that is not
164 The name of your new/existing rackspace server.
168 The size ID of the rackspace server you want to create.
169 Use the following incantation to see them:
171 perl -MNet::RackSpace::CloudServers -e'
172 $r=Net::RackSpace::CloudServers->new(
173 user=>$ENV{CLOUDSERVERS_USER},
174 key=>$ENV{CLOUDSERVERS_KEY},
177 { "id $_->{id} ram $_->{ram} disk $_->{disk}\n" }
178 $r->get_flavor_detail
182 id 3 ram 1024 disk 40
183 id 4 ram 2048 disk 80
184 id 5 ram 4096 disk 160
185 id 6 ram 8192 disk 320
186 id 7 ram 15872 disk 620
190 The image ID of the rackspace server you want to create.
191 Use the following incantation to see them:
193 perl -MNet::RackSpace::CloudServers -e'
194 $r=Net::RackSpace::CloudServers->new(
195 user=>$ENV{CLOUDSERVERS_USER},
196 key=>$ENV{CLOUDSERVERS_KEY},
199 { "id $_->{id} name $_->{name}\n" }
202 id 29 name Windows Server 2003 R2 SP2 x86
203 id 69 name Ubuntu 10.10 (maverick)
204 id 41 name Oracle EL JeOS Release 5 Update 3
205 id 40 name Oracle EL Server Release 5 Update 4
206 id 187811 name CentOS 5.4
207 id 4 name Debian 5.0 (lenny)
208 id 10 name Ubuntu 8.04.2 LTS (hardy)
209 id 23 name Windows Server 2003 R2 SP2 x64
210 id 24 name Windows Server 2008 SP2 x64
211 id 49 name Ubuntu 10.04 LTS (lucid)
212 id 14362 name Ubuntu 9.10 (karmic)
213 id 62 name Red Hat Enterprise Linux 5.5
217 id 31 name Windows Server 2008 SP2 x86
218 id 51 name CentOS 5.5
219 id 14 name Red Hat Enterprise Linux 5.4
220 id 19 name Gentoo 10.1
221 id 28 name Windows Server 2008 R2 x64
222 id 55 name Arch 2010.05
224 Oyster only supports Linux images, specifically
225 Ubuntu 10.10 (maverick).
229 The public ssh key you would like copied to the
230 new server's C</root/.ssh/authorized_keys> file
231 to allow you to ssh in the box without providing