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