You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2011/11/10 16:32:45 UTC

Added support for dynamic provider listing

Hi,

This patchset is targeting the issue of having multiple datacenters
for particular cloud providers (namely: RHEV-M and VSphere).

https://teambox.com/projects/deltacloud/tasks/586718

This patch should support for 'dynamic' providers. For now the list of
providers is hard-coded in driver configuration yaml file. However for
some clouds the list need to be fetched, because we don't know what are the
names or UUIDs of datacenters/etc.

This can be also used in future to fetch providers from EC2 directly instead
of maintaining 'static' list.

 -- Michal


Re: [PATCH core 2/2] Core: Added support for dynamic provider list in /api/drivers/:id

Posted by Michal Fojtik <mi...@mifo.sk>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ping. Anyone willing to review this?

 -- Michal

mfojtik@redhat.com wrote:
> From: Michal Fojtik <mf...@redhat.com>
> 
> 
> Signed-off-by: Michal fojtik <mf...@redhat.com> --- 
> server/lib/deltacloud/base_driver/base_driver.rb |    1 + 
> server/lib/deltacloud/models.rb                  |    1 + 
> server/lib/deltacloud/models/provider.rb         |   27
> ++++++++++++++++++++++ server/lib/deltacloud/server.rb
> |    1 + server/views/drivers/show.xml.haml               |   13
> +++++++--- 5 files changed, 39 insertions(+), 4 deletions(-) create
> mode 100644 server/lib/deltacloud/models/provider.rb
> 
> diff --git a/server/lib/deltacloud/base_driver/base_driver.rb
> b/server/lib/deltacloud/base_driver/base_driver.rb index
> 931ef5c..1aa68e1 100644 ---
> a/server/lib/deltacloud/base_driver/base_driver.rb +++
> b/server/lib/deltacloud/base_driver/base_driver.rb @@ -155,6 +155,7
> @@ module Deltacloud # def delete_firewall(credentials, opts) # def
> create_firewall_rule(credentials, opts) # def
> delete_firewall_rule(credentials, opts) +    # def
> providers(credentials) def realm(credentials, opts) realms =
> realms(credentials, opts).first if has_capability?(:realms) end diff
> --git a/server/lib/deltacloud/models.rb
> b/server/lib/deltacloud/models.rb index e8cd035..a794192 100644 ---
> a/server/lib/deltacloud/models.rb +++
> b/server/lib/deltacloud/models.rb @@ -29,3 +29,4 @@ require
> 'deltacloud/models/blob' require 'deltacloud/models/load_balancer' 
> require 'deltacloud/models/firewall' require
> 'deltacloud/models/firewall_rule' +require
> 'deltacloud/models/provider' diff --git
> a/server/lib/deltacloud/models/provider.rb
> b/server/lib/deltacloud/models/provider.rb new file mode 100644 index
> 0000000..1fc2c7d --- /dev/null +++
> b/server/lib/deltacloud/models/provider.rb @@ -0,0 +1,27 @@ +#
> Licensed to the Apache Software Foundation (ASF) under one or more +#
> contributor license agreements.  See the NOTICE file distributed
> with +# this work for additional information regarding copyright
> ownership.  The +# ASF licenses this file to you under the Apache
> License, Version 2.0 (the +# "License"); you may not use this file
> except in compliance with the +# License.  You may obtain a copy of
> the License at +# +#
> http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by
> applicable law or agreed to in writing, software +# distributed under
> the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES
> OR CONDITIONS OF ANY KIND, either express or implied.  See the +#
> License for the specific language governing permissions and
> limitations +# under the License. + +# Model to store the hardware
> profile applied to an instance together with +# any instance-specific
> overrides + +class Provider < BaseModel +  attr_accessor :url +
> attr_accessor :name + +  def initialize(opts={}) +    super(opts) +
> end + +end diff --git a/server/lib/deltacloud/server.rb
> b/server/lib/deltacloud/server.rb index 2a5d481..3124659 100644 ---
> a/server/lib/deltacloud/server.rb +++
> b/server/lib/deltacloud/server.rb @@ -148,6 +148,7 @@ EOS param :id,
> :string control do @name = params[:id].to_sym +      @providers =
> driver.providers(credentials) if driver.respond_to? :providers 
> @driver = settings.drivers[@name] return [404, "Driver #{@name} not
> found"] unless @driver respond_to do |format| diff --git
> a/server/views/drivers/show.xml.haml
> b/server/views/drivers/show.xml.haml index ea5f508..3734c4d 100644 
> --- a/server/views/drivers/show.xml.haml +++
> b/server/views/drivers/show.xml.haml @@ -1,7 +1,12 @@ %driver{ :href
> => driver_url(@name), :id => @name } %name< = @driver[:name] -  -
> driver_provider(@driver).each do |prov, details| -    %provider{ :id
> => prov } -      - details.each do |kind, url| -        %entrypoint{
> :kind => kind }<=cdata(url) +  - if @providers.nil? +    -
> driver_provider(@driver).each do |prov, details| +      %provider{
> :id => prov } +        - details.each do |kind, url| +
> %entrypoint{ :kind => kind }<=cdata(url) +  - else +    -
> @providers.each do |p| +      %provider{ :id => p.id } +
> %entrypoint{ :kind => p.name }<=p.url

- -- 
- ----------------------------------------------------------------
Michal Fojtik
deltacloud.org - Deltacloud API

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOx+/zAAoJEBGIkweUFTuYAaIIAIrit0n/5qKd7zHjaJ0Q+ed6
9oYyCWRh5DiTzEAbZbfLRGqtHT4npbeX4vY1IT2pbxmNX7YI9T/vN+/tJEq1U1J5
nrwrLjK4XVRXDbMItNubYHiLR02MKIut65wwJtJHJ324JOmzUvyvVTa6AmP8tlw8
0YUp2eqlS1hHCaMxr0egagFnMlU4JqpC83hGe3m0+gEurxUAm+u6h+OHHnDZ1ddE
vUxBKxBjTxhlI5dhFnxMYvoYgKzVuMBmtuTdO+YNLZTDbL+DG+RlhG0CEC7rENEl
rZhGsa48A4kL1jacn9A7nl4L/FQhanVBJbXxp5OyR0TELrnZeSP80v/IMOJljhA=
=tdC2
-----END PGP SIGNATURE-----

[PATCH core 2/2] Core: Added support for dynamic provider list in /api/drivers/:id

Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>


Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 server/lib/deltacloud/base_driver/base_driver.rb |    1 +
 server/lib/deltacloud/models.rb                  |    1 +
 server/lib/deltacloud/models/provider.rb         |   27 ++++++++++++++++++++++
 server/lib/deltacloud/server.rb                  |    1 +
 server/views/drivers/show.xml.haml               |   13 +++++++---
 5 files changed, 39 insertions(+), 4 deletions(-)
 create mode 100644 server/lib/deltacloud/models/provider.rb

diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
index 931ef5c..1aa68e1 100644
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ b/server/lib/deltacloud/base_driver/base_driver.rb
@@ -155,6 +155,7 @@ module Deltacloud
     # def delete_firewall(credentials, opts)
     # def create_firewall_rule(credentials, opts)
     # def delete_firewall_rule(credentials, opts)
+    # def providers(credentials)
     def realm(credentials, opts)
       realms = realms(credentials, opts).first if has_capability?(:realms)
     end
diff --git a/server/lib/deltacloud/models.rb b/server/lib/deltacloud/models.rb
index e8cd035..a794192 100644
--- a/server/lib/deltacloud/models.rb
+++ b/server/lib/deltacloud/models.rb
@@ -29,3 +29,4 @@ require 'deltacloud/models/blob'
 require 'deltacloud/models/load_balancer'
 require 'deltacloud/models/firewall'
 require 'deltacloud/models/firewall_rule'
+require 'deltacloud/models/provider'
diff --git a/server/lib/deltacloud/models/provider.rb b/server/lib/deltacloud/models/provider.rb
new file mode 100644
index 0000000..1fc2c7d
--- /dev/null
+++ b/server/lib/deltacloud/models/provider.rb
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# Model to store the hardware profile applied to an instance together with
+# any instance-specific overrides
+
+class Provider < BaseModel
+  attr_accessor :url
+  attr_accessor :name
+
+  def initialize(opts={})
+    super(opts)
+  end
+
+end
diff --git a/server/lib/deltacloud/server.rb b/server/lib/deltacloud/server.rb
index 2a5d481..3124659 100644
--- a/server/lib/deltacloud/server.rb
+++ b/server/lib/deltacloud/server.rb
@@ -148,6 +148,7 @@ EOS
     param :id,      :string
     control do
       @name = params[:id].to_sym
+      @providers = driver.providers(credentials) if driver.respond_to? :providers
       @driver = settings.drivers[@name]
       return [404, "Driver #{@name} not found"] unless @driver
       respond_to do |format|
diff --git a/server/views/drivers/show.xml.haml b/server/views/drivers/show.xml.haml
index ea5f508..3734c4d 100644
--- a/server/views/drivers/show.xml.haml
+++ b/server/views/drivers/show.xml.haml
@@ -1,7 +1,12 @@
 %driver{ :href => driver_url(@name), :id => @name }
   %name<
     = @driver[:name]
-  - driver_provider(@driver).each do |prov, details|
-    %provider{ :id => prov }
-      - details.each do |kind, url|
-        %entrypoint{ :kind => kind }<=cdata(url)
+  - if @providers.nil?
+    - driver_provider(@driver).each do |prov, details|
+      %provider{ :id => prov }
+        - details.each do |kind, url|
+          %entrypoint{ :kind => kind }<=cdata(url)
+  - else
+    - @providers.each do |p|
+      %provider{ :id => p.id }
+        %entrypoint{ :kind => p.name }<=p.url
-- 
1.7.4.4


[PATCH core 1/2] RHEV-M: Datacenters are now behave as separate regions. Client should not see all clusters in RHEV-M but only clusters defined for current Datacenter

Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>


Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 .../lib/deltacloud/drivers/rhevm/rhevm_client.rb   |   94 ++++++++++++++------
 .../lib/deltacloud/drivers/rhevm/rhevm_driver.rb   |   19 ++++-
 2 files changed, 83 insertions(+), 30 deletions(-)

diff --git a/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb b/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb
index 49f6509..29b3297 100644
--- a/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb
+++ b/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb
@@ -44,10 +44,11 @@ module RHEVM
 
   class Client
 
-    attr_reader :credentials, :api_entrypoint
+    attr_reader :credentials, :api_entrypoint, :datacenter_id
 
-    def initialize(username, password, api_entrypoint)
+    def initialize(username, password, api_entrypoint, datacenter_id=nil)
       @credentials = { :username => username, :password => password }
+      @datacenter_id = datacenter_id
       @api_entrypoint = api_entrypoint
     end
 
@@ -58,11 +59,13 @@ module RHEVM
       headers.merge!(auth_header)
       if opts[:id]
         vm = Client::parse_response(RHEVM::client(@api_entrypoint)["/vms/%s" % opts[:id]].get(headers)).root
+        return [] unless current_datacenter.cluster_ids.include?((vm/'cluster').first[:id])
         [ RHEVM::VM::new(self, vm)]
       else
         Client::parse_response(RHEVM::client(@api_entrypoint)["/vms"].get(headers)).xpath('/vms/vm').collect do |vm|
+          next unless current_datacenter.cluster_ids.include?((vm/'cluster').first[:id])
           RHEVM::VM::new(self, vm)
-        end
+        end.compact
       end
     end
 
@@ -72,6 +75,8 @@ module RHEVM
         :content_type => 'application/xml',
         :accept => 'application/xml',
       })
+      vm = vms(:id => id)
+      raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") if vm.empty?
       if action==:delete
         RHEVM::client(@api_entrypoint)["/vms/%s" % id].delete(headers)
       else
@@ -86,7 +91,6 @@ module RHEVM
           raise RHEVMBackendException::new(fault)
         end
         xml_response = Client::parse_response(client_response)
-
         return false if (xml_response/'action/status').first.text.strip.upcase!="COMPLETE"
       end
       return true
@@ -108,17 +112,17 @@ module RHEVM
         :accept => 'application/xml'
       }
       headers.merge!(auth_header)
-      result_xml = Nokogiri::XML(RHEVM::client(@api_entrypoint)["/clusters/%s" % cluster_id].get(headers))
-      (result_xml/'/cluster/version').first[:major].strip == major
+      current_datacenter.cluster.first.version == major
     end
 
     def create_vm(template_id, opts={})
       opts ||= {}
+      raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") unless template(template_id)
       builder = Nokogiri::XML::Builder.new do
         vm {
           name opts[:name] || "i-#{Time.now.to_i}"
           template_(:id => template_id)
-          cluster(:id => opts[:realm_id].empty? ? clusters.first.id : opts[:realm_id])
+          cluster_(:id => opts[:realm_id].empty? ? clusters.first.id : opts[:realm_id])
           type_ opts[:hwp_id] || 'desktop'
           memory opts[:hwp_memory] ? (opts[:hwp_memory].to_i*1024*1024).to_s : (512*1024*1024).to_s
           cpu {
@@ -127,11 +131,6 @@ module RHEVM
           if opts[:user_data] and not opts[:user_data].empty?
             if api_version?('3') and cluster_version?((opts[:realm_id] || clusters.first.id), '3')
               custom_properties {
-                #
-                # FIXME: 'regexp' parameter is just a temporary workaround. This
-                # is a reported and verified bug and should be fixed in next
-                # RHEV-M release.
-                #
                 custom_property({
                   :name => "floppyinject",
                   :value => "#{RHEVM::FILEINJECT_PATH}:#{opts[:user_data]}",
@@ -176,6 +175,8 @@ module RHEVM
         :content_type => 'application/xml',
         :accept => 'application/xml',
       })
+      vm = vms(:id => id)
+      raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") if vm.empty?
       headers.merge!(auth_header)
       template = RHEVM::client(@api_entrypoint)["/templates"].post(Nokogiri::XML(builder.to_xml).root.to_s, headers)
       RHEVM::Template::new(self, Nokogiri::XML(template).root)
@@ -187,6 +188,8 @@ module RHEVM
         :accept => 'application/xml',
       })
       headers.merge!(auth_header)
+      tmpl = template(id)
+      raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") unless tmpl
       RHEVM::client(@api_entrypoint)["/templates/%s" % id].delete(headers)
       return true
     end
@@ -198,8 +201,9 @@ module RHEVM
       headers.merge!(auth_header)
       rhevm_templates = RHEVM::client(@api_entrypoint)["/templates"].get(headers)
       Client::parse_response(rhevm_templates).xpath('/templates/template').collect do |t|
+        next unless current_datacenter.cluster_ids.include?((t/'cluster').first[:id])
         RHEVM::Template::new(self, t)
-      end
+      end.compact
     end
 
     def template(template_id)
@@ -211,19 +215,12 @@ module RHEVM
       RHEVM::Template::new(self, Client::parse_response(rhevm_template).root)
     end
 
-    def clusters(opts={})
-      headers = {
-        :accept => "application/xml; detail=datacenters"
-      }
-      headers.merge!(auth_header)
-      if opts[:id]
-        vm = Client::parse_response(RHEVM::client(@api_entrypoint)["/clusters/%s" % opts[:id]].get(headers)).root
-        [ RHEVM::Cluster::new(self, vm)]
-      else
-        Client::parse_response(RHEVM::client(@api_entrypoint)["/clusters"].get(headers)).xpath('/clusters/cluster').collect do |vm|
-          RHEVM::Cluster::new(self, vm) if has_datacenter?(vm)
-        end.compact
-      end
+    def clusters
+      current_datacenter.clusters
+    end
+
+    def cluster(cluster_id)
+      current_datacenter.cluster(cluster_id)
     end
 
     def datacenters(opts={})
@@ -295,6 +292,11 @@ module RHEVM
       value=!(vm/'data_center').empty?
       value
     end
+
+    def current_datacenter
+      @current_datacenter ||= self.datacenter_id ? datacenter(self.datacenter_id) : datacenters.first
+    end
+
   end
 
   class BaseObject
@@ -384,7 +386,7 @@ module RHEVM
   end
 
   class Cluster < BaseObject
-    attr_reader :description, :datacenter
+    attr_reader :description, :datacenter, :version
 
     def initialize(client, xml)
       super(client, xml[:id], xml[:href], (xml/'name').first.text)
@@ -396,7 +398,10 @@ module RHEVM
 
     def parse_xml_attributes!(xml)
       @description = ((xml/'description').first.text rescue nil)
-      @datacenter = Link::new(@client, (xml/'data_center').first[:id], (xml/'data_center').first[:href])
+      @version =((xml/'version').first[:major].strip rescue nil)
+      unless (xml/'data_center').empty?
+        @datacenter = Link::new(@client, (xml/'data_center').first[:id], (xml/'data_center').first[:href])
+      end
     end
 
   end
@@ -410,6 +415,39 @@ module RHEVM
       self
     end
 
+    def clusters
+      headers = {
+        :accept => "application/xml; detail=datacenters"
+      }
+      headers.merge!(client.auth_header)
+      clusters_list = RHEVM::client(client.api_entrypoint)["/clusters"].get(headers)
+      cluster_arr = Client::parse_response(clusters_list).xpath('/clusters/cluster')
+      clusters_arr = []
+      cluster_arr.each do |cluster|
+        cluster = RHEVM::Cluster.new(self.client, cluster)
+        clusters_arr << cluster if cluster.datacenter && cluster.datacenter.id == client.datacenter_id
+      end
+      clusters_arr
+    end
+
+    def cluster(cluster_id)
+      headers = {
+        :accept => "application/xml; detail=datacenters"
+      }
+      headers.merge!(client.auth_header)
+      cluster_xml = RHEVM::client(client.api_entrypoint)["/clusters/%s" % cluster_id].get(headers)
+      cluster = RHEVM::Cluster.new(self.client, cluster_xml)
+      if cluster.datacenter && cluster.datacenter.id == client.datacenter_id
+        cluster
+      else
+        nil
+      end
+    end
+
+    def cluster_ids
+      @cluster_ids ||= clusters.collect { |c| c.id }
+    end
+
     private
 
     def parse_xml_attributes!(xml)
diff --git a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
index fa876de..9c8b391 100644
--- a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
+++ b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
@@ -70,6 +70,13 @@ class RHEVMDriver < Deltacloud::BaseDriver
     stopped.to( :finish )         .on( :destroy )
   end
 
+  def providers(credentials)
+    client = new_client(credentials)
+    safely do
+      client.datacenters.collect { |dc| convert_provider(dc) }
+    end
+  end
+
   #
   # Realms
   #
@@ -209,9 +216,9 @@ class RHEVMDriver < Deltacloud::BaseDriver
   private
 
   def new_client(credentials)
-    url = api_provider
+    url, datacenter = api_provider.split(';')
     safely do
-      ::RHEVM::Client.new(credentials.user, credentials.password, url)
+      ::RHEVM::Client.new(credentials.user, credentials.password, url, datacenter)
     end
   end
 
@@ -317,6 +324,14 @@ class RHEVMDriver < Deltacloud::BaseDriver
     )
   end
 
+  def convert_provider(dc)
+    Provider.new(
+      :id => dc.id,
+      :name => dc.name,
+      :url => [api_provider.split(';').first, dc.id].join(';')
+    )
+  end
+
   exceptions do
 
     on /Bad Request/ do
-- 
1.7.4.4