LanGrove 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/.rspec +1 -0
  2. data/.rvmrc +62 -0
  3. data/.watchr +19 -0
  4. data/Gemfile +16 -0
  5. data/Gemfile.lock +61 -0
  6. data/Rakefile +17 -0
  7. data/bin/datagram_example +4 -0
  8. data/config/boot.rb +64 -0
  9. data/config/daemons.yml.tmpl +78 -0
  10. data/config/environment.rb +28 -0
  11. data/config/environments/development.rb +0 -0
  12. data/config/environments/production.rb +0 -0
  13. data/config/environments/test.rb +0 -0
  14. data/lib/adaptor/base.rb +1 -0
  15. data/lib/adaptor/datagram.rb +20 -0
  16. data/lib/adaptor/socket_handler.rb +27 -0
  17. data/lib/adaptor_base.rb +39 -0
  18. data/lib/client/base.rb +1 -0
  19. data/lib/client/puppet_state.rb +74 -0
  20. data/lib/client/radio_state.rb +81 -0
  21. data/lib/client_base.rb +24 -0
  22. data/lib/daemon/base.rb +1 -0
  23. data/lib/daemon/datagram_example.rb +12 -0
  24. data/lib/daemon_base.rb +168 -0
  25. data/lib/ext/config_item.rb +35 -0
  26. data/lib/ext/config_loader.rb +16 -0
  27. data/lib/ext/persistable.rb +103 -0
  28. data/lib/ext/string.rb +35 -0
  29. data/lib/handler/base.rb +1 -0
  30. data/lib/handler/socket_to_file.rb +30 -0
  31. data/lib/handler_base.rb +125 -0
  32. data/lib/jobs/Rakefile +0 -0
  33. data/lib/jobs/jobs.rb +1 -0
  34. data/lib/jobs/updated_puppet_state.rb +17 -0
  35. data/lib/protocol_base.rb +5 -0
  36. data/libexec/daemon.rb +57 -0
  37. data/spec/adaptor/datagram_spec.rb +6 -0
  38. data/spec/adaptor/socket_handler_spec.rb +5 -0
  39. data/spec/adaptor_base_spec.rb +45 -0
  40. data/spec/client_base_spec.rb +5 -0
  41. data/spec/daemon_base_spec.rb +97 -0
  42. data/spec/ext/config_item_spec.rb +77 -0
  43. data/spec/ext/config_loader_spec.rb +5 -0
  44. data/spec/ext/persistable_spec.rb +118 -0
  45. data/spec/ext/string_spec.rb +16 -0
  46. data/spec/functional/datagram_spec.rb +122 -0
  47. data/spec/handler_base_spec.rb +71 -0
  48. data/spec/protocol_base_spec.rb +6 -0
  49. data/spec/todo_spec.rb +13 -0
  50. data/tmp/TMP +0 -0
  51. metadata +97 -0
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.2-p0@langrove"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create use "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+ if [[ $- == *i* ]] # check for interactive shells
56
+ then
57
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
58
+ else
59
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
60
+ fi
61
+
62
+
data/.watchr ADDED
@@ -0,0 +1,19 @@
1
+ def run_spec(file)
2
+ unless File.exist?(file)
3
+ puts "#{file} does not exist"
4
+ return
5
+ end
6
+
7
+ puts "Running #{file}"
8
+ system "rspec #{file}"
9
+ puts
10
+ end
11
+
12
+ watch("spec/.*/*_spec.rb") do |match|
13
+ run_spec match[0]
14
+ end
15
+
16
+ watch("lib/(.*/*).rb") do |match|
17
+ puts match
18
+ run_spec %{spec/#{match[1]}_spec.rb}
19
+ end
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source :gemcutter
2
+ source "http://rubygems.org"
3
+
4
+ gem 'watchr'
5
+ gem 'rspec'
6
+
7
+ # daemon-kit
8
+ gem 'daemon-kit'
9
+ gem 'eventmachine'
10
+ gem 'em-http-request'
11
+ gem 'awesome_print'
12
+
13
+ gem 'eventmachine_httpserver'
14
+
15
+ gem 'resque'
16
+ gem 'rake'
data/Gemfile.lock ADDED
@@ -0,0 +1,61 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ remote: http://rubygems.org/
4
+ specs:
5
+ addressable (2.2.7)
6
+ awesome_print (1.0.2)
7
+ daemon-kit (0.1.8.2)
8
+ eventmachine (>= 0.12.10)
9
+ safely (>= 0.3.1)
10
+ diff-lcs (1.1.3)
11
+ em-http-request (0.3.0)
12
+ addressable (>= 2.0.0)
13
+ escape_utils
14
+ eventmachine (>= 0.12.9)
15
+ escape_utils (0.2.4)
16
+ eventmachine (0.12.10)
17
+ eventmachine_httpserver (0.2.1)
18
+ multi_json (1.3.2)
19
+ rack (1.4.1)
20
+ rack-protection (1.2.0)
21
+ rack
22
+ rake (0.8.7)
23
+ redis (2.2.2)
24
+ redis-namespace (1.0.3)
25
+ redis (< 3.0.0)
26
+ resque (1.20.0)
27
+ multi_json (~> 1.0)
28
+ redis-namespace (~> 1.0.2)
29
+ sinatra (>= 0.9.2)
30
+ vegas (~> 0.1.2)
31
+ rspec (2.9.0)
32
+ rspec-core (~> 2.9.0)
33
+ rspec-expectations (~> 2.9.0)
34
+ rspec-mocks (~> 2.9.0)
35
+ rspec-core (2.9.0)
36
+ rspec-expectations (2.9.1)
37
+ diff-lcs (~> 1.1.3)
38
+ rspec-mocks (2.9.0)
39
+ safely (0.3.1)
40
+ sinatra (1.3.2)
41
+ rack (~> 1.3, >= 1.3.6)
42
+ rack-protection (~> 1.2)
43
+ tilt (~> 1.3, >= 1.3.3)
44
+ tilt (1.3.3)
45
+ vegas (0.1.11)
46
+ rack (>= 1.0.0)
47
+ watchr (0.7)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ awesome_print
54
+ daemon-kit
55
+ em-http-request
56
+ eventmachine
57
+ eventmachine_httpserver
58
+ rake
59
+ resque
60
+ rspec
61
+ watchr
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+
3
+ desc "Publish a new version to ruby-gems.org"
4
+ task :publish do
5
+ require 'langrove/version'
6
+
7
+ sh "gem build langrove.gemspec"
8
+ sh "gem push langrove-#{LanGrove::Version}.gem"
9
+
10
+ #sh "git tag v#{LanGrove::Version}"
11
+ #sh "git push origin v#{Resque::Version}"
12
+ #sh "git push origin master"
13
+ #sh "git clean -fd"
14
+
15
+ # exec "rake documentation"
16
+
17
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ DAEMON_NAME = File.basename $0
3
+ require File.expand_path('../../config/environment', __FILE__)
4
+ DaemonKit::Application.exec( DAEMON_ROOT + '/libexec/daemon.rb' )
data/config/boot.rb ADDED
@@ -0,0 +1,64 @@
1
+ # Don't change this file!
2
+ # Configure your daemon in config/environment.rb
3
+
4
+ DAEMON_ROOT = "#{File.expand_path(File.dirname(__FILE__))}/.." unless defined?( DAEMON_ROOT )
5
+
6
+ require "rubygems"
7
+ require "bundler/setup"
8
+
9
+ module DaemonKit
10
+ class << self
11
+ def boot!
12
+ unless booted?
13
+ pick_boot.run
14
+ end
15
+ end
16
+
17
+ def booted?
18
+ defined? DaemonKit::Initializer
19
+ end
20
+
21
+ def pick_boot
22
+ (vendor_kit? ? VendorBoot : GemBoot).new
23
+ end
24
+
25
+ def vendor_kit?
26
+ File.exists?( "#{DAEMON_ROOT}/vendor/daemon-kit" )
27
+ end
28
+ end
29
+
30
+ class Boot
31
+ def run
32
+ load_initializer
33
+ DaemonKit::Initializer.run
34
+ end
35
+ end
36
+
37
+ class VendorBoot < Boot
38
+ def load_initializer
39
+ require "#{DAEMON_ROOT}/vendor/daemon-kit/lib/daemon_kit/initializer"
40
+ end
41
+ end
42
+
43
+ class GemBoot < Boot
44
+ def load_initializer
45
+ begin
46
+ require 'rubygems' unless defined?( ::Gem )
47
+ gem 'daemon-kit'
48
+ require 'daemon_kit/initializer'
49
+ rescue ::Gem::LoadError => e
50
+ msg = <<EOF
51
+
52
+ You are missing the daemon-kit gem. Please install the following gem:
53
+
54
+ sudo gem install daemon-kit
55
+
56
+ EOF
57
+ $stderr.puts msg
58
+ exit 1
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ DaemonKit.boot!
@@ -0,0 +1,78 @@
1
+ #
2
+ # Using the daemon stubs in bin/ to spawn daemons from this
3
+ # config file with the following guidelines.
4
+ #
5
+ # 1. Each daemon stub name should correspond to a sub-branch in
6
+ # the daemons branch of the config.
7
+ #
8
+ # 2. The daemons are spawned through a generic DaemonKit based
9
+ # spawner.
10
+ #
11
+ # 3. Daemons log to the log/<daemon_name>.log where daemon_name
12
+ # exactly corresponds to the stub name.
13
+ #
14
+ # 4. Daemons keep a pidfile at log/<daemon_name>.pid, these are
15
+ # used by DaemonKit for init.d style stop|start|restart etc.
16
+ #
17
+ # 5. Daemons are spawned through a generic executer which late
18
+ # binds the daemon runner class. Therefore, each daemon with
19
+ # a stub at
20
+ #
21
+ # bin/<daemon_name>
22
+ #
23
+ # should also have a runner class defined at
24
+ #
25
+ # lib/<daemon_name>.rb
26
+ #
27
+ # which defines the class <DaemonName> with the following:
28
+ #
29
+ # Mandatory
30
+ # =========
31
+ #
32
+ # - initialize( entire_config_hash, daemon_name, logger )
33
+ #
34
+ # To load up and initialize as required.
35
+ #
36
+ # It will be provided with
37
+ #
38
+ # <entire_config_hash> - This entire file as a Hash
39
+ # <daemon_name> - From the stub name in bin/
40
+ # <logger> - An initialized logger
41
+ #
42
+ # - run()
43
+ #
44
+ # The daemons 'main' loop
45
+ #
46
+ # Optional
47
+ # ========
48
+ #
49
+ # - stop_daemon()
50
+ #
51
+ # To properly handle daemon shutdown when the server gets
52
+ # rebooted or daemon gets restarted
53
+ #
54
+ # PENDING
55
+ # PENDING - reload_daemon()
56
+ # PENDING
57
+ # PENDING To reload the daemon after a config change without taking
58
+ # PENDING down any currently connected sockets and such.
59
+ # PENDING
60
+ #
61
+ # 6. Each daemon config should contain reference to a Handler class.
62
+ #
63
+ # PENDING explain that later.
64
+ #
65
+ #
66
+
67
+ daemons:
68
+ datagram_example:
69
+ periodic: 5
70
+ adaptor:
71
+ connection: Datagram
72
+ iface: 127.0.0.1
73
+ port: 12701
74
+ handler:
75
+ collection: Base
76
+ protocol: Base
77
+
78
+
@@ -0,0 +1,28 @@
1
+ ENV["TZ"] = "ZA"
2
+ #ENV['DAEMON_ENV'] ||= 'production'
3
+
4
+ # Boot up
5
+ require File.join(File.dirname(__FILE__), 'boot')
6
+
7
+ # Auto-require default libraries.
8
+ Bundler.require :default, DaemonKit.env
9
+
10
+ DaemonKit::Initializer.run do |config|
11
+
12
+ config.daemon_name = DAEMON_NAME
13
+
14
+ # Force the daemon to be killed after X seconds from asking it to
15
+ # config.force_kill_wait = 30
16
+
17
+ # Log backraces when a thread/daemon dies (Recommended)
18
+ config.backtraces = true
19
+
20
+ #
21
+ # TODO: move log level into per daemon config
22
+ #
23
+ #config.log_level = :debug
24
+ config.log_level = :info
25
+ #config.log_level = :warn
26
+ #config.log_level = :error
27
+
28
+ end
File without changes
File without changes
File without changes
@@ -0,0 +1 @@
1
+ require 'adaptor_base'
@@ -0,0 +1,20 @@
1
+ require 'adaptor/base'
2
+
3
+ module Adaptor
4
+
5
+ class Datagram < Base
6
+
7
+ def listen( collection )
8
+
9
+ @logger.info "starting listen at UDP #{@iface}:#{@port}"
10
+
11
+ EventMachine::open_datagram_socket( @iface, @port,
12
+
13
+ @connector ) do |connection|
14
+
15
+ connection.handler = collection
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ require 'eventmachine'
2
+
3
+ module Adaptor
4
+
5
+ class SocketHandler < EM::Connection
6
+
7
+ #
8
+ # The handler collection specified in config
9
+ # is bound to this attribute after connect.
10
+ #
11
+ attr_accessor :handler
12
+ attr_accessor :protocol
13
+
14
+ def receive_data(data)
15
+
16
+ #@handler.message( @protocol.decode( data ) )
17
+ @handler.message( data )
18
+
19
+ #
20
+ # sort out application layer ACKs later
21
+ # currently only datagrams arriving here
22
+ # so it's not necessary
23
+ #
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'eventmachine'
2
+
3
+ require 'adaptor/socket_handler'
4
+
5
+ module Adaptor
6
+
7
+ class Base
8
+
9
+ def initialize( config, logger )
10
+
11
+ @config = config
12
+ @logger = logger
13
+
14
+ @iface = '127.0.0.1'
15
+ @port = 12701
16
+ @connector = Adaptor::SocketHandler
17
+
18
+ @iface = @config['iface'] if @config.has_key? 'iface'
19
+ @port = @config['port'] if @config.has_key? 'port'
20
+
21
+ if @config.has_key? 'connector' then
22
+
23
+ #
24
+ # TODO: may need to override default connection handler
25
+ #
26
+
27
+ end
28
+
29
+ end
30
+
31
+ def listen( collection ) # ---> handler
32
+
33
+ raise DaemonConfigException.new( "NotYetExtended: undefined listen()" )
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1 @@
1
+ require 'client_base'
@@ -0,0 +1,74 @@
1
+ require 'client/abstract/syslog_state_machine'
2
+
3
+ class PuppetState < SyslogStateMachine
4
+
5
+ def initialize( hostname, config, logger )
6
+ super
7
+
8
+ @state[:exit_code] = nil
9
+ @state[:last_run_at] = nil
10
+ @state[:revision] = ''
11
+ @state[:last_run_duration_seconds] = nil
12
+
13
+ end
14
+
15
+ def change_state( date, tag, message )
16
+
17
+ #
18
+ # return true if state changed
19
+ #
20
+
21
+ ### last_started_at
22
+ #
23
+ # run_puppet: obtained lock: beginning run
24
+ #
25
+ if /obtained lock: beginning run/.match( message ) then
26
+
27
+ @state[:last_run_at] = date
28
+ return true
29
+
30
+ end
31
+
32
+ def reset
33
+
34
+ @state[:exit_code] = nil
35
+
36
+ end
37
+
38
+ ### revision
39
+ #
40
+ # puppet-git-rev: 0acbf0a78ed813e31dcc3fe58f9c6e9a30219da4
41
+ #
42
+ if tag == 'puppet-git-rev' then
43
+
44
+ @state[:revision] = message
45
+ return true
46
+
47
+ end
48
+
49
+ ### success
50
+ ### last_run_duration_seconds
51
+ #
52
+ # run_puppet: completed, releasing lock (exit code : 2)
53
+ #
54
+
55
+ if /completed, releasing lock/.match( message ) then
56
+
57
+ @state[:exit_code] = /[\d]+/.match(message)[0]
58
+ @state[:running] = false
59
+
60
+ if @state[:last_run_at] then
61
+ @state[:last_run_duration_seconds] = date - @state[:last_run_at]
62
+ else
63
+ @state[:last_run_duration_seconds] = -1
64
+ end
65
+
66
+ return true
67
+
68
+ end
69
+
70
+ return false
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,81 @@
1
+ require 'client/abstract/syslog_state_machine'
2
+
3
+ class RadioState < SyslogStateMachine
4
+
5
+ def persist_change_state( data )
6
+
7
+ #
8
+ # default product will override with Nano *
9
+ #
10
+ @state[:vendor] = "BST"
11
+ @state[:product] = "Subscriber"
12
+
13
+ @state.merge!( data )
14
+ @state[:last_seen_at] = data[:timestamp].clone
15
+ @state[:last_seen] = data[:timestamp].strftime( '%Y/%m/%d %H:%M:%S')
16
+
17
+
18
+ new_min :rx, :rx_min, :rx_min_at
19
+ new_max :rx, :rx_max, :rx_max_at
20
+
21
+ new_min :tx, :tx_min, :tx_min_at
22
+ new_max :tx, :tx_max, :tx_max_at
23
+
24
+ #
25
+ # flag to store
26
+ #
27
+ @stored = false
28
+
29
+ return true
30
+
31
+ end
32
+
33
+
34
+ def new_min( val, min_val, at )
35
+
36
+ newval = @state[val].to_i
37
+
38
+ if @state.has_key? min_val then
39
+
40
+ minval = @state[min_val]
41
+ begin
42
+
43
+ @state[min_val] = newval
44
+ @state[at] = @state[:timestamp].clone
45
+
46
+ end if minval > newval
47
+
48
+ else
49
+
50
+ @state[min_val] = newval
51
+ @state[at] = @state[:timestamp].clone
52
+
53
+ end
54
+
55
+ end
56
+
57
+
58
+ def new_max( val, max_val, at )
59
+
60
+ newval = @state[val].to_i
61
+
62
+ if @state.has_key? max_val then
63
+
64
+ maxval = @state[max_val]
65
+ begin
66
+
67
+ @state[max_val] = newval
68
+ @state[at] = @state[:timestamp].clone
69
+
70
+ end if maxval < newval
71
+
72
+ else
73
+
74
+ @state[max_val] = newval
75
+ @state[at] = @state[:timestamp].clone
76
+
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,24 @@
1
+ require 'ext/persistable'
2
+
3
+ module Client class Base < Persistable
4
+
5
+ #
6
+ # Misnomer.
7
+ #
8
+ #
9
+ # This is not the client,
10
+ #
11
+ #
12
+ # It is the server's perspective of the client,
13
+ #
14
+ # These are generally stored in the daemon's
15
+ # handler collection,
16
+ #
17
+ # Which contains this and all similar clients,
18
+ #
19
+ # Each bonded through the daemon's connection
20
+ # adaptor to the socket that couples them to
21
+ # their actual client..
22
+ #
23
+
24
+ end; end
@@ -0,0 +1 @@
1
+ require 'daemon_base'
@@ -0,0 +1,12 @@
1
+ require 'daemon/base'
2
+
3
+ class DatagramExample < Daemon::Base
4
+
5
+ #
6
+ # Consider tossing this dependancy.
7
+ #
8
+ # Not entirely certain this layer in
9
+ # the abstraction will be useful.
10
+ #
11
+
12
+ end