%PDF- %PDF-
Direktori : /opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/subsys/ |
Current File : //opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/subsys/svcctl.py |
""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. Copyright © 2019 Cloud Linux Software Inc. This software is also available under ImunifyAV commercial license, see <https://www.imunify360.com/legal/eula> """ import asyncio import logging import os import subprocess as su from typing import Iterable, Union from defence360agent.contracts.config import Core from defence360agent.utils import check_run, run logger = logging.getLogger(__name__) def _apply_cmd(func): async def wrapper(*args, **kwargs): cmd = func(*args, **kwargs) logger.debug('check_call(%r)', cmd) await check_run(cmd) return wrapper async def _reset_failed_state( services: Iterable[Union["_CentOs6", "_SystemctlBased"]] ): for s in services: await s.reset_failed() await s.restart() for _ in range(10): if await s.is_active(): break logger.warning( "Service %s is still not active, sleep for %s seconds", s, 1 ) await asyncio.sleep(1) class _CentOs6: SVC_CTL_BIN = '/sbin/service' _CHKCONFIG = '/sbin/chkconfig' def __init__(self, service_name): self._service_name = service_name @_apply_cmd def start(self): return [self.SVC_CTL_BIN, self._service_name, 'start'] @_apply_cmd def stop(self): return [self.SVC_CTL_BIN, self._service_name, 'stop'] @_apply_cmd def restart(self): return [self.SVC_CTL_BIN, self._service_name, 'restart'] async def reset_failed(self): """Not implemented for Centos6""" pass @_apply_cmd def enable(self): return [self._CHKCONFIG, '--add', self._service_name] async def is_enabled(self): cmd = [self._CHKCONFIG, '--list', self._service_name] proc = await asyncio.create_subprocess_exec( *cmd, stdout=su.PIPE, stderr=su.DEVNULL) out, _ = await proc.communicate() rc = await proc.wait() return rc == 0 and b':on' in out def is_enabled_sync(self): cmd = [self._CHKCONFIG, '--list', self._service_name] cp = su.run(cmd, stdout=su.PIPE, stderr=su.DEVNULL) return cp.returncode == 0 and b':on' in cp.stdout @_apply_cmd def disable(self): return [self._CHKCONFIG, '--del', self._service_name] mask = disable unmask = enable async def is_active(self): cmd = [self.SVC_CTL_BIN, self._service_name, 'status'] exit_code, _, _ = await run(cmd) return exit_code == 0 async def activate_socket_service(self): if await self.is_enabled() and not await self.is_active(): await _reset_failed_state((self,)) class _SystemctlBased: SVC_CTL_BIN = 'systemctl' def __init__(self, service_name): self._service_name = service_name @_apply_cmd def start(self): return [self.SVC_CTL_BIN, 'start', self._service_name] @_apply_cmd def stop(self): return [self.SVC_CTL_BIN, 'stop', self._service_name] @_apply_cmd def restart(self): return [self.SVC_CTL_BIN, 'restart', self._service_name] @_apply_cmd def enable(self): return [self.SVC_CTL_BIN, 'enable', self._service_name] async def is_enabled(self): cmd = [self.SVC_CTL_BIN, 'is-enabled', self._service_name] proc = await asyncio.create_subprocess_exec( *cmd, stdout=su.DEVNULL, stderr=su.DEVNULL) await proc.communicate() rc = await proc.wait() return rc == 0 def is_enabled_sync(self): cmd = [self.SVC_CTL_BIN, 'is-enabled', self._service_name] rc = su.call(cmd, stdout=su.DEVNULL, stderr=su.DEVNULL) return rc == 0 @_apply_cmd def disable(self): return [self.SVC_CTL_BIN, 'disable', self._service_name] @_apply_cmd def mask(self): """ It was created for imunify360-webshield which required masking as far This is no more relevant but let it stay is started by 'Wants=' in imunify360.service """ return [self.SVC_CTL_BIN, 'mask', self._service_name] @_apply_cmd def unmask(self): """ It was created for imunify360-webshield which required masking as far This is no more relevant but let it stay is started by 'Wants=' in imunify360.service """ return [self.SVC_CTL_BIN, 'unmask', self._service_name] async def is_active(self): cmd = [self.SVC_CTL_BIN, 'is-active', self._service_name] exit_code, _, _ = await run(cmd) return exit_code == 0 @_apply_cmd def reset_failed(self): return [self.SVC_CTL_BIN, 'reset-failed', self._service_name] async def activate_socket_service(self): agent_service_socket = adaptor(f"{self._service_name}.socket") if ( await agent_service_socket.is_enabled() and not await agent_service_socket.is_active() ): await _reset_failed_state((self, agent_service_socket)) class _CentOs7(_SystemctlBased): SVC_CTL_BIN = '/usr/bin/systemctl' class _DebianUbuntu(_SystemctlBased): SVC_CTL_BIN = '/bin/systemctl' def adaptor(service_name): for a in (_DebianUbuntu, _CentOs7, _CentOs6): if os.path.exists(a.SVC_CTL_BIN): return a(service_name) else: raise RuntimeError("Cannot instantiate appropriate adaptor.") def imunify360_service(): return adaptor(Core.SVC_NAME)