evesync 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +25 -0
- data/Rakefile +83 -0
- data/bin/evedatad +34 -0
- data/bin/evehand +36 -0
- data/bin/evemond +42 -0
- data/bin/evesync +164 -0
- data/bin/evesyncd +44 -0
- data/bin/start +16 -0
- data/config/example.conf +58 -0
- data/lib/evesync/config.rb +63 -0
- data/lib/evesync/constants.rb +17 -0
- data/lib/evesync/database.rb +107 -0
- data/lib/evesync/discover.rb +77 -0
- data/lib/evesync/err.rb +25 -0
- data/lib/evesync/handler/file.rb +28 -0
- data/lib/evesync/handler/package.rb +30 -0
- data/lib/evesync/handler.rb +89 -0
- data/lib/evesync/ipc/client.rb +37 -0
- data/lib/evesync/ipc/data/file.rb +64 -0
- data/lib/evesync/ipc/data/hashable.rb +74 -0
- data/lib/evesync/ipc/data/ignore.rb +22 -0
- data/lib/evesync/ipc/data/package.rb +58 -0
- data/lib/evesync/ipc/data/utils.rb +14 -0
- data/lib/evesync/ipc/data.rb +50 -0
- data/lib/evesync/ipc/ipc.rb +42 -0
- data/lib/evesync/ipc/server.rb +56 -0
- data/lib/evesync/log.rb +66 -0
- data/lib/evesync/ntp.rb +16 -0
- data/lib/evesync/os/linux/arch/package_manager.rb +29 -0
- data/lib/evesync/os/linux/arch/package_watcher.rb +59 -0
- data/lib/evesync/os/linux/arch.rb +2 -0
- data/lib/evesync/os/linux/base_package_manager.rb +80 -0
- data/lib/evesync/os/linux/deb/dpkg.rb +30 -0
- data/lib/evesync/os/linux/deb/package_manager.rb +38 -0
- data/lib/evesync/os/linux/deb/package_watcher.rb +32 -0
- data/lib/evesync/os/linux/deb.rb +2 -0
- data/lib/evesync/os/linux/rhel/package_manager.rb +42 -0
- data/lib/evesync/os/linux/rhel/package_watcher.rb +32 -0
- data/lib/evesync/os/linux/rhel/rpm.rb +41 -0
- data/lib/evesync/os/linux/rhel.rb +3 -0
- data/lib/evesync/os/linux.rb +9 -0
- data/lib/evesync/os.rb +2 -0
- data/lib/evesync/sync.rb +209 -0
- data/lib/evesync/trigger/base.rb +56 -0
- data/lib/evesync/trigger/file.rb +20 -0
- data/lib/evesync/trigger/package.rb +20 -0
- data/lib/evesync/trigger.rb +106 -0
- data/lib/evesync/utils.rb +51 -0
- data/lib/evesync/watcher/file.rb +156 -0
- data/lib/evesync/watcher/interface.rb +21 -0
- data/lib/evesync/watcher/package.rb +8 -0
- data/lib/evesync/watcher.rb +68 -0
- data/lib/evesync.rb +3 -0
- metadata +198 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a1973a7b7ed425602bbb593496479cfb6ce24e57d5f490ee2d54c52e76375cb
|
4
|
+
data.tar.gz: a593092487578200014b495d75a77c20a9798525d00fe9e9ab94ed26b4eba8fd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b06baf168fac9f60cc20995b586712b1de0cf1f13ab32be858d916686d4a770ea67eba82f9b0967bee7b6cc1d664f788d5c4717489320d224a1f2e724ac1ad4c
|
7
|
+
data.tar.gz: 7178b8ffc3f5a120438ffd5a0ea1a61fbb3c1a2b9b4b55a90242fadd5b2abcc61379af372bd1575551076b59583d3472faab46214f4c9b3c5687cacf83cfd424
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
BSD 2-Clause License
|
2
|
+
|
3
|
+
Copyright (c) 2018, Valentine Kiselev
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
8
|
+
|
9
|
+
* Redistributions of source code must retain the above copyright notice, this
|
10
|
+
list of conditions and the following disclaimer.
|
11
|
+
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
14
|
+
and/or other materials provided with the distribution.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
20
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
21
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
22
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
23
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
24
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'find'
|
3
|
+
require 'mkmf'
|
4
|
+
require_relative 'lib/evesync'
|
5
|
+
VERSION = Evesync::VERSION
|
6
|
+
GEMSPEC = 'evesync.gemspec'.freeze
|
7
|
+
GEMFILE = "evesync-#{VERSION}.gem".freeze
|
8
|
+
|
9
|
+
task default: %i[lint build]
|
10
|
+
|
11
|
+
task :lint do
|
12
|
+
sh 'rubocop -l lib' if find_executable 'rubocop'
|
13
|
+
end
|
14
|
+
|
15
|
+
task :rdoc do
|
16
|
+
sh 'rdoc --ri'
|
17
|
+
sh 'rdoc'
|
18
|
+
end
|
19
|
+
|
20
|
+
task install: [GEMFILE] do
|
21
|
+
sh "gem install --local #{GEMFILE}"
|
22
|
+
end
|
23
|
+
|
24
|
+
task build: GEMFILE
|
25
|
+
file GEMFILE do
|
26
|
+
sh "gem build #{GEMSPEC}"
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec::Core::RakeTask.new(:spec)
|
30
|
+
|
31
|
+
task test: :spec
|
32
|
+
|
33
|
+
task :clean, [:remove_rpm] do |_t, args|
|
34
|
+
args.with_defaults(:remove_rpm => 1)
|
35
|
+
rm_rf('tmp')
|
36
|
+
rm_rf('doc')
|
37
|
+
rm_rf('mkmf.log')
|
38
|
+
rm_rf(Dir['*.zip'])
|
39
|
+
rm_rf('RPM') if args[:remove_rpm] == 1
|
40
|
+
rm_rf("evesync-#{VERSION}")
|
41
|
+
rm_rf(GEMFILE)
|
42
|
+
end
|
43
|
+
|
44
|
+
task todos: :todo
|
45
|
+
task :todo do
|
46
|
+
puts "==== \033[0;31mTODOs\033[0m in code"
|
47
|
+
puts `find bin lib dockerfiles -type f -exec grep --color=always TODO \{} \+ ||:`
|
48
|
+
puts "==== \033[0;31mFIXMEs\033[0m in code"
|
49
|
+
puts `find bin lib dockerfiles -type f -exec grep --color=always FIXME \{} \+ ||:`
|
50
|
+
end
|
51
|
+
|
52
|
+
task :lines do
|
53
|
+
sh 'find . -name "*.rb" -exec grep -v -E "^\s*#|^\s*$" \{} \+ | wc -l'
|
54
|
+
end
|
55
|
+
|
56
|
+
## Docker related targets
|
57
|
+
|
58
|
+
task :docker do
|
59
|
+
sh 'docker-compose build'
|
60
|
+
end
|
61
|
+
|
62
|
+
task :up do
|
63
|
+
sh 'docker-compose up -d'
|
64
|
+
end
|
65
|
+
|
66
|
+
task :down do
|
67
|
+
sh 'docker-compose stop || docker-compose kill ||:'
|
68
|
+
sh 'docker-compose rm --force ||:'
|
69
|
+
end
|
70
|
+
|
71
|
+
task :rpm do
|
72
|
+
sh("rpmbuild -bb "\
|
73
|
+
"--define 'VERSION #{VERSION}' "\
|
74
|
+
"--define 'RELEASE `git rev-list HEAD master --count`' "\
|
75
|
+
"--define '_builddir #{Dir.pwd}' "\
|
76
|
+
"--define '_rpmdir #{Dir.pwd}/RPM/' "\
|
77
|
+
"evesync.spec")
|
78
|
+
sh('chown -R 1000:1000 RPM')
|
79
|
+
end
|
80
|
+
|
81
|
+
task :'build-rpm' do
|
82
|
+
sh('echo rake rpm | docker-compose run build-centos')
|
83
|
+
end
|
data/bin/evedatad
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'evesync/ipc/server'
|
5
|
+
require 'evesync/log'
|
6
|
+
require 'evesync/database'
|
7
|
+
|
8
|
+
Evesync::Log.info('Database daemon starting...')
|
9
|
+
|
10
|
+
database = Evesync::Database.new
|
11
|
+
|
12
|
+
# Creating an IPC server to accept data
|
13
|
+
data_server = Evesync::IPC::Server.new(
|
14
|
+
port: :evedatad,
|
15
|
+
proxy: database
|
16
|
+
).start
|
17
|
+
|
18
|
+
Signal.trap('TERM') do
|
19
|
+
data_server.stop
|
20
|
+
exit(0)
|
21
|
+
end
|
22
|
+
|
23
|
+
Evesync::Log.info('Database daemon started!')
|
24
|
+
|
25
|
+
begin
|
26
|
+
loop do
|
27
|
+
sleep 3600 # FIXME: 1 hour, rewrite better
|
28
|
+
# zip db if needed, save backup
|
29
|
+
end
|
30
|
+
rescue SignalException => e
|
31
|
+
data_server.stop
|
32
|
+
Evesync::Log.warn("Database daemon received signal: #{e.signm}(#{e.signo})")
|
33
|
+
exit(0)
|
34
|
+
end
|
data/bin/evehand
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'evesync/log'
|
5
|
+
require 'evesync/ipc/server'
|
6
|
+
require 'evesync/handler'
|
7
|
+
|
8
|
+
Evesync::Log.info('Handle daemon starting...')
|
9
|
+
|
10
|
+
all_handler = Evesync::Handler.new
|
11
|
+
|
12
|
+
handler_server = Evesync::IPC::Server.new(
|
13
|
+
port: :evehand,
|
14
|
+
proxy: all_handler,
|
15
|
+
ip: '*' # accept remote requests
|
16
|
+
).start
|
17
|
+
|
18
|
+
Evesync::Log.info('Handle daemon started!')
|
19
|
+
|
20
|
+
# Signal handling
|
21
|
+
|
22
|
+
Signal.trap('TERM') do
|
23
|
+
handler_server.stop
|
24
|
+
exit(0)
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
loop do
|
29
|
+
sleep 3600 # FIXME: 1 hour, rewrite better
|
30
|
+
# FIXME: know what to do
|
31
|
+
end
|
32
|
+
rescue SignalException => e
|
33
|
+
handler_server.stop
|
34
|
+
Evesync::Log.warn("Received signal: #{e.signm}(#{e.signo})")
|
35
|
+
exit(0)
|
36
|
+
end
|
data/bin/evemond
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'evesync/log'
|
5
|
+
require 'evesync/ipc/server'
|
6
|
+
require 'evesync/trigger'
|
7
|
+
require 'evesync/watcher'
|
8
|
+
|
9
|
+
Evesync::Log.info 'Monitoring daemon starting...'
|
10
|
+
|
11
|
+
queue = Queue.new
|
12
|
+
trigger = Evesync::Trigger.new(queue)
|
13
|
+
watcher = Evesync::Watcher.new(queue)
|
14
|
+
|
15
|
+
[trigger, watcher].each(&:start)
|
16
|
+
|
17
|
+
evesync_server = Evesync::IPC::Server.new(
|
18
|
+
port: :evemond,
|
19
|
+
proxy: trigger
|
20
|
+
).start
|
21
|
+
|
22
|
+
Evesync::Log.info 'Monitoring daemon started!'
|
23
|
+
|
24
|
+
# Signal handling
|
25
|
+
|
26
|
+
Signal.trap('SIGINT') do
|
27
|
+
[watcher, trigger].each(&:stop)
|
28
|
+
evesync_server.stop
|
29
|
+
exit(0)
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
loop do
|
34
|
+
sleep 100
|
35
|
+
# FIXME: know what to do
|
36
|
+
end
|
37
|
+
rescue SignalException => e
|
38
|
+
watcher.stop
|
39
|
+
evesync_server.stop
|
40
|
+
Evesync::Log.warn("Monitoring daemon received signal: #{e.signm}(#{e.signo})")
|
41
|
+
exit(0)
|
42
|
+
end
|
data/bin/evesync
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'socket'
|
6
|
+
require 'find'
|
7
|
+
require 'zip'
|
8
|
+
require 'evesync'
|
9
|
+
require 'evesync/log'
|
10
|
+
require 'evesync/utils'
|
11
|
+
require 'evesync/database'
|
12
|
+
require 'evesync/config'
|
13
|
+
require 'evesync/sync'
|
14
|
+
require 'evesync/ipc/client'
|
15
|
+
|
16
|
+
DB_TAG = 'db'
|
17
|
+
FILES_TAG = 'files'
|
18
|
+
|
19
|
+
opts = {}
|
20
|
+
$program = File.basename($0)
|
21
|
+
#Evesync::Log.level = :warn
|
22
|
+
Evesync::Log.simple = true
|
23
|
+
|
24
|
+
OptionParser.new do |parser|
|
25
|
+
parser.banner = "#{$program} [OPTIONS...]
|
26
|
+
|
27
|
+
"
|
28
|
+
parser.summary_width = 20
|
29
|
+
|
30
|
+
parser.on('-l', '--load FILE', 'Load events from file') do |f|
|
31
|
+
unless File.file? f
|
32
|
+
puts "File is absent: #{f}"
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
opts['load_file'] = f
|
36
|
+
end
|
37
|
+
|
38
|
+
parser.on('-z', '--zip [DEST]', 'Zip current database') do |d|
|
39
|
+
|
40
|
+
# Pretty default name
|
41
|
+
hostname = Socket.gethostname
|
42
|
+
hostname = hostname == 'localhost' \
|
43
|
+
? Evesync::Utils::local_ip : hostname
|
44
|
+
time_now = Time.now.strftime('%Y.%m.%d-%H:%M:%S')
|
45
|
+
opts['zip'] = d || "#{$program}_#{hostname}_#{time_now}.zip"
|
46
|
+
|
47
|
+
# Validation
|
48
|
+
unless File.directory? File.dirname opts['zip']
|
49
|
+
puts "Directory doesn't exist: #{File.dirname opts['zip']}"
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
parser.on('-f', '--force', 'Enforce synchronization') do
|
55
|
+
opts['sync'] = true
|
56
|
+
end
|
57
|
+
|
58
|
+
parser.on_tail('-v', '--version', "Version of #{$program}") do
|
59
|
+
puts Evesync::VERSION
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
|
63
|
+
parser.on_tail('-h', '--help', 'Help message') do
|
64
|
+
puts parser
|
65
|
+
exit
|
66
|
+
end
|
67
|
+
end.parse!
|
68
|
+
|
69
|
+
def force_sync
|
70
|
+
sync_client = Evesync::IPC::Client.new(
|
71
|
+
port: :evesyncd
|
72
|
+
)
|
73
|
+
sync_client.synchronize
|
74
|
+
end
|
75
|
+
|
76
|
+
def files_in(folder)
|
77
|
+
begin
|
78
|
+
Find.find(folder).collect { |file| file }
|
79
|
+
rescue StandardError
|
80
|
+
puts "No files in #{folder}"
|
81
|
+
[]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def zip(out)
|
86
|
+
databases = {
|
87
|
+
DB_TAG => {
|
88
|
+
Evesync::Config[:evedatad]['db_path'] =>
|
89
|
+
files_in(Evesync::Config[:evedatad]['db_path'])
|
90
|
+
},
|
91
|
+
FILES_TAG => {
|
92
|
+
Evesync::Config[:evedatad]['db_files_path'] =>
|
93
|
+
files_in(Evesync::Config[:evedatad]['db_files_path'])
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
Zip::File.open(out, Zip::File::CREATE) do |zip|
|
98
|
+
databases.each do |key, entries|
|
99
|
+
entries.each do |base_path, files|
|
100
|
+
files.each do |file|
|
101
|
+
relative_path = Pathname.new(file)
|
102
|
+
.relative_path_from(Pathname.new(base_path))
|
103
|
+
zip.add(File.join(key, relative_path.to_s), file)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def load_file(filename)
|
111
|
+
|
112
|
+
Dir.mktmpdir($program) do |tmpdir|
|
113
|
+
# Unpacking...
|
114
|
+
Zip::File.open(filename) do |zip|
|
115
|
+
zip.each do |entry|
|
116
|
+
entry.extract(File.join(tmpdir, entry.name))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
db_path = File.join(tmpdir, DB_TAG)
|
121
|
+
db_files_path = File.join(tmpdir, FILES_TAG)
|
122
|
+
|
123
|
+
loaded_db = Evesync::Database.new(
|
124
|
+
db_path,
|
125
|
+
db_files_path
|
126
|
+
)
|
127
|
+
|
128
|
+
local_db = Evesync::IPC::Client.new(
|
129
|
+
port: :evedatad
|
130
|
+
)
|
131
|
+
|
132
|
+
diff = Evesync::Sync::diff_missed(
|
133
|
+
v1: local_db.events,
|
134
|
+
v2: loaded_db.events
|
135
|
+
)
|
136
|
+
|
137
|
+
new_messages = loaded_db.messages(diff)
|
138
|
+
|
139
|
+
sync_client = Evesync::IPC::Client.new(
|
140
|
+
port: :evesyncd
|
141
|
+
)
|
142
|
+
|
143
|
+
sync_client.apply_events(new_messages)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
def evesync(opts)
|
149
|
+
if opts['sync']
|
150
|
+
puts 'Synchronization enforced'
|
151
|
+
force_sync
|
152
|
+
end
|
153
|
+
|
154
|
+
if opts['load_file']
|
155
|
+
load_file opts['load_file']
|
156
|
+
end
|
157
|
+
|
158
|
+
if opts['zip']
|
159
|
+
zip(opts['zip'])
|
160
|
+
puts(opts['zip'])
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
evesync opts
|
data/bin/evesyncd
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'evesync/log'
|
5
|
+
require 'evesync/sync'
|
6
|
+
require 'evesync/config'
|
7
|
+
require 'evesync/ipc/server'
|
8
|
+
|
9
|
+
# Exiting if `auto_discover = false'
|
10
|
+
unless Evesync::Config['auto_discover']
|
11
|
+
Evesync::Log.info('Synchronizing not required')
|
12
|
+
exit(0)
|
13
|
+
end
|
14
|
+
|
15
|
+
Evesync::Log.info('Synchronizing daemon starting...')
|
16
|
+
|
17
|
+
sync = Evesync::Sync.new
|
18
|
+
|
19
|
+
sync_server = Evesync::IPC::Server.new(
|
20
|
+
port: :evesyncd,
|
21
|
+
proxy: sync
|
22
|
+
).start
|
23
|
+
|
24
|
+
Signal.trap('TERM') do
|
25
|
+
sync_server.stop
|
26
|
+
exit(0)
|
27
|
+
end
|
28
|
+
|
29
|
+
Evesync::Log.info('Synchronizing daemon started!')
|
30
|
+
|
31
|
+
few_seconds = Evesync::Config['discover_timeout'].to_i
|
32
|
+
|
33
|
+
sync.discover # discovering nodes
|
34
|
+
sleep 3 # giving 3 seconds to complete
|
35
|
+
|
36
|
+
begin
|
37
|
+
loop do
|
38
|
+
sync.synchronize # updating this node
|
39
|
+
sleep few_seconds # ... in some interval
|
40
|
+
end
|
41
|
+
rescue SignalException
|
42
|
+
sync_server.stop
|
43
|
+
exit(0)
|
44
|
+
end
|
data/bin/start
ADDED
data/config/example.conf
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# This is a configuration file example
|
2
|
+
# It contains all information about daemons that can be changed
|
3
|
+
# It's TOML formatted file, so feel free to use this format
|
4
|
+
# without any restrictions.
|
5
|
+
#
|
6
|
+
# For more information about TOML format see:
|
7
|
+
# - https://github.com/toml-lang/toml
|
8
|
+
# - https://en.wikipedia.org/wiki/TOML
|
9
|
+
|
10
|
+
# Available log levels:
|
11
|
+
# debug info warn error fatal
|
12
|
+
loglevel = 'debug'
|
13
|
+
# Delay in seconds for discovery package sending
|
14
|
+
discover_timeout = 600
|
15
|
+
# Automate discovering
|
16
|
+
auto_discover = true
|
17
|
+
|
18
|
+
ntp = 'us.pool.ntp.org'
|
19
|
+
|
20
|
+
[evemond] # System Monitor daemon
|
21
|
+
port = 55443
|
22
|
+
|
23
|
+
# A list of remote nodes ips to keep connected with
|
24
|
+
remotes = [ ]
|
25
|
+
|
26
|
+
# Files to watch and synchronize
|
27
|
+
watch = [
|
28
|
+
'/etc/pam.d/login',
|
29
|
+
'/etc/pam.d/other',
|
30
|
+
]
|
31
|
+
|
32
|
+
# Interval for gathering files' changes
|
33
|
+
watch_interval = 3
|
34
|
+
|
35
|
+
# TODO:
|
36
|
+
ignore_packages = [
|
37
|
+
'ruby',
|
38
|
+
]
|
39
|
+
|
40
|
+
# TODO:
|
41
|
+
ignore_files = [
|
42
|
+
'/etc/hosts',
|
43
|
+
]
|
44
|
+
|
45
|
+
|
46
|
+
[evehand] # System Handler daemon
|
47
|
+
port = 55432
|
48
|
+
|
49
|
+
|
50
|
+
[evedatad] # System Data daemon
|
51
|
+
port = 54321
|
52
|
+
|
53
|
+
[evesyncd]
|
54
|
+
port = 64653
|
55
|
+
broadcast_port = 64564
|
56
|
+
|
57
|
+
|
58
|
+
# Copyright (c) Kiselev Valentin 2019
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'toml-rb'
|
2
|
+
require 'evesync/utils'
|
3
|
+
require 'evesync/constants'
|
4
|
+
require 'evesync/log'
|
5
|
+
|
6
|
+
module Evesync
|
7
|
+
module Config
|
8
|
+
class << self
|
9
|
+
|
10
|
+
DEFAULTS = {
|
11
|
+
'ntp' => '',
|
12
|
+
'evemond' => {
|
13
|
+
'port' => Constants::MOOND_PORT,
|
14
|
+
'remotes' => [],
|
15
|
+
'watch' => [],
|
16
|
+
'watch_interval' => Constants::WATCH_INTERVAL
|
17
|
+
},
|
18
|
+
'evedatad' => {
|
19
|
+
'port' => Constants::DATAD_PORT,
|
20
|
+
'db_path' => Constants::DB_PATH,
|
21
|
+
'db_files_path' => Constants::DB_FILES_PATH
|
22
|
+
},
|
23
|
+
'evehand' => {
|
24
|
+
'port' => Constants::HAND_PORT
|
25
|
+
},
|
26
|
+
'evesyncd' => {
|
27
|
+
'port' => Constants::SYNC_PORT
|
28
|
+
},
|
29
|
+
'discover_timeout' => Constants::DISCOVER_TIMEOUT
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
def [](daemon)
|
34
|
+
read_config if needs_reading
|
35
|
+
|
36
|
+
@@config[daemon.to_s]
|
37
|
+
end
|
38
|
+
|
39
|
+
def reread
|
40
|
+
read_config
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def read_config
|
46
|
+
config = begin
|
47
|
+
TomlRB.load_file(Constants::CONFIG_FILE)
|
48
|
+
rescue StandardError => e
|
49
|
+
Log.error("Config ERROR: Couldn't parse file #{Constants::CONFIG_FILE}")
|
50
|
+
Log.error("Config ERROR MESSAGE: #{e}")
|
51
|
+
Log.error("Config ERROR: Using default configuration")
|
52
|
+
{}
|
53
|
+
end
|
54
|
+
@@config = DEFAULTS.deep_merge(config)
|
55
|
+
Log.info("Config initialized!")
|
56
|
+
end
|
57
|
+
|
58
|
+
def needs_reading
|
59
|
+
! defined? @@config
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Evesync
|
2
|
+
module Constants
|
3
|
+
MOOND_PORT = '55443'.freeze
|
4
|
+
DATAD_PORT = '54321'.freeze
|
5
|
+
HAND_PORT = '55432'.freeze
|
6
|
+
SYNC_PORT = '64653'.freeze
|
7
|
+
|
8
|
+
CONFIG_FILE = '/etc/evesync.conf'.freeze
|
9
|
+
DB_PATH = '/var/lib/evesync/db/'.freeze
|
10
|
+
DB_FILES_PATH = '/var/lib/evesync/files/'.freeze
|
11
|
+
|
12
|
+
DEFAULT_LOGLEVEL = 'debug'.freeze
|
13
|
+
|
14
|
+
DISCOVER_TIMEOUT = 3600
|
15
|
+
WATCH_INTERVAL = 2
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
require 'lmdb'
|
4
|
+
require 'evesync/config'
|
5
|
+
require 'evesync/constants'
|
6
|
+
require 'evesync/ipc/data/package'
|
7
|
+
require 'evesync/ipc/data/file'
|
8
|
+
require 'evesync/ipc/data/ignore'
|
9
|
+
|
10
|
+
module Evesync
|
11
|
+
|
12
|
+
##
|
13
|
+
# *Database* class is a proxy for *evedatad* daemon
|
14
|
+
# implements at least one method: +save+. Allows
|
15
|
+
# Local +evemond+ save messages about changes
|
16
|
+
#
|
17
|
+
# Messages should be serializable (JSON)
|
18
|
+
#
|
19
|
+
# TODO:
|
20
|
+
# * Think about how it can be widened
|
21
|
+
|
22
|
+
class Database
|
23
|
+
def initialize(db_path=nil, db_files_path=nil)
|
24
|
+
path = db_path || Config[:evedatad]['db_path']
|
25
|
+
|
26
|
+
unless ::File.exist? path
|
27
|
+
# FIXME: only root. handle exception
|
28
|
+
FileUtils.mkdir_p(path)
|
29
|
+
end
|
30
|
+
@env = LMDB.new(path)
|
31
|
+
@db = @env.database
|
32
|
+
@files_path = db_files_path || Config[:evedatad]['db_files_path']
|
33
|
+
end
|
34
|
+
|
35
|
+
# Save message to database, key is timestamp+object
|
36
|
+
def save(message)
|
37
|
+
Log.debug("Database save: #{message}")
|
38
|
+
db_add_entry(message)
|
39
|
+
|
40
|
+
if message.is_a? Evesync::IPC::Data::File
|
41
|
+
Log.debug("Database save file action: #{message.action}")
|
42
|
+
unless message.action ==
|
43
|
+
IPC::Data::File::Action::DELETE
|
44
|
+
save_file(message)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
# Events simplified: object => [timestamp...]
|
51
|
+
def events
|
52
|
+
events = {}
|
53
|
+
@db.each do |key, _|
|
54
|
+
timestamp, object = parse_event(key)
|
55
|
+
events[object] ||= []
|
56
|
+
events[object].push(timestamp)
|
57
|
+
end
|
58
|
+
events
|
59
|
+
end
|
60
|
+
|
61
|
+
# Messages for events: object => {timestamp => message}
|
62
|
+
def messages(events)
|
63
|
+
ev_msgs = {}
|
64
|
+
@db.each do |key, message|
|
65
|
+
timestamp, object = parse_event(key)
|
66
|
+
next unless events.include?(object)
|
67
|
+
|
68
|
+
ev_msgs[object] ||= {}
|
69
|
+
if events[object].include?(timestamp)
|
70
|
+
ev_msgs[object][timestamp] = message
|
71
|
+
end
|
72
|
+
end
|
73
|
+
ev_msgs
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def db_add_entry(message)
|
79
|
+
Log.debug('Database adding entry...')
|
80
|
+
key = create_key(message)
|
81
|
+
value = create_value(message)
|
82
|
+
@db[key] = value
|
83
|
+
Log.debug('Database adding entry done!')
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_key(message)
|
87
|
+
"#{message.timestamp}_#{message.name}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_value(message)
|
91
|
+
message.to_hash.to_json
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_event(key)
|
95
|
+
key.split('_', 2)
|
96
|
+
end
|
97
|
+
|
98
|
+
def save_file(file)
|
99
|
+
Log.debug('Database saving file...')
|
100
|
+
fulldest = File.join(@files_path,
|
101
|
+
file.name + ".#{file.timestamp}")
|
102
|
+
FileUtils.mkdir_p(File.dirname(fulldest))
|
103
|
+
FileUtils.cp(file.name, fulldest)
|
104
|
+
Log.debug('Database saving file done!')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|