1 # Copyright (c) 2015 Infoblox Inc.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
18 from neutron.common import constants
19 from neutron.db import ipam_backend_mixin
20 from neutron.tests import base
23 class TestIpamBackendMixin(base.BaseTestCase):
26 super(TestIpamBackendMixin, self).setUp()
27 self.mixin = ipam_backend_mixin.IpamBackendMixin()
28 self.ctx = mock.Mock()
29 self.default_new_ips = (('id-1', '192.168.1.1'),
30 ('id-2', '192.168.1.2'))
31 self.default_original_ips = (('id-1', '192.168.1.1'),
32 ('id-5', '172.20.16.5'))
33 self.owner_non_router = constants.DEVICE_OWNER_DHCP
34 self.owner_router = constants.DEVICE_OWNER_ROUTER_INTF
36 def _prepare_ips(self, ips):
37 return [{'ip_address': ip[1],
38 'subnet_id': ip[0]} for ip in ips]
40 def _mock_slaac_subnet_on(self):
41 slaac_subnet = {'ipv6_address_mode': constants.IPV6_SLAAC,
42 'ipv6_ra_mode': constants.IPV6_SLAAC}
43 self.mixin._get_subnet = mock.Mock(return_value=slaac_subnet)
45 def _mock_slaac_subnet_off(self):
46 non_slaac_subnet = {'ipv6_address_mode': None,
48 self.mixin._get_subnet = mock.Mock(return_value=non_slaac_subnet)
50 def _test_get_changed_ips_for_port(self, expected_change, original_ips,
52 change = self.mixin._get_changed_ips_for_port(self.ctx,
56 self.assertEqual(expected_change, change)
58 def test__get_changed_ips_for_port(self):
59 new_ips = self._prepare_ips(self.default_new_ips)
60 original_ips = self._prepare_ips(self.default_original_ips)
62 expected_change = self.mixin.Changes(add=[new_ips[1]],
63 original=[original_ips[0]],
64 remove=[original_ips[1]])
65 self._test_get_changed_ips_for_port(expected_change, original_ips,
66 new_ips, self.owner_router)
68 def test__get_changed_ips_for_port_autoaddress(self):
69 new_ips = self._prepare_ips(self.default_new_ips)
71 original = (('id-1', '192.168.1.1'),
72 ('id-5', '2000:1234:5678::12FF:FE34:5678'))
73 original_ips = self._prepare_ips(original)
75 self._mock_slaac_subnet_on()
77 expected_change = self.mixin.Changes(add=[new_ips[1]],
78 original=original_ips,
80 self._test_get_changed_ips_for_port(expected_change, original_ips,
81 new_ips, self.owner_non_router)
83 def test__get_changed_ips_for_port_autoaddress_ipv6_pd_enabled(self):
84 owner_not_router = constants.DEVICE_OWNER_DHCP
85 new_ips = self._prepare_ips(self.default_new_ips)
87 original = (('id-1', '192.168.1.1'),
88 ('id-5', '2000:1234:5678::12FF:FE34:5678'))
89 original_ips = self._prepare_ips(original)
91 # mock to test auto address part
92 pd_subnet = {'subnetpool_id': constants.IPV6_PD_POOL_ID,
93 'ipv6_address_mode': constants.IPV6_SLAAC,
94 'ipv6_ra_mode': constants.IPV6_SLAAC}
95 self.mixin._get_subnet = mock.Mock(return_value=pd_subnet)
97 # make a copy of original_ips
98 # since it is changed by _get_changed_ips_for_port
99 expected_change = self.mixin.Changes(add=[new_ips[1]],
100 original=[original_ips[0]],
101 remove=[original_ips[1]])
103 self._test_get_changed_ips_for_port(expected_change, original_ips,
104 new_ips, owner_not_router)
106 def _test_get_changed_ips_for_port_no_ip_address(self):
107 # IP address should be added if only subnet_id is provided,
108 # independently from auto_address status for subnet
109 new_ips = [{'subnet_id': 'id-3'}]
112 expected_change = self.mixin.Changes(add=[new_ips[0]],
115 self._test_get_changed_ips_for_port(expected_change, original_ips,
116 new_ips, self.owner_non_router)
118 def test__get_changed_ips_for_port_no_ip_address_no_slaac(self):
119 self._mock_slaac_subnet_off()
120 self._test_get_changed_ips_for_port_no_ip_address()
122 def test__get_changed_ips_for_port_no_ip_address_slaac(self):
123 self._mock_slaac_subnet_on()
124 self._test_get_changed_ips_for_port_no_ip_address()
126 def test__is_ip_required_by_subnet_for_router_port(self):
128 # _get_subnet should not be called,
130 self._mock_slaac_subnet_off()
132 result = self.mixin._is_ip_required_by_subnet(self.ctx, 'id',
134 self.assertTrue(result)
135 self.assertFalse(self.mixin._get_subnet.called)
137 def test__is_ip_required_by_subnet_for_non_router_port(self):
138 # Owner -> not router:
139 # _get_subnet should be called,
140 # expected True, because subnet is not slaac
141 self._mock_slaac_subnet_off()
143 result = self.mixin._is_ip_required_by_subnet(self.ctx, 'id',
144 self.owner_non_router)
145 self.assertTrue(result)
146 self.assertTrue(self.mixin._get_subnet.called)
148 def test__is_ip_required_by_subnet_for_non_router_port_and_slaac(self):
149 # Owner -> not router:
150 # _get_subnet should be called,
151 # expected False, because subnet is slaac
152 self._mock_slaac_subnet_on()
154 result = self.mixin._is_ip_required_by_subnet(self.ctx, 'id',
155 self.owner_non_router)
156 self.assertFalse(result)
157 self.assertTrue(self.mixin._get_subnet.called)