Ejemplo n.º 1
0
    def _allocate_static_ip(self, sid: str) -> Optional[IPDesc]:
        """
        Check if static IP allocation is enabled and then check
        subscriber DB for assigned static IP for the SID
        """
        ip_addr_info = self._subscriber_client.get_subscriber_ip(sid)
        if ip_addr_info is None:
            return None
        logging.debug("Found static IP: sid: %s ip_addr_info: %s", sid,
                      str(ip_addr_info))
        # Validate static IP is not in any of IP pool.
        for ip_pool in self._store.assigned_ip_blocks:
            if ip_addr_info.ip in ip_pool:
                error_msg = "Static Ip {} Overlap with IP-POOL: {}".format(
                    ip_addr_info.ip, ip_pool)
                logging.error(error_msg)
                raise DuplicateIPAssignmentError(error_msg)

        # update gw info if available.
        if ip_addr_info.net_info.gw_ip:
            self._store.dhcp_gw_info.update_ip(ip_addr_info.net_info.gw_ip,
                                               ip_addr_info.net_info.vlan)
            # update mac if IP is present.
            if ip_addr_info.net_info.gw_mac != "":
                self._store.dhcp_gw_info.update_mac(
                    ip_addr_info.net_info.gw_ip, ip_addr_info.net_info.gw_mac,
                    ip_addr_info.net_info.vlan)
        ip_block = ip_network(ip_addr_info.ip)
        self._store.assigned_ip_blocks.add(ip_block)
        return IPDesc(ip=ip_addr_info.ip,
                      state=IPState.ALLOCATED,
                      sid=sid,
                      ip_block=ip_block,
                      ip_type=IPType.STATIC,
                      vlan_id=ip_addr_info.net_info.vlan)
Ejemplo n.º 2
0
    def add_ip_block(self, ipblock: ip_network):
        """ Add a block of IP addresses to the free IP list

        IP blocks should not overlap.

        Args:
            ipblock (ipaddress.ip_network): ip network to add
            e.g. ipaddress.ip_network("10.0.0.0/24")

        Raises:
            OverlappedIPBlocksError: if the given IP block overlaps with
            existing ones
        """
        for blk in self._assigned_ip_blocks:
            if ipblock.overlaps(blk):
                logging.error("Overlapped IP block: %s", ipblock)
                raise OverlappedIPBlocksError(ipblock)

        self._assigned_ip_blocks.add(ipblock)
        # TODO(oramadan) t23793559 HACK reserve the GW address for
        #  gtp_br0 iface and test VM
        num_reserved_addresses = 11
        for ip in ipblock.hosts():
            state = IPState.RESERVED if num_reserved_addresses > 0 \
                else IPState.FREE
            ip_desc = IPDesc(ip=ip, state=state, ip_block=ipblock, sid=None)
            self._ip_state_map.add_ip_to_state(ip, ip_desc, state)
            if num_reserved_addresses > 0:
                num_reserved_addresses -= 1
Ejemplo n.º 3
0
    def alloc_ip_address(self, sid: str) -> IPDesc:
        """
        Assumption: one-to-one mappings between SID and IP.

        Args:
            sid (string): universal subscriber id

        Returns:
            ipaddress.ip_address: IP address allocated

        Raises:
            NoAvailableIPError: if run out of available IP addresses
        """
        mac = create_mac_from_sid(sid)
        LOG.debug("allocate IP for %s mac %s", sid, mac)

        dhcp_desc = self._dhcp_client.get_dhcp_desc(mac)
        LOG.debug("got IP from redis: %s", dhcp_desc)

        if dhcp_allocated_ip(dhcp_desc) is not True:
            dhcp_desc = self._alloc_ip_address_from_dhcp(mac)

        if dhcp_allocated_ip(dhcp_desc):
            ip_block = ip_network(dhcp_desc.subnet)
            ip_desc = IPDesc(ip_address(dhcp_desc.ip), IPState.ALLOCATED, sid,
                             ip_block)
            LOG.debug("Got IP after sending DHCP requests: %s", ip_desc)
            self._assigned_ip_blocks.add(ip_block)

            return ip_desc
        else:
            raise NoAvailableIPError("No available IP addresses From DHCP")
Ejemplo n.º 4
0
    def test_remove_after_releasing_some_addresses(self):
        """ removing after releasing all allocated addresses """
        self._new_ip_allocator(self._block)

        ip0 = self._allocator.alloc_ip_address('SID0', 0).ip
        ip1 = self._allocator.alloc_ip_address('SID1', 0).ip
        ip2 = self._allocator.alloc_ip_address('SID2', 0).ip

        ip_desc0 = IPDesc(ip=ip0, sid='SID0')
        ip_desc1 = IPDesc(ip=ip1, sid='SID1')
        ip_desc2 = IPDesc(ip=ip2, sid='SID2')
        self._allocator.release_ip(ip_desc0)
        self._allocator.release_ip(ip_desc1)
        self._allocator.release_ip(ip_desc2)

        self.assertEqual({},
                         self._allocator._store.sid_session_prefix_allocated)
Ejemplo n.º 5
0
 def _allocate_static_ip(self, sid: str) -> IPDesc:
     """
     Check if static IP allocation is enabled and then check
     subscriber DB for assigned static IP for the SID
     """
     ip_addr = self._subscriber_client.get_subscriber_ip(sid)
     if ip_addr is None:
         return None
     return IPDesc(ip=ip_addr, state=IPState.ALLOCATED,
                   sid=sid, ip_block=ip_addr, ip_type=IPType.STATIC)
Ejemplo n.º 6
0
    def test_release_ipv6_address(self):
        """ test release_ip_address """
        ip0 = self._allocator.alloc_ip_address('SID0', 0).ip

        # release ip
        ip_desc = IPDesc(ip=ip0, sid='SID0')
        self._allocator.release_ip(ip_desc)

        # double release
        with self.assertRaises(IPNotInUseError):
            self._allocator.release_ip(ip_desc)
Ejemplo n.º 7
0
    def alloc_ip_address(self, sid: str, vlan_id: int) -> IPDesc:
        """
        Assumption: one-to-one mappings between SID and IP.

        Args:
            sid (string): universal subscriber id
            vlan_id: vlan of the APN

        Returns:
            ipaddress.ip_address: IP address allocated

        Raises:
            NoAvailableIPError: if run out of available IP addresses
        """
        mac = create_mac_from_sid(sid)

        dhcp_desc = self._dhcp_client.get_dhcp_desc(mac, vlan_id)
        LOG.debug(
            "allocate IP for %s mac %s dhcp_desc %s",
            sid,
            mac,
            dhcp_desc,
        )

        if not dhcp_desc or not dhcp_allocated_ip(dhcp_desc):
            dhcp_desc = self._alloc_ip_address_from_dhcp(mac, vlan_id)

        if dhcp_desc and dhcp_allocated_ip(dhcp_desc):
            ip_block = ip_network(dhcp_desc.subnet)
            ip_desc = IPDesc(
                ip=ip_address(dhcp_desc.ip),
                state=IPState.ALLOCATED,
                sid=sid,
                ip_block=ip_block,
                ip_type=IPType.DHCP,
                vlan_id=vlan_id,
            )
            self._store.assigned_ip_blocks.add(ip_block)

            return ip_desc
        else:
            msg = "No available IP addresses From DHCP for SID: {} MAC {}".format(
                sid,
                mac,
            )
            raise NoAvailableIPError(msg)
Ejemplo n.º 8
0
 def _allocate_static_ip(self, sid: str) -> Optional[IPDesc]:
     """
     Check if static IP allocation is enabled and then check
     subscriber DB for assigned static IP for the SID
     """
     ip_addr_info = self._subscriber_client.get_subscriber_ip(sid)
     if ip_addr_info is None:
         return None
     logging.debug("Found static IP: sid: %s ip_addr_info: %s",
                   sid, str(ip_addr_info))
     # update gw info if available.
     if ip_addr_info.gw_ip:
         self._gw_info.update_ip(ip_addr_info.gw_ip, str(ip_addr_info.vlan))
         # update mac if IP is present.
         if ip_addr_info.gw_mac != "":
             self._gw_info.update_mac(ip_addr_info.gw_ip,
                                      ip_addr_info.gw_mac,
                                      str(ip_addr_info.vlan))
     ip_block = ip_network(ip_addr_info.ip)
     self._assigned_ip_blocks.add(ip_block)
     return IPDesc(ip=ip_addr_info.ip, state=IPState.ALLOCATED,
                   sid=sid, ip_block=ip_block, ip_type=IPType.STATIC,
                   vlan_id=ip_addr_info.vlan)
Ejemplo n.º 9
0
    def test_ip_alloc(self):
        sid1 = "IMSI02917"
        ip1, _ = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        dhcp_gw_info = self._dhcp_allocator._store.dhcp_gw_info
        dhcp_store = self._dhcp_allocator._store.dhcp_store

        self.assertEqual(str(dhcp_gw_info.get_gw_ip()), "192.168.128.211")
        self._dhcp_allocator.release_ip_address(sid1, ip1)

        # wait for DHCP release
        threading.Event().wait(7)
        mac1 = create_mac_from_sid(sid1)
        dhcp_state1 = dhcp_store.get(mac1.as_redis_key(None))

        self.assertEqual(dhcp_state1, None)

        ip1_1, _ = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        self.assertEqual(str(ip1), str(ip1_1))

        self._dhcp_allocator.release_ip_address(sid1, ip1_1)
        threading.Event().wait(5)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(), [])

        ip1, _ = self._dhcp_allocator.alloc_ip_address("IMSI02918")
        self.assertEqual(str(ip1), "192.168.128.146")
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        ip2, _ = self._dhcp_allocator.alloc_ip_address("IMSI029192")
        self.assertNotEqual(ip1, ip2)

        ip3, _ = self._dhcp_allocator.alloc_ip_address("IMSI0432")
        self.assertNotEqual(ip1, ip3)
        self.assertNotEqual(ip2, ip3)
        # release unallocated IP of SID
        ip_unallocated = IPDesc(
            ip=ip3,
            state=IPState.ALLOCATED,
            sid="IMSI033",
            ip_block=ip_network("1.1.1.0/24"),
            ip_type=IPType.DHCP,
        )
        self._dhcp_allocator.ip_allocator.release_ip(ip_unallocated)
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        sid4 = "IMSI54321"
        ip4, _ = self._dhcp_allocator.alloc_ip_address(sid4)
        threading.Event().wait(1)
        self._dhcp_allocator.release_ip_address(sid4, ip4)
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        # wait for DHCP release
        threading.Event().wait(7)
        mac4 = create_mac_from_sid(sid4)
        dhcp_state = dhcp_store.get(mac4.as_redis_key(None))

        self.assertEqual(dhcp_state, None)
        ip4_2, _ = self._dhcp_allocator.alloc_ip_address(sid4)
        self.assertEqual(ip4, ip4_2)

        try:
            self._dhcp_allocator.release_ip_address(sid1, ip1)
            self.assertEqual("should not", "reach here")
        except MappingNotFoundError:
            pass