def __init__(self, poolMgr=SlavePoolManager, mapper=MachineMapper, config=None, pools=[], pool_checks=True, debug=0): self._config = self._load_ctl_config(config) config = self._config mac_pool_range = config.get_option('environment', 'mac_pool_range') self._mac_pool = MacPool(mac_pool_range[0], mac_pool_range[1]) self._log_ctl = LoggingCtl(debug, log_dir=config.get_option('environment','log_dir'), log_subdir=datetime.datetime.now(). strftime("%Y-%m-%d_%H:%M:%S"), colours=not config.get_option("colours", "disable_colours")) self._msg_dispatcher = MessageDispatcher(self._log_ctl) self._network_bridges = {} self._mapper = mapper() select_pools = {} conf_pools = config.get_pools() if len(pools) > 0: for pool_name in pools: if pool_name in conf_pools: select_pools[pool_name] = conf_pools[pool_name] elif len(pools) == 1 and os.path.isdir(pool_name): select_pools = {"cmd_line_pool": pool_name} else: raise ControllerError("Pool %s does not exist!" % pool_name) else: select_pools = conf_pools self._pools = poolMgr(select_pools, self._msg_dispatcher, config, pool_checks)
def __init__(self, poolMgr=SlavePoolManager, mapper=MachineMapper, config=None, pools=[], pool_checks=True, debug=0): """ Args: poolMgr -- class that implements the SlavePoolManager interface will be instantiated by the Controller to provide the mapper with pools available for matching, also handles the creation of Machine objects (internal LNST class used to access the slave hosts) mapper -- class that implements the MachineMapper interface will be instantiated by the Controller to match Recipe requirements to the available pools config -- optional LNST configuration object, if None the Controller will load it's own configuration from default paths pools -- a list of pool names to restrict the used pool directories pool_checks -- boolean (default True), if False will disable checking online status of Slaves debug -- integer (default 0), sets debug level of LNST """ self._config = self._load_ctl_config(config) config = self._config mac_pool_range = config.get_option('environment', 'mac_pool_range') self._mac_pool = MacPool(mac_pool_range[0], mac_pool_range[1]) self._log_ctl = LoggingCtl( debug, log_dir=config.get_option('environment', 'log_dir'), log_subdir=datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"), colours=not config.get_option("colours", "disable_colours")) self._msg_dispatcher = MessageDispatcher(self._log_ctl) self._network_bridges = {} self._mapper = mapper() select_pools = {} conf_pools = config.get_pools() if len(pools) > 0: for pool_name in pools: if pool_name in conf_pools: select_pools[pool_name] = conf_pools[pool_name] elif len(pools) == 1 and os.path.isdir(pool_name): select_pools = {"cmd_line_pool": pool_name} else: raise ControllerError("Pool %s does not exist!" % pool_name) else: select_pools = conf_pools self._pools = poolMgr(select_pools, self._msg_dispatcher, config, pool_checks)
def map_device(self, dev_id, how): #TODO if this is supposed to be public it should be better than dict["hwaddr"]!!!! hwaddr = how["hwaddr"] dev = self._machine.get_dev_by_hwaddr(hwaddr) if dev: self._objects[dev_id] = dev dev._id = dev_id dev._enable() else: raise ControllerError( "Device with macaddr {} not found on {}.".format( hwaddr, self.hostid))
def init_libvirt_con(): try: import libvirt from libvirt import libvirtError except ModuleNotFoundError: msg = "Failed to import libvirt, please install the dependency if you want to use the libvirt network management feature." logging.error(msg) raise ControllerError(msg) global _libvirt_conn if _libvirt_conn is None: _libvirt_conn = libvirt.open(None)
def run(self, recipe, **kwargs): """Execute the provided Recipe This method takes care of both finding Agent hosts matching the Recipe requirements, provisioning them and calling the *test* method of the Recipe object with proper references to the mapped Hosts :param recipe: an instantiated Recipe object :type recipe: :py:class:`lnst.Controller.Recipe.BaseRecipe` :param kwargs: optional keyword arguments passed to the configured Mapper :type kwargs: Dict[str, Any] """ if not isinstance(recipe, BaseRecipe): raise ControllerError( "recipe argument must be a BaseRecipe instance.") recipe_ctl = RecipeControl(self, recipe) recipe._set_ctl(recipe_ctl) req = recipe.req self._mapper.set_pools_manager(self._pools) self._mapper.set_requirements(req._to_dict()) i = 0 for match in self._mapper.matches(**kwargs): self._log_ctl.set_recipe(recipe.__class__.__name__, expand="match_%d" % i) i += 1 for line in format_match_description(match).split('\n'): logging.info(line) try: self._map_match(match, req, recipe) recipe._init_run( RecipeRun(recipe, match, log_dir=self._log_ctl.get_recipe_log_path(), log_list=self._log_ctl.get_recipe_log_list())) recipe.test() except Exception as exc: recipe.current_run.exception = exc logging.error( "Recipe execution terminated by unexpected exception") log_exc_traceback() raise finally: self._cleanup_agents()
def run(self, recipe, **kwargs): """Execute the provided Recipe This method takes care of both finding a Slave hosts matching the Recipe requirements, provisioning them and calling the 'test' method of the Recipe object with proper references to the mapped Hosts Args: recipe -- an instantiated Recipe object (isinstance BaseRecipe) kwargs -- optional keyword arguments passed to the configured Mapper """ if not isinstance(recipe, BaseRecipe): raise ControllerError( "recipe argument must be a BaseRecipe instance.") req = recipe.req self._mapper.set_pools(self._pools.get_pools()) self._mapper.set_requirements(req._to_dict()) i = 0 for match in self._mapper.matches(**kwargs): self._log_ctl.set_recipe(recipe.__class__.__name__, expand="match_%d" % i) i += 1 self._print_match_description(match) self._map_match(match, req) try: recipe._set_hosts(self._hosts) recipe.test() except Exception as exc: logging.error( "Recipe execution terminated by unexpected exception") log_exc_traceback() raise finally: recipe._set_hosts(None) for machine in self._machines.values(): machine.restore_system_config() self._cleanup_slaves()