Note that this is not part of the condor infrastructure -- it's an interim
solution to handle scheduling across providers until the full scheduling
capabilities are put into use with Condor integration.
The full list of provider accounts is filtered by realm, hardware profile, and
image -- so only those accounts that map validly to the "front-end/engine"
realm/hwp/image choices of the user are considered. After this, we filter out
those cloud accounts that do not have the available capacity to schedule the
instance creation request.
As we do not yet have a UI to map images and HWPs from different providers to
the same front-end image or HWP, multi-provider scheduling is only possible
across accounts in the same provider, or across providers after manually
mapping equivalent images and HWPs.
For a simple test case with exactly two providers in the AR database with the
same set of available images and HWPs (this will only be true for two mock
providers, or if you've set up two separate provider objects pointing to the
same driver -- or two drivers pointing to the same cloud impl), the following
should take your separately-mapped resources and map them together on the front
end:
Provider.last.images.each do |image|
if image.aggregator_images[0].provider_images.size < 2
image.aggregator_images[0].delete
image.aggregator_images =
[Provider.first.images.find_by_external_key(image.external_key).aggregator_images[0]]
image.save
end
agg_image = image.aggregator_images[0]
agg_image.name = image.name
agg_image.external_key = image.external_key
agg_image.save
end
Provider.last.hardware_profiles.each do |hardware_profile|
if
hardware_profile.aggregator_hardware_profiles[0].provider_hardware_profiles.size
< 2
hardware_profile.aggregator_hardware_profiles[0].delete
hardware_profile.aggregator_hardware_profiles =
[Provider.first.hardware_profiles.find_by_external_key(hardware_profile.external_key).aggregator_hardware_profiles[0]]
hardware_profile.save
end
agg_hwp = hardware_profile.aggregator_hardware_profiles[0]
agg_hwp.name = hardware_profile.name
agg_hwp.external_key = hardware_profile.external_key
agg_hwp.save
end
Signed-off-by: Scott Seago <[email protected]>
---
src/app/models/instance.rb | 14 +++---
src/app/util/taskomatic.rb | 77 ++++++++++++++++++++++++----------
src/app/views/instance/new.html.erb | 2 +-
3 files changed, 62 insertions(+), 31 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index 21a5cef..56019ff 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -45,8 +45,6 @@ class Instance < ActiveRecord::Base
validates_uniqueness_of :name, :scope => :pool_id
validates_length_of :name, :maximum => 1024
- # FIXME: for now, hardware profile is required, realm is optional, although
for RHEV-M,
- # hardware profile may be optional too
validates_presence_of :hardware_profile_id
validates_presence_of :image_id
@@ -114,11 +112,13 @@ class Instance < ActiveRecord::Base
end
def front_end_realm=(realm_name)
- provider_name, tmpstr =
realm_name.split(Realm::AGGREGATOR_REALM_PROVIDER_DELIMITER,2)
- account_name, realm_name =
tmpstr.split(Realm::AGGREGATOR_REALM_ACCOUNT_DELIMITER,2)
- provider = Provider.find_by_name(provider_name)
- self.cloud_account = provider.cloud_accounts.find_by_username(account_name)
- self.realm = provider.realms.find_by_name(realm_name) unless
realm_name.nil?
+ unless realm_name.nil? or realm_name.empty?
+ provider_name, tmpstr =
realm_name.split(Realm::AGGREGATOR_REALM_PROVIDER_DELIMITER,2)
+ account_name, realm_name =
tmpstr.split(Realm::AGGREGATOR_REALM_ACCOUNT_DELIMITER,2)
+ provider = Provider.find_by_name(provider_name)
+ self.cloud_account =
provider.cloud_accounts.find_by_username(account_name)
+ self.realm = provider.realms.find_by_name(realm_name) unless
realm_name.nil?
+ end
end
# Returns the total time that this instance has been in the state
diff --git a/src/app/util/taskomatic.rb b/src/app/util/taskomatic.rb
index 3277c4d..08da3d2 100644
--- a/src/app/util/taskomatic.rb
+++ b/src/app/util/taskomatic.rb
@@ -50,40 +50,71 @@ class Taskomatic
# can go to state running.
# TODO Modify this to handle generic case for providers
pool = @task.instance.pool
- cloud_account = @task.instance.cloud_account
- [pool, cloud_account].each do |parent|
- quota = parent.quota
- if quota
- if !quota.can_create_instance?(@task.instance) ||
!quota.can_start_instance?(@task.instance)
- @task.state = Task::STATE_FAILED
- @task.instance.state = Instance::STATE_CREATE_FAILED
+ #find matching cloud account
+ if @task.instance.cloud_account
+ cloud_accounts = [[email protected]_account]
+ else
+ # FIXME: this provides a predictable order -- scheduler will eventually
+ # do something entirely different to determine preference
+ cloud_accounts = CloudAccount.find(:all, :order => 'created_at')
+ end
- if parent.class == Pool
- @task.failure_code = Task::FAILURE_OVER_POOL_QUOTA
- elsif parent.class == CloudAccount
- @task.failure_code = Task::FAILURE_OVER_CLOUD_ACCOUNT_QUOTA
- end
+ if @task.instance.image.provider_image?
+ image_providers = Set.new([[email protected]])
+ else
+ image_providers = Set.new(@task.instance.image.provider_images.
+ collect { |image| image.provider})
+ end
- @task.save!
- @task.instance.save!
+ if @task.instance.hardware_profile.provider_hardware_profile?
+ hwp_providers = Set.new([[email protected]_profile])
+ else
+ hwp_providers =
Set.new(@task.instance.hardware_profile.provider_hardware_profiles.
+ collect { |hwp| hwp.provider })
+ end
- return @task
- end
- end
+ matching_providers = hwp_providers & image_providers
+ cloud_accounts.delete_if do |acct|
+ !matching_providers.include?(acct.provider) or
+ (acct.quota and
+ (!acct.quota.can_create_instance?(@task.instance) or
+ !acct.quota.can_start_instance?(@task.instance)))
+ end
+
+ if pool.quota and
+ (!pool.quota.can_create_instance?(@task.instance) or
+ !pool.quota.can_start_instance?(@task.instance))
+ @task.failure_code = Task::FAILURE_OVER_POOL_QUOTA
+ end
+ @task.failure_code = Task::FAILURE_PROVIDER_NOT_FOUND if
cloud_accounts.empty?
+
+ unless @task.failure_code.nil?
+ @task.state = Task::STATE_FAILED
+ @task.instance.state = Instance::STATE_CREATE_FAILED
+ @task.save!
+ @task.instance.save!
+ return @task
end
begin
+ # take first matching cloud account
+ @task.instance.cloud_account = cloud_accounts[0]
client = @task.instance.cloud_account.connect
realm = @task.instance.realm.external_key rescue nil
# Map aggregator HWP/image to back-end provider HWP/image in instance
unless @task.instance.image.provider_image?
- @task.instance.image = @task.instance.image.provider_images[0]
+ @task.instance.image = @task.instance.image.provider_images.
+ find(:first, :conditions => {:provider_id =>
+ @task.instance.cloud_account.provider_id})
end
unless @task.instance.hardware_profile.provider_hardware_profile?
- @task.instance.hardware_profile =
@task.instance.hardware_profile.provider_hardware_profiles[0]
+ @task.instance.hardware_profile = @task.instance.hardware_profile.
+ provider_hardware_profiles.
+ find(:first, :conditions => {:provider_id =>
+ @task.instance.cloud_account.provider_id})
end
@task.state = Task::STATE_PENDING
diff --git a/src/app/views/instance/new.html.erb
b/src/app/views/instance/new.html.erb
index 894d1b6..74096a2 100644
--- a/src/app/views/instance/new.html.erb
+++ b/src/app/views/instance/new.html.erb
@@ -55,7 +55,7 @@
<% end %>
<% if @instance.pool and @instance.pool.realms.size > 0 %>
<li><label>Realm<span>Choose a realm</span></label>
- <%= select("instance", "front_end_realm", @instance.pool.realms, {
:include_blank => false }) %>
+ <%= select("instance", "front_end_realm", @instance.pool.realms, {
:include_blank => true }) %>
</li>
<% end %>
</ul>
--
1.6.2.5
_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel