adminix 0.1.49 → 0.2
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.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/adminix.gemspec +1 -4
- data/app/assets/images/logo.png +0 -0
- data/app/assets/javascripts/application.js +50 -0
- data/app/assets/javascripts/bootstrap.min.js +7 -0
- data/app/assets/javascripts/dataTables.bootstrap4.js +184 -0
- data/app/assets/javascripts/jquery.dataTables.js +15243 -0
- data/app/assets/javascripts/jquery.min.js +2 -0
- data/app/assets/javascripts/sb-admin-2.min.js +6 -0
- data/app/assets/stylesheets/bootstrap.min.css +6 -0
- data/app/assets/stylesheets/dataTables.bootstrap.css +314 -0
- data/app/assets/stylesheets/dataTables.responsive.css +106 -0
- data/app/assets/stylesheets/font-awesome.min.css +4 -0
- data/app/assets/stylesheets/sb-admin-2.min.css +5 -0
- data/app/views/scripts/restart_watcher.sh.erb +9 -0
- data/app/views/scripts/run_script.sh.erb +12 -0
- data/app/views/scripts/start_process.sh.erb +7 -0
- data/app/views/scripts/stop_process.sh.erb +7 -0
- data/app/views/scripts/update_process.sh.erb +24 -0
- data/app/views/scripts/update_watcher.sh.erb +3 -0
- data/app/views/web/dashboard.html.erb +90 -0
- data/app/views/web/job.html.erb +46 -0
- data/app/views/web/link.html.erb +12 -0
- data/app/views/web/loadstamp.html.erb +57 -0
- data/app/views/web/log.html.erb +49 -0
- data/app/views/web/partials/footer.html.erb +11 -0
- data/app/views/web/partials/header.html.erb +50 -0
- data/bin/install_adminix +40 -0
- data/bin/push +13 -0
- data/development.log +0 -0
- data/exe/adminix +91 -28
- data/lib/adminix.rb +42 -5
- data/lib/adminix/config.rb +170 -96
- data/lib/adminix/entities.rb +5 -0
- data/lib/adminix/entities/job.rb +54 -0
- data/lib/adminix/entities/log.rb +21 -0
- data/lib/adminix/entities/service.rb +211 -0
- data/lib/adminix/entities/sysload_stamp.rb +37 -0
- data/lib/adminix/entities/variable.rb +32 -0
- data/lib/adminix/helpers.rb +7 -2
- data/lib/adminix/helpers/command.rb +73 -0
- data/lib/adminix/helpers/files.rb +82 -0
- data/lib/adminix/helpers/log_reader.rb +16 -0
- data/lib/adminix/helpers/net_http.rb +63 -0
- data/lib/adminix/helpers/output.rb +28 -0
- data/lib/adminix/helpers/systemctl.rb +54 -0
- data/lib/adminix/services.rb +3 -0
- data/lib/adminix/services/app_service.rb +143 -0
- data/lib/adminix/services/logs_service.rb +13 -0
- data/lib/adminix/services/system_load_service.rb +16 -0
- data/lib/adminix/version.rb +1 -1
- data/lib/adminix/watcher.rb +76 -144
- data/lib/adminix/web.rb +4 -0
- data/lib/adminix/web/router.rb +98 -0
- data/lib/adminix/web/server.rb +60 -0
- data/lib/adminix/web/view_helper.rb +14 -0
- data/lib/event_machine.rb +2 -0
- data/lib/event_machine/http_server.rb +2 -0
- data/lib/event_machine/http_server/response.rb +314 -0
- data/lib/event_machine/http_server/server.rb +107 -0
- data/lib/event_machine/tail.rb +2 -0
- data/lib/event_machine/tail/filetail.rb +470 -0
- data/lib/event_machine/tail/globwatcher.rb +294 -0
- metadata +60 -45
- data/lib/adminix/errors.rb +0 -7
- data/lib/adminix/helpers/file.rb +0 -13
- data/lib/adminix/helpers/http.rb +0 -19
- data/lib/adminix/log_watch_handler.rb +0 -23
- data/lib/adminix/server_setup.rb +0 -76
- data/lib/adminix/service.rb +0 -179
- data/lib/adminix/setup.rb +0 -3
- data/lib/adminix/setup/routes.rb +0 -113
- data/lib/adminix/setup/services.rb +0 -139
- data/lib/adminix/setup/views.rb +0 -183
- data/lib/adminix/system.rb +0 -106
- data/views/daemon_scripts/upstart.conf.erb +0 -23
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Adminix
|
6
|
+
module Helpers
|
7
|
+
module Files
|
8
|
+
def self.read_json_file(file)
|
9
|
+
content = IO.read(file)
|
10
|
+
JSON.parse(content)
|
11
|
+
rescue JSON::ParserError
|
12
|
+
Helpers::Output.display_error_and_exit(
|
13
|
+
"Error reading JSON inside file #{file}"
|
14
|
+
)
|
15
|
+
{}
|
16
|
+
rescue Errno::ENOENT
|
17
|
+
Helpers::Output.display_error_and_exit("Error reading file #{file}")
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.read_yaml_file(file)
|
22
|
+
content = IO.read(file)
|
23
|
+
obj = YAML.safe_load(content)
|
24
|
+
if obj.is_a? String
|
25
|
+
Helpers::Output.display_error_and_exit("Error reading file #{file}")
|
26
|
+
{}
|
27
|
+
end
|
28
|
+
obj
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
Helpers::Output.display_error_and_exit("Error reading file #{file}")
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.read_plain_file(file)
|
35
|
+
IO.read(file)
|
36
|
+
rescue Errno::ENOENT
|
37
|
+
Helpers::Output.display_error_and_exit("Error reading file #{file}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.write_json_file(file, content)
|
41
|
+
open(file, 'w') { |f| f.puts(content.to_json) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.write_yaml_file(file, content)
|
45
|
+
open(file, 'w') { |f| f.puts(content.to_yaml) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.write_plain_file(file, content)
|
49
|
+
open(file, 'w') { |f| f.puts(content) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.rm(file)
|
53
|
+
File.delete(file) if File.exist?(file)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.mkdir_p(dirname)
|
57
|
+
`mkdir -p #{dirname}`
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.touch(file_path)
|
61
|
+
`touch #{file_path}`
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.file_exists?(file)
|
65
|
+
File.exist?(file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.read_erb_tpl(file, binding)
|
69
|
+
path = "#{Adminix.root}/app/views/web/#{file}.erb"
|
70
|
+
return unless File.exist?(path)
|
71
|
+
template = ERB.new File.read(path), nil, '%'
|
72
|
+
template.result(binding)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.read_asset(file)
|
76
|
+
path = "#{Adminix.root}/app/assets#{file}"
|
77
|
+
return unless File.exist?(path)
|
78
|
+
IO.read(path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Helpers
|
3
|
+
class LogReader < EventMachine::FileTail
|
4
|
+
def initialize(path, startpos=-1)
|
5
|
+
super(path, startpos)
|
6
|
+
Adminix.logger.info "Tailing #{path}"
|
7
|
+
@buffer = BufferedTokenizer.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def receive_data(data)
|
11
|
+
lines = @buffer.extract(data)
|
12
|
+
Services::LogsService.add_logs(Adminix.watcher, path, lines)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Adminix
|
4
|
+
module Helpers
|
5
|
+
class NetHTTP
|
6
|
+
def self.get(path)
|
7
|
+
uri = URI.parse("#{Adminix.config.api_host}/v1/#{path}")
|
8
|
+
request = Net::HTTP::Get.new(uri)
|
9
|
+
default_headers.each { |h| request[h[0]] = h[1] }
|
10
|
+
|
11
|
+
opts = { use_ssl: uri.scheme == 'https' }
|
12
|
+
response = Net::HTTP.start(uri.hostname, uri.port, opts) do |http|
|
13
|
+
http.request(request)
|
14
|
+
end
|
15
|
+
|
16
|
+
read_response_body(response)
|
17
|
+
rescue SocketError, Net::OpenTimeout, Net::ReadTimeout
|
18
|
+
Adminix.logger.error("Can't connect to API")
|
19
|
+
[false, nil]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.post(path, payload)
|
23
|
+
uri = URI.parse("#{Adminix.config.api_host}/v1/#{path}")
|
24
|
+
request = Net::HTTP::Post.new(uri)
|
25
|
+
request.content_type = 'application/json'
|
26
|
+
request.body = payload.to_json
|
27
|
+
default_headers.each { |h| request[h[0]] = h[1] }
|
28
|
+
|
29
|
+
opts = { use_ssl: uri.scheme == 'https' }
|
30
|
+
response = Net::HTTP.start(uri.hostname, uri.port, opts) do |http|
|
31
|
+
http.request(request)
|
32
|
+
end
|
33
|
+
|
34
|
+
read_response_body(response)
|
35
|
+
rescue SocketError, Net::OpenTimeout, Net::ReadTimeout
|
36
|
+
Adminix.logger.error("Can't connect to API")
|
37
|
+
[false, nil]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.read_response_body(response)
|
41
|
+
unless response.is_a? Net::HTTPSuccess
|
42
|
+
Adminix.logger.error("Received code #{response.code} from API")
|
43
|
+
return [false, response.code]
|
44
|
+
end
|
45
|
+
|
46
|
+
data = JSON.parse(response.body)
|
47
|
+
|
48
|
+
success = data['success'] || false
|
49
|
+
result = data['result']
|
50
|
+
|
51
|
+
[success, result]
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.default_headers
|
55
|
+
[
|
56
|
+
['Authorization', "Bearer #{Adminix.config.secret_key}"],
|
57
|
+
['X-Watcher-Version', Adminix::VERSION],
|
58
|
+
['Accept', 'application/json']
|
59
|
+
]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Helpers
|
3
|
+
module Output
|
4
|
+
def self.display_message(msg)
|
5
|
+
return puts(msg) unless Adminix.test?
|
6
|
+
Adminix.logger.info(msg)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.display_multiline_message(lines)
|
10
|
+
unless Adminix.test?
|
11
|
+
lines.each { |msg| puts(msg) }
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
lines.each { |msg| Adminix.logger.info(msg) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.display_error_and_exit(msg)
|
19
|
+
unless Adminix.test?
|
20
|
+
puts "Error: #{msg}"
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
Adminix.logger.error(msg)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Helpers
|
3
|
+
class Systemctl
|
4
|
+
TMP_SCRIPT_PATH = '/tmp/write_systemctl_script.sh'.freeze
|
5
|
+
|
6
|
+
def initialize(opts = {})
|
7
|
+
@adminix_bin = opts[:adminix_bin] || Helpers::Command.which('adminix')
|
8
|
+
@user = opts[:user] || Helpers::Command.whoami
|
9
|
+
@group = opts[:group] || Helpers::Command.whoami
|
10
|
+
@working_dir = opts[:working_dir] || Helpers::Command.home
|
11
|
+
@systemctl_path = Adminix.config.systemctl[:watcher_service_path]
|
12
|
+
end
|
13
|
+
|
14
|
+
def write
|
15
|
+
Helpers::Files.rm(TMP_SCRIPT_PATH)
|
16
|
+
Helpers::Files.write_plain_file(TMP_SCRIPT_PATH, to_s)
|
17
|
+
Helpers::Output.display_multiline_message([
|
18
|
+
"sudo sh #{TMP_SCRIPT_PATH}",
|
19
|
+
'# Run this command to configure your shell:',
|
20
|
+
'# eval $(adminix write_systemctl)'
|
21
|
+
])
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"#!/bin/bash\n" \
|
26
|
+
"touch #{@systemctl_path}\n" \
|
27
|
+
"cat << EOT > #{@systemctl_path}\n" \
|
28
|
+
"[Unit]\n" \
|
29
|
+
"Description=Adminix\n" \
|
30
|
+
"Requires=network.target\n\n" \
|
31
|
+
"[Service]\n" \
|
32
|
+
"Type=simple\n" \
|
33
|
+
"User=#{@user}\n" \
|
34
|
+
"Group=#{@group}\n" \
|
35
|
+
"WorkingDirectory=#{@working_dir}\n" \
|
36
|
+
"ExecStart=#{@adminix_bin} watch\n" \
|
37
|
+
"Restart=always\n" \
|
38
|
+
"RestartSec=5\n" \
|
39
|
+
"StandardInput=null\n" \
|
40
|
+
"StandardOutput=syslog\n" \
|
41
|
+
"StandardError=syslog\n" \
|
42
|
+
"SyslogIdentifier=%n\n" \
|
43
|
+
"KillMode=mixed\n" \
|
44
|
+
"TimeoutStopSec=5\n" \
|
45
|
+
"TimeoutSec=300\n\n" \
|
46
|
+
"[Install]\n" \
|
47
|
+
"WantedBy=multi-user.target\n" \
|
48
|
+
"EOT\n" \
|
49
|
+
"# Run this command to configure your shell:\n" \
|
50
|
+
'# eval $(adminix write_systemctl)'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Services
|
3
|
+
class AppService
|
4
|
+
attr_reader :service
|
5
|
+
|
6
|
+
def initialize(service)
|
7
|
+
@service = service
|
8
|
+
end
|
9
|
+
|
10
|
+
def sync
|
11
|
+
return if !Adminix.config.credentials_defined? || @service.locked?
|
12
|
+
|
13
|
+
service.lock
|
14
|
+
payload = service.sync_payload
|
15
|
+
|
16
|
+
success, result = Helpers::NetHTTP.post(
|
17
|
+
"services/#{service.id}/sync_device",
|
18
|
+
payload
|
19
|
+
)
|
20
|
+
unless success
|
21
|
+
service.unlock
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
service.reset_performed_actions
|
26
|
+
service.remove_completed_jobs
|
27
|
+
service.clean_sent_logs
|
28
|
+
service.clean_load_stamps
|
29
|
+
service.add_new_jobs(result['jobs'])
|
30
|
+
upgrade_watcher if result['upgrade_watcher'] == true
|
31
|
+
start_process if result['start_process'] == true
|
32
|
+
stop_process if result['stop_process'] == true
|
33
|
+
restart_process if result['restart_process'] == true
|
34
|
+
update_process if result['update_process'] == true
|
35
|
+
|
36
|
+
service.unlock
|
37
|
+
# rescue => e
|
38
|
+
# service.unclock
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_jobs
|
42
|
+
@service.new_jobs[0..1].each(&:perform)
|
43
|
+
end
|
44
|
+
|
45
|
+
def allow_sending_logs
|
46
|
+
@service.allow_sending_logs
|
47
|
+
end
|
48
|
+
|
49
|
+
def allow_sending_system_load
|
50
|
+
@service.allow_sending_system_load
|
51
|
+
end
|
52
|
+
|
53
|
+
def upgrade_watcher
|
54
|
+
Adminix.logger.info 'Upgrading watcher'
|
55
|
+
out = Helpers::Command.run_system_command(
|
56
|
+
Adminix.config.scripts[:upgrade_watcher]
|
57
|
+
)
|
58
|
+
|
59
|
+
[true, out]
|
60
|
+
end
|
61
|
+
|
62
|
+
def update_process
|
63
|
+
Adminix.logger.info 'Updating process'
|
64
|
+
out = Helpers::Command.run_system_command(
|
65
|
+
Adminix.config.scripts[:update_process]
|
66
|
+
)
|
67
|
+
service.define_performed_action(:process_updated, true)
|
68
|
+
|
69
|
+
[true, out]
|
70
|
+
end
|
71
|
+
|
72
|
+
def start_process
|
73
|
+
Adminix.logger.info 'Starting process'
|
74
|
+
out = Helpers::Command.run_system_command(
|
75
|
+
Adminix.config.scripts[:start_process]
|
76
|
+
)
|
77
|
+
service.define_performed_action(:process_stopped, false)
|
78
|
+
service.define_performed_action(:process_started, true)
|
79
|
+
|
80
|
+
[true, out]
|
81
|
+
end
|
82
|
+
|
83
|
+
def restart_process
|
84
|
+
Adminix.logger.info 'Restarting process'
|
85
|
+
stop_process
|
86
|
+
_, out = start_process
|
87
|
+
|
88
|
+
[true, out]
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop_process
|
92
|
+
Adminix.logger.info 'Stopping process'
|
93
|
+
out = Helpers::Command.run_system_command(
|
94
|
+
Adminix.config.scripts[:stop_process]
|
95
|
+
)
|
96
|
+
service.define_performed_action(:process_started, false)
|
97
|
+
service.define_performed_action(:process_stopped, true)
|
98
|
+
|
99
|
+
[true, out]
|
100
|
+
end
|
101
|
+
|
102
|
+
def download_source
|
103
|
+
read_vars
|
104
|
+
list = @service.variables
|
105
|
+
repo_var = list.find { |v| v.key == 'git_repo' }
|
106
|
+
branch_var = list.find { |v| v.key == 'git_branch' }
|
107
|
+
|
108
|
+
if repo_var && repo_var.value && branch_var
|
109
|
+
Helpers::Command.git_clone(repo_var.value, branch_var.value)
|
110
|
+
else
|
111
|
+
puts 'Please define your GIT repository and branch'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def read_vars
|
116
|
+
read_local_vars
|
117
|
+
read_remote_vars
|
118
|
+
write_local_vars
|
119
|
+
end
|
120
|
+
|
121
|
+
def read_local_vars
|
122
|
+
vars_file_path = Adminix.config.config_file('vars')
|
123
|
+
return unless File.exist?(vars_file_path)
|
124
|
+
|
125
|
+
vars = Helpers::Files.read_yaml_file(vars_file_path)
|
126
|
+
vars.each do |k, v|
|
127
|
+
@service.add_variable Entities::Variable.new(key: k, value: v)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def read_remote_vars
|
132
|
+
Entities::Variable.all(@service).each { |v| @service.add_variable(v) }
|
133
|
+
end
|
134
|
+
|
135
|
+
def write_local_vars
|
136
|
+
vars_file_path = Adminix.config.config_file('vars')
|
137
|
+
data = {}
|
138
|
+
@service.variables.each { |v| data[v.key] = v.value }
|
139
|
+
Helpers::Files.write_yaml_file(vars_file_path, data)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Services
|
3
|
+
module LogsService
|
4
|
+
def self.add_logs(watcher, _path, lines)
|
5
|
+
logs = lines.map { |l| Entities::Log.new(l) }
|
6
|
+
watcher.service.add_logs(logs)
|
7
|
+
diff = Adminix.config.data_storage_limit[:logs] -
|
8
|
+
watcher.service.logs.count
|
9
|
+
watcher.service.shift_logs(diff.abs) if diff < 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Services
|
3
|
+
class SystemLoadService
|
4
|
+
def initialize(service)
|
5
|
+
@service = service
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_stamp
|
9
|
+
@service.add_system_load(Entities::SysloadStamp.new)
|
10
|
+
diff = Adminix.config.data_storage_limit[:load_stamps] -
|
11
|
+
@service.load_stamps.count
|
12
|
+
@service.shift_load_stamps(diff.abs) if diff < 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/adminix/version.rb
CHANGED
data/lib/adminix/watcher.rb
CHANGED
@@ -1,174 +1,106 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
-
require 'action_cable_client'
|
3
2
|
|
4
3
|
module Adminix
|
5
4
|
class Watcher
|
6
|
-
|
7
|
-
|
5
|
+
attr_reader :quit
|
6
|
+
|
7
|
+
def self.run!(app_service, options)
|
8
|
+
Adminix.logger.info "Starting watcher PID is #{Process.pid}"
|
9
|
+
EM.run do
|
10
|
+
w = Adminix.watcher = Adminix::Watcher.new(app_service, options)
|
11
|
+
c = Adminix.config
|
12
|
+
p = c.watcher_period
|
13
|
+
|
14
|
+
if c.web_debugger_enabled?
|
15
|
+
Adminix.logger.info "Web debugger is running on port #{c.server_port}"
|
16
|
+
EM.start_server('0.0.0.0', c.server_port, Web::Router)
|
17
|
+
end
|
18
|
+
if Adminix.config.watch_system_load?
|
19
|
+
EM.add_periodic_timer(p[:check_system_load]) { w.perform(:check_system_load) }
|
20
|
+
EM.add_periodic_timer(p[:send_system_load]) { w.perform(:send_system_load) }
|
21
|
+
end
|
22
|
+
if Adminix.config.watch_logs?
|
23
|
+
EM.add_periodic_timer(p[:send_logs]) { w.perform(:send_logs) }
|
24
|
+
Adminix.config.log_files.each do |path|
|
25
|
+
EventMachine.file_tail(path, Adminix::Helpers::LogReader)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
if c.credentials_defined?
|
29
|
+
EM.add_periodic_timer(p[:sync_service]) { w.perform(:sync_service) }
|
30
|
+
end
|
31
|
+
EM.add_periodic_timer(p[:execute_jobs]) { w.perform(:execute_jobs) }
|
32
|
+
EM.add_periodic_timer(2) do
|
33
|
+
if w.quit && !w.wait?
|
34
|
+
Adminix.logger.info 'Stopping watcher...'
|
35
|
+
EM.stop
|
36
|
+
end
|
37
|
+
end
|
8
38
|
|
9
|
-
|
10
|
-
|
11
|
-
else
|
12
|
-
options[:daemonize] ? watcher.start : watcher.run!
|
39
|
+
trap('TERM') { w.stop }
|
40
|
+
trap('INT') { w.stop }
|
13
41
|
end
|
14
42
|
end
|
15
43
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
22
|
-
|
23
|
-
@ws_client = nil
|
24
|
-
@ws_uri = "#{config.websocket_path}?secret_key=#{config.secret_key}"
|
25
|
-
@ws_channel = { channel: 'ServiceChannel', service_id: @service.id }
|
26
|
-
@ws_logs_channel = { channel: 'LogsChannel', service_id: @service.id }
|
27
|
-
|
28
|
-
@watching_files = []
|
29
|
-
|
30
|
-
if EM.epoll?
|
31
|
-
EM.epoll
|
32
|
-
elsif EM.kqueue?
|
33
|
-
EM.kqueue
|
34
|
-
else
|
35
|
-
Kernel.warn('Neither epoll nor kqueue are supported.')
|
36
|
-
end
|
44
|
+
def initialize(app_service, options)
|
45
|
+
@options = options
|
46
|
+
@running_jobs = []
|
47
|
+
@app_service = app_service
|
48
|
+
@system_load_service = Services::SystemLoadService.new(service)
|
49
|
+
@quit = false
|
37
50
|
end
|
38
51
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
EventMachine.run do
|
43
|
-
Signal.trap("INT") { EventMachine.stop }
|
44
|
-
Signal.trap("TERM") { EventMachine.stop }
|
52
|
+
def perform(job)
|
53
|
+
return if @running_jobs.include?(job) || @quit
|
45
54
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
EventMachine.add_periodic_timer(config.watcher_sync_period) do
|
51
|
-
@ws_client.perform(:sync, @service.to_cable) if @ws_client.subscribed?
|
52
|
-
end
|
55
|
+
@running_jobs << job
|
56
|
+
send(job)
|
57
|
+
@running_jobs.delete(job)
|
58
|
+
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
config.watch_log_files.each do |file_path|
|
58
|
-
dirname = File.dirname(file_path)
|
59
|
-
Helpers::File.mkdir_p(dirname) unless File.directory?(dirname)
|
60
|
-
Helpers::File.touch(file_path) unless File.exists?(file_path)
|
61
|
-
|
62
|
-
if File.exists?(file_path)
|
63
|
-
log_files_exists = true
|
64
|
-
EventMachine.watch_file(file_path, Adminix::LogWatchHandler)
|
65
|
-
end
|
66
|
-
end
|
60
|
+
def check_logs
|
61
|
+
Adminix.logger.debug 'Checking logs...'
|
62
|
+
end
|
67
63
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
64
|
+
def check_system_load
|
65
|
+
Adminix.logger.debug 'Checking system load...'
|
66
|
+
@system_load_service.create_stamp
|
75
67
|
end
|
76
68
|
|
77
|
-
def
|
78
|
-
|
79
|
-
@
|
80
|
-
|
81
|
-
end
|
82
|
-
@ws_client.disconnected do
|
83
|
-
system.log 'Service disconnected. Reconnecting...'
|
84
|
-
sleep(2)
|
85
|
-
# @ws_client.connect!
|
86
|
-
initialize_ws
|
87
|
-
end
|
88
|
-
@ws_client.received do |msg|
|
89
|
-
message = msg['message'] || {}
|
90
|
-
case message['type']
|
91
|
-
when 'restart' then @service.restart!
|
92
|
-
when 'sync' then @service.sync(@ws_client, message['data'])
|
93
|
-
end
|
94
|
-
end
|
69
|
+
def sync_service
|
70
|
+
Adminix.logger.info 'Syncing service...'
|
71
|
+
@app_service.sync
|
72
|
+
end
|
95
73
|
|
96
|
-
|
97
|
-
|
98
|
-
|
74
|
+
def execute_jobs
|
75
|
+
return unless @app_service.service.new_jobs?
|
76
|
+
Adminix.logger.info 'Executing jobs...'
|
77
|
+
@app_service.run_jobs
|
99
78
|
end
|
100
79
|
|
101
|
-
def
|
102
|
-
|
103
|
-
@
|
104
|
-
puts 'Logs connection established'
|
105
|
-
end
|
106
|
-
@ws_logs_client.disconnected do
|
107
|
-
system.log 'Logs disconnected. Reconnecting...'
|
108
|
-
sleep(2)
|
109
|
-
# @ws_logs_client.connect!
|
110
|
-
initialize_ws_logs
|
111
|
-
end
|
112
|
-
# @ws_logs_client.pinged do |_data|
|
113
|
-
# puts 'logs ping'
|
114
|
-
# end
|
115
|
-
@ws_logs_client.received { |msg| }
|
80
|
+
def send_logs
|
81
|
+
Adminix.logger.debug 'Adding logs to sending queue...'
|
82
|
+
@app_service.allow_sending_logs
|
116
83
|
end
|
117
84
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
file.close
|
85
|
+
def send_system_load
|
86
|
+
Adminix.logger.debug 'Adding system load to sending queue...'
|
87
|
+
@app_service.allow_sending_system_load
|
88
|
+
end
|
123
89
|
|
124
|
-
|
125
|
-
|
126
|
-
0
|
127
|
-
end
|
90
|
+
def wait?
|
91
|
+
!@running_jobs.count.zero?
|
128
92
|
end
|
129
93
|
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
warn "Daemon is already running"
|
134
|
-
exit -1
|
135
|
-
end
|
94
|
+
def service
|
95
|
+
@app_service.service
|
96
|
+
end
|
136
97
|
|
137
|
-
|
138
|
-
|
139
|
-
}
|
140
|
-
begin
|
141
|
-
file = File.new(@pid_full, "w")
|
142
|
-
file.write(pid)
|
143
|
-
file.close
|
144
|
-
Process.detach(pid)
|
145
|
-
rescue => exc
|
146
|
-
Process.kill('TERM', pid)
|
147
|
-
warn "Cannot start daemon: #{exc.message}"
|
148
|
-
end
|
98
|
+
def app_service
|
99
|
+
@app_service
|
149
100
|
end
|
150
101
|
|
151
102
|
def stop
|
152
|
-
|
153
|
-
begin
|
154
|
-
EM.stop
|
155
|
-
rescue
|
156
|
-
end
|
157
|
-
|
158
|
-
if pid != 0
|
159
|
-
Process.kill('HUP', pid.to_i)
|
160
|
-
File.delete(@pid_full)
|
161
|
-
system.log "Stopped"
|
162
|
-
else
|
163
|
-
warn "Daemon is not running"
|
164
|
-
exit -1
|
165
|
-
end
|
103
|
+
@quit = true
|
166
104
|
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
def config() Config.instance end
|
171
|
-
def system() System.instance end
|
172
105
|
end
|
173
106
|
end
|
174
|
-
|