nfagent 0.9.0 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|