You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltacloud.apache.org by lu...@apache.org on 2010/07/09 01:44:10 UTC

svn commit: r962296 - in /incubator/deltacloud/trunk/client: bin/ lib/ lib/dcloud/ specs/ specs/fixtures/instances/

Author: lutter
Date: Thu Jul  8 23:44:09 2010
New Revision: 962296

URL: http://svn.apache.org/viewvc?rev=962296&view=rev
Log:
Client: add hardware profile support

Added:
    incubator/deltacloud/trunk/client/lib/dcloud/hardware_profile.rb
    incubator/deltacloud/trunk/client/specs/fixtures/instances/inst0.yml
    incubator/deltacloud/trunk/client/specs/hardware_profiles_spec.rb
Modified:
    incubator/deltacloud/trunk/client/bin/deltacloudc
    incubator/deltacloud/trunk/client/lib/dcloud/instance.rb
    incubator/deltacloud/trunk/client/lib/deltacloud.rb
    incubator/deltacloud/trunk/client/specs/fixtures/instances/inst1.yml
    incubator/deltacloud/trunk/client/specs/fixtures/instances/inst2.yml
    incubator/deltacloud/trunk/client/specs/instances_spec.rb

Modified: incubator/deltacloud/trunk/client/bin/deltacloudc
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/bin/deltacloudc?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/bin/deltacloudc (original)
+++ incubator/deltacloud/trunk/client/bin/deltacloudc Thu Jul  8 23:44:09 2010
@@ -70,7 +70,6 @@ client = DeltaCloud.new(url.user, url.pa
 collections = client.entry_points.keys
 
 # Exclude collection which don't have methods in client library yet
-collections.delete(:hardware_profiles)
 collections.delete(:instance_states)
 
 # If list parameter passed print out available collection

Added: incubator/deltacloud/trunk/client/lib/dcloud/hardware_profile.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/lib/dcloud/hardware_profile.rb?rev=962296&view=auto
==============================================================================
--- incubator/deltacloud/trunk/client/lib/dcloud/hardware_profile.rb (added)
+++ incubator/deltacloud/trunk/client/lib/dcloud/hardware_profile.rb Thu Jul  8 23:44:09 2010
@@ -0,0 +1,85 @@
+#
+# Copyright (C) 2009  Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+require 'dcloud/base_model'
+
+module DCloud
+    class HardwareProfile < BaseModel
+
+      class Property
+        attr_reader :name, :unit, :value
+
+        def initialize(xml, name)
+          @name = name
+          p = REXML::XPath.first(xml, "property[@name = '#{name}']")
+          if p
+            @value = p.attributes['value']
+            @unit = p.attributes['unit']
+          end
+        end
+
+        def present?
+          ! @value.nil?
+        end
+
+        def to_s
+          v = @value || "---"
+          u = @unit || ""
+          u = "" if ["label", "count"].include?(u)
+          "#{v} #{u}"
+        end
+      end
+
+      class FloatProperty < Property
+        def initialize(xml, name)
+          super(xml, name)
+          @value = @value.to_f if @value
+        end
+      end
+
+      xml_tag_name :hardware_profile
+
+      attribute :memory
+      attribute :storage
+      attribute :architecture
+
+      def initialize(client, uri, xml=nil)
+        super( client, uri, xml )
+      end
+
+      def load_payload(xml=nil)
+        super(xml)
+        unless xml.nil?
+          @memory = FloatProperty.new(xml, 'memory')
+          @storage = FloatProperty.new(xml, 'storage')
+          @architecture = Property.new(xml, 'architecture')
+        end
+      end
+
+      def to_plain
+        sprintf("%-15s | %-6s | %10s | %10s ", id[0, 15],
+                architecture.to_s[0,6], memory.to_s[0,10], storage.to_s[0,10])
+      end
+
+      private
+      def property_value(xml, name)
+        p = REXML::XPath.first(xml, "property[@name = '#{name}']")
+        p ? p.attributes['value'] : ""
+      end
+    end
+end

Modified: incubator/deltacloud/trunk/client/lib/dcloud/instance.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/lib/dcloud/instance.rb?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/lib/dcloud/instance.rb (original)
+++ incubator/deltacloud/trunk/client/lib/dcloud/instance.rb Thu Jul  8 23:44:09 2010
@@ -19,6 +19,33 @@
 require 'dcloud/base_model'
 
 module DCloud
+
+    class InstanceProfile
+      attr_reader :hardware_profile, :id
+
+      def initialize(client, xml)
+        @hardware_profile = HardwareProfile.new(client, xml.attributes['href'])
+        @properties = {}
+        @id = xml.text("id")
+        xml.get_elements('property').each do |prop|
+          @properties[prop.attributes['name'].to_sym] = {
+            :value => prop.attributes['value'],
+            :unit => prop.attributes['unit'],
+            :kind => prop.attributes['kind'].to_sym
+          }
+        end
+      end
+
+      def [](prop)
+        p = @properties[prop]
+        p ? p[:value] : nil
+      end
+
+      def property(prop)
+        @properties[prop]
+      end
+    end
+
     class Instance < BaseModel
 
       xml_tag_name :instance
@@ -33,6 +60,7 @@ module DCloud
       attribute :flavor
       attribute :realm
       attribute :action_urls
+      attribute :instance_profile
 
       def initialize(client, uri, xml=nil)
         @action_urls = {}
@@ -100,6 +128,8 @@ module DCloud
               realm_uri = xml.get_elements( 'realm' )[0].attributes['href']
               @realm = Realm.new( @client, realm_uri )
           end
+          instance_profile = xml.get_elements( 'hardware-profile' ).first
+          @instance_profile = InstanceProfile.new( @client, instance_profile )
           @state = xml.text( 'state' )
           @actions = []
           xml.get_elements( 'actions/link' ).each do |link|

Modified: incubator/deltacloud/trunk/client/lib/deltacloud.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/lib/deltacloud.rb?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/lib/deltacloud.rb (original)
+++ incubator/deltacloud/trunk/client/lib/deltacloud.rb Thu Jul  8 23:44:09 2010
@@ -19,6 +19,7 @@ require 'rest_client'
 require 'rexml/document'
 require 'logger'
 require 'dcloud/flavor'
+require 'dcloud/hardware_profile'
 require 'dcloud/realm'
 require 'dcloud/image'
 require 'dcloud/instance'
@@ -108,6 +109,34 @@ class DeltaCloud
     nil
   end
 
+  def hardware_profiles(opts={})
+    hardware_profiles = []
+    request(entry_points[:hardware_profiles], :get, opts) do |response|
+      doc = REXML::Document.new( response )
+      doc.get_elements( 'hardware-profiles/hardware-profile' ).each do |hwp|
+        uri = hwp.attributes['href']
+        hardware_profiles << DCloud::HardwareProfile.new( self, uri, hwp )
+      end
+    end
+    hardware_profiles
+  end
+
+  def hardware_profile(id)
+    request( entry_points[:hardware_profiles], :get, {:id=>id } ) do |response|
+      doc = REXML::Document.new( response )
+      doc.get_elements( '/hardware-profile' ).each do |hwp|
+        uri = hwp.attributes['href']
+        return DCloud::HardwareProfile.new( self, uri, hwp )
+      end
+    end
+  end
+
+  def fetch_hardware_profile(uri)
+    xml = fetch_resource( :hardware_profile, uri )
+    return DCloud::HardwareProfile.new( self, uri, xml ) if xml
+    nil
+  end
+
   def fetch_resource(type, uri)
     request( uri ) do |response|
       doc = REXML::Document.new( response )
@@ -262,16 +291,32 @@ class DeltaCloud
     nil
   end
 
+  # Create a new instance, using image +image_id+. Possible optiosn are
+  #
+  #   name  - a user-defined name for the instance
+  #   realm - a specific realm for placement of the instance
+  #   hardware_profile - either a string giving the name of the
+  #                      hardware profile or a hash. The hash must have an
+  #                      entry +id+, giving the id of the hardware profile,
+  #                      and may contain additional names of properties,
+  #                      e.g. 'storage', to override entries in the
+  #                      hardware profile
   def create_instance(image_id, opts={})
     name = opts[:name]
     realm_id = opts[:realm]
-    flavor_id = opts[:flavor]
 
     params = {}
     ( params[:realm_id] = realm_id ) if realm_id
-    ( params[:flavor_id] = flavor_id ) if flavor_id
     ( params[:name] = name ) if name
 
+    if opts[:hardware_profile].is_a?(String)
+      params[:hwp_id] = opts[:hardware_profile]
+    elsif opts[:hardware_profile].is_a?(Hash)
+      opts[:hardware_profile].each do |k,v|
+        params[:"hwp_#{k}"] = v
+      end
+    end
+
     params[:image_id] = image_id
     request( entry_points[:instances], :post, {}, params ) do |response|
       doc = REXML::Document.new( response )

Added: incubator/deltacloud/trunk/client/specs/fixtures/instances/inst0.yml
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/specs/fixtures/instances/inst0.yml?rev=962296&view=auto
==============================================================================
--- incubator/deltacloud/trunk/client/specs/fixtures/instances/inst0.yml (added)
+++ incubator/deltacloud/trunk/client/specs/fixtures/instances/inst0.yml Thu Jul  8 23:44:09 2010
@@ -0,0 +1,17 @@
+---
+:realm_id: us
+:public_addresses:
+- img1.inst0.public.com
+:state: RUNNING
+:name: "Mock Instance With Profile Change"
+:private_addresses:
+- img1.inst0.private.com
+:image_id: img1
+:flavor_id: m1-large
+:instance_profile: !ruby/object:InstanceProfile
+  id: m1-large
+  memory: "12288"
+:owner_id: mockuser
+:actions:
+- :reboot
+- :stop

Modified: incubator/deltacloud/trunk/client/specs/fixtures/instances/inst1.yml
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/specs/fixtures/instances/inst1.yml?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/specs/fixtures/instances/inst1.yml (original)
+++ incubator/deltacloud/trunk/client/specs/fixtures/instances/inst1.yml Thu Jul  8 23:44:09 2010
@@ -6,3 +6,5 @@
 :private_addresses: [ img3.inst1.private.com ]
 :flavor_id: m1-small
 :realm_id: us
+:instance_profile: !ruby/object:InstanceProfile
+  id: m1-small

Modified: incubator/deltacloud/trunk/client/specs/fixtures/instances/inst2.yml
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/specs/fixtures/instances/inst2.yml?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/specs/fixtures/instances/inst2.yml (original)
+++ incubator/deltacloud/trunk/client/specs/fixtures/instances/inst2.yml Thu Jul  8 23:44:09 2010
@@ -6,3 +6,5 @@
 :private_addresses: [ img1.inst2.private.com ]
 :flavor_id: m1-small
 :realm_id: us
+:instance_profile: !ruby/object:InstanceProfile
+  id: m1-large

Added: incubator/deltacloud/trunk/client/specs/hardware_profiles_spec.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/specs/hardware_profiles_spec.rb?rev=962296&view=auto
==============================================================================
--- incubator/deltacloud/trunk/client/specs/hardware_profiles_spec.rb (added)
+++ incubator/deltacloud/trunk/client/specs/hardware_profiles_spec.rb Thu Jul  8 23:44:09 2010
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2009  Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+require 'specs/spec_helper'
+
+def prop_check(prop, value_class)
+  if prop.present?
+    prop.value.should_not be_nil
+    prop.value.should be_a(value_class)
+  end
+end
+
+describe "hardware_profiles" do
+
+  it_should_behave_like "all resources"
+
+  it "should allow retrieval of all hardware profiles" do
+    DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
+      hardware_profiles = client.hardware_profiles
+      hardware_profiles.should_not be_empty
+      hardware_profiles.each do |hwp|
+        hwp.uri.should_not be_nil
+        hwp.uri.should be_a(String)
+        prop_check(hwp.architecture, String)
+        prop_check(hwp.storage, Float)
+        prop_check(hwp.memory, Float)
+      end
+    end
+  end
+
+  it "should allow filtering of hardware_profiles by architecture" do
+    DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
+      hardware_profiles = client.hardware_profiles( :architecture=>'i386' )
+      hardware_profiles.should_not be_empty
+      hardware_profiles.size.should eql( 2 )
+      hardware_profiles.first.architecture.value.should eql( 'i386' )
+    end
+  end
+
+  it "should allow fetching a hardware_profile by id" do
+    DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
+      hwp = client.hardware_profile( 'm1-small' )
+      hwp.should_not be_nil
+      hwp.id.should eql( 'm1-small' )
+    end
+  end
+
+  it "should allow fetching a hardware_profile by URI" do
+    DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
+      hwp = client.fetch_hardware_profile( API_URL + '/hardware_profiles/m1-small' )
+      hwp.should_not be_nil
+      hwp.id.should eql( 'm1-small' )
+    end
+  end
+
+end

Modified: incubator/deltacloud/trunk/client/specs/instances_spec.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/client/specs/instances_spec.rb?rev=962296&r1=962295&r2=962296&view=diff
==============================================================================
--- incubator/deltacloud/trunk/client/specs/instances_spec.rb (original)
+++ incubator/deltacloud/trunk/client/specs/instances_spec.rb Thu Jul  8 23:44:09 2010
@@ -35,6 +35,8 @@ describe "instances" do
         instance.image.should be_a( DCloud::Image )
         instance.flavor.should_not be_nil
         instance.flavor.should be_a( DCloud::Flavor )
+        instance.instance_profile.should_not be_nil
+        instance.instance_profile.should be_a( DCloud::InstanceProfile )
         instance.state.should_not be_nil
         instance.state.should be_a( String )
         instance.public_addresses.should_not be_nil
@@ -60,18 +62,23 @@ describe "instances" do
 
   it "should allow retrieval of a single instance" do
     DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
-      instance = client.instance( "inst1" )
+      instance = client.instance( "inst0" )
       instance.should_not be_nil
       instance.name.should_not be_nil
-      instance.name.should eql( 'MockUserInstance' )
+      instance.name.should eql( 'Mock Instance With Profile Change' )
       instance.uri.should_not be_nil
       instance.uri.should be_a( String )
       instance.owner_id.should eql( "mockuser" )
-      instance.public_addresses.first.should eql( "img3.inst1.public.com" )
+      instance.public_addresses.first.should eql( "img1.inst0.public.com" )
       instance.image.should_not be_nil
-      instance.image.uri.should eql( API_URL + "/images/img3" )
+      instance.image.uri.should eql( API_URL + "/images/img1" )
       instance.flavor.should_not be_nil
-      instance.flavor.uri.should eql( API_URL + "/flavors/m1-small" )
+      instance.flavor.uri.should eql( API_URL + "/flavors/m1-large" )
+      instance.instance_profile.should_not be_nil
+      instance.instance_profile.hardware_profile.should_not be_nil
+      instance.instance_profile.hardware_profile.uri.should eql( API_URL + "/hardware_profiles/m1-large" )
+      instance.instance_profile[:memory].should eql( "12288" )
+      instance.instance_profile[:storage].should be_nil
       instance.state.should eql( "RUNNING" )
       instance.actions.should_not be_nil
     end
@@ -86,6 +93,7 @@ describe "instances" do
       instance.name.should eql( 'TestInstance' )
       instance.image.id.should eql( 'img1' )
       instance.flavor.id.should eql( 'm1-large' )
+      instance.instance_profile.id.should eql( 'm1-large' )
       instance.realm.id.should eql( 'us' )
     end
   end
@@ -98,30 +106,50 @@ describe "instances" do
       instance.id.should match( /inst[0-9]+/ )
       instance.image.id.should eql( 'img1' )
       instance.flavor.id.should eql( 'm1-large' )
+      instance.instance_profile.id.should eql( 'm1-large' )
       instance.realm.id.should eql( 'eu' )
     end
   end
 
-  it "should allow creation of new instances with specific flavor" do
+  it "should allow creation of new instances with specific hardware profile" do
     DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
-      instance = client.create_instance( 'img1', :flavor=>'m1-xlarge' )
+      instance = client.create_instance( 'img1',
+                                         :hardware_profile=>'m1-xlarge' )
       instance.should_not be_nil
       instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
       instance.id.should match( /inst[0-9]+/ )
       instance.image.id.should eql( 'img1' )
       instance.flavor.id.should eql( 'm1-xlarge' )
+      instance.instance_profile.id.should eql( 'm1-xlarge' )
       instance.realm.id.should eql( 'us' )
     end
   end
 
-  it "should allow creation of new instances with specific realm and flavor" do
+  it "should allow creation of new instances with specific hardware profile overriding memory" do
     DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
-      instance = client.create_instance( 'img1', :realm=>'eu', :flavor=>'m1-xlarge' )
+      hwp = { :id => 'm1-xlarge', :memory => 32768 }
+      instance = client.create_instance( 'img1', :hardware_profile=> hwp )
       instance.should_not be_nil
       instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
       instance.id.should match( /inst[0-9]+/ )
       instance.image.id.should eql( 'img1' )
       instance.flavor.id.should eql( 'm1-xlarge' )
+      instance.instance_profile.id.should eql( 'm1-xlarge' )
+      instance.instance_profile[:memory].should eql( "32768" )
+      instance.realm.id.should eql( 'us' )
+    end
+  end
+
+  it "should allow creation of new instances with specific realm and hardware profile" do
+    DeltaCloud.new( API_NAME, API_PASSWORD, API_URL ) do |client|
+      instance = client.create_instance( 'img1', :realm=>'eu',
+                                         :hardware_profile=>'m1-xlarge' )
+      instance.should_not be_nil
+      instance.uri.should match( %r{#{API_URL}/instances/inst[0-9]+} )
+      instance.id.should match( /inst[0-9]+/ )
+      instance.image.id.should eql( 'img1' )
+      instance.flavor.id.should eql( 'm1-xlarge' )
+      instance.instance_profile.id.should eql( 'm1-xlarge' )
       instance.realm.id.should eql( 'eu' )
     end
   end