Class: Visor::Image::PostImage
- Inherits:
-
Goliath::API
- Object
- Goliath::API
- Visor::Image::PostImage
- Includes:
- Common::Exception, Common::Util
- Defined in:
- lib/image/routes/post_image.rb
Overview
Post image data and metadata and returns the registered metadata.
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.
-
#insert_meta(meta) ⇒ Hash
Insert image metadata on database (which set its status to locked).
-
#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.
-
#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.
175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/image/routes/post_image.rb', line 175 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.
115 116 117 118 119 120 121 122 123 |
# File 'lib/image/routes/post_image.rb', line 115 def exit_error(code, , set_status=false) logger.error begin vms.put_image(env['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 |
#insert_meta(meta) ⇒ Hash
Insert image metadata on database (which set its status to locked).
131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/image/routes/post_image.rb', line 131 def () image = vms.post_image(, address) env['id'] = image[:_id] 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(env['id'], status: 'available') else image end 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/post_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.
103 104 105 |
# File 'lib/image/routes/post_image.rb', line 103 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/post_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 |
# File 'lib/image/routes/post_image.rb', line 42 def response(env) begin access_key = (env, vas) rescue Forbidden => e return exit_error(403, e.) end = (env['headers']) [:owner] = access_key body = env['body'] location = [:location] 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 registers the image meta or raises on error begin image = () 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 # if has body(image file), upload file and update meta or raise on error begin image = upload_and_update(env['id'], body) rescue UnsupportedStore, ArgumentError => e return exit_error(400, e., true) rescue NotFound => e return exit_error(404, e., true) 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 |
#upload_and_update(id, body) ⇒ Hash
Update image status and launch upload.
151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/image/routes/post_image.rb', line 151 def upload_and_update(id, body) logger.debug "Setting image #{id} status to 'uploading'" = vms.put_image(id, status: 'uploading') checksum = env['md5'] 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', uploaded_at: Time.now, location: location, size: size, checksum: checksum) end |