Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions sonic_package_manager/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

""" Logger for sonic-package-manager. """

import logging.handlers

import logging
import click_log

from logging.handlers import SysLogHandler


class Formatter(click_log.ColorFormatter):
""" Click logging formatter. """
Expand All @@ -25,5 +26,8 @@ class Formatter(click_log.ColorFormatter):
click_handler = click_log.ClickHandler()
click_handler.formatter = Formatter()

syslog_handler = SysLogHandler()
syslog_handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))

log.addHandler(click_handler)
log.addHandler(logging.handlers.SysLogHandler())
log.addHandler(syslog_handler)
37 changes: 35 additions & 2 deletions sonic_package_manager/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import functools
import os
import pkgutil
import subprocess
import tempfile
import yang as ly
from inspect import signature
Expand Down Expand Up @@ -1023,6 +1024,31 @@ def _start_feature(self, package: Package):
self._systemctl_action(package, 'enable')
self._systemctl_action(package, 'start')

@staticmethod
def _systemctl_is_generated_or_transient(unit_name: str) -> bool:
"""Returns True if systemd considers the unit generated/transient.

On some platforms, SONiC's systemd generator
may materialize unit files under /run/systemd/generator.
Such units cannot be enabled/disabled persistently.
"""
try:
proc = subprocess.run(
['systemctl', 'is-enabled', unit_name],
capture_output=True,
text=True,
timeout=15,
)
except subprocess.TimeoutExpired as err:
log.warning(f'systemctl is-enabled timed out for unit {unit_name}: timeout={err.timeout}s')
return False
except Exception as err:
log.error(f'systemctl is-enabled failed for unit {unit_name}: {err}')
return False

state = (proc.stdout or '').strip().lower()
return state in ('generated', 'transient')

def _systemctl_action(self, package: Package, action: str):
""" Execute systemctl action for a service. """

Expand All @@ -1034,10 +1060,17 @@ def _systemctl_action(self, package: Package, action: str):
single_instance = host_service or (asic_service and not self.is_multi_npu)
multi_instance = asic_service and self.is_multi_npu
if single_instance:
run_command(['systemctl', action, name])
if action in ('enable', 'disable') and self._systemctl_is_generated_or_transient(name):
log.warning(f'Skipping systemctl {action} for generated/transient unit {name}')
else:
run_command(['systemctl', action, name])
if multi_instance:
for npu in range(self.num_npus):
run_command(['systemctl', action, f'{name}@{npu}'])
inst_name = f'{name}@{npu}'
if action in ('enable', 'disable') and self._systemctl_is_generated_or_transient(inst_name):
log.warning(f'Skipping systemctl {action} for generated/transient unit {inst_name}')
else:
run_command(['systemctl', action, inst_name])

def _disable_feature(self, package: Package, block: bool = True):
""" Stops the feature and blocks till operation is finished if
Expand Down
Loading