Introduced option to delete deallocated ips immediately. Fixes bug

971504

New flag allows deleting IPs soon on deallocation. This removes the
need to run external script manually or via cron. Get old beaviour by
setting the falg to True.

Added test case for this beahviour.

Change-Id: Ife04dd85ed311e806b790f6d1487a963dd3a05af
This commit is contained in:
Mandar Vaze 2012-04-06 04:35:27 -07:00
parent 91d1ec0753
commit d8ff17ecb9
3 changed files with 45 additions and 12 deletions

View File

@ -44,6 +44,11 @@ api_extensions_path = melange/extensions
dns1 = 8.8.8.8
dns2 = 8.8.4.4
#Release Deallocated fixed IPs immediately
#If set to True, deallocated IPs would be deleted only when
#bin/melange-delete-deallocated-ips script is executed
keep_deallocated_ips = False
#Number of days before deallocated IPs are deleted
keep_deallocated_ips_for_days = 2

View File

@ -233,6 +233,11 @@ class IpAddressIterator(object):
raise StopIteration
def deallocated_by_date():
days = config.Config.get('keep_deallocated_ips_for_days', 2)
return utils.utcnow() - datetime.timedelta(days=int(days))
class IpBlock(ModelBase):
PUBLIC_TYPE = "public"
@ -256,7 +261,8 @@ class IpBlock(ModelBase):
def delete_all_deallocated_ips(cls):
LOG.info("Deleting all deallocated IPs")
for block in db.db_api.find_all_blocks_with_deallocated_ips():
block.delete_deallocated_ips()
block.delete_deallocated_ips(
deallocated_by_func=deallocated_by_date)
@property
def broadcast(self):
@ -414,20 +420,16 @@ class IpBlock(ModelBase):
LOG.debug("Deallocating IP: %s" % ip_address)
ip_address.deallocate()
def delete_deallocated_ips(self):
def delete_deallocated_ips(self, deallocated_by_func):
self.update(is_full=False)
for ip in db.db_api.find_deallocated_ips(
deallocated_by=self._deallocated_by_date(), ip_block_id=self.id):
deallocated_by=deallocated_by_func(), ip_block_id=self.id):
LOG.debug("Deleting deallocated IP: %s" % ip)
generator = ipv4.plugin().get_generator(self)
generator.ip_removed(ip.address)
ip.delete()
def _deallocated_by_date(self):
days = config.Config.get('keep_deallocated_ips_for_days', 2)
return utils.utcnow() - datetime.timedelta(days=int(days))
def subnet(self, cidr, network_id=None, tenant_id=None):
network_id = network_id or self.network_id
tenant_id = tenant_id or self.tenant_id
@ -1058,6 +1060,11 @@ class Network(ModelBase):
ips = IpAddress.find_all_by_network(self.id, interface_id=interface_id)
for ip in ips:
ip.deallocate()
keep_deallocated_ips = config.Config.get('keep_deallocated_ips', 'False')
if not utils.bool_from_string(keep_deallocated_ips):
LOG.debug("Deleting deallocated ips")
for block in db.db_api.find_all_blocks_with_deallocated_ips():
block.delete_deallocated_ips(deallocated_by_func=utils.utcnow)
def find_allocated_ip(self, **conditions):
for ip_block in self.ip_blocks:

View File

@ -956,13 +956,30 @@ class TestIpBlock(tests.BaseTest):
ip2.deallocate()
with unit.StubTime(time=current_time):
models.IpBlock.delete_all_deallocated_ips()
models.IpBlock.delete_all_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
self.assertEqual(models.IpAddress.find_all(
ip_block_id=ip_block1.id).all(), [])
self.assertEqual(models.IpAddress.find_all(
ip_block_id=ip_block2.id).all(), [])
def test_delete_deallocated_ips_immediately(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.1.1/24")
current_time = datetime.datetime(2050, 1, 1)
ip1 = _allocate_ip(ip_block)
ip2 = _allocate_ip(ip_block)
ip3 = _allocate_ip(ip_block)
with unit.StubTime(time=current_time):
ip1.deallocate()
ip3.deallocate()
with unit.StubTime(time=current_time):
ip_block.delete_deallocated_ips(deallocated_by_func=utils.utcnow)
existing_ips = models.IpAddress.find_all(ip_block_id=ip_block.id).all()
self.assertModelsEqual(existing_ips, [ip2])
def test_delete_deallocated_ips_after_default_of_two_days(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.1.1/24")
current_time = datetime.datetime(2050, 1, 1)
@ -975,7 +992,8 @@ class TestIpBlock(tests.BaseTest):
ip3.deallocate()
with unit.StubTime(time=current_time):
ip_block.delete_deallocated_ips()
ip_block.delete_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
existing_ips = models.IpAddress.find_all(ip_block_id=ip_block.id).all()
self.assertModelsEqual(existing_ips, [ip2])
@ -999,7 +1017,8 @@ class TestIpBlock(tests.BaseTest):
with unit.StubConfig(keep_deallocated_ips_for_days=1):
with unit.StubTime(time=current_time):
ip_block.delete_deallocated_ips()
ip_block.delete_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
self.assertEqual(ip_block.addresses(), [ip2])
@ -1014,7 +1033,8 @@ class TestIpBlock(tests.BaseTest):
interface=interface)
self.assertTrue(ip_block.is_full)
models.IpBlock.delete_all_deallocated_ips()
models.IpBlock.delete_all_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
self.assertFalse(models.IpBlock.find(ip_block.id).is_full)
@ -2461,7 +2481,8 @@ class TestAllowedIp(tests.BaseTest):
with unit.StubTime(time=two_days_before):
block.deallocate_ip(ip.address)
with unit.StubTime(time=current_time):
block.delete_deallocated_ips()
block.delete_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
reloaded_ip = models.IpAddress.find(ip.id)
self.assertFalse(reloaded_ip.marked_for_deallocation)