dropmyemail-openstack 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ module OpenStack
2
+ module Compute
3
+ class Flavor
4
+
5
+ attr_reader :id
6
+ attr_reader :name
7
+ attr_reader :ram
8
+ attr_reader :disk
9
+ attr_reader :vcpus
10
+
11
+ # This class provides an object for the "Flavor" of a server. The Flavor can generally be taken as the server specification,
12
+ # providing information on things like memory and disk space.
13
+ #
14
+ # The disk attribute is an integer representing the disk space in GB. The memory attribute is an integer representing the RAM in MB.
15
+ #
16
+ # This is called from the get_flavor method on a OpenStack::Compute::Connection object, returns a OpenStack::Compute::Flavor object, and will likely not be called directly.
17
+ #
18
+ # >> flavor = cs.get_flavor(1)
19
+ # => #<OpenStack::Compute::Flavor:0x1014f8bc8 @name="256 server", @disk=10, @id=1, @ram=256>
20
+ # >> flavor.name
21
+ # => "256 server"
22
+ def initialize(compute,id)
23
+ response = compute.connection.csreq("GET",compute.connection.service_host,"#{compute.connection.service_path}/flavors/#{URI.escape(id.to_s)}",compute.connection.service_port,compute.connection.service_scheme)
24
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
25
+ data = JSON.parse(response.body)['flavor']
26
+ @id = data['id']
27
+ @name = data['name']
28
+ @ram = data['ram']
29
+ @disk = data['disk']
30
+ @vcpus = data['vcpus']
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,73 @@
1
+ module OpenStack
2
+ module Compute
3
+ class Image
4
+
5
+ require 'openstack/compute/metadata'
6
+
7
+ attr_reader :id
8
+ attr_reader :name
9
+ attr_reader :server
10
+ attr_reader :updated
11
+ attr_reader :created
12
+ attr_reader :status
13
+ attr_reader :minDisk
14
+ attr_reader :minRam
15
+ attr_reader :progress
16
+ attr_reader :metadata
17
+
18
+ # This class provides an object for the "Image" of a server. The Image refers to the Operating System type and version.
19
+ #
20
+ # Returns the Image object identifed by the supplied ID number. Called from the get_image instance method of OpenStack::Compute::Connection,
21
+ # it will likely not be called directly from user code.
22
+ #
23
+ # >> cs = OpenStack::Compute::Connection.new(USERNAME,API_KEY)
24
+ # >> image = cs.get_image(2)
25
+ # => #<OpenStack::Compute::Image:0x1015371c0 ...>
26
+ # >> image.name
27
+ # => "CentOS 5.2"
28
+ def initialize(compute,id)
29
+ @id = id
30
+ @compute = compute
31
+ populate
32
+ end
33
+
34
+ # Makes the HTTP call to load information about the provided image. Can also be called directly on the Image object to refresh data.
35
+ # Returns true if the refresh call succeeds.
36
+ #
37
+ # >> image.populate
38
+ # => true
39
+ def populate
40
+ path = "/images/#{URI.escape(self.id.to_s)}"
41
+ response = @compute.connection.req("GET", path)
42
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
43
+ data = JSON.parse(response.body)['image']
44
+ @id = data['id']
45
+ @name = data['name']
46
+ @server = data['server']
47
+ if data['updated'] then
48
+ @updated = DateTime.parse(data['updated'])
49
+ end
50
+ @created = DateTime.parse(data['created'])
51
+ @metadata = OpenStack::Compute::Metadata.new(@compute, path, data['metadata'])
52
+ @status = data['status']
53
+ @minDisk = data['minDisk']
54
+ @minRam = data['minRam']
55
+ @progress = data['progress']
56
+ return true
57
+ end
58
+ alias :refresh :populate
59
+
60
+ # Delete an image. This should be returning invalid permissions when attempting to delete system images, but it's not.
61
+ # Returns true if the deletion succeeds.
62
+ #
63
+ # >> image.delete!
64
+ # => true
65
+ def delete!
66
+ response = @compute.connection.csreq("DELETE",@compute.connection.service_host,"#{@compute.connection.service_path}/images/#{URI.escape(self.id.to_s)}",@compute.connection.service_port,@compute.connection.service_scheme)
67
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
68
+ true
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,116 @@
1
+ module OpenStack
2
+ module Compute
3
+
4
+ class Metadata
5
+
6
+ def initialize(compute, parent_url, metadata=nil)
7
+ @compute = compute
8
+ @base_url = "#{parent_url}/metadata"
9
+ @metadata = metadata
10
+ end
11
+
12
+ def [](key)
13
+ refresh if @metadata.nil?
14
+ @metadata[key]
15
+ end
16
+
17
+ def []=(key, value)
18
+ @metadata = {} if @metadata.nil?
19
+ @metadata[key] = value
20
+ end
21
+
22
+ def store(key, value)
23
+ @metadata = {} if @metadata.nil?
24
+ @metadata[key] = value
25
+ end
26
+
27
+ def each_pair
28
+ @metadata = {} if @metadata.nil?
29
+ @metadata.each_pair do |k,v|
30
+ yield k, v
31
+ end
32
+ end
33
+
34
+ def size
35
+ @metadata = {} if @metadata.nil?
36
+ @metadata.size
37
+ end
38
+
39
+ def each
40
+ refresh if @metadata.nil?
41
+ @metadata.each
42
+ end
43
+
44
+ def save
45
+ return if @metadata.nil?
46
+ json = JSON.generate(:metadata => @metadata)
47
+ response = @compute.connection.req('PUT', @base_url, :data => json)
48
+ @metadata = JSON.parse(response.body)['metadata']
49
+ end
50
+
51
+ def update(keys=nil)
52
+ return if @metadata.nil?
53
+ if keys.nil?
54
+ json = JSON.generate(:metadata => @metadata)
55
+ response = @compute.connection.req('POST', @base_url, :data => json)
56
+ @metadata = JSON.parse(response.body)['metadata']
57
+ else
58
+ keys.each { |key|
59
+ next if not @metadata.has_key?(key)
60
+ json = JSON.generate(:meta => { key => @metadata[key] })
61
+ @compute.connection.req('PUT', "#{@base_url}/#{key}", :data => json)
62
+ }
63
+ end
64
+ end
65
+
66
+ def refresh(keys=nil)
67
+ if keys.nil?
68
+ response = @compute.connection.req('GET', @base_url)
69
+ @metadata = JSON.parse(response.body)['metadata']
70
+ else
71
+ @metadata = {} if @metadata == nil
72
+ keys.each { |key|
73
+ response = @compute.connection.req('GET', "#{@base_url}/#{key}")
74
+ next if response.code == "404"
75
+ meta = JSON.parse(response.body)['meta']
76
+ meta.each { |k, v| @metadata[k] = v }
77
+ }
78
+ end
79
+ end
80
+
81
+ def delete(keys)
82
+ return if @metadata.nil?
83
+ keys.each { |key|
84
+ @metadata.delete(key)
85
+ }
86
+ end
87
+
88
+ def delete!(keys)
89
+ keys.each { |key|
90
+ @compute.connection.req('DELETE', "#{@base_url}/#{key}")
91
+ @metadata.delete(key) if not @metadata.nil?
92
+ }
93
+ end
94
+
95
+ def clear
96
+ if @metadata.nil?
97
+ @metadata = {}
98
+ else
99
+ @metadata.clear
100
+ end
101
+ end
102
+
103
+ def clear!
104
+ clear
105
+ save
106
+ end
107
+
108
+ def has_key?(key)
109
+ return False if @metadata.nil?
110
+ return @metadata.has_key?(key)
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,23 @@
1
+ module OpenStack
2
+ module Compute
3
+ module Personalities
4
+
5
+ # Handles parsing the Personality hash to load it up with Base64-encoded data.
6
+ def self.get_personality(options)
7
+ return if options.nil?
8
+ require 'base64'
9
+ data = []
10
+ itemcount = 0
11
+ options.each do |localpath,svrpath|
12
+ raise OpenStack::Exception::TooManyPersonalityItems, "Personality files are limited to a total of #{MAX_PERSONALITY_ITEMS} items" if itemcount >= MAX_PERSONALITY_ITEMS
13
+ raise OpenStack::Exception::PersonalityFilePathTooLong, "Server-side path of #{svrpath} exceeds the maximum length of #{MAX_SERVER_PATH_LENGTH} characters" if svrpath.size > MAX_SERVER_PATH_LENGTH
14
+ raise OpenStack::Exception::PersonalityFileTooLarge, "Local file #{localpath} exceeds the maximum size of #{MAX_PERSONALITY_FILE_SIZE} bytes" if File.size(localpath) > MAX_PERSONALITY_FILE_SIZE
15
+ b64 = Base64.encode64(IO.read(localpath))
16
+ data.push({:path => svrpath, :contents => b64})
17
+ itemcount += 1
18
+ end
19
+ data
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,254 @@
1
+ module OpenStack
2
+ module Compute
3
+ class Server
4
+
5
+ require 'openstack/compute/metadata'
6
+
7
+ attr_reader :id
8
+ attr_reader :name
9
+ attr_reader :status
10
+ attr_reader :progress
11
+ attr_reader :accessipv4
12
+ attr_reader :accessipv6
13
+ attr_reader :addresses
14
+ attr_reader :hostId
15
+ attr_reader :image
16
+ attr_reader :flavor
17
+ attr_reader :metadata
18
+ attr_accessor :adminPass
19
+ attr_reader :key_name
20
+ attr_reader :security_groups
21
+
22
+ # This class is the representation of a single Server object. The constructor finds the server identified by the specified
23
+ # ID number, accesses the API via the populate method to get information about that server, and returns the object.
24
+ #
25
+ # Will be called via the get_server or create_server methods on the OpenStack::Compute::Connection object, and will likely not be called directly.
26
+ #
27
+ # >> server = cs.get_server(110917)
28
+ # => #<OpenStack::Compute::Server:0x1014e5438 ....>
29
+ # >> server.name
30
+ # => "RenamedRubyTest"
31
+ def initialize(compute,id)
32
+ @compute = compute
33
+ @id = id
34
+ @svrmgmthost = @compute.connection.service_host
35
+ @svrmgmtpath = @compute.connection.service_path
36
+ @svrmgmtport = @compute.connection.service_port
37
+ @svrmgmtscheme = @compute.connection.service_scheme
38
+ populate
39
+ return self
40
+ end
41
+
42
+ # Makes the actual API call to get information about the given server object. If you are attempting to track the status or project of
43
+ # a server object (for example, when rebuilding, creating, or resizing a server), you will likely call this method within a loop until
44
+ # the status becomes "ACTIVE" or other conditions are met.
45
+ #
46
+ # Returns true if the API call succeeds.
47
+ #
48
+ # >> server.refresh
49
+ # => true
50
+ def populate(data=nil)
51
+ path = "/servers/#{URI.encode(@id.to_s)}"
52
+ if data.nil? then
53
+ response = @compute.connection.req("GET", path)
54
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
55
+ data = JSON.parse(response.body)["server"]
56
+ end
57
+ @id = data["id"] || data["uuid"]
58
+ @name = data["name"]
59
+ @status = data["status"]
60
+ @progress = data["progress"]
61
+ @addresses = get_addresses(data["addresses"])
62
+ @metadata = OpenStack::Compute::Metadata.new(@compute, path, data["metadata"])
63
+ @hostId = data["hostId"]
64
+ @image = data["image"] || data["imageId"]
65
+ @flavor = data["flavor"] || data["flavorId"]
66
+ @key_name = data["key_name"] # if provider uses the keys API extension for accessing servers
67
+ @security_groups = (data["security_groups"] || []).inject([]){|res, c| res << c["id"] ; res}
68
+ true
69
+ end
70
+ alias :refresh :populate
71
+
72
+ # Sends an API request to reboot this server. Takes an optional argument for the type of reboot, which can be "SOFT" (graceful shutdown)
73
+ # or "HARD" (power cycle). The hard reboot is also triggered by server.reboot!, so that may be a better way to call it.
74
+ #
75
+ # Returns true if the API call succeeds.
76
+ #
77
+ # >> server.reboot
78
+ # => true
79
+ def reboot(type="SOFT")
80
+ data = JSON.generate(:reboot => {:type => type})
81
+ response = @compute.connection.csreq("POST",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}/action",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
82
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
83
+ true
84
+ end
85
+
86
+ # Sends an API request to hard-reboot (power cycle) the server. See the reboot method for more information.
87
+ #
88
+ # Returns true if the API call succeeds.
89
+ #
90
+ # >> server.reboot!
91
+ # => true
92
+ def reboot!
93
+ self.reboot("HARD")
94
+ end
95
+
96
+ # Updates various parameters about the server. Currently, the only operations supported are changing the server name (not the actual hostname
97
+ # on the server, but simply the label in the Servers API) and the administrator password (note: changing the admin password will trigger
98
+ # a reboot of the server). Other options are ignored. One or both key/value pairs may be provided. Keys are case-sensitive.
99
+ #
100
+ # Input hash key values are :name and :adminPass. Returns true if the API call succeeds.
101
+ #
102
+ # >> server.update(:name => "MyServer", :adminPass => "12345")
103
+ # => true
104
+ # >> server.name
105
+ # => "MyServer"
106
+ def update(options)
107
+ data = JSON.generate(:server => options)
108
+ response = @compute.connection.csreq("PUT",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
109
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
110
+ # If we rename the instance, repopulate the object
111
+ self.populate if options[:name]
112
+ true
113
+ end
114
+
115
+ # Deletes the server from OpenStack Compute. The server will be shut down, data deleted, and billing stopped.
116
+ #
117
+ # Returns true if the API call succeeds.
118
+ #
119
+ # >> server.delete!
120
+ # => true
121
+ def delete!
122
+ response = @compute.connection.csreq("DELETE",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}",@svrmgmtport,@svrmgmtscheme)
123
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
124
+ true
125
+ end
126
+
127
+ # The rebuild function removes all data on the server and replaces it with
128
+ # the specified image. The serverRef and all IP addresses will remain the
129
+ # same. If name and metadata are specified, they will replace existing
130
+ # values, otherwise they will not change. A rebuild operation always
131
+ # removes data injected into the file system via server personality. You
132
+ # may reinsert data into the filesystem during the rebuild.
133
+ #
134
+ # This method expects a hash of the form:
135
+ # {
136
+ # :imageRef => "https://foo.com/v1.1/images/2",
137
+ # :name => "newName",
138
+ # :metadata => { :values => { :foo : "bar" } },
139
+ # :personality => [
140
+ # {
141
+ # :path => "/etc/banner.txt",
142
+ # :contents => : "ICAgpY2hhcmQgQmFjaA=="
143
+ # }
144
+ # ]
145
+ # }
146
+ #
147
+ # This will wipe and rebuild the server, but keep the server ID number,
148
+ # name, and IP addresses the same.
149
+ #
150
+ # Returns true if the API call succeeds.
151
+ #
152
+ # >> server.rebuild!
153
+ # => true
154
+ def rebuild!(options)
155
+ options[:personality] = Personalities.get_personality(options[:personality])
156
+ json = JSON.generate(:rebuild => options)
157
+ response = @compute.connection.req('POST', "/servers/#{@id}/action", :data => json)
158
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
159
+ data = JSON.parse(response.body)['server']
160
+ self.populate(data)
161
+ self.adminPass = data['adminPass']
162
+ true
163
+ end
164
+
165
+ # Takes a snapshot of the server and creates a server image from it. That image can then be used to build new servers. The
166
+ # snapshot is saved asynchronously. Check the image status to make sure that it is ACTIVE before attempting to perform operations
167
+ # on it.
168
+ #
169
+ # A name string for the saved image must be provided. A new OpenStack::Compute::Image object for the saved image is returned.
170
+ #
171
+ # The image is saved as a backup, of which there are only three available slots. If there are no backup slots available,
172
+ # A OpenStack::Exception::OpenStackComputeFault will be raised.
173
+ #
174
+ # >> image = server.create_image(:name => "My Rails Server")
175
+ # =>
176
+ def create_image(options)
177
+ data = JSON.generate(:createImage => options)
178
+ response = @compute.connection.csreq("POST",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}/action",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
179
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
180
+ image_id = response["Location"].scan(/.*\/(.*)/).flatten
181
+ OpenStack::Compute::Image.new(@compute, image_id)
182
+ end
183
+
184
+ # Resizes the server to the size contained in the server flavor found at ID flavorRef. The server name, ID number, and IP addresses
185
+ # will remain the same. After the resize is done, the server.status will be set to "VERIFY_RESIZE" until the resize is confirmed or reverted.
186
+ #
187
+ # Refreshes the OpenStack::Compute::Server object, and returns true if the API call succeeds.
188
+ #
189
+ # >> server.resize!(1)
190
+ # => true
191
+ def resize!(flavorRef)
192
+ data = JSON.generate(:resize => {:flavorRef => flavorRef})
193
+ response = @compute.connection.csreq("POST",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}/action",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
194
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
195
+ self.populate
196
+ true
197
+ end
198
+
199
+ # After a server resize is complete, calling this method will confirm the resize with the OpenStack API, and discard the fallback/original image.
200
+ #
201
+ # Returns true if the API call succeeds.
202
+ #
203
+ # >> server.confirm_resize!
204
+ # => true
205
+ def confirm_resize!
206
+ # If the resize bug gets figured out, should put a check here to make sure that it's in the proper state for this.
207
+ data = JSON.generate(:confirmResize => nil)
208
+ response = @compute.connection.csreq("POST",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}/action",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
209
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
210
+ self.populate
211
+ true
212
+ end
213
+
214
+ # After a server resize is complete, calling this method will reject the resized server with the OpenStack API, destroying
215
+ # the new image and replacing it with the pre-resize fallback image.
216
+ #
217
+ # Returns true if the API call succeeds.
218
+ #
219
+ # >> server.confirm_resize!
220
+ # => true
221
+ def revert_resize!
222
+ # If the resize bug gets figured out, should put a check here to make sure that it's in the proper state for this.
223
+ data = JSON.generate(:revertResize => nil)
224
+ response = @compute.connection.csreq("POST",@svrmgmthost,"#{@svrmgmtpath}/servers/#{URI.encode(self.id.to_s)}/action",@svrmgmtport,@svrmgmtscheme,{'content-type' => 'application/json'},data)
225
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
226
+ self.populate
227
+ true
228
+ end
229
+
230
+ # Changes the admin password.
231
+ # Returns the password if it succeeds.
232
+ def change_password!(password)
233
+ json = JSON.generate(:changePassword => { :adminPass => password })
234
+ @compute.connection.req('POST', "/servers/#{@id}/action", :data => json)
235
+ @adminPass = password
236
+ end
237
+
238
+ def get_addresses(address_info)
239
+ address_info = OpenStack::Compute::Address.fix_labels(address_info)
240
+ address_list = OpenStack::Compute::AddressList.new
241
+ address_info.each do |label, addr|
242
+ addr.each do |address|
243
+ address_list << OpenStack::Compute::Address.new(label,address)
244
+ if address_list.last.version == 4 && (!@accessipv4 || accessipv4 == "") then
245
+ @accessipv4 = address_list.last.address
246
+ end
247
+ end
248
+ end
249
+ address_list
250
+ end
251
+
252
+ end
253
+ end
254
+ end