BYPASS SHELL BY ./RAZORGANZ
Server: nginx/1.20.1
System: Linux iZdzfnv9mwfppeZ 5.10.134-19.2.al8.x86_64 #1 SMP Wed Oct 29 22:47:09 CST 2025 x86_64
User: apache (48)
PHP: 8.2.30
Disabled: NONE
Upload Files
File: //lib/python3.6/site-packages/agent/controller/__init__.py
# Copyright (c) 2021-2023 Alibaba Cloud Computing Ltd.
# SPDX-License-Identifier: MulanPSL-2.0

import logging
import os
import re
from importlib import import_module

import agent  # ! unused import for dynamic loading
from agent import domain, feature

logger = logging.getLogger("keentune")


class Singleton(object):
    def __init__(self, cls):
        self._cls = cls
        self._instance = {}

    def __call__(self):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls()
        return self._instance[self._cls]


@Singleton
class Context(object):
    _pattern_ = re.compile(r"class (.*)\((Feature|BaseDomain|BaseBenchmark|FileConfig|Nginx)\)")

    def __init__(self):
        self.debug = False
        self.domain_class = {}
        self.feature_class = {}
        self.domain_object = {}
        self.feature_object = {}
        self.loadObject()
        self.loadActiveParams()

    def _debug(self, debug):
        self.debug = debug

    def loadObject(self):
        """Try to parse domain & feature file to classes"""
        logger.debug(f"Load feature classes from {os.path.dirname(feature.__file__)}")
        for file_path in os.listdir(os.path.dirname(feature.__file__)):
            file_path = os.path.join(os.path.dirname(feature.__file__), file_path)
            obj = self.__loadObjectImpl(file_path)
            if obj is not None:
                self.feature_class["{}:{}".format(obj.__domain__, obj.__feature__)] = obj
        logger.debug(f"Find {len(self.feature_class)} parameter feature: {list(self.feature_class.keys())}")

        logger.debug(f"Load domain classes from {os.path.dirname(domain.__file__)}")
        for file_path in os.listdir(os.path.dirname(domain.__file__)):
            file_path = os.path.join(os.path.dirname(domain.__file__), file_path)
            obj = self.__loadObjectImpl(file_path)
            if obj is not None:
                self.domain_class["{}".format(obj.__domain__)] = obj
        logger.debug(f"Find {len(self.domain_class)} parameter domain: {list(self.domain_class.keys())}")

    def __loadObjectImpl(self, file_path):
        """Parse file content to checkout domain & feature class"""
        # skip dir
        if os.path.isdir(file_path):
            return None

        with open(file_path) as f:
            content = f.read()

        try:
            class_name = re.search(self._pattern_, content).group(1)
            assert re.match("^\w+$", class_name)
        except Exception:
            return None

        folder_name = os.path.split(file_path)[0].split("/")[-1]
        file_name = os.path.split(file_path)[1].split(".")[0]

        try:
            assert re.match("^\w+$", folder_name)
            assert re.match("^\w+$", file_name)
            import_module("agent.{}.{}".format(folder_name, file_name))

        except Exception as e:
            logger.warning(f"failed to import feature file {file_name}: {e}")
            return None

        else:
            _object = eval("agent.{}.{}.{}".format(folder_name, file_name, class_name))
            return _object

    def loadActiveParams(self):
        """Check backup data and init actived domain/feature"""
        for feature_name, feature_obj in self.feature_class.items():
            if feature_obj.isActived():
                logger.info(f"load actived feature: {feature_name}")
                try:
                    self.feature_object[feature_name] = feature_obj()
                except Exception as e:
                    logger.warning(f"failed to load actived feature {feature_name}: {e}")

        for domain_name, domain_obj in self.domain_class.items():
            if domain_obj.isActived():
                logger.info(f"load actived domain: {domain_name}")
                try:
                    self.domain_object[domain_name] = domain_obj()
                except Exception as e:
                    logger.warning(f"failed to load actived domain {domain_name}: {e}")

    def searchFeatureHandler(self, domain_name, feature_name):
        """A feature handler is wanted, init and return feature object

        Raise:
            Exception: object init failed
        """
        feature_name = "{}:{}".format(domain_name, feature_name)

        if not self.feature_class.__contains__(feature_name):
            return None

        if not self.feature_object.__contains__(feature_name):
            self.feature_object[feature_name] = self.feature_class[feature_name]()

        return self.feature_object[feature_name]

    def searchDomainHandler(self, domain_name):
        from agent.common.exception import InitException

        """A domain handler is wanted, init and return domain object
        
        Raise:
            Exception: object init failed
        """
        if not self.domain_class.__contains__(domain_name):
            #! Different with feature, domain is a guaranteed handler, raise error if miss
            raise InitException("can not find domain:{}".format(domain_name))

        if not self.domain_object.__contains__(domain_name):
            self.domain_object[domain_name] = self.domain_class[domain_name]()

        return self.domain_object[domain_name]

    def rollback(self):
        rollback_result = {}

        for domain_name in list(self.domain_object.keys()):
            domain_handler = self.domain_object[domain_name]

            try:
                logger.info(f"start rollback domain {domain_name}")
                domain_handler.rollback()
                domain_handler.post_rollback()

            except Exception as e:
                logger.warning(f"rollback {domain_name} failed: {e}")
                rollback_result[domain_name] = f"{e}"

            else:
                logger.info(f"rollback domain {domain_name} done.")
                self.domain_object.pop(domain_name)

        sorted_feature_list = sorted(
            [
                (feature_handler.__priority__, feature_name, feature_handler)
                for feature_name, feature_handler in self.feature_object.items()
            ],
            key=lambda x: x[0],
            reverse=True,
        )
        for _, feature_name, feature_handler in sorted_feature_list:
            try:
                logger.info(f"start rollback feature {feature_name}")
                feature_handler.rollback()

            except Exception as e:
                logger.warning(f"rollback {feature_name} failed: {e}")
                rollback_result[feature_name] = "{}".format(e)

            else:
                logger.info(f"rollback feature {feature_name} done.")
                self.feature_object.pop(feature_name)

        return rollback_result