Source code for lago.sdk

from __future__ import absolute_import
from __future__ import print_function

from future.builtins import super
from lago import cmd
from lago.config import config as lago_config
from lago.lago_ansible import LagoAnsible
from lago import workdir as lago_workdir
from lago.log_utils import get_default_log_formatter
from lago.sdk_utils import SDKWrapper, setup_sdk_logging
import weakref
import os
import logging


[docs]def add_stream_logger(level=logging.DEBUG, name=None): """ Add a stream logger. This can be used for printing all SDK calls to stdout while working in an interactive session. Note this is a logger for the entire module, which will apply to all environments started in the same session. If you need a specific logger pass a ``logfile`` to :func:`~sdk.init` Args: level(int): :mod:`logging` log level name(str): logger name, will default to the root logger. Returns: None """ logger = logging.getLogger(name) logger.setLevel(level) handler = logging.StreamHandler() handler.setFormatter(get_default_log_formatter()) handler.setLevel(level) logger.addHandler(handler)
[docs]def init(config, workdir=None, logfile=None, loglevel=logging.INFO, **kwargs): """ Initialize the Lago environment Args: config(str): Path to LagoInitFile workdir(str): Path to initalize the workdir, defaults to "$PWD/.lago" **kwargs(dict): Pass arguments to :func:`~lago.cmd.do_init` logfile(str): A path to setup a log file. loglevel(int): :mod:`logging` log level. Returns: :class:`~lago.sdk.SDK`: Initialized Lago enviornment Raises: :exc:`~lago.utils.LagoException`: If initialization failed """ setup_sdk_logging(logfile, loglevel) defaults = lago_config.get_section('init') if workdir is None: workdir = os.path.abspath('.lago') defaults['workdir'] = workdir defaults['virt_config'] = config defaults.update(kwargs) workdir, prefix = cmd.do_init(**defaults) return SDK(workdir, prefix)
[docs]def load_env(workdir, logfile=None, loglevel=logging.INFO): """ Load an existing Lago environment Args: workdir(str): Path to the workdir directory, as created by :func:`~lago.sdk.init` or created by the CLI. logfile(str): A Path to setup a log file. loglevel(int): :mod:`logging` log level. Returns: :class:`~lago.sdk.SDK`: Initialized Lago environment Raises: :exc:`~lago.utils.LagoException`: If loading the environment failed. """ setup_sdk_logging(logfile, loglevel) workdir = os.path.abspath(workdir) loaded_workdir = lago_workdir.Workdir(path=workdir) prefix = loaded_workdir.get_prefix('current') return SDK(loaded_workdir, prefix)
[docs]class SDK(object): """ The SDK can be initialized in 3 ways: 1. (Preferred) - by calling :func:`sdk.init`. 2. By loading an existing workdir from the disk, with :func:`~load_env`. 3. By passing already created workdir and prefix objects. """ def __init__(self, workdir, prefix): """ __init__ Args: workdir(:class:`~lago.workdir.Workdir`): The enviornment workdir. prefix(:class:~lago.prefix.Prefix): The enviornment Prefix. Returns: None """ self._workdir = workdir self._prefix = prefix # Proxy object to the prefix to expose self._pprefix = SDKWrapper(weakref.proxy(self._prefix)) def __getattr__(self, name): try: attr = super().__getattr__(name) except AttributeError: attr = getattr(self._pprefix, name) return attr def __dir__(self): # For auto-complete to work, we need to return the methods of the proxy # object as well, which we return in __getattr__. # As we cannot call self.__dir__, we need to construct 'self's # attributes. return sorted( set(dir(type(self)) + list(self.__dict__) + dir(self._pprefix)) )
[docs] def destroy(self): """ Destroy the environment, this will terminate all resources, and remove entirely the Lago working directory. """ self._workdir.destroy()
[docs] def ansible_inventory_temp_file( self, keys=['vm-type', 'groups', 'vm-provider'] ): """ Context manager which returns Ansible inventory written on a tempfile. This is the same as :func:`~ansible_inventory`, only the inventory file is written to a tempfile. Args: keys (list of str): Path to the keys that will be used to create groups. Yields: tempfile.NamedTemporaryFile: Temp file containing the inventory """ lansible = LagoAnsible(self._prefix) return lansible.get_inventory_temp_file(keys=keys)
[docs] def ansible_inventory( self, keys=['vm-type', 'groups', 'vm-provider'], ): """ Get an Ansible inventory as a string, ``keys`` should be list on which to group the hosts by. You can use any key defined in LagoInitFile. Examples of possible `keys`: `keys=['disks/0/metadata/arch']`, would group the hosts by the architecture. `keys=['/disks/0/metadata/distro', 'disks/0/metadata/arch']`, would create groups by architecture and also by distro. `keys=['groups']` - would group hosts by the groups defined for each VM in the LagoInitFile, i.e.: domains: vm-01: ... groups: web-server .. vm-02: .. groups: db-server Args: keys (list of str): Path to the keys that will be used to create groups. Returns: str: INI-like Ansible inventory """ lansible = LagoAnsible(self._prefix) return lansible.get_inventory_str(keys=keys)