summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaku Ytti <saku@ytti.fi>2013-04-19 12:36:45 +0300
committerSaku Ytti <saku@ytti.fi>2013-04-19 12:41:29 +0300
commit96668cc2dc0367e3d1a3ec94265ce889b62d8ada (patch)
tree340f92a6dd4b68e41a946729c8fae34db7aff40b
parent9d217025fac3e335c308f02e7377e14ccfdc0e66 (diff)
Add restful API
-rw-r--r--.rspec1
-rw-r--r--README.md3
-rw-r--r--TODO.md5
-rw-r--r--lib/oxidized/api/domain.rb48
-rw-r--r--lib/oxidized/api/rest.rb43
-rw-r--r--lib/oxidized/config/bootstrap.rb3
-rw-r--r--lib/oxidized/config/defaults.rb1
-rw-r--r--lib/oxidized/core.rb15
-rw-r--r--lib/oxidized/manager.rb1
-rw-r--r--lib/oxidized/node.rb19
-rw-r--r--lib/oxidized/nodes.rb20
-rw-r--r--lib/oxidized/output/git.rb1
-rw-r--r--spec/nodes_spec.rb13
13 files changed, 151 insertions, 22 deletions
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..53607ea
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--colour
diff --git a/README.md b/README.md
index 5e2b584..237578b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# Pitch
* automatically adds/removes threads to meet configured retrieval interval
- * can move node immediately to head-of-queue (maybe trigger from snmp trap or syslog), to be serviced by next spawned thread
+ * restful API to move node immediately to head-of-queue (maybe trigger from snmp trap or syslog), to be serviced by next spawned thread (GET /nodes/next/$node)
+ * restful API to reload list of nodes (GET /nodes/reload)
# Install
early days, but try to run it and edit ~/.config/oxidized/config
diff --git a/TODO.md b/TODO.md
index e2ba06d..d67a0bc 100644
--- a/TODO.md
+++ b/TODO.md
@@ -15,11 +15,6 @@ I don't really need it myself, since I don't have platforms where it would be ne
* should we try to avoid max threads from being hit? (like maybe non-success thread is pulling average?)
-# restful API (puma+sinatra):
- * ask to reload node list
- * move node to head of queue
-
-
# config
* save keys as strings, load as symbols?
diff --git a/lib/oxidized/api/domain.rb b/lib/oxidized/api/domain.rb
new file mode 100644
index 0000000..fa6a1c7
--- /dev/null
+++ b/lib/oxidized/api/domain.rb
@@ -0,0 +1,48 @@
+# this is not used, just added here if I want to revive it
+
+module Oxidized
+ require 'socket'
+ require 'json'
+ module API
+ class Domain
+ def initialize nodes, socket=CFG.api
+ puts 'here'
+ @nodes = nodes
+ File.unlink socket rescue Errno::ENOENT
+ @server = UNIXServer.new socket
+ end
+ def work
+ io = select [@server], nil, nil, Config::Sleep
+ process io.first.first.accept if io
+ end
+ def read
+ @socket.recv 1024
+ end
+ def write data=''
+ begin
+ @socket.send JSON.dump(data), 0
+ rescue Errno::EPIPE
+ end
+ end
+ def process socket
+ @socket = socket
+ cmd = read
+ cmd, data = cmd.split /\s+/, 2
+ data = data.to_s.chomp
+ case cmd
+ when /next/i
+ @nodes.next data
+ write 'OK'
+ when /reload/i
+ @nodes.load if data.match /nodes/i
+ write 'OK'
+ when /list/i
+ write @nodes.map{|e|e.name}
+ when /node/i
+ write @nodes.show(data)
+ end
+ @socket.close
+ end
+ end
+ end
+end
diff --git a/lib/oxidized/api/rest.rb b/lib/oxidized/api/rest.rb
new file mode 100644
index 0000000..ee06bc8
--- /dev/null
+++ b/lib/oxidized/api/rest.rb
@@ -0,0 +1,43 @@
+module Oxidized
+ require 'webrick'
+ require 'json'
+ module API
+ class Rest
+ def initialize nodes, listen
+ @nodes = nodes
+ addr, port = listen.to_s.split ':'
+ port, addr = addr, nil if not port
+ @web = WEBrick::HTTPServer.new :BindAddress=>addr, :Port=>port
+ maps
+ end
+ def work
+ req = select @web.listeners, nil, nil, Config::Sleep
+ while req
+ @web.run req.first.first.accept
+ req = select @web.listeners, nil, nil, 0
+ end
+ end
+ def maps
+ @web.mount_proc '/nodes' do |req, res|
+ #script_name, #path_info
+ case req.path_info[1..-1]
+ # /nodes/reload - reloads list of nodes
+ when 'reload'
+ @nodes.load
+ res.body = JSON.dump 'OK'
+ # /nodes/next/node - moves node to head of queue
+ when /next\/(.*)/
+ @nodes.next $1
+ res.body = JSON.dump 'OK'
+ # /nodes/list - returns list of nodes
+ when 'list'
+ res.body = JSON.dump @nodes.list
+ # /nodes/show/node - returns data about node
+ when /show\/(.*)/
+ res.body = JSON.dump @nodes.show $1
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/oxidized/config/bootstrap.rb b/lib/oxidized/config/bootstrap.rb
index e44dde7..2991fa3 100644
--- a/lib/oxidized/config/bootstrap.rb
+++ b/lib/oxidized/config/bootstrap.rb
@@ -10,6 +10,7 @@ module Oxidized
CFG.threads = 10
CFG.timeout = 5
CFG.prompt = /^([\w\.\-@]{3,30}[#>]\s?)$/
+ CFG.rest = 8888
CFG.input = {
:default => 'ssh',
}
@@ -17,7 +18,7 @@ module Oxidized
:default => 'git',
}
CFG.source = {
- :default => 'ascii',
+ :default => 'csv',
}
CFG.model_map = {
'cisco' => 'ios',
diff --git a/lib/oxidized/config/defaults.rb b/lib/oxidized/config/defaults.rb
index a07e1a6..943d90b 100644
--- a/lib/oxidized/config/defaults.rb
+++ b/lib/oxidized/config/defaults.rb
@@ -5,6 +5,7 @@ module Oxidized
OutputDir = File.join Directory, %w(lib oxidized output)
ModelDir = File.join Directory, %w(lib oxidized model)
SourceDir = File.join Directory, %w(lib oxidized source)
+ Sleep = 1
end
class << self
attr_accessor :mgr
diff --git a/lib/oxidized/core.rb b/lib/oxidized/core.rb
index 76aa330..59292f9 100644
--- a/lib/oxidized/core.rb
+++ b/lib/oxidized/core.rb
@@ -4,6 +4,7 @@ module Oxidized
require 'oxidized/worker'
require 'oxidized/nodes'
require 'oxidized/manager'
+ require 'oxidized/api/rest'
class << self
def new *args
Core.new args
@@ -14,8 +15,18 @@ module Oxidized
def initialize args
Oxidized.mgr = Manager.new
nodes = Nodes.new
- worker = Worker.new nodes
- loop { worker.work; sleep 1 }
+ @worker = Worker.new nodes
+ @rest = API::Rest.new nodes, CFG.rest if CFG.rest
+ run
+ end
+
+ private
+
+ def run
+ while true
+ @worker.work
+ @rest ? @rest.work : sleep(Config::Sleep)
+ end
end
end
end
diff --git a/lib/oxidized/manager.rb b/lib/oxidized/manager.rb
index 0edf9e7..8c53d64 100644
--- a/lib/oxidized/manager.rb
+++ b/lib/oxidized/manager.rb
@@ -37,6 +37,7 @@ module Oxidized
@model.merge! _model
end
def source= _source
+ return nil if @source.key? _source
_source = Manager.load Config::SourceDir, _source
return false if _source.empty?
@source.merge! _source
diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb
index 740834a..de04c98 100644
--- a/lib/oxidized/node.rb
+++ b/lib/oxidized/node.rb
@@ -28,6 +28,25 @@ module Oxidized
[status, config]
end
+ def serialize
+ h = {
+ :name => @name,
+ :ip => @ip,
+ :group => @group,
+ :model => @model.class.to_s,
+ :last => nil,
+ }
+ if @last
+ h[:last] = {
+ :start => @last.start,
+ :end => @last.end,
+ :status => @last.status,
+ :time => @last.time,
+ }
+ end
+ h
+ end
+
private
def resolve_prompt opt
diff --git a/lib/oxidized/nodes.rb b/lib/oxidized/nodes.rb
index 467d3a0..3e58348 100644
--- a/lib/oxidized/nodes.rb
+++ b/lib/oxidized/nodes.rb
@@ -2,7 +2,7 @@ module Oxidized
require 'oxidized/node'
class Nodes < Array
attr_accessor :source
- alias :del :delete
+ alias :put :unshift
def initialize *args
super
load if args.empty?
@@ -17,17 +17,25 @@ module Oxidized
replace new
end
def list
- self
+ map { |e| e.name }
end
- # @param node [String] name of the node inserted into nodes array
- def put node
- unshift node
+ def find_index node
+ index { |e| e.name == node }
+ end
+ def show node
+ i = find_index node
+ self[i].serialize if i
+ end
+ def del node
+ i = find_index node
+ delete_at i if i
end
# @param node [String] name of the node moved into the head of array
- def top node
+ def next node
n = del node
put n if n
end
+ alias :top :next
# @return [String] node from the head of the array
def get
(self << shift).last
diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb
index 77d18bb..019d83b 100644
--- a/lib/oxidized/output/git.rb
+++ b/lib/oxidized/output/git.rb
@@ -28,7 +28,6 @@ class Git < Output
repo = File.join File.dirname(repo), opt[:group] + '.git'
end
begin
-
repo = Repo.new repo
actor = Actor.new user, email
update_repo repo, file, data, msg, actor
diff --git a/spec/nodes_spec.rb b/spec/nodes_spec.rb
index ad51525..80ed300 100644
--- a/spec/nodes_spec.rb
+++ b/spec/nodes_spec.rb
@@ -1,15 +1,16 @@
-require 'oxidized/nodes'
+require 'oxidized'
+Oxidized.mgr = Oxidized::Manager.new
describe Oxidized::Nodes do
before(:each) do
@nodes_org = %w(ltt-pe1.hel kes2-rr1.tku tor-peer1.oul
- hal-p2.tre sav-gr1-sw1.kuo psl-sec-pe1.hel)
+ hal-p2.tre sav-gr1-sw1.kuo psl-sec-pe1.hel).map { |e| Oxidized::Node.new(:name=>e) }
@nodes = Oxidized::Nodes.new @nodes_org.dup
end
describe '#put' do
it 'adds node to top of queue' do
- node = 'kst-p1.sto'
+ node = Oxidized::Node.new(:name=>'kst-p1.sto')
@nodes.put node
expect(@nodes).to eq [node] + @nodes_org
end
@@ -30,15 +31,15 @@ describe Oxidized::Nodes do
end
end
- describe '#top' do
+ describe '#next' do
it 'moves node to top of queue' do
node = @nodes[3]
- @nodes.top node
+ @nodes.next node.name
expect(@nodes).to start_with [node]
end
it 'does not change node count' do
before = @nodes.size
- @nodes.top @nodes[3]
+ @nodes.next @nodes[3].name
expect(before).to eq @nodes.size
end
end