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 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( '-f', '--flavor_id FLAVOR', 'Flavor') { |id| options[:flavor_id] = id }
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 /flavors)
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, --flavor-id and --name parameters are used
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!(:flavor_id => options[:flavor_id]) if options[:flavor_id]
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
@@ -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/flavor'
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 flavors(opts={})
78
- flavors = []
79
- request(entry_points[:flavors], :get, opts) do |response|
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( 'flavors/flavor' ).each do |flavor|
82
- uri = flavor.attributes['href']
83
- flavors << DCloud::Flavor.new( self, uri, flavor )
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
- flavors
92
+ hardware_profiles
87
93
  end
88
94
 
89
- def flavor(id)
90
- request( entry_points[:flavors], :get, {:id=>id } ) do |response|
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( '/flavor' ).each do |flavor|
93
- uri = flavor.attributes['href']
94
- return DCloud::Flavor.new( self, uri, flavor )
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 fetch_flavor(uri)
100
- xml = fetch_resource( :flavor, uri )
101
- return DCloud::Flavor.new( self, uri, xml ) if xml
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.to_sym] = uri
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)
@@ -1,3 +1,4 @@
1
1
  :description: Fedora 10
2
2
  :owner_id: fedoraproject
3
3
  :architecture: x86_64
4
+ :id: img1
@@ -1,3 +1,4 @@
1
1
  :description: Fedora 10
2
2
  :owner_id: fedoraproject
3
3
  :architecture: i386
4
+ :id: img2
@@ -1,3 +1,4 @@
1
1
  :description: JBoss
2
2
  :owner_id: mockuser
3
3
  :architecture: i386
4
+ :id: img3
@@ -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
@@ -4,5 +4,6 @@
4
4
  :owner_id: mockuser
5
5
  :public_addresses: [ img3.inst1.public.com ]
6
6
  :private_addresses: [ img3.inst1.private.com ]
7
- :flavor_id: m1-small
8
7
  :realm_id: us
8
+ :instance_profile: !ruby/object:InstanceProfile
9
+ id: m1-small
@@ -4,5 +4,6 @@
4
4
  :owner_id: anotheruser
5
5
  :public_addresses: [ img1.inst2.public.com ]
6
6
  :private_addresses: [ img1.inst2.private.com ]
7
- :flavor_id: m1-small
8
7
  :realm_id: us
8
+ :instance_profile: !ruby/object:InstanceProfile
9
+ id: m1-large
@@ -1,3 +1,4 @@
1
1
  :description: Fedora 10
2
2
  :owner_id: fedoraproject
3
3
  :architecture: x86_64
4
+ :id: img1
@@ -1,3 +1,4 @@
1
1
  :description: Fedora 10
2
2
  :owner_id: fedoraproject
3
3
  :architecture: i386
4
+ :id: img2
@@ -1,3 +1,4 @@
1
1
  :description: JBoss
2
2
  :owner_id: mockuser
3
3
  :architecture: i386
4
+ :id: img3
@@ -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
@@ -4,5 +4,6 @@
4
4
  :owner_id: mockuser
5
5
  :public_addresses: [ img3.inst1.public.com ]
6
6
  :private_addresses: [ img3.inst1.private.com ]
7
- :flavor_id: m1-small
8
7
  :realm_id: us
8
+ :instance_profile: !ruby/object:InstanceProfile
9
+ id: m1-small
@@ -4,5 +4,6 @@
4
4
  :owner_id: anotheruser
5
5
  :public_addresses: [ img1.inst2.public.com ]
6
6
  :private_addresses: [ img1.inst2.private.com ]
7
- :flavor_id: m1-small
8
7
  :realm_id: us
8
+ :instance_profile: !ruby/object:InstanceProfile
9
+ id: m1-large
@@ -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[:flavors].should eql( "#{API_URL}/flavors" )
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" )
@@ -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.flavor.should_not be_nil
37
- instance.flavor.should be_a( DCloud::Flavor )
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( "inst1" )
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( 'MockUserInstance' )
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( "img3.inst1.public.com" )
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/img3" )
73
- instance.flavor.should_not be_nil
74
- instance.flavor.uri.should eql( API_URL + "/flavors/m1-small" )
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.flavor.id.should eql( 'm1-large' )
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.flavor.id.should eql( 'm1-large' )
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 flavor" do
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', :flavor=>'m1-xlarge' )
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.flavor.id.should eql( 'm1-xlarge' )
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 realm and flavor" do
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
- instance = client.create_instance( 'img1', :realm=>'eu', :flavor=>'m1-xlarge' )
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.flavor.id.should eql( 'm1-xlarge' )
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 = 3000 ) if api_port.nil?
28
- ( api_port = 3000 ) if 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.flavor.architecture.should eql( 'i386' )
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.flavor.architecture.should eql( 'i386' )
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.3
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-03-04 00:00:00 -05:00
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/dcloud/image.rb
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/storage_volume.rb
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/flavor.rb
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/instances/inst1.yml
94
- - specs/fixtures/instances/inst2.yml
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/flavors_spec.rb
97
- - specs/data/images/img3.yml
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/instances/inst1.yml
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
@@ -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