Aeolus Community Assessment
by Chris Alfonso
Problem Statement:
Aeolus projects upstream community is Red Hat, full stop.
It's probably too easy to get caught up in hand waving and just say "it's important to have a healthy upstream aeolus community." I've been thinking a lot about what the benefits really are to having a "healthy" community, and what it means to be such. I want to keep this real and not go all academic, but I will add references to really smart people's research and perspective to add some sort of credibility (because you guys know I keep booze at my desk and as such might think I've already started the weekend).
/me pours a shot.
Quickly, the value proposition of having a community (Why it matters that we create a community)[1]:
* Security
* Affordability
* Transparency
* Perpetuity
* Interoperablity
* Localization
A thriving, healthy open source community is one that yields the value proposition listed above. Just throwing a license header in project and making it available for the masses to download is not the blueprint to building a community. All this does is make the project source code 'open'. Without a community, there simply is no project [2]. Furthermore, we can formulate how the Aeolus projects reach the mountain-top that is a vibrant open source community - if we agree on the value proposition listed above as the output of a thriving, healthy community.
Typical paths to a successfull community
- Seed the project development[3]
- Get feedback from early and often releases[3]
- Attract users of the software[2]
- Attract developers[2]
- Letting go[2]
We, as a Red Hat sponsored group of hooligans, and I mean that in the most affectionate way possible, have done a tremendous job seeding the aeolus projects. We've created a metric ton of feature and function. So if we've built some pretty cool features...why aren't they coming[5]? It's necessary to address each of the factors at some point, but I'm just going to focus on how we attract users and developers in this mail. I think we need to ask ourselves some tough questions and be honest with our answers.
1. Are we building function and feature that people want (individuals, entreprenuers, enterprises) to use? If so, is the barrier to setup and use aelous low or high?
2. How easy is it for developers to get involved and understand the components involved and then debug, path, contribute changes?
3. Are we doing a good job letting our target users know aeolus exists?
There are plenty more questions we can analyze to come up with a self evaluation, but I think the above 3 are sufficient for this already too long email.
- First, did we build something that is useful, I say yes. However, we built something that is less useful than using most cloud provider management tools directly (because we went for the common denominator feature/api base). There are some scenarios in which aeolus is easy to setup, and there are others that are mindblowingly difficult and confusing. The learning curve for an admin and a user is fairly steep as well. If you don't believe me, you probably didn't hang out in the SA training classes, or you started working on the projects at their inception and have become blind to the complexities, or you've never had the floppyinject-hook have its way with you!
- Second, all aeolus developers are Red Hat folks. There are probably a number of reasons for this: perhaps the components that make up aeolus don't lend themselves well enough to reuse in other projects, they aren't puzzle pieces that can be plugged in to solve any other problem than what we've decided to solve. The design priniciples of each of the projects differ from one another. The languages themselves used between the projects are different. The frameworks used between the projects are different. The protocols used between the projects are different. What we've done is create an enormous learning curve for any developer that dares to take on the challenge of contributing (and they haven't even looked at the development process guidelines at this point).
- Third, we have folks go to a user group here and there, *I think*. Developers aren't good salesmen or ad-men, in general. Since we are not creating a market with aeolus, we are way behind a lot of other projects in this space, we had probably better pony up and do a much better job letting folks know aeolus exists and is here to take down the competition, because we're better than them! We need to get a fleet of folks traveling to trade-shows, meetups, usergroups, conferences. Put together consistent, professional marketing materials and get it in people's faces.
markmc made a few suggestions to address making aeolus components more useful to the masses, and I tend to agree they are great places to start aeolus components without having to setup all the infrastructure.
(1) Credentials delegation plugin for deltacloud
Add a plugin interface to deltacloud which enables credential re-mapping.
Write a plugin which authenticates the incoming user against its own
user DB and grants any valid user access to a configured set of
credentials
The idea here is to allow deltacloud to be used as a proxy by which
someone can share access to a set of credentials with others, without
actually sharing the credentials themselves
(2) Notifications of interesting deltacloud events
Add a plugin interface which is called with details of any interesting
events happening in deltacloud.
Provide plugins for publishing those notifications over Qpid, RabbitMQ,
ZeroMQ, syslog, etc.
The idea here is that the person sharing their credentials can use this
notifications system to do chargeback
(3) Track resource ownership
If user A launches an instance via the credential re-mapping plugin,
then user B should not be able to see the instance or kill it.
Requires the plugin to have a DB which tracks the ownership of instances
(4) Add instance state change event notifications
There should be a way to have a service monitor clouds (via deltacloud)
for the state of an instance and notify you of changes via a message
bus.
Is this external to deltacloud, just polling via deltacloud? If so, what
credentials is it using to do the polling?
Is it part of the credential re-mapping plugin, since that has access to
credentials? But surely this is useful even if you're not using
credential re-mapping? Does it publish these state changes via the same mechanism as
deltacloud's notification system?
(4) Add per-user quotas
The admin sharing a set of credentials should be able to set quotas on
each of the user accounts. This is for safety sake, not as a replacement
for chargeback.
The plugin needs to listen for instance launch notifications and
instance state change notifications in order to update the quota usage
of each user.
(5) Extend (1) to support credentials for multiple drivers/providers
(6) Experiment with ways for deltacloud (via a plugin or driver) to map
incoming requests to one of multiple clouds
(7) Explore using Heat on top of deltacloud
Suggested Actions:
1 - take one some of the suggested architectural changes that make the aeolus components more reusable in projects outside aeolus as a whole
2 - set up a schedule to start marketing the components and aeolus as a whole, go out and get community members instead of waiting for them to show up
If you think this is bonkers or if you have any other opinions on how we can better foster the community, let's hear it.
Thanks,
Chris
[1] http://papers.ssrn.com/sol3/papers.cfm?abstract_id=1656616
[2] http://www.oss-watch.ac.uk/resources/howtobuildcommunity.xml#body.1_div.3
[3] www.feedbooks.com/book/4285.pdf (The Cathedral and the Bazaar)
[4] http://michaeldehaan.net/post/21881841161/my-working-theory-of-open-sourc...
[5] http://en.wikipedia.org/wiki/Field_of_Dreams
11 years, 10 months
[PATCH] adding audrey deployable compatibility test
by Dan Radez
---
src/app/models/deployable.rb | 39 +++++++++++++++++++++++++++++++++++++++
src/config/locales/en.yml | 1 +
2 files changed, 40 insertions(+)
diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb
index 7659688..8682d63 100644
--- a/src/app/models/deployable.rb
+++ b/src/app/models/deployable.rb
@@ -192,6 +192,8 @@ class Deployable < ActiveRecord::Base
deployable_errors << "#{assembly_hash[:name]}: " + I18n.t('deployables.error.attribute_not_exist')
end
assemblies_array << assembly_hash
+ audrey_error = check_audrey_api_compatibility(image, assembly)
+ deployable_errors << "#{assembly_hash[:name]}: " + audrey_error if not audrey_error.nil?
end
[assemblies_array, images, missing_images, deployable_errors]
end
@@ -245,6 +247,43 @@ class Deployable < ActiveRecord::Base
warnings
end
+ def check_audrey_api_compatibility(image, assembly)
+ # get icicle for agent
+ build ||= (image.nil? ? nil : image.latest_pushed_or_unpushed_build)
+ icicle_uuid = build.target_images.first.icicle
+ icicle = Aeolus::Image::Warehouse::Icicle.find(icicle_uuid) if icicle_uuid
+ agent_v = icicle.packages.find_all { |p| p =~ /aeolus-audrey-agent(.*)/ }
+ if not agent_v.empty?
+ agent_v = agent_v.first.split('-')[3]
+ end
+
+ # calculate audrey api version
+ audrey_api_v = if agent_v >= "0.5.0"
+ 1..2
+ elsif agent_v >= "0.4.0"
+ 1..1
+ else 0
+ end
+
+ # initalize compatibility
+ audrey_api_compat = 1
+
+ # do cs_compat
+ ## All agents are compatible with all Config Servers right now
+ ## so no need to check this right now
+ ## this check should call the cs passing the agent_v and validating
+ ## the response the CS sends back
+
+ # audrey api version 2 added service references, lets check for any
+ assembly.services.each do |service|
+ service.parameters.each do |param|
+ audrey_api_compat = 2 if param.reference_service
+ end
+ end
+
+ I18n.t('deployables.error.audrey_api_incompatibility') if (audrey_api_v != 0 and audrey_api_v.include?(audrey_api_compat))
+ end
+
private
def self.apply_search_filter(search)
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 1a1c69e..6900522 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -1008,6 +1008,7 @@ en:
error:
attribute_not_exists: invalid
hwp_not_exists: "Hardware profile %{name} specified in XML doesn't exist."
+ audrey_api_incompatibility: "The deployable uses features not supported by the audrey agent installed in the latest built image."
properties:
edit_deployable_xml: Edit Deployable XML
name: Name
--
1.7.10.2
11 years, 10 months
[PATCH conductor] Refactor SessionEntity model to work properly with API
by Scott Seago
The direct reference to the Session class in SessionEntity was causing
problems for API calls, since the session object wasn't yet in the db
(but the in-memory session_id and session data was there).
On further investigation, it's considered bad design to reference the
session class directly anyway, as it exposes too many impl details
of the session to the other models, even if it did work here.
I've refactored it to reference the session_id string in the SessionEntity
model instead, which appears to work now for both API and Web UI.
---
src/app/controllers/application_controller.rb | 18 ++-----
src/app/models/permissioned_object.rb | 6 +-
src/app/models/session_entity.rb | 13 ++---
src/config/initializers/session.rb | 23 ---------
src/config/initializers/warden.rb | 3 +
...06200000_fix_session_id_for_session_entities.rb | 51 ++++++++++++++++++++
src/spec/models/deployment_spec.rb | 24 +++++----
src/spec/models/permission_spec.rb | 23 +++++----
src/spec/services/registration_service_spec.rb | 5 +-
src/spec/spec_helper.rb | 8 ++--
10 files changed, 99 insertions(+), 75 deletions(-)
delete mode 100644 src/config/initializers/session.rb
create mode 100644 src/db/migrate/20120606200000_fix_session_id_for_session_entities.rb
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb
index 6f280be..aed6b7e 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -179,9 +179,10 @@ class ApplicationController < ActionController::Base
def http_auth_user
return unless request.authorization && request.authorization =~ /^Basic (.*)/m
authenticate!(:scope => :api)
- request.session_options = request.session_options.dup
+ frozen = request.session_options.frozen?
+ request.session_options = request.session_options.dup if frozen
request.session_options[:expire_after] = 2.minutes
- request.session_options.freeze
+ request.session_options.freeze if frozen
# we use :api scope for authentication to avoid saving session.
# But it's handy to set authenticated user in default scope, so we
# can use current_user, instead of current_user(:api)
@@ -190,18 +191,7 @@ class ApplicationController < ActionController::Base
end
def current_session
- @current_session ||= ActiveRecord::SessionStore::Session.
- find_by_session_id(request.session_options[:id])
- # FIXME: I shouldn't have to reload sessions here, but for some reason
- # without reloading it wasn't working for non-admin permissions.
- # If we ever need to add session_entities for _other_ users to the
- # current session, this won't work
- if @current_session and (!(a)current_session.session_entities.any? or
- @current_session.session_entities.first.user != current_user)
- SessionEntity.update_session(@current_session, current_user)
- @current_session.reload
- end
- @current_session
+ @current_session ||= request.session_options[:id]
end
def require_user
diff --git a/src/app/models/permissioned_object.rb b/src/app/models/permissioned_object.rb
index 4f881ee..b657054 100644
--- a/src/app/models/permissioned_object.rb
+++ b/src/app/models/permissioned_object.rb
@@ -26,7 +26,7 @@ module PermissionedObject
privileges.target_type=:target_type and
privileges.action=:action",
{ :user => user.id,
- :session => session.id,
+ :session => session,
:target_type => target_type.name,
:action => action}]).any?
return true
@@ -39,7 +39,7 @@ module PermissionedObject
privileges.target_type=:target_type and
privileges.action=:action",
{ :user => user.id,
- :session => session.id,
+ :session => session,
:target_type => target_type.name,
:action => action}]).any?
end
@@ -129,7 +129,7 @@ module PermissionedObject
privileges.target_type=:target_type and
privileges.action=:action",
{:user => user.id,
- :session => session.id,
+ :session => session,
:target_type => target_type.name,
:action => action})
end
diff --git a/src/app/models/session_entity.rb b/src/app/models/session_entity.rb
index e7bf869..8a0b85a 100644
--- a/src/app/models/session_entity.rb
+++ b/src/app/models/session_entity.rb
@@ -16,7 +16,6 @@
class SessionEntity < ActiveRecord::Base
belongs_to :user
- belongs_to :session, :class_name => "ActiveRecord::SessionStore::Session"
belongs_to :entity
validates_presence_of :user_id
@@ -24,22 +23,22 @@ class SessionEntity < ActiveRecord::Base
validates_presence_of :entity_id
validates_uniqueness_of :entity_id, :scope => [:user_id, :session_id]
- def self.update_session(session, user)
+ def self.update_session(session_id, user)
self.transaction do
# skips callbacks, which should be fine here
- self.delete_all(:session_id => session.id)
- self.add_to_session(session, user)
+ self.delete_all(:session_id => session_id)
+ self.add_to_session(session_id, user)
end
end
- def self.add_to_session(session, user)
+ def self.add_to_session(session_id, user)
return unless user
# create mapping for user-level permissions
- SessionEntity.create!(:session => session, :user => user,
+ SessionEntity.create!(:session_id => session_id, :user => user,
:entity => user.entity)
# create mappings for local groups
user.user_groups.each do |ug|
- SessionEntity.create!(:session => session, :user => user,
+ SessionEntity.create!(:session_id => session_id, :user => user,
:entity => ug.entity)
end
# TODO: add entities for ldap groups
diff --git a/src/config/initializers/session.rb b/src/config/initializers/session.rb
deleted file mode 100644
index 6d82968..0000000
--- a/src/config/initializers/session.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# 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 ActiveRecord
- class SessionStore
- class Session
- has_many :session_entities, :dependent => :destroy
- end
- end
-end
diff --git a/src/config/initializers/warden.rb b/src/config/initializers/warden.rb
index 80751ad..368a9a2 100644
--- a/src/config/initializers/warden.rb
+++ b/src/config/initializers/warden.rb
@@ -81,3 +81,6 @@ Warden::Strategies.add(:ldap) do
u ? success!(u) : fail!("Username or password is not correct - could not log in")
end
end
+Warden::Manager.after_set_user do |user,auth,opts|
+ SessionEntity.update_session(auth.request.session_options[:id], user)
+end
diff --git a/src/db/migrate/20120606200000_fix_session_id_for_session_entities.rb b/src/db/migrate/20120606200000_fix_session_id_for_session_entities.rb
new file mode 100644
index 0000000..908edae
--- /dev/null
+++ b/src/db/migrate/20120606200000_fix_session_id_for_session_entities.rb
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+class FixSessionIdForSessionEntities < ActiveRecord::Migration
+ def self.up
+ rename_column :session_entities, :session_id, :session_db_id
+ add_column :session_entities, :session_id, :string
+ SessionEntity.reset_column_information
+ SessionEntity.all.each do |se|
+ session = ActiveRecord::SessionStore::Session.find(se.session_db_id)
+ if session
+ se.session_id = session.session_id
+ se.save!
+ else
+ se.delete!
+ end
+ end
+ remove_column :session_entities, :session_db_id
+ change_column :session_entities, :session_id, :string, :null => false
+ end
+
+ def self.down
+ add_column :session_entities, :session_db_id, :integer
+ SessionEntity.reset_column_information
+ SessionEntity.each do |se|
+ session = ActiveRecord::SessionStore::Session.find_by_session_id(se.session_id)
+ if session
+ se.session_db_id = session.id
+ se.save!
+ else
+ se.delete!
+ end
+ end
+ remove_column :session_entities, :session_id
+ rename_column :session_entities, :session_db_id, :session_id
+ change_column :session_entities, :session_id, :integer, :null => false
+
+ end
+end
diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb
index 3ffbae9..47e63ef 100644
--- a/src/spec/models/deployment_spec.rb
+++ b/src/spec/models/deployment_spec.rb
@@ -220,14 +220,15 @@ describe Deployment do
@user_for_launch = admin_perms.user
@user_for_launch.quota.maximum_running_instances = 1
@session = FactoryGirl.create :session
- SessionEntity.update_session(@session, @user_for_launch)
+ @session_id = @session.session_id
+ SessionEntity.update_session(@session_id, @user_for_launch)
@deployment.stub(:common_provider_accounts_for).and_return(["test","test"])
end
it "return error when user quota was reached" do
Instance.any_instance.stub(:matches).and_return(["test","test"])
@deployment.stub!(:find_match_with_common_account).and_return([[], true, []])
- errors = @deployment.check_assemblies_matches(@session, @user_for_launch)
+ errors = @deployment.check_assemblies_matches(@session_id, @user_for_launch)
errors.should have(1).items
errors.last.should include I18n.t('instances.errors.user_quota_reached')
end
@@ -246,20 +247,21 @@ describe Deployment do
admin_perms = FactoryGirl.create :admin_permission
@user_for_launch = admin_perms.user
@session = FactoryGirl.create :session
- SessionEntity.update_session(@session, @user_for_launch)
+ @session_id = @session.session_id
+ SessionEntity.update_session(@session_id, @user_for_launch)
end
it "should return errors when checking assemblies matches which are not launchable" do
- @deployment.check_assemblies_matches(@session, @user_for_launch).should be_empty
+ @deployment.check_assemblies_matches(@session_id, @user_for_launch).should be_empty
@deployment.pool.pool_family.provider_accounts.destroy_all
- @deployment.check_assemblies_matches(@session, @user_for_launch).should_not be_empty
+ @deployment.check_assemblies_matches(@session_id, @user_for_launch).should_not be_empty
end
it "should launch instances when launching deployment" do
@deployment.instances.should be_empty
Taskomatic.stub!(:create_instance!).and_return(true)
- @deployment.create_and_launch(@session, @user_for_launch)
+ @deployment.create_and_launch(@session_id, @user_for_launch)
@deployment.errors.should be_empty
@deployment.instances.count.should == 2
end
@@ -272,7 +274,7 @@ describe Deployment do
Taskomatic.stub!(:create_dcloud_instance).and_return(true)
Taskomatic.stub!(:handle_dcloud_error).and_return(true)
Taskomatic.stub!(:handle_instance_state).and_return(true)
- @deployment.create_and_launch(@session, @user_for_launch)
+ @deployment.create_and_launch(@session_id, @user_for_launch)
@deployment.errors.should be_empty
@deployment.reload
@deployment.instances.count.should == 2
@@ -281,7 +283,7 @@ describe Deployment do
@provider_account1.priority = 30
@provider_account1.save!
deployment2 = Factory.create(:deployment, :pool_id => @pool.id)
- deployment2.create_and_launch(@session, @user_for_launch)
+ deployment2.create_and_launch(@session_id, @user_for_launch)
deployment2.errors.should be_empty
deployment2.reload
deployment2.instances.count.should == 2
@@ -300,7 +302,7 @@ describe Deployment do
Taskomatic.stub!(:create_dcloud_instance).and_return(true)
Taskomatic.stub!(:handle_dcloud_error).and_return(true)
Taskomatic.stub!(:handle_instance_state).and_return(true)
- @deployment.create_and_launch(@session, @user_for_launch)
+ @deployment.create_and_launch(@session_id, @user_for_launch)
@deployment.errors.should be_empty
@deployment.reload
@deployment.instances.count.should == 2
@@ -312,7 +314,7 @@ describe Deployment do
@deployment.instances.should be_empty
@deployment.pool.pool_family.provider_accounts.destroy_all
Taskomatic.stub!(:create_instance!).and_return(true)
- @deployment.create_and_launch(@session, @user_for_launch)
+ @deployment.create_and_launch(@session_id, @user_for_launch)
@deployment.errors.should_not be_empty
lambda { Deployment.find((a)deployment.id) }.should raise_error(ActiveRecord::RecordNotFound)
end
@@ -325,7 +327,7 @@ describe Deployment do
it "should set create_failed status for instances if instance's launch raises an exception" do
@deployment.instances.should be_empty
Taskomatic.stub!(:create_dcloud_instance).and_raise("an exception")
- @deployment.create_and_launch(@session, @user_for_launch)
+ @deployment.create_and_launch(@session_id, @user_for_launch)
@deployment.reload
@deployment.instances.should_not be_empty
@deployment.instances.each {|i| i.state.should == Instance::STATE_CREATE_FAILED}
diff --git a/src/spec/models/permission_spec.rb b/src/spec/models/permission_spec.rb
index ce92bd6..7f05587 100644
--- a/src/spec/models/permission_spec.rb
+++ b/src/spec/models/permission_spec.rb
@@ -32,53 +32,54 @@ describe Permission do
@provider = @provider_admin_permission.provider
@pool = @pool_user_permission.pool
@session = FactoryGirl.create :session
- SessionEntity.update_session(@session, @admin)
- SessionEntity.add_to_session(@session, @provider_admin)
- SessionEntity.add_to_session(@session, @pool_user)
+ @session_id = @session.session_id
+ SessionEntity.update_session(@session_id, @admin)
+ SessionEntity.add_to_session(@session_id, @provider_admin)
+ SessionEntity.add_to_session(@session_id, @pool_user)
end
it "Admin should be able to create users" do
- BasePermissionObject.general_permission_scope.has_privilege(@session,
+ BasePermissionObject.general_permission_scope.has_privilege(@session_id,
@admin,
Privilege::CREATE,
User).should be_true
end
it "Provider Admin should NOT be able to create users" do
- BasePermissionObject.general_permission_scope.has_privilege(@session,
+ BasePermissionObject.general_permission_scope.has_privilege(@session_id,
@provider_admin,
Privilege::CREATE,
User).should be_false
end
it "Pool User should NOT be able to create users" do
- BasePermissionObject.general_permission_scope.has_privilege(@session,
+ BasePermissionObject.general_permission_scope.has_privilege(@session_id,
@pool_user,
Privilege::CREATE,
User).should be_false
end
it "Provider Admin should be able to edit provider" do
- @provider.has_privilege(@session, @provider_admin,
+ @provider.has_privilege(@session_id, @provider_admin,
Privilege::MODIFY).should be_true
end
it "Admin should be able to edit provider" do
- @provider.has_privilege(@session, @admin, Privilege::MODIFY).should be_true
+ @provider.has_privilege(@session_id, @admin, Privilege::MODIFY).should be_true
end
it "Pool User should NOT be able to edit provider" do
- @provider.has_privilege(@session, @pool_user,
+ @provider.has_privilege(@session_id, @pool_user,
Privilege::MODIFY).should be_false
end
it "Pool User should be able to create instances in @pool" do
- @pool.has_privilege(@session, @pool_user,
+ @pool.has_privilege(@session_id, @pool_user,
Privilege::CREATE, Instance).should be_true
end
it "Pool User should NOT be able to create instances in another pool" do
- FactoryGirl.create(:tpool).has_privilege(@session, @pool_user,
+ FactoryGirl.create(:tpool).has_privilege(@session_id, @pool_user,
Privilege::CREATE, Instance).
should be_false
end
diff --git a/src/spec/services/registration_service_spec.rb b/src/spec/services/registration_service_spec.rb
index b7c33cc..76c2544 100644
--- a/src/spec/services/registration_service_spec.rb
+++ b/src/spec/services/registration_service_spec.rb
@@ -38,7 +38,8 @@ describe RegistrationService do
it "should register a user with default pool/quota/role perms when default settings set" do
@user = FactoryGirl.create :user
@session = FactoryGirl.create :session
- SessionEntity.update_session(@session, @user)
+ @session_id = @session.session_id
+ SessionEntity.update_session(@session_id, @user)
@pool = MetadataObject.lookup("self_service_default_pool")
@role = MetadataObject.lookup("self_service_default_role")
@quota = FactoryGirl.create :quota
@@ -47,7 +48,7 @@ describe RegistrationService do
@registration_service = RegistrationService.new(@user)
@registration_service.save
- @pools = Pool.list_for_user(@session, @user, Privilege::CREATE, Instance)
+ @pools = Pool.list_for_user(@session_id, @user, Privilege::CREATE, Instance)
@pools.length.should == 1
@pools[0].name.should == "Default"
diff --git a/src/spec/spec_helper.rb b/src/spec/spec_helper.rb
index 372d7b7..cc97efb 100644
--- a/src/spec/spec_helper.rb
+++ b/src/spec/spec_helper.rb
@@ -56,11 +56,11 @@ def mock_warden(user)
:authenticate! => user,
:user => user,
:raw_session => nil)
- request.session_options[:id] = 'ee73441902cb9445483e498cb05dc398'
- @session = ActiveRecord::SessionStore::Session.
- find_by_session_id('ee73441902cb9445483e498cb05dc398')
+ @session_id = 'ee73441902cb9445483e498cb05dc398'
+ request.session_options[:id] = @session_id
+ @session = ActiveRecord::SessionStore::Session.find_by_session_id(@session_id)
@session = FactoryGirl.create :session unless @session
- SessionEntity.update_session(@session, user) if user
+ SessionEntity.update_session(@session_id, user) if user
end
RSpec.configure do |config|
--
1.7.6.5
11 years, 10 months
Re: [PATCH conductor] RM 3317 - SysV init for conductor-delayed_job service
by Richard Su
On 06/06/2012 02:20 PM, John Eckersberg wrote:
> On Wed, 06 Jun 2012 16:20:17 -0400, John Eckersberg<jeckersb(a)redhat.com> wrote:
>> On Wed, 6 Jun 2012 12:51:25 -0700, Richard Su<rwsu(a)redhat.com> wrote:
>>> We support systems that are not systemd aware. Resurrected the old
>>> SysV init script to support those systems.
>>>
>>> Modified conductor spec file to install either the systemd or SysV
>>> init configuration files depending on what the os supports.
>>> ---
>>> aeolus-conductor.spec.in | 31 +++++++++++++++++-
>>> conf/conductor-delayed_job | 77 ++++++++++++++++++++++++++++++++++++++++++++
>>> 2 files changed, 107 insertions(+), 1 deletions(-)
>>> create mode 100755 conf/conductor-delayed_job
>>>
>>> diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in
>>> index 4c5aad5..9bee661 100644
>>> --- a/aeolus-conductor.spec.in
>>> +++ b/aeolus-conductor.spec.in
>>> @@ -9,6 +9,12 @@
>>> %global rubyabi 1.8
>>> %endif
>>>
>>> +%if %((test -d /etc/systemd&& echo 1) || echo 0)
>>> +%global systemd 1
>>> +%else
>>> +%global systemd 0
>>> +%endif
>>> +
>> The alarms in my head say this might not work depending on what context
>> you're building in. I'm not so sure you're going to have /etc/systemd
>> present in the buildroot for all systemd-enabled targets under mock (and
>> therefor in koji and brew). You may be better off conditionalizing this
>> using %{?fedora} and %{?rhel} and checking versions that way.
>>
>> /me goes off to look into that...
> Verified, at least in a clean mock root for fedora-16-x86_64:
>
> [jeckersb@baozi ~]$ test -d /var/lib/mock/fedora-16-x86_64/root/etc/systemd
> [jeckersb@baozi ~]$ echo $?
> 1
>
> So you won't use the systemd service unit on f16, even though it is
> supported.
Good catch. I will send a updated patch to use version numbers.
11 years, 10 months
[PATCH conductor] Fixed deployment rollback
by Jan Provazník
From: Jan Provaznik <jprovazn(a)redhat.com>
When rollback was initiated, 'stop' request was sent to instances
in 'pending' state too. But it seems that 'stop' is not valid action
for 'pending' state. Now we wait until pending instances are running
and send 'stop' request then.
This is fix for already pushed task:
https://www.aeolusproject.org/redmine/issues/3320
---
src/app/models/deployment.rb | 14 +++++++++-----
src/app/models/instance.rb | 1 +
src/app/models/instance_observer.rb | 2 +-
src/spec/models/deployment_spec.rb | 2 ++
4 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb
index 0cf1137..7b66e56 100644
--- a/src/app/models/deployment.rb
+++ b/src/app/models/deployment.rb
@@ -654,6 +654,8 @@ class Deployment < ActiveRecord::Base
if Instance::ACTIVE_FAILED_STATES.include?(instance.state)
# if this instance stop failed, whole deployment rollback failed
self.state = STATE_ROLLBACK_FAILED
+ elsif instance.state == Instance::STATE_RUNNING
+ deployment_rollback
elsif instances.all? {|i| i.inactive?}
# some other instances might be failed (because their
# launch failed), but it shouldn't be a problem if all
@@ -663,17 +665,19 @@ class Deployment < ActiveRecord::Base
end
def deployment_rollback
- stoppable_instances = instances.stoppable
- if stoppable_instances.empty?
+ unless self.state == STATE_ROLLBACK_IN_PROGRESS
+ self.state = STATE_ROLLBACK_IN_PROGRESS
+ save!
+ end
+
+ if instances.all? {|i| i.inactive?}
self.state = STATE_ROLLBACK_COMPLETE
save!
return
end
- self.state = STATE_ROLLBACK_IN_PROGRESS
- save!
error_occured = false
- stoppable_instances.each do |instance|
+ instances.running.each do |instance|
begin
instance.stop(nil)
rescue
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index aee01a1..3806d16 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -128,6 +128,7 @@ class Instance < ActiveRecord::Base
scope :deployed, :conditions => { :state => [STATE_RUNNING, STATE_SHUTTING_DOWN] }
# FIXME: "pending" is misleading as it doesn't just cover STATE_PENDING
scope :pending, :conditions => { :state => [STATE_NEW, STATE_PENDING] }
+ scope :running, :conditions => { :state => [STATE_RUNNING] }
scope :pending_or_deployed, :conditions => { :state => [STATE_NEW, STATE_PENDING, STATE_RUNNING, STATE_SHUTTING_DOWN] }
# FIXME: "failed" is misleading too...
scope :failed, :conditions => { :state => FAILED_STATES }
diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb
index 77b2e12..d42fbe6 100644
--- a/src/app/models/instance_observer.rb
+++ b/src/app/models/instance_observer.rb
@@ -95,7 +95,6 @@ class InstanceObserver < ActiveRecord::Observer
# This can get stale, so reload it -- if it exists
instance.deployment.reload if instance.deployment
if instance.state_changed?
- instance.deployment.update_state(instance) if instance.deployment
event = Event.new(:source => instance, :event_time => DateTime.now,
:summary => "state changed to #{instance.state}",
:change_hash => instance.changes, :status_code => instance.state)
@@ -126,6 +125,7 @@ class InstanceObserver < ActiveRecord::Observer
:status_code => 'vanished', :summary => "Instance disappeared from cloud provider"
)
end
+ instance.deployment.update_state(instance) if instance.deployment
end
end
diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb
index 3ffbae9..48df0ad 100644
--- a/src/spec/models/deployment_spec.rb
+++ b/src/spec/models/deployment_spec.rb
@@ -428,6 +428,8 @@ describe Deployment do
end
it "should stop all running instances if an instance fails" do
+ @inst1.state = Instance::STATE_RUNNING
+ @inst1.save!
Instance.any_instance.stub(:stop).and_return(true)
Instance.any_instance.should_receive(:stop)
@inst2.state = Instance::STATE_ERROR
--
1.7.7.6
11 years, 10 months
[PATCH conductor] fix API bug introduced by user groups commit
by Scott Seago
The user groups commit introduced a bug in http auth for the Conductor API
where we froze a hash that shouldn't have been frozen.
With this commit we only duplicate and re-freeze if it's frozen to start with.
---
src/app/controllers/application_controller.rb | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb
index 6f280be..559e127 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -179,9 +179,10 @@ class ApplicationController < ActionController::Base
def http_auth_user
return unless request.authorization && request.authorization =~ /^Basic (.*)/m
authenticate!(:scope => :api)
- request.session_options = request.session_options.dup
+ frozen = request.session_options.frozen?
+ request.session_options = request.session_options.dup if frozen
request.session_options[:expire_after] = 2.minutes
- request.session_options.freeze
+ request.session_options.freeze if frozen
# we use :api scope for authentication to avoid saving session.
# But it's handy to set authenticated user in default scope, so we
# can use current_user, instead of current_user(:api)
--
1.7.6.5
11 years, 10 months
[ANNOUNCE] Merged "gelato" into "master" (again)
by Jirka Tomasek
Hi all,
I merged the "gelato" branch into "master". Gelato branch introduces
converge-ui git submodule into src/vendor/converge-ui. This repository
includes common UI parts for Conductor and Katello. To make the
submodule work for the first time, it's necessary to run
git submodule init
followed by
git submodule update
which will clone the converge-ui repo into src/vendor/converge-ui (note
that you have to run these commands from the top level of the working
tree).
more info is described here: https://github.com/Katello/converge-ui-example
If you get something like LoadError (Missing helper file
helpers/layout_helper.rb), It means that you don't have submodule
present and the simlinks leading to it don't work. (Run the commands
described above)
It also brings new gem dependencies: rubygem-compass and
rubygem-compass-960-plugin.
Jirka
11 years, 10 months
[PATCH conductor] Fix the new Provider Account form error
by Jirka Tomasek
From: Jiri Tomasek <jtomasek(a)redhat.com>
---
src/app/models/credential.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/app/models/credential.rb b/src/app/models/credential.rb
index a52319c..bd72783 100644
--- a/src/app/models/credential.rb
+++ b/src/app/models/credential.rb
@@ -36,5 +36,5 @@ class Credential < ActiveRecord::Base
validates_uniqueness_of :credential_definition_id, :scope => :provider_account_id
attr_protected :id, :provider_account_id, :created_at
- attr_accessible :value, :credential_definition_id
+ attr_accessible :value, :credential_definition_id, :credential_definition
end
--
1.7.7.6
11 years, 10 months