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

Jan Provaznik jprovazn at redhat.com
Fri Jun 1 08:27:47 UTC 2012


On 05/31/2012 08:40 PM, Richard Su wrote:
> 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                           |   94 ++++++++++++++++++++
>   .../controllers/job_scheduler_controller_spec.rb   |   84 +++++++++++++++++
>   8 files changed, 233 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..1050ecd
> --- /dev/null
> +++ b/src/lib/job_scheduler.rb
> @@ -0,0 +1,94 @@
> +#
> +#   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'
> +require 'rufus-scheduler'
> +
> +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

Hi Richard,
based on plans from last week (DC is going to implement some kind of 
Cloud State app), I'm not sure for what purposes we will need rufus 
scheduler? Instances/realms would be potentially handled by the Cloud 
State app (though nothing is confirmed yet), and remaining candidate for 
scheduler was LDAP sync which we finally not gonna do too. Is there some 
other usage of the scheduler?

Jan



More information about the aeolus-devel mailing list