nfagent 0.9.0 → 0.9.5
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.
- data/Manifest.txt +5 -0
- data/Rakefile +1 -1
- data/lib/nfagent.rb +8 -2
- data/lib/nfagent/chunk.rb +5 -8
- data/lib/nfagent/chunk_handler.rb +14 -35
- data/lib/nfagent/client.rb +21 -0
- data/lib/nfagent/client_response.rb +13 -0
- data/lib/nfagent/config.rb +2 -0
- data/lib/nfagent/event.rb +3 -2
- data/lib/nfagent/info.rb +26 -0
- data/lib/nfagent/payload.rb +70 -0
- data/lib/nfagent/poller.rb +18 -0
- data/lib/nfagent/server.rb +16 -4
- data/lib/nfagent/submitter.rb +29 -41
- metadata +10 -5
data/Manifest.txt
CHANGED
@@ -7,8 +7,13 @@ lib/nfagent/encoder.rb
|
|
7
7
|
lib/nfagent/server.rb
|
8
8
|
lib/nfagent/chunk_handler.rb
|
9
9
|
lib/nfagent/log.rb
|
10
|
+
lib/nfagent/info.rb
|
10
11
|
lib/nfagent/event.rb
|
12
|
+
lib/nfagent/payload.rb
|
13
|
+
lib/nfagent/poller.rb
|
11
14
|
lib/nfagent/chunk.rb
|
15
|
+
lib/nfagent/client.rb
|
16
|
+
lib/nfagent/client_response.rb
|
12
17
|
lib/nfagent/config.rb
|
13
18
|
lib/nfagent/tail.rb
|
14
19
|
lib/nfagent/submitter.rb
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ $hoe = Hoe.spec('nfagent') do |p|
|
|
11
11
|
p.post_install_message = 'PostInstall.txt'
|
12
12
|
p.rubyforge_name = p.name
|
13
13
|
p.extra_deps = [
|
14
|
-
['svutil','>= 0.0.
|
14
|
+
['svutil','>= 0.0.6'], ['eventmachine', '>= 0.12.8']
|
15
15
|
]
|
16
16
|
p.extra_dev_deps = [
|
17
17
|
['newgem', ">= #{::Newgem::VERSION}"]
|
data/lib/nfagent.rb
CHANGED
@@ -4,25 +4,31 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'svutil'
|
6
6
|
|
7
|
-
require 'thread'
|
8
7
|
require 'fileutils'
|
9
8
|
require 'logger'
|
10
9
|
require 'pp'
|
11
10
|
require 'uri'
|
12
11
|
require 'net/http'
|
13
12
|
require 'eventmachine'
|
13
|
+
require 'em/timers'
|
14
|
+
require 'rbconfig'
|
14
15
|
|
15
16
|
require 'nfagent/chunk'
|
17
|
+
require 'nfagent/client'
|
18
|
+
require 'nfagent/client_response'
|
16
19
|
require 'nfagent/chunk_handler'
|
17
20
|
require 'nfagent/submitter'
|
18
21
|
require 'nfagent/encoder'
|
19
22
|
require 'nfagent/config'
|
20
23
|
require 'nfagent/log'
|
24
|
+
require 'nfagent/info'
|
25
|
+
require 'nfagent/payload'
|
26
|
+
require 'nfagent/poller'
|
21
27
|
require 'nfagent/tail'
|
22
28
|
require 'nfagent/event'
|
23
29
|
require 'nfagent/server'
|
24
30
|
require 'nfagent/cli'
|
25
31
|
|
26
32
|
module NFAgent
|
27
|
-
VERSION = '0.9.
|
33
|
+
VERSION = '0.9.5'
|
28
34
|
end
|
data/lib/nfagent/chunk.rb
CHANGED
@@ -26,19 +26,16 @@ module NFAgent
|
|
26
26
|
(Time.now - @created_at > ::DEFAULT_TIME_OUT) && !@array.empty?
|
27
27
|
end
|
28
28
|
|
29
|
+
# TODO: Is this the right place for compression, encoding and check summing? Perhaps it should go into the submitter to that it can be deferred
|
29
30
|
def dump
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
Payload.new do |payload|
|
32
|
+
payload.data = Encoder.encode64url(Zlib::Deflate.deflate(@array.join("\n"), Zlib::BEST_COMPRESSION))
|
33
|
+
payload.checksum = Digest::SHA1.hexdigest(payload.data)
|
34
|
+
end
|
33
35
|
end
|
34
36
|
|
35
37
|
def clear
|
36
38
|
@array.clear
|
37
39
|
end
|
38
|
-
|
39
|
-
def submit_to_server
|
40
|
-
payload, checksum = dump
|
41
|
-
@submitter.submit(payload, checksum)
|
42
|
-
end
|
43
40
|
end
|
44
41
|
end
|
@@ -1,57 +1,36 @@
|
|
1
1
|
module NFAgent
|
2
2
|
class ChunkHandler
|
3
3
|
|
4
|
+
# TODO: Rename this to Controller later
|
4
5
|
def initialize(chunk_size = 500)
|
5
|
-
@
|
6
|
-
@chunk_size = chunk_size
|
7
|
-
make_new_chunk
|
6
|
+
@chunk = Chunk.new(chunk_size)
|
8
7
|
end
|
9
8
|
|
10
|
-
def
|
9
|
+
def append(line)
|
11
10
|
# if current day is > day of last entry on current_chunk
|
12
11
|
# then submit and reset the chunk before adding the line
|
13
12
|
current_day = Time.now.day
|
14
|
-
if current_day !=
|
13
|
+
if current_day != @chunk.created_at.day
|
15
14
|
Log.info("Expiring chunk due to date rollover")
|
16
15
|
reset_chunk
|
17
16
|
end
|
18
|
-
|
17
|
+
@chunk << line
|
19
18
|
end
|
20
19
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
check_full_or_expired
|
25
|
-
sleep 5
|
26
|
-
end
|
20
|
+
def check_full_or_expired
|
21
|
+
if @chunk.full? || @chunk.expired?
|
22
|
+
reset_chunk
|
27
23
|
end
|
28
24
|
end
|
29
25
|
|
30
26
|
private
|
31
|
-
def check_full_or_expired
|
32
|
-
if current_chunk.full? || current_chunk.expired?
|
33
|
-
reset_chunk
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
27
|
def reset_chunk
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
def make_new_chunk
|
46
|
-
@mutex.synchronize do
|
47
|
-
@current_chunk = Chunk.new(@chunk_size)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def current_chunk
|
52
|
-
@mutex.synchronize do
|
53
|
-
return @current_chunk
|
54
|
-
end
|
28
|
+
submitter = Submitter.new(@chunk.dump)
|
29
|
+
submitter.errback { |payload|
|
30
|
+
payload.write_to_disk(Config.dump_dir)
|
31
|
+
}
|
32
|
+
@chunk.clear
|
33
|
+
submitter.perform
|
55
34
|
end
|
56
35
|
end
|
57
36
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module NFAgent
|
2
|
+
class Client
|
3
|
+
SERVICE_HOST = "collector.service.netfox.com"
|
4
|
+
|
5
|
+
def self.post(end_point, data_hash)
|
6
|
+
proxy_class = Net::HTTP::Proxy(Config.proxy.host, Config.proxy.port, Config.proxy.user, Config.proxy.password)
|
7
|
+
# TODO: Enable SSL
|
8
|
+
proxy_class.start(SERVICE_HOST, 80) do |http|
|
9
|
+
req = Net::HTTP::Post.new("/#{end_point}")
|
10
|
+
req.set_form_data(data_hash.merge("key" => Config.client_key))
|
11
|
+
ClientResponse.new do |resp|
|
12
|
+
resp.response, resp.message = http.request(req)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
rescue
|
16
|
+
ClientResponse.new do |resp|
|
17
|
+
resp.message = $!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/nfagent/config.rb
CHANGED
data/lib/nfagent/event.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module NFAgent
|
2
2
|
class Event < EventMachine::Connection
|
3
|
-
def initialize(chunk_handler)
|
3
|
+
def initialize(chunk_handler, poller)
|
4
4
|
@handler = chunk_handler
|
5
|
+
@poller = poller
|
5
6
|
end
|
6
7
|
|
7
8
|
def post_init
|
@@ -10,7 +11,7 @@ module NFAgent
|
|
10
11
|
|
11
12
|
def receive_data(data)
|
12
13
|
if data && data.length > 2
|
13
|
-
@handler.
|
14
|
+
@handler.append(data)
|
14
15
|
end
|
15
16
|
send_data('OK')
|
16
17
|
end
|
data/lib/nfagent/info.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module NFAgent
|
2
|
+
class Info
|
3
|
+
attr_accessor :last_proxy_connection
|
4
|
+
|
5
|
+
def hostname
|
6
|
+
Socket.gethostname
|
7
|
+
end
|
8
|
+
|
9
|
+
def version
|
10
|
+
NFAgent::VERSION
|
11
|
+
end
|
12
|
+
|
13
|
+
def host_string
|
14
|
+
RBConfig::CONFIG['host']
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
{
|
19
|
+
:hostname => hostname,
|
20
|
+
:version => version,
|
21
|
+
:host_string => host_string,
|
22
|
+
:last_proxy_connection => last_proxy_connection
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
module NFAgent
|
3
|
+
class Payload < Struct.new(:data, :checksum, :filename)
|
4
|
+
def initialize
|
5
|
+
yield self
|
6
|
+
end
|
7
|
+
|
8
|
+
def attempt
|
9
|
+
@attempt || 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def attempt=(value)
|
13
|
+
@attempt = value.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def increment_attempt!
|
17
|
+
@attempt ||= 1
|
18
|
+
@attempt += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def size
|
22
|
+
(self.data || "").size + 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_to_disk(directory)
|
26
|
+
File.open(File.join(directory, "#{self.checksum}-#{self.attempt}"), "w") do |file|
|
27
|
+
file << self.data
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def lock
|
32
|
+
return if locked?
|
33
|
+
FileUtils.touch(lockfile) if filename
|
34
|
+
yield
|
35
|
+
FileUtils.rm_f(lockfile) if filename
|
36
|
+
end
|
37
|
+
|
38
|
+
def locked?
|
39
|
+
filename && File.exists?(lockfile)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.read_from_file(filename)
|
43
|
+
# Ensure the file is only relative
|
44
|
+
filename = File.basename(filename)
|
45
|
+
self.new do |payload|
|
46
|
+
payload.filename = filename
|
47
|
+
payload.checksum, payload.attempt = filename.split("-")
|
48
|
+
payload.data = ""
|
49
|
+
ref = File.join(Config.dump_dir, filename)
|
50
|
+
File.open(ref, "r") do |file|
|
51
|
+
payload.data << file.read
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy!
|
57
|
+
FileUtils.rm_f(File.join(Config.dump_dir, self.filename)) if self.filename
|
58
|
+
end
|
59
|
+
|
60
|
+
def try_again_later
|
61
|
+
# TODO: Move the file to a new name with a later timetamp
|
62
|
+
FileUtils.mv(File.join(Config.dump_dir, self.filename), File.join(Config.dump_dir, "#{self.checksum}-#{self.attempt}"))
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def lockfile
|
67
|
+
File.join(Config.dump_dir, "#{filename}.lock") if filename
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module NFAgent
|
2
|
+
class Poller
|
3
|
+
include EM::Deferrable
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@info = Info.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def send_heartbeat
|
10
|
+
payload = @info.to_hash
|
11
|
+
Log.info("Polling: #{payload.inspect}")
|
12
|
+
response = Client.post(:poller, payload)
|
13
|
+
if !response.ok?
|
14
|
+
Log.error("Poll Failed: #{response.message}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/nfagent/server.rb
CHANGED
@@ -1,14 +1,26 @@
|
|
1
1
|
module NFAgent
|
2
2
|
class Server
|
3
|
-
def
|
3
|
+
def run
|
4
4
|
Log.info("Starting up")
|
5
|
-
Submitter.start_resubmission_thread
|
6
5
|
chunk_handler = ChunkHandler.new
|
7
|
-
|
6
|
+
poller = Poller.new
|
8
7
|
|
9
8
|
EM.run {
|
10
|
-
EM.
|
9
|
+
EM::PeriodicTimer.new(5) do
|
10
|
+
chunk_handler.check_full_or_expired
|
11
|
+
end
|
12
|
+
EM::PeriodicTimer.new(60) do
|
13
|
+
Submitter.resubmit_failed_dumps
|
14
|
+
end
|
15
|
+
EM::PeriodicTimer.new(120) do
|
16
|
+
poller.send_heartbeat
|
17
|
+
end
|
18
|
+
EM.start_server "0.0.0.0", 10000, Event, chunk_handler, poller
|
11
19
|
}
|
12
20
|
end
|
21
|
+
|
22
|
+
def shutdown
|
23
|
+
EM::stop_event_loop
|
24
|
+
end
|
13
25
|
end
|
14
26
|
end
|
data/lib/nfagent/submitter.rb
CHANGED
@@ -1,59 +1,47 @@
|
|
1
1
|
module NFAgent
|
2
2
|
class Submitter
|
3
|
+
include EM::Deferrable
|
3
4
|
attr_accessor :host
|
4
5
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
@key = key
|
6
|
+
def initialize(payload)
|
7
|
+
@payload = payload
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
rescue
|
22
|
-
Log.error "Submission Failed: #{$!}"
|
23
|
-
write_failed_dump(payload, checksum, attempt)
|
24
|
-
end
|
25
|
-
|
26
|
-
def write_failed_dump(payload, checksum, attempt)
|
27
|
-
File.open(File.join(Config.dump_dir, "#{checksum}-#{attempt}"), "w") do |file|
|
28
|
-
file << payload
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.start_resubmission_thread
|
33
|
-
Thread.new do
|
34
|
-
loop do
|
35
|
-
self.resubmit_failed_dumps
|
36
|
-
sleep 60
|
10
|
+
def perform
|
11
|
+
@payload.increment_attempt!
|
12
|
+
fail(@payload) unless [ 1, 2, 4, 8, 16 ].include?(@payload.attempt)
|
13
|
+
Log.info "Submitting Payload: #{@payload.checksum}, Attempt #{@payload.attempt}, (#{@payload.size} bytes)"
|
14
|
+
@payload.lock do
|
15
|
+
response = Client.post(:collector, "payload" => @payload.data, "checksum" => @payload.checksum)
|
16
|
+
if response.ok?
|
17
|
+
succeed(@payload)
|
18
|
+
else
|
19
|
+
Log.error "Submission Failed: #{response.message}"
|
20
|
+
fail(@payload)
|
37
21
|
end
|
38
22
|
end
|
39
23
|
end
|
40
24
|
|
25
|
+
# TODO: Change attempt logic
|
26
|
+
# Add the next timestamp for when submission should be attenpted again to the end of the filename
|
41
27
|
def self.resubmit_failed_dumps
|
42
28
|
submitter = Submitter.new(Config.client_key)
|
43
29
|
dump_dir = Dir.new(Config.dump_dir)
|
44
30
|
dump_dir.entries.select { |e| not e =~ /^\./ }.each do |entry|
|
45
|
-
dump_file, attempt = entry.split("-")
|
46
31
|
Log.info "Resubmitting #{entry}"
|
47
|
-
payload =
|
48
|
-
|
49
|
-
|
50
|
-
payload
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
32
|
+
payload = Payload.read_from_file(entry)
|
33
|
+
submitter = self.new(payload)
|
34
|
+
submitter.callback { |payload|
|
35
|
+
payload.destroy!
|
36
|
+
}
|
37
|
+
submitter.errback { |payload|
|
38
|
+
if payload.attempt > 16
|
39
|
+
payload.destroy!
|
40
|
+
else
|
41
|
+
payload.try_again_later
|
42
|
+
end
|
43
|
+
}
|
44
|
+
submitter.perform
|
57
45
|
end
|
58
46
|
end
|
59
47
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 5
|
9
|
+
version: 0.9.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Daniel Draper
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-12 00:00:00 +09:30
|
18
18
|
default_executable: nfagent
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,8 +27,8 @@ dependencies:
|
|
27
27
|
segments:
|
28
28
|
- 0
|
29
29
|
- 0
|
30
|
-
-
|
31
|
-
version: 0.0.
|
30
|
+
- 6
|
31
|
+
version: 0.0.6
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
@@ -96,8 +96,13 @@ files:
|
|
96
96
|
- lib/nfagent/server.rb
|
97
97
|
- lib/nfagent/chunk_handler.rb
|
98
98
|
- lib/nfagent/log.rb
|
99
|
+
- lib/nfagent/info.rb
|
99
100
|
- lib/nfagent/event.rb
|
101
|
+
- lib/nfagent/payload.rb
|
102
|
+
- lib/nfagent/poller.rb
|
100
103
|
- lib/nfagent/chunk.rb
|
104
|
+
- lib/nfagent/client.rb
|
105
|
+
- lib/nfagent/client_response.rb
|
101
106
|
- lib/nfagent/config.rb
|
102
107
|
- lib/nfagent/tail.rb
|
103
108
|
- lib/nfagent/submitter.rb
|