Merge ~chad.smith/cloud-init:azure-no-ifupdown into cloud-init:master

Proposed by Chad Smith
Status: Merged
Approved by: Scott Moser
Approved revision: 6d567fe2e563f27412b4c6527eb12f57c81aeeea
Merged at revision: b05b9972d20ec3ea699d1691b67314d04e852d2f
Proposed branch: ~chad.smith/cloud-init:azure-no-ifupdown
Merge into: cloud-init:master
Diff against target: 134 lines (+40/-13)
2 files modified
cloudinit/sources/DataSourceAzure.py (+16/-9)
tests/unittests/test_datasource/test_azure.py (+24/-4)
Reviewer Review Type Date Requested Status
Scott Moser Needs Fixing
Server Team CI bot continuous-integration Approve
Review via email: mp+335470@code.launchpad.net

Commit message

azure: Only bounce network when necessary.

This fixes a traceback when attempting to bounce the network after
hostname resets.

In artful and bionic ifupdown package is no longer installed in default
cloud images. As such, Azure can't use those tools to bounce the network
informing DDNS about hostname changes. This doesn't affect DDNS updates
though because systemd-networkd is now watching hostname deltas and with
default behavior to SendHostname=True over dhcp for all hostname updates
which publishes DDNS for us.

LP: #1722668

Description of the change

azure: Don't bounce network with ifdown ifup when those tools don't exist

This fixes a traceback when attempting to bounce the network after
hostname resets.

In artful and bionic ifupdown package is no longer installed in default
cloudimages. As such, Azure can't use those tools to bounce the network
informing DDNS about hostname changes. This doesn't affect DDNS updates
though because systemd-networkd is now watching hostname deltas and with
default behavior to SendHostname=True over dhcp for all hostname updates
which publishes DDNS for us.

LP: #1722668

To post a comment you must log in.
Revision history for this message
Chad Smith (chad.smith) wrote :

One inline comment about a potential alternative that may be more palatable/specific.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:74f546422a0382e5b5782762b0db8be8339d48e3
https://jenkins.ubuntu.com/server/job/cloud-init-ci/648/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/648/rebuild

review: Needs Fixing (continuous-integration)
c092c12... by Chad Smith

flakes

Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:c092c12f606dd5a92e0f80db35a1cb4b8b5c1dcb
https://jenkins.ubuntu.com/server/job/cloud-init-ci/649/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    FAILED: Ubuntu LTS: Build

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/649/rebuild

review: Needs Fixing (continuous-integration)
fdf3923... by Chad Smith

per smoser's review, make the ifup/down check simpler and just don't bounce at all if we are missing ifup util. This will continue to do the right thing if ifup is present (xenial).

74fb5bb... by Chad Smith

drop unused is_bounce_command_missing_dependency

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:74fb5bb7fdd46d7067e371833499131dfde14b30
https://jenkins.ubuntu.com/server/job/cloud-init-ci/650/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    FAILED: Ubuntu LTS: Build

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/650/rebuild

review: Needs Fixing (continuous-integration)
6d567fe... by Chad Smith

properly mock util.which for non-ifupdown test platforms

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:6d567fe2e563f27412b4c6527eb12f57c81aeeea
https://jenkins.ubuntu.com/server/job/cloud-init-ci/651/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/651/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

looks good, thanks.

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

Thank you for your merge proposal.

Your branch has been set to 'Work in progress'.
Please set the branch back to 'Needs Review' after resolving the issues below.

Thanks again,
Your friendly neighborhood cloud-init robot.

Please fix the following issues:
------------------------------
Commit message lints:
 - Expected empty line on line 2 of the commit message
------------------------------

For more information, see commit message guidelines at
https://cloudinit.readthedocs.io/en/latest/topics/hacking.html#do-these-things-for-each-feature-or-bug

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
2index e73b57b..d1d0975 100644
3--- a/cloudinit/sources/DataSourceAzure.py
4+++ b/cloudinit/sources/DataSourceAzure.py
5@@ -26,10 +26,16 @@ DS_NAME = 'Azure'
6 DEFAULT_METADATA = {"instance-id": "iid-AZURE-NODE"}
7 AGENT_START = ['service', 'walinuxagent', 'start']
8 AGENT_START_BUILTIN = "__builtin__"
9-BOUNCE_COMMAND = [
10+BOUNCE_COMMAND_IFUP = [
11 'sh', '-xc',
12 "i=$interface; x=0; ifdown $i || x=$?; ifup $i || x=$?; exit $x"
13 ]
14+BOUNCE_COMMAND_FREEBSD = [
15+ 'sh', '-xc',
16+ ("i=$interface; x=0; ifconfig down $i || x=$?; "
17+ "ifconfig up $i || x=$?; exit $x")
18+]
19+
20 # azure systems will always have a resource disk, and 66-azure-ephemeral.rules
21 # ensures that it gets linked to this path.
22 RESOURCE_DISK_PATH = '/dev/disk/cloud/azure_resource'
23@@ -177,11 +183,6 @@ if util.is_FreeBSD():
24 RESOURCE_DISK_PATH = "/dev/" + res_disk
25 else:
26 LOG.debug("resource disk is None")
27- BOUNCE_COMMAND = [
28- 'sh', '-xc',
29- ("i=$interface; x=0; ifconfig down $i || x=$?; "
30- "ifconfig up $i || x=$?; exit $x")
31- ]
32
33 BUILTIN_DS_CONFIG = {
34 'agent_command': AGENT_START_BUILTIN,
35@@ -190,7 +191,7 @@ BUILTIN_DS_CONFIG = {
36 'hostname_bounce': {
37 'interface': DEFAULT_PRIMARY_NIC,
38 'policy': True,
39- 'command': BOUNCE_COMMAND,
40+ 'command': 'builtin',
41 'hostname_command': 'hostname',
42 },
43 'disk_aliases': {'ephemeral0': RESOURCE_DISK_PATH},
44@@ -606,8 +607,14 @@ def perform_hostname_bounce(hostname, cfg, prev_hostname):
45 env['old_hostname'] = prev_hostname
46
47 if command == "builtin":
48- command = BOUNCE_COMMAND
49-
50+ if util.is_FreeBSD():
51+ command = BOUNCE_COMMAND_FREEBSD
52+ elif util.which('ifup'):
53+ command = BOUNCE_COMMAND_IFUP
54+ else:
55+ LOG.debug(
56+ "Skipping network bounce: ifupdown utils aren't present.")
57+ return # Don't bounce as networkd handles hostname DDNS updates
58 LOG.debug("pubhname: publishing hostname [%s]", msg)
59 shell = not isinstance(command, (list, tuple))
60 # capture=False, see comments in bug 1202758 and bug 1206164.
61diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
62index 5ab4889..6341e1e 100644
63--- a/tests/unittests/test_datasource/test_azure.py
64+++ b/tests/unittests/test_datasource/test_azure.py
65@@ -174,6 +174,7 @@ scbus-1 on xpt0 bus 0
66 (dsaz, 'get_hostname', mock.MagicMock()),
67 (dsaz, 'set_hostname', mock.MagicMock()),
68 (dsaz, 'get_metadata_from_fabric', self.get_metadata_from_fabric),
69+ (dsaz.util, 'which', lambda x: True),
70 (dsaz.util, 'read_dmi_data', mock.MagicMock(
71 side_effect=_dmi_mocks)),
72 (dsaz.util, 'wait_for_files', mock.MagicMock(
73@@ -642,6 +643,8 @@ fdescfs /dev/fd fdescfs rw 0 0
74
75 class TestAzureBounce(CiTestCase):
76
77+ with_logs = True
78+
79 def mock_out_azure_moving_parts(self):
80 self.patches.enter_context(
81 mock.patch.object(dsaz, 'invoke_agent'))
82@@ -653,6 +656,8 @@ class TestAzureBounce(CiTestCase):
83 self.patches.enter_context(
84 mock.patch.object(dsaz, 'get_metadata_from_fabric',
85 mock.MagicMock(return_value={})))
86+ self.patches.enter_context(
87+ mock.patch.object(dsaz.util, 'which', lambda x: True))
88
89 def _dmi_mocks(key):
90 if key == 'system-uuid':
91@@ -753,6 +758,22 @@ class TestAzureBounce(CiTestCase):
92 self.assertTrue(ret)
93 self.assertEqual(1, perform_hostname_bounce.call_count)
94
95+ def test_bounce_skipped_on_ifupdown_absent(self):
96+ host_name = 'unchanged-host-name'
97+ self.get_hostname.return_value = host_name
98+ cfg = {'hostname_bounce': {'policy': 'force'}}
99+ dsrc = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg),
100+ agent_command=['not', '__builtin__'])
101+ patch_path = 'cloudinit.sources.DataSourceAzure.util.which'
102+ with mock.patch(patch_path) as m_which:
103+ m_which.return_value = None
104+ ret = self._get_and_setup(dsrc)
105+ self.assertEqual([mock.call('ifup')], m_which.call_args_list)
106+ self.assertTrue(ret)
107+ self.assertIn(
108+ "Skipping network bounce: ifupdown utils aren't present.",
109+ self.logs.getvalue())
110+
111 def test_different_hostnames_sets_hostname(self):
112 expected_hostname = 'azure-expected-host-name'
113 self.get_hostname.return_value = 'default-host-name'
114@@ -817,9 +838,7 @@ class TestAzureBounce(CiTestCase):
115 self.assertEqual(hostname, bounce_env['hostname'])
116 self.assertEqual(old_hostname, bounce_env['old_hostname'])
117
118- def test_default_bounce_command_used_by_default(self):
119- cmd = 'default-bounce-command'
120- dsaz.BUILTIN_DS_CONFIG['hostname_bounce']['command'] = cmd
121+ def test_default_bounce_command_ifup_used_by_default(self):
122 cfg = {'hostname_bounce': {'policy': 'force'}}
123 data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
124 dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
125@@ -827,7 +846,8 @@ class TestAzureBounce(CiTestCase):
126 self.assertTrue(ret)
127 self.assertEqual(1, self.subp.call_count)
128 bounce_args = self.subp.call_args[1]['args']
129- self.assertEqual(cmd, bounce_args)
130+ self.assertEqual(
131+ dsaz.BOUNCE_COMMAND_IFUP, bounce_args)
132
133 @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
134 def test_set_hostname_option_can_disable_bounce(

Subscribers

People subscribed via source and target branches