Merge ~sw37th/cloud-init:opennebula_fix_null_gateway6 into cloud-init:master

Proposed by Akihiko Ota
Status: Merged
Approved by: Scott Moser
Approved revision: 3f8f3249643056c751efe11ce27edfe56d9cec3d
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~sw37th/cloud-init:opennebula_fix_null_gateway6
Merge into: cloud-init:master
Diff against target: 446 lines (+407/-3)
2 files modified
cloudinit/sources/DataSourceOpenNebula.py (+1/-1)
tests/unittests/test_datasource/test_opennebula.py (+406/-2)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Scott Moser Approve
Review via email: mp+350428@code.launchpad.net

Commit message

OpenNebula: Fix null gateway6

The OpenNebula data source generates an invalid netplan yaml file
if the IPv6 gateway is not defined in context.sh.

LP: #1768547

To post a comment you must log in.
Revision history for this message
Akihiko Ota (sw37th) wrote :

OpenNebula: Fix null gateway6

The OpenNebula data source generates an invalid netplan yaml file
if the IPv6 gateway is not defined in context.sh.

LP: #1768547

Revision history for this message
Scott Moser (smoser) wrote :

Hi,
Thanks for the merge proposal. I'll have the c-i bot run tests on it and it will post result here shortly.

That said, I'd like to see a unit tests added that covers this path.
It looks l ike you should be able to add a test to
  tests/unittests/test_datasource/test_opennebula.py:TestOpenNebulaNetwork

without too much effort.

Please feel free to ping me if you have any questions.

Thanks!

57941a4... by Akihiko Ota

OpenNebula: add tests for OpenNebulaNetwork.gen_conf()

148dda5... by Akihiko Ota

OpenNebula: add tests for several get methods of OpenNebulaNetwork

Revision history for this message
Akihiko Ota (sw37th) wrote :

Hi Scott,

Ok, I added some tests for TestOpenNebulaNetwork.gen_conf().
And also added several tests for get_* methods.

Revision history for this message
Scott Moser (smoser) wrote :

Akihiko,

This looks great, thank you for the extended test coverage.

I have a few little things inline.

https://jenkins.ubuntu.com/server/job/cloud-init-ci/179/
is running against your build here and will post its results.

3f8f324... by Akihiko Ota

OpenNebula: Fix up unittests

Added docstring, changed argument order of assertEqual, and splited some
tests.
Changed from assertIsNone() to assertEqual() to avoid RPM build error.

Revision history for this message
Akihiko Ota (sw37th) wrote :

Hi Scott,

I have changed TestOpenNebulaNetwork:
- added docstrings to each new tests.
- changed argument order of assertEqual().
- splited some tests.

And changed from assertIsNone() to assertEqual() to avoid RPM build error.
Please confirm.

Revision history for this message
Scott Moser (smoser) wrote :

Akihiko,
Thanks.
https://jenkins.ubuntu.com/server/job/cloud-init-ci/189/console
is running it will post here.

if it passes. i approve.
thanks.

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py
index 16c1078..77ccd12 100644
--- a/cloudinit/sources/DataSourceOpenNebula.py
+++ b/cloudinit/sources/DataSourceOpenNebula.py
@@ -232,7 +232,7 @@ class OpenNebulaNetwork(object):
232232
233 # Set IPv6 default gateway233 # Set IPv6 default gateway
234 gateway6 = self.get_gateway6(c_dev)234 gateway6 = self.get_gateway6(c_dev)
235 if gateway:235 if gateway6:
236 devconf['gateway6'] = gateway6236 devconf['gateway6'] = gateway6
237237
238 # Set DNS servers and search domains238 # Set DNS servers and search domains
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
index ab42f34..36b4d77 100644
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ b/tests/unittests/test_datasource/test_opennebula.py
@@ -354,6 +354,412 @@ class TestOpenNebulaNetwork(unittest.TestCase):
354354
355 system_nics = ('eth0', 'ens3')355 system_nics = ('eth0', 'ens3')
356356
357 def test_context_devname(self):
358 """Verify context_devname correctly returns mac and name."""
359 context = {
360 'ETH0_MAC': '02:00:0a:12:01:01',
361 'ETH1_MAC': '02:00:0a:12:0f:0f', }
362 expected = {
363 '02:00:0a:12:01:01': 'ETH0',
364 '02:00:0a:12:0f:0f': 'ETH1', }
365 net = ds.OpenNebulaNetwork(context)
366 self.assertEqual(expected, net.context_devname)
367
368 def test_get_nameservers(self):
369 """
370 Verify get_nameservers('device') correctly returns DNS server addresses
371 and search domains.
372 """
373 context = {
374 'DNS': '1.2.3.8',
375 'ETH0_DNS': '1.2.3.6 1.2.3.7',
376 'ETH0_SEARCH_DOMAIN': 'example.com example.org', }
377 expected = {
378 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8'],
379 'search': ['example.com', 'example.org']}
380 net = ds.OpenNebulaNetwork(context)
381 val = net.get_nameservers('eth0')
382 self.assertEqual(expected, val)
383
384 def test_get_mtu(self):
385 """Verify get_mtu('device') correctly returns MTU size."""
386 context = {'ETH0_MTU': '1280'}
387 net = ds.OpenNebulaNetwork(context)
388 val = net.get_mtu('eth0')
389 self.assertEqual('1280', val)
390
391 def test_get_ip(self):
392 """Verify get_ip('device') correctly returns IPv4 address."""
393 context = {'ETH0_IP': PUBLIC_IP}
394 net = ds.OpenNebulaNetwork(context)
395 val = net.get_ip('eth0', MACADDR)
396 self.assertEqual(PUBLIC_IP, val)
397
398 def test_get_ip_emptystring(self):
399 """
400 Verify get_ip('device') correctly returns IPv4 address.
401 It returns IP address created by MAC address if ETH0_IP has empty
402 string.
403 """
404 context = {'ETH0_IP': ''}
405 net = ds.OpenNebulaNetwork(context)
406 val = net.get_ip('eth0', MACADDR)
407 self.assertEqual(IP_BY_MACADDR, val)
408
409 def test_get_ip6(self):
410 """
411 Verify get_ip6('device') correctly returns IPv6 address.
412 In this case, IPv6 address is Given by ETH0_IP6.
413 """
414 context = {
415 'ETH0_IP6': IP6_GLOBAL,
416 'ETH0_IP6_ULA': '', }
417 expected = [IP6_GLOBAL]
418 net = ds.OpenNebulaNetwork(context)
419 val = net.get_ip6('eth0')
420 self.assertEqual(expected, val)
421
422 def test_get_ip6_ula(self):
423 """
424 Verify get_ip6('device') correctly returns IPv6 address.
425 In this case, IPv6 address is Given by ETH0_IP6_ULA.
426 """
427 context = {
428 'ETH0_IP6': '',
429 'ETH0_IP6_ULA': IP6_ULA, }
430 expected = [IP6_ULA]
431 net = ds.OpenNebulaNetwork(context)
432 val = net.get_ip6('eth0')
433 self.assertEqual(expected, val)
434
435 def test_get_ip6_dual(self):
436 """
437 Verify get_ip6('device') correctly returns IPv6 address.
438 In this case, IPv6 addresses are Given by ETH0_IP6 and ETH0_IP6_ULA.
439 """
440 context = {
441 'ETH0_IP6': IP6_GLOBAL,
442 'ETH0_IP6_ULA': IP6_ULA, }
443 expected = [IP6_GLOBAL, IP6_ULA]
444 net = ds.OpenNebulaNetwork(context)
445 val = net.get_ip6('eth0')
446 self.assertEqual(expected, val)
447
448 def test_get_ip6_prefix(self):
449 """
450 Verify get_ip6_prefix('device') correctly returns IPv6 prefix.
451 """
452 context = {'ETH0_IP6_PREFIX_LENGTH': IP6_PREFIX}
453 net = ds.OpenNebulaNetwork(context)
454 val = net.get_ip6_prefix('eth0')
455 self.assertEqual(IP6_PREFIX, val)
456
457 def test_get_ip6_prefix_emptystring(self):
458 """
459 Verify get_ip6_prefix('device') correctly returns IPv6 prefix.
460 It returns default value '64' if ETH0_IP6_PREFIX_LENGTH has empty
461 string.
462 """
463 context = {'ETH0_IP6_PREFIX_LENGTH': ''}
464 net = ds.OpenNebulaNetwork(context)
465 val = net.get_ip6_prefix('eth0')
466 self.assertEqual('64', val)
467
468 def test_get_gateway(self):
469 """
470 Verify get_gateway('device') correctly returns IPv4 default gateway
471 address.
472 """
473 context = {'ETH0_GATEWAY': '1.2.3.5'}
474 net = ds.OpenNebulaNetwork(context)
475 val = net.get_gateway('eth0')
476 self.assertEqual('1.2.3.5', val)
477
478 def test_get_gateway6(self):
479 """
480 Verify get_gateway6('device') correctly returns IPv6 default gateway
481 address.
482 """
483 context = {'ETH0_GATEWAY6': IP6_GW}
484 net = ds.OpenNebulaNetwork(context)
485 val = net.get_gateway6('eth0')
486 self.assertEqual(IP6_GW, val)
487
488 def test_get_mask(self):
489 """
490 Verify get_mask('device') correctly returns IPv4 subnet mask.
491 """
492 context = {'ETH0_MASK': '255.255.0.0'}
493 net = ds.OpenNebulaNetwork(context)
494 val = net.get_mask('eth0')
495 self.assertEqual('255.255.0.0', val)
496
497 def test_get_mask_emptystring(self):
498 """
499 Verify get_mask('device') correctly returns IPv4 subnet mask.
500 It returns default value '255.255.255.0' if ETH0_MASK has empty string.
501 """
502 context = {'ETH0_MASK': ''}
503 net = ds.OpenNebulaNetwork(context)
504 val = net.get_mask('eth0')
505 self.assertEqual('255.255.255.0', val)
506
507 def test_get_network(self):
508 """
509 Verify get_network('device') correctly returns IPv4 network address.
510 """
511 context = {'ETH0_NETWORK': '1.2.3.0'}
512 net = ds.OpenNebulaNetwork(context)
513 val = net.get_network('eth0', MACADDR)
514 self.assertEqual('1.2.3.0', val)
515
516 def test_get_network_emptystring(self):
517 """
518 Verify get_network('device') correctly returns IPv4 network address.
519 It returns network address created by MAC address if ETH0_NETWORK has
520 empty string.
521 """
522 context = {'ETH0_NETWORK': ''}
523 net = ds.OpenNebulaNetwork(context)
524 val = net.get_network('eth0', MACADDR)
525 self.assertEqual('10.18.1.0', val)
526
527 def test_get_field(self):
528 """
529 Verify get_field('device', 'name') returns *context* value.
530 """
531 context = {'ETH9_DUMMY': 'DUMMY_VALUE'}
532 net = ds.OpenNebulaNetwork(context)
533 val = net.get_field('eth9', 'dummy')
534 self.assertEqual('DUMMY_VALUE', val)
535
536 def test_get_field_withdefaultvalue(self):
537 """
538 Verify get_field('device', 'name', 'default value') returns *context*
539 value.
540 """
541 context = {'ETH9_DUMMY': 'DUMMY_VALUE'}
542 net = ds.OpenNebulaNetwork(context)
543 val = net.get_field('eth9', 'dummy', 'DEFAULT_VALUE')
544 self.assertEqual('DUMMY_VALUE', val)
545
546 def test_get_field_withdefaultvalue_emptycontext(self):
547 """
548 Verify get_field('device', 'name', 'default value') returns *default*
549 value if context value is empty string.
550 """
551 context = {'ETH9_DUMMY': ''}
552 net = ds.OpenNebulaNetwork(context)
553 val = net.get_field('eth9', 'dummy', 'DEFAULT_VALUE')
554 self.assertEqual('DEFAULT_VALUE', val)
555
556 def test_get_field_emptycontext(self):
557 """
558 Verify get_field('device', 'name') returns None if context value is
559 empty string.
560 """
561 context = {'ETH9_DUMMY': ''}
562 net = ds.OpenNebulaNetwork(context)
563 val = net.get_field('eth9', 'dummy')
564 self.assertEqual(None, val)
565
566 def test_get_field_nonecontext(self):
567 """
568 Verify get_field('device', 'name') returns None if context value is
569 None.
570 """
571 context = {'ETH9_DUMMY': None}
572 net = ds.OpenNebulaNetwork(context)
573 val = net.get_field('eth9', 'dummy')
574 self.assertEqual(None, val)
575
576 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
577 def test_gen_conf_gateway(self, m_get_phys_by_mac):
578 """Test rendering with/without IPv4 gateway"""
579 self.maxDiff = None
580 # empty ETH0_GATEWAY
581 context = {
582 'ETH0_MAC': '02:00:0a:12:01:01',
583 'ETH0_GATEWAY': '', }
584 for nic in self.system_nics:
585 expected = {
586 'version': 2,
587 'ethernets': {
588 nic: {
589 'match': {'macaddress': MACADDR},
590 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
591 m_get_phys_by_mac.return_value = {MACADDR: nic}
592 net = ds.OpenNebulaNetwork(context)
593 self.assertEqual(net.gen_conf(), expected)
594
595 # set ETH0_GATEWAY
596 context = {
597 'ETH0_MAC': '02:00:0a:12:01:01',
598 'ETH0_GATEWAY': '1.2.3.5', }
599 for nic in self.system_nics:
600 expected = {
601 'version': 2,
602 'ethernets': {
603 nic: {
604 'gateway4': '1.2.3.5',
605 'match': {'macaddress': MACADDR},
606 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
607 m_get_phys_by_mac.return_value = {MACADDR: nic}
608 net = ds.OpenNebulaNetwork(context)
609 self.assertEqual(net.gen_conf(), expected)
610
611 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
612 def test_gen_conf_gateway6(self, m_get_phys_by_mac):
613 """Test rendering with/without IPv6 gateway"""
614 self.maxDiff = None
615 # empty ETH0_GATEWAY6
616 context = {
617 'ETH0_MAC': '02:00:0a:12:01:01',
618 'ETH0_GATEWAY6': '', }
619 for nic in self.system_nics:
620 expected = {
621 'version': 2,
622 'ethernets': {
623 nic: {
624 'match': {'macaddress': MACADDR},
625 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
626 m_get_phys_by_mac.return_value = {MACADDR: nic}
627 net = ds.OpenNebulaNetwork(context)
628 self.assertEqual(net.gen_conf(), expected)
629
630 # set ETH0_GATEWAY6
631 context = {
632 'ETH0_MAC': '02:00:0a:12:01:01',
633 'ETH0_GATEWAY6': IP6_GW, }
634 for nic in self.system_nics:
635 expected = {
636 'version': 2,
637 'ethernets': {
638 nic: {
639 'gateway6': IP6_GW,
640 'match': {'macaddress': MACADDR},
641 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
642 m_get_phys_by_mac.return_value = {MACADDR: nic}
643 net = ds.OpenNebulaNetwork(context)
644 self.assertEqual(net.gen_conf(), expected)
645
646 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
647 def test_gen_conf_ipv6address(self, m_get_phys_by_mac):
648 """Test rendering with/without IPv6 address"""
649 self.maxDiff = None
650 # empty ETH0_IP6, ETH0_IP6_ULA, ETH0_IP6_PREFIX_LENGTH
651 context = {
652 'ETH0_MAC': '02:00:0a:12:01:01',
653 'ETH0_IP6': '',
654 'ETH0_IP6_ULA': '',
655 'ETH0_IP6_PREFIX_LENGTH': '', }
656 for nic in self.system_nics:
657 expected = {
658 'version': 2,
659 'ethernets': {
660 nic: {
661 'match': {'macaddress': MACADDR},
662 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
663 m_get_phys_by_mac.return_value = {MACADDR: nic}
664 net = ds.OpenNebulaNetwork(context)
665 self.assertEqual(net.gen_conf(), expected)
666
667 # set ETH0_IP6, ETH0_IP6_ULA, ETH0_IP6_PREFIX_LENGTH
668 context = {
669 'ETH0_MAC': '02:00:0a:12:01:01',
670 'ETH0_IP6': IP6_GLOBAL,
671 'ETH0_IP6_PREFIX_LENGTH': IP6_PREFIX,
672 'ETH0_IP6_ULA': IP6_ULA, }
673 for nic in self.system_nics:
674 expected = {
675 'version': 2,
676 'ethernets': {
677 nic: {
678 'match': {'macaddress': MACADDR},
679 'addresses': [
680 IP_BY_MACADDR + '/' + IP4_PREFIX,
681 IP6_GLOBAL + '/' + IP6_PREFIX,
682 IP6_ULA + '/' + IP6_PREFIX]}}}
683 m_get_phys_by_mac.return_value = {MACADDR: nic}
684 net = ds.OpenNebulaNetwork(context)
685 self.assertEqual(net.gen_conf(), expected)
686
687 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
688 def test_gen_conf_dns(self, m_get_phys_by_mac):
689 """Test rendering with/without DNS server, search domain"""
690 self.maxDiff = None
691 # empty DNS, ETH0_DNS, ETH0_SEARCH_DOMAIN
692 context = {
693 'ETH0_MAC': '02:00:0a:12:01:01',
694 'DNS': '',
695 'ETH0_DNS': '',
696 'ETH0_SEARCH_DOMAIN': '', }
697 for nic in self.system_nics:
698 expected = {
699 'version': 2,
700 'ethernets': {
701 nic: {
702 'match': {'macaddress': MACADDR},
703 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
704 m_get_phys_by_mac.return_value = {MACADDR: nic}
705 net = ds.OpenNebulaNetwork(context)
706 self.assertEqual(net.gen_conf(), expected)
707
708 # set DNS, ETH0_DNS, ETH0_SEARCH_DOMAIN
709 context = {
710 'ETH0_MAC': '02:00:0a:12:01:01',
711 'DNS': '1.2.3.8',
712 'ETH0_DNS': '1.2.3.6 1.2.3.7',
713 'ETH0_SEARCH_DOMAIN': 'example.com example.org', }
714 for nic in self.system_nics:
715 expected = {
716 'version': 2,
717 'ethernets': {
718 nic: {
719 'nameservers': {
720 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8'],
721 'search': ['example.com', 'example.org']},
722 'match': {'macaddress': MACADDR},
723 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
724 m_get_phys_by_mac.return_value = {MACADDR: nic}
725 net = ds.OpenNebulaNetwork(context)
726 self.assertEqual(net.gen_conf(), expected)
727
728 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
729 def test_gen_conf_mtu(self, m_get_phys_by_mac):
730 """Test rendering with/without MTU"""
731 self.maxDiff = None
732 # empty ETH0_MTU
733 context = {
734 'ETH0_MAC': '02:00:0a:12:01:01',
735 'ETH0_MTU': '', }
736 for nic in self.system_nics:
737 expected = {
738 'version': 2,
739 'ethernets': {
740 nic: {
741 'match': {'macaddress': MACADDR},
742 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
743 m_get_phys_by_mac.return_value = {MACADDR: nic}
744 net = ds.OpenNebulaNetwork(context)
745 self.assertEqual(net.gen_conf(), expected)
746
747 # set ETH0_MTU
748 context = {
749 'ETH0_MAC': '02:00:0a:12:01:01',
750 'ETH0_MTU': '1280', }
751 for nic in self.system_nics:
752 expected = {
753 'version': 2,
754 'ethernets': {
755 nic: {
756 'mtu': '1280',
757 'match': {'macaddress': MACADDR},
758 'addresses': [IP_BY_MACADDR + '/' + IP4_PREFIX]}}}
759 m_get_phys_by_mac.return_value = {MACADDR: nic}
760 net = ds.OpenNebulaNetwork(context)
761 self.assertEqual(net.gen_conf(), expected)
762
357 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")763 @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
358 def test_eth0(self, m_get_phys_by_mac):764 def test_eth0(self, m_get_phys_by_mac):
359 for nic in self.system_nics:765 for nic in self.system_nics:
@@ -395,7 +801,6 @@ class TestOpenNebulaNetwork(unittest.TestCase):
395 'match': {'macaddress': MACADDR},801 'match': {'macaddress': MACADDR},
396 'addresses': [IP_BY_MACADDR + '/16'],802 'addresses': [IP_BY_MACADDR + '/16'],
397 'gateway4': '1.2.3.5',803 'gateway4': '1.2.3.5',
398 'gateway6': None,
399 'nameservers': {804 'nameservers': {
400 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8']}}}}805 'addresses': ['1.2.3.6', '1.2.3.7', '1.2.3.8']}}}}
401806
@@ -494,7 +899,6 @@ class TestOpenNebulaNetwork(unittest.TestCase):
494 'match': {'macaddress': MAC_1},899 'match': {'macaddress': MAC_1},
495 'addresses': ['10.3.1.3/16'],900 'addresses': ['10.3.1.3/16'],
496 'gateway4': '10.3.0.1',901 'gateway4': '10.3.0.1',
497 'gateway6': None,
498 'nameservers': {902 'nameservers': {
499 'addresses': ['10.3.1.2', '1.2.3.8'],903 'addresses': ['10.3.1.2', '1.2.3.8'],
500 'search': [904 'search': [

Subscribers

People subscribed via source and target branches