forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsystemd_common.rb
206 lines (167 loc) · 4.56 KB
/
systemd_common.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
class MiqWorker
module SystemdCommon
extend ActiveSupport::Concern
class_methods do
def supports_systemd?
return unless worker_settings[:systemd_enabled]
require "dbus/systemd"
true
rescue LoadError
false
end
def ensure_systemd_files
target_file_path.write(target_file)
service_file_path.write(unit_file)
end
def service_base_name
minimal_class_name.underscore.tr("/", "_")
end
def slice_base_name
"miq"
end
def service_name
"#{service_base_name}@"
end
def service_file_name
"#{service_name}.service"
end
def slice_name
"#{slice_base_name}-#{service_base_name}.slice"
end
def service_file_path
systemd_unit_dir.join(service_file_name)
end
def target_file_name
"#{service_base_name}.target"
end
def target_file_path
systemd_unit_dir.join(target_file_name)
end
def systemd_unit_dir
Pathname.new("/etc/systemd/system")
end
def target_file
<<~TARGET_FILE
[Unit]
PartOf=miq.target
TARGET_FILE
end
def unit_file
<<~UNIT_FILE
[Unit]
PartOf=#{target_file_name}
[Install]
WantedBy=#{target_file_name}
[Service]
WorkingDirectory=#{working_directory}
Environment=BUNDLER_GROUPS=#{bundler_groups.join(",")}
ExecStart=/bin/bash -lc '#{exec_start}'
Restart=no
Type=notify
Slice=#{slice_name}
UNIT_FILE
end
def working_directory
Rails.root
end
def exec_start
"exec ruby lib/workers/bin/run_single_worker.rb #{name} #{run_single_worker_args}"
end
def run_single_worker_args
"--heartbeat --guid=%i"
end
end
def start_systemd_worker
enable_systemd_unit
write_unit_settings_file
start_systemd_unit
end
def stop_systemd_worker
stop_systemd_unit
cleanup_unit_settings_file
disable_systemd_unit
end
def enable_systemd_unit(runtime: false, replace: true)
systemd.EnableUnitFiles([unit_name], runtime, replace)
end
def disable_systemd_unit(runtime: false)
systemd.DisableUnitFiles([unit_name], runtime)
end
def start_systemd_unit(mode: "replace")
systemd.StartUnit(unit_name, mode)
end
def stop_systemd_unit(mode: "replace")
systemd.StopUnit(unit_name, mode)
end
def sd_notify_started
sd_notify.ready
end
def sd_notify_stopping
sd_notify.stopping
end
def sd_notify_watchdog
sd_notify.watchdog
end
def sd_notify_watchdog_usec(timeout_in_seconds)
usec = timeout_in_seconds * 1_000_000
sd_notify.notify("WATCHDOG_USEC=#{usec}", false)
end
private
def systemd
@systemd ||= begin
require "dbus/systemd"
DBus::Systemd::Manager.new
end
end
def sd_notify
@sd_notify ||= begin
require "sd_notify"
SdNotify
end
end
def service_base_name
self.class.service_base_name
end
def unit_name
"#{service_base_name}#{unit_instance}.service"
end
def unit_instance
"@#{guid}"
end
def write_unit_settings_file
FileUtils.mkdir_p(unit_config_path) unless unit_config_path.exist?
unit_config_file_path.write(unit_config_file) unless unit_config_file_path.exist?
end
def cleanup_unit_settings_file
unit_config_file_path.delete if unit_config_file_path.exist?
unit_config_path.delete if unit_config_path.exist?
end
def unit_config_name
"#{unit_name}.d"
end
def unit_config_path
self.class.systemd_unit_dir.join(unit_config_name)
end
def unit_config_file_path
unit_config_path.join("override.conf")
end
def unit_config_file
# Override this in a sub-class if the specific instance needs
# any additional config
<<~UNIT_CONFIG_FILE
[Service]
MemoryHigh=#{worker_settings[:memory_threshold].bytes}
TimeoutStartSec=#{worker_settings[:starting_timeout]}
TimeoutStopSec=#{worker_settings[:stopping_timeout]}
WatchdogSec=#{worker_settings[:heartbeat_timeout]}
#{unit_environment_variables.map { |env_var| "Environment=#{env_var}" }.join("\n")}
UNIT_CONFIG_FILE
end
def unit_environment_variables
# Override this in a child class to add env vars
[
"HOME=/root"
]
end
end
end