Class: Visor::Image::PutImage
- Inherits:
-
Goliath::API
- Object
- Goliath::API
- Visor::Image::PutImage
- Includes:
- Common::Exception, Common::Util
- Defined in:
- lib/image/routes/put_image.rb
Overview
Put image metadata and/or data for the image with the given id.
Instance Method Summary collapse
-
#do_upload(id, meta, body) ⇒ Array
Upload image file to wanted store.
-
#exit_error(code, message, set_status = false) ⇒ Array
Produce an HTTP response with an error code and message.
-
#on_body(env, data) ⇒ Object
Pre-process body as it arrives in streaming chunks and load them into a tempfile.
-
#on_close(env) ⇒ Object
On connection close log a message.
-
#on_headers(env, headers) ⇒ Object
Pre-process headers as they arrive and load them into a environment variable.
-
#response(env) ⇒ Array
Main response method which processes the received headers and body, managing image metadata and file data.
-
#update_meta(id, meta) ⇒ Hash
Update image metadata and set status if needed.
-
#upload_and_update(id, body) ⇒ Hash
Update image status and launch upload.
Instance Method Details
#do_upload(id, meta, body) ⇒ Array
Upload image file to wanted store.
191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/image/routes/put_image.rb', line 191 def do_upload(id, , body) content_type = env['headers']['Content-Type'] || '' store_name = [:store] || configs[:default] format = [:format] || 'none' unless content_type == 'application/octet-stream' raise ArgumentError, 'Request Content-Type must be application/octet-stream' end store = Visor::Image::Store.get_backend(store_name, configs) logger.debug "Uploading image #{id} data to #{store_name} store" store.save(id, body, format) end |
#exit_error(code, message, set_status = false) ⇒ Array
Produce an HTTP response with an error code and message.
125 126 127 128 129 130 131 132 133 |
# File 'lib/image/routes/put_image.rb', line 125 def exit_error(code, , set_status=false) logger.error begin vms.put_image(params[:id], status: 'error') if set_status rescue => e logger.error "Unable to set image #{env['id']} status to 'error': #{e.}" end [code, {}, {code: code, message: }] end |
#on_body(env, data) ⇒ Object
Pre-process body as it arrives in streaming chunks and load them into a tempfile.
29 30 31 32 |
# File 'lib/image/routes/put_image.rb', line 29 def on_body(env, data) (env['body'] ||= Tempfile.open('visor-image', encoding: 'ascii-8bit')) << data (env['md5'] ||= Digest::MD5.new) << data end |
#on_close(env) ⇒ Object
On connection close log a message.
113 114 115 |
# File 'lib/image/routes/put_image.rb', line 113 def on_close(env) logger.info 'Connection closed' end |
#on_headers(env, headers) ⇒ Object
Pre-process headers as they arrive and load them into a environment variable.
19 20 21 22 |
# File 'lib/image/routes/put_image.rb', line 19 def on_headers(env, headers) logger.debug "Received headers: #{headers.inspect}" env['headers'] = headers end |
#response(env) ⇒ Array
Main response method which processes the received headers and body, managing image metadata and file data.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/image/routes/put_image.rb', line 42 def response(env) begin (env, vas) rescue Forbidden => e return exit_error(403, e.) end = (env['headers']) body = env['body'] id = params[:id] location = [:location] # a valid update requires the presence of headers and/or body if .empty? && body.nil? msg = 'No headers or body found for update' return exit_error(400, msg) end # only the x-image-meta-location header or the body content should be provided if location && body msg = 'When the location header is present no file content can be provided' return exit_error(400, msg) end if [:store] == 'http' || (location && location.split(':').first == 'http') return exit_error(400, 'Cannot post an image file to a HTTP backend') if body store = Visor::Image::Store::HTTP.new(location) exist, [:size], [:checksum] = store.file_exists?(false) return exit_error(404, "No image file found at #{location}") unless exist end # first update the image meta or raises on error begin image = (id, ) rescue NotFound => e return exit_error(404, e.) rescue ArgumentError => e body.close if body body.unlink if body return exit_error(400, e.) rescue InternalError => e body.close if body body.unlink if body return exit_error(503, e.) end unless .empty? # if has body(image file), upload file and update meta or raise on error begin image = upload_and_update(id, body) rescue UnsupportedStore, ArgumentError => e return exit_error(400, e., true) rescue NotFound => e return exit_error(404, e., true) rescue ConflictError => e return exit_error(409, e.) rescue Duplicated => e return exit_error(409, e., true) rescue InternalError => e return exit_error(503, e., true) ensure body.close body.unlink end unless body.nil? [200, {}, {image: image}] end |
#update_meta(id, meta) ⇒ Hash
Update image metadata and set status if needed.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/image/routes/put_image.rb', line 141 def (id, ) logger.debug "Updating image #{id} meta:" logger.debug "#{id} #{}" image = vms.put_image(id, ) image.each { |k, v| logger.debug "#{k.to_s.capitalize} setted to '#{v}'" if v } if image[:location] logger.debug "Location for image #{env['id']} is #{image[:location]}" logger.debug "Setting image #{env['id']} status to 'available'" vms.put_image(id, status: 'available') else image end end |
#upload_and_update(id, body) ⇒ Hash
Update image status and launch upload.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/image/routes/put_image.rb', line 163 def upload_and_update(id, body) = vms.get_image(id) checksum = env['md5'] valid = ([:status] == 'locked' || [:status] == 'error') raise ConflictError, 'Can only assign image file to a locked or error image' unless valid logger.debug "Setting image #{id} status to 'uploading'" = vms.put_image(id, status: 'uploading') location, size = do_upload(id, , body) logger.debug "Updating image #{id} meta:" logger.debug "Setting status to 'available'" logger.debug "Setting location to '#{location}'" logger.debug "Setting size to '#{size}'" logger.debug "Setting checksum to '#{checksum}'" vms.put_image(id, status: 'available', location: location, size: size, checksum: checksum) end |