From: Imre Farkas <ifarkas(a)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