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