dropmyemail-openstack 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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