melange/melange/tests/unit/test_ipam_models.py
Mandar Vaze d8ff17ecb9 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
2012-04-09 03:49:00 -07:00

2575 lines
112 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import mox
import netaddr
from melange import tests
from melange.common import exception
from melange.common import notifier
from melange.common import utils
from melange.db import db_query
from melange.ipam import models
from melange.tests import unit
from melange.tests.factories import models as factory_models
from melange.tests.unit import mock_generator
class TestModelBase(tests.BaseTest):
def test_create_ignores_inputs_for_auto_generated_attrs(self):
model = factory_models.PublicIpBlockFactory(id="input_id",
created_at="input_time",
updated_at="input_time")
self.assertNotEqual(model.id, "input_id")
self.assertNotEqual(model.created_at, "input_time")
self.assertNotEqual(model.updated_at, "input_time")
def test_create_sets_timestamps(self):
current_time = datetime.datetime(2050, 1, 1)
with unit.StubTime(time=current_time):
model = factory_models.PublicIpBlockFactory()
self.assertEqual(model.created_at, current_time)
self.assertEqual(model.updated_at, current_time)
def test_update_ignores_inputs_for_auto_generated_attrs(self):
model = factory_models.PublicIpBlockFactory()
model.update(id="input_id", created_at="input_time",
updated_at="input_time")
self.assertNotEqual(model.id, "input_id")
self.assertNotEqual(model.created_at, "input_time")
self.assertNotEqual(model.updated_at, "input_time")
def test_update_sets_updated_at_time(self):
model = factory_models.PublicIpBlockFactory()
current_time = datetime.datetime(2050, 1, 1)
with unit.StubTime(time=current_time):
model.update(network_id="321")
updated_model = models.IpBlock.find(model.id)
self.assertEqual(updated_model.updated_at, current_time)
def test_equals_is_true_when_ids_and_class_are_equal(self):
self.assertEqual(models.ModelBase(id=1), models.ModelBase(id=1))
self.assertEqual(models.ModelBase(id=1, name="foo"),
models.ModelBase(id=1, name="bar"))
def test_equals_is_false_when_id_or_class_differ(self):
self.assertNotEqual(models.ModelBase(), models.ModelBase())
self.assertNotEqual(models.ModelBase(id=1), models.ModelBase(id=2))
self.assertNotEqual(models.IpBlock(id=1), models.IpAddress(id=1))
def test_hash_is_id_based(self):
a = models.ModelBase(id="123", name="foo")
b = models.ModelBase(id="123", name="bar")
self.assertEqual(hash(a), hash(b))
class TestQuery(tests.BaseTest):
def test_all(self):
block1 = factory_models.IpBlockFactory(network_id="1")
block2 = factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
blocks = db_query.find_all(models.IpBlock, network_id="1").all()
self.assertModelsEqual(blocks, [block1, block2])
def test_count(self):
factory_models.IpBlockFactory(network_id="1")
factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
count = db_query.find_all(models.IpBlock, network_id="1").count()
self.assertEqual(count, 2)
def test_query_is_iterble(self):
block1 = factory_models.IpBlockFactory(network_id="1")
block2 = factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
query = db_query.find_all(models.IpBlock, network_id="1")
blocks = [block for block in query]
self.assertModelsEqual(blocks, [block1, block2])
def test_limit_with_given_marker(self):
blocks = models.sort([
factory_models.IpBlockFactory(cidr="10.2.0.1/28"),
factory_models.IpBlockFactory(cidr="10.3.0.1/28"),
factory_models.IpBlockFactory(cidr="10.1.0.1/28"),
factory_models.IpBlockFactory(cidr="10.4.0.1/28"),
])
marker_block = blocks[1]
all_blocks_query = db_query.find_all(models.IpBlock)
paginated_blocks = all_blocks_query.limit(limit=2,
marker=marker_block.id)
self.assertEqual(len(paginated_blocks), 2)
self.assertEqual(paginated_blocks, [blocks[2], blocks[3]])
def test_update(self):
block1 = factory_models.IpBlockFactory(network_id="1")
block2 = factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
db_query.find_all(models.IpBlock,
network_id="1").update(network_id="2")
self.assertEqual(models.IpBlock.find(block1.id).network_id, "2")
self.assertEqual(models.IpBlock.find(block2.id).network_id, "2")
noise_network = models.IpBlock.find(noise_block.id).network_id
self.assertNotEqual(noise_network, "2")
def test_delete(self):
block1 = factory_models.IpBlockFactory(network_id="1")
block2 = factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
db_query.find_all(models.IpBlock, network_id="1").delete()
self.assertIsNone(models.IpBlock.get(block1.id))
self.assertIsNone(models.IpBlock.get(block2.id))
self.assertIsNotNone(models.IpBlock.get(noise_block.id))
class TestConverter(tests.BaseTest):
def test_converts_to_integer_value(self):
self.assertEqual(models.Converter('integer').convert("123"), 123)
self.assertEqual(models.Converter('integer').convert(123), 123)
def test_converts_to_boolean_value(self):
self.assertEqual(models.Converter('boolean').convert("True"), True)
self.assertEqual(models.Converter('boolean').convert("False"), False)
class TestIpBlock(tests.BaseTest):
def setUp(self):
self.mock_generator_name = \
"melange.tests.unit.mock_generator.MockIpV6Generator"
super(TestIpBlock, self).setUp()
def test_create_ip_block(self):
factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/8",
network_id="18888", tenant_id='xxxx')
saved_block = models.IpBlock.find_by(network_id="18888")
self.assertEqual(saved_block.cidr, "10.0.0.0/8")
self.assertEqual(saved_block.network_id, '18888')
self.assertEqual(saved_block.type, "private")
self.assertEqual(saved_block.tenant_id, "xxxx")
def test_block_details(self):
v4_block = factory_models.IpBlockFactory.build(cidr="10.0.0.0/24")
v6_block = factory_models.IpBlockFactory.build(cidr="fe::/64")
self.assertEqual(v4_block.broadcast, "10.0.0.255")
self.assertEqual(v4_block.netmask, "255.255.255.0")
self.assertEqual(v6_block.broadcast, "fe::ffff:ffff:ffff:ffff")
self.assertEqual(v6_block.netmask, "64")
def test_length_of_block(self):
block = factory_models.IpBlockFactory
self.assertEqual(block(cidr="10.0.0.0/24").size(), 256)
self.assertEqual(block(cidr="20.0.0.0/31").size(), 2)
self.assertEqual(block(cidr="30.0.0.0/32").size(), 1)
def test_valid_cidr(self):
factory = factory_models.PrivateIpBlockFactory
block = factory.build(cidr="10.1.1.1////", network_id="111")
self.assertFalse(block.is_valid())
self.assertEqual(block.errors, {'cidr': ["cidr is invalid"]})
self.assertRaises(models.InvalidModelError, block.save)
self.assertRaises(models.InvalidModelError, models.IpBlock.create,
cidr="10.1.0.0/33", network_id="111")
block.cidr = "10.1.1.1/8"
self.assertTrue(block.is_valid())
def test_presence_of_tenant_id(self):
factory = factory_models.PrivateIpBlockFactory
block = factory.build(cidr="10.1.1.1/8", tenant_id=None)
self.assertFalse(block.is_valid())
self.assertEqual(block.errors,
{'tenant_id': ["tenant_id should be present"]})
def test_validates_overlapping_cidr_for_public_ip_blocks(self):
factory = factory_models.PublicIpBlockFactory
factory(cidr="10.0.0.0/8", network_id="145")
overlapping_block = factory.build(cidr="10.0.0.0/30", network_id="11")
self.assertFalse(overlapping_block.is_valid())
self.assertEqual(overlapping_block.errors,
{'cidr':
["cidr overlaps with public block 10.0.0.0/8"]})
def test_type_for_block_should_be_either_public_or_private(self):
block = factory_models.IpBlockFactory.build(type=None,
cidr="10.0.0.0/29")
self.assertFalse(block.is_valid())
self.assertEqual(block.errors, {'type':
["type should be one among public, private"]})
def test_different_types_of_blocks_cannot_be_created_within_network(self):
factory = factory_models.IpBlockFactory
factory(network_id="1", type='private')
block_of_different_type = factory.build(network_id="1", type='public')
self.assertFalse(block_of_different_type.is_valid())
self.assertEqual(block_of_different_type.errors,
{'type': ['type should be same within a network']})
def test_different_types_of_blocks_can_be_created_when_no_network(self):
private_block = factory_models.PrivateIpBlockFactory(network_id=None)
public_block = factory_models.PublicIpBlockFactory.build(
network_id=None)
self.assertTrue(public_block.is_valid())
def test_save_validates_cidr_belongs_to_parent_block_cidr(self):
factory = factory_models.PrivateIpBlockFactory
parent_block = factory(cidr="10.0.0.0/28")
ip_block = factory.build(cidr="10.0.0.20/29",
parent_id=parent_block.id)
self.assertFalse(ip_block.is_valid())
self.assertEqual(ip_block.errors['cidr'],
["cidr should be within parent block's cidr"])
def test_does_not_perform_subnetting_validations_for_invalid__cidr(self):
factory = factory_models.PrivateIpBlockFactory
parent_block = factory(cidr="10.0.0.0/28")
ip_block = factory.build(cidr="10.0.0.20////29",
parent_id=parent_block.id)
self.assertFalse(ip_block.is_valid())
self.assertEqual(ip_block.errors['cidr'],
["cidr is invalid"])
def test_validates_subnet_has_same_network_as_parent(self):
factory = factory_models.PrivateIpBlockFactory
parent = factory(cidr="10.0.0.0/28", network_id="1")
subnet = factory.build(cidr="10.0.0.0/29",
network_id="2",
parent_id=parent.id)
self.assertFalse(subnet.is_valid())
self.assertEqual(subnet.errors['network_id'],
["network_id should be same as that of parent"])
def test_subnet_fails_when_parent_block_has_allocated_ips(self):
parent = factory_models.IpBlockFactory(cidr="10.0.0.0/24")
_allocate_ip(parent)
expected_msg = "parent is not subnettable since it has allocated ips"
self.assertRaisesExcMessage(models.InvalidModelError, expected_msg,
parent.subnet, cidr="10.0.0.0/30")
def test_subnets_cidr_can_not_overlap_with_siblings(self):
parent = factory_models.IpBlockFactory(cidr="10.0.0.0/29")
parent.subnet(cidr="10.0.0.0/30")
parent.subnet(cidr="10.0.0.4/30")
factory = factory_models.IpBlockFactory
overlapping_subnet = factory.build(cidr="10.0.0.0/31",
tenant_id="2",
parent_id=parent.id)
self.assertFalse(overlapping_subnet.is_valid())
self.assertEqual(overlapping_subnet.errors['cidr'],
["cidr overlaps with sibling 10.0.0.0/30"])
def test_cidr_can_not_overlap_with_top_level_blocks_in_the_network(self):
factory = factory_models.IpBlockFactory
factory(cidr="10.0.0.0/29", network_id="1")
factory(cidr="20.0.0.0/29", network_id="1")
overlapping_block = factory.build(cidr="10.0.0.0/31", network_id="1")
self.assertFalse(overlapping_block.is_valid())
self.assertEqual(overlapping_block.errors['cidr'],
["cidr overlaps with block 10.0.0.0/29 in same network"])
def test_cidr_can_overlap_for_blocks_in_different_network(self):
block1 = factory_models.IpBlockFactory(cidr="10.0.0.0/29",
network_id="1")
block2 = factory_models.IpBlockFactory.build(cidr="10.0.0.0/29",
network_id="2")
self.assertTrue(block2.is_valid())
def test_cidr_can_overlap_for_blocks_without_network(self):
block1 = factory_models.IpBlockFactory(cidr="10.0.0.0/29",
network_id=None)
block2 = factory_models.IpBlockFactory.build(cidr="10.0.0.0/29",
network_id=None)
self.assertTrue(block2.is_valid())
def test_networked_top_level_blocks_have_blocks_of_different_parents(self):
block1 = factory_models.IpBlockFactory(cidr="10.0.0.0/29",
network_id=None,
parent_id=None)
subnet1 = block1.subnet(cidr="10.0.0.0/30", network_id="1")
block2 = factory_models.IpBlockFactory(cidr="20.0.0.0/29",
network_id="1")
block3 = factory_models.IpBlockFactory(cidr="30.0.0.0/29",
network_id="1")
self.assertModelsEqual(block3.networked_top_level_blocks(),
[subnet1, block2])
def test_networked_top_level_blocks_has_only_top_level_blocks(self):
block1 = factory_models.IpBlockFactory(cidr="10.0.0.0/29",
network_id="1")
subnet1 = block1.subnet(cidr="10.0.0.0/30", network_id="1")
block2 = factory_models.IpBlockFactory(cidr="20.0.0.0/29",
network_id="1")
block3 = factory_models.IpBlockFactory(cidr="30.0.0.0/29",
network_id="1")
self.assertModelsEqual(block3.networked_top_level_blocks(),
[block1, block2])
def test_has_no_networked_top_level_blocks_when_not_in_network(self):
block1 = factory_models.IpBlockFactory(cidr="10.0.0.0/29",
network_id=None)
noise = factory_models.IpBlockFactory(cidr="20.0.0.0/29",
network_id=None)
self.assertModelsEqual(block1.networked_top_level_blocks(), [])
def test_subnet_creates_child_block_with_the_given_params(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/28",
network_id="1",
tenant_id="2")
subnet = ip_block.subnet("10.0.0.0/29",
network_id="1",
tenant_id="3")
self.assertEqual(subnet.cidr, "10.0.0.0/29")
self.assertEqual(subnet.network_id, "1")
self.assertEqual(subnet.parent_id, ip_block.id)
self.assertEqual(subnet.tenant_id, "3")
self.assertEqual(subnet.type, ip_block.type)
def test_subnet_derives_network_id_from_parent_block_when_not_given(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/28",
network_id="2")
subnet = ip_block.subnet("10.0.0.0/29")
self.assertEqual(subnet.cidr, "10.0.0.0/29")
self.assertEqual(subnet.network_id, ip_block.network_id)
def test_subnet_derives_tenant_id_from_parent_block_when_not_given(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/28",
tenant_id="2")
subnet = ip_block.subnet("10.0.0.0/29")
self.assertEqual(subnet.cidr, "10.0.0.0/29")
self.assertEqual(subnet.tenant_id, ip_block.tenant_id)
def test_save_validates_existence_parent_block_of_same_type(self):
noise_block = factory_models.IpBlockFactory(type='public')
block = factory_models.IpBlockFactory.build(parent_id=noise_block.id,
type='private')
self.assertFalse(block.is_valid())
self.assertEqual(block.errors['parent_id'],
["IpBlock with type = 'private', id = '{0}' doesn't "
"exist".format(block.parent_id)])
def test_save_validates_existence_policy(self):
block = factory_models.PublicIpBlockFactory.build(
policy_id="non-existent-id")
self.assertFalse(block.is_valid())
self.assertEqual(block.errors['policy_id'],
["Policy with id = 'non-existent-id' doesn't exist"])
def test_validates_gateway_is_valid_address(self):
block = factory_models.IpBlockFactory.build(gateway="not_valid")
self.assertFalse(block.is_valid())
self.assertEqual(block.errors['gateway'],
["Gateway is not a valid address"])
def test_save_converts_cidr_to_lowest_address_based_on_prefix_length(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/31")
self.assertEqual(block.cidr, "10.0.0.0/31")
def test_gateway_ip_is_not_auto_set_if_ip_block_has_only_one_ip(self):
ipv4_block = factory_models.IpBlockFactory(cidr="10.0.0.0/32",
gateway=None)
self.assertEqual(ipv4_block.gateway, None)
ipv6_block = factory_models.IpBlockFactory(cidr="ff::ff/128",
gateway=None)
self.assertEqual(ipv6_block.gateway, None)
def test_save_sets_the_dns_values_from_conf_when_not_provided(self):
with unit.StubConfig(dns1="ns1.example.com", dns2="ns2.example.com"):
block = factory_models.IpBlockFactory(cidr="10.0.0.0/24",
dns1=None,
dns2=None)
self.assertEqual(block.dns1, "ns1.example.com")
self.assertEqual(block.dns2, "ns2.example.com")
def test_update(self):
block = factory_models.PublicIpBlockFactory(cidr="10.0.0.0/29",
network_id="321")
block.update(network_id="123")
self.assertEqual(block.network_id, "123")
def test_find_ip_block(self):
block1 = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
factory_models.PrivateIpBlockFactory(cidr="30.1.1.1/8")
found_block = models.IpBlock.find(block1.id)
self.assertEqual(found_block.cidr, block1.cidr)
def test_find_ip_block_for_nonexistent_block(self):
self.assertRaises(models.ModelNotFoundError,
models.IpBlock.find,
"123")
def test_find_ip(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
ip = _allocate_ip(block)
self.assertEqual(block.find_ip(address=ip.address).id, ip.id)
def test_find_ip_for_nonexistent_address(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
self.assertRaisesExcMessage(models.ModelNotFoundError,
"IpAddress Not Found",
block.find_ip,
address="10.0.0.1")
def test_policy(self):
policy = factory_models.PolicyFactory(name="Some Policy")
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
policy_id=policy.id)
self.assertEqual(ip_block.policy(), policy)
def test_parent(self):
parent = factory_models.IpBlockFactory()
self.assertEqual(models.IpBlock(parent_id=parent.id).parent, parent)
self.assertEqual(models.IpBlock(parent_id=None).parent, None)
self.assertEqual(models.IpBlock(parent_id='non-existent').parent, None)
def test_allocate_ip(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/31")
interface = factory_models.InterfaceFactory()
ip = block.allocate_ip(interface)
saved_ip = models.IpAddress.find(ip.id)
self.assertEqual(ip.address, saved_ip.address)
self.assertTrue(netaddr.IPAddress(ip.address)
in netaddr.IPNetwork("10.0.0.0/31"))
self.assertEqual(ip.interface_id, interface.id)
self.assertEqual(ip.ip_block_id, block.id)
self.assertEqual(ip.used_by_tenant_id, interface.tenant_id)
def test_allocate_specific_address(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/24")
interface = factory_models.InterfaceFactory(tenant_id="tnt_id")
ip = block.allocate_ip(interface, address="10.0.0.2")
expected_ip = models.IpAddress.find(ip.id)
self.assertEqual(expected_ip.address, "10.0.0.2")
self.assertEqual(ip.interface_id, interface.id)
self.assertEqual(ip.ip_block_id, block.id)
self.assertEqual(ip.used_by_tenant_id, "tnt_id")
def skip_allocate_ip_from_non_leaf_block_fails(self):
parent_block = factory_models.IpBlockFactory(cidr="10.0.0.0/28")
interface = factory_models.InterfaceFactory()
parent_block.subnet(cidr="10.0.0.0/28")
expected_msg = "Subnetted block cannot allocate IPAddress"
self.assertRaisesExcMessage(models.IpAllocationNotAllowedError,
expected_msg,
parent_block.allocate_ip,
interface=interface)
def skip_allocate_ip_from_outside_cidr(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.1.1.1/28")
interface = factory_models.InterfaceFactory()
self.assertRaises(models.AddressDoesNotBelongError,
block.allocate_ip,
interface=interface,
address="192.1.1.1")
def test_allocating_duplicate_address_fails(self):
interface = factory_models.InterfaceFactory()
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29")
block.allocate_ip(address='10.0.0.0', interface=interface)
self.assertRaises(models.DuplicateAddressError,
block.allocate_ip,
interface=interface,
address="10.0.0.0")
def test_allocate_ips_skips_gateway_address(self):
interface = factory_models.InterfaceFactory()
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
gateway="10.0.0.0")
ip_address = block.allocate_ip(interface=interface)
self.assertEqual(ip_address.address, "10.0.0.1")
def test_allocate_ips_skips_broadcast_address(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
interface = factory_models.InterfaceFactory()
#allocate all ips except last ip(broadcast)
for i in range(0, 3):
block.allocate_ip(interface=interface)
self.assertRaises(exception.NoMoreAddressesError,
block.allocate_ip,
interface=interface)
def test_allocating_gateway_address_fails(self):
interface = factory_models.InterfaceFactory()
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
gateway="10.0.0.0")
self.assertRaises(models.DuplicateAddressError,
block.allocate_ip,
interface=interface,
address=block.gateway)
def test_allocating_broadcast_address_fails(self):
interface = factory_models.InterfaceFactory()
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/24")
self.assertRaises(models.DuplicateAddressError,
block.allocate_ip,
interface=interface,
address=block.broadcast)
def test_allocate_ip_skips_ips_disallowed_by_policy(self):
policy = factory_models.PolicyFactory(name="blah")
interface = factory_models.InterfaceFactory()
factory_models.IpRangeFactory(policy_id=policy.id,
offset=1,
length=1)
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
policy_id=policy.id)
self.assertEqual(block.allocate_ip(interface).address, "10.0.0.0")
self.assertEqual(block.allocate_ip(interface).address, "10.0.0.2")
def test_allocating_ip_fails_due_to_policy(self):
policy = factory_models.PolicyFactory(name="blah")
interface = factory_models.InterfaceFactory()
factory_models.IpRangeFactory(policy_id=policy.id,
offset=0,
length=1)
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
policy_id=policy.id)
self.assertRaises(models.AddressDisallowedByPolicyError,
block.allocate_ip,
interface=interface,
address="10.0.0.0")
def test_ip_block_is_marked_full_when_all_ips_are_allocated(self):
interface = factory_models.InterfaceFactory()
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
for i in range(0, 3):
ip_block.allocate_ip(interface=interface)
self.assertRaises(exception.NoMoreAddressesError,
ip_block.allocate_ip,
interface=interface)
self.assertTrue(ip_block.is_full)
def test_allocate_ip_raises_error_when_ip_block_is_marked_full(self):
interface = factory_models.InterfaceFactory()
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
is_full=True)
self.assertRaises(exception.NoMoreAddressesError,
ip_block.allocate_ip,
interface=interface)
def test_allocate_ip_fails_when_iface_configured_for_other_net_ip(self):
iface_with_net1 = factory_models.InterfaceFactory()
net1_block = factory_models.IpBlockFactory(network_id="1")
net1_ip = net1_block.allocate_ip(iface_with_net1)
net2_block = factory_models.IpBlockFactory(network_id="2")
expected_error_msg = ("Interface %s is configured on another network"
% iface_with_net1.vif_id_on_device)
self.assertRaisesExcMessage(models.IpAllocationNotAllowedError,
expected_error_msg,
net2_block.allocate_ip,
iface_with_net1)
def test_allocate_ip_retries_on_ip_creation_constraint_failure(self):
interface = factory_models.InterfaceFactory()
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/24")
no_of_retries = 3
self.mock.StubOutWithMock(models.IpAddress, 'create')
for i in range(no_of_retries - 1):
self._mock_ip_creation().AndRaise(exception.DBConstraintError())
expected_ip = models.IpAddress(id=1, address="10.0.0.2")
self._mock_ip_creation().AndReturn(expected_ip)
self.mock.ReplayAll()
with unit.StubConfig(ip_allocation_retries=no_of_retries):
actual_ip = ip_block.allocate_ip(interface)
self.assertEqual(actual_ip, expected_ip)
def test_allocate_ip_raises_error_after_max_retries(self):
interface = factory_models.InterfaceFactory()
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/24")
no_of_retries = 3
self.mock.StubOutWithMock(models.IpAddress, 'create')
for i in range(no_of_retries):
self._mock_ip_creation().AndRaise(exception.DBConstraintError())
self.mock.ReplayAll()
expected_error_msg = ("Cannot allocate address for block {0} "
"at this time".format(ip_block.id))
expected_exception = models.ConcurrentAllocationError
with unit.StubConfig(ip_allocation_retries=no_of_retries):
self.assertRaisesExcMessage(expected_exception,
expected_error_msg,
ip_block.allocate_ip,
interface=interface)
def _mock_ip_creation(self):
return models.IpAddress.create(address=mox.IgnoreArg(),
interface_id=mox.IgnoreArg(),
used_by_tenant_id=mox.IgnoreArg(),
ip_block_id=mox.IgnoreArg())
def test_ip_block_is_not_full(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/28")
self.assertFalse(ip_block.is_full)
def test_allocate_ip_when_no_more_ips_raises_no_more_addresses_error(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
interface = factory_models.InterfaceFactory()
for i in range(0, 3):
block.allocate_ip(interface=interface)
self.assertRaises(exception.NoMoreAddressesError,
block.allocate_ip,
interface=interface)
def test_allocate_ip_is_not_duplicated(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
interface = factory_models.InterfaceFactory()
self.assertEqual(block.allocate_ip(interface).address, "10.0.0.0")
self.assertEqual(block.allocate_ip(interface).address, "10.0.0.1")
def test_allocate_ip_for_ipv6_block_uses_pluggable_algo(self):
block = factory_models.IpV6IpBlockFactory(cidr="ff::/120")
interface = factory_models.InterfaceFactory()
mock_generator.MockIpV6Generator.ip_list = ["ff::0001", "ff::0002"]
with unit.StubConfig(ipv6_generator=self.mock_generator_name):
ip = block.allocate_ip(interface=interface)
self.assertEqual(ip.address, "00ff:0000:0000:0000:0000:0000:0000:0001")
def test_allocate_ip_for_ipv6_block_iterates_till_free_ip_is_found(self):
block = factory_models.IpV6IpBlockFactory(cidr="ff::/120")
interface = factory_models.InterfaceFactory()
mock_generator.MockIpV6Generator.ip_list = ["ff::0001", "ff::0002"]
factory_models.IpAddressFactory(address="ff::0001",
ip_block_id=block.id)
with unit.StubConfig(ipv6_generator=self.mock_generator_name):
ip = block.allocate_ip(interface=interface)
self.assertEqual(ip.address, "00ff:0000:0000:0000:0000:0000:0000:0002")
def test_allocate_ip_for_given_ipv6_address(self):
block = factory_models.IpV6IpBlockFactory(cidr="ff::/120")
interface = factory_models.InterfaceFactory()
ip = block.allocate_ip(interface=interface, address="ff::2")
self.assertEqual(ip.address, "00ff:0000:0000:0000:0000:0000:0000:0002")
def test_allocate_ip_fails_if_given_ipv6_address_already_exists(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpV6IpBlockFactory(cidr="ff::/120")
factory_models.IpAddressFactory(address="ff::2",
ip_block_id=block.id)
self.assertRaises(models.DuplicateAddressError,
block.allocate_ip,
interface=interface,
address="ff::2")
def test_allocate_ip_fails_if_given_ipv6_address_outside_block_cidr(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpV6IpBlockFactory(cidr="ff::/120")
self.assertRaises(models.AddressDoesNotBelongError,
block.allocate_ip,
interface=interface,
address="fe::2")
def test_find_allocated_ip(self):
block = factory_models.PrivateIpBlockFactory()
actual_ip = _allocate_ip(block)
expected_ip = models.IpBlock.find_allocated_ip(
block.id, block.tenant_id, address=actual_ip.address)
self.assertEqual(expected_ip, actual_ip)
def test_find_allocated_ip_raises_locked_error_for_deallocated_ips(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
ip = _allocate_ip(block)
ip.deallocate()
self.assertRaises(models.AddressLockedError,
models.IpBlock.find_allocated_ip,
block.id,
block.tenant_id,
address=ip.address)
def test_find_allocated_ip_when_ip_block_not_belongs_to_tenant(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
ip = _allocate_ip(block)
self.assertRaises(models.ModelNotFoundError,
models.IpBlock.find_allocated_ip,
block.id,
"wrong_tenant_id",
address=ip.address)
def test_deallocate_ip(self):
interface = factory_models.InterfaceFactory()
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/24")
ip = _allocate_ip(block)
block.deallocate_ip(ip.address)
self.assertRaises(models.AddressLockedError,
models.IpBlock.find_allocated_ip,
block.id,
block.tenant_id,
address=ip.address)
self.assertRaises(models.DuplicateAddressError,
block.allocate_ip,
address=ip.address,
interface=interface)
def test_data_with_gateway(self):
policy = factory_models.PolicyFactory()
parent_block = factory_models.PrivateIpBlockFactory(
cidr="10.0.0.0/24")
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
policy_id=policy.id,
parent_id=parent_block.id,
gateway="10.0.0.1")
data = ip_block.data()
self.assertEqual(data['id'], ip_block.id)
self.assertEqual(data['cidr'], ip_block.cidr)
self.assertEqual(data['network_id'], ip_block.network_id)
self.assertEqual(data['tenant_id'], ip_block.tenant_id)
self.assertEqual(data['policy_id'], ip_block.policy_id)
self.assertEqual(data['parent_id'], ip_block.parent_id)
self.assertEqual(data['created_at'], ip_block.created_at)
self.assertEqual(data['updated_at'], ip_block.updated_at)
self.assertEqual(data['broadcast'], "10.0.0.7")
self.assertEqual(data['gateway'], "10.0.0.1")
self.assertEqual(data['netmask'], "255.255.255.248")
self.assertEqual(data['dns1'], ip_block.dns1)
self.assertEqual(data['dns2'], ip_block.dns2)
def test_data_without_gateway(self):
policy = factory_models.PolicyFactory()
parent_block = factory_models.PrivateIpBlockFactory(
cidr="10.0.0.0/24")
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
policy_id=policy.id,
parent_id=parent_block.id)
data = ip_block.data()
self.assertEqual(data['id'], ip_block.id)
self.assertEqual(data['cidr'], ip_block.cidr)
self.assertEqual(data['network_id'], ip_block.network_id)
self.assertEqual(data['tenant_id'], ip_block.tenant_id)
self.assertEqual(data['policy_id'], ip_block.policy_id)
self.assertEqual(data['parent_id'], ip_block.parent_id)
self.assertEqual(data['created_at'], ip_block.created_at)
self.assertEqual(data['updated_at'], ip_block.updated_at)
self.assertEqual(data['broadcast'], "10.0.0.7")
self.assertEqual(data['gateway'], None)
self.assertEqual(data['netmask'], "255.255.255.248")
self.assertEqual(data['dns1'], ip_block.dns1)
self.assertEqual(data['dns2'], ip_block.dns2)
def test_find_all_ip_blocks(self):
factory_models.PrivateIpBlockFactory(cidr="10.2.0.0/28")
factory_models.PrivateIpBlockFactory(cidr="10.3.0.0/28")
factory_models.PrivateIpBlockFactory(cidr="10.1.0.0/28")
blocks = models.IpBlock.find_all().all()
self.assertEqual(len(blocks), 3)
self.assertItemsEqual(["10.2.0.0/28", "10.3.0.0/28", "10.1.0.0/28"],
[block.cidr for block in blocks])
def test_delete(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29")
ip_block.delete()
self.assertTrue(models.IpBlock.get(ip_block.id) is None)
def test_delete_to_cascade_delete_ip_addresses(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29")
factory_models.IpAddressFactory(ip_block_id=ip_block.id,
address="10.0.0.0")
factory_models.IpAddressFactory(ip_block_id=ip_block.id,
address="10.0.0.1")
ip_block.delete()
ips = models.IpAddress.find_all(ip_block_id=ip_block.id).all()
self.assertTrue(len(ips) is 0)
def test_delete_to_cascade_delete_subnet_tree_and_their_address(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29")
subnet1 = ip_block.subnet("10.0.0.0/30")
subnet11 = subnet1.subnet("10.0.0.1/31")
subnet2 = ip_block.subnet("10.0.0.4/30")
ip1 = factory_models.IpAddressFactory(ip_block_id=subnet11.id,
address="10.0.0.0")
ip2 = factory_models.IpAddressFactory(ip_block_id=subnet2.id,
address="10.0.0.4")
ip_block.delete()
self.assertIsNone(models.IpBlock.get(subnet1.id))
self.assertIsNone(models.IpBlock.get(subnet11.id))
self.assertIsNone(models.IpBlock.get(subnet2.id))
self.assertIsNone(models.IpAddress.get(ip1.id))
self.assertIsNone(models.IpAddress.get(ip2.id))
def test_contains_address(self):
ip_block = models.IpBlock(cidr="10.0.0.0/20")
self.assertTrue(ip_block.contains("10.0.0.232"))
self.assertFalse(ip_block.contains("20.0.0.232"))
def test_is_ipv6(self):
ip_block = models.IpBlock(cidr="ff::/120")
self.assertTrue(ip_block.is_ipv6())
def test_subnets(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/28")
subnet1 = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/29",
parent_id=ip_block.id)
subnet2 = factory_models.PrivateIpBlockFactory(cidr="10.0.0.8/29",
parent_id=ip_block.id)
self.assertModelsEqual(ip_block.subnets(), [subnet1, subnet2])
def test_siblings_of_non_root_node(self):
ip_block = factory_models.IpBlockFactory(cidr="10.0.0.0/28")
subnet1 = ip_block.subnet("10.0.0.0/29")
subnet2 = ip_block.subnet("10.0.0.8/30")
subnet3 = ip_block.subnet("10.0.0.12/30")
subnet11 = subnet1.subnet("10.0.0.0/30")
self.assertModelsEqual(subnet2.siblings(), [subnet1, subnet3])
self.assertModelsEqual(subnet11.siblings(), [])
def test_siblings_of_root_node_is_empty(self):
ip_block = factory_models.IpBlockFactory(cidr="10.0.0.0/28")
self.assertModelsEqual(ip_block.siblings(), [])
def test_delete_all_deallocated_ips_after_default_of_two_days(self):
ip_block1 = factory_models.PrivateIpBlockFactory(cidr="10.0.1.1/24")
ip_block2 = factory_models.PrivateIpBlockFactory(cidr="20.0.1.1/24")
current_time = datetime.datetime(2050, 1, 1)
two_days_before = current_time - datetime.timedelta(days=2)
ip1 = _allocate_ip(ip_block1)
ip2 = _allocate_ip(ip_block2)
with unit.StubTime(time=two_days_before):
ip1.deallocate()
ip2.deallocate()
with unit.StubTime(time=current_time):
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)
two_days_before = current_time - datetime.timedelta(days=2)
ip1 = _allocate_ip(ip_block)
ip2 = _allocate_ip(ip_block)
ip3 = _allocate_ip(ip_block)
with unit.StubTime(time=two_days_before):
ip1.deallocate()
ip3.deallocate()
with unit.StubTime(time=current_time):
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])
def test_delete_deallocated_ips_after_configured_no_of_days(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.1.1/24")
ip1 = _allocate_ip(ip_block)
ip2 = _allocate_ip(ip_block)
ip3 = _allocate_ip(ip_block)
ip4 = _allocate_ip(ip_block)
current_time = datetime.datetime(2050, 1, 1)
one_day_before = current_time - datetime.timedelta(days=1)
two_days_before = current_time - datetime.timedelta(days=2)
with unit.StubTime(time=two_days_before):
ip1.deallocate()
ip3.deallocate()
with unit.StubTime(time=one_day_before):
ip4.deallocate()
with unit.StubTime(time=current_time):
ip2.deallocate()
with unit.StubConfig(keep_deallocated_ips_for_days=1):
with unit.StubTime(time=current_time):
ip_block.delete_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
self.assertEqual(ip_block.addresses(), [ip2])
def test_is_full_flag_reset_when_addresses_are_deleted(self):
interface = factory_models.InterfaceFactory()
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.0/30")
for i in range(0, 3):
ip = _allocate_ip(ip_block, interface=interface)
ip.deallocate()
self.assertRaises(exception.NoMoreAddressesError,
ip_block.allocate_ip,
interface=interface)
self.assertTrue(ip_block.is_full)
models.IpBlock.delete_all_deallocated_ips(
deallocated_by_func=models.deallocated_by_date)
self.assertFalse(models.IpBlock.find(ip_block.id).is_full)
def test_ip_routes(self):
block1 = factory_models.IpBlockFactory()
block2 = factory_models.IpBlockFactory()
ip_routes = [factory_models.IpRouteFactory(source_block_id=block1.id),
factory_models.IpRouteFactory(source_block_id=block1.id)]
noise = factory_models.IpRouteFactory(source_block_id=block2.id)
self.assertModelsEqual(block1.ip_routes(), ip_routes)
def test_ip_block_creation_is_notified(self):
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",
id="ip_block_uuid",
type="private",
created_at=creation_time))
self.mock.ReplayAll()
with unit.StubTime(time=creation_time):
factory_models.IpBlockFactory(tenant_id="tnt_id",
type="private",)
def test_ip_block_deletion_is_notified(self):
block = factory_models.IpBlockFactory(tenant_id="tnt_id",
type="private")
mock_notifier = _setup_notifier(self.mock)
mock_notifier.info("delete IpBlock", dict(tenant_id="tnt_id",
type=block.type,
id=block.id,
created_at=block.created_at))
self.mock.ReplayAll()
block.delete()
def test_no_ips_allocated(self):
empty_block = factory_models.IpBlockFactory()
block = factory_models.IpBlockFactory()
block.allocate_ip(factory_models.InterfaceFactory())
self.assertTrue(empty_block.no_ips_allocated())
self.assertFalse(block.no_ips_allocated())
class TestIpAddress(tests.BaseTest):
def test_str_returns_address(self):
self.assertEqual(str(models.IpAddress(address="10.0.1.1")), "10.0.1.1")
def test_address_for_a_ip_block_is_unique(self):
block1 = factory_models.PrivateIpBlockFactory(cidr="10.1.1.1/24")
block2 = factory_models.PrivateIpBlockFactory(cidr="20.1.1.1/24")
block1_ip = factory_models.IpAddressFactory(address="10.1.1.3",
ip_block_id=block1.id)
interface = factory_models.InterfaceFactory()
expected_error = ("Failed to save IpAddress")
self.assertRaisesExcMessage(exception.DBConstraintError,
expected_error,
models.IpAddress.create,
ip_block_id=block1.id,
address=block1_ip.address,
used_by_tenant_id="tnt_id",
interface_id=interface.id)
self.assertIsNotNone(models.IpAddress.create(ip_block_id=block2.id,
address=block1_ip.address,
used_by_tenant_id="tnt_id",
interface_id=interface.id))
def test_find_ip_address(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
ip_address = factory_models.IpAddressFactory(ip_block_id=block.id,
address="10.0.0.1")
self.assertNotEqual(models.IpAddress.find(ip_address.id), None)
def test_find_ips_in_network(self):
ip_block1 = factory_models.IpBlockFactory(network_id="1")
ip_block2 = factory_models.IpBlockFactory(network_id="1")
noise_block = factory_models.IpBlockFactory(network_id="999")
noise_ip = _allocate_ip(noise_block)
ips = [_allocate_ip(block) for block in [ip_block1, ip_block2]]
self.assertModelsEqual(models.IpAddress.find_all_by_network("1"), ips)
def test_ipv6_address_is_expanded_before_save(self):
ip_address = factory_models.IpAddressFactory(address="fe:0:1::2")
self.assertEqual(ip_address.address,
"00fe:0000:0001:0000:0000:0000:0000:0002")
def test_ipv4_address_is_formatted_before_save(self):
ip_address = factory_models.IpAddressFactory(address="10.11.003.255")
self.assertEqual(ip_address.address, "10.11.3.255")
def test_find_ip_address_for_nonexistent_address(self):
self.assertRaises(models.ModelNotFoundError,
models.IpAddress.find,
"123")
def test_find_all_allocated_ips(self):
block1 = factory_models.IpBlockFactory(tenant_id="1")
block2 = factory_models.IpBlockFactory(tenant_id="1")
interface1 = factory_models.InterfaceFactory()
interface2 = factory_models.InterfaceFactory()
ip1 = _allocate_ip(block1, interface=interface1)
ip2 = _allocate_ip(block1, interface=interface1)
ip3 = _allocate_ip(block1, interface=interface1)
block2_ip = _allocate_ip(block2, interface=interface1)
other_interface_ip = _allocate_ip(block1, interface=interface2)
ip2.deallocate()
allocated_ips = models.IpAddress.find_all_allocated_ips(
interface_id=interface1.id)
self.assertModelsEqual(allocated_ips, [ip1, ip3, block2_ip])
def test_delete_ip_address(self):
block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
ip = factory_models.IpAddressFactory(ip_block_id=block.id,
address="10.0.0.1")
ip.delete()
self.assertIsNone(models.IpAddress.get(ip.id))
def test_add_inside_locals(self):
global_ip = factory_models.IpAddressFactory()
local_ip = factory_models.IpAddressFactory()
global_ip.add_inside_locals([local_ip])
self.assertTrue(global_ip.id in [ip.id for ip
in local_ip.inside_globals()])
def test_add_inside_globals(self):
global_ip = factory_models.IpAddressFactory()
local_ip = factory_models.IpAddressFactory()
local_ip.add_inside_globals([global_ip])
self.assertTrue(local_ip.id in [ip.id for ip in
global_ip.inside_locals()])
def test_limited_show_inside_locals(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
global_ip = _allocate_ip(global_block)
local_ips = models.sort([_allocate_ip(local_block) for i in range(5)])
global_ip.add_inside_locals(local_ips)
inside_locals_query = global_ip.inside_locals()
expected_locals, next_mrk = inside_locals_query.paginated_collection(
limit=2, marker=local_ips[1].id)
self.assertModelsEqual(expected_locals, [local_ips[2], local_ips[3]])
def test_limited_show_inside_globals(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
global_ips = models.sort([_allocate_ip(global_block)
for i in range(5)])
local_ip = _allocate_ip(local_block)
local_ip.add_inside_globals(global_ips)
inside_globals_query = local_ip.inside_globals()
inside_globals, next_mrk = inside_globals_query.paginated_collection(
limit=2, marker=global_ips[1].id)
self.assertModelsEqual(inside_globals, [global_ips[2], global_ips[3]])
self.assertEqual(next_mrk, global_ips[3].id)
def test_remove_inside_globals(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
global_ips = [_allocate_ip(global_block) for i in range(5)]
local_ip = _allocate_ip(local_block)
local_ip.add_inside_globals(global_ips)
local_ip.remove_inside_globals()
self.assertEqual(local_ip.inside_globals().all(), [])
def test_remove_inside_globals_for_specific_address(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
global_ips = [_allocate_ip(global_block) for i in range(5)]
local_ip = _allocate_ip(local_block)
local_ip.add_inside_globals(global_ips)
local_ip.remove_inside_globals(global_ips[0].address)
globals_left = [ip.address for ip in local_ip.inside_globals()]
self.assertItemsEqual(globals_left,
[ip.address for ip in global_ips[1:5]])
def test_remove_inside_locals_for_specific_address(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
global_ip = _allocate_ip(global_block)
local_ips = [_allocate_ip(local_block) for i in range(5)]
global_ip.add_inside_locals(local_ips)
global_ip.remove_inside_locals(local_ips[0].address)
locals_left = [ip.address for ip in global_ip.inside_locals()]
self.assertItemsEqual(locals_left,
[ip.address for ip in local_ips[1:5]])
def test_remove_inside_locals(self):
global_block = factory_models.PrivateIpBlockFactory(cidr="192.0.0.1/8")
local_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
local_ips = [_allocate_ip(local_block) for i in range(5)]
global_ip = _allocate_ip(global_block)
global_ip.add_inside_locals(local_ips)
global_ip.remove_inside_locals()
self.assertEqual(global_ip.inside_locals().all(), [])
def test_data(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
interface = factory_models.InterfaceFactory()
ip = factory_models.IpAddressFactory(ip_block_id=ip_block.id,
interface_id=interface.id)
data = ip.data()
self.assertEqual(data['id'], ip.id)
self.assertEqual(data['ip_block_id'], ip.ip_block_id)
self.assertEqual(data['address'], ip.address)
self.assertEqual(data['version'], ip.version)
self.assertEqual(data['used_by_tenant'], interface.tenant_id)
self.assertEqual(data['used_by_device'], interface.device_id)
self.assertEqual(data['interface_id'], interface.vif_id_on_device)
self.assertEqual(data['created_at'], ip.created_at)
self.assertEqual(data['updated_at'], ip.updated_at)
def test_deallocate(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/8")
ip_address = _allocate_ip(ip_block)
current_time = datetime.datetime(2050, 1, 1)
with unit.StubTime(time=current_time):
ip_address.deallocate()
self.assertNotEqual(models.IpAddress.find(ip_address.id), None)
deallocated_address = models.IpAddress.find(ip_address.id)
self.assertTrue(deallocated_address.marked_for_deallocation)
self.assertTrue(deallocated_address.deallocated_at, current_time)
def test_restore(self):
ip_block = factory_models.PrivateIpBlockFactory(cidr="10.0.0.1/24")
ip_address = _allocate_ip(ip_block)
ip_address.deallocate()
ip_address.restore()
self.assertFalse(ip_address.marked_for_deallocation)
self.assertIsNone(ip_address.deallocated_at)
def test_ip_block(self):
ip_block = factory_models.PrivateIpBlockFactory()
ip_address = factory_models.IpAddressFactory(ip_block_id=ip_block.id)
self.assertEqual(ip_address.ip_block, ip_block)
def test_find_by_takes_care_of_expanding_ipv6_addresses(self):
actual_ip = factory_models.IpAddressFactory(address="00fe:0:0001::2")
noise_ip = factory_models.IpAddressFactory(address="fe00:0:0001::2")
found_ip = models.IpAddress.find_by(address="fe:0:1::2")
self.assertEqual(actual_ip, found_ip)
def test_find_all_takes_care_of_expanding_ipv6_addresses(self):
actual_ip = factory_models.IpAddressFactory(address="00fe:0:0001::2")
noise_ip = factory_models.IpAddressFactory(address="fe00:0:0001::2")
found_ips = models.IpAddress.find_all(address="fe:0:1::2").all()
self.assertEqual([actual_ip], found_ips)
def test_version_of_ip(self):
ipv4 = factory_models.IpAddressFactory(address="10.1.1.1")
ipv6 = factory_models.IpAddressFactory(address="fe::1")
self.assertEqual(ipv4.version, 4)
self.assertEqual(ipv6.version, 6)
def test_retrieves_interface(self):
interface = factory_models.InterfaceFactory(vif_id_on_device="112")
ip = factory_models.IpAddressFactory(interface_id=interface.id)
self.assertEqual(ip.interface, interface)
self.assertEqual(ip.interface.virtual_interface_id, "112")
def test_vif_id_on_device(self):
interface = factory_models.InterfaceFactory(vif_id_on_device="112")
ip = factory_models.IpAddressFactory(interface_id=interface.id)
self.assertEqual(ip.virtual_interface_id, "112")
def test_mac_address(self):
mac_range = factory_models.MacAddressRangeFactory()
interface = factory_models.InterfaceFactory()
mac_address = mac_range.allocate_mac(interface_id=interface.id)
ip = factory_models.IpAddressFactory(interface_id=interface.id)
self.assertEqual(ip.mac_address, mac_address)
def test_validates_existance_of_inteface(self):
ip = factory_models.IpAddressFactory.build(interface_id="bad_id")
self.assertFalse(ip.is_valid())
self.assertEqual(ip.errors['interface_id'],
["Interface with id = 'bad_id' doesn't exist"])
def test_validates_presence_of_used_by_tenant(self):
ip = factory_models.IpAddressFactory.build(used_by_tenant_id=None)
self.assertFalse(ip.is_valid())
self.assertEqual(ip.errors['used_by_tenant_id'],
["used_by_tenant_id should be present"])
def test_ip_addresss_creation_is_notified(self):
block = factory_models.IpBlockFactory(cidr="10.1.1.1/24")
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",
id="ip_address_uuid",
address="10.1.1.1",
used_by_device_id="ins",
ip_block_id=block.id,
created_at=creation_time))
self.mock.ReplayAll()
with unit.StubTime(time=creation_time):
interface = factory_models.InterfaceFactory(device_id="ins")
factory_models.IpAddressFactory(used_by_tenant_id="tnt_id",
address="10.1.1.1",
ip_block_id=block.id,
interface_id=interface.id)
def test_ip_addresss_creation_is_notified(self):
block = factory_models.IpBlockFactory(cidr="10.1.1.1/24")
interface = factory_models.InterfaceFactory(device_id="ins")
ip = factory_models.IpAddressFactory(used_by_tenant_id="tnt_id",
address="10.1.1.1",
ip_block_id=block.id,
interface_id=interface.id,
)
mock_notifier = _setup_notifier(self.mock)
mock_notifier.info("delete IpAddress", dict(used_by_tenant_id="tnt_id",
id=ip.id,
address=ip.address,
used_by_device_id="ins",
ip_block_id=block.id,
created_at=ip.created_at))
self.mock.ReplayAll()
ip.delete()
class TestIpRoute(tests.BaseTest):
def test_create(self):
block = factory_models.IpBlockFactory()
models.IpRoute.create(source_block_id=block.id,
destination="10.0.0.0",
netmask="255.255.192.0",
gateway="192.168.0.1")
created_route = models.IpRoute.find_by(source_block_id=block.id)
self.assertIsNotNone(created_route)
self.assertEqual(created_route.destination, "10.0.0.0")
self.assertEqual(created_route.netmask, "255.255.192.0")
self.assertEqual(created_route.gateway, "192.168.0.1")
def test_presence_of_destination(self):
ip_route = factory_models.IpRouteFactory.build(destination=None)
self.assertFalse(ip_route.is_valid())
self.assertEqual(ip_route.errors['destination'],
["destination should be present"])
def test_presence_of_gateway(self):
ip_route = factory_models.IpRouteFactory.build(gateway=None)
self.assertFalse(ip_route.is_valid())
self.assertEqual(ip_route.errors['gateway'],
["gateway should be present"])
def test_existence_of_source_block(self):
factory = factory_models.IpRouteFactory
ip_route = factory.build(source_block_id="invalid")
self.assertFalse(ip_route.is_valid())
self.assertEqual(ip_route.errors['source_block_id'],
["IpBlock with id = 'invalid' doesn't exist"])
def test_data(self):
ip_route = factory_models.IpRouteFactory()
data = ip_route.data()
self.assertEqual(data["destination"], ip_route.destination)
self.assertEqual(data["netmask"], ip_route.netmask)
self.assertEqual(data["gateway"], ip_route.gateway)
class TestMacAddressRange(tests.BaseTest):
def test_allocate_mac_address(self):
mac_address_range = factory_models.MacAddressRangeFactory(
cidr="BC:76:4E:20:00:00/27")
mac_address = mac_address_range.allocate_mac()
self.assertEqual(netaddr.EUI(mac_address.address),
netaddr.EUI("BC:76:4E:20:00:00"))
saved_mac = models.MacAddress.get(mac_address.id)
self.assertIsNotNone(saved_mac)
self.assertEqual(saved_mac.mac_address_range_id,
mac_address_range.id)
self.assertEqual(saved_mac.address,
int(netaddr.EUI("BC:76:4E:20:00:00")))
def test_allocate_multiple_addresses(self):
mac_address_range = factory_models.MacAddressRangeFactory(
cidr="BC:76:4E:00:00:00/24")
mac_address1 = mac_address_range.allocate_mac()
mac_address2 = mac_address_range.allocate_mac()
self.assertEqual(netaddr.EUI(mac_address1.address),
netaddr.EUI("BC:76:4E:00:00:00"))
self.assertEqual(netaddr.EUI(mac_address2.address),
netaddr.EUI("BC:76:4E:00:00:01"))
def test_allocate_mac_address_raises_no_more_addresses_error_if_full(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/48")
rng.allocate_mac()
self.assertRaises(models.NoMoreMacAddressesError, rng.allocate_mac)
def test_allocate_next_free_mac_from_first_free_range(self):
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()
mac2 = models.MacAddressRange.allocate_next_free_mac()
mac3 = models.MacAddressRange.allocate_next_free_mac()
mac4 = models.MacAddressRange.allocate_next_free_mac()
self.assertEqual(netaddr.EUI(mac1.address),
netaddr.EUI("BC:76:4E:20:00:00"))
self.assertEqual(netaddr.EUI(mac2.address),
netaddr.EUI("BC:76:4E:20:00:01"))
self.assertEqual(netaddr.EUI(mac3.address),
netaddr.EUI("BC:76:4E:30:00:00"))
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")
models.MacAddressRange.allocate_next_free_mac()
models.MacAddressRange.allocate_next_free_mac()
self.assertRaises(models.NoMoreMacAddressesError,
models.MacAddressRange.allocate_next_free_mac)
def test_allocate_next_free_mac_goes_to_next_range_on_nomoreaddrserr(self):
already_full_rng = factory_models.MacAddressRangeFactory(
cidr="BC:76:4E:20:0:0/48")
allocatable_rng = factory_models.MacAddressRangeFactory(
cidr="BC:76:4E:30:0:0/48")
self.mock.StubOutWithMock(models.MacAddressRange, "find_all")
models.MacAddressRange.find_all().AndReturn([already_full_rng,
allocatable_rng])
self.mock.StubOutWithMock(already_full_rng, "allocate_mac")
already_full_rng.allocate_mac().AndRaise(
models.NoMoreMacAddressesError())
self.mock.StubOutWithMock(allocatable_rng, "allocate_mac")
expected_mac = models.MacAddress()
allocatable_rng.allocate_mac().AndReturn(expected_mac)
self.mock.ReplayAll()
actual_mac = models.MacAddressRange.allocate_next_free_mac()
self.assertEqual(expected_mac, actual_mac)
def test_allocate_mac_retries_on_mac_creation_constraint_failure(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/24")
no_of_retries = 3
self.mock.StubOutWithMock(models.MacAddress, 'create')
for i in range(no_of_retries - 1):
self._mock_mac_creation().AndRaise(exception.DBConstraintError())
expected_mac = models.MacAddress(id=1, address=int(
netaddr.EUI("BC:76:4E:20:0:0")))
self._mock_mac_creation().AndReturn(expected_mac)
self.mock.ReplayAll()
with unit.StubConfig(mac_allocation_retries=no_of_retries):
actual_mac = rng.allocate_mac()
self.assertEqual(actual_mac, expected_mac)
def test_allocate_mac_raises_error_after_max_retries(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/24")
no_of_retries = 3
self.mock.StubOutWithMock(models.MacAddress, 'create')
for i in range(no_of_retries):
self._mock_mac_creation().AndRaise(exception.DBConstraintError())
self.mock.ReplayAll()
expected_error_msg = ("Cannot allocate mac address at this time")
expected_exception = models.ConcurrentAllocationError
with unit.StubConfig(mac_allocation_retries=no_of_retries):
self.assertRaisesExcMessage(expected_exception,
expected_error_msg,
rng.allocate_mac)
def test_allocate_mac_raises_nomoreaddrs_if_retries_exceed_capacity(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/47")
no_of_retries = 10
self.mock.StubOutWithMock(models.MacAddress, 'create')
for i in range(rng.length()):
self._mock_mac_creation().AndRaise(exception.DBConstraintError())
self.mock.ReplayAll()
with unit.StubConfig(mac_allocation_retries=no_of_retries):
self.assertRaises(models.NoMoreMacAddressesError,
rng.allocate_mac)
def test_mac_allocation_enabled_when_ranges_exist(self):
factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/48")
self.assertTrue(models.MacAddressRange.mac_allocation_enabled())
def test_mac_allocation_disabled_when_no_ranges_exist(self):
self.assertFalse(models.MacAddressRange.mac_allocation_enabled())
def test_deallocated_macs_are_allocated_again(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/40")
mac = rng.allocate_mac()
mac.delete()
self.assertEqual(rng.allocate_mac().address, mac.address)
def test_contains_mac_address(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/40")
self.assertTrue(rng.contains("BC:76:4E:20:00:00"))
self.assertTrue(rng.contains("BC:76:4E:20:00:FF"))
self.assertFalse(rng.contains("BC:76:4E:20:01:00"))
self.assertFalse(rng.contains("AA:BB:CC:20:00:00"))
def test_data(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/40")
expected_data = {
'cidr': "BC:76:4E:20:0:0/40",
'id': rng.id,
'created_at': rng.created_at,
'updated_at': rng.updated_at,
}
self.assertEqual(expected_data, rng.data())
def _mock_mac_creation(self):
return models.MacAddress.create(address=mox.IgnoreArg(),
mac_address_range_id=mox.IgnoreArg())
class TestMacAddress(tests.BaseTest):
def test_mac_address_in_eui_format(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/40")
mac = rng.allocate_mac()
self.assertIsNotNone(mac)
self.assertEqual(mac.eui_format, "BC-76-4E-20-00-00")
def test_mac_address_is_saved_in_int_format(self):
mac = models.MacAddress.create(address="BC-76-4E-20-00-00")
self.assertEqual(mac.address, int(netaddr.EUI("BC-76-4E-20-00-00")))
mac = mac.update(address="BC-76-4E-20-00-01")
self.assertEqual(mac.address, int(netaddr.EUI("BC-76-4E-20-00-01")))
mac = mac.update(address=int(netaddr.EUI("BC-76-4E-20-00-02")))
self.assertEqual(mac.address, int(netaddr.EUI("BC-76-4E-20-00-02")))
def test_mac_address_is_within_range(self):
rng = factory_models.MacAddressRangeFactory(cidr="BC:76:4E:20:0:0/40")
mac = models.MacAddress(address="AA:AA:AA:20:0:0",
mac_address_range_id=rng.id)
self.assertFalse(mac.is_valid())
self.assertEqual(mac.errors['address'],
["address does not belong to range"])
class TestPolicy(tests.BaseTest):
def test_create_policy(self):
factory_models.PolicyFactory(name="new policy", tenant_id="123",
description="desc")
policy = models.Policy.find_by(name="new policy")
self.assertEqual(policy.name, "new policy")
self.assertEqual(policy.description, "desc")
self.assertEqual(policy.tenant_id, "123")
def test_validates_presence_of_name(self):
policy = factory_models.PolicyFactory.build(name="")
self.assertFalse(policy.is_valid())
self.assertEqual(policy.errors['name'], ["name should be present"])
def test_allows_address_not_in_last_ip_octets(self):
policy = factory_models.PolicyFactory(name="blah")
ip_octet1 = factory_models.IpOctetFactory(octet=123,
policy_id=policy.id)
ip_octet2 = factory_models.IpOctetFactory(octet=124,
policy_id=policy.id)
self.assertFalse(policy.allows("10.0.0.0/29", "10.0.0.123"))
self.assertTrue(policy.allows("10.0.0.0/29", "10.0.0.1"))
self.assertFalse(policy.allows("10.0.0.0/29", "10.0.0.124"))
self.assertTrue(policy.allows("10.0.0.0/29", "10.124.123.6"))
def test_allows_addresses_not_in_ip_range(self):
policy = factory_models.PolicyFactory(name="blah")
factory_models.IpRangeFactory(offset=0,
length=2,
policy_id=policy.id)
factory_models.IpRangeFactory(offset=3,
length=2,
policy_id=policy.id)
self.assertFalse(policy.allows("10.0.0.0/29", "10.0.0.1"))
self.assertTrue(policy.allows("10.0.0.0/29", "10.0.0.2"))
self.assertFalse(policy.allows("10.0.0.0/29", "10.0.0.4"))
self.assertTrue(policy.allows("10.0.0.0/29", "10.0.0.6"))
def test_unusable_ip_ranges_for_policy(self):
policy = factory_models.PolicyFactory(name="blah")
ip_range1 = factory_models.IpRangeFactory(offset=0,
length=2,
policy_id=policy.id)
ip_range2 = factory_models.IpRangeFactory(offset=3,
length=2,
policy_id=policy.id)
self.assertModelsEqual(policy.unusable_ip_ranges,
[ip_range1, ip_range2])
def test_unusable_ip_ranges_are_cached(self):
self.assertTrue(isinstance(models.Policy.unusable_ip_ranges,
utils.cached_property))
def test_unusable_ip_octets_for_policy(self):
policy = factory_models.PolicyFactory(name="blah")
ip_octet1 = factory_models.IpOctetFactory(octet=123,
policy_id=policy.id)
ip_octet2 = factory_models.IpOctetFactory(octet=124,
policy_id=policy.id)
self.assertModelsEqual(policy.unusable_ip_octets,
[ip_octet1, ip_octet2])
def test_unusable_ip_octets_are_cached(self):
self.assertTrue(isinstance(models.Policy.unusable_ip_octets,
utils.cached_property))
def test_data(self):
policy = factory_models.PolicyFactory()
data = policy.data()
self.assertEqual(data['id'], policy.id)
self.assertEqual(data['name'], policy.name)
self.assertEqual(data['description'], policy.description)
self.assertEqual(data['tenant_id'], policy.tenant_id)
self.assertEqual(data['created_at'], policy.created_at)
self.assertEqual(data['updated_at'], policy.updated_at)
def test_find_all_to_return_all_policies(self):
policy1 = factory_models.PolicyFactory(name="physically unstable")
policy2 = factory_models.PolicyFactory(name="host")
policies = models.Policy.find_all().all()
self.assertModelsEqual(policies, [policy1, policy2])
def test_find_ip_range(self):
policy = factory_models.PolicyFactory(name='infra')
ip_range = policy.create_unusable_range(offset=10, length=1)
noise_ip_range = factory_models.IpRangeFactory(offset=1, length=22)
self.assertEqual(policy.find_ip_range(ip_range.id), ip_range)
def test_find_ip_octet(self):
policy = factory_models.PolicyFactory()
ip_octet = factory_models.IpOctetFactory(octet=10,
policy_id=policy.id)
noise_ip_octet = factory_models.IpOctetFactory()
self.assertEqual(policy.find_ip_octet(ip_octet.id), ip_octet)
def test_find_invalid_ip_range(self):
policy = factory_models.PolicyFactory(name='infra')
noise_ip_range = policy.create_unusable_range(offset=10, length=1)
self.assertRaises(models.ModelNotFoundError,
policy.find_ip_range,
ip_range_id="122222")
def test_create_unusable_ip_range(self):
policy = factory_models.PolicyFactory(name="BLAH")
ip_range = policy.create_unusable_range(offset=1, length=2)
self.assertEqual(ip_range,
models.IpRange.find_by(policy_id=policy.id))
self.assertEqual(ip_range.offset, 1)
self.assertEqual(ip_range.length, 2)
def test_delete_to_cascade_delete_ip_ranges(self):
policy = factory_models.PolicyFactory(name="Blah")
ip_range1 = factory_models.IpRangeFactory(offset=1, length=2,
policy_id=policy.id)
ip_range2 = factory_models.IpRangeFactory(offset=4, length=2,
policy_id=policy.id)
noise_ip_range = factory_models.IpRangeFactory()
ranges = models.IpRange.find_all(policy_id=policy.id).all()
self.assertModelsEqual(ranges, [ip_range1, ip_range2])
policy.delete()
ranges_after_policy_deletion = models.IpRange.find_all(
policy_id=policy.id).all()
self.assertTrue(len(ranges_after_policy_deletion) is 0)
self.assertTrue(models.IpRange.find(noise_ip_range.id) is not None)
def test_delete_to_cascade_delete_ip_octets(self):
policy = factory_models.PolicyFactory(name="Blah")
ip_octet1 = factory_models.IpOctetFactory(octet=2,
policy_id=policy.id)
ip_octet2 = factory_models.IpOctetFactory(octet=255,
policy_id=policy.id)
noise_ip_octet = factory_models.IpOctetFactory()
octets = models.IpOctet.find_all(policy_id=policy.id).all()
self.assertModelsEqual(octets, [ip_octet1, ip_octet2])
policy.delete()
octets_after_policy_deletion = models.IpOctet.find_all(
policy_id=policy.id).all()
self.assertTrue(len(octets_after_policy_deletion) is 0)
self.assertTrue(models.IpOctet.find(noise_ip_octet.id) is not None)
def test_delete_to_update_associated_ip_blocks_policy(self):
policy = factory_models.PolicyFactory(name="Blah")
ip_block = factory_models.PrivateIpBlockFactory(policy_id=policy.id)
noise_ip_block = factory_models.PrivateIpBlockFactory(
policy_id=factory_models.PolicyFactory().id)
policy.delete()
self.assertTrue(models.IpBlock.find(ip_block.id).policy_id is None)
self.assertTrue(models.IpBlock.find(noise_ip_block.id).policy_id
is not None)
class TestIpRange(tests.BaseTest):
def test_create_ip_range(self):
policy = factory_models.PolicyFactory(name='blah')
factory_models.IpRangeFactory(offset=3, length=10,
policy_id=policy.id)
ip_range = policy.unusable_ip_ranges[0]
self.assertEqual(ip_range.offset, 3)
self.assertEqual(ip_range.length, 10)
def test_before_save_converts_offset_and_length_to_integer(self):
ip_range = factory_models.IpRangeFactory(offset="10", length="11")
self.assertEqual(ip_range.offset, 10)
self.assertEqual(ip_range.length, 11)
def test_data(self):
policy = factory_models.PolicyFactory()
ip_range = factory_models.IpRangeFactory(offset=10, length=3,
policy_id=policy.id)
data = ip_range.data()
self.assertEqual(data['id'], ip_range.id)
self.assertEqual(data['offset'], 10)
self.assertEqual(data['length'], 3)
self.assertEqual(data['policy_id'], policy.id)
self.assertEqual(data['created_at'], ip_range.created_at)
self.assertEqual(data['updated_at'], ip_range.updated_at)
def test_ip_range_offset_is_an_integer(self):
ip_range = models.IpRange(offset='spdoe', length=10)
self.assertFalse(ip_range.is_valid())
self.assertIn('offset should be of type integer',
ip_range.errors['offset'])
def test_ip_range_length_is_an_integer(self):
ip_range = models.IpRange(offset='23', length='blah')
self.assertFalse(ip_range.is_valid())
self.assertTrue('length should be a positive integer' in
ip_range.errors['length'])
def test_ip_range_length_is_a_natural_number(self):
ip_range = models.IpRange(offset=11, length='-1')
self.assertFalse(ip_range.is_valid())
self.assertTrue('length should be a positive integer' in
ip_range.errors['length'])
def test_range_contains_address(self):
ip_range = factory_models.IpRangeFactory(offset=0, length=1)
self.assertTrue(ip_range.contains("10.0.0.0/29", "10.0.0.0"))
self.assertFalse(ip_range.contains("10.0.0.0/29", "10.0.0.1"))
def test_range_contains_for_reverse_offset(self):
ip_range1 = factory_models.IpRangeFactory(offset=-3, length=2)
ip_range2 = factory_models.IpRangeFactory(offset=-3, length=3)
self.assertTrue(ip_range1.contains("10.0.0.0/29", "10.0.0.5"))
self.assertFalse(ip_range1.contains("10.0.0.0/29", "10.0.0.7"))
self.assertTrue(ip_range2.contains("10.0.0.0/29", "10.0.0.7"))
class TestIpOctet(tests.BaseTest):
def test_before_save_converts_octet_to_integer(self):
ip_octet = factory_models.IpOctetFactory(octet="123")
self.assertEqual(ip_octet.octet, 123)
def test_data(self):
policy = factory_models.PolicyFactory()
ip_octet = factory_models.IpOctetFactory(policy_id=policy.id,
octet=123)
data = ip_octet.data()
self.assertEqual(data['id'], ip_octet.id)
self.assertEqual(data['octet'], 123)
self.assertEqual(data['policy_id'], policy.id)
self.assertEqual(data['created_at'], ip_octet.created_at)
self.assertEqual(data['updated_at'], ip_octet.updated_at)
def test_applies_to_is_true_if_address_last_octet_matches(self):
ip_octet = factory_models.IpOctetFactory(octet=123)
self.assertTrue(ip_octet.applies_to("10.0.0.123"))
self.assertTrue(ip_octet.applies_to("192.168.0.123"))
self.assertFalse(ip_octet.applies_to("123.0.0.124"))
class TestNetwork(tests.BaseTest):
def test_find_when_ip_blocks_for_given_network_exist(self):
ip_block1 = factory_models.PublicIpBlockFactory(network_id="1",
tenant_id="123")
noise_ip_block1 = factory_models.PublicIpBlockFactory(network_id="1",
tenant_id="321")
network = models.Network.find_by(id="1", tenant_id="123")
self.assertEqual(network.id, "1")
self.assertEqual(network.ip_blocks, [ip_block1])
def test_find_when_no_ip_blocks_for_given_network_exist(self):
noise_ip_block = factory_models.PublicIpBlockFactory(network_id="9999")
self.assertRaises(models.ModelNotFoundError,
models.Network.find_by,
id="1")
def test_find_or_create_when_no_ip_blocks_for_given_network_exist(self):
noise_ip_block = factory_models.PublicIpBlockFactory(network_id="9999")
with unit.StubConfig(default_cidr="10.10.10.0/24"):
network = models.Network.find_or_create_by(id='1', tenant_id='123')
self.assertEqual(network.id, '1')
self.assertEqual(len(network.ip_blocks), 1)
self.assertEqual(network.ip_blocks[0].cidr, "10.10.10.0/24")
self.assertEqual(network.ip_blocks[0].tenant_id, '123')
self.assertEqual(network.ip_blocks[0].network_id, '1')
self.assertEqual(network.ip_blocks[0].type, 'private')
def test_find_or_create_raises_err_if_no_default_cidr_and_net_blocks(self):
noise_ip_block = factory_models.PublicIpBlockFactory(network_id="9999",
tenant_id="tnt")
with unit.StubConfig(default_cidr=None):
self.assertRaisesExcMessage(models.ModelNotFoundError,
"Network 100 not found",
models.Network.find_or_create_by,
id="100",
tenant_id="tnt")
def test_allocate_ip_to_allocate_both_ipv4_and_ipv6_addresses(self):
ipv4_block = factory_models.PublicIpBlockFactory(network_id="1",
cidr="10.0.0.0/24",
tenant_id="111")
ipv6_block = factory_models.PublicIpBlockFactory(network_id="1",
cidr="ff::00/120",
tenant_id="111")
network = models.Network.find_by(id="1", tenant_id="111")
interface = factory_models.InterfaceFactory()
models.MacAddress.create(interface_id=interface.id,
address="aa:bb:cc:dd:ee:ff")
allocated_ips = network.allocate_ips(interface=interface)
allocated_ip_blocks_ids = [ip.ip_block_id for ip in allocated_ips]
self.assertEqual(len(allocated_ips), 2)
self.assertItemsEqual(allocated_ip_blocks_ids,
[ipv4_block.id, ipv6_block.id])
def test_allocate_ip_from_first_free_ip_block(self):
interface = factory_models.InterfaceFactory()
full_ip_block = factory_models.PublicIpBlockFactory(network_id="1",
is_full=True)
free_ip_block = factory_models.PublicIpBlockFactory(network_id="1",
is_full=False)
network = models.Network(ip_blocks=[full_ip_block, free_ip_block])
[allocated_ipv4] = network.allocate_ips(interface=interface)
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",
is_full=True,
tenant_id="111")
network = models.Network.find_by(id="1", tenant_id="111")
self.assertRaises(exception.NoMoreAddressesError,
network.allocate_ips,
interface=interface)
def test_allocate_ip_assigns_given_interface_and_addresses(self):
factory_models.PublicIpBlockFactory(network_id="1", cidr="10.0.0.0/24")
block = factory_models.PublicIpBlockFactory(network_id="1",
cidr="169.0.0.0/24")
addresses = ["10.0.0.7", "169.0.0.2", "10.0.0.3"]
network = models.Network.find_by(id="1", tenant_id=block.tenant_id)
interface = factory_models.InterfaceFactory()
allocated_ips = network.allocate_ips(interface=interface,
addresses=addresses)
self.assertItemsEqual([ip.address for ip in allocated_ips], addresses)
for ip in allocated_ips:
self.assertEqual(ip.interface_id, interface.id)
def test_allocate_ip_assigns_given_address_from_its_block(self):
interface = factory_models.InterfaceFactory()
ip_block1 = factory_models.PublicIpBlockFactory(network_id="1",
cidr="10.0.0.0/24")
ip_block2 = factory_models.PublicIpBlockFactory(network_id="1",
cidr="20.0.0.0/24")
network = models.Network(ip_blocks=[ip_block1, ip_block2])
allocated_ip = network.allocate_ips(addresses=["20.0.0.4"],
interface=interface)[0]
self.assertEqual(allocated_ip.address, "20.0.0.4")
self.assertEqual(allocated_ip.ip_block_id, ip_block2.id)
def test_allocate_ip_ignores_already_allocated_addresses(self):
interface = factory_models.InterfaceFactory()
ip_block1 = factory_models.PublicIpBlockFactory(network_id="1",
cidr="10.0.0.0/24")
ip_block2 = factory_models.PublicIpBlockFactory(network_id="1",
cidr="20.0.0.0/24")
factory_models.IpAddressFactory(ip_block_id=ip_block1.id,
address="10.0.0.0")
network = models.Network(ip_blocks=[ip_block1, ip_block2])
allocted_ips = network.allocate_ips(addresses=["10.0.0.0", "20.0.0.0"],
interface=interface)
self.assertTrue(len(allocted_ips) is 1)
self.assertEqual(allocted_ips[0].address, "20.0.0.0")
def test_deallocate_ips(self):
ip_block1 = factory_models.IpBlockFactory(network_id="1",
cidr="10.0.0.0/24")
ip_block2 = factory_models.IpBlockFactory(network_id="1",
cidr="fe80::/64")
network = models.Network(id="1", ip_blocks=[ip_block1, ip_block2])
interface = factory_models.InterfaceFactory()
ip1 = factory_models.IpAddressFactory(ip_block_id=ip_block1.id,
interface_id=interface.id)
ip2 = factory_models.IpAddressFactory(ip_block_id=ip_block2.id,
interface_id=interface.id)
network.deallocate_ips(interface_id=interface.id)
self.assertTrue(models.IpAddress.get(ip1.id).marked_for_deallocation)
self.assertTrue(models.IpAddress.get(ip2.id).marked_for_deallocation)
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",
cidr="20.0.0.0/24")
interface1 = factory_models.InterfaceFactory()
interface2 = factory_models.InterfaceFactory()
ip1 = _allocate_ip(ip_block1, interface=interface1)
ip2 = _allocate_ip(ip_block1, interface=interface1)
ip3 = _allocate_ip(ip_block2, interface=interface2)
ip4 = _allocate_ip(ip_block2, interface=interface1)
network = models.Network.find_by(id="1")
allocated_ips = network.allocated_ips(interface_id=interface1.id)
self.assertModelsEqual(allocated_ips, [ip1, ip2, ip4])
def test_find_allocated_ip(self):
ip_block1 = factory_models.IpBlockFactory(network_id="1",
cidr="10.0.0.0/24")
ip_block2 = factory_models.IpBlockFactory(network_id="1",
cidr="20.0.0.0/24")
noise_block = factory_models.IpBlockFactory(network_id="1",
cidr="30.0.0.0/24")
ip1 = _allocate_ip(ip_block1)
ip2 = _allocate_ip(ip_block2)
network = models.Network.find_by(id="1")
self.assertEqual(network.find_allocated_ip(address=ip1.address), ip1)
self.assertEqual(network.find_allocated_ip(address=ip2.address), ip2)
def test_find_allocated_ip_raises_model_not_found_for_invalid_ip(self):
ip_block = factory_models.IpBlockFactory(network_id="1",
cidr="10.0.0.0/24")
network = models.Network.find_by(id="1")
self.assertRaisesExcMessage(models.ModelNotFoundError,
("IpAddress with {'address': '10.1.1.1'} "
"for network %s not found" % network.id),
network.find_allocated_ip,
address="10.1.1.1")
class TestInterface(tests.BaseTest):
def test_find_or_configure_finds_existing_interface(self):
existing_interface = factory_models.InterfaceFactory(
vif_id_on_device="11234",
device_id="huge_instance",
tenant_id="tnt")
interface_found = models.Interface.find_or_configure(
virtual_interface_id="11234",
device_id="huge_instance",
tenant_id="tnt")
self.assertEqual(existing_interface, interface_found)
def test_find_or_configure_finds_without_device_id(self):
existing_interface = factory_models.InterfaceFactory(
vif_id_on_device="11234",
device_id="huge_instance",
tenant_id="tnt")
interface_found = models.Interface.find_or_configure(
virtual_interface_id="11234",
tenant_id="tnt")
self.assertEqual(existing_interface, interface_found)
def test_find_or_configure_fails_if_vif_exists_for_another_tenant(self):
existing_interface = factory_models.InterfaceFactory(
vif_id_on_device="vif", device_id="device", tenant_id="tnt1")
self.assertRaises(models.InvalidModelError,
models.Interface.find_or_configure,
virtual_interface_id="vif",
tenant_id="tnt2",
device_id="device")
def test_find_or_configure_creates_interface_when_not_found(self):
interface = models.Interface.find_or_configure(
virtual_interface_id="new_interface",
device_id="huge_instance",
tenant_id="tenant")
created_interface = models.Interface.find_by(id=interface.id)
self.assertEqual(interface, created_interface)
self.assertEqual(created_interface.vif_id_on_device,
"new_interface")
self.assertEqual(created_interface.device_id, "huge_instance")
self.assertEqual(created_interface.tenant_id, "tenant")
def test_find_or_configure_allocates_mac_address_for_new_interface(self):
mac_range = factory_models.MacAddressRangeFactory()
interface = models.Interface.find_or_configure(
virtual_interface_id="new_interface",
tenant_id="tenant")
mac = models.MacAddress.find_by(mac_address_range_id=mac_range.id)
self.assertEqual(mac.interface_id, interface.id)
def test_find_or_configure_allocates_mac_for_given_mac_address(self):
interface = models.Interface.find_or_configure(
virtual_interface_id="new_interface",
tenant_id="tenant",
mac_address="ab:bc:cd:01:12:23")
mac = models.MacAddress.find_by(interface_id=interface.id)
self.assertEqual(mac.eui_format,
str(netaddr.EUI("ab:bc:cd:01:12:23")))
self.assertEqual(mac.address, int(netaddr.EUI("ab:bc:cd:01:12:23")))
def test_find_or_configure_cant_allocate_mac_if_allocation_disabled(self):
self.assertFalse(models.MacAddressRange.mac_allocation_enabled())
interface = models.Interface.find_or_configure(
virtual_interface_id="new_interface",
tenant_id="tenant")
self.assertIsNone(models.MacAddress.get_by(interface_id=interface.id))
def test_validate_virtual_interface_id_is_unique(self):
factory_models.InterfaceFactory(vif_id_on_device="iface_id")
dup_iface = factory_models.InterfaceFactory.build(
vif_id_on_device="iface_id")
self.assertFalse(dup_iface.is_valid())
self.assertEqual(dup_iface.errors['virtual_interface_id'],
["Virtual Interface iface_id already exists"])
def test_validate_presence_of_tenant_id(self):
interface = factory_models.InterfaceFactory.build(
tenant_id=None)
self.assertFalse(interface.is_valid())
self.assertEqual(interface.errors['tenant_id'],
["tenant_id should be present"])
def test_update(self):
interface = factory_models.InterfaceFactory(device_id="device_id")
interface.update(device_id="new_device_id")
self.assertEqual(interface.device_id, "new_device_id")
def test_delete_removes_mac_address(self):
interface = factory_models.InterfaceFactory()
mac_range = factory_models.MacAddressRangeFactory()
mac = mac_range.allocate_mac(interface_id=interface.id)
interface.delete()
self.assertIsNone(models.Interface.get(interface.id))
self.assertIsNone(models.MacAddress.get(mac.id))
def test_delete_deallocates_ips_on_interface(self):
interface = factory_models.InterfaceFactory()
ip1 = factory_models.IpAddressFactory(interface_id=interface.id)
ip2 = factory_models.IpAddressFactory(interface_id=interface.id)
interface.delete()
self.assertIsNone(models.Interface.get(interface.id))
self.assertTrue(models.IpAddress.get(ip1.id).locked())
self.assertTrue(models.IpAddress.get(ip2.id).locked())
self.assertIsNone(models.IpAddress.get(ip1.id).interface_id)
self.assertIsNone(models.IpAddress.get(ip2.id).interface_id)
def test_data(self):
interface = factory_models.InterfaceFactory()
data = interface.data()
self.assertEqual(data['id'], interface.virtual_interface_id)
self.assertEqual(data['device_id'], interface.device_id)
self.assertEqual(data['tenant_id'], interface.tenant_id)
self.assertEqual(data['created_at'], interface.created_at)
self.assertEqual(data['updated_at'], interface.updated_at)
def test_mac_address(self):
interface = factory_models.InterfaceFactory()
mac = models.MacAddress.create(interface_id=interface.id,
address="ab:bc:cd:12:23:34")
self.assertEqual(interface.mac_address, mac)
def test_eui_formatted_mac_address(self):
interface = factory_models.InterfaceFactory()
models.MacAddress.create(interface_id=interface.id,
address="ab:bc:cd:12:23:34")
self.assertEqual(interface.mac_address_eui_format,
str(netaddr.EUI("ab-bc-cd-12-23-34")))
def test_mac_address_eui_format_is_none_when_no_mac_address(self):
interface = factory_models.InterfaceFactory()
self.assertIsNone(interface.mac_address_eui_format)
def test_unix_formatted_mac_address(self):
interface = factory_models.InterfaceFactory()
models.MacAddress.create(interface_id=interface.id,
address="ab:bc:cd:12:23:34")
self.assertEqual(interface.mac_address_unix_format,
"AB:BC:CD:12:23:34")
def test_mac_address_unix_format_is_none_when_no_mac_address(self):
interface = factory_models.InterfaceFactory()
self.assertIsNone(interface.mac_address_unix_format)
def test_ip_addresses(self):
interface = factory_models.InterfaceFactory()
ip1 = factory_models.IpAddressFactory(interface_id=interface.id)
ip2 = factory_models.IpAddressFactory(interface_id=interface.id)
noise_ip = factory_models.IpAddressFactory()
self.assertEqual(len(interface.ip_addresses), 2)
self.assertModelsEqual(interface.ip_addresses, [ip1, ip2])
def test_network_plugged_into_is_network_of_ip_configured_on_network(self):
interface = factory_models.InterfaceFactory()
net1_block = factory_models.IpBlockFactory(network_id="net1")
net1_block.allocate_ip(interface)
self.assertEqual(interface.plugged_in_network_id(), "net1")
def test_delete_by(self):
interface1 = factory_models.InterfaceFactory(device_id="instance1")
net1_block = factory_models.IpBlockFactory(network_id="net1")
iface1_ip = net1_block.allocate_ip(interface1)
interface2 = factory_models.InterfaceFactory(device_id="instance1")
interface3 = factory_models.InterfaceFactory(device_id="instance1")
noise_interface = factory_models.InterfaceFactory(device_id="ins")
models.Interface.delete_by(device_id="instance1")
[self.assertIsNone(models.Interface.get(iface.id)) for iface in
[interface1, interface2, interface3]]
self.assertTrue(models.IpAddress.get(
iface1_ip.id).marked_for_deallocation)
class TestAllowedIp(tests.BaseTest):
def _ip_on_network(self, network_id):
block = factory_models.IpBlockFactory(
network_id=network_id)
return block.allocate_ip(factory_models.InterfaceFactory())
def _plug_interface_into_network(self, network_id, interface):
factory_models.IpBlockFactory(
network_id=network_id).allocate_ip(interface)
def test_allow_ip_on_an_interface(self):
interface = factory_models.InterfaceFactory()
ip_on_interface = factory_models.IpBlockFactory(
network_id="x").allocate_ip(interface)
ip1 = self._ip_on_network("x")
ip2 = self._ip_on_network("x")
noise_ip1 = factory_models.IpAddressFactory()
noise_ip2 = factory_models.IpAddressFactory()
interface.allow_ip(ip1)
interface.allow_ip(ip2)
actual_allowed_ips = interface.ips_allowed()
self.assertModelsEqual(actual_allowed_ips, [ip1, ip2, ip_on_interface])
def test_disallow_an_ip_on_an_interface(self):
interface1 = factory_models.InterfaceFactory()
ip_on_interface1 = factory_models.IpBlockFactory(
network_id="A").allocate_ip(interface1)
interface2 = factory_models.InterfaceFactory()
ip_on_interface2 = factory_models.IpBlockFactory(
network_id="A").allocate_ip(interface2)
ip1 = self._ip_on_network("A")
ip2 = self._ip_on_network("A")
ip3 = self._ip_on_network("A")
noise_ip1 = self._ip_on_network("A")
noise_ip2 = self._ip_on_network("A")
interface1.allow_ip(ip1)
interface1.allow_ip(ip2)
interface1.allow_ip(ip3)
interface2.allow_ip(ip3)
interface1.disallow_ip(ip2)
self.assertModelsEqual(interface1.ips_allowed(),
[ip1, ip3, ip_on_interface1])
interface1.disallow_ip(ip3)
self.assertModelsEqual(interface1.ips_allowed(),
[ip1, ip_on_interface1])
self.assertModelsEqual(interface2.ips_allowed(),
[ip3, ip_on_interface2])
def test_allocating_ips_allows_the_ip_on_the_interface(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory()
ip = block.allocate_ip(interface=interface)
self.assertEqual(interface.ips_allowed(), [ip])
def test_deallocating_ip_disallows_that_ip_on_interface(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory(network_id="xyz")
ip = block.allocate_ip(interface=interface)
other_interface = factory_models.InterfaceFactory()
block.allocate_ip(interface=other_interface)
other_interface.allow_ip(ip)
block.deallocate_ip(ip.address)
self.assertEqual(interface.ips_allowed(), [])
self.assertEqual(other_interface.find_allowed_ip(ip.address), ip)
def test_deallocating_allowed_ip_only_disassociates_from_interface(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory(network_id="net123")
ip = block.allocate_ip(interface=interface)
other_interface = factory_models.InterfaceFactory()
self._plug_interface_into_network("net123", other_interface)
other_interface.allow_ip(ip)
current_time = datetime.datetime.now()
two_days_before = current_time - datetime.timedelta(days=2)
with unit.StubTime(time=two_days_before):
block.deallocate_ip(ip.address)
with unit.StubTime(time=current_time):
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)
self.assertIsNone(reloaded_ip.deallocated_at)
self.assertIsNone(reloaded_ip.interface_id)
def test_can_explicitly_allow_allocated_ip_on_same_interface(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory()
ip = block.allocate_ip(interface=interface)
interface.allow_ip(ip)
self.assertEqual(interface.ips_allowed(), [ip])
def test_if_ip_was_explicitly_allowed_deallocating_doesnt_disallow(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory()
ip = block.allocate_ip(interface=interface)
interface.allow_ip(ip)
ip.deallocate()
self.assertEqual(interface.ips_allowed(), [ip])
def test_find_allowed_ip(self):
interface = factory_models.InterfaceFactory()
self._plug_interface_into_network("xyz", interface)
ip1 = self._ip_on_network("xyz")
ip2 = self._ip_on_network("xyz")
interface.allow_ip(ip1)
interface.allow_ip(ip2)
self.assertEqual(interface.find_allowed_ip(ip1.address), ip1)
self.assertEqual(interface.find_allowed_ip(ip2.address), ip2)
def test_find_allowed_ip_raises_model_not_found(self):
interface = factory_models.InterfaceFactory(
vif_id_on_device="vif_1")
self._plug_interface_into_network("AAA", interface)
ip1 = self._ip_on_network("AAA")
ip2 = self._ip_on_network("AAA")
unshared_ip = factory_models.IpAddressFactory()
interface.allow_ip(ip1)
interface.allow_ip(ip2)
self.assertRaisesExcMessage(models.ModelNotFoundError,
_("Ip Address %s hasnt been allowed on "
"interface vif_1") % unshared_ip.address,
interface.find_allowed_ip,
unshared_ip.address)
def test_cannot_allow_ip_when_interface_is_pluged_into_other_network(self):
interface_plugged_into_net1 = factory_models.InterfaceFactory(
vif_id_on_device="viffy")
net1_block = factory_models.IpBlockFactory(network_id="1")
net1_ip = net1_block.allocate_ip(interface_plugged_into_net1)
net2_block = factory_models.IpBlockFactory(network_id="2")
net2_ip = net2_block.allocate_ip(factory_models.InterfaceFactory())
err_msg = ("Ip %s cannot be allowed on interface viffy "
"as interface is not configured "
"for ip's network") % net2_ip.address
self.assertRaisesExcMessage(models.IpNotAllowedOnInterfaceError,
err_msg,
interface_plugged_into_net1.allow_ip,
net2_ip)
def test_cannot_allow_ip_if_interface_isnt_plugged_into_any_network(self):
unplugged_interface = factory_models.InterfaceFactory(
vif_id_on_device="vif_id")
ip = factory_models.IpAddressFactory()
err_msg = ("Ip %s cannot be allowed on interface vif_id "
"as interface is not configured "
"for ip's network") % ip.address
self.assertRaisesExcMessage(models.IpNotAllowedOnInterfaceError,
err_msg,
unplugged_interface.allow_ip,
ip)
def _allocate_ip(block, interface=None, **kwargs):
interface = interface or factory_models.InterfaceFactory()
return block.allocate_ip(interface=interface, **kwargs)
def _setup_notifier(mock):
mock.StubOutClassWithMocks(notifier, "NoopNotifier")
return notifier.NoopNotifier()