ggoodale-rackspace_cloud 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -7,7 +7,7 @@ Example:
7
7
  => nil
8
8
  >> cloud.servers
9
9
  => []
10
- >> new_server = cloud.create_server('development', 1, 8) # create a 256MB Ubunty 9.04 instance)
10
+ >> new_server = cloud.create_server('development', 1, 8) # create a 256MB Ubuntu 9.04 instance)
11
11
  => #<RackspaceCloud::Server:0x1054a78 @image=#<RackspaceCloud::Image:0x10598e8 @name="Ubuntu 9.04 (jaunty)", @updated="2009-07-20T09:14:37-05:00", @created="2009-07-20T09:14:37-05:00", @status="ACTIVE", @rackspace_id=8>, @public_ips=["174.xxx.xxx.xxx"], @flavor=#<RackspaceCloud::Flavor:0x105d40c @name="256 slice", @ram=256, @disk=10, @rackspace_id=1>, @name="development", @progress=80, @adminPass="developmentU5fG3", @host_id="a7765fde333eead221", @private_ips=["10.xxx.xxx.xxx"], @rackspace_id=1, @status="BUILD">
12
12
 
13
13
  ... wait a while ...
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -26,29 +26,6 @@ module RackspaceCloud
26
26
  #This should eventually check the versions and raise an APIVersionError if there's a mismatch.
27
27
  end
28
28
 
29
- # storage for the lists of flavors and images we request at auth time
30
- FLAVORS = {}
31
- def RackspaceCloud.populate_flavors
32
- request("/flavors/detail")['flavors'].each do |flavor|
33
- FLAVORS[flavor['id']] = RackspaceCloud::Flavor.new(flavor)
34
- end
35
- nil
36
- end
37
-
38
- IMAGES = {}
39
- def RackspaceCloud.populate_images
40
- request("/images/detail")['images'].each do |image|
41
- IMAGES[image['id']] = RackspaceCloud::Image.new(image)
42
- end
43
- nil
44
- end
45
-
46
- LIMITS = {}
47
- def RackspaceCloud.get_limits
48
- LIMITS.merge!(request("/limits")['limits'])
49
- nil
50
- end
51
-
52
29
  def RackspaceCloud.request_authorization(user, access_key)
53
30
  session = Patron::Session.new
54
31
  session.base_url = BASE_AUTH_URI
@@ -59,48 +36,9 @@ module RackspaceCloud
59
36
 
60
37
  case response.status
61
38
  when 204 # "No Content", which means success
62
- @server_management_url = response.headers['X-Server-Management-Url']
63
- @storage_url = response.headers['X-Storage-Url']
64
- @storage_token = response.headers['X-Storage-Token']
65
- @cdn_management_url = response.headers['X-CDN-Management-Url']
66
- @auth_token = response.headers['X-Auth-Token']
67
- @@authorized = true
39
+ response.headers
68
40
  else
69
41
  raise AuthorizationError, "Error during authorization: #{response.status}"
70
42
  end
71
- nil
72
- end
73
-
74
- def RackspaceCloud.request(path, options={})
75
- raise RuntimeError, "Please authorize before using by calling connect()" unless defined?(@@authorized) && @@authorized
76
- @session ||= begin
77
- s = Patron::Session.new
78
- s.base_url = @server_management_url
79
- s.headers['X-Auth-Token'] = @auth_token
80
- s.headers["User-Agent"] = "rackspacecloud_ruby_gem"
81
- s.timeout = 10
82
- s
83
- end
84
- response = case options[:method]
85
- when :post
86
- @session.headers['Accept'] = "application/json"
87
- @session.headers['Content-Type'] = "application/json"
88
- @session.post("#{path}", options[:data].to_json)
89
- when :put
90
- @session.headers['Content-Type'] = "application/json"
91
- @session.put("#{path}", options[:data].to_json)
92
- when :delete
93
- @session.delete("#{path}")
94
- else
95
- @session.get("#{path}.json")
96
- end
97
-
98
- case response.status
99
- when 200, 202, 204
100
- JSON.parse(response.body) unless response.body.empty?
101
- else
102
- puts response.body
103
- raise RuntimeError, "Error fetching #{path}: #{response.status}"
104
- end
105
43
  end
106
44
  end
@@ -6,22 +6,54 @@ module RackspaceCloud
6
6
  validate_config(config)
7
7
  @user = config[:user]
8
8
  @access_key = config[:access_key]
9
+ @authorized = false
9
10
  end
10
11
 
11
12
  def connect
12
- RackspaceCloud.request_authorization(@user, @access_key)
13
+ configure_service_urls(RackspaceCloud.request_authorization(@user, @access_key))
13
14
  RackspaceCloud.check_version_compatibility
14
- RackspaceCloud.populate_flavors
15
- RackspaceCloud.populate_images
16
- RackspaceCloud.get_limits
15
+ @authorized = true
16
+ populate_flavors
17
+ populate_images
18
+ get_limits
19
+ end
20
+
21
+ def authorized?
22
+ @authorized
17
23
  end
18
24
 
19
- def servers(force_refresh=false)
20
- RackspaceCloud.request("/servers/detail")["servers"].collect {|server_json|
21
- RackspaceCloud::Server.new(server_json)
22
- }
25
+ # storage for the lists of flavors and images we request at auth time
26
+ attr_reader :flavors
27
+ def populate_flavors
28
+ @flavors ||= {}
29
+ request("/flavors/detail")['flavors'].each do |flavor|
30
+ @flavors[flavor['id']] = RackspaceCloud::Flavor.new(flavor)
31
+ end
32
+ nil
33
+ end
34
+
35
+ attr_reader :images
36
+ def populate_images
37
+ @images ||= {}
38
+ request("/images/detail")['images'].each do |image|
39
+ @images[image['id']] = RackspaceCloud::Image.new(self, image)
40
+ end
41
+ nil
23
42
  end
24
43
 
44
+ attr_reader :limits
45
+ def get_limits
46
+ @limits ||= {}
47
+ @limits.merge!(request("/limits")['limits'])
48
+ nil
49
+ end
50
+
51
+ def servers
52
+ request("/servers/detail")["servers"].collect {|server_json|
53
+ RackspaceCloud::Server.new(self, server_json)
54
+ }
55
+ end
56
+
25
57
  def create_server(name, flavor, image, metadata={}, personality=[])
26
58
  new_server_data = {'server' => {
27
59
  'name' => name,
@@ -31,7 +63,53 @@ module RackspaceCloud
31
63
  'personality' => personality
32
64
  }}
33
65
 
34
- RackspaceCloud::Server.new(RackspaceCloud.request("/servers", :method => :post, :data => new_server_data)['server'])
66
+ RackspaceCloud::Server.new(self, request("/servers", :method => :post, :data => new_server_data)['server'])
67
+ end
68
+
69
+ def shared_ip_groups
70
+ request("/shared_ip_groups/detail")['sharedIpGroups'].collect {|group_json|
71
+ RackspaceCloud::SharedIPGroup.new(self, group_json)
72
+ }
73
+ end
74
+
75
+ # Yes, you can only specify at most a single server to initially populate a shared IP group. Odd, that.
76
+ def create_shared_ip_group(name, server=nil)
77
+ new_group_data = {'sharedIpGroup' => {'name' => name, 'server' => server}}
78
+ new_group_data['sharedIpGroup']['server'] = server.to_i unless server.nil?
79
+ RackspaceCloud::SharedIPGroup.new(self, request("/shared_ip_groups", :method => :post, :data => new_group_data))
80
+ end
81
+
82
+ def request(path, options={})
83
+ raise RuntimeError, "Please authorize before using by calling connect()" unless authorized?
84
+ @session ||= begin
85
+ s = Patron::Session.new
86
+ s.base_url = @server_management_url
87
+ s.headers['X-Auth-Token'] = @auth_token
88
+ s.headers["User-Agent"] = "rackspacecloud_ruby_gem"
89
+ s.timeout = 10
90
+ s
91
+ end
92
+ response = case options[:method]
93
+ when :post
94
+ @session.headers['Accept'] = "application/json"
95
+ @session.headers['Content-Type'] = "application/json"
96
+ @session.post("#{path}", options[:data].to_json)
97
+ when :put
98
+ @session.headers['Content-Type'] = "application/json"
99
+ @session.put("#{path}", options[:data].to_json)
100
+ when :delete
101
+ @session.delete("#{path}")
102
+ else
103
+ @session.get("#{path}.json")
104
+ end
105
+
106
+ case response.status
107
+ when 200, 201, 202, 204
108
+ JSON.parse(response.body) unless response.body.empty?
109
+ else
110
+ puts response.body
111
+ raise RuntimeError, "Error fetching #{path}: #{response.status}"
112
+ end
35
113
  end
36
114
 
37
115
  def api_version
@@ -46,5 +124,13 @@ module RackspaceCloud
46
124
  (config[:access_key] && config[:access_key].length) || errors << "missing access_key"
47
125
  raise(ArgumentError, "Error: invalid configuration: #{errors.join(';')}") unless errors.empty?
48
126
  end
127
+
128
+ def configure_service_urls(url_hash = {})
129
+ @server_management_url = url_hash['X-Server-Management-Url']
130
+ @storage_url = url_hash['X-Storage-Url']
131
+ @storage_token = url_hash['X-Storage-Token']
132
+ @cdn_management_url = url_hash['X-CDN-Management-Url']
133
+ @auth_token = url_hash['X-Auth-Token']
134
+ end
49
135
  end
50
136
  end
@@ -2,12 +2,6 @@ module RackspaceCloud
2
2
  class Flavor
3
3
  attr_reader :name, :disk, :ram, :rackspace_id
4
4
 
5
- class << self
6
- def lookup_by_id(id)
7
- RackspaceCloud::FLAVORS[id]
8
- end
9
- end
10
-
11
5
  def initialize(flavor_json)
12
6
  @rackspace_id = flavor_json['id']
13
7
  @name = flavor_json['name']
@@ -3,21 +3,26 @@ module RackspaceCloud
3
3
 
4
4
  MAX_RACKSPACE_IMAGE_ID = 10 # the highest id in use by a standard rackspace image (vs. a user backup)
5
5
 
6
- attr_reader :name, :created, :updated, :status, :progress, :rackspace_id
6
+ attr_reader :name, :created, :updated, :status, :progress, :rackspace_id, :base
7
7
 
8
8
  class << self
9
- def lookup_by_id(id)
10
- RackspaceCloud::IMAGES[id]
9
+ def create_from_server(server, name=nil)
10
+ name ||= generate_timestamped_name(server)
11
+ image_json = server.base.request("/images", :method => :post, :data => {'image' => {'name' => name, 'serverId' => @rackspace_id}})['image']
12
+ new_image = RackspaceCloud::Image.new(image_json)
13
+ @images[new_image.rackspace_id] = new_image
14
+ new_image
11
15
  end
12
16
  end
13
17
 
14
- def initialize(image_json)
18
+ def initialize(base, image_json)
19
+ @base = base
15
20
  populate(image_json)
16
21
  end
17
22
 
18
23
  def delete
19
- raise RuntimeError, "Can't delete Rackspace standar images" if @rackspace_id <= MAX_RACKSPACE_IMAGE_ID
20
- RackspaceCloud.request("/images/#{@rackspace_id}", :method => :delete)
24
+ raise RuntimeError, "Can't delete Rackspace standard images" if @rackspace_id <= MAX_RACKSPACE_IMAGE_ID
25
+ @base.request("/images/#{@rackspace_id}", :method => :delete)
21
26
  end
22
27
 
23
28
  def to_i
@@ -25,8 +30,8 @@ module RackspaceCloud
25
30
  end
26
31
 
27
32
  def refresh
28
- populate(RackspaceCloud.request("/images/#{@rackspace_id}")['image'])
29
- RackspaceCloud::IMAGES[@rackspace_id] = self
33
+ populate(@base.request("/images/#{@rackspace_id}")['image'])
34
+ self
30
35
  end
31
36
 
32
37
  protected
@@ -39,5 +44,9 @@ module RackspaceCloud
39
44
  @status = image_json['status']
40
45
  @progress = image_json['progress']
41
46
  end
47
+
48
+ def generate_timestamped_name(server)
49
+ "#{server.downcase.gsub!(/\W/, "-")}-#{Time.nowTime.now.strftime('%Y%m%d%H%M%S%z')}"
50
+ end
42
51
  end
43
52
  end
@@ -1,17 +1,18 @@
1
1
  module RackspaceCloud
2
2
  class Server
3
- attr_reader :name, :status, :flavor, :image
3
+ attr_reader :name, :status, :flavor, :image, :base
4
4
  attr_reader :rackspace_id, :host_id, :progress
5
5
  attr_reader :public_ips, :private_ips, :adminPass
6
6
 
7
7
  STATUS_VALUES = %w{ACTIVE BUILD REBUILD SUSPENDED QUEUE_RESIZE PREP_RESIZE VERIFY_RESIZE PASSWORD RESCUE REBOOT HARD_REBOOT SHARE_IP SHARE_IP_NO_CONFIG DELETE_IP UNKNOWN}
8
8
 
9
- def initialize(server_json)
9
+ def initialize(base, server_json)
10
+ @base = base
10
11
  populate(server_json)
11
12
  end
12
13
 
13
14
  def ready?
14
- @status == 'ACTIVE'
15
+ self.refresh.status == 'ACTIVE'
15
16
  end
16
17
 
17
18
  def reboot
@@ -38,42 +39,44 @@ module RackspaceCloud
38
39
  action_request('revertResize' => nil)
39
40
  end
40
41
 
42
+ def share_ip_address(ip_address, shared_ip_address_group, configure_server = true)
43
+ @base.request("/servers/#{@rackspace_id}/ips/public/#{ip_address}",
44
+ :method => :put, :data => {'shareIp' => {'sharedIpGroupId' => shared_ip_address_group.to_i, 'configureServer' => configure_server}})
45
+ end
46
+
47
+ def unshare_ip_address(ip_address)
48
+ @base.request("/servers/#{@rackspace_id}/ips/public/#{ip_address}", :method => :delete)
49
+ end
50
+
41
51
  def delete
42
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :delete)
52
+ @base.request("/servers/#{@rackspace_id}", :method => :delete)
43
53
  end
44
54
 
45
55
  def update_server_name(new_name)
46
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"name" => new_name}})
56
+ @base.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"name" => new_name}})
47
57
  end
48
58
 
49
59
  def update_admin_password(new_password)
50
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"adminPass" => new_password}})
51
- end
52
-
53
- def save_as_image(name)
54
- image_json = RackspaceCloud.request("/images", :method => :post, :data => {'image' => {'name' => name, 'serverId' => @rackspace_id}})['image']
55
- new_image = RackspaceCloud::Image.new(image_json)
56
- RackspaceCloud::IMAGES[new_image.rackspace_id] = new_image
57
- new_image
60
+ @base.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"adminPass" => new_password}})
58
61
  end
59
62
 
60
63
  # update this server's status and progress by calling /servers/<id>
61
64
  def refresh
62
- populate(RackspaceCloud.request("/servers/#{@rackspace_id}")['server'])
65
+ populate(@base.request("/servers/#{@rackspace_id}")['server'])
63
66
  self
64
67
  end
65
68
 
66
69
  protected
67
70
 
68
71
  def action_request(data)
69
- RackspaceCloud.request("/servers/#{@rackspace_id}/action", :method => :post, :data => data)
72
+ @base.request("/servers/#{@rackspace_id}/action", :method => :post, :data => data)
70
73
  end
71
74
 
72
75
  def populate(server_json)
73
76
  @name = server_json['name']
74
77
  @status = server_json['status']
75
- @flavor = RackspaceCloud::Flavor.lookup_by_id(server_json['flavorId'])
76
- @image = RackspaceCloud::Image.lookup_by_id(server_json['imageId'])
78
+ @flavor = @base.flavors[server_json['flavorId']]
79
+ @image = @base.images[server_json['imageId']]
77
80
  @rackspace_id = server_json['id']
78
81
  @host_id = server_json['hostId']
79
82
  @progress = server_json['progress']
@@ -0,0 +1,33 @@
1
+ module RackspaceCloud
2
+ class SharedIPGroup
3
+ attr_reader :rackspace_id, :name, :servers
4
+
5
+ def initialize(base, group_json)
6
+ @base = base
7
+ populate(group_json)
8
+ end
9
+
10
+ def delete
11
+ @base.request("/shared_ip_groups/#{@rackspace_id}", :method => :delete)
12
+ end
13
+
14
+ def refresh
15
+ populate(@base.request("/shared_ip_groups/detail")['sharedIpGroup'])
16
+ end
17
+
18
+ def to_i
19
+ @rackspace_id
20
+ end
21
+
22
+ protected
23
+
24
+ def populate(group_json)
25
+ puts group_json.inspect
26
+ @rackspace_id = group_json['id']
27
+ @name = group_json['name']
28
+ unless group_json['servers'].nil?
29
+ @servers = @base.servers.select{|server| group_json['servers'].include? server.rackspace_id}
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rackspace_cloud}
5
- s.version = "0.3.0"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Grant Goodale"]
9
- s.date = %q{2009-07-22}
9
+ s.date = %q{2009-08-03}
10
10
  s.description = %q{Gem enabling the management of Rackspace Cloud Server instances.}
11
11
  s.email = %q{grant@moreblinktag.com}
12
12
  s.extra_rdoc_files = [
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "lib/rackspace_cloud/flavor.rb",
25
25
  "lib/rackspace_cloud/image.rb",
26
26
  "lib/rackspace_cloud/server.rb",
27
+ "lib/rackspace_cloud/shared_ip_group.rb",
27
28
  "rackspace_cloud.gemspec",
28
29
  "test/authentication_test.rb",
29
30
  "test/configuration_test.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ggoodale-rackspace_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grant Goodale
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-22 00:00:00 -07:00
12
+ date: 2009-08-03 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,12 +42,14 @@ files:
42
42
  - lib/rackspace_cloud/flavor.rb
43
43
  - lib/rackspace_cloud/image.rb
44
44
  - lib/rackspace_cloud/server.rb
45
+ - lib/rackspace_cloud/shared_ip_group.rb
45
46
  - rackspace_cloud.gemspec
46
47
  - test/authentication_test.rb
47
48
  - test/configuration_test.rb
48
49
  - test/test_helper.rb
49
50
  has_rdoc: false
50
51
  homepage: http://github.com/ggoodale/rackspace_cloud
52
+ licenses:
51
53
  post_install_message:
52
54
  rdoc_options:
53
55
  - --charset=UTF-8
@@ -68,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
70
  requirements: []
69
71
 
70
72
  rubyforge_project:
71
- rubygems_version: 1.2.0
73
+ rubygems_version: 1.3.5
72
74
  signing_key:
73
75
  specification_version: 3
74
76
  summary: Gem enabling the management of Rackspace Cloud Server instances