Beispiel #1
0
    def assign_ips(cls, nodes_ids, network_name):
        """Idempotent assignment IP addresses to nodes.

        All nodes passed as first argument get IP address
        from network, referred by network_name.
        If node already has IP address from this network,
        it remains unchanged. If one of the nodes is the
        node from other cluster, this func will fail.

        :param node_ids: List of nodes IDs in database.
        :type  node_ids: list
        :param network_name: Network name
        :type  network_name: str
        :returns: None
        :raises: Exception, errors.AssignIPError
        """
        cluster_id = db().query(Node).get(nodes_ids[0]).cluster_id
        for node_id in nodes_ids:
            node = db().query(Node).get(node_id)
            if node.cluster_id != cluster_id:
                raise Exception(
                    u"Node id='{0}' doesn't belong to cluster_id='{1}'".format(
                        node_id, cluster_id))

        network = db().query(NetworkGroup).\
            filter(NetworkGroup.cluster_id == cluster_id).\
            filter_by(name=network_name).first()

        if not network:
            raise errors.AssignIPError(
                u"Network '%s' for cluster_id=%s not found." %
                (network_name, cluster_id))

        for node_id in nodes_ids:
            node_ips = imap(
                lambda i: i.ip_addr,
                cls._get_ips_except_admin(node_id=node_id,
                                          network_id=network.id))
            # check if any of node_ips in required ranges

            ip_already_assigned = False

            for ip in node_ips:
                if cls.check_ip_belongs_to_net(ip, network):
                    logger.info(u"Node id='{0}' already has an IP address "
                                "inside '{1}' network.".format(
                                    node_id, network.name))
                    ip_already_assigned = True
                    break

            if ip_already_assigned:
                continue

            # IP address has not been assigned, let's do it
            logger.info("Assigning IP for node '{0}' in network '{1}'".format(
                node_id, network_name))
            free_ip = cls.get_free_ips(network.id)[0]
            ip_db = IPAddr(network=network.id, node=node_id, ip_addr=free_ip)
            db().add(ip_db)
            db().commit()
Beispiel #2
0
    def assign_admin_ips(cls, nodes):
        """Method for assigning admin IP addresses to nodes.

        :param node_id: Node database ID.
        :type  node_id: int
        :param num: Number of IP addresses for node.
        :type  num: int
        :returns: None
        """
        # Check which nodes need ips
        # verification that node.ip (which is reported by agent) belongs
        # to one of the ranges of required to be able to reuse admin ip address
        # also such approach is backward compatible
        nodes_need_ips = defaultdict(list)
        for node in nodes:
            node_id = node.id
            admin_net = cls.get_admin_network_group(node_id)
            node_admin_ips = db().query(IPAddr).filter_by(node=node_id,
                                                          network=admin_net.id)
            logger.debug(u"Trying to assign admin ip: node=%s", node_id)
            if not db().query(node_admin_ips.exists()).scalar():
                reusable_ip = cls.reusable_ip_address(node, admin_net)
                if reusable_ip:
                    db().add(reusable_ip)
                else:
                    nodes_need_ips[admin_net].append(node_id)
        db().flush()

        for admin_net, nodes in six.iteritems(nodes_need_ips):
            free_ips = cls.get_free_ips(admin_net, len(nodes))
            for ip, n in zip(free_ips, nodes):
                ip_db = IPAddr(node=n, ip_addr=ip, network=admin_net.id)
                db().add(ip_db)
            db().flush()
Beispiel #3
0
    def assign_admin_ips(cls, node_id, num=1):
        """Method for assigning admin IP addresses to nodes.

        :param node_id: Node database ID.
        :type  node_id: int
        :param num: Number of IP addresses for node.
        :type  num: int
        :returns: None
        """
        admin_net_id = cls.get_admin_network_group_id()
        node_admin_ips = db().query(IPAddr).filter_by(
            node=node_id,
            network=admin_net_id
        ).all()

        if not node_admin_ips or len(node_admin_ips) < num:
            admin_net = db().query(NetworkGroup).get(admin_net_id)
            logger.debug(
                u"Trying to assign admin ips: node=%s count=%s",
                node_id,
                num - len(node_admin_ips)
            )
            free_ips = cls.get_free_ips(
                admin_net.id,
                num=num - len(node_admin_ips)
            )
            logger.info(len(free_ips))
            for ip in free_ips:
                ip_db = IPAddr(
                    node=node_id,
                    ip_addr=ip,
                    network=admin_net_id
                )
                db().add(ip_db)
            db().commit()
Beispiel #4
0
    def reusable_ip_address(cls, node, network):
        """Verifies that ip belongs to network and creates IPAddr in case it is

        :param node: Node database object.
        :param network: Network database object.
        :returns: IPAddr object or None
        """
        if node.ip and cls.check_ip_belongs_to_net(node.ip, network):
            return IPAddr(node=node.id, ip_addr=node.ip, network=network.id)
        return None
Beispiel #5
0
    def assign_vip(cls, cluster_id, network_name):
        """Idempotent assignment VirtualIP addresses to cluster.
        Returns VIP for given cluster and network.

        It's required for HA deployment to have IP address
        not assigned to any of nodes. Currently we need one
        VIP per network in cluster. If cluster already has
        IP address from this network, it remains unchanged.
        If one of the nodes is the node from other cluster,
        this func will fail.

        :param cluster_id: Cluster database ID.
        :type  cluster_id: int
        :param network_name: Network name
        :type  network_name: str
        :returns: None
        :raises: Exception
        """
        cluster = objects.Cluster.get_by_uid(cluster_id)
        if not cluster:
            raise Exception(u"Cluster id='%s' not found" % cluster_id)

        network = db().query(NetworkGroup).\
            filter(NetworkGroup.cluster_id == cluster_id).\
            filter_by(name=network_name).first()

        if not network:
            raise Exception(u"Network '%s' for cluster_id=%s not found." %
                            (network_name, cluster_id))

        admin_net_id = cls.get_admin_network_group_id()
        cluster_ips = [ne.ip_addr for ne in db().query(IPAddr).filter_by(
            network=network.id,
            node=None
        ).filter(
            not_(IPAddr.network == admin_net_id)
        ).all()]
        # check if any of used_ips in required cidr: network.cidr
        ips_belongs_to_net = False
        for ip in cluster_ips:
            if cls.check_ip_belongs_to_net(ip, network):
                ips_belongs_to_net = True
                break

        if ips_belongs_to_net:
            vip = cluster_ips[0]
        else:
            # IP address has not been assigned, let's do it
            vip = cls.get_free_ips(network.id)[0]
            ne_db = IPAddr(network=network.id, ip_addr=vip)
            db().add(ne_db)
            db().commit()

        return vip
Beispiel #6
0
    def reusable_ip_address(cls, node, network):
        """Verifies that ip belongs to network and creates IPAddr in case it did

        :param node: Node database object.
        :param network: Network database object.
        :returns: IPAddr object or None
        """
        #此处暂时先注释掉
        #if node.ip and cls.check_ip_belongs_to_net(node.ip, network):
        logger.info("the node {0} admin ip is {1} power ip is {2}".format(
            node.name, node.ip, node.power_ip))
        return IPAddr(node=node.id, ip_addr=node.ip, network=network.id)
Beispiel #7
0
 def _create_ip_addrs_by_rules(self, cluster, rules):
     created_ips = []
     for net_group in cluster.network_groups:
         if net_group.name not in rules:
             continue
         vips_by_types = rules[net_group.name]
         for vip_type, ip_addr in vips_by_types.items():
             ip = IPAddr(
                 network=net_group.id,
                 ip_addr=ip_addr,
                 vip_type=vip_type,
             )
             self.db.add(ip)
             created_ips.append(ip)
     if created_ips:
         self.db.flush()
     return created_ips
Beispiel #8
0
    def assign_vip(cls,
                   cluster,
                   network_name,
                   vip_type=consts.NETWORK_VIP_TYPES.haproxy):
        """Idempotent assignment of VirtualIP addresses to cluster.
        Returns VIP for given cluster and network.

        It's required for HA deployment to have IP address
        not assigned to any of nodes. Currently we need one
        VIP per network in cluster. If cluster already has
        IP address from this network, it remains unchanged.
        If one of the nodes is the node from other cluster,
        this func will fail.

        :param cluster: Cluster instance
        :type  cluster: Cluster model
        :param network_name: Network name
        :type  network_name: str
        :param vip_type: Type of VIP
        :type  vip_type: str
        :returns: assigned VIP (string)
        :raises: Exception
        """
        group_id = objects.Cluster.get_controllers_group_id(cluster)
        network = db().query(NetworkGroup).\
            filter_by(name=network_name, group_id=group_id).first()

        if not network:
            raise Exception(u"Network '%s' for cluster_id=%s not found." %
                            (network_name, cluster.id))

        cluster_vip = db().query(IPAddr).filter_by(network=network.id,
                                                   node=None,
                                                   vip_type=vip_type).first()
        # check if cluster_vip is in required cidr: network.cidr
        if cluster_vip and cls.check_ip_belongs_to_net(cluster_vip.ip_addr,
                                                       network):
            return cluster_vip.ip_addr

        # IP address has not been assigned, let's do it
        vip = cls.get_free_ips(network)[0]
        ne_db = IPAddr(network=network.id, ip_addr=vip, vip_type=vip_type)
        db().add(ne_db)
        db().flush()

        return vip
Beispiel #9
0
    def test_fail_on_no_vip_metadata(self):
        not_vip_ip_addr = IPAddr(network=self.cluster.network_groups[0].id,
                                 ip_addr="127.0.0.1",
                                 vip_name=None)
        self.db.add(not_vip_ip_addr)
        self.db.flush()
        not_vip_id = not_vip_ip_addr.get('id')

        resp = self.app.get(reverse(self.handler_name,
                                    kwargs={
                                        'cluster_id': self.cluster['id'],
                                        'ip_addr_id': not_vip_id
                                    }),
                            headers=self.default_headers,
                            expect_errors=True)
        self.assertEqual(400, resp.status_code)
        self.assertIn("has no VIP metadata attached",
                      resp.json_body['message'])
Beispiel #10
0
    def test_get_free_ips_from_ranges(self):
        ranges = [IPRange("192.168.33.2", "192.168.33.222")]

        ips = self.env.network_manager.get_free_ips_from_ranges(
            'management', ranges, set(), 3)
        self.assertItemsEqual(["192.168.33.2", "192.168.33.3", "192.168.33.4"],
                              ips)

        self.db.add(IPAddr(ip_addr="192.168.33.3"))
        self.db.flush()
        ips = self.env.network_manager.get_free_ips_from_ranges(
            'management', ranges, set(), 3)
        self.assertItemsEqual(["192.168.33.2", "192.168.33.4", "192.168.33.5"],
                              ips)

        ips = self.env.network_manager.get_free_ips_from_ranges(
            'management', ranges, set(["192.168.33.5", "192.168.33.8"]), 7)
        self.assertItemsEqual([
            "192.168.33.2", "192.168.33.4", "192.168.33.6", "192.168.33.7",
            "192.168.33.9", "192.168.33.10", "192.168.33.11"
        ], ips)
Beispiel #11
0
    def test_get_vip_fail_if_ip_from_generic_admin_net(self):
        generic_admin_id = next(net
                                for net in self.net_manager.get_admin_networks(
                                    cluster_nodegroup_info=True)
                                if net['node_group_id'] is None)['id']

        ip_addr_db = IPAddr(ip_addr='127.0.0.1', network=generic_admin_id)
        self.db.add(ip_addr_db)
        self.db.flush()

        resp = self.app.get(reverse(self.handler_name,
                                    kwargs={
                                        'cluster_id': self.cluster['id'],
                                        'ip_addr_id': ip_addr_db.id
                                    }),
                            headers=self.default_headers,
                            expect_errors=True)

        self.assertEqual(resp.status_code, 400)
        self.assertIn('belongs to default Admin network and cannot be a VIP',
                      resp.json_body['message'])
Beispiel #12
0
    def assign_ips(cls, nodes, network_name):
        """Idempotent assignment IP addresses to nodes.

        All nodes passed as first argument get IP address
        from network, referred by network_name.
        If node already has IP address from this network,
        it remains unchanged. If one of the nodes is the
        node from other cluster, this func will fail.

        :param node_ids: List of nodes IDs in database.
        :type  node_ids: list
        :param network_name: Network name
        :type  network_name: str
        :returns: None
        :raises: Exception, errors.AssignIPError
        """
        cluster_id = nodes[0].cluster_id
        for node in nodes:
            if node.cluster_id != cluster_id:
                raise Exception(
                    u"Node id='{0}' doesn't belong to cluster_id='{1}'".format(
                        node.id, cluster_id))

        network_groups = db().query(NetworkGroup).\
            filter_by(name=network_name)

        if not network_groups:
            raise errors.AssignIPError(
                u"Network '%s' for cluster_id=%s not found." %
                (network_name, cluster_id))

        # Check which nodes need ips
        nodes_need_ips = defaultdict(list)
        for node in nodes:
            node_id = node.id

            if network_name == 'public' and \
                    not objects.Node.should_have_public(node):
                continue
            group_id = (node.group_id
                        or objects.Cluster.get_default_group(node.cluster).id)

            network = network_groups.filter(
                or_(
                    NetworkGroup.group_id == group_id,
                    NetworkGroup.group_id == None  # flake8: noqa
                )).first()

            node_ips = imap(
                lambda i: i.ip_addr,
                cls._get_ips_except_admin(node_id=node_id,
                                          network_id=network.id))

            # check if any of node_ips in required ranges
            ip_already_assigned = False

            for ip in node_ips:
                if cls.check_ip_belongs_to_net(ip, network):
                    logger.info(u"Node id='{0}' already has an IP address "
                                "inside '{1}' network.".format(
                                    node_id, network.name))
                    ip_already_assigned = True
                    break

            if ip_already_assigned:
                continue

            nodes_need_ips[network].append(node_id)

        # Get and assign ips for nodes

        for network, nodes in six.iteritems(nodes_need_ips):
            free_ips = cls.get_free_ips(network, len(nodes))
            for ip, n in zip(free_ips, nodes):
                logger.info(
                    "Assigning IP for node '{0}' in network '{1}'".format(
                        n, network_name))
                pxeip = cls.get_admin_ip_for_node(n)
                logger.info("pxeip is {0}".format(pxeip))
                newip = cls.handleipgroup(pxeip, ip)
                logger.info("newip is {0}".format(newip))
                ip_db = IPAddr(node=n, ip_addr=newip, network=network.id)
                db().add(ip_db)
            db().flush()