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