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)
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")
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__)
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__)
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))
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
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")
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)
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
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())
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)
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")
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())
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)
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)
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)