fixes bug 911242
mac address ranges and ip blocks for selecting ips/macs are sorted by created date and id Change-Id: Ib0bafcd9600bba70fff163da536551b2d7bf9acc
This commit is contained in:
parent
14966a13f3
commit
56b4466c39
@ -15,7 +15,7 @@ bind_port = 9898
|
||||
# registry server. Any valid SQLAlchemy connection string is fine.
|
||||
# See: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html#sqlalchemy.create_engine
|
||||
sql_connection = sqlite:///melange_test.sqlite
|
||||
#sql_connection = mysql://root:root@localhost/melange
|
||||
# sql_connection = mysql://root:root@localhost/melange
|
||||
#sql_connection = postgresql://melange:melange@localhost/melange
|
||||
|
||||
# Period in seconds after which SQLAlchemy should reestablish its connection
|
||||
|
@ -20,6 +20,7 @@
|
||||
import datetime
|
||||
import logging
|
||||
import netaddr
|
||||
import operator
|
||||
|
||||
from melange import db
|
||||
from melange import ipv6
|
||||
@ -688,7 +689,8 @@ class MacAddressRange(ModelBase):
|
||||
|
||||
@classmethod
|
||||
def allocate_next_free_mac(cls, **kwargs):
|
||||
ranges = sorted(cls.find_all(), key=lambda model: model.created_at)
|
||||
ranges = sorted(cls.find_all(),
|
||||
key=operator.attrgetter('created_at', 'id'))
|
||||
for range in ranges:
|
||||
try:
|
||||
return range.allocate_mac(**kwargs)
|
||||
@ -956,9 +958,12 @@ class Network(ModelBase):
|
||||
@classmethod
|
||||
def find_by(cls, id, **conditions):
|
||||
ip_blocks = IpBlock.find_all(network_id=id, **conditions).all()
|
||||
if len(ip_blocks) == 0:
|
||||
sorted_blocks = sorted(ip_blocks,
|
||||
key=operator.attrgetter('created_at', 'id'))
|
||||
|
||||
if len(sorted_blocks) == 0:
|
||||
raise ModelNotFoundError(_("Network %s not found") % id)
|
||||
return cls(id=id, ip_blocks=ip_blocks)
|
||||
return cls(id=id, ip_blocks=sorted_blocks)
|
||||
|
||||
@classmethod
|
||||
def find_or_create_by(cls, id, tenant_id):
|
||||
|
@ -20,6 +20,7 @@ import unittest
|
||||
import urlparse
|
||||
|
||||
from melange.db import db_api
|
||||
from melange.common import utils
|
||||
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
@ -82,3 +83,7 @@ class BaseTest(unittest.TestCase):
|
||||
def assertErrorResponse(self, response, error_type, expected_error):
|
||||
self.assertEqual(response.status_int, error_type().code)
|
||||
self.assertIn(expected_error, response.body)
|
||||
|
||||
def setup_uuid_with(self, fake_uuid):
|
||||
self.mock.StubOutWithMock(utils, "generate_uuid")
|
||||
utils.generate_uuid().MultipleTimes().AndReturn(fake_uuid)
|
||||
|
@ -1025,7 +1025,7 @@ class TestIpBlock(tests.BaseTest):
|
||||
self.assertModelsEqual(block1.ip_routes(), ip_routes)
|
||||
|
||||
def test_ip_block_creation_is_notified(self):
|
||||
_setup_uuid(self.mock, "ip_block_uuid")
|
||||
self.setup_uuid_with("ip_block_uuid")
|
||||
creation_time = datetime.datetime(2050, 1, 1)
|
||||
mock_notifier = _setup_notifier(self.mock)
|
||||
mock_notifier.info("create IpBlock", dict(tenant_id="tnt_id",
|
||||
@ -1348,7 +1348,7 @@ class TestIpAddress(tests.BaseTest):
|
||||
|
||||
def test_ip_addresss_creation_is_notified(self):
|
||||
block = factory_models.IpBlockFactory(cidr="10.1.1.1/24")
|
||||
_setup_uuid(self.mock, "ip_address_uuid")
|
||||
self.setup_uuid_with("ip_address_uuid")
|
||||
creation_time = datetime.datetime(2050, 1, 1)
|
||||
mock_notifier = _setup_notifier(self.mock)
|
||||
mock_notifier.info("create IpAddress", dict(used_by_tenant_id="tnt_id",
|
||||
@ -1486,6 +1486,7 @@ class TestMacAddressRange(tests.BaseTest):
|
||||
two_days_before = datetime.datetime.now() - datetime.timedelta(days=2)
|
||||
with unit.StubTime(time=two_days_before):
|
||||
factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:00:00/47")
|
||||
|
||||
factory_models.MacAddressRangeFactory(cidr="BC:76:4E:30:00:00/40")
|
||||
|
||||
mac1 = models.MacAddressRange.allocate_next_free_mac()
|
||||
@ -1502,6 +1503,36 @@ class TestMacAddressRange(tests.BaseTest):
|
||||
self.assertEqual(netaddr.EUI(mac4.address),
|
||||
netaddr.EUI("BC:76:4E:30:00:01"))
|
||||
|
||||
def test_allocate_next_free_mac_chooses_range_by_created_date_and_id(self):
|
||||
self.mock.StubOutWithMock(utils, "generate_uuid")
|
||||
|
||||
def setup_range(cidr, uuid):
|
||||
utils.generate_uuid().MultipleTimes().AndReturn(uuid)
|
||||
self.mock.ReplayAll()
|
||||
rng = factory_models.MacAddressRangeFactory(cidr=cidr)
|
||||
self.mock.ResetAll()
|
||||
return rng
|
||||
today = datetime.datetime.now()
|
||||
two_days_before = today - datetime.timedelta(days=2)
|
||||
with unit.StubTime(time=two_days_before):
|
||||
setup_range("BC:00:4E:20:00:00/47", 0)
|
||||
|
||||
three_days_before = today - datetime.timedelta(days=3)
|
||||
with unit.StubTime(time=three_days_before):
|
||||
rng_of_uuid_5 = setup_range("AC:76:4E:20:00:00/48", 5)
|
||||
rng_of_uuid_2 = setup_range("BC:76:4E:20:00:00/48", 2)
|
||||
rng_of_uuid_3 = setup_range("CC:76:4E:20:00:00/48", 3)
|
||||
rng_of_uuid_1 = setup_range("DC:76:4E:20:00:00/48", 1)
|
||||
rng_of_uuid_4 = setup_range("EC:76:4E:20:00:00/48", 4)
|
||||
self.mock.UnsetStubs()
|
||||
|
||||
allocate_mac = models.MacAddressRange.allocate_next_free_mac
|
||||
self.assertTrue(rng_of_uuid_1.contains(allocate_mac().address))
|
||||
self.assertTrue(rng_of_uuid_2.contains(allocate_mac().address))
|
||||
self.assertTrue(rng_of_uuid_3.contains(allocate_mac().address))
|
||||
self.assertTrue(rng_of_uuid_4.contains(allocate_mac().address))
|
||||
self.assertTrue(rng_of_uuid_5.contains(allocate_mac().address))
|
||||
|
||||
def test_allocate_next_free_mac_raises_error_when_no_more_free_macs(self):
|
||||
factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/48")
|
||||
factory_models.MacAddressRangeFactory(cidr="BC:76:4E:30:0:0/48")
|
||||
@ -1980,6 +2011,41 @@ class TestNetwork(tests.BaseTest):
|
||||
ip_address = models.IpAddress.find_by(ip_block_id=free_ip_block.id)
|
||||
self.assertEqual(allocated_ipv4, ip_address)
|
||||
|
||||
def test_picks_block_to_allocate_sorted_by_created_date_and_id(self):
|
||||
interface = factory_models.InterfaceFactory(tenant_id="tenant_id")
|
||||
self.mock.StubOutWithMock(utils, "generate_uuid")
|
||||
|
||||
def setup_block(cidr, uuid):
|
||||
utils.generate_uuid().MultipleTimes().AndReturn(uuid)
|
||||
self.mock.ReplayAll()
|
||||
block = factory_models.IpBlockFactory(cidr=cidr,
|
||||
network_id="net",
|
||||
tenant_id="tenant_id")
|
||||
self.mock.ResetAll()
|
||||
return block
|
||||
today = datetime.datetime.now()
|
||||
two_days_before = today - datetime.timedelta(days=2)
|
||||
with unit.StubTime(time=two_days_before):
|
||||
setup_block("10.1.1.1/31", 0)
|
||||
|
||||
three_days_before = today - datetime.timedelta(days=3)
|
||||
with unit.StubTime(time=three_days_before):
|
||||
block_of_uuid_5 = setup_block("20.1.1.1/31", 5)
|
||||
block_of_uuid_2 = setup_block("30.1.1.1/31", 2)
|
||||
block_of_uuid_3 = setup_block("40.1.1.1/31", 3)
|
||||
block_of_uuid_1 = setup_block("50.1.1.1/31", 1)
|
||||
block_of_uuid_4 = setup_block("60.1.1.1/31", 4)
|
||||
self.mock.UnsetStubs()
|
||||
|
||||
network = models.Network.find_by("net", tenant_id="tenant_id")
|
||||
allocate_ip = lambda interface: network.allocate_ips(
|
||||
interface=interface)[0].address
|
||||
self.assertTrue(block_of_uuid_1.contains(allocate_ip(interface)))
|
||||
self.assertTrue(block_of_uuid_2.contains(allocate_ip(interface)))
|
||||
self.assertTrue(block_of_uuid_3.contains(allocate_ip(interface)))
|
||||
self.assertTrue(block_of_uuid_4.contains(allocate_ip(interface)))
|
||||
self.assertTrue(block_of_uuid_5.contains(allocate_ip(interface)))
|
||||
|
||||
def test_allocate_ip_raises_error_when_all_ip_blocks_are_full(self):
|
||||
interface = factory_models.InterfaceFactory()
|
||||
full_ip_block = factory_models.PublicIpBlockFactory(network_id="1",
|
||||
@ -2053,7 +2119,7 @@ class TestNetwork(tests.BaseTest):
|
||||
self.assertTrue(models.IpAddress.get(ip1.id).marked_for_deallocation)
|
||||
self.assertTrue(models.IpAddress.get(ip2.id).marked_for_deallocation)
|
||||
|
||||
def test_retrives_allocated_ips(self):
|
||||
def test_retrieves_allocated_ips(self):
|
||||
ip_block1 = factory_models.IpBlockFactory(network_id="1",
|
||||
cidr="10.0.0.0/24")
|
||||
ip_block2 = factory_models.IpBlockFactory(network_id="1",
|
||||
@ -2458,8 +2524,3 @@ def _allocate_ip(block, interface=None, **kwargs):
|
||||
def _setup_notifier(mock):
|
||||
mock.StubOutClassWithMocks(notifier, "NoopNotifier")
|
||||
return notifier.NoopNotifier()
|
||||
|
||||
|
||||
def _setup_uuid(mock, uuid):
|
||||
mock.StubOutWithMock(utils, "generate_uuid")
|
||||
utils.generate_uuid().MultipleTimes().AndReturn(uuid)
|
||||
|
@ -34,7 +34,7 @@ class NotifierTestBase():
|
||||
|
||||
def _setup_expected_message(self, priority, event,
|
||||
message):
|
||||
self._setup_uuid_with("test_uuid")
|
||||
self.setup_uuid_with("test_uuid")
|
||||
return {
|
||||
'event_type': event,
|
||||
'timestamp': str(utils.utcnow()),
|
||||
@ -44,10 +44,6 @@ class NotifierTestBase():
|
||||
'publisher_id': socket.gethostname(),
|
||||
}
|
||||
|
||||
def _setup_uuid_with(self, fake_uuid):
|
||||
self.mock.StubOutWithMock(utils, "generate_uuid")
|
||||
utils.generate_uuid().AndReturn(fake_uuid)
|
||||
|
||||
|
||||
class TestLoggingNotifier(tests.BaseTest, NotifierTestBase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user