deltacloud-client 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|