evesync 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acd82817da3db48b0d5f142a1a5764f50617e9e56abd55d9ecb20cd92cca0aaf
4
- data.tar.gz: 3dc586adc166118cda1961d6489914cb2193319642ab6c2fde7897db17f9a0a4
3
+ metadata.gz: 32546fdd2bf3681b09b5d76b29a9afe2559f726f328274b8d0cccbe26a6cbc46
4
+ data.tar.gz: b9e529c9972c92dcc3035ef8028600c6ecfe30004dd704dc01c0f45eb8728cce
5
5
  SHA512:
6
- metadata.gz: 4b6b3ab34063bd3f57ac41b2859983f999bc1cdab2a31b7a7da69b750ab564c8e7637c56250a4eca24aa958ae9b578730d2aa8cbffbb2a2acf6112bbd18cbaae
7
- data.tar.gz: 13897826a7bb2aee1e25f17a811c66483268e6a2f78e68a0797bc07ae74d33420c450a1ceb0134180858a72fcb656cc2b67ccad94b65a7471b11bbb5953f1d07
6
+ metadata.gz: 0d467ccd88887d72c85056c0097838cb9e11416e07d1ab2b3b616642a0984cef50c1a60cf0f3595c9c4e6aa806f4bd48fc2581aea56fe374c6f5a1bb669ceb38
7
+ data.tar.gz: 836b9e00da567d26161402c41146b37166d60627e536b0e4a26c6e154ee54fc21f2ed439ee09b0e9280b25be7663119229eab09eb98a2e2ef2e9c18ead41e8b8
data/Rakefile CHANGED
@@ -56,17 +56,20 @@ end
56
56
 
57
57
  ## Docker related targets
58
58
 
59
- task :docker do
60
- sh 'docker-compose build'
61
- end
59
+ namespace :docker do
62
60
 
63
- task :up do
64
- sh 'docker-compose up -d'
65
- end
61
+ task :build do
62
+ sh 'docker-compose build'
63
+ end
66
64
 
67
- task :down do
68
- sh 'docker-compose stop || docker-compose kill ||:'
69
- sh 'docker-compose rm --force ||:'
65
+ task :up do
66
+ sh 'docker-compose up -d node-1 node-2'
67
+ end
68
+
69
+ task :down do
70
+ sh 'docker-compose stop || docker-compose kill ||:'
71
+ sh 'docker-compose rm --force ||:'
72
+ end
70
73
  end
71
74
 
72
75
  namespace :rhel do
@@ -1,34 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require 'evesync/ipc/server'
5
- require 'evesync/log'
4
+ require 'evesync/service'
6
5
  require 'evesync/database'
7
6
 
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)
7
+ evedata = Evesync::Service.new(:evedatad) do |config|
8
+ config.proxy = Evesync::Database.new
9
+ # zip db if needed, save backup
21
10
  end
22
11
 
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
12
+ evedata.start
@@ -1,36 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require 'evesync/log'
5
- require 'evesync/ipc/server'
4
+ require 'evesync/service'
6
5
  require 'evesync/handler'
7
6
 
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)
7
+ evehand = Evesync::Service.new(:evehand) do |config|
8
+ config.proxy = Evesync::Handler.new
9
+ config.ip = '*'
25
10
  end
26
11
 
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
12
+ evehand.start
@@ -1,42 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require 'evesync/log'
5
- require 'evesync/ipc/server'
4
+ require 'evesync/service'
6
5
  require 'evesync/trigger'
7
6
  require 'evesync/watcher'
8
7
 
9
- Evesync::Log.info 'Monitoring daemon starting...'
10
-
11
8
  queue = Queue.new
12
9
  trigger = Evesync::Trigger.new(queue)
13
10
  watcher = Evesync::Watcher.new(queue)
14
11
 
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)
12
+ evemon = Evesync::Service.new(:evemond) do |config|
13
+ config.proxy = trigger
14
+ config.at_start = lambda { [trigger, watcher].each(&:start) }
15
+ config.at_exit = lambda { [trigger, watcher].each(&:stop) }
30
16
  end
31
17
 
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
18
+ evemon.start
@@ -14,28 +14,24 @@ require 'evesync/config'
14
14
  require 'evesync/sync'
15
15
  require 'evesync/ipc/client'
16
16
 
17
- DB_TAG = 'db'
18
- FILES_TAG = 'files'
17
+ DB_TAG = 'db'.freeze
18
+ FILES_TAG = 'files'.freeze
19
19
 
20
- opts = {}
20
+ opts = {}
21
21
  $program = File.basename($0)
22
- #Evesync::Log.level = :warn
23
- Evesync::Log.simple = true
24
22
 
25
23
  def kill_by_pid(daemon)
26
24
  begin
27
- Process.kill('TERM', File.read("/var/run/evesync/#{daemon}.pid").to_i)
28
- rescue Errno::ESRCH
25
+ puts "Killing #{daemon}..."
26
+ pid = File.read("/var/run/evesync/#{daemon}.pid").to_i
27
+ Process.kill('INT', pid)
28
+ rescue Errno::ESRCH, Errno::ENOENT
29
29
  puts("#{daemon} already killed")
30
30
  end
31
31
  end
32
32
 
33
33
  def spawn_daemon(daemon)
34
- pid = spawn(daemon,
35
- :err => "/var/log/evesync/#{daemon}.log",
36
- :out=>:err)
37
- File.write("/var/run/evesync/#{daemon}.pid", pid)
38
- pid
34
+ system(daemon)
39
35
  end
40
36
 
41
37
  OptionParser.new do |parser|
@@ -84,8 +80,6 @@ OptionParser.new do |parser|
84
80
 
85
81
  # TODO: refactor
86
82
  parser.on('-r', '--run', 'Start daemons') do
87
- FileUtils.mkdir_p '/var/log/evesync'
88
- FileUtils.mkdir_p '/var/run/evesync'
89
83
  spawn_daemon 'evedatad'
90
84
  spawn_daemon 'evemond'
91
85
  spawn_daemon 'evehand'
@@ -99,10 +93,8 @@ OptionParser.new do |parser|
99
93
  kill_by_pid 'evesyncd'
100
94
  kill_by_pid 'evedatad'
101
95
  rescue StandardError => e
102
- puts("Error: #{e}")
103
- puts('Something went wrong while killing processes. Do it yourself!')
104
- ensure
105
- FileUtils.rm_f Dir.glob('/var/run/evesync/*.pid')
96
+ puts("(!) Error: #{e} (!)")
97
+ puts('Something went wrong while killing processes...')
106
98
  end
107
99
  end
108
100
  end.parse!
@@ -1,44 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require 'evesync/log'
4
+ require 'evesync/service'
5
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
6
 
17
7
  sync = Evesync::Sync.new
18
8
 
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)
9
+ evesync = Evesync::Service.new(:evesyncd) do |config|
10
+ config.proxy = sync
11
+ config.at_start = sync.method(:discover)
12
+ config.interval = 15 # TODO: read from config
27
13
  end
28
14
 
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)
15
+ evesync.start do
16
+ sync.synchronize
44
17
  end
data/bin/start CHANGED
@@ -1,16 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- trap 'echo Exiting; \
3
- pkill evedatad; \
4
- pkill evemond; \
5
- pkill evehand; \
6
- pkill evesyncd
7
- exit 1' 2
8
- evedatad &
9
- evemond &
10
- evehand &
11
- sleep 3s
12
- evesyncd &
13
-
14
- while true; do
15
- sleep 1000
16
- done
2
+ evedatad
3
+ evemond
4
+ evehand
5
+ evesyncd
@@ -1,3 +1,3 @@
1
1
  module Evesync
2
- VERSION = '1.0.7'.freeze
2
+ VERSION = '1.0.8'.freeze
3
3
  end
@@ -9,7 +9,7 @@ module Evesync
9
9
  DB_PATH = '/var/lib/evesync/db/'.freeze
10
10
  DB_FILES_PATH = '/var/lib/evesync/files/'.freeze
11
11
 
12
- DEFAULT_LOGLEVEL = 'info'.freeze
12
+ DEFAULT_LOGLEVEL = :info
13
13
 
14
14
  DISCOVER_TIMEOUT = 3600
15
15
  WATCH_INTERVAL = 2
@@ -1,6 +1,9 @@
1
1
  require 'evesync/ipc/client'
2
2
  require 'evesync/log'
3
3
  require 'evesync/config'
4
+ require 'evesync/os'
5
+
6
+ require 'json'
4
7
 
5
8
  module Evesync
6
9
 
@@ -35,14 +38,14 @@ module Evesync
35
38
  # Sending UDP message on broadcast
36
39
  # Discovering our nodes
37
40
 
38
- def send_discovery_message(ip = '<broadcast>', message = DISCOVERY_REQ)
41
+ def send_discovery_message(ip='<broadcast>', message=DISCOVERY_REQ)
39
42
  udp_sock = UDPSocket.new
40
- if ip == '<broadcast>'
43
+ if is_broadcast(ip)
41
44
  udp_sock.setsockopt(
42
45
  Socket::SOL_SOCKET, Socket::SO_BROADCAST, true
43
46
  )
44
47
  end
45
- udp_sock.send(message, 0, ip, @port)
48
+ udp_sock.send(to_discover_msg(message: message), 0, ip, @port)
46
49
  udp_sock.close
47
50
  end
48
51
 
@@ -54,17 +57,18 @@ module Evesync
54
57
 
55
58
  def listen_discovery
56
59
  loop do
57
- data, recvdata = @listen_sock.recvfrom(1024)
60
+ datajson, recvdata = @listen_sock.recvfrom(1024)
58
61
  node_ip = recvdata[-1]
59
62
 
60
63
  next if Utils.local_ip?(node_ip)
61
64
 
62
- if [DISCOVERY_REQ, DISCOVERY_ANS].include? data
65
+ data = from_discover_msg(datajson)
66
+ if fine_node?(data)
63
67
  # Push new node_ip to trigger
64
68
  @evesync.add_remote_node(node_ip)
65
69
  end
66
70
 
67
- case data
71
+ case data['message']
68
72
  when DISCOVERY_REQ
69
73
  Log.info("Discover host request got: #{node_ip}")
70
74
  send_discovery_message(node_ip, DISCOVERY_ANS)
@@ -73,5 +77,29 @@ module Evesync
73
77
  end
74
78
  end
75
79
  end
80
+
81
+ def to_discover_msg(msg)
82
+ {
83
+ evesync: {
84
+ message: msg,
85
+ os: EVESYNC_OS,
86
+ }
87
+ }.to_json.freeze
88
+ end
89
+
90
+ def from_discover_msg(data)
91
+ JSON.parse(data)['evesync'] # TODO: catch error
92
+ end
93
+
94
+ def is_broadcast(ip)
95
+ ip == '<broadcast>'
96
+ end
97
+
98
+ def fine_node?(data)
99
+ [
100
+ [DISCOVERY_ANS, DISCOVERY_REQ].include?(data['message']),
101
+ data['os'] == EVESYNC_OS,
102
+ ].all?
103
+ end
76
104
  end
77
105
  end
@@ -48,7 +48,7 @@ module Evesync
48
48
  end
49
49
 
50
50
  def stop
51
- DRb.thread.exit
51
+ DRb.stop_service
52
52
  self
53
53
  end
54
54
  end
@@ -1,62 +1,105 @@
1
- require 'logger'
2
1
  require 'evesync/config'
3
2
  require 'evesync/constants'
4
3
 
4
+ require 'syslog'
5
+ require 'logger'
6
+ require 'fileutils'
5
7
 
6
8
  module Evesync
7
9
 
8
- # This module is responsible for logging
10
+ # Logging via syslog
9
11
  module Log
10
12
  # Supported levels for logging
11
- LEVELS = %i[debug info warn error fatal].freeze
13
+ LEVELS = %i[debug info notice warn error fatal]
14
+ def LEVELS.less(a, b)
15
+ (self.index(a) <=> self.index(b) or -1) >= 0
16
+ end
17
+
18
+ # Default engine for logging, one of (:io, :syslog)
19
+ DEFAULT_ENGINE = :io
20
+
21
+ # Log level mapping for syslog
22
+ SYSLOG = {
23
+ :debug => Syslog::LOG_DEBUG,
24
+ :info => Syslog::LOG_INFO,
25
+ :notice => Syslog::LOG_NOTICE,
26
+ :warn => Syslog::LOG_WARNING,
27
+ :error => Syslog::LOG_ERR,
28
+ :fatal => Syslog::LOG_CRIT,
29
+ #:alert => Syslog::LOG_ALERT,
30
+ #:emerg => Syslog::LOG_EMERG,
31
+ }
32
+
33
+ SYSLOG_OPTIONS = [
34
+ Syslog::LOG_PID,
35
+ Syslog::LOG_NOWAIT,
36
+ Syslog::LOG_CONS,
37
+ Syslog::LOG_PERROR,
38
+ ].inject(&:|)
39
+
40
+ SYSLOG_FACILITY = [
41
+ Syslog::LOG_DAEMON,
42
+ Syslog::LOG_LOCAL5,
43
+ ].inject(&:|)
12
44
 
45
+ # Public methods available via Log.method
13
46
  class << self
14
- def method_missing(m, *args)
15
- # Unlisted methods are not allowed
16
- raise NoMethodError unless LEVELS.include?(m)
17
47
 
18
- check_logger
19
- @logger.send(m, to_string(*args))
20
- nil
21
- end
48
+ LEVELS.each do |level|
49
+ define_method(level) do |*args|
50
+ check_logger
51
+ return unless LEVELS.less(level.to_sym, @level.to_sym)
22
52
 
23
- def check_logger
24
- init_logger unless @logger
53
+ case @engine
54
+ when :syslog
55
+ @logger.log(SYSLOG[level], to_string(*args))
56
+ when :io
57
+ @logger.send(level, to_string(*args))
58
+ end
59
+
60
+ nil # prevent from being able to access the object
61
+ end
25
62
  end
26
63
 
27
64
  def level=(lvl)
28
65
  check_logger
29
- if lvl.is_a?(Symbol) or lvl.is_a?(String)
30
- @logger.level =
31
- begin
32
- Logger.const_get(lvl.to_s.upcase)
33
- rescue NameError
34
- Logger::DEBUG
35
- end
36
- end
66
+ raise "Unknown level #{lvl}" unless LEVELS.include? lvl
67
+ @level = lvl
37
68
  end
38
69
 
39
70
  def level
40
- check_logger
41
- @logger.level
71
+ @level
42
72
  end
43
73
 
44
- def simple=(bool)
74
+ def check_logger
45
75
  init_logger unless @logger
46
- if bool
47
- @logger.formatter = proc do |_sev, _dt, _prog, msg|
48
- "#{msg}\n"
49
- end
50
- end
51
76
  end
52
77
 
78
+ def engine=(engine)
79
+ raise UnsupportedLogEngine.new(engine) \
80
+ unless [:syslog, :io].member? engine
81
+ @engine = engine
82
+ end
83
+
84
+ # Using syslog implementation
53
85
  def init_logger
54
- @logger = Logger.new(STDERR)
55
- @logger.formatter = proc do |sev, dtime, _prog, msg|
56
- time = dtime.strftime('%Y-%m-%d %H:%M:%S')
57
- prog = File.basename($PROGRAM_NAME)
58
- "[#{time}] #{prog.ljust(8)} #{sev.ljust(5)}: #{msg}\n"
86
+ @engine ||= DEFAULT_ENGINE
87
+ prog = File.basename($PROGRAM_NAME)
88
+
89
+ case @engine
90
+ when :syslog
91
+ @logger = Syslog.open(prog, SYSLOG_OPTIONS, SYSLOG_FACILITY)
92
+
93
+ when :io
94
+ FileUtils.mkdir_p '/var/log/evesync/'
95
+ @logger = Logger.new("/var/log/evesync/#{prog}.log")
96
+ @logger.formatter = proc do |sev, dtime, _prog, msg|
97
+ time = dtime.strftime('%Y-%m-%d %H:%M:%S')
98
+ "[#{time}] #{prog.ljust(8)} #{sev.ljust(5)}: #{msg}\n"
99
+ end
59
100
  end
101
+
102
+ @level = Config[:loglevel] || :info
60
103
  end
61
104
 
62
105
  def to_string(*args)
@@ -2,8 +2,13 @@ text = File.new('/etc/os-release').read
2
2
 
3
3
  if text =~ /^ID.*(rhel|centos|fedora)/
4
4
  require 'evesync/os/linux/rhel'
5
+ EVESYNC_OS = 'rhel'.freeze
5
6
  elsif text =~ /ID.*arch/
6
7
  require 'evesync/os/linux/arch'
8
+ EVESYNC_OS = 'arch'.freeze
7
9
  elsif text =~ /ID.*debian/
8
10
  require 'evesync/os/linux/deb'
11
+ EVESYNC_OS = 'deb'.freeze
12
+ else
13
+ EVESYNC_OS = 'not implemented'
9
14
  end
@@ -0,0 +1,104 @@
1
+ require 'evesync/log'
2
+ require 'evesync/ipc/server'
3
+
4
+ require 'fileutils'
5
+
6
+ module Evesync
7
+ # Class for creating daemons which are DRb servers with
8
+ # proxy object to accept requests.
9
+ #
10
+ # Traps signals to exit.
11
+ #
12
+ # Example:
13
+ # d = Evesync::Service.new(:mydaemond) do |config|
14
+ # config.proxy = SomeProxyObject.new
15
+ # end
16
+ #
17
+ # d.start
18
+ #
19
+ class Service
20
+ def initialize(name)
21
+ @factory = ServiceFactory.new
22
+ @factory.name = name unless name.nil?
23
+ yield @factory
24
+ end
25
+
26
+ def start
27
+ daemonize
28
+
29
+ Log.info("#{@factory.name} daemon starting...")
30
+
31
+ @ipc_server = IPC::Server.new(
32
+ port: @factory.port,
33
+ proxy: @factory.proxy,
34
+ ip: @factory.ip,
35
+ ).start
36
+
37
+ Signal.trap('TERM') do
38
+ @ipc_server.stop
39
+ exit 0
40
+ end
41
+
42
+ Log.info("#{@factory.name} daemon started!")
43
+
44
+ @factory.at_start.call if @factory.at_start.respond_to? :call
45
+
46
+ loop do
47
+ sleep @factory.interval
48
+ yield if block_given?
49
+ end
50
+
51
+ rescue SignalException => e
52
+ Log.warn("#{@factory.name} daemon received signal: " \
53
+ "#{e.signm}(#{e.signo})")
54
+ exit 0
55
+
56
+ # rubocop:disable Lint/RescueException
57
+ rescue Exception => crit
58
+ Log.fatal(crit)
59
+ crit.backtrace.each { |line| Log.fatal(line) }
60
+ exit 1
61
+
62
+ # rubocop:enable Lint/RescueException
63
+ ensure
64
+ @factory.at_exit.call if @factory.at_exit.respond_to? :call
65
+ @ipc_server.stop
66
+ end
67
+
68
+ def daemonize
69
+ Process.daemon
70
+ Process.setproctitle(@factory.name.to_s) \
71
+ if Process.respond_to? :setproctitle
72
+ $0 = @factory.name.to_s
73
+ FileUtils.mkdir_p @factory.pids
74
+ File.open("#{@factory.pids}/#{@factory.name}.pid", 'w') do |f|
75
+ f.puts(Process.pid)
76
+ end
77
+ end
78
+ end
79
+
80
+ class ServiceFactory
81
+ attr_accessor :name, :proxy, :at_start, :at_exit
82
+ attr_writer :interval, :port, :ip, :logs, :pids
83
+
84
+ def logs
85
+ @logs || '/var/log/evesync/'
86
+ end
87
+
88
+ def pids
89
+ @pids || '/var/run/evesync/'
90
+ end
91
+
92
+ def port
93
+ @port || name.to_sym
94
+ end
95
+
96
+ def ip
97
+ @ip || 'localhost'
98
+ end
99
+
100
+ def interval
101
+ @interval || 3600
102
+ end
103
+ end
104
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evesync
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kiselev Valentine
@@ -163,6 +163,7 @@ files:
163
163
  - lib/evesync/os/linux/rhel/package_manager.rb
164
164
  - lib/evesync/os/linux/rhel/package_watcher.rb
165
165
  - lib/evesync/os/linux/rhel/rpm.rb
166
+ - lib/evesync/service.rb
166
167
  - lib/evesync/sync.rb
167
168
  - lib/evesync/trigger.rb
168
169
  - lib/evesync/trigger/base.rb