def __init__(self, *, config, recycling_interval: int = DEFAULT_IP_RECYCLE_INTERVAL): """ Initializes a new IP allocator Args: recycling_interval (number): minimum time, in seconds, before a released IP is recycled and freed into the pool of available IPs. Default: None, no recycling will occur automatically. """ persist_to_redis = config.get('persist_to_redis', True) redis_port = config.get('redis_port', 6379) if 'allocator_type' in config: if config['allocator_type'] == 'ip_pool': self.allocator_type = IPAllocatorType.IP_POOL elif config['allocator_type'] == 'dhcp': self.allocator_type = IPAllocatorType.DHCP else: raise ArgumentError("unknown allocator config {}" .format(config['allocator_type'])) else: self.allocator_type = IPAllocatorType.IP_POOL logging.debug('Persist to Redis: %s', persist_to_redis) self._lock = threading.RLock() # re-entrant locks self._recycle_timer = None # reference to recycle timer self._recycling_interval_seconds = recycling_interval if not persist_to_redis: self._assigned_ip_blocks = set() # {ip_block} self.sid_ips_map = defaultdict(IPDesc) # {SID=>IPDesc} else: if not redis_port: raise ValueError( 'Must specify a redis_port in mobilityd config.') client = get_default_client() self._assigned_ip_blocks = store.AssignedIpBlocksSet(client) self.sid_ips_map = store.IPDescDict(client) self.ip_state_map = IpDescriptorMap(persist_to_redis, redis_port) if self.allocator_type == IPAllocatorType.IP_POOL: self.ip_allocator = IpAllocatorStatic(self._assigned_ip_blocks, self.ip_state_map, self.sid_ips_map) elif self.allocator_type == IPAllocatorType.DHCP: dhcp_store = store.MacToIP() # mac => DHCP_State dhcp_gw_info = UplinkGatewayInfo(store.GatewayInfoMap()) iface = config.get('dhcp_iface', 'dhcp0') retry_limit = config.get('retry_limit', 300) self.ip_allocator = IPAllocatorDHCP(self._assigned_ip_blocks, self.ip_state_map, iface=iface, retry_limit=retry_limit, dhcp_store=dhcp_store, gw_info=dhcp_gw_info)
def __init__(self): """ Inspect and manipulate DHCP client state. """ self.dhcp_client_state = store.MacToIP() # mac => DHCP_State
def __init__(self, *, config, mconfig, subscriberdb_rpc_stub=None, recycling_interval: int = DEFAULT_IP_RECYCLE_INTERVAL): """ Initializes a new IP allocator Args: recycling_interval (number): minimum time, in seconds, before a released IP is recycled and freed into the pool of available IPs. Default: None, no recycling will occur automatically. """ persist_to_redis = config.get('persist_to_redis', True) redis_port = config.get('redis_port', 6379) self.allocator_type = mconfig.ip_allocator_type logging.debug('Persist to Redis: %s', persist_to_redis) self._lock = threading.RLock() # re-entrant locks self._recycle_timer = None # reference to recycle timer self._recycling_interval_seconds = recycling_interval self.static_ip_enabled = mconfig.static_ip_enabled if not persist_to_redis: self._assigned_ip_blocks = set() # {ip_block} self.sid_ips_map = defaultdict(IPDesc) # {SID=>IPDesc} self._dhcp_gw_info = UplinkGatewayInfo(defaultdict(str)) self._dhcp_store = {} # mac => DHCP_State else: if not redis_port: raise ValueError( 'Must specify a redis_port in mobilityd config.') client = get_default_client() self._assigned_ip_blocks = store.AssignedIpBlocksSet(client) self.sid_ips_map = store.IPDescDict(client) self._dhcp_gw_info = UplinkGatewayInfo(store.GatewayInfoMap()) self._dhcp_store = store.MacToIP() # mac => DHCP_State self.ip_state_map = IpDescriptorMap(persist_to_redis, redis_port) logging.info("Using allocator: %s static ip: %s", self.allocator_type, self.static_ip_enabled) if self.allocator_type == MobilityD.IP_POOL: self._dhcp_gw_info.read_default_gw() ip_allocator = IpAllocatorPool(self._assigned_ip_blocks, self.ip_state_map, self.sid_ips_map) elif self.allocator_type == MobilityD.DHCP: iface = config.get('dhcp_iface', 'dhcp0') retry_limit = config.get('retry_limit', 300) ip_allocator = IPAllocatorDHCP(self._assigned_ip_blocks, self.ip_state_map, iface=iface, retry_limit=retry_limit, dhcp_store=self._dhcp_store, gw_info=self._dhcp_gw_info) if self.static_ip_enabled: self.ip_allocator = IPAllocatorStaticWrapper( subscriberdb_rpc_stub=subscriberdb_rpc_stub, ip_allocator=ip_allocator) else: self.ip_allocator = ip_allocator
def test_ip_alloc(self): sid1 = "IMSI02917" ip1 = self._dhcp_allocator.alloc_ip_address(sid1) threading.Event().wait(2) gw_map = store.GatewayInfoMap() dhcp_gw_info = UplinkGatewayInfo(gw_map) dhcp_store = store.MacToIP() # mac => DHCP_State self.assertEqual(str(dhcp_gw_info.getIP()), "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()) self.assertEqual(dhcp_state1.state, DHCPState.RELEASE) 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 self._dhcp_allocator.ip_allocator.release_ip("IMSI033", ip3, ip_network("1.1.1.0/24")) 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()) self.assertEqual(dhcp_state.state, DHCPState.RELEASE) 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