https://www.aeolusproject.org/redmine/issues/3273
REST api to turn the rufus scheduler on (:new) and off (:destroy)
and to check its status (:index).
A singleton class JobScheduler encapsulates the rufus scheduler
so that only a single scheduler instance runs at any time.
Only users who have the ROLE view and modify permissions may
control the scheduler.
---
aeolus-conductor.spec.in | 2 +
src/app/controllers/job_scheduler_controller.rb | 45 ++++++++++
src/app/views/job_scheduler/destroy.xml.haml | 2 +
src/app/views/job_scheduler/index.xml.haml | 2 +
src/app/views/job_scheduler/new.xml.haml | 2 +
src/config/routes.rb | 2 +
src/lib/job_scheduler.rb | 93 ++++++++++++++++++++
.../controllers/job_scheduler_controller_spec.rb | 84 ++++++++++++++++++
8 files changed, 232 insertions(+), 0 deletions(-)
create mode 100644 src/app/controllers/job_scheduler_controller.rb
create mode 100644 src/app/views/job_scheduler/destroy.xml.haml
create mode 100644 src/app/views/job_scheduler/index.xml.haml
create mode 100644 src/app/views/job_scheduler/new.xml.haml
create mode 100644 src/lib/job_scheduler.rb
create mode 100644 src/spec/controllers/job_scheduler_controller_spec.rb
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in
index a40d517..6cca32f 100644
--- a/aeolus-conductor.spec.in
+++ b/aeolus-conductor.spec.in
@@ -47,6 +47,7 @@ Requires: rubygem(oauth)
Requires: rubygem(rake)
Requires: rubygem(delayed_job) >= 2.1.4
Requires: rubygem(paranoia)
+Requires: rubygem(rufus-scheduler)
Requires: postgresql
Requires: postgresql-server
Requires: system-logos
@@ -189,6 +190,7 @@ haml="app/views/hardware_profiles app/views/realm_mappings \
app/views/deployables app/views/catalogs \
app/views/provider_types app/views/api/images \
app/views/config_servers app/views/provider_realms \
+ app/views/job_scheduler \
app/views/logs \
app/views/api/hooks \
app/views/api \
diff --git a/src/app/controllers/job_scheduler_controller.rb
b/src/app/controllers/job_scheduler_controller.rb
new file mode 100644
index 0000000..b1a2701
--- /dev/null
+++ b/src/app/controllers/job_scheduler_controller.rb
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+
+require 'job_scheduler'
+
+class JobSchedulerController < ApplicationController
+ before_filter :require_user_api
+ respond_to :xml
+ layout :false
+
+ # GET /jobscheduler
+ # GET /jobscheduler.xml
+ def index
+ require_privilege(Privilege::PERM_VIEW)
+ respond_with(JobScheduler.activated?)
+ end
+
+ # GET /jobscheduler/new
+ # GET /jobscheduler/new.xml
+ def new
+ require_privilege(Privilege::PERM_SET)
+ respond_with(JobScheduler.start)
+ end
+
+ # DELETE /jobscheduler/1
+ # DELETE /jobscheduler/1.xml
+ def destroy
+ require_privilege(Privilege::PERM_SET)
+ respond_with(JobScheduler.stop)
+ end
+
+end
diff --git a/src/app/views/job_scheduler/destroy.xml.haml
b/src/app/views/job_scheduler/destroy.xml.haml
new file mode 100644
index 0000000..18e796d
--- /dev/null
+++ b/src/app/views/job_scheduler/destroy.xml.haml
@@ -0,0 +1,2 @@
+!!! XML
+%activated=JobScheduler.activated?
\ No newline at end of file
diff --git a/src/app/views/job_scheduler/index.xml.haml
b/src/app/views/job_scheduler/index.xml.haml
new file mode 100644
index 0000000..b5c75d6
--- /dev/null
+++ b/src/app/views/job_scheduler/index.xml.haml
@@ -0,0 +1,2 @@
+!!! XML
+%activated=JobScheduler.activated?
diff --git a/src/app/views/job_scheduler/new.xml.haml
b/src/app/views/job_scheduler/new.xml.haml
new file mode 100644
index 0000000..18e796d
--- /dev/null
+++ b/src/app/views/job_scheduler/new.xml.haml
@@ -0,0 +1,2 @@
+!!! XML
+%activated=JobScheduler.activated?
\ No newline at end of file
diff --git a/src/config/routes.rb b/src/config/routes.rb
index 265f752..518b013 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -238,6 +238,8 @@ Conductor::Application.routes.draw do
resources :provider_images
end
+ resources :job_scheduler, :only => [:index, :new, :destroy]
+
get 'api', :controller => 'api/entrypoint', :action =>
'index'
namespace :api do
resources :images do
diff --git a/src/lib/job_scheduler.rb b/src/lib/job_scheduler.rb
new file mode 100644
index 0000000..f30ff2d
--- /dev/null
+++ b/src/lib/job_scheduler.rb
@@ -0,0 +1,93 @@
+#
+# 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.
+#
+
+require 'curb'
+
+class JobScheduler
+
+ @@scheduler = nil
+
+ def self.initialize
+ self.start
+ end
+
+ def self.start
+ if @(a)scheduler.nil?
+ @@scheduler = Rufus::Scheduler::PlainScheduler.start_new
+ schedule_tasks(@@scheduler)
+ end
+ end
+
+ def self.stop
+ if @@scheduler
+ @(a)scheduler.stop
+ @@scheduler = nil
+ end
+ end
+
+ def self.activated?
+ if @@scheduler
+ true
+ else
+ false
+ end
+ end
+
+ def self.status_via_http(login, password, hostname)
+ curl = self.curl_request(login, password)
+ curl.url = job_scheduler_url(hostname, '')
+ curl.http_get
+ curl.body_str.to_s
+ end
+
+ def self.start_via_http(login, password, hostname)
+ curl = self.curl_request(login, password)
+ curl.url = job_scheduler_url(hostname, 'new')
+ curl.http_get
+ curl.body_str.to_s
+ end
+
+ def self.stop_via_http(login, password, hostname)
+ curl = self.curl_request(login, password)
+ curl.url = job_scheduler_url(hostname, '1')
+ curl.http_delete
+ curl.body_str.to_s
+ end
+
+ private
+
+ def self.schedule_tasks(scheduler)
+ scheduler.every("1m") do
+ puts "job scheduler is running"
+ end
+ end
+
+ def self.job_scheduler_url(hostname, suffix)
+ # TODO: is there a better way to generate this url?
+ url =
"https://#{hostname}/conductor/#{JobSchedulerController.controller_path}/#{suffix}"
+ end
+
+ def self.curl_request(login, password)
+ curl = Curl::Easy.new
+ curl.username = login
+ curl.password = password
+ curl.headers['HTTP_ACCEPT'] = 'application/xml'
+ curl.headers['CONTENT_TYPE'] = 'application/xml'
+ curl.http_auth_types = :basic
+ return curl
+ end
+
+end
diff --git a/src/spec/controllers/job_scheduler_controller_spec.rb
b/src/spec/controllers/job_scheduler_controller_spec.rb
new file mode 100644
index 0000000..75726ec
--- /dev/null
+++ b/src/spec/controllers/job_scheduler_controller_spec.rb
@@ -0,0 +1,84 @@
+#
+# 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.
+#
+
+require 'spec_helper'
+
+describe JobSchedulerController do
+ render_views
+
+ context "when authenticated as admin" do
+
+ before(:each) do
+ @admin_permission = FactoryGirl.create :admin_permission
+ @admin = @admin_permission.user
+ mock_warden(@admin)
+ end
+
+ describe "scheduler controls" do
+
+ it "scheduler status from 'GET index'" do
+ send_and_accept_xml
+ get :index
+ response.should be_success
+ response.body.strip.should ==
"<activated>false</activated>"
+ end
+
+ it "turn on scheduler by 'GET new'" do
+ send_and_accept_xml
+ get :new
+ response.should be_success
+ response.body.strip.should ==
"<activated>true</activated>"
+ end
+
+ it "turn off scheduler by 'POST destroy'" do
+ send_and_accept_xml
+ post :destroy, :id => 1
+ response.should be_success
+ response.body.strip.should ==
"<activated>false</activated>"
+ end
+
+ it "turn scheduler on and then off" do
+ send_and_accept_xml
+ get :index
+ response.should be_success
+ response.body.strip.should ==
"<activated>false</activated>"
+ get :new
+ response.should be_success
+ response.body.strip.should ==
"<activated>true</activated>"
+ post :destroy, :id => 1
+ response.should be_success
+ response.body.strip.should ==
"<activated>false</activated>"
+ end
+ end
+ end
+
+ context "when not authenticated as admin" do
+
+ before(:each) do
+ @non_admin_permission = FactoryGirl.create :pool_user_permission
+ @user = @non_admin_permission.user
+ mock_warden(@user)
+ end
+
+ it "requests should be denied" do
+ send_and_accept_xml
+ get :index
+ response.should_not be_success
+ end
+
+ end
+
+end
--
1.7.7.6