l4d.tools/lib/l4d_server/systemd_manager.rb

117 lines
2.6 KiB
Ruby

module L4dServer
class SystemdManager
SYSTEMD_USER_DIR = File.expand_path("~/.config/systemd/user").freeze
def self.start(server)
new(server).start
end
def self.stop(server)
new(server).stop
end
def self.restart(server)
new(server).restart
end
def self.status(server)
new(server).status
end
def self.cleanup(server)
new(server).cleanup
end
def initialize(server)
@server = server
end
def start
execute("systemctl --user start #{unit_name}")
end
def stop
execute("systemctl --user stop #{unit_name}")
end
def restart
execute("systemctl --user restart #{unit_name}")
end
def status
output = `systemctl --user is-active #{unit_name} 2>&1`
output.strip
rescue StandardError => e
Rails.logger.error("Failed to get status: #{e.message}")
"unknown"
end
def cleanup
begin
stop
execute("systemctl --user disable #{unit_name}")
execute("systemctl --user daemon-reload")
File.delete(unit_file_path) if File.exist?(unit_file_path)
rescue StandardError => e
Rails.logger.error("Failed to cleanup systemd unit: #{e.message}")
end
end
def create_unit_file
FileUtils.mkdir_p(SYSTEMD_USER_DIR) unless Dir.exist?(SYSTEMD_USER_DIR)
File.write(unit_file_path, render_unit)
@server.update(unit_file_path: unit_file_path)
execute("systemctl --user daemon-reload")
end
def enable_and_start
execute("systemctl --user enable #{unit_name}")
start
end
private
def unit_name
"left4dead2-#{@server.id}.service"
end
def unit_file_path
File.join(SYSTEMD_USER_DIR, unit_name)
end
def render_unit
template = @server.server_template
# startup_params is now a text field, not an association
startup_args = template.startup_params.to_s.strip
<<~UNIT
[Unit]
Description=L4D2 Server #{@server.name}
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=steam
ExecStart=/opt/l4d2/bin/start-server #{@server.id}
ExecStop=/opt/l4d2/bin/stop-server #{@server.id}
Restart=on-failure
RestartSec=10
Nice=-10
[Install]
WantedBy=default.target
UNIT
end
def execute(command)
output = `#{command} 2>&1`
raise "Command failed: #{command}\n#{output}" unless $?.success?
output
rescue StandardError => e
Rails.logger.error("Systemd command failed: #{e.message}")
raise
end
end
end