Commit 99af00cb authored by Cool Fire's avatar Cool Fire

Added job requesting and mailer for notifications of pending jobs.

parent d793312f
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
// Place all the styles related to the jobrequests controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
class ApiController < ApplicationController class ApiController < ApplicationController
skip_before_filter :verify_authenticity_token, only: [:index] include JobsHelper
include JobrequestsHelper
skip_before_filter :verify_authenticity_token, only: [:index, :jobrequest]
def index def index
@result = update_job(params) @result = update_job(params)
end end
private def jobrequest
def command_params @result = ""
params.require(:job_update).permit(:id, :timestamp, :exitcode, :message, :key)
end
def update_job(j) # Check if this needs to be a request or if it can be done directly
# Check key if(autorun(params[:command]))
config = loadconfig() @job = Job.new()
if(config['api_pass'] != j[:key]) @job.server_id = Server.find_by_shortname(params[:server_id]).id
return "Invalid key" @job.command_id = Command.find_by_command(params[:command_id]).id
end @job.args = params[:args]
@job.state = 2
@job.result = "Waiting for results"
@job.timestampstarted = DateTime.now
@job.save
# Get job # Fire job into rabbitmq
job = Job.find(j[:id]) queue_job(@job)
@result = "Job is being executed"
else
# Make jobrequest
@jobr = Jobrequest.new()
@jobr.server_id = Server.find_by_shortname(params[:server_id]).id
@jobr.command_id = Command.find_by_command(params[:command_id]).id
@jobr.args = params[:args]
@jobr.state = 2
@jobr.result = "Waiting for approval"
@jobr.timestampstarted = DateTime.now
@jobr.user = params[:user]
@jobr.email = params[:email]
@jobr.save
# Update values # Send notifivation to admin there is a pending job
job.timestampcompleted = j[:timestamp] JobwaitingMailer.jobwaiting(@jobr).deliver
job.state = j[:exitcode]
job.result = j[:message] @result = "Job is pending approval"
job.save end
end end
end end
class JobrequestsController < ApplicationController
def index
@jobrequests = Jobrequest.all
end
def show
begin
@job = Jobrequest.find(params[:id])
rescue => e
flash[:error] = "No jobrequest with that ID."
redirect_to jobrequests_path
end
end
end
class JobsController < ApplicationController class JobsController < ApplicationController
include JobsHelper
def index def index
@jobs = Job.all @jobs = Job.all
end end
...@@ -57,47 +58,4 @@ class JobsController < ApplicationController ...@@ -57,47 +58,4 @@ class JobsController < ApplicationController
redirect_to jobs_path redirect_to jobs_path
end end
end end
private
# Function to submit jobs to the queue
def queue_job(job)
# Load configuration
config = loadconfig()
# Read encryption key
private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
# Establish connection to RabbitMQ
conn = Bunny.new(
:host => config['host'],
:user => config['user'],
:password => config['pass'],
)
conn.start
ch = conn.create_channel
q = ch.queue(job.server.shortname)
# Build message
message = JSON.generate({
:id => job.id,
:timestamp => job.timestampstarted,
:command => job.command.command,
:args => job.args
})
# Encrypt message
if(message.length > 501)
raise "String too long to encrypt."
end
string = private_key.private_encrypt(message)
# Send message to the queue
ch.default_exchange.publish(string, :routing_key => q.name)
conn.close
end
end end
module JobrequestsHelper
# List of jobs that do not require admin approval
# Values of key-value pair are for future use
def autorun(j)
autorun_jobs = {
'httpd_public_html_enable' => '',
'httpd_public_html_disable' => '',
'httpd_cgi-bin_enable' => '',
'httpd_chi-bin_disable' => '',
'httpd_logs_enable' => '',
'httpd_logs_disable' => ''
}
return autorun_jobs.has_key? j
end
def update_job(j)
# Check key
config = loadconfig()
if(config['api_pass'] != j[:key])
return "Invalid key"
end
# Get job
job = Job.find(j[:id])
# Update values
job.timestampcompleted = j[:timestamp]
job.state = j[:exitcode]
job.result = j[:message]
job.save
end
end
module JobsHelper module JobsHelper
# Function to submit jobs to the queue
def queue_job(job)
# Load configuration
config = loadconfig()
# Read encryption key
private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
# Establish connection to RabbitMQ
conn = Bunny.new(
:host => config['host'],
:user => config['user'],
:password => config['pass'],
)
conn.start
ch = conn.create_channel
q = ch.queue(job.server.shortname)
# Build message
message = JSON.generate({
:id => job.id,
:timestamp => job.timestampstarted,
:command => job.command.command,
:args => job.args
})
# Encrypt message
if(message.length > 501)
raise "String too long to encrypt."
end
string = private_key.private_encrypt(message)
# Send message to the queue
ch.default_exchange.publish(string, :routing_key => q.name)
conn.close
end
end end
class JobwaitingMailer < ActionMailer::Base
default from: 'no-reply@insomnia247.nl'
def jobwaiting(jobrequest)
@jobrequest = jobrequest
mail :to => @jobrequest.email, :subject => "New pending job for #{@jobrequest.user}"
end
end
class Command < ActiveRecord::Base class Command < ActiveRecord::Base
has_many :jobs has_many :jobs
has_many :jobrequests
end end
class Jobrequest < ActiveRecord::Base
belongs_to :server
belongs_to :command
end
class Server < ActiveRecord::Base class Server < ActiveRecord::Base
has_many :jobs has_many :jobs
has_many :jobrequests
end end
<%= @result.inspect %>
\ No newline at end of file
<div class='pagetitle'>
Job requests
</div>
<div class='list'>
<table>
<tr class='listtiles'>
<td>Job ID</td>
<td>User</td>
<td>E-mail</td>
<td>Requested</td>
<td>Processed</td>
<td>Server</td>
<td>Command</td>
<td>Arguments</td>
<td>Status</td>
</tr>
<% @jobrequests.reverse.each do |job| %>
<tr class='jobstatus<%= job.state %>'>
<td><%= job.id %></td>
<td><%= job.user %></td>
<td><%= job.email %></td>
<td><%= showtime(job.timestampstarted) %></td>
<td><%= showtime(job.timestampcompleted) %></td>
<td><%= link_to job.server.shortname, server_path(job.server) %></td>
<td><%= link_to job.command.name, job_path(job) %></td>
<td><%= job.args %></td>
<td><%= job.result %></td>
</tr>
<% end %>
</table>
</div>
\ No newline at end of file
<div class='pagetitle'>
Jobrequest: <%= @job.id %>
</div>
<div class='form'>
<table>
<tr>
<td>Id</td>
<td><%= @job.id %></td>
</tr>
<tr>
<td>User</td>
<td><%= @job.user %></td>
</tr>
<tr>
<td>E-mail address </td>
<td><%= @job.email %></td>
</tr>
<tr>
<td>Server</td>
<td><%= @job.server.shortname %></td>
</tr>
<tr>
<td>Command</td>
<td><%= @job.command.name %></td>
</tr>
<tr>
<td>Arguments</td>
<td><%= @job.args %></td>
</tr>
<tr>
<td>State id</td>
<td><%= @job.state %></td>
</tr>
<tr>
<td>Status</td>
<td><%= @job.result %></td>
</tr>
<tr>
<td>Request time</td>
<td><%= showtime(@job.timestampstarted) %></td>
</tr>
<tr>
<td>Processed time</td>
<td><%= showtime(@job.timestampcompleted) %></td>
</tr>
</table>
</div>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta content='text/html, charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<p>
New job is pending approval.
</p>
<p>
<table>
<tr>
<td>User</td>
<td><%= @jobrequest.user %></td>
</tr>
<tr>
<td>Command</td>
<td><%= @jobrequest.command.name %></td>
</tr>
<tr>
<td>Arguments</td>
<td><%= @jobrequest.args %></td>
</tr>
</table>
</p>
</body>
</html>
\ No newline at end of file
...@@ -4,6 +4,15 @@ require File.expand_path('../application', __FILE__) ...@@ -4,6 +4,15 @@ require File.expand_path('../application', __FILE__)
# Initialize the Rails application. # Initialize the Rails application.
Rails.application.initialize! Rails.application.initialize!
# Mail stuff
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => 'smtp.ziggozakelijk.nl',
:port => '25',
:domain => 'insomnia247.nl',
:authentication => 'none'
}
# Show time just the way we like it # Show time just the way we like it
def showtime(timestamp) def showtime(timestamp)
timestamp ? Time.at(timestamp).strftime('%F %T') : "-" timestamp ? Time.at(timestamp).strftime('%F %T') : "-"
......
Rails.application.routes.draw do Rails.application.routes.draw do
get 'jobrequests/index'
get 'api/jobrequest'
post 'api/jobrequest'
get 'api/index' get 'api/index'
post 'api/index' post 'api/index'
resources :commands, :servers, :jobs resources :commands, :servers, :jobs, :jobrequests
root to: 'login#index' root to: 'login#index'
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140718230625) do ActiveRecord::Schema.define(version: 20140719163052) do
create_table "commands", force: true do |t| create_table "commands", force: true do |t|
t.string "name" t.string "name"
...@@ -22,6 +22,20 @@ ActiveRecord::Schema.define(version: 20140718230625) do ...@@ -22,6 +22,20 @@ ActiveRecord::Schema.define(version: 20140718230625) do
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "jobrequests", force: true do |t|
t.integer "state"
t.string "result"
t.integer "timestampstarted"
t.integer "timestampcompleted"
t.integer "command_id"
t.integer "server_id"
t.string "args"
t.string "user"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "jobs", force: true do |t| create_table "jobs", force: true do |t|
t.integer "state" t.integer "state"
t.string "result" t.string "result"
......
require 'test_helper'
class JobrequestsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
state: 1
result: MyString
timestampstarted: 1
timestampcompleted: 1
command_id: 1
server_id: 1
args: MyString
user: MyString
email: MyString
two:
state: 1
result: MyString
timestampstarted: 1
timestampcompleted: 1
command_id: 1
server_id: 1
args: MyString
user: MyString
email: MyString
require 'test_helper'
class JobrequestsHelperTest < ActionView::TestCase
end
require 'test_helper'
class JobwaitingMailerTest < ActionMailer::TestCase
# test "the truth" do
# assert true
# end
end
# Preview all emails at http://localhost:3000/rails/mailers/jobwaiting_mailer
class JobwaitingMailerPreview < ActionMailer::Preview
end
require 'test_helper'
class JobrequestTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment