diff --git a/lib/fog/openstack/image.rb b/lib/fog/openstack/image.rb index 11bb9b7cd..09a9b852e 100644 --- a/lib/fog/openstack/image.rb +++ b/lib/fog/openstack/image.rb @@ -19,7 +19,14 @@ module Fog request :list_public_images request :list_public_images_detailed - request :get_image_by_id + request :get_image + request :create_image + request :update_image + request :get_image_members + request :get_shared_images + request :add_member_to_image + request :remove_member_from_image + request :delete_image class Mock diff --git a/lib/fog/openstack/models/image/image.rb b/lib/fog/openstack/models/image/image.rb index 928b6ac0c..c5992dac1 100644 --- a/lib/fog/openstack/models/image/image.rb +++ b/lib/fog/openstack/models/image/image.rb @@ -15,8 +15,66 @@ module Fog attribute :id attribute :checksum + #detailed + attribute :min_disk + attribute :created_at + attribute :deleted_at + attribute :updated_at + attribute :deleted + attribute :protected + attribute :is_public + attribute :status + attribute :min_ram + attribute :owner + attribute :properties + + + def initialize(attributes) + @connection = attributes[:connection] + attributes[:size] ||= 0 + super end + def save + requires :name + identity ? update : create + end + + def create + requires :name + merge_attributes(connection.create_image(self.attributes).body['image']) + self + end + + def update + requires :name + merge_attributes(connection.update_image(self.attributes).body['image']) + self + end + + def destroy + requires :id + connection.delete_image(self.id) + true + end + + def add_member(member_id) + requires :id + connection.add_member_to_image(self.id, member_id) + end + + def remove_member(member_id) + requires :id + connection.remove_member_from_image(self.id, member_id) + end + + def members + requires :id + connection.get_image_members(self.id).body['members'] + end + + end + end end end diff --git a/lib/fog/openstack/models/image/images.rb b/lib/fog/openstack/models/image/images.rb index 602136616..6cb290da8 100644 --- a/lib/fog/openstack/models/image/images.rb +++ b/lib/fog/openstack/models/image/images.rb @@ -8,7 +8,22 @@ module Fog model Fog::Image::OpenStack::Image def all - load(connection.list_public_images.body['images']) + load(connection.list_public_images_detailed.body['images']) + end + + def details + load(connection.list_public_images_detailed.body['images']) + end + + def find_by_id(id) + self.find {|image| image.id == id} || + Fog::Image::OpenStack::Image.new( + connection.get_image(id).body['image']) + end + + def destroy(id) + image = self.find_by_id(id) + image.destroy end end end diff --git a/lib/fog/openstack/requests/image/add_member_to_image.rb b/lib/fog/openstack/requests/image/add_member_to_image.rb new file mode 100644 index 000000000..4da3ff626 --- /dev/null +++ b/lib/fog/openstack/requests/image/add_member_to_image.rb @@ -0,0 +1,23 @@ +module Fog + module Image + class OpenStack + class Real + def add_member_to_image(image_id, tenant_id) + request( + :expects => [200, 204], + :method => 'PUT', + :path => "images/#{image_id}/members/#{tenant_id}" + ) + end + end # class Real + + class Mock + def add_member_to_image(image_id, tenant_id) + response = Excon::Response.new + response.status = [200, 204][rand(1)] + response + end # def list_tenants + end # class Mock + end # class OpenStack + end # module Identity +end # module Fog diff --git a/lib/fog/openstack/requests/image/create_image.rb b/lib/fog/openstack/requests/image/create_image.rb new file mode 100644 index 000000000..27d2693b8 --- /dev/null +++ b/lib/fog/openstack/requests/image/create_image.rb @@ -0,0 +1,68 @@ +module Fog + module Image + class OpenStack + class Real + + def create_image(attributes) + + + data = { + "x-image-meta-name" => attributes[:name], + "x-image-meta-disk-format" => attributes[:disk_format], + "x-image-meta-container-format" => attributes[:container_format], + "x-image-meta-size" => attributes[:size], + "x-image-meta-is-public" => attributes[:is_public], + "x-image-meta-owner" => attributes[:owner] + } + + unless attributes[:properties].nil? + attributes[:properties].each do |key,value| + data["x-image-meta-property-#{key}"] = value + end + end + + + + request( + :headers => data, + :expects => 201, + :method => 'POST', + :path => "images" + ) + end + + end + + class Mock + + def create_image(attributes) + response = Excon::Response.new + response.status = 201 + response.body = {"image"=> + {"name"=>"new image", + "size"=>0, + "min_disk"=>0, + "disk_format"=>nil, + "created_at"=>"2012-02-24T06:45:00", + "container_format"=>nil, + "deleted_at"=>nil, + "updated_at"=>"2012-02-24T06:45:00", + "checksum"=>nil, + "id"=>"e41304f3-2453-42b4-9829-2e220a737395", + "deleted"=>false, + "protected"=>false, + "is_public"=>false, + "status"=>"queued", + "min_ram"=>0, + "owner"=>"728ecc7c10614a1faa6fbabd1a68a4a0", + "properties"=>{} + } + } + response + + end + + end + end + end +end diff --git a/lib/fog/openstack/requests/image/delete_image.rb b/lib/fog/openstack/requests/image/delete_image.rb new file mode 100644 index 000000000..c4e407174 --- /dev/null +++ b/lib/fog/openstack/requests/image/delete_image.rb @@ -0,0 +1,27 @@ +module Fog + module Image + class OpenStack + class Real + + def delete_image(image_id) + request( + :expects => 200, + :method => 'DELETE', + :path => "images/#{image_id}" + ) + end + + end + + class Mock + + def delete_image(image_id) + response = Excon::Response.new + response.status = 200 + response + end + + end + end + end +end diff --git a/lib/fog/openstack/requests/image/get_image.rb b/lib/fog/openstack/requests/image/get_image.rb new file mode 100644 index 000000000..611bc1818 --- /dev/null +++ b/lib/fog/openstack/requests/image/get_image.rb @@ -0,0 +1,45 @@ +module Fog + module Image + class OpenStack + class Real + def get_image(image_id) + request( + :expects => [200, 204], + :method => 'HEAD', + :path => "images/#{image_id}" + ) + end + end # class Real + + class Mock + def get_image(image_id) + response = Excon::Response.new + response.status = [200, 204][rand(1)] + response.headers= {"X-Image-Meta-Is_public"=>"True", + "X-Image-Meta-Min_disk"=>"0", + "X-Image-Meta-Property-Ramdisk_id"=>"b45aa128-cd36-4ad9-a026-1a1c2bfd8fdc", + "X-Image-Meta-Disk_format"=>"ami", + "X-Image-Meta-Created_at"=>"2012-02-21T07:32:26", + "X-Image-Meta-Container_format"=>"ami", + "Etag"=>"2f81976cae15c16ef0010c51e3a6c163", + "Location"=>"http://192.168.27.100:9292/v1/images/0e09fbd6-43c5-448a-83e9-0d3d05f9747e", + "X-Image-Meta-Protected"=>"False", + "Date"=>"Fri, 24 Feb 2012 02:14:25 GMT", + "X-Image-Meta-Name"=>"cirros-0.3.0-x86_64-blank", + "X-Image-Meta-Min_ram"=>"0", "Content-Type"=>"text/html; charset=UTF-8", + "X-Image-Meta-Updated_at"=>"2012-02-21T07:32:29", + "X-Image-Meta-Property-Kernel_id"=>"cd28951e-e1c2-4bc5-95d3-f0495abbcdc5", + "X-Image-Meta-Size"=>"25165824", + "X-Image-Meta-Checksum"=>"2f81976cae15c16ef0010c51e3a6c163", + "X-Image-Meta-Deleted"=>"False", + "Content-Length"=>"0", + "X-Image-Meta-Owner"=>"ff528b20431645ebb5fa4b0a71ca002f", + "X-Image-Meta-Status"=>"active", + "X-Image-Meta-Id"=>"0e09fbd6-43c5-448a-83e9-0d3d05f9747e"} + response.body = "" + response + end # def list_tenants + end # class Mock + end # class OpenStack + end # module Identity +end # module Fog diff --git a/lib/fog/openstack/requests/image/get_image_by_id.rb b/lib/fog/openstack/requests/image/get_image_members.rb similarity index 51% rename from lib/fog/openstack/requests/image/get_image_by_id.rb rename to lib/fog/openstack/requests/image/get_image_members.rb index 2e3e095fd..5de3790ca 100644 --- a/lib/fog/openstack/requests/image/get_image_by_id.rb +++ b/lib/fog/openstack/requests/image/get_image_members.rb @@ -2,28 +2,25 @@ module Fog module Image class OpenStack class Real - def get_image_by_id(image_id) + def get_image_members(image_id) request( :expects => [200, 204], :method => 'GET', - :path => "images/#{image_id}" + :path => "images/#{image_id}/members" ) end end # class Real class Mock - def get_image_by_id(image_id) + def get_image_members(image_id) response = Excon::Response.new response.status = [200, 204][rand(1)] response.body = { - "images"=>[{ - "name"=>"mock-image-name", - "size"=>25165824, - "disk_format"=>"ami", - "container_format"=>"ami", - "id"=>"0e09fbd6-43c5-448a-83e9-0d3d05f9747e", - "checksum"=>"2f81976cae15c16ef0010c51e3a6c163"}] - } + "members"=>[ + {"member_id"=>"ff528b20431645ebb5fa4b0a71ca002f", + "can_share"=>false} + ] + } response end # def list_tenants end # class Mock diff --git a/lib/fog/openstack/requests/image/get_shared_images.rb b/lib/fog/openstack/requests/image/get_shared_images.rb new file mode 100644 index 000000000..2e4b6190a --- /dev/null +++ b/lib/fog/openstack/requests/image/get_shared_images.rb @@ -0,0 +1,29 @@ +module Fog + module Image + class OpenStack + class Real + def get_shared_images(tenant_id) + request( + :expects => [200, 204], + :method => 'GET', + :path => "shared-images/#{tenant_id}" + ) + end + end # class Real + + class Mock + def get_shared_images(tenant_id) + response = Excon::Response.new + response.status = [200, 204][rand(1)] + response.body = { + "shared_images"=>[ + {"image_id"=>"ff528b20431645ebb5fa4b0a71ca002f", + "can_share"=>false} + ] + } + response + end # def list_tenants + end # class Mock + end # class OpenStack + end # module Identity +end # module Fog diff --git a/lib/fog/openstack/requests/image/remove_member_from_image.rb b/lib/fog/openstack/requests/image/remove_member_from_image.rb new file mode 100644 index 000000000..cb89d79f4 --- /dev/null +++ b/lib/fog/openstack/requests/image/remove_member_from_image.rb @@ -0,0 +1,23 @@ +module Fog + module Image + class OpenStack + class Real + def remove_member_from_image(image_id, member_id) + request( + :expects => [200, 204], + :method => 'DELETE', + :path => "images/#{image_id}/members/#{member_id}" + ) + end + end # class Real + + class Mock + def remove_member_from_image(image_id, member_id) + response = Excon::Response.new + response.status = [200, 204][rand(1)] + response + end # def list_tenants + end # class Mock + end # class OpenStack + end # module Identity +end # module Fog diff --git a/lib/fog/openstack/requests/image/update_image.rb b/lib/fog/openstack/requests/image/update_image.rb new file mode 100644 index 000000000..860121d03 --- /dev/null +++ b/lib/fog/openstack/requests/image/update_image.rb @@ -0,0 +1,65 @@ +module Fog + module Image + class OpenStack + class Real + + def update_image(attributes) + + data = { + "x-image-meta-name" => attributes[:name], + "x-image-meta-disk-format" => attributes[:disk_format], + "x-image-meta-container-format" => attributes[:container_format], + "x-image-meta-size" => attributes[:size], + "x-image-meta-is-public" => attributes[:is_public], + "x-image-meta-owner" => attributes[:owner] + } + + unless attributes[:properties].nil? + attributes[:properties].each do |key,value| + data["x-image-meta-property-#{key}"] = value + end + end + + request( + :headers => data, + :expects => 200, + :method => 'PUT', + :path => "images/#{attributes[:id]}" + ) + end + + end + + class Mock + + def update_image(attributes) + response = Excon::Response.new + response.status = 200 + response.body = {"image"=> + {"name"=>"new image", + "size"=>0, + "min_disk"=>0, + "disk_format"=>nil, + "created_at"=>"2012-02-24T06:45:00", + "container_format"=>nil, + "deleted_at"=>nil, + "updated_at"=>"2012-02-24T06:45:00", + "checksum"=>nil, + "id"=>"e41304f3-2453-42b4-9829-2e220a737395", + "deleted"=>false, + "protected"=>false, + "is_public"=>false, + "status"=>"queued", + "min_ram"=>0, + "owner"=>"728ecc7c10614a1faa6fbabd1a68a4a0", + "properties"=>{} + } + } + response + + end + + end + end + end +end diff --git a/tests/openstack/models/image/image_tests.rb b/tests/openstack/models/image/image_tests.rb new file mode 100644 index 000000000..f8f027aa4 --- /dev/null +++ b/tests/openstack/models/image/image_tests.rb @@ -0,0 +1,31 @@ +Shindo.tests("Fog::Image[:openstack] | image", ['openstack']) do + + tests('success') do + tests('#create').succeeds do + @instance = Fog::Image[:openstack].images.create(:name => 'test image') + !@instance.id.nil? + end + + tests('#update').succeeds do + @instance.name = 'edit test image' + @instance.update + @instance.name == 'edit test image' + end + + tests('#add member').succeeds do + @instance.add_member(@instance.owner) + end + + tests('#show members').succeeds do + @instance.members + end + + tests('#remove member').succeeds do + @instance.remove_member(@instance.owner) + end + + tests('#destroy').succeeds do + @instance.destroy == true + end + end +end diff --git a/tests/openstack/models/image/images_tests.rb b/tests/openstack/models/image/images_tests.rb new file mode 100644 index 000000000..b20c8445c --- /dev/null +++ b/tests/openstack/models/image/images_tests.rb @@ -0,0 +1,14 @@ +Shindo.tests("Fog::Image[:openstack] | images", ['openstack']) do + @instance = Fog::Image[:openstack].create_image({:name => "model test image"}).body + + tests('success') do + tests('#find_by_id').succeeds do + image = Fog::Image[:openstack].images.find_by_id(@instance['image']['id']) + image.id == @instance['image']['id'] + end + + tests('#destroy').succeeds do + Fog::Image[:openstack].images.destroy(@instance['image']['id']) + end + end +end diff --git a/tests/openstack/requests/image/image_tests.rb b/tests/openstack/requests/image/image_tests.rb new file mode 100644 index 000000000..4f901c8ec --- /dev/null +++ b/tests/openstack/requests/image/image_tests.rb @@ -0,0 +1,98 @@ +Shindo.tests('Fog::Image[:openstack] | image requests', ['openstack']) do + + @image_format = { + 'id' => String, + 'name' => String, + 'size' => Integer, + 'disk_format' => Fog::Nullable::String, + 'container_format' => Fog::Nullable::String, + 'checksum' => Fog::Nullable::String, + 'min_disk' => Fog::Nullable::Integer, + 'created_at' => Fog::Nullable::String, + 'deleted_at' => Fog::Nullable::String, + 'updated_at' => Fog::Nullable::String, + 'deleted' => Fog::Nullable::Boolean, + 'protected' => Fog::Nullable::Boolean, + 'is_public' => Fog::Nullable::Boolean, + 'status' => Fog::Nullable::String, + 'min_ram' => Fog::Nullable::Integer, + 'owner' => Fog::Nullable::String, + 'properties' => Fog::Nullable::Hash + } + + @image_meta_format ={ + "X-Image-Meta-Is_public"=>String, + "X-Image-Meta-Min_disk"=>Fog::Nullable::String, + "X-Image-Meta-Property-Ramdisk_id"=>Fog::Nullable::String, + "X-Image-Meta-Disk_format"=>Fog::Nullable::String, + "X-Image-Meta-Created_at"=>String, + "X-Image-Meta-Container_format"=>Fog::Nullable::String, + "Etag"=>String, + "Location"=>String, + "X-Image-Meta-Protected"=>String, + "Date"=>String, + "X-Image-Meta-Name"=>String, + "X-Image-Meta-Min_ram"=>String, + "Content-Type"=>String, + "X-Image-Meta-Updated_at"=>String, + "X-Image-Meta-Property-Kernel_id"=>Fog::Nullable::String, + "X-Image-Meta-Size"=>String, + "X-Image-Meta-Checksum"=>Fog::Nullable::String, + "X-Image-Meta-Deleted"=>String, + "Content-Length"=>String, + "X-Image-Meta-Owner"=>String, + "X-Image-Meta-Status"=>String, + "X-Image-Meta-Id"=>String} + + @image_members_format =[ + {"can_share"=>Fog::Nullable::Boolean, + "member_id"=>String + } + ] + + tests('success') do + tests('#list_public_images').formats({'images' => [@image_format]}) do + Fog::Image[:openstack].list_public_images.body + end + + tests('#list_public_images_detailed').formats({'images' => [@image_format]}) do + Fog::Image[:openstack].list_public_images.body + end + + tests('#create_image').formats({'image' => @image_format}) do + @instance = Fog::Image[:openstack].create_image({:name => "test image"}).body + end + + tests('#get_image').formats(@image_meta_format) do + Fog::Image[:openstack].get_image(@instance['image']['id']).headers + end + + tests('#update_image').formats(@image_format) do + Fog::Image[:openstack].update_image({:id => @instance['image']['id'], + :name => "edit image"}).body['image'] + end + + tests('#add_member_to_image').succeeds do + Fog::Image[:openstack].add_member_to_image( + @instance['image']['id'], @instance['image']['owner']) + end + + tests('#get_image_members').succeeds do + Fog::Image[:openstack].get_image_members(@instance['image']['id']) + end + + tests('#get_shared_images').succeeds do + Fog::Image[:openstack].get_shared_images(@instance['image']['owner']) + end + + tests('#remove_member_from_image').succeeds do + Fog::Image[:openstack].remove_member_from_image( + @instance['image']['id'], @instance['image']['owner']) + end + + tests('#delete_image').succeeds do + Fog::Image[:openstack].delete_image(@instance['image']['id']) + end + + end +end