mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
[cloudstack|compute] volumes support
This commit is contained in:
parent
4859206f34
commit
54f1c92184
10 changed files with 494 additions and 161 deletions
lib/fog
|
@ -19,14 +19,16 @@ module Fog
|
|||
|
||||
model_path 'fog/cloudstack/models/compute'
|
||||
model :address
|
||||
model :flavor
|
||||
collection :flavors
|
||||
model :job
|
||||
collection :jobs
|
||||
model :server
|
||||
collection :servers
|
||||
model :image
|
||||
collection :images
|
||||
model :flavor
|
||||
collection :flavors
|
||||
model :volume
|
||||
collection :volumes
|
||||
model :zone
|
||||
collection :zones
|
||||
|
||||
|
@ -180,21 +182,21 @@ module Fog
|
|||
|
||||
# Decode the login response
|
||||
response = Fog::JSON.decode(response.body)
|
||||
|
||||
|
||||
user = response['loginresponse']
|
||||
user.merge!('sessionid' => sessionid)
|
||||
|
||||
|
||||
@cloudstack_session_id = user['sessionid']
|
||||
@cloudstack_session_key = user['sessionkey']
|
||||
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
|
||||
def request(params)
|
||||
params.reject!{|k,v| v.nil?}
|
||||
|
||||
|
||||
params.merge!('response' => 'json')
|
||||
|
||||
|
||||
if has_session?
|
||||
params, headers = authorize_session(params)
|
||||
elsif has_keys?
|
||||
|
@ -210,20 +212,20 @@ module Fog
|
|||
def has_session?
|
||||
@cloudstack_session_id && @cloudstack_session_key
|
||||
end
|
||||
|
||||
|
||||
def has_keys?
|
||||
@cloudstack_api_key && @cloudstack_secret_access_key
|
||||
end
|
||||
|
||||
|
||||
def authorize_session(params)
|
||||
# set the session id cookie for the request
|
||||
headers = {'Cookie' => "JSESSIONID=#{@cloudstack_session_id};"}
|
||||
# set the sesion key for the request, params are not signed using session auth
|
||||
params.merge!('sessionkey' => @cloudstack_session_key)
|
||||
|
||||
|
||||
return params, headers
|
||||
end
|
||||
|
||||
|
||||
def authorize_api_keys(params)
|
||||
headers = {}
|
||||
# merge the api key into the params
|
||||
|
@ -232,10 +234,10 @@ module Fog
|
|||
signature = Fog::Cloudstack.signed_params(@cloudstack_secret_access_key,params)
|
||||
# merge signature into request param
|
||||
params.merge!({'signature' => signature})
|
||||
|
||||
|
||||
return params, headers
|
||||
end
|
||||
|
||||
|
||||
def issue_request(params={},headers={},method='GET',expects=200)
|
||||
begin
|
||||
response = @connection.request({
|
||||
|
@ -244,13 +246,13 @@ module Fog
|
|||
:method => method,
|
||||
:expects => expects
|
||||
})
|
||||
|
||||
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
error_response = Fog::JSON.decode(error.response.body)
|
||||
|
||||
|
||||
error_code = error_response.values.first['errorcode']
|
||||
error_text = error_response.values.first['errortext']
|
||||
|
||||
|
||||
case error_code
|
||||
when 401
|
||||
raise Fog::Compute::Cloudstack::Unauthorized, error_text
|
||||
|
@ -285,140 +287,151 @@ module Fog
|
|||
"haschild" => false,
|
||||
"path" => "ROOT/accountname"
|
||||
}
|
||||
user = {
|
||||
"id" => user_id,
|
||||
"username" => "username",
|
||||
"firstname" => "Bob",
|
||||
"lastname" => "Lastname",
|
||||
"email" => "email@example.com",
|
||||
"created" => "2012-05-14T16:25:17-0500",
|
||||
"state" => "enabled",
|
||||
"account" => "accountname",
|
||||
"accounttype" => 2,
|
||||
"domainid" => domain_id,
|
||||
"domain" => domain_name,
|
||||
"apikey" => Fog::Cloudstack.uuid,
|
||||
"secretkey" => Fog::Cloudstack.uuid
|
||||
}
|
||||
{
|
||||
:users => { user_id => user },
|
||||
:networks => { network_id => {
|
||||
"id" => network_id,
|
||||
"name" => "10.56.23.0/26",
|
||||
"displaytext" => "10.56.23.0/26",
|
||||
"broadcastdomaintype" => "Vlan",
|
||||
"traffictype" => "Guest",
|
||||
"gateway" => "10.56.23.1",
|
||||
"netmask" => "255.255.255.192",
|
||||
"cidr" => "10.56.23.0/26",
|
||||
"zoneid" => zone_id,
|
||||
"zonename" => "zone-00",
|
||||
"networkofferingid" => "af0c9bd5-a1b2-4ad0-bf4b-d6fa9b1b9d5b",
|
||||
"networkofferingname" => "DefaultSharedNetworkOffering",
|
||||
"networkofferingdisplaytext" => "Offering for Shared networks",
|
||||
"id" => network_id,
|
||||
"name" => "10.56.23.0/26",
|
||||
"displaytext" => "10.56.23.0/26",
|
||||
"broadcastdomaintype" => "Vlan",
|
||||
"traffictype" => "Guest",
|
||||
"gateway" => "10.56.23.1",
|
||||
"netmask" => "255.255.255.192",
|
||||
"cidr" => "10.56.23.0/26",
|
||||
"zoneid" => zone_id,
|
||||
"zonename" => "zone-00",
|
||||
"networkofferingid" => "af0c9bd5-a1b2-4ad0-bf4b-d6fa9b1b9d5b",
|
||||
"networkofferingname" => "DefaultSharedNetworkOffering",
|
||||
"networkofferingdisplaytext" => "Offering for Shared networks",
|
||||
"networkofferingavailability" => "Optional",
|
||||
"issystem" => false,
|
||||
"state" => "Setup",
|
||||
"related" => "86bbc9fc-d92e-49db-9fdc-296189090017",
|
||||
"broadcasturi" => "vlan://800",
|
||||
"dns1" => "10.0.80.11",
|
||||
"type" => "Shared",
|
||||
"vlan" => "800",
|
||||
"acltype" => "Domain",
|
||||
"subdomainaccess" => true,
|
||||
"domainid" => domain_id,
|
||||
"domain" => "ROOT",
|
||||
"issystem" => false,
|
||||
"state" => "Setup",
|
||||
"related" => "86bbc9fc-d92e-49db-9fdc-296189090017",
|
||||
"broadcasturi" => "vlan://800",
|
||||
"dns1" => "10.0.80.11",
|
||||
"type" => "Shared",
|
||||
"vlan" => "800",
|
||||
"acltype" => "Domain",
|
||||
"subdomainaccess" => true,
|
||||
"domainid" => domain_id,
|
||||
"domain" => "ROOT",
|
||||
"service" => [
|
||||
{"name" => "UserData"},
|
||||
{"name" => "Dhcp"},
|
||||
{"name" => "Dns", "capability" => [
|
||||
{"name" => "AllowDnsSuffixModification",
|
||||
"value" => "true",
|
||||
"canchooseservicecapability" => false}]
|
||||
{
|
||||
"name" => "Dns",
|
||||
"capability" => [
|
||||
{
|
||||
"name" => "AllowDnsSuffixModification",
|
||||
"value" => "true",
|
||||
"canchooseservicecapability" => false
|
||||
}
|
||||
]
|
||||
}],
|
||||
"networkdomain" => "cs1cloud.internal",
|
||||
"networkdomain" => "cs1cloud.internal",
|
||||
"physicalnetworkid" => "8f4627c5-1fdd-4504-8a92-f61b4e9cb3e3",
|
||||
"restartrequired" => false,
|
||||
"specifyipranges" => true}
|
||||
"restartrequired" => false,
|
||||
"specifyipranges" => true}
|
||||
},
|
||||
:zones => { zone_id => {
|
||||
"id" => zone_id,
|
||||
"name"=> "zone-00",
|
||||
"domainid" => 1,
|
||||
"domainname" => "ROOT",
|
||||
"networktype" => "Advanced",
|
||||
"id" => zone_id,
|
||||
"name" => "zone-00",
|
||||
"domainid" => 1,
|
||||
"domainname" => "ROOT",
|
||||
"networktype" => "Advanced",
|
||||
"securitygroupsenabled" => false,
|
||||
"allocationstate" => "Enabled",
|
||||
"zonetoken" => Fog::Cloudstack.uuid,
|
||||
"dhcpprovider" => "VirtualRouter"}},
|
||||
"allocationstate" => "Enabled",
|
||||
"zonetoken" => Fog::Cloudstack.uuid,
|
||||
"dhcpprovider" => "VirtualRouter"}},
|
||||
:images => { image_id => {
|
||||
"id" => image_id,
|
||||
"name" => "CentOS 5.6(64-bit) no GUI (XenServer)",
|
||||
"displaytext" => "CentOS 5.6(64-bit) no GUI (XenServer)",
|
||||
"ispublic" => true,
|
||||
"created" => "2012-05-09T15:29:33-0500",
|
||||
"isready" => true,
|
||||
"id" => image_id,
|
||||
"name" => "CentOS 5.6(64-bit) no GUI (XenServer)",
|
||||
"displaytext" => "CentOS 5.6(64-bit) no GUI (XenServer)",
|
||||
"ispublic" => true,
|
||||
"created" => "2012-05-09T15:29:33-0500",
|
||||
"isready" => true,
|
||||
"passwordenabled" => false,
|
||||
"format" => "VHD",
|
||||
"isfeatured" => true,
|
||||
"crossZones" => true,
|
||||
"ostypeid" => "a6a6694a-18f5-4765-8418-2b7a5f37cd0f",
|
||||
"ostypename" => "CentOS 5.3 (64-bit)",
|
||||
"account" => "system",
|
||||
"zoneid" => zone_id,
|
||||
"zonename" => "zone-00",
|
||||
"status" => "Download Complete",
|
||||
"size" => 21474836480,
|
||||
"templatetype" => "BUILTIN",
|
||||
"domain" => "ROOT",
|
||||
"domainid" => "6023b6fe-5bef-4358-bc76-9f4e75afa52f",
|
||||
"isextractable" => true,
|
||||
"checksum" => "905cec879afd9c9d22ecc8036131a180"}},
|
||||
"format" => "VHD",
|
||||
"isfeatured" => true,
|
||||
"crossZones" => true,
|
||||
"ostypeid" => "a6a6694a-18f5-4765-8418-2b7a5f37cd0f",
|
||||
"ostypename" => "CentOS 5.3 (64-bit)",
|
||||
"account" => "system",
|
||||
"zoneid" => zone_id,
|
||||
"zonename" => "zone-00",
|
||||
"status" => "Download Complete",
|
||||
"size" => 21474836480,
|
||||
"templatetype" => "BUILTIN",
|
||||
"domain" => "ROOT",
|
||||
"domainid" => "6023b6fe-5bef-4358-bc76-9f4e75afa52f",
|
||||
"isextractable" => true,
|
||||
"checksum" => "905cec879afd9c9d22ecc8036131a180"}},
|
||||
:flavors => { flavor_id => {
|
||||
"id" => flavor_id,
|
||||
"name" => "Medium Instance",
|
||||
"id" => flavor_id,
|
||||
"name" => "Medium Instance",
|
||||
"displaytext" => "Medium Instance",
|
||||
"cpunumber" => 1,
|
||||
"cpuspeed" => 1000,
|
||||
"memory" => 1024,
|
||||
"created" => "2012-05-09T14:48:36-0500",
|
||||
"cpunumber" => 1,
|
||||
"cpuspeed" => 1000,
|
||||
"memory" => 1024,
|
||||
"created" => "2012-05-09T14:48:36-0500",
|
||||
"storagetype" => "shared",
|
||||
"offerha" => false,
|
||||
"offerha" => false,
|
||||
"limitcpuuse" => false,
|
||||
"issystem" => false,
|
||||
"defaultuse" => false}},
|
||||
"issystem" => false,
|
||||
"defaultuse" => false}},
|
||||
:accounts => { account_id => {
|
||||
"id" => account_id,
|
||||
"name" => "accountname",
|
||||
"accounttype" => 2,
|
||||
"domainid" => domain_id,
|
||||
"domain" => domain_name,
|
||||
"receivedbytes" => 0,
|
||||
"sentbytes" => 0,
|
||||
"vmlimit" => "Unlimited",
|
||||
"vmtotal" => 0,
|
||||
"vmavailable" => "Unlimited",
|
||||
"iplimit" => "Unlimited",
|
||||
"iptotal" => 0,
|
||||
"ipavailable" => "Unlimited",
|
||||
"volumelimit" => "Unlimited",
|
||||
"volumetotal" => 0,
|
||||
"volumeavailable" => "Unlimited",
|
||||
"snapshotlimit" => "Unlimited",
|
||||
"snapshottotal" => 0,
|
||||
"id" => account_id,
|
||||
"name" => "accountname",
|
||||
"accounttype" => 2,
|
||||
"domainid" => domain_id,
|
||||
"domain" => domain_name,
|
||||
"receivedbytes" => 0,
|
||||
"sentbytes" => 0,
|
||||
"vmlimit" => "Unlimited",
|
||||
"vmtotal" => 0,
|
||||
"vmavailable" => "Unlimited",
|
||||
"iplimit" => "Unlimited",
|
||||
"iptotal" => 0,
|
||||
"ipavailable" => "Unlimited",
|
||||
"volumelimit" => "Unlimited",
|
||||
"volumetotal" => 0,
|
||||
"volumeavailable" => "Unlimited",
|
||||
"snapshotlimit" => "Unlimited",
|
||||
"snapshottotal" => 0,
|
||||
"snapshotavailable" => "Unlimited",
|
||||
"templatelimit" => "Unlimited",
|
||||
"templatetotal" => 0,
|
||||
"templatelimit" => "Unlimited",
|
||||
"templatetotal" => 0,
|
||||
"templateavailable" => "Unlimited",
|
||||
"vmstopped" => 0,
|
||||
"vmrunning" => 0,
|
||||
"projectlimit" => "Unlimited",
|
||||
"projecttotal" => 1,
|
||||
"projectavailable" => "Unlimited",
|
||||
"networklimit" => "Unlimited",
|
||||
"networktotal" => 0,
|
||||
"networkavailable" => "Unlimited",
|
||||
"state" => "enabled",
|
||||
"user" =>
|
||||
[{"id" => user_id,
|
||||
"username" => "username",
|
||||
"firstname" => "Bob",
|
||||
"lastname" => "Lastname",
|
||||
"email" => "email@example.com",
|
||||
"created" => "2012-05-14T16:25:17-0500",
|
||||
"state" => "enabled",
|
||||
"account" => "accountname",
|
||||
"accounttype" => 2,
|
||||
"domainid" => domain_id,
|
||||
"domain" => domain_name,
|
||||
"apikey" => Fog::Cloudstack.uuid,
|
||||
"secretkey" => Fog::Cloudstack.uuid}]}},
|
||||
"vmstopped" => 0,
|
||||
"vmrunning" => 0,
|
||||
"projectlimit" => "Unlimited",
|
||||
"projecttotal" => 1,
|
||||
"projectavailable" => "Unlimited",
|
||||
"networklimit" => "Unlimited",
|
||||
"networktotal" => 0,
|
||||
"networkavailable" => "Unlimited",
|
||||
"state" => "enabled",
|
||||
"user" => [user]}
|
||||
},
|
||||
:domains => { domain_id => domain },
|
||||
:servers => {}
|
||||
:servers => {},
|
||||
:jobs => {},
|
||||
:volumes => {}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,18 +7,22 @@ module Fog
|
|||
attribute :user_id, :aliases => 'userid'
|
||||
attribute :account_id, :aliases => 'accountid'
|
||||
attribute :cmd
|
||||
attribute :job_status, :aliases => 'jobstatus'
|
||||
attribute :job_status, :aliases => 'jobstatus', :type => :integer
|
||||
attribute :job_result_type, :aliases => 'jobresulttype'
|
||||
attribute :job_result_code, :aliases => 'jobresultcode'
|
||||
attribute :job_proc_status, :aliases => 'jobprocstatus'
|
||||
attribute :job_result_code, :aliases => 'jobresultcode', :type => :integer
|
||||
attribute :job_proc_status, :aliases => 'jobprocstatus', :type => :integer
|
||||
|
||||
attribute :created_at, :aliases => 'created', :type => :time
|
||||
attribute :created_at, :aliases => 'created', :type => :time
|
||||
attribute :job_result, :aliases => 'jobresult'
|
||||
|
||||
def reload
|
||||
requires :id
|
||||
merge_attributes(connection.query_async_job_result('jobid' => self.id)['queryasyncjobresultresponse'])
|
||||
end
|
||||
|
||||
def finished?
|
||||
self.job_status != 0
|
||||
end
|
||||
end # Job
|
||||
end # Cloudstack
|
||||
end # Compute
|
||||
|
|
119
lib/fog/cloudstack/models/compute/volume.rb
Normal file
119
lib/fog/cloudstack/models/compute/volume.rb
Normal file
|
@ -0,0 +1,119 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Cloudstack
|
||||
class Volume < Fog::Model
|
||||
identity :id, :aliases => 'id'
|
||||
|
||||
attribute :name, :aliases => 'name'
|
||||
attribute :zone_id, :aliases => 'zoneid'
|
||||
attribute :zone_name, :aliases => 'zonename'
|
||||
attribute :type, :aliases => 'type'
|
||||
attribute :size, :aliases => 'size'
|
||||
attribute :created, :aliases => 'created'
|
||||
attribute :state, :aliases => 'state'
|
||||
attribute :account, :aliases => 'account'
|
||||
attribute :domain_id, :aliases => 'domainid'
|
||||
attribute :domain, :aliases => 'domain'
|
||||
attribute :storage_type, :aliases => 'storagetype'
|
||||
attribute :hypervisor, :aliases => 'hypervisor'
|
||||
attribute :disk_offering_id, :aliases => 'diskofferingid'
|
||||
attribute :disk_offering_name, :aliases => 'diskofferingname'
|
||||
attribute :disk_offering_display_text, :aliases => 'diskofferingdisplaytext'
|
||||
attribute :storage, :aliases => 'storage'
|
||||
attribute :destroyed, :aliases => 'destroyed'
|
||||
attribute :is_extractable, :aliases => 'isextractable', :type => :boolean
|
||||
attribute :server_id, :aliases => 'virtualmachineid'
|
||||
attribute :server_name, :aliases => 'vmname'
|
||||
attribute :server_display_name, :aliases => 'vmdisplayname'
|
||||
|
||||
attr_accessor :snapshot_id, :project_id
|
||||
|
||||
def save
|
||||
requires :name, :disk_offering_id, :zone_id
|
||||
|
||||
options = {
|
||||
'size' => size,
|
||||
'name' => name,
|
||||
'diskofferingid' => disk_offering_id,
|
||||
'zoneid' => zone_id,
|
||||
'snapshotid' => snapshot_id,
|
||||
'projectid' => project_id
|
||||
}
|
||||
data = connection.create_volume(options)
|
||||
merge_attributes(data['createvolumeresponse'])
|
||||
end
|
||||
|
||||
def ready?
|
||||
state == 'Allocated' || state == 'Ready'
|
||||
end
|
||||
|
||||
def flavor
|
||||
connection.disk_offerings.get(self.disk_offering_id)
|
||||
end
|
||||
alias disk_offering flavor
|
||||
|
||||
def server
|
||||
if server_id
|
||||
connection.servers.get(server_id)
|
||||
end
|
||||
end
|
||||
|
||||
def reload
|
||||
requires :identity
|
||||
|
||||
return unless data = begin
|
||||
collection.get(identity)
|
||||
rescue Excon::Errors::SocketError
|
||||
nil
|
||||
end
|
||||
|
||||
new_attributes = {
|
||||
'virtualmachineid' => nil,
|
||||
'vmname' => nil,
|
||||
'vmdisplayname' => nil
|
||||
}.merge(data.attributes)
|
||||
|
||||
merge_attributes(new_attributes)
|
||||
self
|
||||
end
|
||||
|
||||
|
||||
def attach(instance_or_id, mountpoint=nil)
|
||||
requires :id
|
||||
instance_id = instance_or_id.is_a?(Server) ? instance_or_id.id : instance_or_id
|
||||
unless instance_id
|
||||
raise ArgumentError, "Missing required argument: instance_or_id"
|
||||
end
|
||||
|
||||
options = {
|
||||
'id' => id,
|
||||
'virtualmachineid' => instance_id,
|
||||
}
|
||||
options.merge!('deviceid' => mountpoint) if mountpoint
|
||||
|
||||
data = connection.attach_volume(options)
|
||||
|
||||
Job.new(data["attachvolumeresponse"]).tap do |job|
|
||||
job.connection= self.connection
|
||||
end
|
||||
end
|
||||
|
||||
def detach
|
||||
requires :id
|
||||
|
||||
data = connection.detach_volume('id' => id)
|
||||
|
||||
Job.new(data["detachvolumeresponse"]).tap do |job|
|
||||
job.connection= self.connection
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
connection.delete_volume('id' => id)
|
||||
true
|
||||
end
|
||||
end # Volume
|
||||
end # Cloudstack
|
||||
end # Compute
|
||||
end # Fog
|
28
lib/fog/cloudstack/models/compute/volumes.rb
Normal file
28
lib/fog/cloudstack/models/compute/volumes.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/cloudstack/models/compute/volume'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Cloudstack
|
||||
|
||||
class Volumes < Fog::Collection
|
||||
|
||||
model Fog::Compute::Cloudstack::Volume
|
||||
|
||||
def all
|
||||
data = connection.list_volumes["listvolumesresponse"]["volume"] || []
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(volume_id)
|
||||
if volume = connection.list_volumes('id' => volume_id)["listvolumesresponse"]["volume"].first
|
||||
new(volume)
|
||||
end
|
||||
rescue Fog::Compute::Cloudstack::BadRequest
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,18 +6,65 @@ module Fog
|
|||
# Attaches a disk volume to a virtual machine.
|
||||
#
|
||||
# {CloudStack API Reference}[http://http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/attachVolume.html]
|
||||
def attach_volume(id,virtualmachineid,deviceid=nil)
|
||||
options = {
|
||||
def attach_volume(options={})
|
||||
options.merge!(
|
||||
'command' => 'attachVolume',
|
||||
'id' => id,
|
||||
'virtualmachineid' => virtualmachineid,
|
||||
'deviceid' => deviceid
|
||||
}
|
||||
)
|
||||
|
||||
request(options)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end # Real
|
||||
|
||||
class Mock
|
||||
|
||||
def attach_volume(options={})
|
||||
volume_id = options['id']
|
||||
server_id = options['virtualmachineid']
|
||||
|
||||
volume = self.data[:volumes][volume_id]
|
||||
unless volume
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new("Unable to execute API command attachvolume due to invalid value. Object volumes(uuid: #{volume_id}) does not exist.")
|
||||
end
|
||||
|
||||
server = self.data[:servers][server_id]
|
||||
unless server
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new("Unable to execute API command attachvolume due to invalid value. Object vm_instance(uuid: #{server_id}) does not exist.")
|
||||
end
|
||||
|
||||
volume['virtualmachineid']= server['id']
|
||||
volume['vmname']= server['name']
|
||||
volume['vmdisplayname']= server['displayname']
|
||||
|
||||
job_id = Fog::Cloudstack.uuid
|
||||
|
||||
# FIXME: need to determine current user
|
||||
account_id = self.data[:accounts].first
|
||||
user_id = self.data[:users].first
|
||||
|
||||
job = {
|
||||
"accountid" => account_id,
|
||||
"userid" => user_id,
|
||||
"cmd" => "com.cloud.api.commands.AttachVolumeCmd",
|
||||
"created" => Time.now.iso8601,
|
||||
"jobid" => job_id,
|
||||
"jobstatus" => 1,
|
||||
"jobprocstatus" => 0,
|
||||
"jobresultcode" => 0,
|
||||
"jobresulttype" => "object",
|
||||
"jobresult" =>
|
||||
{"volume" => volume}
|
||||
}
|
||||
|
||||
self.data[:jobs][job_id]= job
|
||||
|
||||
{
|
||||
"attachvolumeresponse" => {
|
||||
"jobid" => job_id
|
||||
}
|
||||
}
|
||||
end
|
||||
end # Mock
|
||||
end # Cloudstack
|
||||
end # Compute
|
||||
end # Fog
|
||||
|
|
|
@ -14,6 +14,49 @@ module Fog
|
|||
request(options)
|
||||
end
|
||||
|
||||
end # Real
|
||||
|
||||
class Mock
|
||||
def create_volume(options={})
|
||||
volume_id = Fog::Cloudstack.uuid
|
||||
|
||||
unless volume_name = options['name']
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new('Unable to execute API command createvolume due to missing parameter name')
|
||||
end
|
||||
|
||||
unless zone_id = options['zoneid']
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new('Unable to execute API command createvolume due to missing parameter zoneid')
|
||||
end
|
||||
|
||||
unless disk_offering_id = options['diskofferingid']
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new('Unable to execute API command createvolume due to missing parameter diskofferingid')
|
||||
end
|
||||
|
||||
volume = {
|
||||
"id" => volume_id,
|
||||
"name" => volume_name,
|
||||
"zoneid" => zone_id,
|
||||
"zonename" => "ey-wdc-00",
|
||||
"type" => "DATADISK",
|
||||
"size" => 5368709120,
|
||||
"created" => "2012-05-22T14:52:55-0500",
|
||||
"state" => "Allocated",
|
||||
"account" => "accountname",
|
||||
"domainid" => "6023b6fe-5bef-4358-bc76-9f4e75afa52f",
|
||||
"domain" => "ROOT",
|
||||
"storagetype" => "shared",
|
||||
"hypervisor" => "None",
|
||||
"diskofferingid" => disk_offering_id,
|
||||
"diskofferingname" => "Small",
|
||||
"diskofferingdisplaytext" => "Small Disk, 5 GB",
|
||||
"storage" => "none",
|
||||
"destroyed" => false,
|
||||
"isextractable" => false
|
||||
}
|
||||
|
||||
self.data[:volumes][volume_id]= volume
|
||||
{'createvolumeresponse' => volume}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,27 @@ module Fog
|
|||
request(options)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end # Real
|
||||
class Mock
|
||||
def delete_volume(options={})
|
||||
volume_id = options['id']
|
||||
if self.data[:volumes][volume_id]
|
||||
self.data[:volumes].delete(volume_id)
|
||||
{
|
||||
"deletevolumeresponse" => {
|
||||
"success" => "true"
|
||||
}
|
||||
}
|
||||
else # FIXME: mayhaps
|
||||
self.data[:volumes].delete(volume_id)
|
||||
{
|
||||
"deletevolumeresponse" => {
|
||||
"success" => "false"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end # Mock
|
||||
end # Cloudstack
|
||||
end # Compute
|
||||
end # Fog
|
||||
|
|
|
@ -6,16 +6,57 @@ module Fog
|
|||
# Deletes a specified domain.
|
||||
#
|
||||
# {CloudStack API Reference}[http://download.cloud.com/releases/2.2.0/api_2.2.4/global_admin/detachVolume.html]
|
||||
def detach_volume(id)
|
||||
options = {
|
||||
'command' => 'detachVolume',
|
||||
'id' => id
|
||||
}
|
||||
def detach_volume(options={})
|
||||
options.merge!(
|
||||
'command' => 'detachVolume'
|
||||
)
|
||||
|
||||
request(options)
|
||||
end
|
||||
|
||||
end
|
||||
end # Real
|
||||
|
||||
class Mock
|
||||
|
||||
def detach_volume(options={})
|
||||
volume_id = options['id']
|
||||
|
||||
volume = self.data[:volumes][volume_id]
|
||||
unless volume
|
||||
raise Fog::Compute::Cloudstack::BadRequest.new("Unable to execute API command attachvolume due to invalid value. Object volumes(uuid: #{volume_id}) does not exist.")
|
||||
end
|
||||
|
||||
volume['virtualmachineid']= volume['vmname']= volume['vmdisplayname']= nil
|
||||
|
||||
job_id = Fog::Cloudstack.uuid
|
||||
|
||||
# FIXME: need to determine current user
|
||||
account_id = self.data[:accounts].first
|
||||
user_id = self.data[:users].first
|
||||
|
||||
job = {
|
||||
"accountid" => account_id,
|
||||
"userid" => user_id,
|
||||
"cmd" => "com.cloud.api.commands.DetachVolumeCmd",
|
||||
"created" => Time.now.iso8601,
|
||||
"jobid" => job_id,
|
||||
"jobstatus" => 1,
|
||||
"jobprocstatus" => 0,
|
||||
"jobresultcode" => 0,
|
||||
"jobresulttype" => "object",
|
||||
"jobresult" =>
|
||||
{"volume" => volume}
|
||||
}
|
||||
|
||||
self.data[:jobs][job_id]= job
|
||||
|
||||
{
|
||||
"detachvolumeresponse" => {
|
||||
"jobid" => job_id
|
||||
}
|
||||
}
|
||||
end
|
||||
end # Mock
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,11 +10,29 @@ module Fog
|
|||
options.merge!(
|
||||
'command' => 'listVolumes'
|
||||
)
|
||||
|
||||
|
||||
request(options)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end # Real
|
||||
|
||||
class Mock
|
||||
def list_volumes(options={})
|
||||
volume_id = options.delete('id')
|
||||
if volume_id
|
||||
volumes = [self.data[:volumes][volume_id]]
|
||||
else
|
||||
volumes = self.data[:volumes].values
|
||||
end
|
||||
|
||||
{
|
||||
'listvolumesresponse' => {
|
||||
'count' => volumes.size,
|
||||
'volume' => volumes
|
||||
}
|
||||
}
|
||||
end
|
||||
end # Mock
|
||||
end # Cloudstack
|
||||
end # Compute
|
||||
end #Fog
|
||||
|
|
|
@ -99,8 +99,8 @@ module Fog
|
|||
end
|
||||
|
||||
def new(attributes = {})
|
||||
unless attributes.is_a?(Hash)
|
||||
raise(ArgumentError.new("Initialization parameters must be an attributes hash, got #{attributes.inspect}"))
|
||||
unless attributes.is_a?(::Hash)
|
||||
raise(ArgumentError.new("Initialization parameters must be an attributes hash, got #{attributes.class} #{attributes.inspect}"))
|
||||
end
|
||||
model.new(
|
||||
attributes.merge(
|
||||
|
|
Loading…
Add table
Reference in a new issue