Die, Confess! Or the other way around?
[p5sagit/Oyster.git] / lib / Oyster / Provision / Rackspace.pm
CommitLineData
c9ecd647 1package Oyster::Provision::Rackspace;
3ded6347 2use Moose::Role;
4bd125ea 3use Net::RackSpace::CloudServers;
4use Net::RackSpace::CloudServers::Server;
5use MIME::Base64;
3ded6347 6
7requires 'config';
8
189564ce 9has 'api_username' => ( is => 'ro', isa => 'Str', required => 1, lazy_build => 1);
10sub _build_api_username {
758d921f 11 return $ENV{CLOUDSERVERS_USER} if exists $ENV{CLOUDSERVERS_USER};
370470b2 12 die "Need api_username or CLOUDSERVERS_USER in environment";
e4c30324 13}
8a0402ec 14
189564ce 15has 'api_password' => ( is => 'ro', isa => 'Str', required => 1, lazy_build => 1);
16sub _build_api_password {
758d921f 17 return $ENV{CLOUDSERVERS_KEY} if exists $ENV{CLOUDSERVERS_KEY};
370470b2 18 die "Need api_password or CLOUDSERVERS_KEY in environment";
189564ce 19}
4bd125ea 20
1f1bb35e 21has '_rs' => ( is => 'rw', isa => 'Net::RackSpace::CloudServers', default => sub {
4bd125ea 22 my $self = shift;
23 my $rs = Net::RackSpace::CloudServers->new(
24 user => $self->api_username,
8a0402ec 25 key => $self->api_password,
4bd125ea 26 );
27 $rs;
28});
29
3ded6347 30sub create {
31 my $self = shift;
32
4bd125ea 33 # Do nothing if the server named $self->name already exists
34 return if scalar grep { $_->name eq $self->name } $self->_rs->get_server();
35
36 # Check the ssh pub key exists and is <10K
370470b2 37 die "SSH pubkey needs to exist" if !-f $self->pub_ssh;
4bd125ea 38 my $pub_ssh = do {
39 local $/=undef;
40 open my $fh, '<', $self->pub_ssh or die "Cannot open ", $self->pub_ssh, ": $!";
41 my $_data = <$fh>;
42 close $fh or die "Cannot close ", $self->pub_ssh, ": $!";
43 $_data;
44 };
370470b2 45 die "SSH pubkey needs to be < 10KiB" if length $pub_ssh > 10*1024;
4bd125ea 46
47 # Build the server
48 my $server = Net::RackSpace::CloudServers::Server->new(
6895749d 49 cloudservers => $self->_rs,
50 name => $self->name,
51 flavorid => $self->size,
52 imageid => $self->image,
53 personality => [
4bd125ea 54 {
83928564 55 path => '/root/.ssh/authorized_keys',
4bd125ea 56 contents => encode_base64($pub_ssh),
57 },
6895749d 58 ],
4bd125ea 59 );
355db0c8 60 my $newserver = $server->create_server;
61 warn "Server root password: ", $newserver->adminpass, "\n";
4bd125ea 62
9e1b1d26 63 do {
64 $|=1;
65 my @tmpservers = $self->_rs->get_server_detail();
66 $server = ( grep { $_->name eq $self->name } @tmpservers )[0];
67 print "\rServer status: ", ($server->status || '?'), " progress: ", ($server->progress || '?');
68 if ( ( $server->status // '' ) ne 'ACTIVE' ) {
69 print " sleeping..";
70 sleep 2;
71 }
72 } while ( ( $server->status // '' ) ne 'ACTIVE' );
73
2bfa7038 74 warn "Server public IP is: @{$server->public_address}\n";
4bd125ea 75
76 # Connect to server and execute installation routines?
77 # Use Net::SSH?
3ded6347 78}
79
3ded6347 80sub delete {
81 my $self = shift;
82
4bd125ea 83 # Die if the server named $self->name already exists
84 my ($server) = grep { $_->name eq $self->name } $self->_rs->get_server();
370470b2 85 die "No such server: ", $self->name if !$server;
4bd125ea 86
87 # Goodbye cruel user!
88 $server->delete_server();
3ded6347 89}
90
91sub resize {
92 my $self = shift;
93
94 $self->config();
95}
c9ecd647 96
971;
dd69a60d 98
99__END__
100
101=head1 NAME
102
103Oyster::Provision::Rackspace -- Provision your Oyster on Rackspace
104
105=head1 SYNOPSIS
106
107Use the Rackspace backend on your Oyster configuration file
108
109=head1 REQUIRED PARAMETERS
110
111The following are required to instantiate a backend:
112
113=over
114
4bd125ea 115=item api_username
116
117The rackspace API username, or C<$ENV{RACKSPACE_USER}> will be used if that is
118not given
119
8a0402ec 120=item password
121
122This is your rackspace API Key
4bd125ea 123
124The rackspace API key, or C<$ENV{RACKSPACE_KEY}> will be used if that is not
125given
126
dd69a60d 127=item name
128
129The name of your new/existing rackspace server.
130
131=item size
132
133The size ID of the rackspace server you want to create.
134Use the following incantation to see them:
135
136 perl -MNet::RackSpace::CloudServers -e'
137 $r=Net::RackSpace::CloudServers->new(
138 user=>$ENV{CLOUDSERVERS_USER},
139 key=>$ENV{CLOUDSERVERS_KEY},
140 );
141 print map
142 { "id $_->{id} ram $_->{ram} disk $_->{disk}\n" }
143 $r->get_flavor_detail
144 '
145 id 1 ram 256 disk 10
146 id 2 ram 512 disk 20
147 id 3 ram 1024 disk 40
148 id 4 ram 2048 disk 80
149 id 5 ram 4096 disk 160
150 id 6 ram 8192 disk 320
151 id 7 ram 15872 disk 620
152
153=item image
154
155The image ID of the rackspace server you want to create.
156Use the following incantation to see them:
157
158 perl -MNet::RackSpace::CloudServers -e'
159 $r=Net::RackSpace::CloudServers->new(
160 user=>$ENV{CLOUDSERVERS_USER},
161 key=>$ENV{CLOUDSERVERS_KEY},
162 );
163 print map
164 { "id $_->{id} name $_->{name}\n" }
165 $r->get_image_detail
166 '
167 id 29 name Windows Server 2003 R2 SP2 x86
168 id 69 name Ubuntu 10.10 (maverick)
169 id 41 name Oracle EL JeOS Release 5 Update 3
170 id 40 name Oracle EL Server Release 5 Update 4
171 id 187811 name CentOS 5.4
172 id 4 name Debian 5.0 (lenny)
173 id 10 name Ubuntu 8.04.2 LTS (hardy)
174 id 23 name Windows Server 2003 R2 SP2 x64
175 id 24 name Windows Server 2008 SP2 x64
176 id 49 name Ubuntu 10.04 LTS (lucid)
177 id 14362 name Ubuntu 9.10 (karmic)
178 id 62 name Red Hat Enterprise Linux 5.5
179 id 53 name Fedora 13
180 id 17 name Fedora 12
181 id 71 name Fedora 14
182 id 31 name Windows Server 2008 SP2 x86
183 id 51 name CentOS 5.5
184 id 14 name Red Hat Enterprise Linux 5.4
185 id 19 name Gentoo 10.1
186 id 28 name Windows Server 2008 R2 x64
187 id 55 name Arch 2010.05
188
189Oyster only supports Linux images, specifically
190Ubuntu 10.10 (maverick).
191
192=item pub_ssh
193
194The public ssh key you would like copied to the
195new server's C</root/.ssh/authorized_keys> file
196to allow you to ssh in the box without providing
197a root password.
198
199=back
200
201=cut