mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Merge branch 'master' of github.com:fog/fog
This commit is contained in:
commit
fc5675dfdb
30 changed files with 1342 additions and 183 deletions
11
.travis.yml
11
.travis.yml
|
@ -9,10 +9,17 @@ rvm:
|
|||
- 1.9.2
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- jruby-18mode
|
||||
- jruby-19mode
|
||||
|
||||
script: bundle exec rake travis
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: jruby-18mode
|
||||
gemfile: Gemfile.1.8.7
|
||||
- rvm: jruby-19mode
|
||||
gemfile: Gemfile
|
||||
exclude:
|
||||
- rvm: 1.8.7
|
||||
gemfile: Gemfile
|
||||
|
@ -22,6 +29,10 @@ matrix:
|
|||
gemfile: Gemfile.1.8.7
|
||||
- rvm: 2.0.0
|
||||
gemfile: Gemfile.1.8.7
|
||||
- rvm: jruby-18mode
|
||||
gemfile: Gemfile
|
||||
- rvm: jruby-19mode
|
||||
gemfile: Gemfile.1.8.7
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
|
25
README.md
25
README.md
|
@ -135,6 +135,31 @@ for more details and examples. Once you are ready to start scripting fog, here i
|
|||
|
||||
geemus says: "That should give you everything you need to get started, but let me know if there is anything I can do to help!"
|
||||
|
||||
## Versioning
|
||||
|
||||
Fog library aims to adhere to [Semantic Versioning 2.0.0][semver], although it does not
|
||||
address challenges of multi-provider libraries. Semantic versioning is only guaranteed for
|
||||
the common API, not any provider-specific extensions. You may also need to update your
|
||||
configuration from time to time (even between Fog releases) as providers update or deprecate
|
||||
services.
|
||||
|
||||
However, we still aim for forwards compatibility within Fog major versions. As a result of this policy, you can (and
|
||||
should) specify a dependency on this gem using the [Pessimistic Version
|
||||
Constraint][pvc] with two digits of precision. For example:
|
||||
|
||||
```ruby
|
||||
spec.add_dependency 'fog', '~> 1.0'
|
||||
```
|
||||
|
||||
This means your project is compatible with Fog 1.0 up until 2.0. You can also set a higher minimum version:
|
||||
|
||||
```ruby
|
||||
spec.add_dependency 'fog', '~> 1.16'
|
||||
```
|
||||
|
||||
[semver]: http://semver.org/
|
||||
[pvc]: http://guides.rubygems.org/patterns/
|
||||
|
||||
## Contributing
|
||||
|
||||
* Find something you would like to work on.
|
||||
|
|
|
@ -50,11 +50,10 @@ Gem::Specification.new do |s|
|
|||
s.add_dependency('net-ssh', '>=2.1.3')
|
||||
s.add_dependency('nokogiri', '~>1.5')
|
||||
s.add_dependency('ruby-hmac')
|
||||
s.add_dependency('unicode', "~> 0.4.4")
|
||||
|
||||
## List your development dependencies here. Development dependencies are
|
||||
## those that are only needed during development
|
||||
s.add_development_dependency('jekyll')
|
||||
s.add_development_dependency('jekyll') unless RUBY_PLATFORM == 'java'
|
||||
s.add_development_dependency('rake')
|
||||
s.add_development_dependency('rbvmomi')
|
||||
s.add_development_dependency('yard')
|
||||
|
@ -65,7 +64,10 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency('fission')
|
||||
s.add_development_dependency('pry')
|
||||
s.add_development_dependency('google-api-client', '~>0.6.2')
|
||||
# s.add_development_dependency('ruby-libvirt','~>0.4.0')
|
||||
s.add_development_dependency('unf')
|
||||
if ENV["FOG_USE_LIBVIRT"] && RUBY_PLATFORM != 'java'
|
||||
s.add_development_dependency('ruby-libvirt','~>0.4.0')
|
||||
end
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {spec,tests}/*`.split("\n")
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
require 'fog/core'
|
||||
require 'fog/aws/credential_fetcher'
|
||||
require 'fog/aws/signaturev4'
|
||||
require 'unicode'
|
||||
|
||||
begin
|
||||
require 'unf/normalizer'
|
||||
rescue LoadError
|
||||
Fog::Logger.warning("Unable to load the 'unf' gem. Your AWS strings may not be properly encoded.")
|
||||
end
|
||||
|
||||
module Fog
|
||||
module AWS
|
||||
extend Fog::Provider
|
||||
|
@ -86,7 +92,7 @@ module Fog
|
|||
end
|
||||
|
||||
def self.escape(string)
|
||||
string = Unicode::normalize_C(string)
|
||||
string = defined?(::UNF::Normalizer) ? ::UNF::Normalizer.normalize(string, :nfc) : string
|
||||
string.gsub(/([^a-zA-Z0-9_.\-~]+)/) {
|
||||
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
||||
}
|
||||
|
|
|
@ -168,9 +168,9 @@ module Fog
|
|||
"/#{escape(bucket_name.to_s)}#{path}"
|
||||
end
|
||||
|
||||
# NOTE: differs fram Fog::AWS.escape by NOT escaping `/`
|
||||
# NOTE: differs from Fog::AWS.escape by NOT escaping `/`
|
||||
def escape(string)
|
||||
string = Unicode::normalize_C(string)
|
||||
string = defined?(::UNF::Normalizer) ? ::UNF::Normalizer.normalize(string, :nfc) : string
|
||||
string.gsub(/([^a-zA-Z0-9_.\-~\/]+)/) {
|
||||
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ module Fog
|
|||
request :insert_image
|
||||
request :insert_network
|
||||
request :insert_server
|
||||
request :insert_snapshot
|
||||
|
||||
request :set_metadata
|
||||
|
||||
|
|
|
@ -84,6 +84,29 @@ module Fog
|
|||
self
|
||||
end
|
||||
|
||||
def create_snapshot(snap_name, snap_desc)
|
||||
requires :name
|
||||
requires :zone_name
|
||||
|
||||
if snap_name.nil? or snap_name.empty?
|
||||
raise ArgumentError, 'Invalid snapshot name'
|
||||
end
|
||||
|
||||
options = {
|
||||
'name' => snap_name,
|
||||
'description' => snap_desc,
|
||||
}
|
||||
|
||||
service.insert_snapshot(name, self.zone, service.project, options)
|
||||
data = service.backoff_if_unfound {
|
||||
service.get_snapshot(snap_name, service.project).body
|
||||
}
|
||||
service.snapshots.merge_attributes(data)
|
||||
|
||||
# Try to return the representation of the snapshot we created
|
||||
service.snapshots.get(snap_name)
|
||||
end
|
||||
|
||||
RUNNING_STATE = "READY"
|
||||
|
||||
end
|
||||
|
|
|
@ -15,6 +15,7 @@ module Fog
|
|||
attribute :source_disk , :aliases => 'sourceDisk'
|
||||
attribute :source_disk_id , :aliases => 'sourceDiskId'
|
||||
attribute :description
|
||||
attribute :status
|
||||
|
||||
def reload
|
||||
requires :name
|
||||
|
|
49
lib/fog/google/requests/compute/insert_snapshot.rb
Normal file
49
lib/fog/google/requests/compute/insert_snapshot.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Mock
|
||||
|
||||
def insert_snapshot(snap_name)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
|
||||
def insert_snapshot(disk_name, zone_name, project=@project, opts={})
|
||||
|
||||
# This is unfortunate, since we might be called from 2 contexts
|
||||
# 1. disk.snapshot <-- here validation of disk_name is not needed
|
||||
# 2. snapshot.create <-- here we must validate the disk_name
|
||||
#
|
||||
# Validation would involve 'get'ing the disk by that name. This is
|
||||
# redundant (and expensive) for case (1) which is likely the common
|
||||
# codepath. So we won't do it.
|
||||
|
||||
api_method = @compute.disks.create_snapshot
|
||||
|
||||
parameters = {
|
||||
'disk' => disk_name,
|
||||
'zone' => zone_name,
|
||||
'project' => @project,
|
||||
}
|
||||
|
||||
snap_name = opts.delete('name')
|
||||
raise ArgumentError.new('Must specify snapshot name') unless snap_name
|
||||
body_object = { 'name' => snap_name }
|
||||
|
||||
# Merge in any remaining options (description)
|
||||
body_object.merge(opts)
|
||||
|
||||
result = self.build_result(api_method, parameters,
|
||||
body_object)
|
||||
response = self.build_response(result)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -187,7 +187,7 @@ module Fog
|
|||
request :get_vm_pending_question
|
||||
request :get_vms
|
||||
request :get_vms_by_metadata
|
||||
request :get_vms_disks_attached_to
|
||||
request :get_vms_disk_attached_to
|
||||
request :get_vms_in_lease_from_query
|
||||
request :instantiate_vapp_template # to be deprecated
|
||||
request :post_acquire_ticket
|
||||
|
@ -231,6 +231,7 @@ module Fog
|
|||
request :post_update_vapp_metadata
|
||||
request :post_update_vapp_template_metadata
|
||||
request :post_upgrade_hw_version
|
||||
request :post_upload_disk
|
||||
request :post_upload_media
|
||||
request :post_upload_vapp_template
|
||||
request :put_catalog_item_metadata_item_metadata
|
||||
|
@ -482,6 +483,7 @@ module Fog
|
|||
:name => 'vAppTemplate 1'
|
||||
}
|
||||
},
|
||||
:disks => {},
|
||||
:edge_gateways => {
|
||||
uuid => {
|
||||
:name => 'MockEdgeGateway',
|
||||
|
@ -627,6 +629,63 @@ module Fog
|
|||
[8,4,4,4,12].map {|i| Fog::Mock.random_hex(i)}.join('-')
|
||||
end
|
||||
|
||||
# Create a task.
|
||||
#
|
||||
# @param [String] operation A message describing the operation that is
|
||||
# tracked by this task.
|
||||
# @param [String] operation_name The short name of the operation that
|
||||
# is tracked by this task.
|
||||
# @param [Hash] owner Reference to the owner of the task. This is
|
||||
# typically the object that the task is creating or updating.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :type<~String> - Contains the MIME type of the entity.
|
||||
# @return [String] Object identifier of the task.
|
||||
def enqueue_task(operation, operation_name, owner, options={})
|
||||
task_id = uuid
|
||||
now = DateTime.now
|
||||
|
||||
data[:tasks][task_id] = {
|
||||
:cancel_requested => false,
|
||||
:details => '',
|
||||
:expiry_time => now + 86400, # in 24 hours
|
||||
:name => 'task',
|
||||
:progress => 1,
|
||||
:service_namespace => 'com.vmware.vcloud',
|
||||
:start_time => now,
|
||||
:status => 'running',
|
||||
}.merge(options).merge(
|
||||
:operation => operation,
|
||||
:operation_name => operation_name,
|
||||
:owner => owner
|
||||
)
|
||||
|
||||
task_id
|
||||
end
|
||||
|
||||
# @note As far as this method is concerned, the only possible task
|
||||
# states are 'running' and 'success'.
|
||||
#
|
||||
# @param [Hash] response_body
|
||||
# @return [Boolean]
|
||||
def process_task(response_body)
|
||||
task_id = response_body[:href].split('/').last
|
||||
task = data[:tasks][task_id]
|
||||
|
||||
if task[:status] == 'running'
|
||||
task[:end_time] = DateTime.now
|
||||
task[:progress] = 100
|
||||
task[:status] = 'success'
|
||||
|
||||
if task[:on_success]
|
||||
task[:on_success].call
|
||||
task.delete(:on_success)
|
||||
end
|
||||
end
|
||||
|
||||
return true if task[:status] == 'success'
|
||||
raise TaskError.new "status: #{task[:status]}, error: #{task[:Error]}"
|
||||
end
|
||||
|
||||
def add_id_from_href!(data={})
|
||||
data[:id] = data[:href].split('/').last
|
||||
end
|
||||
|
|
|
@ -22,6 +22,39 @@ module Fog
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def delete_disk(id)
|
||||
unless data[:disks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"(com.vmware.vcloud.entity.disk:#{id})\""
|
||||
)
|
||||
end
|
||||
|
||||
owner = {
|
||||
:href => make_href("disk/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.disk+xml'
|
||||
}
|
||||
task_id = enqueue_task(
|
||||
"Deleting Disk(#{id})", 'vdcDeleteDisk', owner,
|
||||
:on_success => lambda do
|
||||
data[:disks].delete(id)
|
||||
end
|
||||
)
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location,
|
||||
}.merge(task_body(task_id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 202,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,67 @@ module Fog
|
|||
# @param [String] id Object identifier of the media object.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the entity.
|
||||
# * :type<~String> - The MIME type of the entity.
|
||||
# * :id<~String> - The entity identifier, expressed in URN format.
|
||||
# The value of this attribute uniquely identifies the entity,
|
||||
# persists for the life of the entity, and is never reused.
|
||||
# * :operationKey<~String> - Optional unique identifier to support
|
||||
# idempotent semantics for create and delete operations.
|
||||
# * :name<~String> - The name of the entity.
|
||||
# * :cancelRequested<~String> - Whether user has requested this
|
||||
# processing to be canceled.
|
||||
# * :endTime<~String> - The date and time that processing of the
|
||||
# task was completed. May not be present if the task is still
|
||||
# being executed.
|
||||
# * :expiryTime<~String> - The date and time at which the task
|
||||
# resource will be destroyed and no longer available for
|
||||
# retrieval. May not be present if the task has not been executed
|
||||
# or is still being executed.
|
||||
# * :operation<~String> - A message describing the operation that
|
||||
# is tracked by this task.
|
||||
# * :operationName<~String> - The short name of the operation that
|
||||
# is tracked by this task.
|
||||
# * :serviceNamespace<~String> - Identifier of the service that
|
||||
# created the task.
|
||||
# * :startTime<~String> - The date and time the system started
|
||||
# executing the task. May not be present if the task has not been
|
||||
# executed yet.
|
||||
# * :status<~String> - The execution status of the task.
|
||||
# * :Link<~Array<Hash>>:
|
||||
# * :Description<~String> - Optional description.
|
||||
# * :Owner<~Hash> - Reference to the owner of the task. This is
|
||||
# typically the object that the task is creating or updating.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Error<~Hash> - Represents error information from a failed
|
||||
# task.
|
||||
# * :majorErrorCode<~String> - The class of the error. Matches
|
||||
# the HTTP status code.
|
||||
# * :message<~String> - An one line, human-readable message
|
||||
# describing the error that occurred.
|
||||
# * :minorErrorCode<~String> - Resource-specific error code.
|
||||
# * :stackTrace<~String> - The stack trace of the exception.
|
||||
# * :vendorSpecificErrorCode<~String> - A vendor- or
|
||||
# implementation-specific error code that can reference
|
||||
# specific modules or source lines for diagnostic purposes.
|
||||
# * :User<~Hash> - The user who started the task.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Organization<~Hash> - The organization to which the :User
|
||||
# belongs.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Progress<~String> - Read-only indicator of task progress as
|
||||
# an approximate percentage between 0 and 100. Not available
|
||||
# for all tasks.
|
||||
# * :Params
|
||||
# * :Details<~String> - Detailed message about the task. Also
|
||||
# contained by the :Owner entity when task status is
|
||||
# preRunning.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
|
@ -33,8 +94,27 @@ module Fog
|
|||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
media.is_used_here # avoid warning from syntax checker
|
||||
owner = {
|
||||
:href => make_href("media/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.media+xml'
|
||||
}
|
||||
task_id = enqueue_task(
|
||||
"Deleting Media File(#{media[:file][:uuid]})", 'vdcDeleteMedia', owner,
|
||||
:on_success => lambda do
|
||||
data[:medias].delete(id)
|
||||
end
|
||||
)
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location,
|
||||
}.merge(task_body(task_id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 202,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,17 +7,115 @@ module Fog
|
|||
# @param [String] id Object identifier of the disk.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the disk.
|
||||
# * :type<~String> - The MIME type of the disk.
|
||||
# * :id<~String> - The disk identifier, expressed in URN format.
|
||||
# * :name<~String> - The name of the disk.
|
||||
# * :status<~String> - Creation status of the disk.
|
||||
# * :busSubType<~String> - Disk bus sub type.
|
||||
# * :busType<~String> - Disk bus type.
|
||||
# * :size<~String> - Size of the disk.
|
||||
# * :Description<~String> - Optional description.
|
||||
# * :Tasks<~Hash> - A list of queued, running, or recently
|
||||
# completed tasks associated with this disk.
|
||||
# * :StorageProfile<~Hash> - Storage profile of the disk.
|
||||
# * :Owner<~Hash> - Disk owner.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/GET-Disk.html
|
||||
# @since vCloud API version 5.1
|
||||
def get_disk(id)
|
||||
request(
|
||||
response = request(
|
||||
:expects => 200,
|
||||
:idempotent => true,
|
||||
:method => 'GET',
|
||||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "disk/#{id}"
|
||||
)
|
||||
ensure_list! response.body, :Link
|
||||
ensure_list! response.body, :Tasks, :Task
|
||||
ensure_list! response.body, :Files, :File
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_disk(id)
|
||||
unless data[:disks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'No access to entity "com.vmware.vcloud.entity.disk:%s".' % id
|
||||
)
|
||||
end
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(disk_body(id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{@version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def disk_body(id)
|
||||
disk = data[:disks][id]
|
||||
storage_class_id = disk[:vdc_storage_class]
|
||||
|
||||
body = {
|
||||
:href => make_href("disk/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.disk+xml',
|
||||
:id => "urn:vcloud:disk:#{id}",
|
||||
:name => disk[:name],
|
||||
:status => disk[:status].to_s,
|
||||
:busSubType => disk[:bus_sub_type],
|
||||
:busType => disk[:bus_type],
|
||||
:size => disk[:size].to_s,
|
||||
:Link => [
|
||||
{
|
||||
:href => make_href("vdc/#{disk[:vdc_id]}"),
|
||||
:rel => 'up',
|
||||
:type => 'application/vnd.vmware.vcloud.vdc+xml'
|
||||
}
|
||||
],
|
||||
:Description => disk[:description],
|
||||
:Tasks => {
|
||||
# FIXME: there's only one for now
|
||||
:Task => disk[:tasks].map {|task_id| task_body(task_id)}.first
|
||||
},
|
||||
:Files => {
|
||||
:File => []
|
||||
},
|
||||
:StorageProfile => {
|
||||
:href => make_href("vdcStorageProfile/#{storage_class_id}"),
|
||||
:name => data[:vdc_storage_classes][storage_class_id][:name],
|
||||
:type => 'application/vnd.vmware.vcloud.vdcStorageProfile+xml',
|
||||
},
|
||||
:Owner => {
|
||||
:type => 'application/vnd.vmware.vcloud.owner+xml',
|
||||
:User => {
|
||||
:href => make_href("admin/user/#{user_uuid}"),
|
||||
:name => user_name,
|
||||
:type => 'application/vnd.vmware.admin.user+xml',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if api_version.to_f >= 5.1
|
||||
storage_class_id = disk[:vdc_storage_class]
|
||||
body[:VdcStorageProfile] = {
|
||||
:href => make_href("vdcStorageProfile/#{storage_class_id}"),
|
||||
:name => data[:vdc_storage_classes][storage_class_id][:name],
|
||||
:type => 'application/vnd.vmware.vcloud.vdcStorageProfile+xml',
|
||||
}
|
||||
end
|
||||
|
||||
body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,19 @@ module Fog
|
|||
# @param [String] id Object identifier of the disk.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the disk.
|
||||
# * :type<~String> - The MIME type of the disk.
|
||||
# * :Link<~Hash>:
|
||||
# * :href<~String> -
|
||||
# * :type<~String> -
|
||||
# * :rel<~String> -
|
||||
# * :User<~Hash> - Reference to the user who is the owner of this
|
||||
# disk.
|
||||
# * :href<~String> - The URI of the user.
|
||||
# * :name<~String> - The name of the user.
|
||||
# * :type<~String> - The MIME type of the user.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/GET-DiskOwner.html
|
||||
# @since vCloud API version 5.1
|
||||
|
@ -20,6 +33,38 @@ module Fog
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_disk_owner(id)
|
||||
unless data[:disks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'No access to entity "com.vmware.vcloud.entity.disk:%s".' % id
|
||||
)
|
||||
end
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location,
|
||||
:Link => {
|
||||
:href => make_href("disk/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.disk+xml',
|
||||
:rel => 'up'
|
||||
},
|
||||
:User => {
|
||||
:href => make_href("admin/user/#{user_uuid}"),
|
||||
:name => user_name,
|
||||
:type => 'application/vnd.vmware.admin.user+xml',
|
||||
}
|
||||
}
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{@version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,26 +13,97 @@ module Fog
|
|||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/GET-Media.html
|
||||
# @since vCloud API version 0.9
|
||||
def get_media(id)
|
||||
request(
|
||||
response = request(
|
||||
:expects => 200,
|
||||
:idempotent => true,
|
||||
:method => 'GET',
|
||||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "media/#{id}"
|
||||
)
|
||||
ensure_list! response.body, :Files, :File
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_media(id)
|
||||
unless media = data[:medias][id]
|
||||
unless data[:medias][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"(com.vmware.vcloud.entity.media:#{id})\"."
|
||||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
media.is_used_here # avoid warning from syntax checker
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(media_body(id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=>#{@api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def media_body(id)
|
||||
media = data[:medias][id]
|
||||
|
||||
body = {
|
||||
:size => media[:size].to_s,
|
||||
:imageType => media[:image_type],
|
||||
:status => media[:status].to_s,
|
||||
:name => media[:name],
|
||||
:id => "urn:vcloud:media:#{id}",
|
||||
:type => 'application/vnd.vmware.vcloud.media+xml',
|
||||
:href => make_href("media/#{id}"),
|
||||
:Link => {
|
||||
:href => make_href("vdc/#{media[:vdc_id]}"),
|
||||
:type => 'application/vnd.vmware.vcloud.vdc+xml',
|
||||
:rel => 'up'
|
||||
},
|
||||
:Description => media[:description] || '',
|
||||
:Tasks => {
|
||||
# FIXME: there's only one for now
|
||||
:Task => media[:tasks].map {|task_id| task_body(task_id)}.first
|
||||
},
|
||||
:Files => {
|
||||
:File => []
|
||||
},
|
||||
:Owner => {
|
||||
:type => 'application/vnd.vmware.vcloud.owner+xml',
|
||||
:User => {
|
||||
:href => make_href("admin/user/#{user_uuid}"),
|
||||
:name => user_uuid,
|
||||
:type => 'application/vnd.vmware.admin.user+xml',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if media[:status] == 0
|
||||
body[:Files][:File] << {
|
||||
:size => media[:size].to_s,
|
||||
:bytesTransferred => media[:file][:bytes_transferred].to_s,
|
||||
:name => 'file',
|
||||
:Link=> {
|
||||
:href => make_href("transfer/#{media[:file][:uuid]}/file"),
|
||||
:rel => 'upload:default'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
if api_version.to_f >= 5.1
|
||||
storage_class_id = media[:vdc_storage_class]
|
||||
body[:VdcStorageProfile] = {
|
||||
:href => make_href("vdcStorageProfile/#{storage_class_id}"),
|
||||
:name => data[:vdc_storage_classes][storage_class_id][:name],
|
||||
:type => 'application/vnd.vmware.vcloud.vdcStorageProfile+xml',
|
||||
}
|
||||
end
|
||||
|
||||
body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,17 @@ module Fog
|
|||
# @param [String] id Object identifier of the media object.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the media object.
|
||||
# * :type<~String> - The MIME type of the media object.
|
||||
# * :Link<~Hash>:
|
||||
# * :href<~String> -
|
||||
# * :type<~String> -
|
||||
# * :rel<~String> -
|
||||
# * :User<~Hash> - Reference to the user who is the owner of this
|
||||
# media object.
|
||||
# * :href<~String> - The URI of the user.
|
||||
# * :name<~String> - The name of the user.
|
||||
# * :type<~String> - The MIME type of the user.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
|
@ -25,14 +36,33 @@ module Fog
|
|||
|
||||
class Mock
|
||||
def get_media_owner(id)
|
||||
unless media = data[:medias][id]
|
||||
unless data[:medias][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"com.vmware.vcloud.entity.media:#{id}\"."
|
||||
'No access to entity "com.vmware.vcloud.entity.media:%s".' % id
|
||||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
media.is_used_here # avoid warning from syntax checker
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location,
|
||||
:Link => {
|
||||
:href => make_href("media/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.media+xml',
|
||||
:rel => 'up'
|
||||
},
|
||||
:User => {
|
||||
:href => make_href("admin/user/#{user_uuid}"),
|
||||
:name => user_name,
|
||||
:type => 'application/vnd.vmware.admin.user+xml',
|
||||
}
|
||||
}
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{@version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require 'date'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class VcloudDirector
|
||||
|
@ -7,6 +9,66 @@ module Fog
|
|||
# @param [String] id The object identifier of the task.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the entity.
|
||||
# * :type<~String> - The MIME type of the entity.
|
||||
# * :id<~String> - The entity identifier, expressed in URN format.
|
||||
# The value of this attribute uniquely identifies the entity,
|
||||
# persists for the life of the entity, and is never reused.
|
||||
# * :operationKey<~String> - Optional unique identifier to support
|
||||
# idempotent semantics for create and delete operations.
|
||||
# * :name<~String> - The name of the entity.
|
||||
# * :cancelRequested<~String> - Whether user has requested this
|
||||
# processing to be canceled.
|
||||
# * :endTime<~String> - The date and time that processing of the
|
||||
# task was completed. May not be present if the task is still
|
||||
# being executed.
|
||||
# * :expiryTime<~String> - The date and time at which the task
|
||||
# resource will be destroyed and no longer available for
|
||||
# retrieval. May not be present if the task has not been executed
|
||||
# or is still being executed.
|
||||
# * :operation<~String> - A message describing the operation that
|
||||
# is tracked by this task.
|
||||
# * :operationName<~String> - The short name of the operation that
|
||||
# is tracked by this task.
|
||||
# * :serviceNamespace<~String> - Identifier of the service that
|
||||
# created the task.
|
||||
# * :startTime<~String> - The date and time the system started
|
||||
# executing the task. May not be present if the task has not been
|
||||
# executed yet.
|
||||
# * :status<~String> - The execution status of the task.
|
||||
# * :Link<~Array<Hash>>:
|
||||
# * :Description<~String> - Optional description.
|
||||
# * :Owner<~Hash> - Reference to the owner of the task. This is
|
||||
# typically the object that the task is creating or updating.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Error<~Hash> - Represents error information from a failed
|
||||
# task.
|
||||
# * :majorErrorCode<~String> - The class of the error. Matches
|
||||
# the HTTP status code.
|
||||
# * :message<~String> - An one line, human-readable message
|
||||
# describing the error that occurred.
|
||||
# * :minorErrorCode<~String> - Resource-specific error code.
|
||||
# * :stackTrace<~String> - The stack trace of the exception.
|
||||
# * :vendorSpecificErrorCode<~String> - A vendor- or
|
||||
# implementation-specific error code that can reference
|
||||
# specific modules or source lines for diagnostic purposes.
|
||||
# * :User<~Hash> - The user who started the task.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Organization<~Hash> - The organization to which the :User
|
||||
# belongs.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Progress<~String> - Read-only indicator of task progress as an
|
||||
# approximate percentage between 0 and 100. Not available for all
|
||||
# tasks.
|
||||
# * :Params
|
||||
# * :Details<~String> - Detailed message about the task. Also
|
||||
# contained by the :Owner entity when task status is preRunning.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
|
@ -25,14 +87,71 @@ module Fog
|
|||
|
||||
class Mock
|
||||
def get_task(id)
|
||||
unless task = data[:tasks][id]
|
||||
unless data[:tasks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'This operation is denied.'
|
||||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
task.is_used_here # avoid warning from syntax checker
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(task_body(id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
:headers => {'Type' => "application/#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @param [String] id Object identifier of the task.
|
||||
# @return [Hash]
|
||||
def task_body(id)
|
||||
task = data[:tasks][id]
|
||||
|
||||
body = {
|
||||
:href => make_href("tasks/#{id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.task+xml',
|
||||
:id => "urn:vcloud:tasl:#{id}",
|
||||
:name => task[:name],
|
||||
:cancelRequested => task[:cancel_requested].to_s,
|
||||
:expiryTime => task[:expiry_time].strftime('%Y-%m-%dT%H:%M:%S%z'),
|
||||
:operation => task[:operation],
|
||||
:operationName => task[:operation_name],
|
||||
:serviceNamespace => task[:service_namespace],
|
||||
:status => task[:status],
|
||||
:Link => [],
|
||||
:Owner => task[:owner],
|
||||
:User => { # for now, always the current user
|
||||
:href => make_href("admin/user/#{user_uuid}"),
|
||||
:name => user_name,
|
||||
:type => 'application/vnd.vmware.admin.user+xml',
|
||||
},
|
||||
:Organization => { # for now, always the current org
|
||||
:href => make_href("org/#{data[:org][:uuid]}"),
|
||||
:name => data[:org][:name],
|
||||
:type => 'application/vnd.vmware.vcloud.org+xml',
|
||||
},
|
||||
:Progress => task[:progress].to_s,
|
||||
:Details => task[:details] || '',
|
||||
}
|
||||
body[:endTime] = task[:end_time].strftime('%Y-%m-%dT%H:%M:%S%z') if task[:end_time]
|
||||
body[:startTime] = task[:start_time].strftime('%Y-%m-%dT%H:%M:%S%z') if task[:start_time]
|
||||
body[:Description] = task[:description] if task[:description]
|
||||
|
||||
if task[:status] == 'running'
|
||||
body[:Link] << {
|
||||
:href => make_href("task/#{id}/action/cancel"),
|
||||
:type => 'application/vnd.vmware.vcloud.task+xml',
|
||||
:rel => 'cancel',
|
||||
}
|
||||
end
|
||||
|
||||
body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,78 @@ module Fog
|
|||
# @param [String] id Object identifier of the organization.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the entity.
|
||||
# * :type<~String> - The MIME type of the entity.
|
||||
# * :id<~String> - The entity identifier, expressed in URN format.
|
||||
# The value of this attribute uniquely identifies the entity,
|
||||
# persists for the life of the entity, and is never reused.
|
||||
# * :name<~String> - The name of the entity.
|
||||
# * :Task<~Array<Hash>>:
|
||||
# * :href<~String> - The URI of the entity.
|
||||
# * :type<~String> - The MIME type of the entity.
|
||||
# * :id<~String> - The entity identifier, expressed in URN
|
||||
# format. The value of this attribute uniquely identifies the
|
||||
# entity, persists for the life of the entity, and is never
|
||||
# reused.
|
||||
# * :operationKey<~String> - Optional unique identifier to
|
||||
# support idempotent semantics for create and delete
|
||||
# operations.
|
||||
# * :name<~String> - The name of the entity.
|
||||
# * :cancelRequested<~String> - Whether user has requested this
|
||||
# processing to be canceled.
|
||||
# * :endTime<~String> - The date and time that processing of the
|
||||
# task was completed. May not be present if the task is still
|
||||
# being executed.
|
||||
# * :expiryTime<~String> - The date and time at which the task
|
||||
# resource will be destroyed and no longer available for
|
||||
# retrieval. May not be present if the task has not been
|
||||
# executed or is still being executed.
|
||||
# * :operation<~String> - A message describing the operation that
|
||||
# is tracked by this task.
|
||||
# * :operationName<~String> - The short name of the operation
|
||||
# that is tracked by this task.
|
||||
# * :serviceNamespace<~String> - Identifier of the service that
|
||||
# created the task.
|
||||
# * :startTime<~String> - The date and time the system started
|
||||
# executing the task. May not be present if the task has not
|
||||
# been executed yet.
|
||||
# * :status<~String> - The execution status of the task.
|
||||
# * :Link<~Array<Hash>>:
|
||||
# * :Description<~String> - Optional description.
|
||||
# * :Owner<~Hash> - Reference to the owner of the task. This is
|
||||
# typically the object that the task is creating or updating.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Error<~Hash> - Represents error information from a failed
|
||||
# task.
|
||||
# * :majorErrorCode<~String> - The class of the error. Matches
|
||||
# the HTTP status code.
|
||||
# * :message<~String> - An one line, human-readable message
|
||||
# describing the error that occurred.
|
||||
# * :minorErrorCode<~String> - Resource-specific error code.
|
||||
# * :stackTrace<~String> - The stack trace of the exception.
|
||||
# * :vendorSpecificErrorCode<~String> - A vendor- or
|
||||
# implementation-specific error code that can reference
|
||||
# specific modules or source lines for diagnostic purposes.
|
||||
# * :User<~Hash> - The user who started the task.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Organization<~Hash> - The organization to which the :User
|
||||
# belongs.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Progress<~String> - Read-only indicator of task progress as
|
||||
# an approximate percentage between 0 and 100. Not available
|
||||
# for all tasks.
|
||||
# * :Params
|
||||
# * :Details<~String> - Detailed message about the task. Also
|
||||
# contained by the :Owner entity when task status is
|
||||
# preRunning.
|
||||
#
|
||||
# @raise [Fog::Compute::VcloudDirector::BadRequest]
|
||||
# @raise [Fog::Compute::VcloudDirector::Forbidden]
|
||||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/GET-TaskList.html
|
||||
|
@ -37,43 +108,15 @@ module Fog
|
|||
)
|
||||
end
|
||||
|
||||
body =
|
||||
{:xmlns=>xmlns,
|
||||
:xmlns_xsi=>xmlns_xsi,
|
||||
:name=>"Tasks Lists",
|
||||
:type=>"application/vnd.vmware.vcloud.tasksList+xml",
|
||||
:href=>make_href("tasksList/#{id}"),
|
||||
:xsi_schemaLocation=>xsi_schema_location}
|
||||
|
||||
tasks = data[:tasks].map do |task_id, task|
|
||||
{:status => task[:status],
|
||||
:startTime => task[:startTime].iso8601,
|
||||
:operationName => task[:operationName],
|
||||
:operation => task[:operation],
|
||||
:expiryTime => task[:expiryTime].utc.iso8601,
|
||||
:endTime => task[:endTime].iso8601,
|
||||
:cancelRequested => task[:cancelRequested].to_s,
|
||||
:name => task[:name],
|
||||
:id => "urn:vcloud:task:#{id}",
|
||||
:type => 'application/vnd.vmware.vcloud.task+xml',
|
||||
:href => make_href("task/#{task_id}"),
|
||||
:Owner =>
|
||||
{:type => "application/vnd.vmware.vcloud.vApp+xml",
|
||||
:name => "vApp_#{user_name}_0",
|
||||
:href=> make_href("vApp/vapp-#{uuid}")},
|
||||
:User =>
|
||||
{:type => "application/vnd.vmware.admin.user+xml",
|
||||
:name => user_name,
|
||||
:href => make_href("admin/user/#{user_uuid}")},
|
||||
:Organization =>
|
||||
{:type => "application/vnd.vmware.vcloud.org+xml",
|
||||
:name => org_name,
|
||||
:href => make_href("org/#{org_uuid}")},
|
||||
:Progress => task[:Progress].to_s,
|
||||
:Details => task[:Details] || ''}
|
||||
end
|
||||
tasks = tasks.first if tasks.size == 1
|
||||
body[:Task] = tasks
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location,
|
||||
:href => make_href("tasksList/#{id}"),
|
||||
:type => "application/vnd.vmware.vcloud.tasksList+xml",
|
||||
:name => "Tasks Lists",
|
||||
:Task => data[:tasks].keys.map {|task_id| task_body(task_id)}
|
||||
}
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 200,
|
||||
|
|
|
@ -10,14 +10,28 @@ module Fog
|
|||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/GET-VmsDisksAttachedTo.html
|
||||
# @since vCloud API version 5.1
|
||||
def get_vms_disks_attached_to(id)
|
||||
request(
|
||||
def get_vms_disk_attached_to(id)
|
||||
response = request(
|
||||
:expects => 200,
|
||||
:idempotent => true,
|
||||
:method => 'GET',
|
||||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "disk/#{id}/attachedVms"
|
||||
)
|
||||
ensure_list! response.body, :VmReference
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_vms_disk_attached_to(id)
|
||||
unless data[:disks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'No access to entity "com.vmware.vcloud.entity.disk:%s".' % id
|
||||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
end
|
|
@ -20,6 +20,24 @@ module Fog
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def post_cancel_task(id)
|
||||
unless task = data[:tasks][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'No access to entity "com.vmware.vcloud.entity.task:%s"' % id
|
||||
)
|
||||
end
|
||||
|
||||
# @note Tasks don't actually get cancelled (confirmed VCloud Director
|
||||
# bug) so we'll emulate that. Set the flag and we're done!
|
||||
task[:cancel_requested] = true
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 204
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,7 +36,7 @@ module Fog
|
|||
}
|
||||
end.to_xml
|
||||
|
||||
request(
|
||||
response = request(
|
||||
:body => body,
|
||||
:expects => 201,
|
||||
:headers => {'Content-Type' => 'application/vnd.vmware.vcloud.cloneMediaParams+xml'},
|
||||
|
@ -44,6 +44,57 @@ module Fog
|
|||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "vdc/#{vdc_id}/action/cloneMedia"
|
||||
)
|
||||
ensure_list! response.body, :Files, :File
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def post_clone_media(vdc_id, source_id, options={})
|
||||
# TODO: check this happens.
|
||||
unless source_media = data[:medias][source_id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"(com.vmware.vcloud.entity.media:#{source_id})\"."
|
||||
)
|
||||
end
|
||||
unless data[:vdcs][vdc_id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"(com.vmware.vcloud.entity.vdc:#{vdc_id})\"."
|
||||
)
|
||||
end
|
||||
|
||||
media_id = uuid
|
||||
media_name = "#{source_media[:name]}-copy-#{uuid}"
|
||||
|
||||
owner = {
|
||||
:href => make_href("media/#{media_id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.media+xml'
|
||||
}
|
||||
task_id = enqueue_task(
|
||||
"Copy Media File #{media_name}(#{media_id})", 'vdcCopyMedia', owner,
|
||||
:on_success => lambda do
|
||||
data[:medias][media_id][:status] = 1
|
||||
end
|
||||
)
|
||||
|
||||
media = source_media.dup.merge(
|
||||
:name => media_name,
|
||||
:status => 0,
|
||||
:tasks => [task_id]
|
||||
)
|
||||
data[:medias][media_id] = media
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(media_body(media_id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 201,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
133
lib/fog/vcloud_director/requests/compute/post_upload_disk.rb
Normal file
133
lib/fog/vcloud_director/requests/compute/post_upload_disk.rb
Normal file
|
@ -0,0 +1,133 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class VcloudDirector
|
||||
class Real
|
||||
# Create a disk.
|
||||
#
|
||||
# @param [String] id Object identifier of the vDC.
|
||||
# @param [String] name The name of the disk.
|
||||
# @param [Integer] size Size of the disk. For modify operation this is
|
||||
# required only for the XSD validation it could not be changed.
|
||||
# @param [Hash] options
|
||||
# @option options [String] :operationKey Optional unique identifier to
|
||||
# support idempotent semantics for create and delete operations.
|
||||
# @option options [Integer] :busSubType Disk bus sub type.
|
||||
# @option options [Integer] :busType Disk bus type.
|
||||
# @option options [String] :Description Optional description.
|
||||
# @return [Excon::Response]
|
||||
# * body<~Hash>:
|
||||
# * :href<~String> - The URI of the disk.
|
||||
# * :type<~String> - The MIME type of the disk.
|
||||
# * :id<~String> - The disk identifier, expressed in URN format.
|
||||
# * :operationKey<~String> - Optional unique identifier to support
|
||||
# idempotent semantics for create and delete operations.
|
||||
# * :name<~String> - The name of the disk.
|
||||
# * :status<~String> - Creation status of the disk.
|
||||
# * :busSubType<~String> - Disk bus sub type.
|
||||
# * :busType<~String> - Disk bus type.
|
||||
# * :size<~String> - Size of the disk.
|
||||
# * :Link:
|
||||
# * :Description<~String> - Optional description.
|
||||
# * :Tasks<~Hash>:
|
||||
# * :StorageProfile<~Hash> - Storage profile of the disk.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
# * :Owner<~Hash> - Disk owner.
|
||||
# * :type<~String> - The MIME type of the entity.
|
||||
# * :User<~Hash> - Reference to the user who is the owner of this
|
||||
# disk.
|
||||
# * :href<~String> - Contains the URI to the entity.
|
||||
# * :name<~String> - Contains the name of the entity.
|
||||
# * :type<~String> - Contains the type of the entity.
|
||||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/POST-CreateDisk.html
|
||||
# @since vCloud API version 5.1
|
||||
def post_upload_disk(id, name, size, options={})
|
||||
body = Nokogiri::XML::Builder.new do
|
||||
DiskCreateParams(:xmlns => 'http://www.vmware.com/vcloud/v1.5') {
|
||||
attrs = {
|
||||
:name => name,
|
||||
:size => size
|
||||
}
|
||||
attrs[:operationKey] = options[:operationKey] if options.key?(:operationKey)
|
||||
attrs[:busSubType] = options[:busSubType] if options.key?(:busSubType)
|
||||
attrs[:busType] = options[:busType] if options.key?(:busType)
|
||||
Disk(attrs) {
|
||||
if options.key?(:Description)
|
||||
Description options[:Description]
|
||||
end
|
||||
if options.key?(:StorageProfile)
|
||||
attrs = {
|
||||
:href => options[:StorageProfile][:href]
|
||||
}
|
||||
StorageProfile(attrs)
|
||||
end
|
||||
}
|
||||
}
|
||||
end.to_xml
|
||||
|
||||
request(
|
||||
:body => body,
|
||||
:expects => 201,
|
||||
:headers => {'Content-Type' => 'application/vnd.vmware.vcloud.diskCreateParams+xml'},
|
||||
:method => 'POST',
|
||||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "vdc/#{id}/disk"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def post_upload_disk(id, name, size, options={})
|
||||
unless size.to_s =~ /^\d+$/
|
||||
raise Fog::Compute::VcloudDirector::BadRequest.new(
|
||||
"validation error on field 'diskSpec.sizeBytes': must be greater than or equal to 0"
|
||||
)
|
||||
end
|
||||
unless data[:vdcs][id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
'No access to entity "(com.vmware.vcloud.entity.vdc:%s)".' % id
|
||||
)
|
||||
end
|
||||
|
||||
disk_id = uuid
|
||||
|
||||
owner = {
|
||||
:href => make_href("disk/#{disk_id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.disk+xml'
|
||||
}
|
||||
task_id = enqueue_task(
|
||||
"Creating Disk #{name}(#{disk_id})", 'vdcCreateDisk', owner,
|
||||
:on_success => lambda do
|
||||
data[:disks][disk_id][:status] = 1
|
||||
end
|
||||
)
|
||||
|
||||
disk = {
|
||||
:description => options[:Description],
|
||||
:name => name,
|
||||
:size => size.to_i,
|
||||
:status => 0,
|
||||
:tasks => [task_id],
|
||||
:vdc_id => id,
|
||||
:vdc_storage_class => data[:vdc_storage_classes].detect {|k,v| v[:default]}.first
|
||||
}
|
||||
data[:disks][disk_id] = disk
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(disk_body(disk_id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 201,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -22,6 +22,7 @@ module Fog
|
|||
#
|
||||
# @see http://pubs.vmware.com/vcd-51/topic/com.vmware.vcloud.api.reference.doc_51/doc/operations/POST-UploadMedia.html
|
||||
# @since vCloud API version 0.9
|
||||
# @todo Support vDC Storage Profiles.
|
||||
def post_upload_media(vdc_id, name, image_type, size, options={})
|
||||
body = Nokogiri::XML::Builder.new do
|
||||
attrs = {
|
||||
|
@ -38,7 +39,7 @@ module Fog
|
|||
}
|
||||
end.to_xml
|
||||
|
||||
request(
|
||||
response = request(
|
||||
:body => body,
|
||||
:expects => 201,
|
||||
:headers => {'Content-Type' => 'application/vnd.vmware.vcloud.media+xml'},
|
||||
|
@ -46,6 +47,8 @@ module Fog
|
|||
:parser => Fog::ToHashDocument.new,
|
||||
:path => "vdc/#{vdc_id}/media"
|
||||
)
|
||||
ensure_list! response.body, :Files, :File
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -61,14 +64,55 @@ module Fog
|
|||
'validation error on field \'size\': must be greater than or equal to 0'
|
||||
)
|
||||
end
|
||||
unless vdc = data[:vdcs][vdc_id]
|
||||
unless data[:vdcs][vdc_id]
|
||||
raise Fog::Compute::VcloudDirector::Forbidden.new(
|
||||
"No access to entity \"(com.vmware.vcloud.entity.vdc:#{vdc_id})\"."
|
||||
)
|
||||
end
|
||||
|
||||
Fog::Mock.not_implemented
|
||||
vdc.is_used_here # avoid warning from syntax checker
|
||||
media_id = uuid
|
||||
file_id = uuid
|
||||
|
||||
owner = {
|
||||
:href => make_href("media/#{media_id}"),
|
||||
:type => 'application/vnd.vmware.vcloud.media+xml'
|
||||
}
|
||||
task_id = enqueue_task(
|
||||
"Importing Media File #{name}(#{file_id})", 'vdcUploadMedia', owner,
|
||||
:on_success => lambda do
|
||||
media = data[:medias][media_id]
|
||||
media[:file][:bytes_transferred] = media[:size]
|
||||
media[:status] = 1
|
||||
end
|
||||
)
|
||||
|
||||
media = {
|
||||
:description => options[:Description],
|
||||
:file => {
|
||||
:bytes_transferred => 0,
|
||||
:uuid => file_id
|
||||
},
|
||||
:image_type => image_type,
|
||||
:name => name,
|
||||
:size => size.to_i,
|
||||
:status => 0,
|
||||
:tasks => [task_id],
|
||||
:vdc_id => vdc_id,
|
||||
:vdc_storage_class => data[:vdc_storage_classes].detect {|k,v| v[:default]}.first
|
||||
}
|
||||
data[:medias][media_id] = media
|
||||
|
||||
body = {
|
||||
:xmlns => xmlns,
|
||||
:xmlns_xsi => xmlns_xsi,
|
||||
:xsi_schemaLocation => xsi_schema_location
|
||||
}.merge(media_body(media_id))
|
||||
|
||||
Excon::Response.new(
|
||||
:status => 201,
|
||||
:headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"},
|
||||
:body => body
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -54,7 +54,13 @@ Shindo.tests do
|
|||
returns(nil, 'File.expand_path raises because of non-absolute path') {
|
||||
ENV.delete('FOG_RC')
|
||||
ENV['HOME'] = '.'
|
||||
Fog.credentials_path
|
||||
|
||||
if RUBY_PLATFORM == 'java'
|
||||
Fog::Logger.warning("Stubbing out non-absolute path credentials test due to JRuby bug: https://github.com/jruby/jruby/issues/1163")
|
||||
nil
|
||||
else
|
||||
Fog.credentials_path
|
||||
end
|
||||
}
|
||||
|
||||
returns(nil, 'returns nil when neither FOG_RC or HOME are set') {
|
||||
|
|
|
@ -46,7 +46,7 @@ posuere eu odio. Donec sodales, ante porta condimentum
|
|||
}
|
||||
|
||||
@xmlNS = %{
|
||||
<myns:MyResponse>
|
||||
<myns:MyResponse xmlns:myns="http://www.example.com/">
|
||||
<myns:MyObject>
|
||||
<myns:key1>value1</myns:key1>
|
||||
<myns:key2>value2</myns:key2>
|
||||
|
|
|
@ -1,6 +1,166 @@
|
|||
Shindo.tests('Compute::VcloudDirector | disk requests', ['vclouddirector']) do
|
||||
|
||||
@service = Fog::Compute::VcloudDirector.new
|
||||
@disk_name = VcloudDirector::Compute::Helper.test_name
|
||||
|
||||
tests('error conditions') do
|
||||
tests('#post_upload_disk') do
|
||||
tests('Invalid size').raises(Fog::Compute::VcloudDirector::BadRequest) do
|
||||
@service.post_upload_disk('00000000-0000-0000-0000-000000000000', @disk_name, -1)
|
||||
end
|
||||
end
|
||||
tests('Upload to non-existent vDC').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.post_upload_disk('00000000-0000-0000-0000-000000000000', @disk_name, 0)
|
||||
end
|
||||
tests('Retrieve non-existent Disk').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_disk('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('Retrieve owner of non-existent Disk').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_disk_owner('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('Retrieve VM list for non-existent Disk').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_vms_disk_attached_to('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('Delete non-existent Disk').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.delete_disk('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
end
|
||||
|
||||
@org = VcloudDirector::Compute::Helper.current_org(@service)
|
||||
@size = 1024
|
||||
|
||||
tests('Upload and manipulate a disk') do
|
||||
tests('#post_upload_disk').data_matches_schema(VcloudDirector::Compute::Schema::DISK_TYPE) do
|
||||
@vdc_id = VcloudDirector::Compute::Helper.first_vdc_id(@org)
|
||||
@disk = @service.post_upload_disk(@vdc_id, @disk_name, @size).body
|
||||
end
|
||||
@service.process_task(@disk[:Tasks][:Task])
|
||||
@disk_id = @disk[:href].split('/').last
|
||||
|
||||
tests("#get_disk(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::DISK_TYPE) do
|
||||
@disk = @service.get_disk(@disk_id).body
|
||||
end
|
||||
tests("disk[:name]").returns(@disk_name) { @disk[:name] }
|
||||
tests("disk[:size]").returns(@size) { @disk[:size].to_i }
|
||||
|
||||
tests("#get_disk_owner(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::OWNER_TYPE) do
|
||||
@owner = @service.get_disk_owner(@disk_id).body
|
||||
end
|
||||
tests("owner[:User][:name]").returns(@service.user_name) { @owner[:User][:name] }
|
||||
|
||||
#tests("#put_disk(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
# @disk_name += '-renamed'
|
||||
# @task = @service.put_disk(@disk_id, @disk_name).body
|
||||
#end
|
||||
#@service.process_task(@task)
|
||||
#tests("#get_disk(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::DISK_TYPE) do
|
||||
# @disk = @service.get_disk(@disk_id).body
|
||||
#end
|
||||
#tests("disk[:name]").returns(@disk_name) { @disk[:name] }
|
||||
#tests("disk[:size]").returns(@size) { @disk[:size].to_i } # shouldn't change
|
||||
|
||||
tests('disk metadata') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
tests("#put_disk_metadata_item_metadata(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
@task = @service.put_disk_metadata_item_metadata(@disk_id, 'fog-test-key', 'fog-test-value').body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
|
||||
tests("#put_disk_metadata_item_metadata(#{@disk_id})") do
|
||||
tests("#put_disk_metadata_item_metadata(Boolean)").returns(true) do
|
||||
task = @service.put_disk_metadata_item_metadata(@disk_id, 'fog-test-boolean', true).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
tests("#put_disk_metadata_item_metadata(DateTime)").returns(true) do
|
||||
task = @service.put_disk_metadata_item_metadata(@disk_id, 'fog-test-datetime', DateTime.now).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
tests("#put_disk_metadata_item_metadata(Number)").returns(true) do
|
||||
task = @service.put_disk_metadata_item_metadata(@disk_id, 'fog-test-number', 111).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
end
|
||||
|
||||
tests("#post_update_disk_metadata(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
metadata = {
|
||||
'fog-test-key-update' => 'fog-test-value-update',
|
||||
'fog-test-boolean-update' => false,
|
||||
'fog-test-datetime-update' => DateTime.now,
|
||||
'fog-test-number-update' => 222
|
||||
}
|
||||
@task = @service.post_update_disk_metadata(@disk_id, metadata).body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
|
||||
tests("#get_disk_metadata(#{@disk_id})") do
|
||||
tests('response format').data_matches_schema(VcloudDirector::Compute::Schema::METADATA_TYPE) do
|
||||
@metadata = @service.get_disk_metadata(@disk_id).body
|
||||
end
|
||||
tests('TypedValue') do
|
||||
pending if @service.api_version.to_f < 5.1
|
||||
tests('key').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('boolean').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('key-update').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('boolean-update').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime-update').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number-update').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tests("#get_vms_disk_attached_to(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::VMS_TYPE) do
|
||||
pending if Fog.mocking?
|
||||
@service.get_vms_disk_attached_to(@disk_id).body
|
||||
end
|
||||
|
||||
tests("#delete_disk(#{@disk_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
@task = @service.delete_disk(@disk_id).body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
end
|
||||
|
||||
tests('Disk no longer exists') do
|
||||
tests("#get_disk(#{@disk_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_disk(@disk_id)
|
||||
end
|
||||
tests("#get_disk_owner(#{@disk_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_disk_owner(@disk_id)
|
||||
end
|
||||
tests("#get_disk_metadata(#{@disk_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
pending if Fog.mocking?
|
||||
@service.get_disk_metadata(@disk_id)
|
||||
end
|
||||
tests("#delete_disk(#{@disk_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.delete_disk(@disk_id)
|
||||
end
|
||||
end
|
||||
|
||||
tests('#get_disks_from_query') do
|
||||
pending if Fog.mocking?
|
||||
|
@ -15,9 +175,4 @@ Shindo.tests('Compute::VcloudDirector | disk requests', ['vclouddirector']) do
|
|||
end
|
||||
end
|
||||
|
||||
tests('Retrieve non-existent Disk').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
pending if Fog.mocking?
|
||||
@service.get_disk('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -11,11 +11,15 @@ class VcloudDirector
|
|||
end
|
||||
|
||||
def self.current_org(service)
|
||||
service.get_organization(current_org_id(service)).body
|
||||
end
|
||||
|
||||
def self.current_org_id(service)
|
||||
session = service.get_current_session.body
|
||||
link = session[:Link].detect do |l|
|
||||
l[:type] == 'application/vnd.vmware.vcloud.org+xml'
|
||||
end
|
||||
service.get_organization(link[:href].split('/').last).body
|
||||
link[:href].split('/').last
|
||||
end
|
||||
|
||||
def self.first_vdc_id(org)
|
||||
|
|
|
@ -1,31 +1,60 @@
|
|||
Shindo.tests('Compute::VcloudDirector | media requests', ['vclouddirector']) do
|
||||
|
||||
@service = Fog::Compute::VcloudDirector.new
|
||||
|
||||
tests('error conditions') do
|
||||
tests('#post_upload_media') do
|
||||
tests('Invalid image_type').raises(Fog::Compute::VcloudDirector::BadRequest) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'isox', 0)
|
||||
end
|
||||
tests('Invalid size').raises(Fog::Compute::VcloudDirector::BadRequest) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'iso', -1)
|
||||
end
|
||||
end
|
||||
tests('Upload to non-existent vDC').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'iso', 0)
|
||||
end
|
||||
tests('Retrieve non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_media('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('Retrieve owner of non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_media_owner('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('Delete non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.delete_media('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
end
|
||||
|
||||
@org = VcloudDirector::Compute::Helper.current_org(@service)
|
||||
@media_name = VcloudDirector::Compute::Helper.test_name
|
||||
|
||||
tests('Upload and manipulate a media object') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
File.open(VcloudDirector::Compute::Helper.fixture('test.iso'), 'rb') do |iso|
|
||||
tests('#post_upload_media').data_matches_schema(VcloudDirector::Compute::Schema::MEDIA_TYPE) do
|
||||
@vdc_id = VcloudDirector::Compute::Helper.first_vdc_id(@org)
|
||||
@media = @service.post_upload_media(@vdc_id, @media_name, 'iso', iso.size).body
|
||||
@size = File.size(iso.path)
|
||||
@media = @service.post_upload_media(@vdc_id, @media_name, 'iso', @size).body
|
||||
end
|
||||
|
||||
tests('media object has an upload link').returns(true) do
|
||||
@link = @media[:Files][:File][:Link]
|
||||
tests('media object has exactly one file').returns(true) do
|
||||
@media[:Files][:File].size == 1
|
||||
end
|
||||
|
||||
tests('media object file has an upload link').returns(true) do
|
||||
@link = @media[:Files][:File].first[:Link]
|
||||
@link[:rel] == 'upload:default'
|
||||
end
|
||||
|
||||
headers = {
|
||||
'Content-Length' => iso.size,
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'x-vcloud-authorization' => @service.vcloud_token
|
||||
}
|
||||
Excon.put(
|
||||
@link[:href], :body => iso.read, :expects => 200, :headers => headers
|
||||
)
|
||||
unless Fog.mocking?
|
||||
headers = {
|
||||
'Content-Length' => @size,
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'x-vcloud-authorization' => @service.vcloud_token
|
||||
}
|
||||
Excon.put(
|
||||
@link[:href], :body => iso.read, :expects => 200, :headers => headers
|
||||
)
|
||||
end
|
||||
|
||||
@service.process_task(@media[:Tasks][:Task])
|
||||
@media_id = @media[:href].split('/').last
|
||||
|
@ -35,81 +64,85 @@ Shindo.tests('Compute::VcloudDirector | media requests', ['vclouddirector']) do
|
|||
end
|
||||
tests("media[:name]").returns(@media_name) { @media[:name] }
|
||||
tests("media[:imageType]").returns('iso') { @media[:imageType] }
|
||||
tests("media[:size]").returns(iso.size) { @media[:size].to_i }
|
||||
tests("media[:size]").returns(@size) { @media[:size].to_i }
|
||||
|
||||
tests("#get_media_owner(#{@media_id})").data_matches_schema(VcloudDirector::Compute::Schema::OWNER_TYPE) do
|
||||
@owner = @service.get_media_owner(@media_id).body
|
||||
end
|
||||
tests("owner[:User][:name]").returns(@service.user_name) { @owner[:User][:name] }
|
||||
|
||||
tests("#put_media_metadata_item_metadata(#{@media_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
@task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-key', 'fog-test-value').body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
tests('media metadata') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
tests("#put_media_metadata_item_metadata(#{@media_id})") do
|
||||
tests("#put_media_metadata_item_metadata(Boolean)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-boolean', true).body
|
||||
@service.process_task(task)
|
||||
tests("#put_media_metadata_item_metadata(#{@media_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
@task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-key', 'fog-test-value').body
|
||||
end
|
||||
tests("#put_media_metadata_item_metadata(DateTime)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-datetime', DateTime.now).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
tests("#put_media_metadata_item_metadata(Number)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-number', 111).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
end
|
||||
@service.process_task(@task)
|
||||
|
||||
tests("#post_update_media_metadata(#{@media_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
metadata = {
|
||||
'fog-test-key-update' => 'fog-test-value-update',
|
||||
'fog-test-boolean-update' => false,
|
||||
'fog-test-datetime-update' => DateTime.now,
|
||||
'fog-test-number-update' => 222
|
||||
}
|
||||
@task = @service.post_update_media_metadata(@media_id, metadata).body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
|
||||
tests("#get_media_metadata(#{@media_id})") do
|
||||
tests('response format').data_matches_schema(VcloudDirector::Compute::Schema::METADATA_TYPE) do
|
||||
@metadata = @service.get_media_metadata(@media_id).body
|
||||
tests("#put_media_metadata_item_metadata(#{@media_id})") do
|
||||
tests("#put_media_metadata_item_metadata(Boolean)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-boolean', true).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
tests("#put_media_metadata_item_metadata(DateTime)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-datetime', DateTime.now).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
tests("#put_media_metadata_item_metadata(Number)").returns(true) do
|
||||
task = @service.put_media_metadata_item_metadata(@media_id, 'fog-test-number', 111).body
|
||||
@service.process_task(task)
|
||||
end
|
||||
end
|
||||
tests('TypedValue') do
|
||||
pending if @service.api_version.to_f < 5.1
|
||||
tests('key').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
|
||||
tests("#post_update_media_metadata(#{@media_id})").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
metadata = {
|
||||
'fog-test-key-update' => 'fog-test-value-update',
|
||||
'fog-test-boolean-update' => false,
|
||||
'fog-test-datetime-update' => DateTime.now,
|
||||
'fog-test-number-update' => 222
|
||||
}
|
||||
@task = @service.post_update_media_metadata(@media_id, metadata).body
|
||||
end
|
||||
@service.process_task(@task)
|
||||
|
||||
tests("#get_media_metadata(#{@media_id})") do
|
||||
tests('response format').data_matches_schema(VcloudDirector::Compute::Schema::METADATA_TYPE) do
|
||||
@metadata = @service.get_media_metadata(@media_id).body
|
||||
end
|
||||
tests('boolean').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('key-update').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('boolean-update').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime-update').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number-update').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
tests('TypedValue') do
|
||||
pending if @service.api_version.to_f < 5.1
|
||||
tests('key').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('boolean').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('key-update').returns('MetadataStringValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-key-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('boolean-update').returns('MetadataBooleanValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-boolean-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('datetime-update').returns('MetadataDateTimeValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-datetime-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
tests('number-update').returns('MetadataNumberValue') do
|
||||
entry = @metadata[:MetadataEntry].detect {|e| e[:Key] == 'fog-test-number-update'}
|
||||
entry[:TypedValue][:xsi_type]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -131,7 +164,6 @@ Shindo.tests('Compute::VcloudDirector | media requests', ['vclouddirector']) do
|
|||
end
|
||||
|
||||
tests('Media item no longer exists') do
|
||||
pending if Fog.mocking?
|
||||
tests("#get_media(#{@media_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_media(@media_id)
|
||||
end
|
||||
|
@ -139,6 +171,7 @@ Shindo.tests('Compute::VcloudDirector | media requests', ['vclouddirector']) do
|
|||
@service.get_media_owner(@media_id)
|
||||
end
|
||||
tests("#get_media_metadata(#{@media_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
pending if Fog.mocking?
|
||||
@service.get_media_metadata(@media_id)
|
||||
end
|
||||
tests("#delete_media(#{@media_id})").raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
|
@ -159,27 +192,4 @@ Shindo.tests('Compute::VcloudDirector | media requests', ['vclouddirector']) do
|
|||
end
|
||||
end
|
||||
|
||||
tests('Invalid image_type').raises(Fog::Compute::VcloudDirector::BadRequest) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'isox', 0)
|
||||
end
|
||||
tests('Invalid size').raises(Fog::Compute::VcloudDirector::BadRequest) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'iso', -1)
|
||||
end
|
||||
|
||||
tests('Upload to non-existent vDC').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.post_upload_media('00000000-0000-0000-0000-000000000000', 'test.iso', 'iso', 0)
|
||||
end
|
||||
|
||||
tests('Retrieve non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_media('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
|
||||
tests('Retrieve owner of non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_media_owner('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
|
||||
tests('Delete non-existent Media').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.delete_media('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ class VcloudDirector
|
|||
|
||||
# Represents a list of files to be transferred (uploaded or downloaded).
|
||||
FILES_LIST_TYPE = {
|
||||
:File => FILE_TYPE
|
||||
:File => [FILE_TYPE]
|
||||
}
|
||||
|
||||
# Container for query result sets.
|
||||
|
@ -123,7 +123,7 @@ class VcloudDirector
|
|||
:status => Fog::Nullable::String,
|
||||
:Description => Fog::Nullable::String,
|
||||
# :Tasks => TASKS_IN_PROGRESS_TYPE,
|
||||
# :Files => FILES_LIST_TYPE
|
||||
# :Files => FILES_LIST_TYPE
|
||||
})
|
||||
|
||||
# Container for references to ResourceEntity objects in this vDC.
|
||||
|
@ -620,6 +620,19 @@ class VcloudDirector
|
|||
:RoleReferences => ROLE_REFERENCES_TYPE,
|
||||
:Networks => NETWORKS_TYPE
|
||||
})
|
||||
|
||||
# Represents a named disk.
|
||||
DISK_TYPE = RESOURCE_ENTITY_TYPE.merge({
|
||||
:busSubType => Fog::Nullable::String,
|
||||
:busType => Fog::Nullable::String,
|
||||
:size => String,
|
||||
:StorageProfile => REFERENCE_TYPE,
|
||||
:Owner => OWNER_TYPE
|
||||
})
|
||||
|
||||
VMS_TYPE = RESOURCE_TYPE.merge({
|
||||
:VmReference => [REFERENCE_TYPE]
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,20 @@ Shindo.tests('Compute::VcloudDirector | task requests', ['vclouddirector']) do
|
|||
|
||||
@service = Fog::Compute::VcloudDirector.new
|
||||
|
||||
tests('error conditions') do
|
||||
tests('retrieve non-existent TasksList').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_task_list('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('retrieve non-existent Task').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_task('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
tests('cancel non-existent Task').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.post_cancel_task('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
end
|
||||
|
||||
@org_id = VcloudDirector::Compute::Helper.current_org_id(@service)
|
||||
|
||||
tests('#get_task_list').data_matches_schema(VcloudDirector::Compute::Schema::TASKS_LIST_TYPE) do
|
||||
session = @service.get_current_session.body
|
||||
org_href = session[:Link].detect {|l| l[:type] == 'application/vnd.vmware.vcloud.org+xml'}[:href]
|
||||
|
@ -9,12 +23,13 @@ Shindo.tests('Compute::VcloudDirector | task requests', ['vclouddirector']) do
|
|||
@tasks_list = @service.get_task_list(@org_uuid).body
|
||||
end
|
||||
|
||||
tests('retrieve non-existent TasksList').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_task_list('00000000-0000-0000-0000-000000000000')
|
||||
end
|
||||
|
||||
tests('retrieve non-existent Task').raises(Fog::Compute::VcloudDirector::Forbidden) do
|
||||
@service.get_task('00000000-0000-0000-0000-000000000000')
|
||||
tests('each task in the task list') do
|
||||
@tasks_list[:Task].each do |task|
|
||||
task_id = task[:href].split('/').last
|
||||
tests("#get_task(#{task_id}").data_matches_schema(VcloudDirector::Compute::Schema::TASK_TYPE) do
|
||||
@service.get_task(task_id).body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue