[PATCH conductor 1/9] ProviderSelection improvements:

ifarkas at redhat.com ifarkas at redhat.com
Thu Aug 16 14:44:01 UTC 2012


From: Imre Farkas <ifarkas at redhat.com>

- decouple the strategy from its proprties
- chain_strategy method more fault tolerant in case the strategy doesn't exist anymore
- Match initializer handles attributes dynamically
- score is required for the priority group
---
 src/app/models/deployment.rb                       |  2 +-
 src/lib/provider_selection.rb                      |  2 +-
 src/lib/provider_selection/base.rb                 | 12 ++++--
 src/lib/provider_selection/chainable_strategy.rb   | 20 ++++------
 .../chainable_strategy_options.rb                  | 29 ++++++++++++++
 src/lib/provider_selection/match.rb                | 17 +++++++--
 src/lib/provider_selection/priority_group.rb       |  8 +++-
 src/lib/provider_selection/strategy.rb             |  8 ++--
 src/lib/provider_selection/strategy_options.rb     | 44 ++++++++++++++++++++++
 9 files changed, 116 insertions(+), 26 deletions(-)
 create mode 100644 src/lib/provider_selection/chainable_strategy_options.rb
 create mode 100644 src/lib/provider_selection/strategy_options.rb

diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb
index 523c6cd..79bcb82 100644
--- a/src/app/models/deployment.rb
+++ b/src/app/models/deployment.rb
@@ -577,7 +577,7 @@ class Deployment < ActiveRecord::Base
 
     provider_selection_strategy = ProviderSelection::Base.new(instances)
     pool.provider_selection_strategies.enabled.each do  |strategy|
-      provider_selection_strategy.chain_strategy(strategy.name)
+      provider_selection_strategy.chain_strategy(strategy.name, strategy.config)
     end
 
     match = provider_selection_strategy.next_match
diff --git a/src/lib/provider_selection.rb b/src/lib/provider_selection.rb
index 375c9dc..08e8d89 100644
--- a/src/lib/provider_selection.rb
+++ b/src/lib/provider_selection.rb
@@ -15,6 +15,6 @@
 #
 
 # Require files in lib dir
-['match', 'priority_group', 'rank', 'strategy', 'base', 'chainable_strategy'].each do |file_name|
+['match', 'priority_group', 'rank', 'strategy', 'base', 'chainable_strategy', 'chainable_strategy_options'].each do |file_name|
   require File.join(File.dirname(__FILE__), 'provider_selection', file_name)
 end
diff --git a/src/lib/provider_selection/base.rb b/src/lib/provider_selection/base.rb
index b7a4300..b75bd35 100644
--- a/src/lib/provider_selection/base.rb
+++ b/src/lib/provider_selection/base.rb
@@ -28,8 +28,9 @@ module ProviderSelection
       def register_strategy(name, lib_path, options = {})
         # TODO: this require call should be revised in the future considering security aspects
         require lib_path
-        new_klass = "provider_selection/strategies/#{name.to_s}".classify.constantize
-        @strategies << Strategy.new(name, new_klass)
+        base_klass = "provider_selection/strategies/#{name.to_s}/base".classify.constantize
+        strategy_klass = "provider_selection/strategies/#{name.to_s}/strategy".classify.constantize
+        @strategies << Strategy.new(name, base_klass, strategy_klass)
       end
 
       def find_strategy_by_name(name)
@@ -71,7 +72,8 @@ module ProviderSelection
           score = Match::LOWER_LIMIT
         end
 
-        default_priority_group.matches << Match.new(provider_account, score)
+        default_priority_group.matches << Match.new(:provider_account => provider_account,
+                                                    :score => score)
       end
 
       rank
@@ -89,7 +91,9 @@ module ProviderSelection
 
     def chain_strategy(name, options = {})
       @strategy = self.class.find_strategy_by_name(name)
-      @strategy_chain = @strategy.klass.new(@strategy_chain, options)
+      @strategy_chain = @strategy.strategy_klass.new(@strategy_chain, options) unless @strategy.nil?
+
+      @strategy_chain
     end
 
     private
diff --git a/src/lib/provider_selection/chainable_strategy.rb b/src/lib/provider_selection/chainable_strategy.rb
index 9f3b974..ece0ec6 100644
--- a/src/lib/provider_selection/chainable_strategy.rb
+++ b/src/lib/provider_selection/chainable_strategy.rb
@@ -15,14 +15,19 @@
 #
 
 module ProviderSelection
-
   module ChainableStrategy
 
     module InstanceMethods
 
-      def initialize(strategies, options)
+      def initialize(strategies, options = {})
         @strategies = strategies
-        @options = options
+        options ||= {}
+
+        if self.class.methods.include?(:default_options)
+          @options = self.class.default_options.with_indifferent_access.merge(options)
+        else
+          @options = options
+        end
       end
 
       def method_missing(method, *args)
@@ -31,14 +36,5 @@ module ProviderSelection
 
     end
 
-    module ClassMethods
-
-      def properties
-        @properties || {}
-      end
-
-    end
-
   end
-
 end
diff --git a/src/lib/provider_selection/chainable_strategy_options.rb b/src/lib/provider_selection/chainable_strategy_options.rb
new file mode 100644
index 0000000..d33c6cf
--- /dev/null
+++ b/src/lib/provider_selection/chainable_strategy_options.rb
@@ -0,0 +1,29 @@
+#
+#   Copyright 2012 Red Hat, Inc.
+#
+#   Licensed 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.
+#
+
+module ProviderSelection
+  module ChainableStrategyOptions
+
+    module ClassMethods
+
+      def properties
+        @properties || {}
+      end
+
+    end
+
+  end
+end
diff --git a/src/lib/provider_selection/match.rb b/src/lib/provider_selection/match.rb
index 485bc3a..4cd77c2 100644
--- a/src/lib/provider_selection/match.rb
+++ b/src/lib/provider_selection/match.rb
@@ -24,9 +24,10 @@ module ProviderSelection
     attr_reader :score
     attr_accessor :provider_account
 
-    def initialize(provider_account, score = nil)
-      @provider_account = provider_account
-      @score = score
+    def initialize(attributes)
+      attributes.each do |name, value|
+        instance_variable_set("@#{name}", value)
+      end
     end
 
     def score=(val)
@@ -45,6 +46,16 @@ module ProviderSelection
       end
     end
 
+    def penalize_by(percentage)
+      new_score = calculated_score + ((UPPER_LIMIT - LOWER_LIMIT) * percentage / 100)
+      @score = [(UPPER_LIMIT + 1), new_score].min
+    end
+
+    def reward_by(percentage)
+      new_score = calculated_score - ((UPPER_LIMIT - LOWER_LIMIT) * percentage / 100)
+      @score = [LOWER_LIMIT, new_score].max
+    end
+
   end
 
 end
\ No newline at end of file
diff --git a/src/lib/provider_selection/priority_group.rb b/src/lib/provider_selection/priority_group.rb
index c2a0c0d..4f16df0 100644
--- a/src/lib/provider_selection/priority_group.rb
+++ b/src/lib/provider_selection/priority_group.rb
@@ -21,7 +21,7 @@ module ProviderSelection
     attr_accessor :matches
     attr_accessor :score
 
-    def initialize(score = nil)
+    def initialize(score)
       @matches = []
       @score = score
     end
@@ -39,7 +39,7 @@ module ProviderSelection
       return nil if possible_provider_accounts.empty?
 
       possible_provider_accounts.each do |provider_account|
-        priority_group.matches << Match.new(provider_account)
+        priority_group.matches << Match.new(:provider_account => provider_account)
       end
 
       priority_group
@@ -66,6 +66,10 @@ module ProviderSelection
       nil
     end
 
+    def delete_matches(attribute, values)
+      matches.delete_if{ |match| values.include?(match.send(attribute)) }
+    end
+
   end
 
 end
diff --git a/src/lib/provider_selection/strategy.rb b/src/lib/provider_selection/strategy.rb
index 2706f92..91cd82d 100644
--- a/src/lib/provider_selection/strategy.rb
+++ b/src/lib/provider_selection/strategy.rb
@@ -19,11 +19,13 @@ module ProviderSelection
   class Strategy
 
     attr_reader :name
-    attr_reader :klass
+    attr_reader :base_klass
+    attr_reader :strategy_klass
 
-    def initialize(name, klass)
+    def initialize(name, base_klass, strategy_klass)
       @name = name
-      @klass = klass
+      @base_klass = base_klass
+      @strategy_klass = strategy_klass
     end
 
     def translated_name
diff --git a/src/lib/provider_selection/strategy_options.rb b/src/lib/provider_selection/strategy_options.rb
new file mode 100644
index 0000000..b525321
--- /dev/null
+++ b/src/lib/provider_selection/strategy_options.rb
@@ -0,0 +1,44 @@
+#
+#   Copyright 2012 Red Hat, Inc.
+#
+#   Licensed 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.
+#
+
+module ProviderSelection
+
+  module ChainableStrategyOptions
+
+    module InstanceMethods
+
+      def initialize(strategies, options)
+        @strategies = strategies
+        @options = options
+      end
+
+      def method_missing(method, *args)
+        args.empty? ? @strategies.send(method) : @strategies.send(method, args)
+      end
+
+    end
+
+    module ClassMethods
+
+      def properties
+        @properties || {}
+      end
+
+    end
+
+  end
+
+end
-- 
1.7.11.2




More information about the aeolus-devel mailing list