visor-image 0.0.3 → 0.0.4

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.
@@ -65,30 +65,30 @@ module Visor
65
65
  options[:address] = addr
66
66
  new_opts << :address
67
67
  end
68
- opts.on("-p", "--port PORT", "Use PORT (default: #{options[:port]})") do |port|
68
+ opts.on("-p", "--port PORT", "Bind to PORT number (default: #{options[:port]})") do |port|
69
69
  options[:port] = port.to_i
70
70
  new_opts << :port
71
71
  end
72
- opts.on("-e", "--env NAME", "Set the execution environment (default: #{options[:env]})") do |env|
72
+ opts.on("-e", "--env ENV", "Set execution environment (default: #{options[:env]})") do |env|
73
73
  options[:env] = env.to_sym
74
74
  new_opts << :env
75
75
  end
76
-
77
- opts.separator ""
78
- opts.on('-l', '--log FILE', "Log to file (default: #{@options[:log_file]})") do |file|
79
- @options[:log_file] = file
80
- new_opts << :log_file
81
- end
82
- opts.on('-u', '--user USER', "Run as specified user") do |v|
83
- @options[:user] = v
84
- new_opts << :user
85
- end
86
- opts.on("-f", "--foreground", "Do not daemonize") do
76
+ opts.on("-f", "--foreground", "Do not daemonize, run in foreground") do
87
77
  options[:daemonize] = false
88
78
  options[:log_stdout] = true
89
79
  new_opts << :daemonize
90
80
  end
91
81
 
82
+ #opts.separator ""
83
+ #opts.on('-l', '--log FILE', "Log to file (default: #{@options[:log_file]})") do |file|
84
+ # @options[:log_file] = file
85
+ # new_opts << :log_file
86
+ #end
87
+ #opts.on('-u', '--user USER', "Run as specified user") do |v|
88
+ # @options[:user] = v
89
+ # new_opts << :user
90
+ #end
91
+
92
92
  #opts.separator ""
93
93
  #opts.separator "SSL options:"
94
94
  #opts.on('--ssl', 'Enables SSL (default: off)') {|v| @options[:ssl] = v }
@@ -99,16 +99,16 @@ module Visor
99
99
  opts.separator ""
100
100
  opts.separator "Common options:"
101
101
 
102
- opts.on_tail("-d", "--debug", "Set debugging on") do
102
+ opts.on_tail("-d", "--debug", "Enable debugging") do
103
103
  options[:debug] = true
104
104
  new_opts << :debug
105
105
  end
106
- opts.on_tail('-v', '--verbose', "Enable verbose logging") do
107
- options[:verbose] = true
108
- new_opts << :verbose
109
- end
110
- opts.on_tail("-h", "--help", "Show this message") { show_options(opts) }
111
- opts.on_tail('-V', '--version', "Show version") { show_version }
106
+ #opts.on_tail('-v', '--verbose', "Enable verbose logging") do
107
+ # options[:verbose] = true
108
+ # new_opts << :verbose
109
+ #end
110
+ opts.on_tail("-h", "--help", "Show this help message") { show_options(opts) }
111
+ opts.on_tail('-v', '--version', "Show version") { show_version }
112
112
  end
113
113
  end
114
114
 
@@ -161,9 +161,9 @@ module Visor
161
161
  # Display current server status
162
162
  def status
163
163
  if running?
164
- STDERR.puts "VISoR Image Server is running PID: #{fetch_pid} URL: #{fetch_url}"
164
+ STDERR.puts "visor-image is running PID: #{fetch_pid} URL: #{fetch_url}"
165
165
  else
166
- STDERR.puts "VISoR Image Server is not running."
166
+ STDERR.puts "visor-image is not running."
167
167
  end
168
168
  end
169
169
 
@@ -171,11 +171,11 @@ module Visor
171
171
  def stop
172
172
  begin
173
173
  pid = File.read(pid_file)
174
- put_and_log :warn, "Stopping VISoR Image Server with PID: #{pid.to_i} Signal: INT"
174
+ put_and_log :warn, "Stopping visor-image with PID: #{pid.to_i} Signal: INT"
175
175
  Process.kill(:INT, pid.to_i)
176
176
  File.delete(url_file)
177
177
  rescue
178
- put_and_log :warn, "Cannot stop VISoR Image Server, is it running?"
178
+ put_and_log :warn, "Cannot stop visor-image, is it running?"
179
179
  exit! 1
180
180
  end
181
181
  end
@@ -189,14 +189,14 @@ module Visor
189
189
  write_url
190
190
  launch!
191
191
  rescue => e
192
- put_and_log :warn, "Error starting VISoR Image Server: #{e.message}\n#{e.backtrace.to_s}"
192
+ put_and_log :warn, "Error starting visor-image: #{e.message}\n#{e.backtrace.to_s}"
193
193
  exit! 1
194
194
  end
195
195
  end
196
196
 
197
197
  # Launch the server
198
198
  def launch!
199
- put_and_log :info, "Starting VISoR Image Server at #{options[:address]}:#{options[:port]}"
199
+ put_and_log :info, "Starting visor-image at #{options[:address]}:#{options[:port]}"
200
200
  debug_settings
201
201
 
202
202
  runner = Goliath::Runner.new(opts_to_goliath, Visor::Image::Server.new)
@@ -243,9 +243,9 @@ module Visor
243
243
  exit
244
244
  end
245
245
 
246
- # Show VISoR Image Server version
246
+ # Show VISOR Image System version
247
247
  def show_version
248
- puts "VISoR Image Server v#{Visor::Image::VERSION}"
248
+ puts "visor-image #{Visor::Image::VERSION}"
249
249
  exit
250
250
  end
251
251
 
@@ -253,7 +253,7 @@ module Visor
253
253
  def is_it_running?
254
254
  if files_exist?(pid_file, url_file)
255
255
  if running?
256
- put_and_log :warn, "VISoR Image Server is already running at #{fetch_url}"
256
+ put_and_log :warn, "visor-image is already running at #{fetch_url}"
257
257
  exit! 1
258
258
  else
259
259
  clean
@@ -330,7 +330,7 @@ module Visor
330
330
  conf_file.each { |k, v| logger.debug "#{k}: #{v}" unless k == :file }
331
331
  logger.debug "**************************************************************"
332
332
 
333
- logger.debug "Configurations passed from VISoR Image Server CLI:"
333
+ logger.debug "Configurations passed from visor-image CLI:"
334
334
  logger.debug "**************************************************************"
335
335
  if new_opts.empty?
336
336
  logger.debug "none"
@@ -6,37 +6,45 @@ require 'json'
6
6
  module Visor
7
7
  module Image
8
8
 
9
- # The Client API for the VISoR Image Server. This class supports all image metadata and
10
- # files operations through a programmatically interface.
9
+ # The programming API for the VISOR Image System (VIS). This class supports all image metadata and
10
+ # files operations through a programming interface.
11
11
  #
12
- # After Instantiate a Client object its possible to directly interact with the
13
- # image server and its store backends.
12
+ # After Instantiate a VIS Client object, its possible to directly interact with the VIS server. This API conforms
13
+ # to the tenets of the VIS server REST API {Visor::Image::Server Visor Image System server}.
14
+ #
15
+ # @note In the examples presented in this page, we will consider that the VIS server is listening in the 10.0.0.1 address and port 4568. We will also use a sample user account, with access_key "foo" and secret_key "bar".
14
16
  #
15
17
  class Client
16
18
  include Visor::Common::Exception
17
19
  include Visor::Common::Util
18
20
 
19
- attr_reader :host, :port, :ssl, :access_key, :secret_key
21
+ attr_reader :host, :port, :access_key, :secret_key
20
22
 
21
- # Initializes a new new VISoR Image Client.
23
+ # Initializes a new VIS programming client. VIS server settings (host and port address) and user's
24
+ # credentials should be provided for initialization or ignored (where settings will be loaded from the local VISOR configuration file).
22
25
  #
23
- # @option opts [String] :host (DEFAULT_HOST) The host address where VISoR image server resides.
24
- # @option opts [String] :port (DEFAULT_PORT) The host port where VISoR image server resides.
25
- # @option opts [String] :ssl (false) If the connection should be made through HTTPS (SSL).
26
+ # @option opts [String] :host The host address where the VIS server resides.
27
+ # @option opts [String] :port The host port where the VIS server listens.
28
+ # @option opts [String] :access_key The user access key.
29
+ # @option opts [String] :secret_key The user secret key.
26
30
  #
27
- # @example Instantiate a client with default values:
31
+ # @example Instantiate a client with default values loaded from the VISOR configuration file:
28
32
  # client = Visor::Image::Client.new
29
33
  #
30
- # @example Instantiate a client with custom host and port:
31
- # client = Visor::Image::Client.new(host: '127.0.0.1', port: 3000)
34
+ # @example Instantiate a client with custom host and port and with user's credentials loaded from the VISOR configuration file:
35
+ # client = Visor::Image::Client.new(host: '10.0.0.1', port: 4568)
36
+ #
37
+ # @example Instantiate a client with custom host, port and user's credentials (nothing is loaded from the VISOR configuration file):
38
+ # client = Visor::Image::Client.new(host: '10.0.0.1', port: 4568, access_key: 'foo', secret_key: 'bar')
39
+ #
40
+ # @return [Visor::Image::Client] A VIS programming client object.
32
41
  #
33
42
  def initialize(opts = {})
34
43
  configs = Common::Config.load_config :visor_image
35
44
  @host = opts[:host] || configs[:bind_host] || '0.0.0.0'
36
45
  @port = opts[:port] || configs[:bind_port] || 4568
37
- @ssl = opts[:ssl] || false
38
- @access_key = configs[:access_key]
39
- @secret_key = configs[:secret_key]
46
+ @access_key = opts[:access_key] || configs[:access_key]
47
+ @secret_key = opts[:secret_key] || configs[:secret_key]
40
48
  end
41
49
 
42
50
  # Retrieves detailed image metadata of the image with the given id.
@@ -46,25 +54,32 @@ module Visor
46
54
  # @example Retrieve the image metadata with _id value:
47
55
  # # wanted image _id
48
56
  # id = "5e47a41e-7b94-4f65-824e-28f94e15bc6a"
57
+ #
49
58
  # # ask for that image metadata
50
59
  # client.head_image(id)
51
60
  #
52
61
  # # return example:
53
62
  # {
54
- # :_id => "2cceffc6-ebc5-4741-9653-745524e7ac30",
55
- # :name => "Ubuntu 10.10",
63
+ # :_id => "edfa919a-0415-4d26-b54d-ae78ffc4dc79",
64
+ # :uri => "http://10.0.0.1:4568/images/edfa919a-0415-4d26-b54d-ae78ffc4dc79",
65
+ # :name => "Ubuntu 12.04 Server",
56
66
  # :architecture => "x86_64",
57
67
  # :access => "public",
58
- # :uri => "http://0.0.0.0:4567/images/2cceffc6-ebc5-4741-9653-745524e7ac30",
59
- # :format => "iso",
60
68
  # :status => "available",
61
- # :store => "file"
69
+ # :format => "iso",
70
+ # :size => "732213248",
71
+ # :store => "s3",
72
+ # :location => "s3://mys3accesskey:mys3secretkey@s3.amazonaws.com/mybucket/edfa919a-0415-4d26-b54d-ae78ffc4dc79.iso",
73
+ # :created_at => "2012-06-15 21:05:20 +0100",
74
+ # :checksum => "140f3-2ba4b000-4be8328106940",
75
+ # :owner => "foo"
62
76
  # }
63
77
  #
64
78
  # @return [Hash] The requested image metadata.
65
79
  #
66
80
  # @raise [NotFound] If image not found.
67
- # @raise [InternalError] On internal server error.
81
+ # @raise [Forbidden] If user authentication fails.
82
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
68
83
  #
69
84
  def head_image(id)
70
85
  path = "/images/#{id}"
@@ -73,20 +88,20 @@ module Visor
73
88
  pull_meta_from_headers(res)
74
89
  end
75
90
 
76
- # Retrieves brief metadata of all public images.
91
+ # Retrieves brief metadata of all public and user's private images.
77
92
  # Options for filtering the returned results can be passed in.
78
93
  #
79
94
  # @option query [String] :attribute The image attribute value to filter returned results.
80
95
  # @option query [String] :sort ("_id") The image attribute to sort returned results.
81
96
  # @option query [String] :dir ("asc") The direction to sort results ("asc"/"desc").
82
97
  #
83
- # @example Retrieve all public images brief metadata:
98
+ # @example Retrieve all images brief metadata:
84
99
  # client.get_images
85
100
  #
86
101
  # # returns:
87
102
  # [<all images brief metadata>]
88
103
  #
89
- # @example Retrieve all public 32bit images brief metadata:
104
+ # @example Retrieve all 32bit images brief metadata:
90
105
  # client.get_images(architecture: 'i386')
91
106
  #
92
107
  # # returns something like:
@@ -95,7 +110,7 @@ module Visor
95
110
  # {:_id => "8cb55bb6...", :architecture => "i386", :name => "Ubuntu 11.10 Desktop"}
96
111
  # ]
97
112
  #
98
- # @example Retrieve all public 64bit images brief metadata, descending sorted by their name:
113
+ # @example Retrieve all 64bit images brief metadata, descending sorted by their name:
99
114
  # client.get_images(architecture: 'x86_64', sort: 'name', dir: 'desc')
100
115
  #
101
116
  # # returns something like:
@@ -104,11 +119,12 @@ module Visor
104
119
  # {:_id => "069320f0...", :architecture => "x86_64", :name => "CentOS 6"}
105
120
  # ]
106
121
  #
107
- # @return [Array] All public images brief metadata.
122
+ # @return [Array] All images brief metadata.
108
123
  # Just {Visor::Meta::Backends::Base::BRIEF BRIEF} fields are returned.
109
124
  #
110
- # @raise [NotFound] If there are no public images registered on the server.
111
- # @raise [InternalError] On internal server error.
125
+ # @raise [NotFound] If there are no images registered on VISOR.
126
+ # @raise [Forbidden] If user authentication fails.
127
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
112
128
  #
113
129
  def get_images(query = {})
114
130
  str = build_query(query)
@@ -116,7 +132,7 @@ module Visor
116
132
  do_request(req)
117
133
  end
118
134
 
119
- # Retrieves detailed metadata of all public images.
135
+ # Retrieves detailed metadata of all public and user's private images.
120
136
  #
121
137
  # @note Filtering and querying works the same as with {#get_images}. The only difference is the number
122
138
  # of disclosed attributes.
@@ -125,16 +141,17 @@ module Visor
125
141
  # @option query [String] :sort ("_id") The image attribute to sort returned results.
126
142
  # @option query [String] :dir ("asc") The direction to sort results ("asc"/"desc").
127
143
  #
128
- # @example Retrieve all public images detailed metadata:
144
+ # @example Retrieve all images detailed metadata:
129
145
  # # request for it
130
146
  # client.get_images_detail
131
- # # returns an array of hashes with all public images metadata.
147
+ # # returns an array of hashes with all images detailed metadata.
132
148
  #
133
- # @return [Array] All public images detailed metadata.
149
+ # @return [Array] All images detailed metadata.
134
150
  # The {Visor::Meta::Backends::Base::DETAIL_EXC DETAIL_EXC} fields are excluded from results.
135
151
  #
136
- # @raise [NotFound] If there are no public images registered on the server.
137
- # @raise [InternalError] On internal server error.
152
+ # @raise [NotFound] If there are no images registered on VISOR.
153
+ # @raise [Forbidden] If user authentication fails.
154
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
138
155
  #
139
156
  def get_images_detail(query = {})
140
157
  str = build_query(query)
@@ -152,6 +169,7 @@ module Visor
152
169
  # @example Retrieve the image file with _id value:
153
170
  # # wanted image _id
154
171
  # id = "5e47a41e-7b94-4f65-824e-28f94e15bc6a"
172
+ #
155
173
  # # ask for that image file
156
174
  # client.get_image(id) do |chunk|
157
175
  # # do something with chunks as they arrive here (e.g. write to file, etc)
@@ -160,7 +178,8 @@ module Visor
160
178
  # @return [Binary] The requested image file binary data.
161
179
  #
162
180
  # @raise [NotFound] If image not found.
163
- # @raise [InternalError] On internal server error.
181
+ # @raise [Forbidden] If user authentication fails.
182
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
164
183
  #
165
184
  def get_image(id)
166
185
  req = Net::HTTP::Get.new("/images/#{id}")
@@ -174,7 +193,7 @@ module Visor
174
193
  end
175
194
  end
176
195
 
177
- # Register a new image on the server with the given metadata and optionally
196
+ # Register a new image on VISOR with the given metadata and optionally
178
197
  # upload its file, or provide a :location parameter containing the full path to
179
198
  # the already existing image file, stored somewhere.
180
199
  #
@@ -189,68 +208,74 @@ module Visor
189
208
  #
190
209
  # @example Insert a sample image metadata:
191
210
  # # sample image metadata
192
- # meta = {:name => 'example', :architecture => 'i386'}
211
+ # meta = {:name => 'CentOS 6.2', :architecture => 'i386', :format => 'iso', :access => 'private'}
212
+ #
193
213
  # # insert the new image metadata
194
214
  # client.post_image(meta)
195
215
  #
196
216
  # # returns:
197
217
  # {
198
- # :_id => "d8b36b3f-e044-4a57-88fc-27b57338be10",
199
- # :uri => "http://0.0.0.0:4568/images/d8b36b3f-e044-4a57-88fc-27b57338be10",
200
- # :name => "Ubuntu 10.04 Server",
201
- # :architecture => "x86_64",
202
- # :access => "public",
218
+ # :_id => "7583d669-8a65-41f1-b8ae-eb34ff6b322f",
219
+ # :uri => "http://10.0.0.1:4568/images/7583d669-8a65-41f1-b8ae-eb34ff6b322f",
220
+ # :name => "CentOS 6.2",
221
+ # :architecture => "i386",
222
+ # :access => "private",
203
223
  # :status => "locked",
204
- # :created_at => "2012-02-04 16:33:27 +0000"
224
+ # :format => "iso",
225
+ # :created_at => "2012-06-15 21:01:21 +0100",
226
+ # :owner => "foo"
205
227
  # }
206
228
  #
207
229
  # @example Insert a sample image metadata and provide the location of its file:
208
- # # sample image poiting to the latest release of Ubuntu Server distro
209
- # meta = {:name => 'Ubuntu Server (Latest)', :architecture => 'x86_64', :format => 'iso',
210
- # :store => 'http', :location => 'http://www.ubuntu.com/start-download?distro=server&bits=64&release=latest'}
230
+ # # sample image pointing to the latest release of Ubuntu Server distro
231
+ # meta = {:name => 'Ubuntu 12.04 Server', :architecture => 'x86_64', :format => 'iso',
232
+ # :store => 'http', :location => 'http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-amd64.iso'}
233
+ #
211
234
  # # insert the new image metadata
212
235
  # client.post_image(meta)
213
236
  #
214
237
  # # returns:
215
238
  # {
216
- # :_id => "0733827b-836d-469e-8860-b900d4dabc46",
217
- # :uri => "http://0.0.0.0:4568/images/0733827b-836d-469e-8860-b900d4dabc46",
218
- # :name => "Ubuntu Server (Latest)",
239
+ # :_id => "edfa919a-0415-4d26-b54d-ae78ffc4dc79",
240
+ # :uri => "http://10.0.0.1:4568/images/edfa919a-0415-4d26-b54d-ae78ffc4dc79",
241
+ # :name => "Ubuntu 12.04 Server",
219
242
  # :architecture => "x86_64",
220
243
  # :access => "public",
244
+ # :status => "available",
221
245
  # :format => "iso",
246
+ # :size => 732213248, # it will find the remote file size
222
247
  # :store => "http",
223
- # :location => "http://www.ubuntu.com/start-download?distro=server&bits=64&release=latest",
224
- # :status => "available",
225
- # :size => 715436032, # it will fetch the correct remote file size
226
- # :created_at => "2012-02-04 16:40:04 +0000",
227
- # :updated_at => "2012-02-04 16:40:04 +0000",
228
- # :checksum => "76264-2aa4b000-4af0618f1b180" # it will also fetch the remote file checksum or etag
248
+ # :location => "http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-amd64.iso",
249
+ # :created_at => "2012-06-15 21:05:20 +0100",
250
+ # :checksum => "140f3-2ba4b000-4be8328106940", # it will also find the remote file checksum or etag
251
+ # :owner => "foo"
229
252
  # }
230
253
  #
231
254
  # @example Insert a sample image metadata and upload its file:
232
255
  # # sample image metadata
233
- # meta = {:name => 'Ubuntu 10.04 Server', :architecture => 'x86_64', :store => 's3', :format => 'iso'}
256
+ # meta = {:name => 'Fedora Desktop 17', :architecture => 'x86_64', :format => 'iso', :store => 'file'}
257
+ #
234
258
  # # sample image file path
235
- # file = '~/ubuntu-10.04.3-server-amd64.iso'
259
+ # file = '~/Fedora-17-x86_64-Live-Desktop.iso'
260
+ #
236
261
  # # insert the new image metadata and upload file
237
262
  # client.post_image(meta, file)
238
263
  #
239
264
  # # returns:
240
265
  # {
241
- # :_id => "8074d23e-a9c0-454d-b935-cda5f6eb1bc8",
242
- # :uri => "http://0.0.0.0:4568/images/8074d23e-a9c0-454d-b935-cda5f6eb1bc8",
243
- # :name => "Ubuntu 10.04 Server",
266
+ # :_id => "e5fe8ea5-4704-48f1-905a-f5747cf8ba5e",
267
+ # :uri => "http://10.0.0.1:4568/images/e5fe8ea5-4704-48f1-905a-f5747cf8ba5e",
268
+ # :name => "Fedora Desktop 17",
244
269
  # :architecture => "x86_64",
245
270
  # :access => "public",
271
+ # :status => "available",
246
272
  # :format => "iso",
273
+ # :size => 676331520,
247
274
  # :store => "file",
248
- # :location => "s3://<access_key>:<secret_key>@s3.amazonaws.com/<bucket>/8074d23e-a9c0-454d-b935-cda5f6eb1bc8.iso",
249
- # :status => "available",
250
- # :size => 713529344,
251
- # :created_at => "2012-02-04 16:29:04 +0000",
252
- # :updated_at => "2012-02-04 16:29:04 +0000",
253
- # :checksum => "fbd9044604120a1f6cc708048a21e066"
275
+ # :location => "file:///home/foo/VMs/e5fe8ea5-4704-48f1-905a-f5747cf8ba5e.iso",
276
+ # :created_at => "2012-06-15 21:03:32 +0100",
277
+ # :checksum => "330dcb53f253acdf76431cecca0fefe7",
278
+ # :owner => "foo"
254
279
  # }
255
280
  #
256
281
  # @return [Hash] The already inserted image metadata.
@@ -259,9 +284,10 @@ module Visor
259
284
  # @raise [Invalid] If the location header is present no file content can be provided.
260
285
  # @raise [Invalid] If trying to post an image file to a HTTP backend.
261
286
  # @raise [Invalid] If provided store is an unsupported store backend.
262
- # @raise [NotFound] If no image data is found at the provided location.
263
- # @raise [ConflictError] If the provided image file already exists in the backend store.
264
- # @raise [InternalError] On internal server error.
287
+ # @raise [NotFound] If no image file is found at the provided location.
288
+ # @raise [ConflictError] If the provided image file already exists in the target backend store.
289
+ # @raise [Forbidden] If user authentication fails.
290
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
265
291
  #
266
292
  def post_image(meta, file = nil)
267
293
  req = Net::HTTP::Post.new('/images')
@@ -290,74 +316,91 @@ module Visor
290
316
  #
291
317
  # @example Update a sample image metadata:
292
318
  # # wanted image _id
293
- # id = "2373c3e5-b302-4529-8e23-c4ffc85e7613"
319
+ # id = "edfa919a-0415-4d26-b54d-ae78ffc4dc79."
320
+ #
294
321
  # # metadata to update
295
- # update = {:name => 'Debian 6.0', :architecture => "x86_64"}
322
+ # update = {:name => 'Ubuntu 12.04', :architecture => "i386"}
323
+ #
296
324
  # # update the image metadata with some new values
297
325
  # client.put_image(id, update)
298
326
  #
299
327
  # # returns:
300
328
  # {
301
- # :_id => "2373c3e5-b302-4529-8e23-c4ffc85e7613",
302
- # :uri => "http://0.0.0.0:4568/images/2373c3e5-b302-4529-8e23-c4ffc85e7613",
303
- # :name => "Debian 6.0",
304
- # :architecture => "x86_64",
329
+ # :_id => "edfa919a-0415-4d26-b54d-ae78ffc4dc79",
330
+ # :uri => "http://10.0.0.1:4568/images/edfa919a-0415-4d26-b54d-ae78ffc4dc79",
331
+ # :name => "Ubuntu 12.04",
332
+ # :architecture => "i386",
305
333
  # :access => "public",
306
- # :status => "locked",
307
- # :created_at => "2012-02-03 12:40:30 +0000",
308
- # :updated_at => "2012-02-04 16:35:10 +0000"
334
+ # :status => "available",
335
+ # :format => "iso",
336
+ # :size => 732213248,
337
+ # :store => "http",
338
+ # :location => "http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-amd64.iso",
339
+ # :created_at => "2012-06-15 21:05:20 +0100",
340
+ # :updated_at => "2012-06-15 21:10:36 +0100",
341
+ # :checksum => "140f3-2ba4b000-4be8328106940",
342
+ # :owner => "foo"
309
343
  # }
310
344
  #
311
- # @example Update a sample image metadata and provide the location of its file:
345
+ # @example Update the image metadata and provide the location of its file. In this example,
346
+ # the image file was already stored in the local filesystem backend,
347
+ # thus it is not needed to upload the file, but rather just register that the image file is there.
312
348
  # # wanted image _id
313
- # id = "2373c3e5-b302-4529-8e23-c4ffc85e7613"
349
+ # id = "7583d669-8a65-41f1-b8ae-eb34ff6b322f"
350
+ #
314
351
  # # metadata update
315
352
  # update = {:format => 'iso', :store => 'file', :location => 'file:///Users/server/debian-6.0.4-amd64.iso'}
353
+ #
316
354
  # # update the image metadata with file values
317
355
  # client.put_image(id, update)
318
356
  #
319
357
  # # returns:
320
358
  # {
321
- # :_id => "2373c3e5-b302-4529-8e23-c4ffc85e7613",
322
- # :uri => "http://0.0.0.0:4568/images/2373c3e5-b302-4529-8e23-c4ffc85e7613",
323
- # :name => "Debian 6.0",
324
- # :architecture => "x86_64",
325
- # :access => "public",
326
- # :status => "locked",
359
+ # :_id => "7583d669-8a65-41f1-b8ae-eb34ff6b322f",
360
+ # :uri => "http://10.0.0.1:4568/images/7583d669-8a65-41f1-b8ae-eb34ff6b322f",
361
+ # :name => "CentOS 6.2",
362
+ # :architecture => "i386",
363
+ # :access => "private",
364
+ # :status => "available",
327
365
  # :format => "iso",
366
+ # :size => 729808896,
328
367
  # :store => "file",
329
- # :location => "file:///Users/server/debian-6.0.4-amd64.iso",
330
- # :status => "available",
331
- # :size => 764529654,
332
- # :created_at => "2012-02-03 12:40:30 +0000",
333
- # :updated_at => "2012-02-04 16:38:55 +0000"
368
+ # :location => "file:///home/foo/downloads/CentOS-6.2-i386-LiveCD.iso",
369
+ # :created_at => "2012-06-15 21:01:21 +0100",
370
+ # :updated_at => "2012-06-15 21:12:27 +0100",
371
+ # :checksum => "1b8441b6f4556be61c16d9750da42b3f",
372
+ # :owner => "foo"
334
373
  # }
335
374
  #
336
- # @example Update image metadata and upload its file:
375
+ # @example OR update image metadata and upload its file, if it is not already in some compatible storage backend:
337
376
  # # wanted image _id
338
- # id = "d5bebdc8-66eb-4450-b8d1-d8127f50779d"
377
+ # id = "7583d669-8a65-41f1-b8ae-eb34ff6b322f"
378
+ #
339
379
  # # metadata update
340
- # update = {:format => 'iso', :store => 's3'}
380
+ # update = {:format => 'iso', :store => 'file'}
381
+ #
341
382
  # # sample image file path
342
- # file = '~/CentOS-6.2-x86_64-LiveCD.iso'
383
+ # file = '~/CentOS-6.2-i386-LiveCD.iso'
384
+ #
343
385
  # # insert the new image metadata and upload file
344
386
  # client.put_image(id, meta, file)
345
387
  #
346
388
  # # returns:
347
389
  # {
348
- # :_id => "d5bebdc8-66eb-4450-b8d1-d8127f50779d",
349
- # :uri => "http://0.0.0.0:4568/images/d5bebdc8-66eb-4450-b8d1-d8127f50779d",
390
+ # :_id => "7583d669-8a65-41f1-b8ae-eb34ff6b322f",
391
+ # :uri => "http://10.0.0.1:4568/images/7583d669-8a65-41f1-b8ae-eb34ff6b322f",
350
392
  # :name => "CentOS 6.2",
351
- # :architecture => "x86_64",
352
- # :access => "public",
353
- # :format => "iso",
354
- # :store => "s3",
355
- # :location => "s3://<access_key>:<secret_key>@s3.amazonaws.com/<bucket>/d5bebdc8-66eb-4450-b8d1-d8127f50779d.iso",
393
+ # :architecture => "i386",
394
+ # :access => "private",
356
395
  # :status => "available",
357
- # :size => 731906048,
358
- # :created_at => "2012-01-20 16:29:01 +0000",
359
- # :updated_at => "2012-02-04 16:50:12 +0000",
360
- # :checksum => "610c0b9684dba804467514847e8a012f"
396
+ # :format => "iso",
397
+ # :size => 729808896,
398
+ # :store => "file",
399
+ # :location => "file:///home/foo/VMs/7583d669-8a65-41f1-b8ae-eb34ff6b322f.iso",
400
+ # :created_at => "2012-06-15 21:01:21 +0100",
401
+ # :updated_at => "2012-06-15 21:12:27 +0100",
402
+ # :checksum => "1b8441b6f4556be61c16d9750da42b3f",
403
+ # :owner => "foo"
361
404
  # }
362
405
  #
363
406
  # @return [Hash] The already inserted image metadata.
@@ -370,7 +413,8 @@ module Visor
370
413
  # @raise [NotFound] If no image data is found at the provided location.
371
414
  # @raise [ConflictError] If trying to assign image file to a locked or uploading image.
372
415
  # @raise [ConflictError] If the provided image file already exists in the backend store.
373
- # @raise [InternalError] On internal server error.
416
+ # @raise [Forbidden] If user authentication fails.
417
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
374
418
  #
375
419
  def put_image(id, meta, file = nil)
376
420
  req = Net::HTTP::Put.new("/images/#{id}")
@@ -388,42 +432,95 @@ module Visor
388
432
  #
389
433
  # @param id [String] The image's _id which will be deleted.
390
434
  #
391
- # @example Delete an image metadata:
435
+ # @example Delete an image:
392
436
  # # wanted image _id
393
- # id = "66414330-bbb5-42be-8a0e-b336cf6665f4"
437
+ # id = "edfa919a-0415-4d26-b54d-ae78ffc4dc79"
438
+ #
394
439
  # # delete the image metadata and file
395
440
  # client.delete_image(id)
396
441
  #
397
442
  # # returns:
398
443
  # {
399
- # :_id => "66414330-bbb5-42be-8a0e-b336cf6665f4",
400
- # :uri => "http://0.0.0.0:4568/images/66414330-bbb5-42be-8a0e-b336cf6665f4",
401
- # :name => "Ubuntu 11.04 Server",
402
- # :architecture => "x86_64",
444
+ # :_id => "edfa919a-0415-4d26-b54d-ae78ffc4dc79",
445
+ # :uri => "http://10.0.0.1:4568/images/edfa919a-0415-4d26-b54d-ae78ffc4dc79",
446
+ # :name => "Ubuntu 12.04",
447
+ # :architecture => "i386",
403
448
  # :access => "public",
404
- # :format => "iso",
405
- # :store => "file",
406
- # :location => "file:///Users/server/VMs/66414330-bbb5-42be-8a0e-b336cf6665f4.iso",
407
449
  # :status => "available",
408
- # :size => 722549344,
409
- # :created_at => "2012-02-04 15:23:48 +0000",
410
- # :updated_at => "2012-02-04 15:54:52 +0000",
411
- # :accessed_at => "2012-02-04 16:02:44 +0000",
412
- # :access_count => 26,
413
- # :checksum => "fbd9044604120a1f6cc708048a21e066"
450
+ # :format => "iso",
451
+ # :size => 732213248,
452
+ # :store => "http",
453
+ # :location => "http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-amd64.iso",
454
+ # :created_at => "2012-06-15 21:05:20 +0100",
455
+ # :updated_at => "2012-06-15 21:10:36 +0100",
456
+ # :checksum => "140f3-2ba4b000-4be8328106940",
457
+ # :owner => "foo"
414
458
  # }
415
459
  #
416
460
  # @return [Hash] The already deleted image metadata. Useful for recover on accidental delete.
417
461
  #
418
- # @raise [NotFound] If image meta or data not found.
462
+ # @raise [NotFound] If image meta or file were not found.
419
463
  # @raise [Forbidden] If user does not have permission to manipulate the image file.
420
- # @raise [InternalError] On internal server error.
464
+ # @raise [Forbidden] If user authentication fails.
465
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
421
466
  #
422
467
  def delete_image(id)
423
468
  req = Net::HTTP::Delete.new("/images/#{id}")
424
469
  do_request(req)
425
470
  end
426
471
 
472
+ # Removes images that match a specific query.
473
+ #
474
+ # @param query [Hash] A query to find images that should be deleted.
475
+ #
476
+ # @example Delete an image by queries:
477
+ # # we want to delete all 64-bit images:
478
+ # query = {architecture: 'x86_64'}
479
+ #
480
+ # # delete the image metadata and file
481
+ # client.delete_by_query(query)
482
+ #
483
+ # # returns the matched and deleted images metadata (where in this example we had only the following 64-bit images registered):
484
+ # [
485
+ # {
486
+ # :_id => "e5fe8ea5-4704-48f1-905a-f5747cf8ba5e",
487
+ # :uri => "http://10.0.0.1:4568/images/e5fe8ea5-4704-48f1-905a-f5747cf8ba5e",
488
+ # :name => "Fedora Desktop 17",
489
+ # :architecture => "x86_64",
490
+ # :access => "public",
491
+ # :status => "available",
492
+ # :format => "iso",
493
+ # :size => 676331520,
494
+ # :store => "file",
495
+ # :location => "file:///home/foo/VMs/e5fe8ea5-4704-48f1-905a-f5747cf8ba5e.iso",
496
+ # :created_at => "2012-06-15 21:03:32 +0100",
497
+ # :checksum => "330dcb53f253acdf76431cecca0fefe7",
498
+ # :owner => "foo"
499
+ # },
500
+ # {
501
+ # :_id => "edfa919a-0415-4d26-b54d-ae78ffc4dc79",
502
+ # :uri => "http://10.0.0.1:4568/images/edfa919a-0415-4d26-b54d-ae78ffc4dc79",
503
+ # :name => "Ubuntu 12.04 Server",
504
+ # :architecture => "x86_64",
505
+ # :access => "public",
506
+ # :status => "available",
507
+ # :format => "iso",
508
+ # :size => "732213248",
509
+ # :store => "s3",
510
+ # :location => "s3://mys3accesskey:mys3secretkey@s3.amazonaws.com/mybucket/edfa919a-0415-4d26-b54d-ae78ffc4dc79.iso",
511
+ # :created_at => "2012-06-15 21:05:20 +0100",
512
+ # :checksum => "140f3-2ba4b000-4be8328106940",
513
+ # :owner => "foo"
514
+ # }
515
+ # ]
516
+ #
517
+ # @return [Hash] The already deleted image metadata. Useful for recover on accidental delete.
518
+ #
519
+ # @raise [NotFound] If image meta or file were not found.
520
+ # @raise [Forbidden] If user does not have permission to manipulate the image file.
521
+ # @raise [Forbidden] If user authentication fails.
522
+ # @raise [InternalError] If VIS server was not found on the referenced host and port address.
523
+ #
427
524
  def delete_by_query(query)
428
525
  result = []
429
526
  images = get_images(query)
@@ -440,7 +537,7 @@ module Visor
440
537
  # Prepare headers for request
441
538
  def prepare_headers(req)
442
539
  sign_request(access_key, secret_key, req.method, req.path, req)
443
- req['User-Agent'] = 'VISoR Image Server client'
540
+ req['User-Agent'] = 'VISOR Image System client'
444
541
  req['Accept'] = "application/json"
445
542
  end
446
543
 
@@ -473,6 +570,8 @@ module Visor
473
570
  raise Forbidden, parse_response(res)
474
571
  when Net::HTTPInternalServerError then
475
572
  raise InternalError, parse_response(res)
573
+ when Net::HTTPServiceUnavailable then
574
+ raise InternalError, parse_response(res)
476
575
  end
477
576
  end
478
577