deltacloud-core 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +10 -12
- data/config/drivers/{aruba.yaml → arubacloud.yaml} +2 -2
- data/deltacloud-core.gemspec +4 -4
- data/lib/cimi/collections/address_templates.rb +1 -1
- data/lib/cimi/collections/addresses.rb +2 -2
- data/lib/cimi/collections/base.rb +1 -0
- data/lib/cimi/collections/credentials.rb +1 -1
- data/lib/cimi/collections/forwarding_group_templates.rb +1 -1
- data/lib/cimi/collections/forwarding_groups.rb +1 -1
- data/lib/cimi/collections/machine_configurations.rb +1 -1
- data/lib/cimi/collections/machine_images.rb +1 -1
- data/lib/cimi/collections/machine_templates.rb +1 -1
- data/lib/cimi/collections/machines.rb +2 -2
- data/lib/cimi/collections/network_configurations.rb +1 -1
- data/lib/cimi/collections/network_port_configurations.rb +1 -1
- data/lib/cimi/collections/network_port_templates.rb +1 -1
- data/lib/cimi/collections/network_ports.rb +1 -1
- data/lib/cimi/collections/network_templates.rb +1 -1
- data/lib/cimi/collections/networks.rb +1 -1
- data/lib/cimi/collections/volume_configurations.rb +1 -1
- data/lib/cimi/collections/volume_images.rb +1 -1
- data/lib/cimi/collections/volume_templates.rb +1 -1
- data/lib/cimi/collections/volumes.rb +1 -1
- data/lib/cimi/helpers/database_helper.rb +16 -61
- data/lib/cimi/helpers/filter_helper.rb +41 -0
- data/lib/cimi/helpers/select_helper.rb +62 -0
- data/lib/cimi/models.rb +21 -2
- data/lib/cimi/models/address.rb +9 -7
- data/lib/cimi/models/address_template.rb +4 -4
- data/lib/cimi/models/base.rb +62 -197
- data/lib/cimi/models/collection.rb +78 -70
- data/lib/cimi/models/disk.rb +15 -8
- data/lib/cimi/models/machine.rb +27 -29
- data/lib/cimi/models/machine_image.rb +10 -13
- data/lib/cimi/models/machine_template.rb +3 -3
- data/lib/cimi/models/resource.rb +190 -0
- data/lib/cimi/models/schema.rb +9 -0
- data/lib/cimi/models/volume.rb +10 -13
- data/lib/cimi/models/volume_configuration.rb +3 -3
- data/lib/cimi/models/volume_template.rb +2 -2
- data/lib/cimi/server.rb +1 -0
- data/lib/db.rb +15 -0
- data/lib/db/address_template.rb +15 -0
- data/lib/db/entity.rb +55 -0
- data/lib/db/machine_template.rb +15 -0
- data/lib/db/provider.rb +40 -0
- data/lib/db/volume_configuration.rb +15 -0
- data/lib/db/volume_template.rb +15 -0
- data/lib/deltacloud/collections/base.rb +1 -0
- data/lib/deltacloud/collections/instances.rb +2 -1
- data/lib/deltacloud/collections/storage_snapshots.rb +3 -1
- data/lib/deltacloud/core_ext/array.rb +5 -0
- data/lib/deltacloud/drivers/{aruba/aruba_driver.rb → arubacloud/arubacloud_driver.rb} +3 -6
- data/lib/deltacloud/drivers/digitalocean/digitalocean_driver.rb +48 -75
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +18 -3
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +25 -0
- data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +1 -1
- data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +34 -14
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +2 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +3 -3
- data/lib/deltacloud/drivers/openstack/openstack_driver.rb +93 -33
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +2 -0
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +2 -2
- data/lib/deltacloud/helpers/deltacloud_helper.rb +3 -1
- data/lib/deltacloud/helpers/rabbit_helper.rb +1 -2
- data/lib/deltacloud/models/address.rb +1 -0
- data/lib/deltacloud/models/blob.rb +1 -0
- data/lib/deltacloud/models/bucket.rb +1 -0
- data/lib/deltacloud/models/firewall.rb +1 -0
- data/lib/deltacloud/models/hardware_profile.rb +3 -1
- data/lib/deltacloud/models/image.rb +7 -0
- data/lib/deltacloud/models/instance.rb +12 -3
- data/lib/deltacloud/models/key.rb +1 -0
- data/lib/deltacloud/models/load_balancer.rb +1 -0
- data/lib/deltacloud/models/metric.rb +1 -0
- data/lib/deltacloud/models/realm.rb +10 -1
- data/lib/deltacloud/models/storage_snapshot.rb +1 -0
- data/lib/deltacloud/models/storage_volume.rb +2 -1
- data/lib/deltacloud/runner.rb +2 -1
- data/lib/deltacloud/server.rb +1 -0
- data/lib/deltacloud/version.rb +1 -1
- data/lib/deltacloud_rack.rb +4 -0
- data/tests/cimi/collections/machines_test.rb +80 -0
- data/tests/cimi/db/database_helper_test.rb +54 -99
- data/tests/cimi/db/db_helper.rb +2 -0
- data/tests/cimi/db/entity_test.rb +29 -0
- data/tests/cimi/model/collection_spec.rb +2 -2
- data/tests/cimi/model/credential_spec.rb +2 -2
- data/tests/cimi/model/machine_configuration_spec.rb +2 -2
- data/tests/cimi/model/machine_image_spec.rb +2 -2
- data/tests/cimi/model/machine_spec.rb +4 -4
- data/tests/cimi/model/machine_template_spec.rb +2 -2
- data/tests/cimi/model/volume_configuration_spec.rb +2 -2
- data/tests/cimi/model/volume_image_spec.rb +2 -2
- data/tests/cimi/model/volume_spec.rb +2 -2
- data/tests/cimi/model/volume_template_spec.rb +2 -2
- data/tests/cimi/spec_helper.rb +4 -0
- data/tests/deltacloud/collections/instances_collection_test.rb +3 -1
- data/tests/deltacloud/launcher_test.rb +3 -5
- data/tests/drivers/ec2/images_test.rb +7 -0
- data/tests/drivers/gogrid/images_test.rb +7 -0
- data/tests/drivers/openstack/instances_test.rb +8 -8
- data/tests/drivers/openstack/realms_test.rb +13 -13
- data/views/errors/403.xml.haml +2 -1
- data/views/images/show.html.haml +4 -1
- data/views/images/show.xml.haml +1 -0
- data/views/instances/new.html.haml +1 -1
- data/views/instances/show.html.haml +3 -0
- data/views/realms/index.html.haml +2 -0
- data/views/realms/show.html.haml +4 -0
- data/views/realms/show.xml.haml +3 -0
- metadata +19 -14
|
@@ -254,6 +254,7 @@ class RhevmDriver < Deltacloud::BaseDriver
|
|
|
254
254
|
public_addresses << InstanceAddress.new(inst.vnc[:address], :port => inst.vnc[:port], :type => :vnc)
|
|
255
255
|
end
|
|
256
256
|
|
|
257
|
+
can_create_image = state == 'STOPPED'
|
|
257
258
|
# Remove 'destroy' operation from list of actions when RHEV-M instance
|
|
258
259
|
# is suspended or paused.
|
|
259
260
|
if state == 'PAUSED'
|
|
@@ -261,7 +262,6 @@ class RhevmDriver < Deltacloud::BaseDriver
|
|
|
261
262
|
actions.delete(:destroy)
|
|
262
263
|
else
|
|
263
264
|
actions = instance_actions_for(state)
|
|
264
|
-
can_create_image = true
|
|
265
265
|
end
|
|
266
266
|
|
|
267
267
|
Instance.new(
|
|
@@ -277,7 +277,7 @@ class RhevmDriver < Deltacloud::BaseDriver
|
|
|
277
277
|
:hardware_profile_id => profile.id,
|
|
278
278
|
:public_addresses => public_addresses,
|
|
279
279
|
:private_addresses => [],
|
|
280
|
-
:create_image => can_create_image
|
|
280
|
+
:create_image => can_create_image
|
|
281
281
|
)
|
|
282
282
|
end
|
|
283
283
|
|
|
@@ -140,7 +140,9 @@ module Deltacloud::Helpers
|
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
def instance_action(name)
|
|
143
|
-
original_instance = driver.instance(credentials, :id => params[:id])
|
|
143
|
+
unless original_instance = driver.instance(credentials, :id => params[:id])
|
|
144
|
+
return report_error(403)
|
|
145
|
+
end
|
|
144
146
|
|
|
145
147
|
# If original instance doesn't include called action
|
|
146
148
|
# return with 405 error (Method is not Allowed)
|
|
@@ -64,7 +64,6 @@ module Sinatra::Rabbit
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
helper_method_name += '_url'
|
|
67
|
-
|
|
68
67
|
[Proc.new do
|
|
69
68
|
define_method helper_method_name do |*args|
|
|
70
69
|
if (opts = args.first).kind_of? Hash
|
|
@@ -76,7 +75,7 @@ module Sinatra::Rabbit
|
|
|
76
75
|
else
|
|
77
76
|
path = operation.full_path
|
|
78
77
|
end
|
|
79
|
-
path.slice!(root_url)
|
|
78
|
+
path.slice!(root_url) if path.start_with?(root_url)
|
|
80
79
|
url(path)
|
|
81
80
|
end unless respond_to?(helper_method_name)
|
|
82
81
|
end, helper_method_name]
|
|
@@ -27,6 +27,7 @@ class Blob < BaseModel
|
|
|
27
27
|
def to_hash(context)
|
|
28
28
|
{
|
|
29
29
|
:id => self.id,
|
|
30
|
+
:href => context.bucket_url(bucket) + '/' + self.id,
|
|
30
31
|
:bucket => { :rel => :bucket, :href => context.bucket_url(bucket), :id => bucket },
|
|
31
32
|
:content_length => content_length,
|
|
32
33
|
:content_type => content_type,
|
|
@@ -27,6 +27,7 @@ class Bucket < BaseModel
|
|
|
27
27
|
def to_hash(context)
|
|
28
28
|
{
|
|
29
29
|
:id => self.id,
|
|
30
|
+
:href => context.bucket_url(self.id),
|
|
30
31
|
:name => name,
|
|
31
32
|
:size => size,
|
|
32
33
|
:blob_list => blob_list.map { |b| { :rel => :blob, :href => context.url("/buckets/#{self.id}/#{b}"), :id => b }}
|
|
@@ -31,7 +31,7 @@ module Deltacloud
|
|
|
31
31
|
class << self
|
|
32
32
|
def property(prop)
|
|
33
33
|
define_method(prop) do |*args|
|
|
34
|
-
values, opts,
|
|
34
|
+
values, opts, _ = *args
|
|
35
35
|
unless values.nil?
|
|
36
36
|
@properties[prop] = Property.new(prop, values, opts || {})
|
|
37
37
|
end
|
|
@@ -46,6 +46,7 @@ module Deltacloud
|
|
|
46
46
|
property :architecture
|
|
47
47
|
property :memory
|
|
48
48
|
property :storage
|
|
49
|
+
property :root_type
|
|
49
50
|
|
|
50
51
|
def initialize(profile_id, &block)
|
|
51
52
|
@properties = {}
|
|
@@ -88,6 +89,7 @@ module Deltacloud
|
|
|
88
89
|
def to_hash(context)
|
|
89
90
|
r = {
|
|
90
91
|
:id => self.id,
|
|
92
|
+
:href => context.hardware_profile_url(self.id),
|
|
91
93
|
:name => name,
|
|
92
94
|
}
|
|
93
95
|
r.merge!({:properties => @properties}) if !@properties.empty?
|
|
@@ -24,15 +24,22 @@ class Image < BaseModel
|
|
|
24
24
|
attr_accessor :state
|
|
25
25
|
attr_accessor :hardware_profiles
|
|
26
26
|
attr_accessor :creation_time
|
|
27
|
+
attr_accessor :root_type
|
|
28
|
+
|
|
29
|
+
def root_type
|
|
30
|
+
@root_type || 'transient'
|
|
31
|
+
end
|
|
27
32
|
|
|
28
33
|
def to_hash(context)
|
|
29
34
|
{
|
|
30
35
|
:id => self.id,
|
|
36
|
+
:href => context.image_url(self.id),
|
|
31
37
|
:name => name,
|
|
32
38
|
:description => description,
|
|
33
39
|
:owner => owner_id,
|
|
34
40
|
:architecture => architecture,
|
|
35
41
|
:state => state,
|
|
42
|
+
:root_type => root_type,
|
|
36
43
|
:creation_time => creation_time,
|
|
37
44
|
:hardware_profiles => hardware_profiles.map { |p|
|
|
38
45
|
{ :id => p.id, :href => context.hardware_profile_url(p.id), :rel => :hardware_profile }
|
|
@@ -41,6 +41,7 @@ class Instance < BaseModel
|
|
|
41
41
|
def to_hash(context)
|
|
42
42
|
r = {
|
|
43
43
|
:id => self.id,
|
|
44
|
+
:href => context.instance_url(self.id),
|
|
44
45
|
:name => name,
|
|
45
46
|
:state => state,
|
|
46
47
|
:owner => owner_id,
|
|
@@ -53,7 +54,7 @@ class Instance < BaseModel
|
|
|
53
54
|
:method => context.instance_action_method(a)
|
|
54
55
|
}
|
|
55
56
|
},
|
|
56
|
-
:
|
|
57
|
+
:hardware_profile => {
|
|
57
58
|
:id => instance_profile.id,
|
|
58
59
|
:href => context.hardware_profile_url(instance_profile.id),
|
|
59
60
|
:rel => :hardware_profile,
|
|
@@ -62,17 +63,25 @@ class Instance < BaseModel
|
|
|
62
63
|
:public_addresses => public_addresses.map { |addr| addr.to_hash(context) },
|
|
63
64
|
:private_addresses => private_addresses.map { |addr| addr.to_hash(context) }
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
if context.driver.respond_to? :run_on_instance
|
|
67
|
+
r[:actions] << { :href => "#{context.run_instance_url(self.id)};id=#{self.id}", :rel => 'run', :method => 'post'}
|
|
68
|
+
end
|
|
69
|
+
if can_create_image?
|
|
70
|
+
r[:actions] << { :href => "#{context.create_image_url};instance_id=#{self.id}", :rel => 'create_image', :method => 'post'}
|
|
71
|
+
end
|
|
72
|
+
r.merge!(:create_time => launch_time) if launch_time
|
|
66
73
|
r.merge!(:create_image => create_image) if create_image
|
|
67
74
|
r.merge!(:firewalls => firewalls.map { |f| { :id => f, :href => context.firewall_url(f), :rel => :firewall }}) if firewalls
|
|
68
75
|
if storage_volumes
|
|
69
76
|
r.merge!(:storage_volumes => storage_volumes.map { |v| { :id => v.keys.first, :href => context.storage_volume_url(v.keys.first), :rel => :storage_volume }})
|
|
70
77
|
end
|
|
71
78
|
if context.driver.class.has_feature?(:instances, :authentication_key)
|
|
79
|
+
r.merge!(:authentication_type => 'key' )
|
|
72
80
|
r.merge!(:authentication => { :keyname => keyname }) if keyname
|
|
73
81
|
end
|
|
74
82
|
if context.driver.class.has_feature?(:instances, :authentication_password)
|
|
75
|
-
r.merge!(
|
|
83
|
+
r[:authentication] && username ? r[:authentication].merge!({ :user => username, :password => password }) :
|
|
84
|
+
(username ? r.merge!(:authentication => { :user => username, :password => password }) : nil)
|
|
76
85
|
end
|
|
77
86
|
r
|
|
78
87
|
end
|
|
@@ -30,6 +30,7 @@ class LoadBalancer < BaseModel
|
|
|
30
30
|
def to_hash(context)
|
|
31
31
|
{
|
|
32
32
|
:id => self.id,
|
|
33
|
+
:href => context.load_balancer_url(self.id),
|
|
33
34
|
:realms => realms,
|
|
34
35
|
:listeners => listeners.map { |l| l.to_hash(context) },
|
|
35
36
|
:instances => instances.map { |i| i.to_hash(context) },
|
|
@@ -20,14 +20,23 @@ class Realm < BaseModel
|
|
|
20
20
|
attr_accessor :name
|
|
21
21
|
attr_accessor :limit
|
|
22
22
|
attr_accessor :state
|
|
23
|
+
attr_accessor :resource_types
|
|
24
|
+
|
|
25
|
+
def initialize(init=nil)
|
|
26
|
+
super(init)
|
|
27
|
+
self.resource_types ||= []
|
|
28
|
+
end
|
|
23
29
|
|
|
24
30
|
def to_hash(context)
|
|
25
|
-
{
|
|
31
|
+
r = {
|
|
26
32
|
:id => self.id,
|
|
33
|
+
:href => context.realm_url(self.id),
|
|
27
34
|
:name => name,
|
|
28
35
|
:state => state,
|
|
29
36
|
:limit => limit
|
|
30
37
|
}
|
|
38
|
+
r.merge!({:resource_types => resource_types}) if resource_types
|
|
39
|
+
r
|
|
31
40
|
end
|
|
32
41
|
|
|
33
42
|
end
|
|
@@ -31,6 +31,7 @@ class StorageSnapshot < BaseModel
|
|
|
31
31
|
def to_hash(context)
|
|
32
32
|
{
|
|
33
33
|
:id => self.id,
|
|
34
|
+
:href => context.storage_snapshot_url(self.id),
|
|
34
35
|
:state => state,
|
|
35
36
|
:storage_volume => { :id => storage_volume_id, :href => context.storage_volume_url(storage_volume_id), :rel => :storage_volume },
|
|
36
37
|
:created => created
|
|
@@ -31,6 +31,7 @@ class StorageVolume < BaseModel
|
|
|
31
31
|
def to_hash(context)
|
|
32
32
|
r = {
|
|
33
33
|
:id => self.id,
|
|
34
|
+
:href => context.storage_volume_url(self.id),
|
|
34
35
|
:name => name,
|
|
35
36
|
:description => description,
|
|
36
37
|
:state => state,
|
|
@@ -41,7 +42,7 @@ class StorageVolume < BaseModel
|
|
|
41
42
|
:capacity => capacity,
|
|
42
43
|
}
|
|
43
44
|
r[:actions] = (actions || []).map { |a|
|
|
44
|
-
{ :href => context.send("#{a}
|
|
45
|
+
{ :href => context.send("#{a}_storage_volume_url", self.id), :rel => a }
|
|
45
46
|
}
|
|
46
47
|
if instance_id
|
|
47
48
|
r[:instance] = { :id => instance_id, :href => context.instance_url(instance_id), :rel => :instance }
|
data/lib/deltacloud/runner.rb
CHANGED
|
@@ -69,6 +69,7 @@ module Deltacloud
|
|
|
69
69
|
def execute(command)
|
|
70
70
|
@command = command
|
|
71
71
|
config = ssh_config(@network, @credentials, @key)
|
|
72
|
+
username = (@credentials[:username]) ? @credentials[:username] : 'root'
|
|
72
73
|
begin
|
|
73
74
|
session = nil
|
|
74
75
|
# Default timeout for connecting to an instance.
|
|
@@ -77,7 +78,7 @@ module Deltacloud
|
|
|
77
78
|
# Please keep in mind that the HTTP request timeout is set to 60
|
|
78
79
|
# seconds, so you need to fit into this time
|
|
79
80
|
Timeout::timeout(20) do
|
|
80
|
-
session = Net::SSH.start(@network.ip,
|
|
81
|
+
session = Net::SSH.start(@network.ip, username, config)
|
|
81
82
|
end
|
|
82
83
|
session.open_channel do |channel|
|
|
83
84
|
channel.on_data do |ch, data|
|
data/lib/deltacloud/server.rb
CHANGED
data/lib/deltacloud/version.rb
CHANGED
data/lib/deltacloud_rack.rb
CHANGED
|
@@ -68,6 +68,10 @@ module Deltacloud
|
|
|
68
68
|
|
|
69
69
|
set :views, File.join(File.dirname(__FILE__), '..', 'views')
|
|
70
70
|
|
|
71
|
+
get '/robots.txt' do
|
|
72
|
+
send_file File.join('public', 'robots.txt')
|
|
73
|
+
end
|
|
74
|
+
|
|
71
75
|
get '/' do
|
|
72
76
|
respond_to do |format|
|
|
73
77
|
format.xml { haml :'index', :layout => false }
|
|
@@ -72,6 +72,86 @@ describe CIMI::Collections::Machines do
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
describe '$filter' do
|
|
76
|
+
|
|
77
|
+
it 'should filter collection by name attribute' do
|
|
78
|
+
get root_url("/machines?$filter=name='MockUserInstance'")
|
|
79
|
+
status.must_equal 200
|
|
80
|
+
(xml/'Collection/Machine').wont_be_empty
|
|
81
|
+
(xml/'Collection/Machine').size.must_equal 1
|
|
82
|
+
xml.at('Collection/count').text.must_equal '1'
|
|
83
|
+
xml.at('Collection/Machine/name').text.must_equal 'MockUserInstance'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'should filter collection by reverse name attribute' do
|
|
87
|
+
get root_url("/machines?$filter=name!='MockUserInstance'")
|
|
88
|
+
status.must_equal 200
|
|
89
|
+
(xml/'Collection/Machine').wont_be_empty
|
|
90
|
+
(xml/'Collection/Machine').size.must_equal 1
|
|
91
|
+
xml.at('Collection/count').text.must_equal '1'
|
|
92
|
+
xml.at('Collection/Machine/name').text.must_equal 'Mock Instance With Profile Change'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '$select' do
|
|
98
|
+
|
|
99
|
+
it 'should return only selected attribute' do
|
|
100
|
+
get root_url('/machines?$select=name')
|
|
101
|
+
status.must_equal 200
|
|
102
|
+
(xml/'Collection/Machine/name').wont_be_empty
|
|
103
|
+
(xml/'Collection/Machine/name').first.text.wont_be_empty
|
|
104
|
+
xml.xpath("/c:Collection/c:Machine/*[not(self::c:name)]", NS).must_be_empty
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should support multiple selected attributes' do
|
|
108
|
+
get root_url('/machines?$select=name,description')
|
|
109
|
+
status.must_equal 200
|
|
110
|
+
(xml/'Collection/Machine/name').wont_be_empty
|
|
111
|
+
(xml/'Collection/Machine/name').first.text.wont_be_empty
|
|
112
|
+
(xml/'Collection/Machine/description').wont_be_empty
|
|
113
|
+
(xml/'Collection/Machine/description').first.text.wont_be_empty
|
|
114
|
+
xml.xpath("/c:Collection/c:Machine/*[not(self::c:name) and not(self::c:description)]", NS).must_be_empty
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'should support select on non-expanded subcollection' do
|
|
118
|
+
get root_url('/machines?$select=disks')
|
|
119
|
+
xml.xpath("/c:Collection/c:Machine/*[not(self::c:disks)]", NS).must_be_empty
|
|
120
|
+
(xml/'Collection/Machine/disks').wont_be_empty
|
|
121
|
+
(xml/'Collection/Machine/disks').each do |d|
|
|
122
|
+
d[:href].wont_be_empty
|
|
123
|
+
d[:href].must_match(/^http/)
|
|
124
|
+
d.children.must_be_empty
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def disks
|
|
129
|
+
(xml/'Collection/Machine/disks').wont_be_empty
|
|
130
|
+
(xml/'Collection/Machine/disks').each do |d|
|
|
131
|
+
d[:href].wont_be_empty
|
|
132
|
+
d[:href].must_match(/^http/)
|
|
133
|
+
d.at('id').wont_be_nil
|
|
134
|
+
d.at('count').wont_be_nil
|
|
135
|
+
d.at('Disk/id').wont_be_nil
|
|
136
|
+
d.at('Disk/description').wont_be_nil
|
|
137
|
+
d.at('Disk/capacity').wont_be_nil
|
|
138
|
+
d.at('Disk/created').wont_be_nil
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'should support select on expanded subcollection' do
|
|
143
|
+
get root_url('/machines?$select=disks&$expand=disks')
|
|
144
|
+
xml.xpath("/c:Collection/c:Machine/*[not(self::c:disks)]", NS).must_be_empty
|
|
145
|
+
disks
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'should support select on expanded subcollection and regular attribute' do
|
|
149
|
+
get root_url('/machines?$select=name,disks&$expand=disks')
|
|
150
|
+
xml.xpath("/c:Collection/c:Machine/*[not(self::c:disks) and not(self::c:name)]", NS).must_be_empty
|
|
151
|
+
disks
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
75
155
|
it 'should not return non-existing machine' do
|
|
76
156
|
get root_url '/machines/unknown-machine'
|
|
77
157
|
status.must_equal 404
|
|
@@ -13,9 +13,14 @@ end
|
|
|
13
13
|
describe Deltacloud::Helpers::Database do
|
|
14
14
|
include Deltacloud::DatabaseTestHelper
|
|
15
15
|
|
|
16
|
+
Provider = Deltacloud::Database::Provider
|
|
17
|
+
Entity = Deltacloud::Database::Entity
|
|
18
|
+
BaseModel = CIMI::Model::Base
|
|
19
|
+
|
|
16
20
|
before do
|
|
17
21
|
ENV['RACK_ENV'] = 'development'
|
|
18
22
|
@db = DatabaseHelper.new
|
|
23
|
+
@prov = Provider::lookup
|
|
19
24
|
end
|
|
20
25
|
|
|
21
26
|
it 'report if application is running under test environment' do
|
|
@@ -35,97 +40,84 @@ describe Deltacloud::Helpers::Database do
|
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
it 'create provider when it does not exists' do
|
|
38
|
-
@
|
|
39
|
-
@
|
|
40
|
-
@
|
|
41
|
-
@
|
|
42
|
-
@
|
|
43
|
-
@
|
|
44
|
-
@
|
|
45
|
-
@
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
it 'extract attributes both from JSON and XMLSimple' do
|
|
49
|
-
xml_simple_test = { 'property' => [ { 'key' => 'template', 'content' => "value"} ] }
|
|
50
|
-
json_test = { 'properties' => { 'template' => 'value' } }
|
|
51
|
-
|
|
52
|
-
@db.extract_attribute_value('property', xml_simple_test).must_equal('template' => 'value')
|
|
53
|
-
@db.extract_attribute_value('properties', json_test).must_equal('template' => 'value')
|
|
43
|
+
@prov.must_be_kind_of Deltacloud::Database::Provider
|
|
44
|
+
@prov.driver.must_equal 'mock'
|
|
45
|
+
@prov.url.must_equal @db.current_provider
|
|
46
|
+
@prov.must_respond_to :entities
|
|
47
|
+
@prov.must_respond_to :machine_templates
|
|
48
|
+
@prov.must_respond_to :address_templates
|
|
49
|
+
@prov.must_respond_to :volume_configurations
|
|
50
|
+
@prov.must_respond_to :volume_templates
|
|
54
51
|
end
|
|
55
52
|
|
|
56
53
|
it 'must return entity for given model' do
|
|
57
|
-
|
|
58
|
-
entity = Deltacloud::Database::Entity
|
|
59
|
-
@db.current_db.wont_be_nil
|
|
54
|
+
@prov.wont_be_nil
|
|
60
55
|
|
|
61
|
-
new_entity = @
|
|
56
|
+
new_entity = @prov.add_entity(
|
|
62
57
|
:name => 'testMachine1',
|
|
63
58
|
:description => 'testMachine1 description',
|
|
64
59
|
:ent_properties => JSON::dump(:key => 'value'),
|
|
65
|
-
:be_kind =>
|
|
60
|
+
:be_kind => BaseModel.name,
|
|
66
61
|
:be_id => 'inst1'
|
|
67
62
|
)
|
|
68
63
|
|
|
69
|
-
check_entity_base_attrs new_entity,
|
|
64
|
+
check_entity_base_attrs new_entity, Entity, @prov
|
|
70
65
|
|
|
71
|
-
result =
|
|
66
|
+
result = Entity.retrieve(BaseModel.new(:id => 'inst1'))
|
|
72
67
|
result.must_equal new_entity
|
|
73
68
|
|
|
74
|
-
new_entity.destroy
|
|
69
|
+
new_entity.destroy
|
|
70
|
+
result = Entity.retrieve(BaseModel.new(:id => 'inst1'))
|
|
71
|
+
result.exists?.must_equal false
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
it 'must load attributes for entity for given model' do
|
|
78
|
-
|
|
79
|
-
entity = Deltacloud::Database::Entity
|
|
80
|
-
@db.current_db.wont_be_nil
|
|
75
|
+
@prov.wont_be_nil
|
|
81
76
|
|
|
82
|
-
new_entity = @
|
|
77
|
+
new_entity = @prov.add_entity(
|
|
83
78
|
:name => 'testMachine1',
|
|
84
79
|
:description => 'testMachine1 description',
|
|
85
80
|
:ent_properties => JSON::dump(:key => 'value'),
|
|
86
|
-
:be_kind =>
|
|
87
|
-
:be_id => '
|
|
81
|
+
:be_kind => BaseModel.name,
|
|
82
|
+
:be_id => 'base1'
|
|
88
83
|
)
|
|
89
84
|
|
|
90
|
-
check_entity_base_attrs new_entity,
|
|
85
|
+
check_entity_base_attrs new_entity, Entity, @prov
|
|
91
86
|
|
|
92
|
-
result =
|
|
93
|
-
result.
|
|
94
|
-
result
|
|
95
|
-
result
|
|
96
|
-
result[:property].must_equal JSON::parse(new_entity.ent_properties)
|
|
87
|
+
result = Entity::retrieve(BaseModel.new(:id => 'base1'))
|
|
88
|
+
result.name.must_equal new_entity.name
|
|
89
|
+
result.description.must_equal new_entity.description
|
|
90
|
+
result.properties.must_equal new_entity.properties
|
|
97
91
|
|
|
98
92
|
new_entity.destroy.wont_equal false
|
|
99
93
|
end
|
|
100
94
|
|
|
101
95
|
it 'must delete attributes for entity for given model' do
|
|
102
|
-
|
|
103
|
-
entity = Deltacloud::Database::Entity
|
|
104
|
-
@db.current_db.wont_be_nil
|
|
96
|
+
@prov.wont_be_nil
|
|
105
97
|
|
|
106
|
-
new_entity = @
|
|
98
|
+
new_entity = @prov.add_entity(
|
|
107
99
|
:name => 'testMachine1',
|
|
108
100
|
:description => 'testMachine1 description',
|
|
109
101
|
:ent_properties => JSON::dump(:key => 'value'),
|
|
110
|
-
:be_kind =>
|
|
111
|
-
:be_id => '
|
|
102
|
+
:be_kind => BaseModel.name,
|
|
103
|
+
:be_id => 'base1'
|
|
112
104
|
)
|
|
113
105
|
|
|
114
|
-
check_entity_base_attrs new_entity,
|
|
106
|
+
check_entity_base_attrs new_entity, Entity, @prov
|
|
115
107
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
108
|
+
base = BaseModel.new(:id => 'base1')
|
|
109
|
+
base.destroy
|
|
110
|
+
entity = Entity.retrieve(base)
|
|
111
|
+
entity.wont_be_nil
|
|
112
|
+
entity.exists?.must_equal false
|
|
119
113
|
end
|
|
120
114
|
|
|
121
|
-
it 'must store
|
|
122
|
-
|
|
123
|
-
entity = Deltacloud::Database::Entity
|
|
124
|
-
@db.current_db.wont_be_nil
|
|
115
|
+
it 'must store attributes for a given CIMI::Model' do
|
|
116
|
+
@prov.wont_be_nil
|
|
125
117
|
|
|
126
|
-
|
|
127
|
-
mock_json = '
|
|
118
|
+
json = '
|
|
128
119
|
{
|
|
120
|
+
"id": "http://localhost:3001/cimi/machines/42",
|
|
129
121
|
"resourceURI": "http://schemas.dmtf.org/cimi/1/MachineCreate",
|
|
130
122
|
"name": "myDatabaseMachine",
|
|
131
123
|
"description": "This is a demo machine",
|
|
@@ -139,52 +131,15 @@ describe Deltacloud::Helpers::Database do
|
|
|
139
131
|
}
|
|
140
132
|
}
|
|
141
133
|
'
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
load_result[:property]['foo'].must_equal 'bar'
|
|
153
|
-
load_result[:property]['life'].must_equal 'is life'
|
|
154
|
-
result.destroy.wont_equal false
|
|
134
|
+
machine = CIMI::Model::Machine.from_json(json)
|
|
135
|
+
machine.save
|
|
136
|
+
|
|
137
|
+
m2 = CIMI::Model::Machine.new(:id => machine.id)
|
|
138
|
+
m2.name.must_equal 'myDatabaseMachine'
|
|
139
|
+
m2.description.must_equal 'This is a demo machine'
|
|
140
|
+
m2.property.must_be_kind_of Hash
|
|
141
|
+
m2.property.size.must_equal 2
|
|
142
|
+
m2.property['foo'].must_equal 'bar'
|
|
143
|
+
m2.property['life'].must_equal 'is life'
|
|
155
144
|
end
|
|
156
|
-
|
|
157
|
-
it 'must store XML attributes for entity for given model' do
|
|
158
|
-
provider = Deltacloud::Database::Provider
|
|
159
|
-
entity = Deltacloud::Database::Entity
|
|
160
|
-
@db.current_db.wont_be_nil
|
|
161
|
-
|
|
162
|
-
mock_instance = Instance.new(:id => 'inst1')
|
|
163
|
-
mock_xml = '
|
|
164
|
-
<MachineCreate>
|
|
165
|
-
<name>myMachineXML123</name>
|
|
166
|
-
<description>Description of my new Machine</description>
|
|
167
|
-
<machineTemplate>
|
|
168
|
-
<machineConfig href="http://localhost:3001/cimi/machine_configurations/m1-small"/>
|
|
169
|
-
<machineImage href="http://localhost:3001/cimi/machine_images/img1"/>
|
|
170
|
-
</machineTemplate>
|
|
171
|
-
<property key="test">value</property>
|
|
172
|
-
<property key="foo">bar</property>
|
|
173
|
-
</MachineCreate>
|
|
174
|
-
'
|
|
175
|
-
result = @db.store_attributes_for(mock_instance, XmlSimple.xml_in(mock_xml))
|
|
176
|
-
result.must_be_kind_of entity
|
|
177
|
-
check_entity_base_attrs result, entity, @db.current_db
|
|
178
|
-
load_result = @db.load_attributes_for(mock_instance)
|
|
179
|
-
load_result.must_be_kind_of Hash
|
|
180
|
-
load_result.wont_be_empty
|
|
181
|
-
load_result[:name].must_equal 'myMachineXML123'
|
|
182
|
-
load_result[:description].must_equal 'Description of my new Machine'
|
|
183
|
-
load_result[:property].must_be_kind_of Hash
|
|
184
|
-
load_result[:property].wont_be_empty
|
|
185
|
-
load_result[:property]['test'].must_equal 'value'
|
|
186
|
-
result.destroy.wont_equal false
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
|
|
190
145
|
end
|