c25045a63a0e1f757cd1c5cc0b804ac502f28a45
[openstack-build/neutron-build.git] / neutron / tests / unit / db / test_ipam_backend_mixin.py
1 # Copyright (c) 2015 Infoblox Inc.
2 # All Rights Reserved.
3 #
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
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
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
14 #    under the License.
15
16 import mock
17
18 from neutron.common import constants
19 from neutron.db import ipam_backend_mixin
20 from neutron.tests import base
21
22
23 class TestIpamBackendMixin(base.BaseTestCase):
24
25     def setUp(self):
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
35
36     def _prepare_ips(self, ips):
37         return [{'ip_address': ip[1],
38                  'subnet_id': ip[0]} for ip in ips]
39
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)
44
45     def _mock_slaac_subnet_off(self):
46         non_slaac_subnet = {'ipv6_address_mode': None,
47                             'ipv6_ra_mode': None}
48         self.mixin._get_subnet = mock.Mock(return_value=non_slaac_subnet)
49
50     def _test_get_changed_ips_for_port(self, expected_change, original_ips,
51                                        new_ips, owner):
52         change = self.mixin._get_changed_ips_for_port(self.ctx,
53                                                       original_ips,
54                                                       new_ips,
55                                                       owner)
56         self.assertEqual(expected_change, change)
57
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)
61
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)
67
68     def test__get_changed_ips_for_port_autoaddress(self):
69         new_ips = self._prepare_ips(self.default_new_ips)
70
71         original = (('id-1', '192.168.1.1'),
72                     ('id-5', '2000:1234:5678::12FF:FE34:5678'))
73         original_ips = self._prepare_ips(original)
74
75         self._mock_slaac_subnet_on()
76
77         expected_change = self.mixin.Changes(add=[new_ips[1]],
78                                              original=original_ips,
79                                              remove=[])
80         self._test_get_changed_ips_for_port(expected_change, original_ips,
81                                             new_ips, self.owner_non_router)
82
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)
86
87         original = (('id-1', '192.168.1.1'),
88                     ('id-5', '2000:1234:5678::12FF:FE34:5678'))
89         original_ips = self._prepare_ips(original)
90
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)
96
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]])
102
103         self._test_get_changed_ips_for_port(expected_change, original_ips,
104                                             new_ips, owner_not_router)
105
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'}]
110         original_ips = []
111
112         expected_change = self.mixin.Changes(add=[new_ips[0]],
113                                              original=[],
114                                              remove=[])
115         self._test_get_changed_ips_for_port(expected_change, original_ips,
116                                             new_ips, self.owner_non_router)
117
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()
121
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()
125
126     def test__is_ip_required_by_subnet_for_router_port(self):
127         # Owner -> router:
128         # _get_subnet should not be called,
129         # expected True
130         self._mock_slaac_subnet_off()
131
132         result = self.mixin._is_ip_required_by_subnet(self.ctx, 'id',
133                                                       self.owner_router)
134         self.assertTrue(result)
135         self.assertFalse(self.mixin._get_subnet.called)
136
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()
142
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)
147
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()
153
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)