[PATCH conductor 1/2] rufus scheduler integration - RM 3273

Richard Su rwsu at redhat.com
Thu May 31 18:10:28 UTC 2012


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 @@scheduler.nil?
+      @@scheduler = Rufus::Scheduler::PlainScheduler.start_new
+      schedule_tasks(@@scheduler)
+    end
+  end
+
+  def self.stop
+    if @@scheduler
+      @@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




More information about the aeolus-devel mailing list