Source code for pybsd.handlers

# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

import logging

import unipath

from . import network
from .exceptions import InvalidMainIPError, MasterJailMismatchError, MissingMainIPError
from .utils import from_split_if, split_if

__logger__ = logging.getLogger('pybsd')


[docs]class BaseJailHandler(object): """Provides a base jail handler Handlers allow custom parametrization and customization of all logic pertaining to the jails. Each aspect of the handling is delegated to a method that can be called from the master or the jail. Parameters ---------- master : Optional[:py:class:`~pybsd.systems.masters.Master`] The handler's master. jail_root : :py:class:`str` the path on the host's filesystem to the jails directory that the handler will enforce Attributes ---------- default_jail_root : :py:class:`str` the default jail_root. jail_class_ids : :py:class:`dict` a dictionary linking jail class types and the numerical ids that are to be linked to them by this handler. Raises ------ MissingMainIPError when a master's interface does not define a main_if InvalidMainIPError when a master's main_if violates established rules MasterJailMismatchError if a `master` and a `jail` called in a method are not related """ default_jail_root = '/usr/jails' jail_class_ids = {'service': 1, 'web': 2} def __init__(self, master=None, jail_root=None): super(BaseJailHandler, self).__init__() self.master = master j = jail_root or '/usr/jails' self.jail_root = unipath.Path(j) @classmethod
[docs] def derive_interface(cls, master_if, jail): """Derives a jail's :py:class:`~pybsd.network.Interface` based on the handler's master's Parameters ---------- master_if : :py:class:`~pybsd.systems.jails.Jail` master's :py:class:`~pybsd.network.Interface` to which the jail's is attched jail : :py:class:`~pybsd.network.Interface` the jail whose :py:class:`~pybsd.network.Interface` is requested Returns ------- : :py:class:`~pybsd.network.Interface` the jail's :py:class:`~pybsd.network.Interface` Raises ------ MissingMainIPError when a master's interface does not define a main_if InvalidMainIPError when a master's main_if violates established rules """ if master_if.main_ifv4 or master_if.main_ifv6: _if = network.Interface(master_if.name) if master_if.main_ifv4: ip_chunks = split_if(master_if.main_ifv4) if int(ip_chunks[-1]) != 0: raise InvalidMainIPError(jail.master, master_if, "an IPv4 main_ip's last octet must be equal to 0") ip_chunks[4] = str(jail.jail_class_id) ip_chunks[5] = str(jail.uid) _ip = from_split_if(ip_chunks) _if.add_ips(_ip) if master_if.main_ifv6: ip_chunks = split_if(master_if.main_ifv6) if int(ip_chunks[-2]) != 0: raise InvalidMainIPError(jail.master, master_if, "an IPv6 main_ip's penultimate octet must be equal to 0") ip_chunks[7] = str(jail.jail_class_id) ip_chunks[8] = str(jail.uid) ip_chunks[9] = '1' _ip = from_split_if(ip_chunks) _if.add_ips(_ip) return _if else: raise MissingMainIPError(jail.master, master_if)
[docs] def check_mismatch(self, jail): """Checks whether a given jail belongs to the handler's master Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose status is checked Returns ------- : :py:class:`bool` whether the jail belongs to the handler's master Raises ------ MasterJailMismatchError if a `master` and a `jail` called in a method are not related """ if jail.master != self.master: raise MasterJailMismatchError(self.master, jail)
[docs] def get_jail_type(self, jail): """Returns a given jail's type. The default implementation simply honours the master's default jail type and provides an esaily overridable method where custom logic can be applied. Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose jail type is requested Returns ------- : :py:class:`str` the jail's type. For base values see :py:meth:`~pybsd.systems.jails.Jail.jail_type` """ self.check_mismatch(jail) return self.master.default_jail_type
[docs] def get_jail_hostname(self, jail, strict=True): """Returns a given jail's hostname. if strict is set to `False`, it will evaluate what the jail hostname would be if it were attached to the handler's master. Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose hostname is requested strict : Optional[ :py:class:`bool` ] whether the handler should only return hostnames for jails attached to its master. Default is `True`. Returns ------- : :py:class:`unipath.Path` the jail's path """ if strict: self.check_mismatch(jail) return '{}.{}'.format(jail.name, self.master.hostname)
[docs] def get_jail_path(self, jail): """Returns a given jail's path Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose path is requested Returns ------- : :py:class:`unipath.Path` the jail's path """ self.check_mismatch(jail) return self.jail_root.child(jail.name)
[docs] def get_jail_ext_if(self, jail): """Returns a given jail's ext_if Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose ext_if is requested Returns ------- : :py:class:`~pybsd.network.Interface` the jail's ext_if """ self.check_mismatch(jail) return self.derive_interface(self.master.j_if, jail=jail)
[docs] def get_jail_lo_if(self, jail): """Returns a given jail's lo_if Parameters ---------- jail : :py:class:`~pybsd.systems.jails.Jail` the jail whose lo_if is requested Returns ------- : :py:class:`~pybsd.network.Interface` the jail's lo_if """ self.check_mismatch(jail) return self.derive_interface(self.master.jlo_if, jail=jail)