lib/fog/openstack/image/v2/models/image.rb
require 'fog/openstack/models/model'
module Fog
module OpenStack
class Image
class V2
class Image < Fog::OpenStack::Model
identity :id
attribute :name
attribute :visibility # public or private
attribute :tags
attribute :self
attribute :size
attribute :virtual_size
attribute :disk_format
attribute :container_format
attribute :id
attribute :checksum
attribute :self
attribute :file
# detailed
attribute :min_disk
attribute :created_at
attribute :updated_at
attribute :protected
attribute :status # "queued","saving","active","killed","deleted","pending_delete"
attribute :min_ram
attribute :owner
attribute :properties
attribute :metadata
attribute :location
# from snapshot support
attribute :network_allocated
attribute :base_image_ref
attribute :image_type
attribute :instance_uuid
attribute :user_id
def method_missing(method_sym, *arguments, &block)
if attributes.key?(method_sym)
attributes[method_sym]
elsif attributes.key?(method_sym.to_s)
attributes[method_sym.to_s]
elsif method_sym.to_s.end_with?('=')
attributes[method_sym.to_s.gsub(/=$/, '').to_sym] = arguments[0]
else
super
end
end
def respond_to?(method_sym, include_all = false)
if attributes.key?(method_sym)
true
elsif attributes.key?(method_sym.to_s)
true
elsif method_sym.to_s.end_with?('=')
true
else
super
end
end
def create
requires :name
merge_attributes(service.create_image(attributes).body)
self
end
# Here we convert 'attributes' into a form suitable for Glance's usage of JSON Patch (RFC6902).
# We fetch the existing attributes from the server to compute the delta (difference)
# Setting value to nil will delete that attribute from the server.
def update(attr = nil)
requires :id
client_attributes = attr || @attributes
server_attributes = service.images.get(id).attributes
json_patch = build_update_json_patch(client_attributes, server_attributes)
merge_attributes(
service.update_image(id, json_patch).body
)
self
end
# This overrides the behaviour of Fog::OpenStack::Model::save() which tries to be clever and
# assumes save=update if an ID is present - but Image V2 allows ID to be specified on creation
def save
if @attributes[:self].nil?
create
else
update
end
end
def destroy
requires :id
service.delete_image(id)
true
end
def upload_data(io_obj)
requires :id
if io_obj.kind_of? Hash
service.upload_image(id, nil, io_obj)
else
service.upload_image(id, io_obj)
end
end
def download_data(params = {})
requires :id
service.download_image(id, params[:content_range], params)
end
def reactivate
requires :id
service.reactivate_image(id)
end
def deactivate
requires :id
service.deactivate_image(id)
end
def add_member(member_id)
requires :id
service.add_member_to_image(id, member_id)
end
def remove_member(member_id)
requires :id
service.remove_member_from_image(id, member_id)
end
def update_member(member)
requires :id
service.update_image_member(id, member)
end
def members
requires :id
service.get_image_members(id).body['members']
end
def member(member_id)
requires :id
service.get_member_details(id, member_id)
end
def add_tags(tags)
requires :id
tags.each { |tag| add_tag tag }
end
def add_tag(tag)
requires :id
service.add_tag_to_image(id, tag)
end
def remove_tags(tags)
requires :id
tags.each { |tag| remove_tag tag }
end
def remove_tag(tag)
requires :id
service.remove_tag_from_image(id, tag)
end
private
def build_update_json_patch(client_attributes, server_attributes)
[
build_patch_operation('remove', patch_attributes_to_remove(client_attributes, server_attributes)),
build_patch_operation('add', patch_attributes_to_add(client_attributes, server_attributes)),
build_patch_operation('replace', patch_attributes_to_replace(client_attributes, server_attributes)),
].flatten
end
def patch_attributes_to_remove(client_attributes, server_attributes)
client_attributes.select do |key, value|
value.nil? && !server_attributes[key].nil?
end
end
def patch_attributes_to_add(client_attributes, server_attributes)
client_attributes.reject do |key, _|
server_attributes.key?(key) || client_attributes[key].nil?
end
end
def patch_attributes_to_replace(client_attributes, server_attributes)
client_attributes.reject do |key, value|
value.nil? || server_attributes[key] == value
end
end
def build_patch_operation(op_name, attributes)
json_patch = []
attributes.each do |key, value|
json_patch << {:op => op_name, :path => "/#{key}", :value => value}
end
json_patch
end
end
end
end
end
end