Example #1
0
 def create_db(self, _id, db_type):
     credentials = {}
     if "mysql" in db_type:
         log_message("Creating mysql for {}".format(_id), component="Roots")
         db = self.__get_mysql__(_id)
         yield db.initialize()
         credentials["mysql"] = {
             "host": self.trunk.host,
             "port": db.__port__,
             "name": db.__database__,
             "user": db.__username__,
             "pass": db.__password__
         }
     if "mongo" in db_type:
         log_message("Creating mongodb for {}".format(_id),
                     component="Roots")
         db = self.__get_mongo__(_id)
         yield db.initialize()
         credentials["mongo"] = {
             "host": self.trunk.host,
             "port": db.__port__,
             "name": db.__database__,
             "user": db.__username__,
             "pass": db.__password__
         }
     raise Return(credentials)
Example #2
0
    def __init__(self, trunk, settings):
        self.settings = settings
        self.trunk = trunk
        self.__mongo_settings__ = self.settings.get("mongo", {})
        self.__mysql_settings__ = self.settings.get("mysql", {})

        log_message("Started roots", component="Roots")
Example #3
0
    def __init__(self, trunk, settings):
        """Инициализирует ветвь.

        :param trunk: корневой объект ноды леса.
        :type trunk: Trunk
        :param settings: Настройки ветви
        :type settings: dict
        """
        self.__host__ = settings.get("host", "127.0.0.1")
        self.trunk = trunk

        self.leaves = {}
        self.species = {}
        self.__loggers__ = []

        for logger in settings.get("loggers", []):
            try:
                self.add_logger(logger)
            except Logger.LoggerCreationError as e:
                log_message("Error adding '{}': {}".format(logger.get("identifier"), e.message), component="Branch")

        self.batteries = defaultdict(list)

        ctx = zmq.Context()
        s = ctx.socket(zmq.PULL)
        s.bind("tcp://127.0.0.1:5122")
        self.stream = ZMQStream(s)
        self.stream.on_recv(self.log_message)
        log_message("Started branch", component="Branch")

        IOLoop.current().spawn_callback(self.__restore_species__)
Example #4
0
    def __init__(self, trunk, settings):
        self.settings = settings
        self.trunk = trunk
        self.__mongo_settings__ = self.settings.get("mongo", {})
        self.__mysql_settings__ = self.settings.get("mysql", {})

        log_message("Started roots", component="Roots")
Example #5
0
 def create_db(self, _id, db_type):
     credentials = {}
     if "mysql" in db_type:
         log_message("Creating mysql for {}".format(_id), component="Roots")
         db = self.__get_mysql__(_id)
         yield db.initialize()
         credentials["mysql"] = {
             "host": self.trunk.host,
             "port": db.__port__,
             "name": db.__database__,
             "user": db.__username__,
             "pass": db.__password__
         }
     if "mongo" in db_type:
         log_message("Creating mongodb for {}".format(_id), component="Roots")
         db = self.__get_mongo__(_id)
         yield db.initialize()
         credentials["mongo"] = {
             "host": self.trunk.host,
             "port": db.__port__,
             "name": db.__database__,
             "user": db.__username__,
             "pass": db.__password__
         }
     raise Return(credentials)
Example #6
0
    def __init__(self, trunk, settings):
        """Инициализирует ветвь.

        :param trunk: корневой объект ноды леса.
        :type trunk: Trunk
        :param settings: Настройки ветви
        :type settings: dict
        """
        self.__host__ = settings.get("host", "127.0.0.1")
        self.trunk = trunk

        self.leaves = {}
        self.species = {}
        self.__loggers__ = []

        for logger in settings.get("loggers", []):
            try:
                self.add_logger(logger)
            except Logger.LoggerCreationError as e:
                log_message("Error adding '{}': {}".format(logger.get("identifier"), e.message), component="Branch")

        self.batteries = defaultdict(list)

        ctx = zmq.Context()
        s = ctx.socket(zmq.PULL)
        s.bind('tcp://127.0.0.1:5122')
        self.stream = ZMQStream(s)
        self.stream.on_recv(self.log_message)
        log_message("Started branch", component="Branch")

        IOLoop.current().spawn_callback(self.__restore_species__)
Example #7
0
    def stop(self):
        """Останавливает uwsgi-emperor и очищает директорию вассалов."""
        log_message("Stopping uwsgi emperor", component="Emperor")
        subprocess.call([self.uwsgi_binary, "--stop", self.pidfile])
        os.remove(self.pidfile)

        for name in os.listdir(self.vassal_dir):
            os.remove(os.path.join(self.vassal_dir, name))
Example #8
0
    def stop(self):
        """Останавливает uwsgi-emperor и очищает директорию вассалов."""
        log_message("Stopping uwsgi emperor", component="Emperor")
        subprocess.call([self.uwsgi_binary, "--stop", self.pidfile])
        os.remove(self.pidfile)

        for name in os.listdir(self.vassal_dir):
            os.remove(os.path.join(self.vassal_dir, name))
Example #9
0
    def status(self, value):
        """Устанавливает статус вассала и логгирует его.

        :param value: Новый статус
        :type value: str
        """
        if value != self.__status__:
            log_message("{} entered '{}' state".format(self.id, value), self.__class__.__name__)
            self.__status__ = value
Example #10
0
    def status(self, value):
        """Устанавливает статус вассала и логгирует его.

        :param value: Новый статус
        :type value: str
        """
        if value != self.__status__:
            log_message("{} entered '{}' state".format(self.id, value),
                        self.__class__.__name__)
            self.__status__ = value
Example #11
0
    def initialize(self):
        """Инициализирует корневую директорию вида.

        Инициализация включает в себя следующие шаги:

        1. Удаление имеющейся директории исходного кода
        2. Создание директории исходного кода из используемого хранилища
        3. Удаление имеющегося виртуального окружения
        4. Создание нового виртуального окружения
        5. Установка пакетов в новое виртуальное окружение

        В ходе установки пакетов в виртуальное окружение предполагается, что список пакетов будет описан в
        файле requirements.txt, находящемся в корне директории с исходным кодом.

        .. note::
            В данный момент в качестве хранилища исходного кода поддерживается только git, с возможностью указания
            используемой ветви
        """
        if not self.is_ready:
            if os.path.exists(self.src_path):
                shutil.rmtree(self.src_path)

            log_message("Initializing sources for {}".format(self.id), "Species")

            yield self.run_in_env([
                "git",
                "clone",
                "--depth", "1",
                "--branch", self.branch,
                self.url,
                self.src_path
                ],
                apply_env=False
            )

            if os.path.exists(self.environment):
                shutil.rmtree(self.environment)

            log_message("Creating virtualenv for species {}".format(self.id), "Species")

            yield self.run_in_env([
                "virtualenv",
                "--python={}".format(self.python),
                self.environment
                ],
                apply_env=False
            )

            log_message("Installing virtualenv requirements for {}".format(self.id), "Species")

            yield self.run_in_env([
                os.path.join(self.environment, "bin/pip"),
                "install",
                "-r",
                os.path.join(self.src_path, "requirements.txt"),
                "--upgrade"
            ])

            log_message("Done initializing {}".format(self.id), "Species")
Example #12
0
    def allow_host(self, host):
        """Добавляет указанный хост в список разрешенных к подключению.

        Добавление представляет из себя создание публичного файла ключа в с заданным именем
        формата <hostname>.pem в директории ключей.

        :param host: Добавляемый в разрешенные хост
        :type host: str
        """
        default_key = os.path.join(self.keydir, "default.pem")

        key_file = os.path.join(self.keydir, host + ".pem")

        if not os.path.isfile(key_file):
            log_message("Creating key for address: {0}".format(host), component="Air")
            shutil.copyfile(default_key, key_file)
Example #13
0
    def __restore_leaves__(self):
        """Выполняет восстановление листьев после перезагрузки."""
        for leaf_config in os.listdir(self.trunk.emperor.vassal_dir):
            config = ConfigParser.ConfigParser()
            config.read(os.path.join(self.trunk.emperor.vassal_dir, leaf_config))
            try:
                data = loads(config.get("forest", "data"))

                if data.get("cls") != "Leaf":
                    continue

                try:
                    leaf = self.create_leaf(**data)
                except (TypeError, ValueError):
                    pass

                if leaf:
                    log_message("Restoring leaf {}".format(leaf.id), component="Branch")
                    self.add_leaf(leaf, start=False)
            except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, Species.NotDefined):
                continue
Example #14
0
    def start_vassal(self, vassal):
        """Запускает указанного вассала.

        :param vassal: Запускаемый вассал
        :type vassal: Vassal
        """
        cfg_path = os.path.join(self.vassal_dir, "{}.ini".format(vassal.id))

        self.vassals[str(vassal.id)] = vassal

        if os.path.exists(cfg_path):
            with open(cfg_path, "r") as cfg:
                data = cfg.read()

            if data == vassal.get_config():
                return

            log_message("Leaf {} have stale configuration, will restart".format(vassal.id))

        with open(cfg_path, "w") as cfg:
            cfg.write(vassal.get_config())
Example #15
0
    def __restore_leaves__(self):
        """Выполняет восстановление листьев после перезагрузки."""
        for leaf_config in os.listdir(self.trunk.emperor.vassal_dir):
            config = ConfigParser.ConfigParser()
            config.read(os.path.join(self.trunk.emperor.vassal_dir, leaf_config))
            try:
                data = loads(config.get("forest", "data"))

                if data.get("cls") != "Leaf":
                    continue

                try:
                    leaf = self.create_leaf(**data)
                except (TypeError, ValueError):
                    pass

                if leaf:
                    log_message("Restoring leaf {}".format(leaf.id), component="Branch")
                    self.add_leaf(leaf, start=False)
            except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, Species.NotDefined):
                continue
Example #16
0
    def create_species(self, species, initialize=True):
        """Создает вид листа по данным из словаря.

        :rtype : Species
        :param species: словарь с данными конфигурации вида
        :return: Созданный экземпляр вида листа
        """
        species = Species(directory=os.path.join(self.trunk.forest_root, "species"), **species)

        if species.id in self.species:
            log_message("Updating species {}".format(species.id), component="Branch")
        elif initialize:
            log_message("Creating species {}".format(species.id), component="Branch")
        else:
            log_message("Restoring species {}".format(species.id), component="Branch")

        self.species[species.id] = species

        if initialize:

            species.is_ready = False
            for leaf in (_ for _ in self.leaves.values() if _.species.id == species.id):
                leaf.species = species
                leaf.pause()

            yield species.initialize()

            species.is_ready = True
            for leaf in (_ for _ in self.leaves.values() if _.species.id == species.id):
                leaf.species = species
                leaf.start()

        raise Return(species)
Example #17
0
    def __init__(self, trunk, host, fastrouter, port=3000):
        """Инициализирует компонент Air.

        :param trunk: Корневой объект ноды леса
        :type trunk: Trunk
        :param host: Хост, на котором fastrouter-subscription-server будет ждать подписок
        :type host: str
        :param fastrouter: Порт, на котором fastrouter-subscription-server будет ждать подписок
        :type fastrouter: int
        :param port: Порт, на котором fastrouter будет ждать входящих запросов
        :type port: int
        """
        self.trunk = trunk

        self.__fastrouter__ = Fastrouter(
            host=host,
            port=port,
            fastrouter=fastrouter,
            keydir=self.keydir,
            _id="fastrouter"
        )
        self.trunk.emperor.start_vassal(self.__fastrouter__)
        log_message("Started air", component="Air")
Example #18
0
    def start_vassal(self, vassal):
        """Запускает указанного вассала.

        :param vassal: Запускаемый вассал
        :type vassal: Vassal
        """
        cfg_path = os.path.join(self.vassal_dir, "{}.ini".format(vassal.id))

        self.vassals[str(vassal.id)] = vassal

        if os.path.exists(cfg_path):
            with open(cfg_path, "r") as cfg:
                data = cfg.read()

            if data == vassal.get_config():
                return

            log_message(
                "Leaf {} have stale configuration, will restart".format(
                    vassal.id))

        with open(cfg_path, "w") as cfg:
            cfg.write(vassal.get_config())
Example #19
0
    def __init__(self, root_dir):
        """Инициализирует uwsgi-emperor.

        :param root_dir: Полный путь к корневой директории uwsgi-emperor
        :type root_dir: str
        """
        self.__root_dir__ = root_dir

        if not os.path.exists(self.vassal_dir):
            log_message("Vassal directory does not exist, creating one", component="Emperor")
            os.mkdir(self.vassal_dir)

        emperor_pid = 0

        if os.path.exists(self.pidfile):
            with open(self.pidfile) as pid_file:
                try:
                    emperor_pid = int(pid_file.read())
                    psutil.Process(emperor_pid)

                    log_message("Found running emperor server", component="Emperor")
                except (ValueError, psutil.NoSuchProcess):
                    os.remove(self.pidfile)

        if not emperor_pid:
            emperor = subprocess.Popen(
                [
                    self.uwsgi_binary,
                    "--plugins-dir", self.binary_dir,
                    "--emperor", self.vassal_dir,
                    "--pidfile", self.pidfile,
                    "--logger", "zeromq:tcp://127.0.0.1:5123",
                    "--daemonize", "/dev/null",
                    "--emperor-stats", "127.0.0.1:1777",
                    "--emperor-required-heartbeat", "40",
                    "--emperor-throttle", "10000",
                    "--vassal-set", "plugins-dir={}".format(self.binary_dir)
                ],
                bufsize=1,
                close_fds=True
            )
            code = emperor.wait()

            assert code == 0, "Error starting emperor server"
            log_message("Started emperor server", component="Emperor")

        self.vassals = {}

        ctx = zmq.Context()
        s = ctx.socket(zmq.PULL)
        s.bind('tcp://127.0.0.1:5123')
        self.stream = ZMQStream(s)
        self.stream.on_recv(self.log_message)
Example #20
0
    def __init__(self, root_dir):
        """Инициализирует uwsgi-emperor.

        :param root_dir: Полный путь к корневой директории uwsgi-emperor
        :type root_dir: str
        """
        self.__root_dir__ = root_dir

        if not os.path.exists(self.vassal_dir):
            log_message("Vassal directory does not exist, creating one",
                        component="Emperor")
            os.mkdir(self.vassal_dir)

        emperor_pid = 0

        if os.path.exists(self.pidfile):
            with open(self.pidfile) as pid_file:
                try:
                    emperor_pid = int(pid_file.read())
                    psutil.Process(emperor_pid)

                    log_message("Found running emperor server",
                                component="Emperor")
                except (ValueError, psutil.NoSuchProcess):
                    os.remove(self.pidfile)

        if not emperor_pid:
            emperor = subprocess.Popen([
                self.uwsgi_binary, "--plugins-dir", self.binary_dir,
                "--emperor", self.vassal_dir, "--pidfile", self.pidfile,
                "--logger", "zeromq:tcp://127.0.0.1:5123", "--daemonize",
                "/dev/null", "--emperor-stats", "127.0.0.1:1777",
                "--emperor-required-heartbeat", "40", "--emperor-throttle",
                "10000", "--vassal-set", "plugins-dir={}".format(
                    self.binary_dir)
            ],
                                       bufsize=1,
                                       close_fds=True)
            code = emperor.wait()

            assert code == 0, "Error starting emperor server"
            log_message("Started emperor server", component="Emperor")

        self.vassals = {}

        ctx = zmq.Context()
        s = ctx.socket(zmq.PULL)
        s.bind('tcp://127.0.0.1:5123')
        self.stream = ZMQStream(s)
        self.stream.on_recv(self.log_message)
Example #21
0
    def create_species(self, species, initialize=True):
        """Создает вид листа по данным из словаря.

        :rtype : Species
        :param species: словарь с данными конфигурации вида
        :return: Созданный экземпляр вида листа
        """
        species = Species(
            directory=os.path.join(self.trunk.forest_root, "species"),
            **species
        )

        if species.id in self.species:
            log_message("Updating species {}".format(species.id), component="Branch")
        elif initialize:
            log_message("Creating species {}".format(species.id), component="Branch")
        else:
            log_message("Restoring species {}".format(species.id), component="Branch")

        self.species[species.id] = species

        if initialize:

            species.is_ready = False
            for leaf in (_ for _ in self.leaves.values() if _.species.id == species.id):
                leaf.species = species
                leaf.pause()

            yield species.initialize()

            species.is_ready = True
            for leaf in (_ for _ in self.leaves.values() if _.species.id == species.id):
                leaf.species = species
                leaf.start()

        raise Return(species)