1
# Copyright (c) 2014 Thales Services SAS
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
17
from testtools import matchers
19
from neutron.common import exceptions as exc
20
import neutron.db.api as db
21
from neutron.plugins.common import constants as p_const
22
from neutron.plugins.common import utils as plugin_utils
23
from neutron.plugins.ml2 import config
24
from neutron.plugins.ml2 import driver_api as api
25
from neutron.plugins.ml2.drivers import type_vlan
26
from neutron.tests.unit import testlib_api
28
PROVIDER_NET = 'phys_net1'
29
TENANT_NET = 'phys_net2'
32
NETWORK_VLAN_RANGES = [PROVIDER_NET, "%s:%s:%s" %
33
(TENANT_NET, VLAN_MIN, VLAN_MAX)]
34
UPDATED_VLAN_RANGES = {
36
TENANT_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)],
40
class VlanTypeTest(testlib_api.SqlTestCase):
43
super(VlanTypeTest, self).setUp()
44
config.cfg.CONF.set_override('network_vlan_ranges',
46
group='ml2_type_vlan')
47
self.network_vlan_ranges = plugin_utils.parse_network_vlan_ranges(
49
self.driver = type_vlan.VlanTypeDriver()
50
self.driver._sync_vlan_allocations()
51
self.session = db.get_session()
52
self.driver.physnet_mtus = []
54
def test_parse_network_exception_handling(self):
55
with mock.patch.object(plugin_utils,
56
'parse_network_vlan_ranges') as parse_ranges:
57
parse_ranges.side_effect = Exception('any exception')
58
self.assertRaises(SystemExit,
59
self.driver._parse_network_vlan_ranges)
61
def _get_allocation(self, session, segment):
62
return session.query(type_vlan.VlanAllocation).filter_by(
63
physical_network=segment[api.PHYSICAL_NETWORK],
64
vlan_id=segment[api.SEGMENTATION_ID]).first()
66
def test_partial_segment_is_partial_segment(self):
67
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN}
68
self.assertTrue(self.driver.is_partial_segment(segment))
70
def test_specific_segment_is_not_partial_segment(self):
71
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
72
api.PHYSICAL_NETWORK: PROVIDER_NET,
73
api.SEGMENTATION_ID: 1}
74
self.assertFalse(self.driver.is_partial_segment(segment))
76
def test_validate_provider_segment(self):
77
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
78
api.PHYSICAL_NETWORK: PROVIDER_NET,
79
api.SEGMENTATION_ID: 1}
80
self.assertIsNone(self.driver.validate_provider_segment(segment))
82
def test_validate_provider_segment_without_segmentation_id(self):
83
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
84
api.PHYSICAL_NETWORK: TENANT_NET}
85
self.driver.validate_provider_segment(segment)
87
def test_validate_provider_segment_without_physical_network(self):
88
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN}
89
self.driver.validate_provider_segment(segment)
91
def test_validate_provider_segment_with_missing_physical_network(self):
92
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
93
api.SEGMENTATION_ID: 1}
94
self.assertRaises(exc.InvalidInput,
95
self.driver.validate_provider_segment,
98
def test_validate_provider_segment_with_invalid_physical_network(self):
99
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
100
api.PHYSICAL_NETWORK: 'other_phys_net',
101
api.SEGMENTATION_ID: 1}
102
self.assertRaises(exc.InvalidInput,
103
self.driver.validate_provider_segment,
106
def test_validate_provider_segment_with_invalid_segmentation_id(self):
107
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
108
api.PHYSICAL_NETWORK: PROVIDER_NET,
109
api.SEGMENTATION_ID: 5000}
110
self.assertRaises(exc.InvalidInput,
111
self.driver.validate_provider_segment,
114
def test_validate_provider_segment_with_invalid_input(self):
115
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
116
api.PHYSICAL_NETWORK: PROVIDER_NET,
117
api.SEGMENTATION_ID: 1,
119
self.assertRaises(exc.InvalidInput,
120
self.driver.validate_provider_segment,
123
def test_sync_vlan_allocations(self):
124
def check_in_ranges(network_vlan_ranges):
125
vlan_min, vlan_max = network_vlan_ranges[TENANT_NET][0]
126
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
127
api.PHYSICAL_NETWORK: TENANT_NET}
129
segment[api.SEGMENTATION_ID] = vlan_min - 1
131
self._get_allocation(self.session, segment))
132
segment[api.SEGMENTATION_ID] = vlan_max + 1
134
self._get_allocation(self.session, segment))
136
segment[api.SEGMENTATION_ID] = vlan_min
138
self._get_allocation(self.session, segment).allocated)
139
segment[api.SEGMENTATION_ID] = vlan_max
141
self._get_allocation(self.session, segment).allocated)
143
check_in_ranges(self.network_vlan_ranges)
144
self.driver.network_vlan_ranges = UPDATED_VLAN_RANGES
145
self.driver._sync_vlan_allocations()
146
check_in_ranges(UPDATED_VLAN_RANGES)
148
def test_reserve_provider_segment(self):
149
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
150
api.PHYSICAL_NETWORK: PROVIDER_NET,
151
api.SEGMENTATION_ID: 101}
152
alloc = self._get_allocation(self.session, segment)
153
self.assertIsNone(alloc)
154
observed = self.driver.reserve_provider_segment(self.session, segment)
155
alloc = self._get_allocation(self.session, observed)
156
self.assertTrue(alloc.allocated)
158
def test_reserve_provider_segment_already_allocated(self):
159
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
160
api.PHYSICAL_NETWORK: PROVIDER_NET,
161
api.SEGMENTATION_ID: 101}
162
observed = self.driver.reserve_provider_segment(self.session, segment)
163
self.assertRaises(exc.VlanIdInUse,
164
self.driver.reserve_provider_segment,
168
def test_reserve_provider_segment_in_tenant_pools(self):
169
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
170
api.PHYSICAL_NETWORK: TENANT_NET,
171
api.SEGMENTATION_ID: VLAN_MIN}
172
alloc = self._get_allocation(self.session, segment)
173
self.assertFalse(alloc.allocated)
174
observed = self.driver.reserve_provider_segment(self.session, segment)
175
alloc = self._get_allocation(self.session, observed)
176
self.assertTrue(alloc.allocated)
178
def test_reserve_provider_segment_without_segmentation_id(self):
179
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
180
api.PHYSICAL_NETWORK: TENANT_NET}
181
observed = self.driver.reserve_provider_segment(self.session, segment)
182
alloc = self._get_allocation(self.session, observed)
183
self.assertTrue(alloc.allocated)
184
vlan_id = observed[api.SEGMENTATION_ID]
185
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
186
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
188
def test_reserve_provider_segment_without_physical_network(self):
189
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN}
190
observed = self.driver.reserve_provider_segment(self.session, segment)
191
alloc = self._get_allocation(self.session, observed)
192
self.assertTrue(alloc.allocated)
193
vlan_id = observed[api.SEGMENTATION_ID]
194
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
195
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
196
self.assertEqual(TENANT_NET, observed[api.PHYSICAL_NETWORK])
198
def test_reserve_provider_segment_all_allocateds(self):
199
for __ in range(VLAN_MIN, VLAN_MAX + 1):
200
self.driver.allocate_tenant_segment(self.session)
201
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN}
202
self.assertRaises(exc.NoNetworkAvailable,
203
self.driver.reserve_provider_segment,
207
def test_get_mtu(self):
208
config.cfg.CONF.set_override('segment_mtu', 1475, group='ml2')
209
config.cfg.CONF.set_override('path_mtu', 1400, group='ml2')
210
self.driver.physnet_mtus = {'physnet1': 1450, 'physnet2': 1400}
211
self.assertEqual(1450, self.driver.get_mtu('physnet1'))
213
config.cfg.CONF.set_override('segment_mtu', 1375, group='ml2')
214
config.cfg.CONF.set_override('path_mtu', 1400, group='ml2')
215
self.driver.physnet_mtus = {'physnet1': 1450, 'physnet2': 1400}
216
self.assertEqual(1375, self.driver.get_mtu('physnet1'))
218
config.cfg.CONF.set_override('segment_mtu', 0, group='ml2')
219
config.cfg.CONF.set_override('path_mtu', 1400, group='ml2')
220
self.driver.physnet_mtus = {'physnet1': 1450, 'physnet2': 1400}
221
self.assertEqual(1450, self.driver.get_mtu('physnet1'))
223
config.cfg.CONF.set_override('segment_mtu', 0, group='ml2')
224
config.cfg.CONF.set_override('path_mtu', 0, group='ml2')
225
self.driver.physnet_mtus = {}
226
self.assertEqual(0, self.driver.get_mtu('physnet1'))
228
def test_allocate_tenant_segment(self):
229
for __ in range(VLAN_MIN, VLAN_MAX + 1):
230
segment = self.driver.allocate_tenant_segment(self.session)
231
alloc = self._get_allocation(self.session, segment)
232
self.assertTrue(alloc.allocated)
233
vlan_id = segment[api.SEGMENTATION_ID]
234
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
235
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
236
self.assertEqual(TENANT_NET, segment[api.PHYSICAL_NETWORK])
238
def test_allocate_tenant_segment_no_available(self):
239
for __ in range(VLAN_MIN, VLAN_MAX + 1):
240
self.driver.allocate_tenant_segment(self.session)
241
segment = self.driver.allocate_tenant_segment(self.session)
242
self.assertIsNone(segment)
244
def test_release_segment(self):
245
segment = self.driver.allocate_tenant_segment(self.session)
246
self.driver.release_segment(self.session, segment)
247
alloc = self._get_allocation(self.session, segment)
248
self.assertFalse(alloc.allocated)
250
def test_release_segment_unallocated(self):
251
segment = {api.NETWORK_TYPE: p_const.TYPE_VLAN,
252
api.PHYSICAL_NETWORK: PROVIDER_NET,
253
api.SEGMENTATION_ID: 101}
254
with mock.patch.object(type_vlan.LOG, 'warning') as log_warn:
255
self.driver.release_segment(self.session, segment)
256
log_warn.assert_called_once_with(
257
"No vlan_id %(vlan_id)s found on physical network "
258
"%(physical_network)s",
259
{'vlan_id': 101, 'physical_network': PROVIDER_NET})