%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/3/root/opt/imunify360/venv/lib/python3.8/site-packages/defence360agent/subsys/
Upload File :
Create Path :
Current File : //proc/3/root/opt/imunify360/venv/lib/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)

Zerion Mini Shell 1.0