[hp|block_storage_v2] Add request methods for volumes, along with tests.

This commit is contained in:
Rupak Ganguly 2013-05-17 13:27:40 -04:00
parent 3ae6df8f49
commit 54c8905e4f
9 changed files with 486 additions and 5 deletions

View File

@ -56,7 +56,7 @@ module Fog
end
service(:block_storage, 'hp/block_storage', 'BlockStorage')
service(:block_storageV2, 'hp/block_storage_v2', 'BlockStorageV2')
service(:block_storage_v2, 'hp/block_storage_v2', 'BlockStorageV2')
service(:cdn, 'hp/cdn', 'CDN')
service(:compute, 'hp/compute', 'Compute')
service(:network, 'hp/network', 'Network')

View File

@ -19,10 +19,12 @@ module Fog
#collection :snapshots
request_path 'fog/hp/requests/block_storage_v2'
#request :create_volume
#request :delete_volume
#request :get_volume_details
#request :list_volumes
request :create_volume
request :delete_volume
request :get_volume_details
request :list_volumes
request :list_volumes_detail
request :update_volume
#request :create_snapshot
#request :delete_snapshot
#request :get_snapshot_details

View File

@ -0,0 +1,90 @@
module Fog
module HP
class BlockStorageV2
class Real
# Create a new block storage volume
#
# ==== Parameters
# * options<~Hash>:
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size of the volume (in GBs). Size is optional only if 'snapshot_id' is specified.
# * 'snapshot_id'<~String> - UUId of the volume snapshot to create the volume from. The snapshot_id, imageRef and the source_volid parameters are mutually exclusive, and only one should be specified in the request.
# * 'imageRef'<~String> - UUId of the image to create the volume from. This creates a bootable volume. The snapshot_id, imageRef and the source_volid parameters are mutually exclusive, and only one should be specified in the request.
# * 'source_volid'<~String> - UUId of an 'available' volume to create the volume from. The request is invalid if the volume is not available. The snapshot_id, imageRef and the source_volid parameters are mutually exclusive, and only one should be specified in the request.
# * 'availability_zone'<~String> - Availability zone where the volume should be created. Defaults to 'az1'.
# * 'volume_type'<~String> - Type of the volume
# * 'metadata'<~Hash> - Up to 5 key value pairs containing 255 bytes of info
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * volume<~Hash>:
# * 'id'<~String> - UUId for the volume
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size in GB for the volume
# * 'status'<~String> - Status of the volume i.e. "creating"
# * 'volume_type'<~String> - Type of the volume
# * 'snapshot_id'<~String> - UUId of the snapshot, the volume was created from.
# * 'source_volid'<~String> - UUId of a volume, the volume was created from.
# * 'created_at'<~String> - Timestamp in UTC when volume was created
# * 'availability_zone'<~String> - Availability zone i.e. "az1"
# * attachments<~Array>: Array of hashes of attachments
# * metadata<~Hash>: Hash of metadata for the volume
def create_volume(options={})
data = {
'volume' => {}
}
l_options = ['display_name', 'display_description', 'size',
'snapshot_id', 'imageRef', 'source_volid',
'availability_zone', 'volume_type', 'metadata']
l_options.select{|o| options[o]}.each do |key|
data['volume'][key] = options[key]
end
request(
:body => Fog::JSON.encode(data),
:expects => 200,
:method => 'POST',
:path => 'volumes'
)
end
end
class Mock # :nodoc:all
def create_volume(options={})
if options['snapshot_id'] && options['imageRef'] && options['source_volid']
raise Fog::Errors::BadRequest.new('The snapshot_id, imageRef and the source_volid parameters are mutually exclusive, and only one should be specified in the request.')
else
response = Excon::Response.new
response.status = 200
data = {
'id' => Fog::HP::Mock.uuid.to_s,
'status' => 'available',
'display_name' => options['display_name'] || '',
'attachments' => [{}],
'availability_zone' => options['availability_zone'] || 'az1',
'bootable' => false,
'created_at' => Time.now.to_s,
'display_description' => options['display_description'] || '',
'volume_type' => 'None',
'snapshot_id' => options['snapshot_id'] || '',
'source_volid' => options['source_volid'] || '',
'metadata' => options['metadata'] || {},
'size' => options['size']
}
self.data[:volumes][data['id']] = data
response.body = { 'volume' => data }
response
end
end
end
end
end
end

View File

@ -0,0 +1,38 @@
module Fog
module HP
class BlockStorageV2
class Real
# Delete an existing block storage volume
#
# ==== Parameters
# * 'volume_id'<~String> - UUId of the volume to delete
#
def delete_volume(volume_id)
response = request(
:expects => 202,
:method => 'DELETE',
:path => "volumes/#{volume_id}"
)
response
end
end
class Mock # :nodoc:all
def delete_volume(volume_id)
response = Excon::Response.new
if self.data[:volumes][volume_id]
self.data[:volumes].delete(volume_id)
response.status = 202
else
raise Fog::HP::BlockStorageV2::NotFound
end
response
end
end
end
end
end

View File

@ -0,0 +1,58 @@
module Fog
module HP
class BlockStorageV2
class Real
# Get details for existing block storage volume
#
# ==== Parameters
# * 'volume_id'<~String> - UUId of the volume to get
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * volume<~Hash>:
# * 'id'<~String> - UUId for the volume
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size in GB for the volume
# * 'status'<~String> - Status of the volume i.e. "creating"
# * 'volume_type'<~String> - Type of the volume
# * 'snapshot_id'<~String> - UUId of the snapshot, the volume was created from.
# * 'source_volid'<~String> - UUId of a volume, the volume was created from.
# * 'created_at'<~String> - Timestamp in UTC when volume was created
# * 'availability_zone'<~String> - Availability zone i.e. "az1"
# * attachments<~Array>: Array of hashes of attachments
# * metadata<~Hash>: Hash of metadata for the volume
def get_volume_details(volume_id)
response = request(
:expects => 200,
:method => 'GET',
:path => "volumes/#{volume_id}"
)
response
end
end
class Mock # :nodoc:all
def get_volume_details(volume_id)
unless volume_id
raise ArgumentError.new('volume_id is required')
end
response = Excon::Response.new
if volume = self.data[:volumes][volume_id]
response.status = 200
response.body = { 'volume' => volume }
response
else
raise Fog::HP::BlockStorageV2::NotFound
end
end
end
end
end
end

View File

@ -0,0 +1,61 @@
module Fog
module HP
class BlockStorageV2
class Real
# List existing block storage volumes
#
# ==== Parameters
# * options<~Hash>: filter options
# * 'display_name'<~String> - Name of the volume
# * 'marker'<~String> - The ID of the last item in the previous list
# * 'limit'<~Integer> - Sets the page size
# * 'changes-since'<~DateTime> - Filters by the changes-since time. The list contains servers that have been deleted since the changes-since time.
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * volumes<~Hash>:
# * 'id'<~String> - UUId for the volume
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size in GB for the volume
# * 'status'<~String> - Status of the volume i.e. "creating"
# * 'volume_type'<~String> - Type of the volume
# * 'snapshot_id'<~String> - UUId of the snapshot, the volume was created from.
# * 'source_volid'<~String> - UUId of a volume, the volume was created from.
# * 'created_at'<~String> - Timestamp in UTC when volume was created
# * 'availability_zone'<~String> - Availability zone i.e. "az1"
# * attachments<~Array>: Array of hashes of attachments
# * metadata<~Hash>: Hash of metadata for the volume
def list_volumes(options = {})
response = request(
:expects => 200,
:method => 'GET',
:path => 'volumes',
:query => options
)
response
end
end
class Mock # :nodoc:all
def list_volumes(options = {})
response = Excon::Response.new
volumes = []
data = list_volumes_detail.body['volumes']
for volume in data
volumes << volume.reject { |key, _| ['volume_image_metadata'].include?(key) }
end
response.status = 200
response.body = { 'volumes' => volumes }
response
end
end
end
end
end

View File

@ -0,0 +1,59 @@
module Fog
module HP
class BlockStorageV2
class Real
# List details about existing block storage volumes
#
# ==== Parameters
# * options<~Hash>: filter options
# * 'display_name'<~String> - Name of the volume
# * 'marker'<~String> - The ID of the last item in the previous list
# * 'limit'<~Integer> - Sets the page size
# * 'changes-since'<~DateTime> - Filters by the changes-since time. The list contains servers that have been deleted since the changes-since time.
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * volumes<~Hash>:
# * 'id'<~String> - UUId for the volume
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size in GB for the volume
# * 'status'<~String> - Status of the volume i.e. "creating"
# * 'volume_type'<~String> - Type of the volume
# * 'snapshot_id'<~String> - UUId of the snapshot, the volume was created from.
# * 'source_volid'<~String> - UUId of a volume, the volume was created from.
# * 'created_at'<~String> - Timestamp in UTC when volume was created
# * 'availability_zone'<~String> - Availability zone i.e. "az1"
# * attachments<~Array>: Array of hashes of attachments
# * metadata<~Hash>: Hash of metadata for the volume
# * volume_image_metadata<~Hash>: Hash of image metadata for the volume, only if the volume was created from an image.
def list_volumes_detail(options = {})
response = request(
:expects => 200,
:method => 'GET',
:path => 'volumes/detail',
:query => options
)
response
end
end
class Mock # :nodoc:all
def list_volumes_detail(options = {})
response = Excon::Response.new
volumes = []
volumes = self.data[:volumes].values unless self.data[:volumes].nil?
response.status = 200
response.body = { 'volumes' => volumes }
response
end
end
end
end
end

View File

@ -0,0 +1,70 @@
module Fog
module HP
class BlockStorageV2
class Real
# Update an existing block storage volume
#
# ==== Parameters
# * 'volume_id'<~String> - UUId of the volume to update
# * options<~Hash>:
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'metadata'<~Hash> - Up to 5 key value pairs containing 255 bytes of info
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * volume<~Hash>:
# * 'id'<~String> - UUId for the volume
# * 'display_name'<~String> - Name of the volume
# * 'display_description'<~String> - Description of the volume
# * 'size'<~Integer> - Size in GB for the volume
# * 'status'<~String> - Status of the volume i.e. "creating"
# * 'volume_type'<~String> - Type of the volume
# * 'snapshot_id'<~String> - UUId of the snapshot, the volume was created from.
# * 'source_volid'<~String> - UUId of a volume, the volume was created from.
# * 'created_at'<~String> - Timestamp in UTC when volume was created
# * 'availability_zone'<~String> - Availability zone i.e. "az1"
# * attachments<~Array>: Array of hashes of attachments
# * metadata<~Hash>: Hash of metadata for the volume
def update_volume(volume_id, options={})
data = {
'volume' => {}
}
l_options = ['display_name', 'display_description', 'metadata']
l_options.select{|o| options[o]}.each do |key|
data['volume'][key] = options[key]
end
request(
:body => Fog::JSON.encode(data),
:expects => 200,
:method => 'PUT',
:path => "volumes/#{volume_id}"
)
end
end
class Mock # :nodoc:all
def update_volume(volume_id, options={})
response = Excon::Response.new
if volume = self.data[:volumes][volume_id]
response.status = 200
volume['display_name'] = options['display_name'] if options['display_name']
volume['display_description'] = options['display_description'] if options['display_description']
volume['metadata'] = options['metadata'] if options['metadata']
response.body = { 'volume' => volume }
response
else
raise Fog::HP::BlockStorageV2::NotFound
end
end
end
end
end
end

View File

@ -0,0 +1,103 @@
Shindo.tests("Fog::HP::BlockStorageV2 | volume requests", ['hp', 'v2', 'block_storage', 'volumes']) do
compute_service = Fog::Compute.new(:provider => 'HP', :version => :v2)
@volume_format = {
'id' => String,
'display_name' => Fog::Nullable::String,
'display_description' => Fog::Nullable::String,
'size' => Integer,
'status' => String,
'volume_type' => Fog::Nullable::String,
'snapshot_id' => Fog::Nullable::String,
'source_volid' => Fog::Nullable::String,
'created_at' => String,
'availability_zone' => String,
'attachments' => [Fog::Nullable::Hash],
'metadata' => Fog::Nullable::Hash
}
@volume_attach_format = {
'volumeId' => String,
'id' => String
}
tests('success') do
@volume_id = nil
@volume_name = 'fogvolume2tests'
@volume_desc = @volume_name + ' desc'
@base_image_id = ENV['BASE_IMAGE_ID'] || '7f60b54c-cd15-433f-8bed-00acbcd25a17'
@server = compute_service.servers.create(:name => 'fogvoltests', :flavor_id => 100, :image_id => @base_image_id)
@server.wait_for { ready? }
tests("#create_volume('display_name' => #{@volume_name}, 'display_description' => #{@volume_desc}, 'size' => 1)").formats(@volume_format) do
data = HP[:block_storage_v2].create_volume('display_name' => @volume_name, 'display_description' => @volume_desc, 'size' => 1).body['volume']
@volume_id = data['id']
data
end
tests("#get_volume_details(#{@volume_id})").formats(@volume_format) do
HP[:block_storage_v2].get_volume_details(@volume_id).body['volume']
end
tests("#update_volume(#{@volume_id}, 'display_name' => #{@volume_name}+' Upd'").formats(@volume_format) do
data = HP[:block_storage_v2].update_volume(@volume_id, 'display_name' => @volume_name).body['volume']
@volume_id = data['id']
data
end
tests('#list_volumes').formats({'volumes' => [@volume_format]}) do
HP[:block_storage_v2].list_volumes.body
end
tests('#list_volumes_detail').formats({'volumes' => [@volume_format]}) do
HP[:block_storage_v2].list_volumes_detail.body
end
tests("#attach_volume(#{@server.id}, #{@volume_id}, '/dev/sdg')").formats(@volume_attach_format) do
compute_service.attach_volume(@server.id, @volume_id, "/dev/sdg").body['volumeAttachment']
end
tests("#detach_volume(#{@server.id}, #{@volume_id})").succeeds do
compute_service.detach_volume(@server.id, @volume_id)
end
tests("#delete_volume(#{@volume_id})").succeeds do
HP[:block_storage_v2].delete_volume(@volume_id)
end
end
tests('failure') do
tests('#get_volume_details(0)').raises(Fog::HP::BlockStorageV2::NotFound) do
HP[:block_storage_v2].get_volume_details(0)
end
tests("#attach_volume(0, 0, '/dev/sdg')").raises(Fog::Compute::HPV2::NotFound) do
compute_service.attach_volume(0, 0, "/dev/sdg")
end
tests("#attach_volume(#{@server.id}, 0, '/dev/sdg')").raises(Fog::HP::BlockStorageV2::NotFound) do
pending if Fog.mocking?
compute_service.attach_volume(@server.id, 0, "/dev/sdg")
end
tests('#detach_volume(0, 0)').raises(Fog::Compute::HPV2::NotFound) do
compute_service.detach_volume(0, 0)
end
tests("#detach_volume(#{@server.id}, 0)").raises(Fog::HP::BlockStorageV2::NotFound) do
pending if Fog.mocking?
compute_service.detach_volume(@server.id, 0)
end
tests('#delete_volume(0)').raises(Fog::HP::BlockStorageV2::NotFound) do
HP[:block_storage_v2].delete_volume(0)
end
end
@server.destroy
end