deltacloud-client 0.0.3 → 0.0.4
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 +6 -1
- data/bin/deltacloudc +10 -7
- data/lib/dcloud/hardware_profile.rb +124 -0
- data/lib/dcloud/instance.rb +37 -3
- data/lib/deltacloud.rb +48 -20
- data/specs/data/images/img1.yml +1 -0
- data/specs/data/images/img2.yml +1 -0
- data/specs/data/images/img3.yml +1 -0
- data/specs/data/instances/inst0.yml +16 -0
- data/specs/data/instances/inst1.yml +2 -1
- data/specs/data/instances/inst2.yml +2 -1
- data/specs/fixtures/images/img1.yml +1 -0
- data/specs/fixtures/images/img2.yml +1 -0
- data/specs/fixtures/images/img3.yml +1 -0
- data/specs/fixtures/instances/inst0.yml +16 -0
- data/specs/fixtures/instances/inst1.yml +2 -1
- data/specs/fixtures/instances/inst2.yml +2 -1
- data/specs/hardware_profiles_spec.rb +71 -0
- data/specs/initialization_spec.rb +1 -1
- data/specs/instances_spec.rb +35 -16
- data/specs/spec_helper.rb +2 -2
- data/specs/storage_volume_spec.rb +4 -2
- metadata +39 -27
- data/lib/dcloud/flavor.rb +0 -49
- data/specs/flavors_spec.rb +0 -67
data/Rakefile
CHANGED
@@ -15,9 +15,14 @@
|
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
16
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
|
-
|
18
|
+
require 'rake/gempackagetask'
|
19
19
|
require 'spec/rake/spectask'
|
20
20
|
|
21
|
+
load 'deltacloud-client.gemspec'
|
22
|
+
|
23
|
+
Rake::GemPackageTask.new(@spec) do |pkg|
|
24
|
+
pkg.need_tar = true
|
25
|
+
end
|
21
26
|
|
22
27
|
desc "Run all examples"
|
23
28
|
Spec::Rake::SpecTask.new('spec') do |t|
|
data/bin/deltacloudc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/bin/env ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
#
|
3
3
|
# Copyright (C) 2009 Red Hat, Inc.
|
4
4
|
#
|
@@ -39,7 +39,7 @@ BANNER
|
|
39
39
|
opts.on( '-i', '--id ID', 'ID for operation') { |id| options[:id] = id }
|
40
40
|
opts.on( '-d', '--image-id ID', 'Image ID') { |id| options[:image_id] = id }
|
41
41
|
opts.on( '-a', '--arch ARCH', 'Architecture (x86, x86_64)') { |id| options[:architecture] = id }
|
42
|
-
opts.on( '-
|
42
|
+
opts.on( '-p', '--hardware-profile HARDWARE_PROFILE', 'Hardware Profile') { |id| options[:hwp_id] = id }
|
43
43
|
opts.on( '-n', '--name NAME', 'Name (for instance eg.)') { |name| options[:name] = name }
|
44
44
|
opts.on( '-s', '--state STATE', 'Instance state (RUNNING, STOPPED)') { |state| options[:state] = state }
|
45
45
|
opts.on( '-u', '--url URL', 'API url ($API_URL variable)') { |url| options[:api_url] = url }
|
@@ -66,11 +66,10 @@ options[:collection] = ARGV[0]
|
|
66
66
|
options[:operation] = ARGV[1]
|
67
67
|
|
68
68
|
# Connect to Deltacloud API and fetch all entry points
|
69
|
-
client = DeltaCloud.new(url.user, url.password, api_url, { :verbose => options[:verbose] })
|
69
|
+
client = DeltaCloud.new(url.user || ENV['API_USER'], url.password || ENV['API_PASSWORD'], api_url, { :verbose => options[:verbose] })
|
70
70
|
collections = client.entry_points.keys
|
71
71
|
|
72
72
|
# Exclude collection which don't have methods in client library yet
|
73
|
-
collections.delete(:hardware_profiles)
|
74
73
|
collections.delete(:instance_states)
|
75
74
|
|
76
75
|
# If list parameter passed print out available collection
|
@@ -98,7 +97,7 @@ if options[:version]
|
|
98
97
|
exit(0)
|
99
98
|
end
|
100
99
|
|
101
|
-
# List items from collection (typically /
|
100
|
+
# List items from collection (typically /instances)
|
102
101
|
# Do same if 'index' operation is set
|
103
102
|
if options[:collection] and ( options[:operation].nil? or options[:operation].eql?('index') )
|
104
103
|
invalid_usage("Unknown collection: #{options[:collection]}") unless collections.include?(options[:collection].to_sym)
|
@@ -127,12 +126,16 @@ if options[:collection] and options[:operation]
|
|
127
126
|
end
|
128
127
|
|
129
128
|
# If collection is set and requested operation is create new instance,
|
130
|
-
# --image-id, --
|
129
|
+
# --image-id, --hardware-profile and --name parameters are used
|
131
130
|
# Returns created instance in plain form
|
132
131
|
if options[:collection].eql?('instances') and options[:operation].eql?('create')
|
132
|
+
invalid_usage("Missing image-id") unless options[:image_id]
|
133
|
+
if options[:name] and ! client.feature?(:instances, :user_name)
|
134
|
+
invalid_usage("Driver does not support user-supplied name")
|
135
|
+
end
|
133
136
|
params.merge!(:name => options[:name]) if options[:name]
|
134
137
|
params.merge!(:image_id => options[:image_id]) if options[:image_id]
|
135
|
-
params.merge!(:
|
138
|
+
params.merge!(:hwp_id => options[:hwp_id]) if options[:hwp_id]
|
136
139
|
instance = client.create_instance(options[:image_id], params)
|
137
140
|
puts instance.to_plain
|
138
141
|
exit(0)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This library is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
6
|
+
# License as published by the Free Software Foundation; either
|
7
|
+
# version 2.1 of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
+
|
18
|
+
|
19
|
+
require 'dcloud/base_model'
|
20
|
+
|
21
|
+
module DCloud
|
22
|
+
class HardwareProfile < BaseModel
|
23
|
+
|
24
|
+
class Property
|
25
|
+
class Range
|
26
|
+
attr_reader :first, :last
|
27
|
+
def initialize(element)
|
28
|
+
if element
|
29
|
+
@first = element.attributes['first']
|
30
|
+
@last = element.attributes['last']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def present?
|
34
|
+
! @first.nil?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
class Enum
|
38
|
+
attr_reader :entries
|
39
|
+
def initialize(element)
|
40
|
+
@entries = []
|
41
|
+
if element
|
42
|
+
element.get_elements( 'entry' ).each do |entry|
|
43
|
+
@entries << entry.attributes['value']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def present?
|
48
|
+
! @entries.empty?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
attr_reader :name, :kind, :unit, :value, :range, :enum
|
52
|
+
|
53
|
+
def initialize(xml, name)
|
54
|
+
@name = name
|
55
|
+
p = REXML::XPath.first(xml, "property[@name = '#{name}']")
|
56
|
+
if p
|
57
|
+
@value = p.attributes['value']
|
58
|
+
@unit = p.attributes['unit']
|
59
|
+
@kind = p.attributes['kind']
|
60
|
+
@range = Range.new(p.get_elements('range')[0]) if @kind=='range'
|
61
|
+
@enum = Enum.new(p.get_elements('enum')[0]) if @kind=='enum'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def present?
|
66
|
+
! @value.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
# FIXME: how to range/enum/kind bits fit into this?
|
70
|
+
def to_s
|
71
|
+
v = @value || "---"
|
72
|
+
u = @unit || ""
|
73
|
+
u = "" if ["label", "count"].include?(u)
|
74
|
+
"#{v} #{u}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class FloatProperty < Property
|
79
|
+
def initialize(xml, name)
|
80
|
+
super(xml, name)
|
81
|
+
@value = @value.to_f if @value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class IntegerProperty < Property
|
86
|
+
def initialize(xml, name)
|
87
|
+
super(xml, name)
|
88
|
+
@value = @value.to_i if @value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
xml_tag_name :hardware_profile
|
93
|
+
|
94
|
+
attribute :memory
|
95
|
+
attribute :storage
|
96
|
+
attribute :cpu
|
97
|
+
attribute :architecture
|
98
|
+
|
99
|
+
def initialize(client, uri, xml=nil)
|
100
|
+
super( client, uri, xml )
|
101
|
+
end
|
102
|
+
|
103
|
+
def load_payload(xml=nil)
|
104
|
+
super(xml)
|
105
|
+
unless xml.nil?
|
106
|
+
@memory = FloatProperty.new(xml, 'memory')
|
107
|
+
@storage = FloatProperty.new(xml, 'storage')
|
108
|
+
@cpu = IntegerProperty.new(xml, 'cpu')
|
109
|
+
@architecture = Property.new(xml, 'architecture')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_plain
|
114
|
+
sprintf("%-15s | %-6s | %10s | %10s ", id[0, 15],
|
115
|
+
architecture.to_s[0,6], memory.to_s[0,10], storage.to_s[0,10])
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def property_value(xml, name)
|
120
|
+
p = REXML::XPath.first(xml, "property[@name = '#{name}']")
|
121
|
+
p ? p.attributes['value'] : ""
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/dcloud/instance.rb
CHANGED
@@ -19,6 +19,33 @@
|
|
19
19
|
require 'dcloud/base_model'
|
20
20
|
|
21
21
|
module DCloud
|
22
|
+
|
23
|
+
class InstanceProfile
|
24
|
+
attr_reader :hardware_profile, :id
|
25
|
+
|
26
|
+
def initialize(client, xml)
|
27
|
+
@hardware_profile = HardwareProfile.new(client, xml.attributes['href'])
|
28
|
+
@properties = {}
|
29
|
+
@id = xml.text("id")
|
30
|
+
xml.get_elements('property').each do |prop|
|
31
|
+
@properties[prop.attributes['name'].to_sym] = {
|
32
|
+
:value => prop.attributes['value'],
|
33
|
+
:unit => prop.attributes['unit'],
|
34
|
+
:kind => prop.attributes['kind'].to_sym
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](prop)
|
40
|
+
p = @properties[prop]
|
41
|
+
p ? p[:value] : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def property(prop)
|
45
|
+
@properties[prop]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
22
49
|
class Instance < BaseModel
|
23
50
|
|
24
51
|
xml_tag_name :instance
|
@@ -30,9 +57,9 @@ module DCloud
|
|
30
57
|
attribute :state
|
31
58
|
attribute :actions
|
32
59
|
attribute :image
|
33
|
-
attribute :flavor
|
34
60
|
attribute :realm
|
35
61
|
attribute :action_urls
|
62
|
+
attribute :instance_profile
|
36
63
|
|
37
64
|
def initialize(client, uri, xml=nil)
|
38
65
|
@action_urls = {}
|
@@ -71,6 +98,13 @@ module DCloud
|
|
71
98
|
unload
|
72
99
|
end
|
73
100
|
|
101
|
+
def destroy!()
|
102
|
+
url = action_urls['destroy']
|
103
|
+
throw Exception.new( "Unable to destroy" ) unless url
|
104
|
+
client.post_instance( url )
|
105
|
+
unload
|
106
|
+
end
|
107
|
+
|
74
108
|
def load_payload(xml=nil)
|
75
109
|
super(xml)
|
76
110
|
unless xml.nil?
|
@@ -86,13 +120,13 @@ module DCloud
|
|
86
120
|
end
|
87
121
|
image_uri = xml.get_elements( 'image' )[0].attributes['href']
|
88
122
|
@image = Image.new( @client, image_uri )
|
89
|
-
flavor_uri = xml.get_elements( 'flavor' )[0].attributes['href']
|
90
|
-
@flavor = Flavor.new( @client, flavor_uri )
|
91
123
|
# Only use realms if they are there
|
92
124
|
if (!xml.get_elements( 'realm' ).empty?)
|
93
125
|
realm_uri = xml.get_elements( 'realm' )[0].attributes['href']
|
94
126
|
@realm = Realm.new( @client, realm_uri )
|
95
127
|
end
|
128
|
+
instance_profile = xml.get_elements( 'hardware-profile' ).first
|
129
|
+
@instance_profile = InstanceProfile.new( @client, instance_profile )
|
96
130
|
@state = xml.text( 'state' )
|
97
131
|
@actions = []
|
98
132
|
xml.get_elements( 'actions/link' ).each do |link|
|
data/lib/deltacloud.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
require 'rest_client'
|
19
19
|
require 'rexml/document'
|
20
20
|
require 'logger'
|
21
|
-
require 'dcloud/
|
21
|
+
require 'dcloud/hardware_profile'
|
22
22
|
require 'dcloud/realm'
|
23
23
|
require 'dcloud/image'
|
24
24
|
require 'dcloud/instance'
|
@@ -35,6 +35,7 @@ class DeltaCloud
|
|
35
35
|
attr_reader :entry_points
|
36
36
|
attr_reader :driver_name
|
37
37
|
attr_reader :last_request_xml
|
38
|
+
attr_reader :features
|
38
39
|
|
39
40
|
def self.driver_name(url)
|
40
41
|
DeltaCloud.new( nil, nil, url) do |client|
|
@@ -49,6 +50,7 @@ class DeltaCloud
|
|
49
50
|
@api_uri = URI.parse( api_uri )
|
50
51
|
@entry_points = {}
|
51
52
|
@verbose = opts[:verbose]
|
53
|
+
@features = {}
|
52
54
|
discover_entry_points
|
53
55
|
connect( &block )
|
54
56
|
self
|
@@ -74,31 +76,35 @@ class DeltaCloud
|
|
74
76
|
@api_uri.path
|
75
77
|
end
|
76
78
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
79
|
+
def feature?(collection, name)
|
80
|
+
@features.has_key?(collection) && @features[collection].include?(name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def hardware_profiles(opts={})
|
84
|
+
hardware_profiles = []
|
85
|
+
request(entry_points[:hardware_profiles], :get, opts) do |response|
|
80
86
|
doc = REXML::Document.new( response )
|
81
|
-
doc.get_elements( '
|
82
|
-
uri =
|
83
|
-
|
87
|
+
doc.get_elements( 'hardware-profiles/hardware-profile' ).each do |hwp|
|
88
|
+
uri = hwp.attributes['href']
|
89
|
+
hardware_profiles << DCloud::HardwareProfile.new( self, uri, hwp )
|
84
90
|
end
|
85
91
|
end
|
86
|
-
|
92
|
+
hardware_profiles
|
87
93
|
end
|
88
94
|
|
89
|
-
def
|
90
|
-
request( entry_points[:
|
95
|
+
def hardware_profile(id)
|
96
|
+
request( entry_points[:hardware_profiles], :get, {:id=>id } ) do |response|
|
91
97
|
doc = REXML::Document.new( response )
|
92
|
-
doc.get_elements( '/
|
93
|
-
uri =
|
94
|
-
return DCloud::
|
98
|
+
doc.get_elements( '/hardware-profile' ).each do |hwp|
|
99
|
+
uri = hwp.attributes['href']
|
100
|
+
return DCloud::HardwareProfile.new( self, uri, hwp )
|
95
101
|
end
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
|
-
def
|
100
|
-
xml = fetch_resource( :
|
101
|
-
return DCloud::
|
105
|
+
def fetch_hardware_profile(uri)
|
106
|
+
xml = fetch_resource( :hardware_profile, uri )
|
107
|
+
return DCloud::HardwareProfile.new( self, uri, xml ) if xml
|
102
108
|
nil
|
103
109
|
end
|
104
110
|
|
@@ -256,16 +262,32 @@ class DeltaCloud
|
|
256
262
|
nil
|
257
263
|
end
|
258
264
|
|
265
|
+
# Create a new instance, using image +image_id+. Possible optiosn are
|
266
|
+
#
|
267
|
+
# name - a user-defined name for the instance
|
268
|
+
# realm - a specific realm for placement of the instance
|
269
|
+
# hardware_profile - either a string giving the name of the
|
270
|
+
# hardware profile or a hash. The hash must have an
|
271
|
+
# entry +id+, giving the id of the hardware profile,
|
272
|
+
# and may contain additional names of properties,
|
273
|
+
# e.g. 'storage', to override entries in the
|
274
|
+
# hardware profile
|
259
275
|
def create_instance(image_id, opts={})
|
260
276
|
name = opts[:name]
|
261
277
|
realm_id = opts[:realm]
|
262
|
-
flavor_id = opts[:flavor]
|
263
278
|
|
264
279
|
params = {}
|
265
280
|
( params[:realm_id] = realm_id ) if realm_id
|
266
|
-
( params[:flavor_id] = flavor_id ) if flavor_id
|
267
281
|
( params[:name] = name ) if name
|
268
282
|
|
283
|
+
if opts[:hardware_profile].is_a?(String)
|
284
|
+
params[:hwp_id] = opts[:hardware_profile]
|
285
|
+
elsif opts[:hardware_profile].is_a?(Hash)
|
286
|
+
opts[:hardware_profile].each do |k,v|
|
287
|
+
params[:"hwp_#{k}"] = v
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
269
291
|
params[:image_id] = image_id
|
270
292
|
request( entry_points[:instances], :post, {}, params ) do |response|
|
271
293
|
doc = REXML::Document.new( response )
|
@@ -344,15 +366,21 @@ class DeltaCloud
|
|
344
366
|
attr_reader :http
|
345
367
|
|
346
368
|
def discover_entry_points
|
369
|
+
return if @discovered
|
347
370
|
request(api_uri.to_s) do |response|
|
348
371
|
doc = REXML::Document.new( response )
|
349
372
|
@driver_name = doc.root.attributes['driver']
|
350
373
|
doc.get_elements( 'api/link' ).each do |link|
|
351
|
-
rel = link.attributes['rel']
|
374
|
+
rel = link.attributes['rel'].to_sym
|
352
375
|
uri = link.attributes['href']
|
353
|
-
@entry_points[rel
|
376
|
+
@entry_points[rel] = uri
|
377
|
+
@features[rel] ||= []
|
378
|
+
link.get_elements('feature').each do |feature|
|
379
|
+
@features[rel] << feature.attributes['name'].to_sym
|
380
|
+
end
|
354
381
|
end
|
355
382
|
end
|
383
|
+
@discovered = true
|
356
384
|
end
|
357
385
|
|
358
386
|
def request(path='', method=:get, query_args={}, form_data={}, &block)
|
data/specs/data/images/img1.yml
CHANGED
data/specs/data/images/img2.yml
CHANGED
data/specs/data/images/img3.yml
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
:realm_id: us
|
3
|
+
:public_addresses:
|
4
|
+
- img1.inst0.public.com
|
5
|
+
:state: RUNNING
|
6
|
+
:name: "Mock Instance With Profile Change"
|
7
|
+
:private_addresses:
|
8
|
+
- img1.inst0.private.com
|
9
|
+
:image_id: img1
|
10
|
+
:instance_profile: !ruby/object:InstanceProfile
|
11
|
+
id: m1-large
|
12
|
+
memory: "12288"
|
13
|
+
:owner_id: mockuser
|
14
|
+
:actions:
|
15
|
+
- :reboot
|
16
|
+
- :stop
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
:realm_id: us
|
3
|
+
:public_addresses:
|
4
|
+
- img1.inst0.public.com
|
5
|
+
:state: RUNNING
|
6
|
+
:name: "Mock Instance With Profile Change"
|
7
|
+
:private_addresses:
|
8
|
+
- img1.inst0.private.com
|
9
|
+
:image_id: img1
|
10
|
+
:instance_profile: !ruby/object:InstanceProfile
|
11
|
+
id: m1-large
|
12
|
+
memory: "12288"
|
13
|
+
:owner_id: mockuser
|
14
|
+
:actions:
|
15
|
+
- :reboot
|
16
|
+
- :stop
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This library is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
6
|
+
# License as published by the Free Software Foundation; either
|
7
|
+
# version 2.1 of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
+
|
18
|
+
|
19
|
+
require 'specs/spec_helper'
|
20
|
+
|
21
|
+
def prop_check(prop, value_class)
|
22
|
+
if prop.present?
|
23
|
+
prop.value.should_not be_nil
|
24
|
+
prop.value.should be_a(value_class)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "hardware_profiles" do
|
29
|
+
|
30
|
+
it_should_behave_like "all resources"
|
31
|
+
|
32
|
+
it "should allow retrieval of all hardware profiles" do
|
33
|
+
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
34
|
+
hardware_profiles = client.hardware_profiles
|
35
|
+
hardware_profiles.should_not be_empty
|
36
|
+
hardware_profiles.each do |hwp|
|
37
|
+
hwp.uri.should_not be_nil
|
38
|
+
hwp.uri.should be_a(String)
|
39
|
+
prop_check(hwp.architecture, String)
|
40
|
+
prop_check(hwp.storage, Float)
|
41
|
+
prop_check(hwp.memory, Float)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should allow filtering of hardware_profiles by architecture" do
|
47
|
+
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
48
|
+
hardware_profiles = client.hardware_profiles( :architecture=>'i386' )
|
49
|
+
hardware_profiles.should_not be_empty
|
50
|
+
hardware_profiles.size.should eql( 2 )
|
51
|
+
hardware_profiles.first.architecture.value.should eql( 'i386' )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should allow fetching a hardware_profile by id" do
|
56
|
+
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
57
|
+
hwp = client.hardware_profile( 'm1-small' )
|
58
|
+
hwp.should_not be_nil
|
59
|
+
hwp.id.should eql( 'm1-small' )
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should allow fetching a hardware_profile by URI" do
|
64
|
+
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
65
|
+
hwp = client.fetch_hardware_profile( API_URL + '/hardware_profiles/m1-small' )
|
66
|
+
hwp.should_not be_nil
|
67
|
+
hwp.id.should eql( 'm1-small' )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -28,7 +28,7 @@ describe "initializing the client" do
|
|
28
28
|
|
29
29
|
it "should discover entry points upon connection" do
|
30
30
|
DeltaCloud.new( "name", "password", API_URL ) do |client|
|
31
|
-
client.entry_points[:
|
31
|
+
client.entry_points[:hardware_profiles].should eql( "#{API_URL}/hardware_profiles" )
|
32
32
|
client.entry_points[:images].should eql( "#{API_URL}/images" )
|
33
33
|
client.entry_points[:instances].should eql( "#{API_URL}/instances" )
|
34
34
|
client.entry_points[:storage_volumes].should eql( "#{API_URL}/storage_volumes" )
|
data/specs/instances_spec.rb
CHANGED
@@ -33,8 +33,8 @@ describe "instances" do
|
|
33
33
|
instance.owner_id.should be_a( String )
|
34
34
|
instance.image.should_not be_nil
|
35
35
|
instance.image.should be_a( DCloud::Image )
|
36
|
-
instance.
|
37
|
-
instance.
|
36
|
+
instance.instance_profile.should_not be_nil
|
37
|
+
instance.instance_profile.should be_a( DCloud::InstanceProfile )
|
38
38
|
instance.state.should_not be_nil
|
39
39
|
instance.state.should be_a( String )
|
40
40
|
instance.public_addresses.should_not be_nil
|
@@ -60,18 +60,21 @@ describe "instances" do
|
|
60
60
|
|
61
61
|
it "should allow retrieval of a single instance" do
|
62
62
|
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
63
|
-
instance = client.instance( "
|
63
|
+
instance = client.instance( "inst0" )
|
64
64
|
instance.should_not be_nil
|
65
65
|
instance.name.should_not be_nil
|
66
|
-
instance.name.should eql( '
|
66
|
+
instance.name.should eql( 'Mock Instance With Profile Change' )
|
67
67
|
instance.uri.should_not be_nil
|
68
68
|
instance.uri.should be_a( String )
|
69
69
|
instance.owner_id.should eql( "mockuser" )
|
70
|
-
instance.public_addresses.first.should eql( "
|
70
|
+
instance.public_addresses.first.should eql( "img1.inst0.public.com" )
|
71
71
|
instance.image.should_not be_nil
|
72
|
-
instance.image.uri.should eql( API_URL + "/images/
|
73
|
-
instance.
|
74
|
-
instance.
|
72
|
+
instance.image.uri.should eql( API_URL + "/images/img1" )
|
73
|
+
instance.instance_profile.should_not be_nil
|
74
|
+
instance.instance_profile.hardware_profile.should_not be_nil
|
75
|
+
instance.instance_profile.hardware_profile.uri.should eql( API_URL + "/hardware_profiles/m1-large" )
|
76
|
+
instance.instance_profile[:memory].should eql( "12288" )
|
77
|
+
instance.instance_profile[:storage].should be_nil
|
75
78
|
instance.state.should eql( "RUNNING" )
|
76
79
|
instance.actions.should_not be_nil
|
77
80
|
end
|
@@ -85,7 +88,7 @@ describe "instances" do
|
|
85
88
|
instance.id.should match( /inst[0-9]+/ )
|
86
89
|
instance.name.should eql( 'TestInstance' )
|
87
90
|
instance.image.id.should eql( 'img1' )
|
88
|
-
instance.
|
91
|
+
instance.instance_profile.id.should eql( 'm1-large' )
|
89
92
|
instance.realm.id.should eql( 'us' )
|
90
93
|
end
|
91
94
|
end
|
@@ -97,31 +100,47 @@ describe "instances" do
|
|
97
100
|
instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
|
98
101
|
instance.id.should match( /inst[0-9]+/ )
|
99
102
|
instance.image.id.should eql( 'img1' )
|
100
|
-
instance.
|
103
|
+
instance.instance_profile.id.should eql( 'm1-large' )
|
101
104
|
instance.realm.id.should eql( 'eu' )
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
105
|
-
it "should allow creation of new instances with specific
|
108
|
+
it "should allow creation of new instances with specific hardware profile" do
|
106
109
|
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
107
|
-
instance = client.create_instance( 'img1',
|
110
|
+
instance = client.create_instance( 'img1',
|
111
|
+
:hardware_profile=>'m1-xlarge' )
|
108
112
|
instance.should_not be_nil
|
109
113
|
instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
|
110
114
|
instance.id.should match( /inst[0-9]+/ )
|
111
115
|
instance.image.id.should eql( 'img1' )
|
112
|
-
instance.
|
116
|
+
instance.instance_profile.id.should eql( 'm1-xlarge' )
|
113
117
|
instance.realm.id.should eql( 'us' )
|
114
118
|
end
|
115
119
|
end
|
116
120
|
|
117
|
-
it "should allow creation of new instances with specific
|
121
|
+
it "should allow creation of new instances with specific hardware profile overriding memory" do
|
118
122
|
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
119
|
-
|
123
|
+
hwp = { :id => 'm1-xlarge', :memory => 32768 }
|
124
|
+
instance = client.create_instance( 'img1', :hardware_profile=> hwp )
|
120
125
|
instance.should_not be_nil
|
121
126
|
instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
|
122
127
|
instance.id.should match( /inst[0-9]+/ )
|
123
128
|
instance.image.id.should eql( 'img1' )
|
124
|
-
instance.
|
129
|
+
instance.instance_profile.id.should eql( 'm1-xlarge' )
|
130
|
+
instance.instance_profile[:memory].should eql( "32768" )
|
131
|
+
instance.realm.id.should eql( 'us' )
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should allow creation of new instances with specific realm and hardware profile" do
|
136
|
+
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
137
|
+
instance = client.create_instance( 'img1', :realm=>'eu',
|
138
|
+
:hardware_profile=>'m1-xlarge' )
|
139
|
+
instance.should_not be_nil
|
140
|
+
instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
|
141
|
+
instance.id.should match( /inst[0-9]+/ )
|
142
|
+
instance.image.id.should eql( 'img1' )
|
143
|
+
instance.instance_profile.id.should eql( 'm1-xlarge' )
|
125
144
|
instance.realm.id.should eql( 'eu' )
|
126
145
|
end
|
127
146
|
end
|
data/specs/spec_helper.rb
CHANGED
@@ -24,8 +24,8 @@ api_host = ENV['API_HOST']
|
|
24
24
|
( api_host = 'localhost' ) if api_host == ''
|
25
25
|
|
26
26
|
api_port = ENV['API_PORT']
|
27
|
-
( api_port =
|
28
|
-
( api_port =
|
27
|
+
( api_port = 3001 ) if api_port.nil?
|
28
|
+
( api_port = 3001 ) if api_port == ''
|
29
29
|
|
30
30
|
API_HOST = api_host
|
31
31
|
API_PORT = api_port
|
@@ -46,7 +46,8 @@ describe "storage volumes" do
|
|
46
46
|
storage_volume.device.should eql( '/dev/sda1' )
|
47
47
|
storage_volume.instance.should_not be_nil
|
48
48
|
storage_volume.instance.id.should eql( 'inst1' )
|
49
|
-
storage_volume.instance.
|
49
|
+
ip = storage_volume.instance.instance_profile
|
50
|
+
ip.hardware_profile.architecture.value.should eql( 'i386' )
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
@@ -62,7 +63,8 @@ describe "storage volumes" do
|
|
62
63
|
storage_volume.device.should eql( '/dev/sda1' )
|
63
64
|
storage_volume.instance.should_not be_nil
|
64
65
|
storage_volume.instance.id.should eql( 'inst1' )
|
65
|
-
storage_volume.instance.
|
66
|
+
ip = storage_volume.instance.instance_profile
|
67
|
+
ip.hardware_profile.architecture.value.should eql( 'i386' )
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deltacloud-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Red Hat, Inc.
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-06-17 00:00:00 +02:00
|
13
13
|
default_executable: deltacloudc
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,6 +22,16 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 1.3.1
|
24
24
|
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.0
|
34
|
+
version:
|
25
35
|
description: Deltacloud REST Client for API
|
26
36
|
email: deltacloud-users@lists.fedorahosted.org
|
27
37
|
executables:
|
@@ -33,16 +43,16 @@ extra_rdoc_files:
|
|
33
43
|
files:
|
34
44
|
- Rakefile
|
35
45
|
- credentials.yml
|
36
|
-
- lib/
|
37
|
-
- lib/dcloud/storage_snapshot.rb
|
38
|
-
- lib/dcloud/realm.rb
|
46
|
+
- lib/deltacloud.rb
|
39
47
|
- lib/dcloud/base_model.rb
|
40
|
-
- lib/dcloud/
|
48
|
+
- lib/dcloud/hardware_profile.rb
|
49
|
+
- lib/dcloud/image.rb
|
41
50
|
- lib/dcloud/instance.rb
|
51
|
+
- lib/dcloud/realm.rb
|
42
52
|
- lib/dcloud/state.rb
|
43
|
-
- lib/dcloud/
|
53
|
+
- lib/dcloud/storage_snapshot.rb
|
54
|
+
- lib/dcloud/storage_volume.rb
|
44
55
|
- lib/dcloud/transition.rb
|
45
|
-
- lib/deltacloud.rb
|
46
56
|
- init.rb
|
47
57
|
- bin/deltacloudc
|
48
58
|
- COPYING
|
@@ -75,35 +85,37 @@ signing_key:
|
|
75
85
|
specification_version: 3
|
76
86
|
summary: Deltacloud REST Client
|
77
87
|
test_files:
|
78
|
-
- specs/storage_volume_spec.rb
|
79
|
-
- specs/realms_spec.rb
|
80
|
-
- specs/initialization_spec.rb
|
81
|
-
- specs/spec_helper.rb
|
82
|
-
- specs/images_spec.rb
|
83
|
-
- specs/instances_spec.rb
|
84
|
-
- specs/fixtures/images/img3.yml
|
85
88
|
- specs/fixtures/images/img1.yml
|
86
89
|
- specs/fixtures/images/img2.yml
|
90
|
+
- specs/fixtures/images/img3.yml
|
91
|
+
- specs/fixtures/instances/inst1.yml
|
92
|
+
- specs/fixtures/instances/inst2.yml
|
93
|
+
- specs/fixtures/instances/inst0.yml
|
87
94
|
- specs/fixtures/storage_snapshots/snap1.yml
|
88
|
-
- specs/fixtures/storage_snapshots/snap3.yml
|
89
95
|
- specs/fixtures/storage_snapshots/snap2.yml
|
96
|
+
- specs/fixtures/storage_snapshots/snap3.yml
|
90
97
|
- specs/fixtures/storage_volumes/vol1.yml
|
91
|
-
- specs/fixtures/storage_volumes/vol3.yml
|
92
98
|
- specs/fixtures/storage_volumes/vol2.yml
|
93
|
-
- specs/fixtures/
|
94
|
-
- specs/
|
99
|
+
- specs/fixtures/storage_volumes/vol3.yml
|
100
|
+
- specs/spec_helper.rb
|
101
|
+
- specs/images_spec.rb
|
102
|
+
- specs/initialization_spec.rb
|
95
103
|
- specs/instance_states_spec.rb
|
96
|
-
- specs/
|
97
|
-
- specs/
|
104
|
+
- specs/instances_spec.rb
|
105
|
+
- specs/realms_spec.rb
|
106
|
+
- specs/shared/resources.rb
|
107
|
+
- specs/storage_snapshot_spec.rb
|
108
|
+
- specs/storage_volume_spec.rb
|
109
|
+
- specs/hardware_profiles_spec.rb
|
98
110
|
- specs/data/images/img1.yml
|
99
111
|
- specs/data/images/img2.yml
|
112
|
+
- specs/data/images/img3.yml
|
113
|
+
- specs/data/instances/inst1.yml
|
114
|
+
- specs/data/instances/inst2.yml
|
115
|
+
- specs/data/instances/inst0.yml
|
100
116
|
- specs/data/storage_snapshots/snap1.yml
|
101
|
-
- specs/data/storage_snapshots/snap3.yml
|
102
117
|
- specs/data/storage_snapshots/snap2.yml
|
118
|
+
- specs/data/storage_snapshots/snap3.yml
|
103
119
|
- specs/data/storage_volumes/vol1.yml
|
104
|
-
- specs/data/storage_volumes/vol3.yml
|
105
120
|
- specs/data/storage_volumes/vol2.yml
|
106
|
-
- specs/data/
|
107
|
-
- specs/data/instances/inst2.yml
|
108
|
-
- specs/storage_snapshot_spec.rb
|
109
|
-
- specs/shared/resources.rb
|
121
|
+
- specs/data/storage_volumes/vol3.yml
|
data/lib/dcloud/flavor.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This library is free software; you can redistribute it and/or
|
5
|
-
# modify it under the terms of the GNU Lesser General Public
|
6
|
-
# License as published by the Free Software Foundation; either
|
7
|
-
# version 2.1 of the License, or (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This library is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
-
# Lesser General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU Lesser General Public
|
15
|
-
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
|
19
|
-
require 'dcloud/base_model'
|
20
|
-
|
21
|
-
module DCloud
|
22
|
-
class Flavor < BaseModel
|
23
|
-
|
24
|
-
xml_tag_name :flavor
|
25
|
-
|
26
|
-
attribute :memory
|
27
|
-
attribute :storage
|
28
|
-
attribute :architecture
|
29
|
-
|
30
|
-
def initialize(client, uri, xml=nil)
|
31
|
-
super( client, uri, xml )
|
32
|
-
end
|
33
|
-
|
34
|
-
def load_payload(xml=nil)
|
35
|
-
super(xml)
|
36
|
-
unless xml.nil?
|
37
|
-
@memory = xml.text( 'memory' ).to_f
|
38
|
-
@storage = xml.text( 'storage' ).to_f
|
39
|
-
@architecture = xml.text( 'architecture' )
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def to_plain
|
44
|
-
sprintf("%-15s | %-6s | %10s GB | %10s GB", self.id[0, 15], self.architecture[0,6],
|
45
|
-
self.memory.to_s[0,10], self.storage.to_s[0,10])
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
data/specs/flavors_spec.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This library is free software; you can redistribute it and/or
|
5
|
-
# modify it under the terms of the GNU Lesser General Public
|
6
|
-
# License as published by the Free Software Foundation; either
|
7
|
-
# version 2.1 of the License, or (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This library is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
-
# Lesser General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU Lesser General Public
|
15
|
-
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
|
19
|
-
require 'specs/spec_helper'
|
20
|
-
|
21
|
-
describe "flavors" do
|
22
|
-
|
23
|
-
it_should_behave_like "all resources"
|
24
|
-
|
25
|
-
it "should allow retrieval of all flavors" do
|
26
|
-
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
27
|
-
flavors = client.flavors
|
28
|
-
flavors.should_not be_empty
|
29
|
-
flavors.each do |flavor|
|
30
|
-
flavor.uri.should_not be_nil
|
31
|
-
flavor.uri.should be_a(String)
|
32
|
-
flavor.architecture.should_not be_nil
|
33
|
-
flavor.architecture.should be_a(String)
|
34
|
-
flavor.storage.should_not be_nil
|
35
|
-
flavor.storage.should be_a(Float)
|
36
|
-
flavor.memory.should_not be_nil
|
37
|
-
flavor.memory.should be_a(Float)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should allow filtering of flavors by architecture" do
|
43
|
-
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
44
|
-
flavors = client.flavors( :architecture=>'i386' )
|
45
|
-
flavors.should_not be_empty
|
46
|
-
flavors.size.should eql( 1 )
|
47
|
-
flavors.first.architecture.should eql( 'i386' )
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should allow fetching a flavor by id" do
|
52
|
-
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
53
|
-
flavor = client.flavor( 'm1-small' )
|
54
|
-
flavor.should_not be_nil
|
55
|
-
flavor.id.should eql( 'm1-small' )
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should allow fetching a flavor by URI" do
|
60
|
-
DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
|
61
|
-
flavor = client.fetch_flavor( API_URL + '/flavors/m1-small' )
|
62
|
-
flavor.should_not be_nil
|
63
|
-
flavor.id.should eql( 'm1-small' )
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|