]> git.proxmox.com Git - pve-network.git/blame - src/test/run_test_vnets_blackbox.pl
tests: test VNets functionality as a blackbox
[pve-network.git] / src / test / run_test_vnets_blackbox.pl
CommitLineData
e4914916
SL
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use lib qw(..);
7use File::Slurp;
8use List::Util qw(first all);
9use NetAddr::IP qw(:lower);
10
11use Test::More;
12use Test::MockModule;
13
14use PVE::Tools qw(extract_param file_set_contents);
15
16use PVE::Network::SDN;
17use PVE::Network::SDN::Zones;
18use PVE::Network::SDN::Zones::Plugin;
19use PVE::Network::SDN::Controllers;
20use PVE::Network::SDN::Dns;
21use PVE::Network::SDN::Vnets;
22
23use PVE::RESTEnvironment;
24
25use PVE::API2::Network::SDN::Zones;
26use PVE::API2::Network::SDN::Subnets;
27use PVE::API2::Network::SDN::Vnets;
28use PVE::API2::Network::SDN::Ipams;
29
30my $TMP_ETHERS_FILE = "/tmp/ethers";
31
32my $test_state = undef;
33sub clear_test_state {
34 $test_state = {
35 locks => {},
36 datacenter_config => {},
37 subnets_config => {},
38 controller_config => {},
39 dns_config => {},
40 zones_config => {},
41 vnets_config => {},
42 macdb => {},
43 ipamdb => {},
44 ipam_config => {
45 'ids' => {
46 'pve' => {
47 'type' => 'pve'
48 },
49 }
50 },
51 };
52 PVE::Tools::file_set_contents($TMP_ETHERS_FILE, "\n");
53}
54clear_test_state();
55
56my $mocked_cfs_lock_file = sub {
57 my ($filename, $timeout, $code, @param) = @_;
58
59 die "$filename already locked\n" if ($test_state->{locks}->{$filename});
60
61 $test_state->{locks}->{$filename} = 1;
62
63 my $res = eval { $code->(@param); };
64
65 delete $test_state->{locks}->{$filename};
66
67 return $res;
68};
69
70sub read_sdn_config {
71 my ($file) = @_;
72 # Read structure back in again
73 open my $in, '<', $file or die $!;
74 my $sdn_config;
75 {
76 local $/; # slurp mode
77 $sdn_config = eval <$in>;
78 }
79 close $in;
80 return $sdn_config;
81}
82
83my $mocked_pve_sdn;
84$mocked_pve_sdn = Test::MockModule->new('PVE::Network::SDN');
85$mocked_pve_sdn->mock(
86 cfs_lock_file => $mocked_cfs_lock_file,
87);
88
89my $mocked_pve_tools = Test::MockModule->new('PVE::Tools');
90$mocked_pve_tools->mock(
91 lock_file => $mocked_cfs_lock_file,
92);
93
94my $mocked_sdn_zones;
95$mocked_sdn_zones = Test::MockModule->new('PVE::Network::SDN::Zones');
96$mocked_sdn_zones->mock(
97 config => sub {
98 return $test_state->{zones_config};
99 },
100 write_config => sub {
101 my ($cfg) = @_;
102 $test_state->{zones_config} = $cfg;
103 },
104);
105
106my $mocked_sdn_zones_super_plugin;
107$mocked_sdn_zones_super_plugin = Test::MockModule->new('PVE::Network::SDN::Zones::Plugin');
108$mocked_sdn_zones_super_plugin->mock(
109 datacenter_config => sub {
110 return $test_state->{datacenter_config};
111 },
112);
113
114my $mocked_sdn_vnets;
115$mocked_sdn_vnets = Test::MockModule->new('PVE::Network::SDN::Vnets');
116$mocked_sdn_vnets->mock(
117 config => sub {
118 return $test_state->{vnets_config};
119 },
120 write_config => sub {
121 my ($cfg) = @_;
122 $test_state->{vnets_config} = $cfg;
123 },
124 cfs_lock_file => $mocked_cfs_lock_file,
125);
126
127my $mocked_sdn_subnets;
128$mocked_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
129$mocked_sdn_subnets->mock(
130 config => sub {
131 return $test_state->{subnets_config};
132 },
133 write_config => sub {
134 my ($cfg) = @_;
135 $test_state->{subnets_config} = $cfg;
136 },
137 cfs_lock_file => $mocked_cfs_lock_file,
138);
139
140my $mocked_sdn_controller;
141$mocked_sdn_controller = Test::MockModule->new('PVE::Network::SDN::Controllers');
142$mocked_sdn_controller->mock(
143 config => sub {
144 return $test_state->{controller_config};
145 },
146 write_config => sub {
147 my ($cfg) = @_;
148 $test_state->{controller_config} = $cfg;
149 },
150 cfs_lock_file => $mocked_cfs_lock_file,
151);
152
153
154my $mocked_sdn_dns;
155$mocked_sdn_dns = Test::MockModule->new('PVE::Network::SDN::Dns');
156$mocked_sdn_dns->mock(
157 config => sub {
158 return $test_state->{dns_config};
159 },
160 write_config => sub {
161 my ($cfg) = @_;
162 $test_state->{dns_config} = $cfg;
163 },
164 cfs_lock_file => $mocked_cfs_lock_file,
165);
166
167
168my $mocked_sdn_ipams;
169$mocked_sdn_ipams = Test::MockModule->new('PVE::Network::SDN::Ipams');
170$mocked_sdn_ipams->mock(
171 config => sub {
172 return $test_state->{ipam_config};
173 },
174 write_config => sub {
175 my ($cfg) = @_;
176 $test_state->{ipam_config} = $cfg;
177 },
178 read_macdb => sub {
179 return $test_state->{macdb};
180 },
181 write_macdb => sub {
182 my ($cfg) = @_;
183 $test_state->{macdb} = $cfg;
184 },
185 cfs_lock_file => $mocked_cfs_lock_file,
186);
187
188my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup("pve"); # NOTE this is hard-coded to pve
189my $mocked_ipam_plugin = Test::MockModule->new($ipam_plugin);
190$mocked_ipam_plugin->mock(
191 read_db => sub {
192 return $test_state->{ipamdb};
193 },
194 write_db => sub {
195 my ($cfg) = @_;
196 $test_state->{ipamdb} = $cfg;
197 },
198 cfs_lock_file => $mocked_cfs_lock_file,
199);
200
201my $mocked_sdn_dhcp_dnsmasq = Test::MockModule->new('PVE::Network::SDN::Dhcp::Dnsmasq');
202$mocked_sdn_dhcp_dnsmasq->mock(
203 assert_dnsmasq_installed => sub { return 1; },
204 before_configure => sub {},
205 ethers_file => sub { return "/tmp/ethers"; },
206 systemctl_service => sub {},
207 update_lease => sub {},
208);
209
210my $mocked_api_zones = Test::MockModule->new('PVE::API2::Network::SDN::Zones');
211$mocked_api_zones->mock(
212 create_etc_interfaces_sdn_dir => sub {},
213);
214
215my $rpcenv = PVE::RESTEnvironment->init('priv');
216$rpcenv->init_request();
217$rpcenv->set_language("en_US.UTF-8");
218$rpcenv->set_user('root@pam');
219
220my $mocked_rpc_env_obj = Test::MockModule->new('PVE::RESTEnvironment');
221$mocked_rpc_env_obj->mock(
222 check_any => sub { return 1; },
223);
224
225my $mocked_pve_cluster_obj = Test::MockModule->new('PVE::Cluster');
226$mocked_pve_cluster_obj->mock(
227 check_cfs_quorum => sub { return 1; },
228);
229
230# ------- TEST FUNCTIONS --------------
231
232sub nic_join {
233 my ($vnetid, $mac, $hostname, $vmid) = @_;
234 return PVE::Network::SDN::Vnets::add_next_free_cidr($vnetid, $hostname, $mac, "$vmid", undef, 1);
235}
236
237sub nic_leave {
238 my ($vnetid, $mac, $hostname) = @_;
239 return PVE::Network::SDN::Vnets::del_ips_from_mac($vnetid, $mac, $hostname);
240}
241
242sub nic_start {
243 my ($vnetid, $mac, $vmid, $hostname) = @_;
244 return PVE::Network::SDN::Vnets::add_dhcp_mapping($vnetid, $mac, $vmid, $hostname);
245}
246
247
248# ---- API HELPER FUNCTIONS FOR THE TESTS -----
249
250my $t_invalid;
251sub get_zone {
252 my ($id) = @_;
253 return eval { PVE::API2::Network::SDN::Zones->read({zone => $id}); };
254}
255# verify get_zone actually fails if invalid
256$t_invalid = get_zone("invalid");
257die("getting an invalid zone must fail") if (!$@);
258fail("getting an invalid zone must fail") if (defined $t_invalid);
259
260sub create_zone {
261 my ($params) = @_;
262 my $zoneid = $params->{zone};
263 # die if failed!
264 eval { PVE::API2::Network::SDN::Zones->create($params); };
265 die("creating zone failed: $@") if ($@);
266
267 my $zone = get_zone($zoneid);
268 die ("test setup: zone ($zoneid) not defined") if (!defined $zone);
269 return $zone;
270}
271
272sub get_vnet {
273 my ($id) = @_;
274 return eval { PVE::API2::Network::SDN::Vnets->read({vnet => $id}); };
275}
276# verify get_vnet
277$t_invalid = get_vnet("invalid");
278die("getting an invalid vnet must fail") if (!$@);
279fail("getting an invalid vnet must fail") if (defined $t_invalid);
280
281sub create_vnet {
282 my ($params) = @_;
283 my $vnetid = $params->{vnet};
284 PVE::API2::Network::SDN::Vnets->create($params);
285
286 my $vnet = get_vnet($vnetid);
287 die ("test setup: vnet ($vnetid) not defined") if (!defined $vnet);
288 return $vnet;
289}
290
291sub get_subnet {
292 my ($id) = @_;
293 return eval { PVE::API2::Network::SDN::Subnets->read({subnet => $id}); };
294}
295# verify get_subnet
296$t_invalid = get_subnet("invalid");
297die("getting an invalid subnet must fail") if (!$@);
298fail("getting an invalid subnet must fail") if (defined $t_invalid);
299
300sub create_subnet {
301 my ($params) = @_;
302 PVE::API2::Network::SDN::Subnets->create($params);
303}
304
305sub get_ipam_entries {
306 return PVE::API2::Network::SDN::Ipams->ipamindex({ipam => "pve"});
307}
308
309sub create_ip {
310 my ($param) = @_;
311 return PVE::API2::Network::SDN::Ips->ipcreate($param);
312}
313
314sub run_test {
315 my $test = shift;
316 clear_test_state();
317 $test->(@_);
318}
319
320sub get_ips_from_mac {
321 my ($mac) = @_;
322 my $ipam_entries = get_ipam_entries();
323 return grep { $_->{mac} eq $mac if defined $_->{mac} } $ipam_entries->@* if $ipam_entries;
324}
325
326sub get_ip4 {
327 my $ip4 = first { Net::IP::ip_is_ipv4($_->{ip}) } @_;
328 return $ip4->{ip} if defined $ip4;
329}
330
331sub get_ip6 {
332 my $ip6 = first { Net::IP::ip_is_ipv6($_->{ip}) } @_;
333 return $ip6->{ip} if defined $ip6;
334}
335
336
337# -------------- ACTUAL TESTS -----------------------
338
339sub test_create_vnet_with_gateway {
340 my $test_name = (split(/::/,(caller(0))[3]))[-1];
341 my $zoneid = "TESTZONE";
342 my $vnetid = "testvnet";
343
344 my $zone = create_zone({
345 type => "simple",
346 dhcp => "dnsmasq",
347 ipam => "pve",
348 zone => $zoneid,
349 });
350
351 my $vnet = create_vnet({
352 type => "vnet",
353 zone => $zoneid,
354 vnet => $vnetid,
355 });
356
357 create_subnet({
358 type => "subnet",
359 vnet => $vnetid,
360 subnet => "10.0.0.0/24",
361 gateway => "10.0.0.1",
362 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
363 });
364
365 my ($p) = first { $_->{gateway} == 1 } get_ipam_entries()->@*;
366 ok ($p, "$test_name: Gateway IP was created in IPAM");
367}
368run_test(\&test_create_vnet_with_gateway);
369
370
371sub test_without_subnet {
372 my $test_name = (split(/::/,(caller(0))[3]))[-1];
373
374 my $zoneid = "TESTZONE";
375 my $vnetid = "testvnet";
376
377 my $zone = create_zone({
378 type => "simple",
379 dhcp => "dnsmasq",
380 ipam => "pve",
381 zone => $zoneid,
382 });
383
384 my $vnet = create_vnet({
385 type => "vnet",
386 zone => $zoneid,
387 vnet => $vnetid,
388 });
389
390 my $hostname = "testhostname";
391 my $mac = "da:65:8f:18:9b:6f";
392 my $vmid = "999";
393
394 eval {
395 nic_join($vnetid, $mac, $hostname, $vmid);
396 };
397
398 if ($@) {
399 fail("$test_name: $@");
400 return;
401 }
402
403 my @ips = get_ips_from_mac($mac);
404 my $num_ips = scalar @ips;
405 is ($num_ips, 0, "$test_name: No IP allocated in IPAM");
406}
407run_test(\&test_without_subnet);
408
409
410sub test_nic_join {
411 my ($test_name, $subnets) = @_;
412
413 die "$test_name: we're expecting an array of subnets" if !$subnets;
414 my $num_subnets = scalar $subnets->@*;
415 die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
416 my $num_dhcp_ranges = scalar grep { $_->{'dhcp-range'} } $subnets->@*;
417
418 my $zoneid = "TESTZONE";
419 my $vnetid = "testvnet";
420
421 my $zone = create_zone({
422 type => "simple",
423 dhcp => "dnsmasq",
424 ipam => "pve",
425 zone => $zoneid,
426 });
427
428 my $vnet = create_vnet({
429 type => "vnet",
430 zone => $zoneid,
431 vnet => $vnetid,
432 });
433
434 foreach my $subnet ($subnets->@*) {
435 $subnet->{type} = "subnet";
436 $subnet->{vnet} = $vnetid;
437 create_subnet($subnet);
438 };
439
440 my $hostname = "testhostname";
441 my $mac = "da:65:8f:18:9b:6f";
442 my $vmid = "999";
443
444 eval {
445 nic_join($vnetid, $mac, $hostname, $vmid);
446 };
447
448 if ($@) {
449 fail("$test_name: $@");
450 return;
451 }
452
453 my @ips = get_ips_from_mac($mac);
454 my $num_ips = scalar @ips;
455 is ($num_ips, $num_dhcp_ranges, "$test_name: Expecting $num_dhcp_ranges IPs, found $num_ips");
456 ok ((all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
457 "$test_name: all IPs in correct vnet and zone"
458 );
459}
460
461run_test(
462 \&test_nic_join,
463 "nic_join IPv4 no dhcp",
464 [{
465 subnet => "10.0.0.0/24",
466 gateway => "10.0.0.1",
467 },
468]);
469
470run_test(
471 \&test_nic_join,
472 "nic_join IPv6 no dhcp",
473 [{
474 subnet => "8888::/64",
475 gateway => "8888::1",
476 },
477]);
478
479run_test(
480 \&test_nic_join,
481 "nic_join IPv4+6 no dhcp",
482 [{
483 subnet => "10.0.0.0/24",
484 gateway => "10.0.0.1",
485 }, {
486 subnet => "8888::/64",
487 gateway => "8888::1",
488 },
489]);
490
491run_test(
492 \&test_nic_join,
493 "nic_join IPv4 with dhcp",
494 [{
495 subnet => "10.0.0.0/24",
496 gateway => "10.0.0.1",
497 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
498 },
499]);
500
501run_test(
502 \&test_nic_join,
503 "nic_join IPv6 with dhcp",
504 [{
505 subnet => "8888::/64",
506 gateway => "8888::1",
507 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
508 },
509]);
510
511run_test(
512 \&test_nic_join,
513 "nic_join IPv4+6 with dhcp",
514 [{
515 subnet => "10.0.0.0/24",
516 gateway => "10.0.0.1",
517 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
518 }, {
519 subnet => "8888::/64",
520 gateway => "8888::1",
521 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
522 },
523]);
524
525run_test(
526 \&test_nic_join,
527 "nic_join IPv4 no DHCP, IPv6 with DHCP",
528 [{
529 subnet => "10.0.0.0/24",
530 gateway => "10.0.0.1",
531 }, {
532 subnet => "8888::/64",
533 gateway => "8888::1",
534 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
535 },
536]);
537
538run_test(
539 \&test_nic_join,
540 "nic_join IPv4 with DHCP, IPv6 no DHCP",
541 [{
542 subnet => "10.0.0.0/24",
543 gateway => "10.0.0.1",
544 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
545 }, {
546 subnet => "8888::/64",
547 gateway => "8888::1",
548 },
549]);
550
551
552sub test_nic_join_full_dhcp_range {
553 my ($test_name, $subnets, $expected_ip4, $expected_ip6) = @_;
554
555 die "$test_name: we're expecting an array of subnets" if !$subnets;
556 my $num_subnets = scalar $subnets->@*;
557 die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
558
559 my $zoneid = "TESTZONE";
560 my $vnetid = "testvnet";
561
562 my $zone = create_zone({
563 type => "simple",
564 dhcp => "dnsmasq",
565 ipam => "pve",
566 zone => $zoneid,
567 });
568
569 my $vnet = create_vnet({
570 type => "vnet",
571 zone => $zoneid,
572 vnet => $vnetid,
573 });
574
575 foreach my $subnet ($subnets->@*) {
576 $subnet->{type} = "subnet";
577 $subnet->{vnet} = $vnetid;
578 create_subnet($subnet);
579 };
580
581 my $hostname = "testhostname";
582 my $mac = "da:65:8f:18:9b:6f";
583 my $vmid = "999";
584
585 eval {
586 nic_join($vnetid, $mac, $hostname, $vmid);
587 };
588
589 if (! $@) {
590 fail ("$test_name: nic_join() is expected to fail because we cannot allocate all IPs");
591 }
592
593 my @ips = get_ips_from_mac($mac);
594 my $num_ips = scalar @ips;
595 is ($num_ips, 0, "$test_name: No IP allocated in IPAM");
596}
597
598run_test(
599 \&test_nic_join_full_dhcp_range,
600 "nic_join IPv4 with DHCP, dhcp-range full",
601 [{
602 subnet => "10.0.0.0/24",
603 gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
604 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
605 }
606]);
607
608run_test(
609 \&test_nic_join_full_dhcp_range,
610 "nic_join IPv6 with DHCP, dhcp-range full",
611 [{
612 subnet => "8888::/64",
613 gateway => "8888::100", # the gateway uses the only available IP in the dhcp-range
614 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
615 },
616]);
617
618run_test(
619 \&test_nic_join_full_dhcp_range,
620 "nic_join IPv4+6 with DHCP, dhcp-range full for both",
621 [{
622 subnet => "10.0.0.0/24",
623 gateway => "10.0.0.100",
624 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
625 }, {
626 subnet => "8888::/64",
627 gateway => "8888::100",
628 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
629 }
630]);
631
632run_test(
633 \&test_nic_join_full_dhcp_range,
634 "nic_join IPv4+6 with DHCP, dhcp-range full for IPv4",
635 [{
636 subnet => "10.0.0.0/24",
637 gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
638 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
639 }, {
640 subnet => "8888::/64",
641 gateway => "8888::1",
642 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
643 }],
644);
645
646run_test(
647 \&test_nic_join_full_dhcp_range,
648 "nic_join IPv4+6 with DHCP, dhcp-range full for IPv6",
649 [{
650 subnet => "10.0.0.0/24",
651 gateway => "10.0.0.1",
652 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
653 }, {
654 subnet => "8888::/64",
655 gateway => "8888::100",
656 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
657 }],
658);
659
660run_test(
661 \&test_nic_join_full_dhcp_range,
662 "nic_join IPv4 no DHCP, dhcp-range full for IPv6",
663 [{
664 subnet => "10.0.0.0/24",
665 gateway => "10.0.0.1",
666 }, {
667 subnet => "8888::/64",
668 gateway => "8888::100",
669 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
670 }],
671);
672
673
674# -------------- nic_start
675sub test_nic_start {
676 my ($test_name, $subnets, $current_ip4, $current_ip6, $num_expected_ips) = @_;
677
678 die "$test_name: we're expecting an array of subnets" if !$subnets;
679 my $num_subnets = scalar $subnets->@*;
680 die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
681
682 $num_expected_ips = scalar grep { $_->{'dhcp-range'} } $subnets->@* if !defined $num_expected_ips;
683
684 my $zoneid = "TESTZONE";
685 my $vnetid = "testvnet";
686
687 my $zone = create_zone({
688 type => "simple",
689 dhcp => "dnsmasq",
690 ipam => "pve",
691 zone => $zoneid,
692 });
693
694 my $vnet = create_vnet({
695 type => "vnet",
696 zone => $zoneid,
697 vnet => $vnetid,
698 });
699
700 foreach my $subnet ($subnets->@*) {
701 $subnet->{type} = "subnet";
702 $subnet->{vnet} = $vnetid;
703 create_subnet($subnet);
704 };
705
706 my $hostname = "testhostname";
707 my $mac = "da:65:8f:18:9b:6f";
708 my $vmid = "999";
709
710 if ($current_ip4) {
711 create_ip({
712 zone => $zoneid,
713 vnet => $vnetid,
714 mac => $mac,
715 ip => $current_ip4,
716 });
717 }
718
719 if ($current_ip6) {
720 create_ip({
721 zone => $zoneid,
722 vnet => $vnetid,
723 mac => $mac,
724 ip => $current_ip6,
725 });
726 }
727 my @current_ips = get_ips_from_mac($mac);
728 is ( get_ip4(@current_ips), $current_ip4, "$test_name: setup current IPv4: $current_ip4" ) if defined $current_ip4;
729 is ( get_ip6(@current_ips), $current_ip6, "$test_name: setup current IPv6: $current_ip6" ) if defined $current_ip6;
730
731 eval {
732 nic_start($vnetid, $mac, $hostname, $vmid);
733 };
734
735 if ($@) {
736 fail("$test_name: $@");
737 return;
738 }
739
740 my @ips = get_ips_from_mac($mac);
741 my $num_ips = scalar @ips;
742 is ($num_ips, $num_expected_ips, "$test_name: Expecting $num_expected_ips IPs, found $num_ips");
743 ok ((all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
744 "$test_name: all IPs in correct vnet and zone"
745 );
746
747 is ( get_ip4(@ips), $current_ip4, "$test_name: still current IPv4: $current_ip4" ) if $current_ip4;
748 is ( get_ip6(@ips), $current_ip6, "$test_name: still current IPv6: $current_ip6" ) if $current_ip6;
749}
750
751run_test(
752 \&test_nic_start,
753 "nic_start no IP, IPv4 without dhcp",
754 [{
755 subnet => "10.0.0.0/24",
756 gateway => "10.0.0.1",
757 },
758]);
759
760run_test(
761 \&test_nic_start,
762 "nic_start already IP, IPv4 without dhcp",
763 [{
764 subnet => "10.0.0.0/24",
765 gateway => "10.0.0.1",
766 }],
767 "10.0.0.99",
768 undef,
769 1
770);
771
772run_test(
773 \&test_nic_start,
774 "nic_start already IPv6, IPv6 without dhcp",
775 [{
776 subnet => "8888::/64",
777 gateway => "8888::1",
778 }],
779 undef,
780 "8888::99",
781 1
782);
783
784run_test(
785 \&test_nic_start,
786 "nic_start no IP, IPv4 subnet with dhcp",
787 [{
788 subnet => "10.0.0.0/24",
789 gateway => "10.0.0.1",
790 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
791 },
792]);
793
794run_test(
795 \&test_nic_start,
796 "nic_start already IP, IPv4 subnet with dhcp",
797 [{
798 subnet => "10.0.0.0/24",
799 gateway => "10.0.0.1",
800 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
801 }],
802 "10.0.0.99"
803);
804
805run_test(
806 \&test_nic_start,
807 "nic_start already IP, IPv6 subnet with dhcp",
808 [{
809 subnet => "8888::/64",
810 gateway => "8888::1",
811 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
812 }],
813 undef,
814 "8888::99"
815);
816
817run_test(
818 \&test_nic_start,
819 "nic_start IP, IPv4+6 subnet with dhcp",
820 [{
821 subnet => "10.0.0.0/24",
822 gateway => "10.0.0.1",
823 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
824 }, {
825 subnet => "8888::/64",
826 gateway => "8888::1",
827 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
828 },
829]);
830
831run_test(
832 \&test_nic_start,
833 "nic_start already IPv4, IPv4+6 subnet with dhcp",
834 [{
835 subnet => "10.0.0.0/24",
836 gateway => "10.0.0.1",
837 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
838 }, {
839 subnet => "8888::/64",
840 gateway => "8888::1",
841 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
842 }],
843 "10.0.0.99"
844);
845
846run_test(
847 \&test_nic_start,
848 "nic_start already IPv6, IPv4+6 subnet with dhcp",
849 [{
850 subnet => "10.0.0.0/24",
851 gateway => "10.0.0.1",
852 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
853 }, {
854 subnet => "8888::/64",
855 gateway => "8888::1",
856 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
857 }],
858 undef,
859 "8888::99"
860);
861
862run_test(
863 \&test_nic_start,
864 "nic_start already IPv4+6, IPv4+6 subnets with dhcp",
865 [{
866 subnet => "10.0.0.0/24",
867 gateway => "10.0.0.1",
868 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
869 }, {
870 subnet => "8888::/64",
871 gateway => "8888::1",
872 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
873 }],
874 "10.0.0.99",
875 "8888::99"
876);
877
878run_test(
879 \&test_nic_start,
880 "nic_start already IPv4+6, only IPv4 subnet with dhcp",
881 [{
882 subnet => "10.0.0.0/24",
883 gateway => "10.0.0.1",
884 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
885 }, {
886 subnet => "8888::/64",
887 gateway => "8888::1",
888 }],
889 "10.0.0.99",
890 "8888::99",
891 2
892);
893
894done_testing();