This commit is contained in:
2025-08-29 09:48:44 +02:00
parent 03bb86bd72
commit ce6cf3aa9c
27 changed files with 129 additions and 144 deletions

View File

@@ -42,7 +42,7 @@ pub fn ping(args PingArgs) !bool {
if res.exit_code > 0 {
nrerrors += 1
}
console.print_debug("${cmd} ${res.exit_code} ${nrerrors}")
console.print_debug('${cmd} ${res.exit_code} ${nrerrors}')
}
successes := args.nr_ping - nrerrors
if successes >= args.nr_ok {
@@ -233,7 +233,7 @@ fn ssh_testrun_internal(args TcpPortTestArgs) !(string, SSHResult) {
fi
echo "ERROR: Host unreachable, over ping and ssh"
exit 3
'
'
res := exec(cmd: cmd, ignore_error: true, stdout: false, debug: false)!
// console.print_debug('ssh test ${res.exit_code}: ===== cmd:\n${cmd}\n=====\n${res.output}')

View File

@@ -56,7 +56,7 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
mut scr := screen.new(reset: false)!
console.print_debug('screen startup manager ${args.name} cmd:${args.cmd}')
_ = scr.add(name: args.name, cmd: args.cmd, reset: args.restart)!
//because of how screen works the start is immediate
// because of how screen works the start is immediate
}
.systemd {
// console.print_debug('systemd start ${args.name}')
@@ -74,7 +74,7 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
// Get the Zinit RPC client instance.
// We assume it's properly configured (e.g., socket_path) via its factory setup.
mut zinit_client := zinit.get(create: true)!
// Map ZProcessNewArgs to zinit.ServiceConfig
mut service_config := zinit.ServiceConfig{
exec: args.cmd
@@ -90,16 +90,16 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
// Create the service configuration file in zinit
zinit_client.service_create(args.name, service_config) or {
return error('startupmanager: failed to create zinit service ${args.name}: ${err}')
}
} else {
}
}
else {
panic('to implement, startup manager only support screen & systemd for now: ${mycat}')
}
}
// If 'start' is true, also monitor and start the service
if args.start {
sm.start(args.name)!
}
}
}
pub fn (mut sm StartupManager) start(name string) ! {
@@ -129,7 +129,6 @@ pub fn (mut sm StartupManager) start(name string) ! {
zinit_client.service_monitor(name) or {
return error('startupmanager: Failed to monitor zinit service ${name}: ${err}')
}
}
else {
panic('to implement, startup manager only support screen, systemd and zinit for now')
@@ -355,7 +354,7 @@ pub fn (mut sm StartupManager) exists(name string) !bool {
}
.zinit {
console.print_debug('zinit exists ${name} using clients.zinit')
mut zinit_client := zinit.get(create:true)!
mut zinit_client := zinit.get(create: true)!
zinit_client.service_status(name) or { return false }
return true
}

View File

@@ -6,49 +6,49 @@ import freeflowuniverse.herolib.osal.core as osal
@[params]
pub struct JournalArgs {
pub:
service string // name of service for which logs will be retrieved
limit int = 100 // number of last log lines to be shown
since string // time since when to show logs (e.g., "1 hour ago", "2024-01-01")
follow bool // follow logs in real-time
priority string // log priority (emerg, alert, crit, err, warning, notice, info, debug)
grep string // filter logs containing this text
service string // name of service for which logs will be retrieved
limit int = 100 // number of last log lines to be shown
since string // time since when to show logs (e.g., "1 hour ago", "2024-01-01")
follow bool // follow logs in real-time
priority string // log priority (emerg, alert, crit, err, warning, notice, info, debug)
grep string // filter logs containing this text
}
pub fn journalctl(args JournalArgs) !string {
mut cmd_parts := ['journalctl', '--no-pager']
if args.limit > 0 {
cmd_parts << ['-n', args.limit.str()]
}
if args.service != '' {
cmd_parts << ['-u', name_fix(args.service)]
}
if args.since != '' {
cmd_parts << ['--since', '"${args.since}"']
}
if args.follow {
cmd_parts << ['-f']
}
if args.priority != '' {
cmd_parts << ['-p', args.priority]
}
cmd := cmd_parts.join(' ')
mut response := osal.execute_silent(cmd) or {
return error('Failed to get journal logs for ${args.service}: ${err}')
}
if args.grep != '' {
lines := response.split('\n')
filtered_lines := lines.filter(it.contains(args.grep))
response = filtered_lines.join('\n')
}
return response
}

View File

@@ -179,7 +179,7 @@ pub fn (mut systemd Systemd) destroy(name_ string) ! {
pub fn (mut systemd Systemd) validate_service(name string) !bool {
service := systemd.get(name)!
status := service.status()!
match status {
.active {
console.print_item(' Service ${name} is running')
@@ -200,14 +200,14 @@ pub fn (mut systemd Systemd) validate_service(name string) !bool {
// Add method to check all services
pub fn (mut systemd Systemd) health_check() !map[string]bool {
mut results := map[string]bool{}
for process in systemd.processes {
if process.name.ends_with('_test') || process.name.ends_with('testservice') {
continue // Skip test services
}
results[process.name] = systemd.validate_service(process.name) or { false }
}
return results
}

View File

@@ -43,24 +43,24 @@ pub fn (mut self SystemdProcess) write() ! {
pub fn (mut self SystemdProcess) start() ! {
console.print_header('starting systemd process: ${self.name}')
cmd := '
systemctl daemon-reload
systemctl enable ${self.name}
systemctl start ${self.name}
'
job := osal.exec(cmd: cmd, stdout: false)!
// Wait for service to start with timeout
mut attempts := 0
max_attempts := 10
wait_interval := 500 // milliseconds
for attempts < max_attempts {
time.sleep(wait_interval * time.millisecond)
status := self.status()!
match status {
.active {
console.print_header(' systemd process started successfully: ${self.name}')
@@ -81,11 +81,10 @@ pub fn (mut self SystemdProcess) start() ! {
}
}
}
// If we get here, service didn't start in time
logs := self.get_logs(50)!
return error('Service ${self.name} did not start within expected time. Status: ${self.status()!}. Recent logs:\n${logs}')
}
// get status from system
@@ -109,30 +108,30 @@ pub fn (mut self SystemdProcess) delete() ! {
pub fn (mut self SystemdProcess) stop() ! {
console.print_header('stopping systemd process: ${self.name}')
cmd := '
systemctl stop ${self.name}
systemctl disable ${self.name}
systemctl daemon-reload
'
_ = osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
// Wait for service to stop
mut attempts := 0
max_attempts := 10
for attempts < max_attempts {
time.sleep(500 * time.millisecond)
status := self.status()!
if status == .inactive {
console.print_header(' systemd process stopped: ${self.name}')
return
}
attempts++
}
console.print_header(' systemd process may still be running: ${self.name}')
}
@@ -161,11 +160,11 @@ pub fn (self SystemdProcess) get_logs(lines int) !string {
// Improve status method with better error handling
pub fn (self SystemdProcess) status() !SystemdStatus {
cmd := 'systemctl is-active ${name_fix(self.name)}'
job := osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
// console.print_debug("${cmd} \n***\n${job.output}\n***")
match job.output.trim_space() {
'active' { return .active }
'inactive' { return .inactive }
@@ -182,4 +181,3 @@ pub fn (self SystemdProcess) status_detailed() !string {
job := osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
return job.output
}

View File

@@ -32,8 +32,8 @@ pub fn testsuite_end() ! {
pub fn test_systemd_process_start_stop() ! {
mut systemdfactory := new()!
mut process := systemdfactory.new(
cmd: 'redis-server'
name: 'testservice'
cmd: 'redis-server'
name: 'testservice'
start: false
)!