Пример #1
0
    def host_set_vars(self, host, data):
        """Set keyval parameter for a host.

        This method sets a keyval argument for given host. In case of plain
        variables, that do not involve ip address resources, it simply sets
        keyvals using Host.set_keyval().

        When the keyval involves ip addresses, it takes care of auto-assignement,
        if value has not been provided (==user asked for auto assignement) or
        simply marks given IP as allocated so that it is not auto-assigned later
        on.

        Args:
            host: name of the host keyval should be assigned to
            data: a list of hashes with two keys:
                {"key": key of the variable, "val": variable's value}

        Raises:
            MalformedInputException: provided data does not make sense.
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n in self._data['hosts']:
            for keyval in data:
                if v.KeyWordValidator.is_ipaddress_keyword(keyval["key"]):
                    # First, lets deallocate old ip (if any):
                    ip = self._data['hosts'][host_n].get_keyval(
                        keyval["key"], reporting=False)
                    if ip is not None:
                        self._ippool_find_and_deallocate(ip)
                    if keyval["val"] is None:
                        # Lets find a group with a pool capable of assigning an
                        # address to us
                        groups = self.host_to_groups(host_n)
                        ippool = None
                        for group in groups:
                            tmp = self._data['groups'][group].get_pool(
                                keyval["key"])
                            if tmp is not None and ippool is None:
                                ippool = tmp
                            else:
                                msg = "Host {0} may get ip for var {1} "
                                msg += "from more than one ippool: {2} <-> {3}"
                                MalformedInputException(
                                    msg.format(host_n, keyval["key"], tmp,
                                               ippool))
                        if ippool is None:
                            msg = "There are no ippools suitable for assigning"
                            msg += " an IP to " + keyval[
                                "key"] + " variable for"
                            msg += " this host"
                            raise MalformedInputException(msg)
                        else:
                            keyval["val"] = \
                                self._data['ippools'][ippool].allocate()
                    else:
                        self._ippool_find_and_assign(keyval["val"])
                self._data['hosts'][host_n].set_keyval(keyval)
        else:
            raise MalformedInputException(
                "Host {0} does not exist!".format(host_n))
Пример #2
0
    def host_alias_add(self, host, alias):
        """Assign an alias to the host

        Add an alias to a host, but first check whether it has not been assigned
        yet, either as a hostname or some other alias.

        Raises:
            MalformedInputException: either host to which alias should be assigned
                does not exists, or a host/alias with such name already exists,
                or host/alias are malformed.
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n in self._data['hosts']:
            alias_n = v.HostnameParser.normalize_hostname(alias)
            if alias_n not in self._data['hosts']:
                for tmp in self._data['hosts']:
                    if self._data['hosts'][tmp].get_aliases(alias_n,
                                                            reporting=False):
                        msg = "Alias {0} is already assigned to host {1}"
                        raise MalformedInputException(msg.format(alias_n, tmp))
                else:
                    self._data['hosts'][host_n].alias_add(alias_n)
            else:
                msg = "There exists host with the same name as an alias {0}."
                raise MalformedInputException(msg.format(alias_n))
        else:
            raise MalformedInputException(
                "Host {0} does not exist!".format(host_n))
Пример #3
0
    def _ippool_overlaps(self, other=None):
        """Check if two ip pool overlap

        Depending on orguments, this method checks all ip pools or just
        selected one for conflicts with other ip pools.

        Args:
            other: ip pool to check, None if checking all IP pools is desired

        Raises:
            BadDataException if ip pool/pools overlap, None otherwise
        """
        logging.info("Checking for overlapping ip pools")
        if other is not None:
            for tmp in self._data["ippools"]:
                if other.overlaps(self._data["ippools"][tmp]):
                    msg = "Ippool {0} overlaps ".format(other)
                    msg += "with {0}".format(self._data["ippools"][tmp])
                    raise MalformedInputException(msg)
        else:
            # Check for all ippools for conflicts:
            # Simple n^2 algorithm, divide-an-conquer has 0.5(n^2-n) ~= O(n^2).
            # FIXME - add sorting the table first!
            tmp = list(self._data["ippools"].keys())
            size = len(tmp)
            for i in range(size - 1):
                for j in range(i + 1, size):
                    if self._data["ippools"][tmp[i]].overlaps(
                            self._data["ippools"][tmp[j]]):
                        msg = "Ippool {0} overlaps with {1}".format(
                            tmp[i], tmp[j])
                        raise BadDataException(msg)
Пример #4
0
    def host_del(self, host):
        """Delete host from inventory

        This method deltes host from inventory, and removes it from all the groups
        it was member of.

        Args:
            host: name of the host to remove

        Raises:
            MalformedInputException: host with given name does not exists, or is
                malformed
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n in self._data['hosts']:
            # Remove the host from all groups:
            for group in self._data['groups']:
                self._data['groups'][group].del_host(host_n, reporting=False)
            # Remove host's IP from all ip pools:
            for ippool in self._data["ippools"]:
                for var in v.KeyWordValidator.get_ipaddress_keywords():
                    ip = self._data['hosts'][host].get_keyval(var,
                                                              reporting=False)
                    if ip is not None and ip in self._data["ippools"][ippool]:
                        self._data["ippools"][ippool].release(ip)
            # And finally remove the host itself
            del self._data['hosts'][host_n]
        else:
            raise MalformedInputException(
                "Host {0} does not exist!".format(host_n))
Пример #5
0
    def get_keyval(self, key=None, reporting=True):
        """Get a value for given key or all keyvals

        Important to note is the fact that exception handling is quite heavy,
        so for loops that issue a lot of obj.get_keyval calls, we specify
        reporting=False param and just check for None object as an output.

        Args:
            key: key of the value that should be returned. None if returning
                all keys is desired.
            reporting: In case of inexistant key, should an exception be
                returned or just a 'None'.

        Raises:
            MalformedInputException: only when reporting is True - provided key
                has not been found in hosts data
        """
        if key is None:
            ret = self._keyvals.copy()
            ret['aliases'] = list(self._aliases)
            return ret
        elif key == 'aliases':
            return list(self._aliases)
        else:
            if key in self._keyvals:
                return self._keyvals[key]
            elif reporting:
                raise MalformedInputException(
                    "Key {0} has not been found.".format(key))
            else:
                return None
Пример #6
0
    def host_del_vars(self, host, keys):
        """Remove a keyval from host

        Removes a keyval from host object and takes care of deallocating ip
        addresses from ip pools if applicable.

        Args:
            host: name of the host keyval should be removed from
            key: keys used to identify keyvals destined for deletion

        Raises:
            MalformedInputException: host or key with given name does not exists,
                or host is malformed
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n in self._data['hosts']:
            for key in keys:
                if v.KeyWordValidator.is_ipaddress_keyword(key):
                    # First, lets deallocate old ip (if any):
                    ip = self._data['hosts'][host_n].get_keyval(
                        key, reporting=False)
                    if ip is not None:
                        self._ippool_find_and_deallocate(ip)
                self._data['hosts'][host_n].del_keyval(key)
        else:
            raise MalformedInputException(
                "Host {0} does not exist!".format(host_n))
Пример #7
0
    def host_rename(self, host_old, host_new):
        """Rename a host

        Args:
            host_old: old hostname
            host_new: new hostname

        Raises:
            MalformedInputException: host_old does not exist, or both hostnames
                are malformed.
        """
        # Sanity checking first:
        if host_old not in self._data['hosts']:
            msg = "Host {0} does not exist, and thus cannot be renamed"
            raise MalformedInputException(msg.format(host_old))
        host_new_n = v.HostnameParser.normalize_hostname(host_new)

        # First, lets rename it in "hosts" hash:
        self._data['hosts'][host_new_n] = self._data['hosts'].pop(host_old)

        # And now lets rename all references in groups:
        for group in self._data['groups']:
            try:
                self._data['groups'][group].del_host(host_old)
            except MalformedInputException:
                pass
            else:
                self._data['groups'][group].add_host(host_new_n)
Пример #8
0
    def host_get(self, host=None):
        """Get a Host object identified by name.

        Args:
            host: name of the host to get, or None if all object names should
                returned

        Returns:
            Depending on the value of group param, either all object *names* are
            returned, or the *object* identified by group param

        Raises:
            MalformedInputException: host with given name does not exists or is
                malformed.
        """
        if host is not None:
            host_n = v.HostnameParser.normalize_hostname(host)
            if host_n not in self._data['hosts']:
                msg = "Host {0} does not exist".format(host_n)
                raise MalformedInputException(msg)
            else:
                return self._data['hosts'][host_n]
        else:
            # Create a shallow copy of the internal data
            return list(self._data['hosts'])
Пример #9
0
    def allocate(self, ip=None):
        """Allocate an IP from the pool.

        Method allocates next free adress from the pool if ip is None, or
        marks given ip as already allocated

        Args:
            ip: either None or ipaddress.ip_address object

        Returns:
            An ip that has been allocated. In case when "ip" argument is not
            none, then the object pointed by it is returned.

        Raises:
            MalformedInputException - user provided data is invalid
            GenericException - pool has run out of free ip adresses
        """
        if ip is not None:
            if ip not in self._network:
                msg = "Attempt to allocate IP from outside of the pool: "
                msg += "{0} is not in {1}.".format(ip, self._network)
                raise MalformedInputException(msg)
            if ip in self._allocated:
                msg = "Attempt to allocate already allocated IP: " + str(ip)
                raise MalformedInputException(msg)
            elif ip in self._reserved:
                msg = "Attempt to allocate from reserved pool: " + str(ip)
                raise MalformedInputException(msg)
            else:
                self._allocated.append(ip)
                return ip
        else:
            for candidate in [
                    x for x in self._network
                    if x != self._network.__getattribute__(
                        ipaddress_name_broadcast) and
                    x != self._network.__getattribute__(ipaddress_name_network)
            ]:
                if candidate not in self._allocated and \
                        candidate not in self._reserved:
                    logging.info(
                        "IP {0} has been auto-assigned.".format(candidate))
                    self._allocated.append(candidate)
                    return candidate
            msg = "The pool has run out of free ip addresses."
            raise GenericException(msg)
Пример #10
0
    def book(self, ip):
        """Prevent IP from being allocated.

        Marks given IP as reserved/unavailable for allocation.

        Args:
            ip: ip to book.

        Raises:
            MalformedInputException: ip does not belong to this pool
        """
        if ip not in self._network:
            msg = "IP {0} does not belong to network {1}".format(
                ip, self._network)
            raise MalformedInputException(msg)
        elif ip in self._reserved:
            msg = "IP {0} has already been booked".format(ip)
            raise MalformedInputException(msg)
        else:
            self._reserved.append(ip)
Пример #11
0
    def group_child_add(self, group, child):
        """Add a child group to group

        Args:
            group: name of the group to add child to
            child: name of the child group

        Raises:
            MalformedInputException: either child group or a parent group does
                not exists.
        """
        if group in self._data['groups']:
            if child in self._data['groups']:
                self._data['groups'][group].add_child(child)
            else:
                msg = "Child group {0} does not exist!".format(child)
                raise MalformedInputException(msg)
        else:
            raise MalformedInputException(
                "Group {0} does not exist!".format(group))
Пример #12
0
    def group_host_add(self, group, host):
        """Add a host to a group

        Args:
            host: name of the host
            group: name of the group

        Raises:
            MalformedInputException: either host or group does not exist, or
                host name is malformed.
        """
        if group in self._data['groups']:
            host_n = v.HostnameParser.normalize_hostname(host)
            if host_n in self._data['hosts']:
                self._data['groups'][group].add_host(host_n)
            else:
                msg = "Host {0} does not exist!".format(host_n)
                raise MalformedInputException(msg)
        else:
            msg = "Group {0} does not exist!".format(group)
            raise MalformedInputException(msg)
Пример #13
0
    def ippool_assign(self, pool, group, pool_related_var):
        """Assign pool to group via keyval var

        Args:
            pool: name of the pool to assign
            pool_related_var: keyval that shoul use given pool for ip address
                auto-assignement
            group: name of the group given pool should be assigned to

        Raises:
            MalformedInputException: input data is malformed
        """
        if group not in self._data['groups']:
            msg = "Group with name {0} does not exist!".format(group)
            raise MalformedInputException(msg)
        elif pool not in self._data['ippools']:
            msg = "IP pool with name {0} does not exist!".format(pool)
            raise MalformedInputException(msg)
        else:
            self._data['groups'][group].set_pool(var=pool_related_var,
                                                 name=pool)
Пример #14
0
    def del_pool_by_var(self, var):
        """Unlink ip pool from variable

        Removes the link between some hostvar and an IPPool for given group.

        Args:
            var: variable from which ippool should be unlinked
        """
        try:
            del self._ippools[var]
        except KeyError:
            msg = "Trying to remove a pool from var that has not been assigned yet"
            raise MalformedInputException(msg)
Пример #15
0
    def normalize_hostname(cls, name):
        """Remove backend domain from hostname

        Args:
            name: hostname to standarize

        Returns:
            Hostname relative to cls._backend_domain. Function returns
            unchanged string if hostname was absolute (but in different
            domain), or already relative.
        """
        if cls._backend_domain is None:
            raise MalformedInputException("Backend domain has not been set yet")
        if cls._backend_domain in name and name[-1] != '.':
            msg = "{0} contains default backend domain, append '.' to the end " + \
                  "to force absolute dns names"
            raise MalformedInputException(msg.format(name))
        suffix = '.' + cls._backend_domain + '.'
        if re.search(suffix + '$', name):
            return name[:-len(suffix)]
        else:
            return name
Пример #16
0
    def del_keyval(self, key):
        """Remove val identified by key

        Args:
            key: key to remove

        Raises:
            MalformedInputException: key has not been set yet.
        """
        if key in self._keyvals:
            del self._keyvals[key]
        else:
            raise MalformedInputException("Key {0} has not been found.".format(key))
Пример #17
0
    def group_add(self, group):
        """Add a new group to inventory.

        Args:
            group: name of the new group

        Raises:
            MalformedInputException: group with such name already exists
        """
        if group not in self._data['groups']:
            self._data['groups'][group] = g.Group()
        else:
            raise MalformedInputException(
                "Group {0} already exists!".format(group))
Пример #18
0
    def add_child(self, child):
        """Add a child group to the group

        Args:
            child: child group we are adding

        Raises:
            MalformedInputException: child has already been aded
        """
        if child not in self._children:
            self._children.append(child)
        else:
            msg = "Child {0} has already been added to this group"
            raise MalformedInputException(msg.format(child))
Пример #19
0
    def alias_del(self, alias):
        """Remove alias

        Args:
            alias: alias to remove

        Raises:
            MalformedInputException: alias has not been set yet
        """
        if alias in self._aliases:
            self._aliases.remove(alias)
        else:
            raise MalformedInputException("Alias {0} has not been ".format(alias) +
                                          "assigned to this host yet.")
Пример #20
0
    def alias_add(self, alias):
        """Add new alias for the host

        Args:
            alias: alias to add

        Raises:
            MalformedInputException: alias is already present in the aliases list
        """
        alias_n = v.HostnameParser.normalize_hostname(alias)
        if alias_n not in self._aliases:
            self._aliases.append(alias_n)
        else:
            msg = "Alias {0} has already been added."
            raise MalformedInputException(msg.format(alias_n))
Пример #21
0
    def group_host_del(self, group, host):
        """Remove a host from a group

        Args:
            host: name of the host
            group: name of the group

        Raises:
            MalformedInputException: either host or group does not exist
        """
        if group in self._data['groups']:
            self._data['groups'][group].del_host(host)
        else:
            msg = "Group with name {0} does not exist!".format(group)
            raise MalformedInputException(msg)
Пример #22
0
    def ippool_revoke(self, pool, group, pool_related_var):
        """Revoke pool from group

        Args:
            pool: name of the pool to revoke
            pool_related_var: keyval that has been using given pool for ip address
                auto-assignement
            group: name of the group given pool should be revoked from
        """
        if group not in self._data['groups']:
            msg = "An attemtp to remove ip pool from inexistant group {0}"
            msg = msg.format(group)
            raise MalformedInputException(msg)
        else:
            self._data['groups'][group].del_pool_by_var(var=pool_related_var)
Пример #23
0
    def release(self, ip):
        """Mark given IP as free, available for allocation.

        Args:
            ip: ip to deallocate

        Raises:
            MalformedInputException: provided ip has not been alocated yet.
        """
        if ip in self._allocated:
            self._allocated.remove(ip_address(ip))
        else:
            msg = "An attempt to release an ip {0} ".format(ip)
            msg += "which has not been allocated yet."
            raise MalformedInputException(msg)
Пример #24
0
    def host_add(self, host):
        """Add a host to inventory

        This method simply creates new Host object identified by "host" name
        object in the inventory.

        Args:
            host: name of the new host

        Raises:
            MalformedInputException: host with that name already exists, or is
                malformed
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n not in self._data['hosts']:
            for tmp in self._data['hosts']:
                if self._data['hosts'][tmp].get_aliases(alias=host_n,
                                                        reporting=False):
                    msg = "Host {0} already has alias with the name of new host"
                    raise MalformedInputException(msg.format(tmp))
            self._data['hosts'][host_n] = h.Host()
        else:
            raise MalformedInputException(
                "Host {0} already exist!".format(host_n))
Пример #25
0
    def ippool_del(self, pool):
        """Delete pool

        Args:
            pool: name of the ip pool to delete

        Raises:
            MalformedInputException: pool with given name does not exist
        """
        if pool not in self._data['ippools']:
            msg = "IP Pool {0} does not exist".format(pool)
            raise MalformedInputException(msg)
        else:
            for group in self._data['groups']:
                self._data['groups'][group].del_pool_by_pool(pool)
            del self._data['ippools'][pool]
Пример #26
0
    def group_child_del(self, group, child):
        """Remove a child group from a group

        Args:
            group: name of the group to remove child from
            child: name of the child group

        Raises:
            MalformedInputException: either child group or a parent group does
                exists
        """
        if group in self._data['groups']:
            self._data['groups'][group].del_child(child)
        else:
            msg = "Group with name {0} does not exist!".format(group)
            raise MalformedInputException(msg)
Пример #27
0
    def cancel(self, ip):
        """Remove reservation of an IP address

        Marks given IP as available for allocation.

        Args:
            ip: ip to release

        Raises:
            MalformedInputException: ip has not been reserved yet.
        """
        if ip in self._reserved:
            self._reserved.remove(ip)
        else:
            msg = "IP {0} has not been reserved yet".format(ip)
            raise MalformedInputException(msg)
Пример #28
0
    def add_host(self, host):
        """Add host to group

        Args:
            host: host to add

        Raises:
            MalformedInputException: host has already been added to the group,
                or host name is malformed.
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n not in self._hosts:
            self._hosts.append(host_n)
        else:
            msg = "Host {0} has already been added to this group"
            raise MalformedInputException(msg.format(host_n))
Пример #29
0
    def host_alias_del(self, host, alias):
        """Remove an alias from the host

        Args:
            alias: name of the alias to remove

        Raises:
            MalformedInputException: either alias or host does not exist, or are
                malformed.
        """
        host_n = v.HostnameParser.normalize_hostname(host)
        if host_n in self._data['hosts']:
            self._data['hosts'][host_n].alias_del(alias)
        else:
            raise MalformedInputException(
                "Host {0} does not exist!".format(host))
Пример #30
0
    def ippool_add(self, pool, pool_obj):
        """Add new ip pool object to inventory

        Args:
            pool: name of the pool
            pool_object: an IPPool object

        Raises:
            MalformedInputException: ip pool with given name already exists
        """
        self._ippool_overlaps(pool_obj)
        if pool not in self._data['ippools']:
            self._data['ippools'][pool] = pool_obj
        else:
            raise MalformedInputException("Ippool with name {0}".format(pool) +
                                          "already exists!")