Merge ~xnox/cloud-init:networkd into cloud-init:master

Proposed by Dimitri John Ledkov
Status: Work in progress
Proposed branch: ~xnox/cloud-init:networkd
Merge into: cloud-init:master
Diff against target: 174 lines (+84/-6)
3 files modified
cloudinit/sources/DataSourceCloudStack.py (+20/-1)
cloudinit/sources/helpers/azure.py (+23/-5)
tests/unittests/test_datasource/test_azure_helper.py (+41/-0)
Reviewer Review Type Date Requested Status
Dimitri John Ledkov (community) Needs Resubmitting
Server Team CI bot continuous-integration Approve
cloud-init Commiters Pending
Review via email: mp+331642@code.launchpad.net

Commit message

azure: discover datasource from networkd lease files

LP: #1718029

Description of the change

azure: discover datasource from networkd lease files

LP: #1718029

To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Testing seems all good. In-place test on Azure yields:

2017-10-02 08:06:31,894 - azure.py[DEBUG]: Finding Azure endpoint from networkd...
2017-10-02 08:06:31,895 - util.py[DEBUG]: Reading from /run/systemd/netif/leases/2 (quiet=False)
2017-10-02 08:06:31,895 - util.py[DEBUG]: Read 410 bytes from /run/systemd/netif/leases/2
2017-10-02 08:06:31,896 - azure.py[DEBUG]: Azure endpoint found at 168.63.129.16

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

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

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

review: Needs Fixing (continuous-integration)
~xnox/cloud-init:networkd updated
19e4771... by Dimitri John Ledkov

CloudStack: discover server address from networkd lease files

LP: #1718029

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

CloudStack portion is untested; please provide a cloudstack xenial instance with ssh-import-id lp:xnox

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

PASSED: Continuous integration, rev:19e4771e125793d34e24cd7a35876f19bd4ebe25
https://jenkins.ubuntu.com/server/job/cloud-init-ci/365/
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/365/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :
Revision history for this message
Dimitri John Ledkov (xnox) wrote :
review: Needs Resubmitting

Unmerged commits

19e4771... by Dimitri John Ledkov

CloudStack: discover server address from networkd lease files

LP: #1718029

9d7548b... by Dimitri John Ledkov

azure: discover datasource from networkd lease files

LP: #1718029

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
2index 7e0f9bb..5efbb99 100644
3--- a/cloudinit/sources/DataSourceCloudStack.py
4+++ b/cloudinit/sources/DataSourceCloudStack.py
5@@ -12,6 +12,7 @@
6 #
7 # This file is part of cloud-init. See LICENSE file for license information.
8
9+import glob
10 import os
11 from socket import inet_ntoa
12 from struct import pack
13@@ -23,6 +24,9 @@ from cloudinit import sources
14 from cloudinit import url_helper as uhelp
15 from cloudinit import util
16
17+from six.moves.configparser import ConfigParser
18+from six.moves import cStringIO as StringIO
19+
20 LOG = logging.getLogger(__name__)
21
22
23@@ -220,16 +224,31 @@ def get_latest_lease(lease_d=None):
24 return latest_file
25
26
27+def _get_server_address_from_networkd(_leases='/run/systemd/netif/leases/*'):
28+ for lease in glob.iglob(_leases):
29+ cp = ConfigParser()
30+ # pylint: disable=deprecated-method
31+ cp.readfp(StringIO('[LEASE]\n' + util.load_file(lease)))
32+ return cp.get('LEASE', 'SERVER_ADDRESS')
33+ return None
34+
35+
36 def get_vr_address():
37 # Get the address of the virtual router via dhcp leases
38 # If no virtual router is detected, fallback on default gateway.
39 # See http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.8/virtual_machines/user-data.html # noqa
40+
41+ # Try networkd first...
42+ latest_address = _get_server_address_from_networkd()
43+ if latest_address:
44+ return latest_address
45+
46+ # Try dhcp lease files next...
47 lease_file = get_latest_lease()
48 if not lease_file:
49 LOG.debug("No lease file found, using default gateway")
50 return get_default_gateway()
51
52- latest_address = None
53 with open(lease_file, "r") as fd:
54 for line in fd:
55 if "dhcp-server-identifier" in line:
56diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
57index 28ed0ae..adffe98 100644
58--- a/cloudinit/sources/helpers/azure.py
59+++ b/cloudinit/sources/helpers/azure.py
60@@ -1,5 +1,6 @@
61 # This file is part of cloud-init. See LICENSE file for license information.
62
63+import glob
64 import json
65 import logging
66 import os
67@@ -15,6 +16,8 @@ from xml.etree import ElementTree
68
69 from cloudinit import util
70
71+from six.moves.configparser import ConfigParser
72+from six.moves import cStringIO as StringIO
73
74 LOG = logging.getLogger(__name__)
75
76@@ -239,6 +242,18 @@ class WALinuxAgentShim(object):
77 return socket.inet_ntoa(packed_bytes)
78
79 @staticmethod
80+ def _get_value_from_networkd_leases(_leases='/run/systemd/netif/leases/*'):
81+ for lease in glob.iglob(_leases):
82+ cp = ConfigParser()
83+ try:
84+ # pylint: disable=deprecated-method
85+ cp.readfp(StringIO('[LEASE]\n' + util.load_file(lease)))
86+ return cp.get('LEASE', 'OPTION_245')
87+ except Exception:
88+ pass
89+ return None
90+
91+ @staticmethod
92 def _get_value_from_leases_file(fallback_lease_file):
93 leases = []
94 content = util.load_file(fallback_lease_file)
95@@ -287,12 +302,15 @@ class WALinuxAgentShim(object):
96
97 @staticmethod
98 def find_endpoint(fallback_lease_file=None):
99- LOG.debug('Finding Azure endpoint...')
100 value = None
101- # Option-245 stored in /run/cloud-init/dhclient.hooks/<ifc>.json
102- # a dhclient exit hook that calls cloud-init-dhclient-hook
103- dhcp_options = WALinuxAgentShim._load_dhclient_json()
104- value = WALinuxAgentShim._get_value_from_dhcpoptions(dhcp_options)
105+ LOG.debug('Finding Azure endpoint from networkd...')
106+ value = WALinuxAgentShim._get_value_from_networkd_leases()
107+ if value is None:
108+ # Option-245 stored in /run/cloud-init/dhclient.hooks/<ifc>.json
109+ # a dhclient exit hook that calls cloud-init-dhclient-hook
110+ LOG.debug('Finding Azure endpoint from hook json...')
111+ dhcp_options = WALinuxAgentShim._load_dhclient_json()
112+ value = WALinuxAgentShim._get_value_from_dhcpoptions(dhcp_options)
113 if value is None:
114 # Fallback and check the leases file if unsuccessful
115 LOG.debug("Unable to find endpoint in dhclient logs. "
116diff --git a/tests/unittests/test_datasource/test_azure_helper.py b/tests/unittests/test_datasource/test_azure_helper.py
117index 44b99ec..10cd7f4 100644
118--- a/tests/unittests/test_datasource/test_azure_helper.py
119+++ b/tests/unittests/test_datasource/test_azure_helper.py
120@@ -1,6 +1,8 @@
121 # This file is part of cloud-init. See LICENSE file for license information.
122
123 import os
124+import shutil
125+import tempfile
126
127 from cloudinit.sources.helpers import azure as azure_helper
128 from cloudinit.tests.helpers import ExitStack, mock, TestCase
129@@ -135,6 +137,45 @@ class TestExtractIpAddressFromLeaseValue(TestCase):
130 ))
131
132
133+class TestExtractIpAddressFromNetworkd(TestCase):
134+
135+ def setUp(self):
136+ super(TestExtractIpAddressFromNetworkd, self).setUp()
137+ lease_dir = tempfile.mkdtemp()
138+ self.leases = lease_dir + '/*'
139+ ifindex = '2'
140+ self.lease_file = os.path.join(lease_dir, ifindex)
141+ self.addCleanup(shutil.rmtree, lease_dir, ignore_errors=True)
142+
143+ def test_none(self):
144+ value = None
145+ self.assertEqual(
146+ value,
147+ azure_helper.WALinuxAgentShim._get_value_from_networkd_leases(
148+ self.leases
149+ ))
150+
151+ def test_typical(self):
152+ value = '624c3620'
153+ with open(self.lease_file, 'w') as f:
154+ f.write('OPTION_245=%s\n' % value)
155+ self.assertEqual(
156+ value,
157+ azure_helper.WALinuxAgentShim._get_value_from_networkd_leases(
158+ self.leases
159+ ))
160+
161+ def test_malformed(self):
162+ value = None
163+ with open(self.lease_file, 'w') as f:
164+ f.write('OPTION_246=624c3620\n')
165+ self.assertEqual(
166+ value,
167+ azure_helper.WALinuxAgentShim._get_value_from_networkd_leases(
168+ self.leases
169+ ))
170+
171+
172 class TestGoalStateParsing(TestCase):
173
174 default_parameters = {

Subscribers

People subscribed via source and target branches