133
144
def test__user_optional(self):
134
subnet = factory.make_Subnet(cidr='192.168.0.0/24')
145
subnet = make_plain_subnet()
135
146
iprange = IPRange(
136
start_ip='192.168.0.1', end_ip='192.168.0.254',
147
start_ip='192.168.0.2', end_ip='192.168.0.254',
137
148
type=IPRANGE_TYPE.DYNAMIC, subnet=subnet,
138
149
comment="The quick brown owl jumps over the lazy alligator.")
141
152
def test__comment_optional(self):
142
subnet = factory.make_Subnet(cidr='192.168.0.0/24')
153
subnet = make_plain_subnet()
143
154
iprange = IPRange(
144
start_ip='192.168.0.1', end_ip='192.168.0.254', subnet=subnet,
155
start_ip='192.168.0.2', end_ip='192.168.0.254', subnet=subnet,
145
156
type=IPRANGE_TYPE.RESERVED, user=factory.make_User())
160
class TestIPRangeSavePreventsOverlapping(MAASServerTestCase):
162
no_fit = ".*No %s range can be created at requested start IP."
163
dynamic_no_fit = no_fit % IPRANGE_TYPE.DYNAMIC
164
reserved_no_fit = no_fit % IPRANGE_TYPE.RESERVED
166
overlaps = ".*Requested %s range conflicts with an existing %srange.*"
167
dynamic_overlaps = overlaps % (IPRANGE_TYPE.DYNAMIC, "IP address or ")
168
reserved_overlaps = overlaps % (IPRANGE_TYPE.RESERVED, "")
170
no_room = ".*There is no room for any %s ranges on this subnet.*"
171
dynamic_no_room = no_room % IPRANGE_TYPE.DYNAMIC
172
reserved_no_room = no_room % IPRANGE_TYPE.RESERVED
174
def test__no_save_duplicate_ipranges(self):
175
subnet = make_plain_subnet()
178
type=IPRANGE_TYPE.DYNAMIC,
179
start_ip="192.168.0.100",
180
end_ip="192.168.0.150",
182
# Make the same range again, should fail to save.
185
type=IPRANGE_TYPE.DYNAMIC,
186
start_ip="192.168.0.100",
187
end_ip="192.168.0.150",
189
with ExpectedException(ValidationError, self.dynamic_no_fit):
192
def test__no_save_range_overlap_begin(self):
193
subnet = make_plain_subnet()
196
type=IPRANGE_TYPE.DYNAMIC,
197
start_ip="192.168.0.100",
198
end_ip="192.168.0.150",
200
# Make an overlapping range across start_ip, should fail to save.
203
type=IPRANGE_TYPE.DYNAMIC,
204
start_ip="192.168.0.90",
205
end_ip="192.168.0.100",
207
with ExpectedException(ValidationError, self.dynamic_overlaps):
209
# Try as reserved range.
210
iprange.type = IPRANGE_TYPE.RESERVED
211
with ExpectedException(ValidationError, self.reserved_overlaps):
214
def test__no_save_range_overlap_end(self):
215
subnet = make_plain_subnet()
218
type=IPRANGE_TYPE.DYNAMIC,
219
start_ip="192.168.0.100",
220
end_ip="192.168.0.150",
222
# Make an overlapping range across end_ip, should fail to save.
225
type=IPRANGE_TYPE.DYNAMIC,
226
start_ip="192.168.0.140",
227
end_ip="192.168.0.160",
229
with ExpectedException(ValidationError, self.dynamic_no_fit):
232
def test__no_save_range_within_ranges(self):
233
subnet = make_plain_subnet()
236
type=IPRANGE_TYPE.DYNAMIC,
237
start_ip="192.168.0.100",
238
end_ip="192.168.0.150",
240
# Make a contained range, should not save.
243
type=IPRANGE_TYPE.DYNAMIC,
244
start_ip="192.168.0.110",
245
end_ip="192.168.0.140",
247
with ExpectedException(ValidationError, self.dynamic_no_fit):
250
def test__no_save_range_spanning_existing_range(self):
251
subnet = make_plain_subnet()
254
type=IPRANGE_TYPE.DYNAMIC,
255
start_ip="192.168.0.100",
256
end_ip="192.168.0.150",
258
# Make a contained range, should not save.
261
type=IPRANGE_TYPE.DYNAMIC,
262
start_ip="192.168.0.10",
263
end_ip="192.168.0.240",
265
with ExpectedException(ValidationError, self.dynamic_overlaps):
268
def test__no_save_range_within_existing_range(self):
269
subnet = make_plain_subnet()
272
type=IPRANGE_TYPE.DYNAMIC,
273
start_ip="192.168.0.100",
274
end_ip="192.168.0.150",
276
# Make a contained range, should not save.
279
type=IPRANGE_TYPE.DYNAMIC,
280
start_ip="192.168.0.110",
281
end_ip="192.168.0.140",
283
with ExpectedException(ValidationError, self.dynamic_no_fit):
286
def test__no_save_range_within_existing_reserved_range(self):
287
subnet = make_plain_subnet()
290
type=IPRANGE_TYPE.RESERVED,
291
start_ip="192.168.0.100",
292
end_ip="192.168.0.150",
294
# Make a contained range, should not save.
297
type=IPRANGE_TYPE.DYNAMIC,
298
start_ip="192.168.0.110",
299
end_ip="192.168.0.140",
301
with ExpectedException(ValidationError, self.dynamic_no_fit):
304
def test__no_save_when_no_ranges_available(self):
305
subnet = make_plain_subnet()
306
# Reserve the whole subnet, except gateway.
309
type=IPRANGE_TYPE.RESERVED,
310
start_ip="192.168.0.2",
311
end_ip="192.168.0.254",
313
# Try to make dynamic range at gateway (anywhere, actually) = no room!
316
type=IPRANGE_TYPE.DYNAMIC,
317
start_ip="192.168.0.1",
318
end_ip="192.168.0.1",
320
with ExpectedException(ValidationError, self.dynamic_no_room):
322
# We CAN reserve the gateway addr.
325
type=IPRANGE_TYPE.RESERVED,
326
start_ip="192.168.0.1",
327
end_ip="192.168.0.1",
329
# But now it's full - trying to save any reserved = no room!
332
type=IPRANGE_TYPE.RESERVED,
333
start_ip="192.168.0.25",
334
end_ip="192.168.0.35",
336
with ExpectedException(ValidationError, self.reserved_no_room):
339
def test__modify_existing_performs_validation(self):
340
subnet = make_plain_subnet()
343
type=IPRANGE_TYPE.DYNAMIC,
344
start_ip="192.168.0.100",
345
end_ip="192.168.0.150",
349
type=IPRANGE_TYPE.DYNAMIC,
350
start_ip="192.168.0.151",
351
end_ip="192.168.0.200",
354
# Make sure safe modification works.
355
iprange.start_ip = "192.168.0.210"
356
iprange.end_ip = "192.168.0.250"
358
# Modify again, but conflict with first range this time.
359
instance_id = iprange.id
360
iprange.start_ip = "192.168.0.110"
361
iprange.end_ip = "192.168.0.140"
362
with ExpectedException(ValidationError, self.dynamic_no_fit):
364
# Make sure original range isn't deleted after failure to modify.
365
iprange = reload_object(iprange)
366
self.assertEqual(iprange.id, instance_id)
368
def test__dynamic_range_cant_overlap_gateway_ip(self):
369
subnet = make_plain_subnet()
372
type=IPRANGE_TYPE.DYNAMIC,
373
start_ip="192.168.0.2",
374
end_ip="192.168.0.5",
377
# A DYNAMIC range cannot overlap the gateway IP.
378
iprange.start_ip = "192.168.0.1"
379
with ExpectedException(ValidationError, self.dynamic_no_fit):
382
def test__reserved_range_can_overlap_gateway_ip(self):
383
subnet = make_plain_subnet()
386
type=IPRANGE_TYPE.RESERVED,
387
start_ip="192.168.0.2",
388
end_ip="192.168.0.5",
391
# A RESERVED range can overlap the gateway IP.
392
iprange.start_ip = "192.168.0.1"
395
def test__reserved_range_cannot_overlap_dynamic_ranges(self):
396
subnet = factory.make_Subnet(
397
cidr='192.168.0.0/24',
398
gateway_ip='192.168.0.1',
399
dns_servers=['192.168.0.50', '192.168.0.200'])
402
type=IPRANGE_TYPE.DYNAMIC,
403
start_ip="192.168.0.2",
404
end_ip="192.168.0.49",
408
type=IPRANGE_TYPE.RESERVED,
409
start_ip="192.168.0.25",
410
end_ip="192.168.0.30",
412
with ExpectedException(ValidationError, self.reserved_no_fit):
415
def test__reserved_range_cannot_overlap_reserved_ranges(self):
416
subnet = factory.make_Subnet(
417
cidr='192.168.0.0/24',
418
gateway_ip='192.168.0.1',
419
dns_servers=['192.168.0.50', '192.168.0.200'])
422
type=IPRANGE_TYPE.RESERVED,
423
start_ip="192.168.0.1",
424
end_ip="192.168.0.250",
428
type=IPRANGE_TYPE.RESERVED,
429
start_ip="192.168.0.250",
430
end_ip="192.168.0.254",
432
with ExpectedException(ValidationError, self.reserved_no_fit):
435
def test__dynamic_range_cannot_overlap_static_ip(self):
436
subnet = make_plain_subnet()
437
factory.make_StaticIPAddress(
438
alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet=subnet)
441
type=IPRANGE_TYPE.DYNAMIC,
442
start_ip="192.168.0.2",
443
end_ip="192.168.0.254",
445
with ExpectedException(ValidationError, self.dynamic_overlaps):
448
def test__reserved_range_can_overlap_static_ip(self):
449
subnet = make_plain_subnet()
450
factory.make_StaticIPAddress(
451
alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet=subnet)
454
type=IPRANGE_TYPE.RESERVED,
455
start_ip="192.168.0.1",
456
end_ip="192.168.0.254",
460
def test__dynamic_range_cannot_overlap_dns_servers(self):
461
subnet = factory.make_Subnet(
462
cidr='192.168.0.0/24',
463
gateway_ip='192.168.0.1',
464
dns_servers=['192.168.0.50', '192.168.0.200'])
467
type=IPRANGE_TYPE.DYNAMIC,
468
start_ip="192.168.0.1",
469
end_ip="192.168.0.254",
471
with ExpectedException(ValidationError, self.dynamic_no_fit):
474
def test__reserved_range_can_overlap_dns_servers(self):
475
subnet = factory.make_Subnet(
476
cidr='192.168.0.0/24',
477
gateway_ip='192.168.0.1',
478
dns_servers=['192.168.0.50', '192.168.0.200'])
481
type=IPRANGE_TYPE.RESERVED,
482
start_ip="192.168.0.1",
483
end_ip="192.168.0.254",
487
def test__change_reserved_to_dynamic(self):
488
subnet = make_plain_subnet()
491
type=IPRANGE_TYPE.RESERVED,
492
start_ip="192.168.0.1",
493
end_ip="192.168.0.5",
495
# Reserved should save OK overlapping gateway IP.
498
# Dynamic should not save overlapping gateway IP.
499
iprange.type = IPRANGE_TYPE.DYNAMIC
500
with ExpectedException(ValidationError, self.dynamic_no_fit):
502
# Fix start_ip and now it should save.
503
iprange.start_ip = "192.168.0.2"
506
def test__change_dynamic_to_reserved(self):
507
subnet = make_plain_subnet()
510
type=IPRANGE_TYPE.DYNAMIC,
511
start_ip="192.168.0.2",
512
end_ip="192.168.0.5",
515
# Reserved should save OK overlapping gateway IP.
516
iprange.type = IPRANGE_TYPE.RESERVED
517
iprange.start_ip = "192.168.0.1"