Merge lp:~oddbloke/ubuntu/precise/cloud-init/lp1374600 into lp:ubuntu/precise-proposed/cloud-init
- Precise (12.04)
- lp1374600
- Merge into precise-proposed
Proposed by
Dan Watkins
Status: | Merged |
---|---|
Merged at revision: | 212 |
Proposed branch: | lp:~oddbloke/ubuntu/precise/cloud-init/lp1374600 |
Merge into: | lp:ubuntu/precise-proposed/cloud-init |
Diff against target: |
388 lines (+338/-3) 6 files modified
.pc/applied-patches (+1/-0) cloudinit/DataSourceGCE.py (+156/-0) debian/changelog (+7/-0) debian/cloud-init.templates (+3/-3) debian/patches/lp-1378441-backport-gce-data-source.patch (+170/-0) debian/patches/series (+1/-0) |
To merge this branch: | bzr merge lp:~oddbloke/ubuntu/precise/cloud-init/lp1374600 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Scott Moser | Needs Fixing | ||
Review via email: mp+237813@code.launchpad.net |
Commit message
Description of the change
This backports the GCE data source from trusty; the intent is to SRU it in the near future.
To post a comment you must log in.
- 212. By Dan Watkins
-
debian/
patches/ lp-1378441- backport- gce-data- source. patch: backported
Google Compute Engine data source. (LP: #1378441)
Revision history for this message
Dan Watkins (oddbloke) wrote : | # |
I've just pushed up those changes.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.pc/applied-patches' |
2 | --- .pc/applied-patches 2014-09-17 19:44:07 +0000 |
3 | +++ .pc/applied-patches 2014-10-10 08:21:23 +0000 |
4 | @@ -24,3 +24,4 @@ |
5 | lp-1302229-fix_futils_azure.patch |
6 | lp-1363260-add-cloudsigma_ds.patch |
7 | lp-1336855-grub_xvda.patch |
8 | +lp-1378441-backport-gce-data-source.patch |
9 | |
10 | === added directory '.pc/lp-1378441-backport-gce-data-source.patch' |
11 | === added directory '.pc/lp-1378441-backport-gce-data-source.patch/cloudinit' |
12 | === added file '.pc/lp-1378441-backport-gce-data-source.patch/cloudinit/DataSourceGCE.py' |
13 | === added file '.pc/lp-1378441-backport-gce-data-source.patch/cloudinit/url_helper.py' |
14 | === added file 'cloudinit/DataSourceGCE.py' |
15 | --- cloudinit/DataSourceGCE.py 1970-01-01 00:00:00 +0000 |
16 | +++ cloudinit/DataSourceGCE.py 2014-10-10 08:21:23 +0000 |
17 | @@ -0,0 +1,156 @@ |
18 | +# vi: ts=4 expandtab |
19 | +# |
20 | +# Author: Vaidas Jablonskis <jablonskis@gmail.com> |
21 | +# |
22 | +# This program is free software: you can redistribute it and/or modify |
23 | +# it under the terms of the GNU General Public License version 3, as |
24 | +# published by the Free Software Foundation. |
25 | +# |
26 | +# This program is distributed in the hope that it will be useful, |
27 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | +# GNU General Public License for more details. |
30 | +# |
31 | +# You should have received a copy of the GNU General Public License |
32 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | + |
34 | +import logging |
35 | +import urllib2 |
36 | + |
37 | +from cloudinit import util |
38 | +from cloudinit import DataSource as sources |
39 | + |
40 | +LOG = logging.getLogger(__name__) |
41 | + |
42 | +BUILTIN_DS_CONFIG = { |
43 | + 'metadata_url': 'http://metadata.google.internal./computeMetadata/v1/' |
44 | +} |
45 | +REQUIRED_FIELDS = ('instance-id', 'availability-zone', 'local-hostname') |
46 | + |
47 | + |
48 | +class _FakeResponse(object): |
49 | + |
50 | + def __init__(self, code, contents): |
51 | + self.code = code |
52 | + self.contents = contents |
53 | + |
54 | + |
55 | +class url_helper(object): |
56 | + # This is a shim designed to look like url_helper.py from future versions |
57 | + # of cloud-init. |
58 | + |
59 | + @staticmethod |
60 | + def readurl(url, headers): |
61 | + request = urllib2.Request(url, headers=headers) |
62 | + response = urllib2.urlopen(request) |
63 | + return _FakeResponse(code=response.getcode(), contents=response.read()) |
64 | + |
65 | + UrlError = urllib2.URLError |
66 | + |
67 | + |
68 | +class DataSourceGCE(sources.DataSource): |
69 | + def __init__(self, sys_cfg): |
70 | + sources.DataSource.__init__(self, sys_cfg) |
71 | + self.metadata = dict() |
72 | + self.ds_cfg = util.mergedict( |
73 | + util.get_cfg_by_path(sys_cfg, ["datasource", "GCE"], {}), |
74 | + BUILTIN_DS_CONFIG) |
75 | + self.metadata_address = self.ds_cfg['metadata_url'] |
76 | + |
77 | + # GCE takes sshKeys attribute in the format of '<user>:<public_key>' |
78 | + # so we have to trim each key to remove the username part |
79 | + def _trim_key(self, public_key): |
80 | + try: |
81 | + index = public_key.index(':') |
82 | + if index > 0: |
83 | + return public_key[(index + 1):] |
84 | + except: |
85 | + return public_key |
86 | + |
87 | + def get_data(self): |
88 | + # GCE metadata server requires a custom header since v1 |
89 | + headers = {'X-Google-Metadata-Request': 'True'} |
90 | + |
91 | + # url_map: (our-key, path, required) |
92 | + url_map = [ |
93 | + ('instance-id', 'instance/id', True), |
94 | + ('availability-zone', 'instance/zone', True), |
95 | + ('local-hostname', 'instance/hostname', True), |
96 | + ('public-keys', 'project/attributes/sshKeys', False), |
97 | + ('user-data', 'instance/attributes/user-data', False), |
98 | + ] |
99 | + |
100 | + # if we cannot resolve the metadata server, then no point in trying |
101 | + if not util.is_resolvable_url(self.metadata_address): |
102 | + LOG.debug("%s is not resolvable", self.metadata_address) |
103 | + return False |
104 | + |
105 | + # iterate over url_map keys to get metadata items |
106 | + found = False |
107 | + for (mkey, path, required) in url_map: |
108 | + try: |
109 | + resp = url_helper.readurl(url=self.metadata_address + path, |
110 | + headers=headers) |
111 | + if resp.code == 200: |
112 | + found = True |
113 | + self.metadata[mkey] = resp.contents |
114 | + else: |
115 | + if required: |
116 | + msg = "required url %s returned code %s. not GCE" |
117 | + if not found: |
118 | + LOG.debug(msg, path, resp.code) |
119 | + else: |
120 | + LOG.warn(msg, path, resp.code) |
121 | + return False |
122 | + else: |
123 | + self.metadata[mkey] = None |
124 | + except url_helper.UrlError as e: |
125 | + if required: |
126 | + msg = "required url %s raised exception %s. not GCE" |
127 | + if not found: |
128 | + LOG.debug(msg, path, e) |
129 | + else: |
130 | + LOG.warn(msg, path, e) |
131 | + return False |
132 | + msg = "Failed to get %s metadata item: %s." |
133 | + LOG.debug(msg, path, e) |
134 | + |
135 | + self.metadata[mkey] = None |
136 | + |
137 | + if self.metadata['public-keys']: |
138 | + lines = self.metadata['public-keys'].splitlines() |
139 | + self.metadata['public-keys'] = [self._trim_key(k) for k in lines] |
140 | + |
141 | + return found |
142 | + |
143 | + @property |
144 | + def launch_index(self): |
145 | + # GCE does not provide lauch_index property |
146 | + return None |
147 | + |
148 | + def get_instance_id(self): |
149 | + return self.metadata['instance-id'] |
150 | + |
151 | + def get_public_ssh_keys(self): |
152 | + return self.metadata['public-keys'] |
153 | + |
154 | + def get_hostname(self, fqdn=False, _resolve_ip=False): |
155 | + return self.metadata['local-hostname'] |
156 | + |
157 | + @property |
158 | + def userdata_raw(self): |
159 | + return self.metadata['user-data'] or '' |
160 | + |
161 | + @property |
162 | + def availability_zone(self): |
163 | + return self.metadata['availability-zone'] |
164 | + |
165 | +# Used to match classes to dependencies |
166 | +datasources = [ |
167 | + (DataSourceGCE, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)), |
168 | +] |
169 | + |
170 | + |
171 | +# Return a list of data sources that match this set of dependencies |
172 | +def get_datasource_list(depends): |
173 | + return sources.list_from_depends(depends, datasources) |
174 | |
175 | === modified file 'debian/changelog' |
176 | --- debian/changelog 2014-09-18 22:26:16 +0000 |
177 | +++ debian/changelog 2014-10-10 08:21:23 +0000 |
178 | @@ -1,3 +1,10 @@ |
179 | +cloud-init (0.6.3-0ubuntu1.15) precise; urgency=medium |
180 | + |
181 | + * debian/patches/lp-1378441-backport-gce-data-source.patch: backported |
182 | + Google Compute Engine data source. (LP: #1378441) |
183 | + |
184 | + -- Daniel Watkins <daniel.watkins@canonical.com> Thu, 10 Oct 2014 09:24:57 +0100 |
185 | + |
186 | cloud-init (0.6.3-0ubuntu1.14) precise-proposed; urgency=medium |
187 | |
188 | * debian/patches/lp-1363260-add-cloudsigma_ds.patch: backport from |
189 | |
190 | === modified file 'debian/cloud-init.templates' |
191 | --- debian/cloud-init.templates 2014-09-17 19:44:07 +0000 |
192 | +++ debian/cloud-init.templates 2014-10-10 08:21:23 +0000 |
193 | @@ -1,8 +1,8 @@ |
194 | Template: cloud-init/datasources |
195 | Type: multiselect |
196 | -Default: NoCloud, ConfigDrive, Azure, OVF, MAAS, CloudSigma |
197 | -Choices-C: NoCloud, ConfigDrive, Azure, OVF, MAAS, Ec2, SmartOS, CloudSigma |
198 | -Choices: NoCloud: Reads info from /var/lib/cloud/seed only, ConfigDrive: Reads data from Openstack Config Drive, Azure: read from MS Azure cdrom. Requires walinux-agent, OVF: Reads data from OVF Transports, MAAS: Reads data from Ubuntu MAAS, Ec2: reads data from EC2 Metadata service, SmartOS: reads data from serial console, CloudSigma: reads data from serial console |
199 | +Default: NoCloud, ConfigDrive, Azure, OVF, MAAS, CloudSigma, GCE |
200 | +Choices-C: NoCloud, ConfigDrive, Azure, OVF, MAAS, Ec2, SmartOS, CloudSigma, GCE |
201 | +Choices: NoCloud: Reads info from /var/lib/cloud/seed only, ConfigDrive: Reads data from Openstack Config Drive, Azure: read from MS Azure cdrom. Requires walinux-agent, OVF: Reads data from OVF Transports, MAAS: Reads data from Ubuntu MAAS, Ec2: reads data from EC2 Metadata service, SmartOS: reads data from serial console, CloudSigma: reads data from serial console, GCE: reads data from Google Compute Engine metadata service |
202 | Description: Which data sources should be searched? |
203 | Cloud-init supports searching different "Data Sources" for information |
204 | that it uses to configure a cloud instance. |
205 | |
206 | === added file 'debian/patches/lp-1378441-backport-gce-data-source.patch' |
207 | --- debian/patches/lp-1378441-backport-gce-data-source.patch 1970-01-01 00:00:00 +0000 |
208 | +++ debian/patches/lp-1378441-backport-gce-data-source.patch 2014-10-10 08:21:23 +0000 |
209 | @@ -0,0 +1,170 @@ |
210 | +Origin: upstream |
211 | +Bug: https://launchpad.net/bugs/1378441 |
212 | +Forwarded: not-needed |
213 | +Description: Add support for Google Compute Engine |
214 | + In order to use cloud-init on GCE, we need a GCE data source. This backports |
215 | + the GCE datasource from trusty, DataSourceGCE.py. |
216 | + . |
217 | + This is accompanied by a debian/cloud-init.templates change to enable debconf |
218 | + to select the 'GCE' datasource. |
219 | +Index: precise-proposed/cloudinit/DataSourceGCE.py |
220 | +=================================================================== |
221 | +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
222 | ++++ precise-proposed/cloudinit/DataSourceGCE.py 2014-10-07 15:43:05.054129022 +0100 |
223 | +@@ -0,0 +1,156 @@ |
224 | ++# vi: ts=4 expandtab |
225 | ++# |
226 | ++# Author: Vaidas Jablonskis <jablonskis@gmail.com> |
227 | ++# |
228 | ++# This program is free software: you can redistribute it and/or modify |
229 | ++# it under the terms of the GNU General Public License version 3, as |
230 | ++# published by the Free Software Foundation. |
231 | ++# |
232 | ++# This program is distributed in the hope that it will be useful, |
233 | ++# but WITHOUT ANY WARRANTY; without even the implied warranty of |
234 | ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
235 | ++# GNU General Public License for more details. |
236 | ++# |
237 | ++# You should have received a copy of the GNU General Public License |
238 | ++# along with this program. If not, see <http://www.gnu.org/licenses/>. |
239 | ++ |
240 | ++import logging |
241 | ++import urllib2 |
242 | ++ |
243 | ++from cloudinit import util |
244 | ++from cloudinit import DataSource as sources |
245 | ++ |
246 | ++LOG = logging.getLogger(__name__) |
247 | ++ |
248 | ++BUILTIN_DS_CONFIG = { |
249 | ++ 'metadata_url': 'http://metadata.google.internal./computeMetadata/v1/' |
250 | ++} |
251 | ++REQUIRED_FIELDS = ('instance-id', 'availability-zone', 'local-hostname') |
252 | ++ |
253 | ++ |
254 | ++class _FakeResponse(object): |
255 | ++ |
256 | ++ def __init__(self, code, contents): |
257 | ++ self.code = code |
258 | ++ self.contents = contents |
259 | ++ |
260 | ++ |
261 | ++class url_helper(object): |
262 | ++ # This is a shim designed to look like url_helper.py from future versions |
263 | ++ # of cloud-init. |
264 | ++ |
265 | ++ @staticmethod |
266 | ++ def readurl(url, headers): |
267 | ++ request = urllib2.Request(url, headers=headers) |
268 | ++ response = urllib2.urlopen(request) |
269 | ++ return _FakeResponse(code=response.getcode(), contents=response.read()) |
270 | ++ |
271 | ++ UrlError = urllib2.URLError |
272 | ++ |
273 | ++ |
274 | ++class DataSourceGCE(sources.DataSource): |
275 | ++ def __init__(self, sys_cfg): |
276 | ++ sources.DataSource.__init__(self, sys_cfg) |
277 | ++ self.metadata = dict() |
278 | ++ self.ds_cfg = util.mergedict( |
279 | ++ util.get_cfg_by_path(sys_cfg, ["datasource", "GCE"], {}), |
280 | ++ BUILTIN_DS_CONFIG) |
281 | ++ self.metadata_address = self.ds_cfg['metadata_url'] |
282 | ++ |
283 | ++ # GCE takes sshKeys attribute in the format of '<user>:<public_key>' |
284 | ++ # so we have to trim each key to remove the username part |
285 | ++ def _trim_key(self, public_key): |
286 | ++ try: |
287 | ++ index = public_key.index(':') |
288 | ++ if index > 0: |
289 | ++ return public_key[(index + 1):] |
290 | ++ except: |
291 | ++ return public_key |
292 | ++ |
293 | ++ def get_data(self): |
294 | ++ # GCE metadata server requires a custom header since v1 |
295 | ++ headers = {'X-Google-Metadata-Request': 'True'} |
296 | ++ |
297 | ++ # url_map: (our-key, path, required) |
298 | ++ url_map = [ |
299 | ++ ('instance-id', 'instance/id', True), |
300 | ++ ('availability-zone', 'instance/zone', True), |
301 | ++ ('local-hostname', 'instance/hostname', True), |
302 | ++ ('public-keys', 'project/attributes/sshKeys', False), |
303 | ++ ('user-data', 'instance/attributes/user-data', False), |
304 | ++ ] |
305 | ++ |
306 | ++ # if we cannot resolve the metadata server, then no point in trying |
307 | ++ if not util.is_resolvable_url(self.metadata_address): |
308 | ++ LOG.debug("%s is not resolvable", self.metadata_address) |
309 | ++ return False |
310 | ++ |
311 | ++ # iterate over url_map keys to get metadata items |
312 | ++ found = False |
313 | ++ for (mkey, path, required) in url_map: |
314 | ++ try: |
315 | ++ resp = url_helper.readurl(url=self.metadata_address + path, |
316 | ++ headers=headers) |
317 | ++ if resp.code == 200: |
318 | ++ found = True |
319 | ++ self.metadata[mkey] = resp.contents |
320 | ++ else: |
321 | ++ if required: |
322 | ++ msg = "required url %s returned code %s. not GCE" |
323 | ++ if not found: |
324 | ++ LOG.debug(msg, path, resp.code) |
325 | ++ else: |
326 | ++ LOG.warn(msg, path, resp.code) |
327 | ++ return False |
328 | ++ else: |
329 | ++ self.metadata[mkey] = None |
330 | ++ except url_helper.UrlError as e: |
331 | ++ if required: |
332 | ++ msg = "required url %s raised exception %s. not GCE" |
333 | ++ if not found: |
334 | ++ LOG.debug(msg, path, e) |
335 | ++ else: |
336 | ++ LOG.warn(msg, path, e) |
337 | ++ return False |
338 | ++ msg = "Failed to get %s metadata item: %s." |
339 | ++ LOG.debug(msg, path, e) |
340 | ++ |
341 | ++ self.metadata[mkey] = None |
342 | ++ |
343 | ++ if self.metadata['public-keys']: |
344 | ++ lines = self.metadata['public-keys'].splitlines() |
345 | ++ self.metadata['public-keys'] = [self._trim_key(k) for k in lines] |
346 | ++ |
347 | ++ return found |
348 | ++ |
349 | ++ @property |
350 | ++ def launch_index(self): |
351 | ++ # GCE does not provide lauch_index property |
352 | ++ return None |
353 | ++ |
354 | ++ def get_instance_id(self): |
355 | ++ return self.metadata['instance-id'] |
356 | ++ |
357 | ++ def get_public_ssh_keys(self): |
358 | ++ return self.metadata['public-keys'] |
359 | ++ |
360 | ++ def get_hostname(self, fqdn=False, _resolve_ip=False): |
361 | ++ return self.metadata['local-hostname'] |
362 | ++ |
363 | ++ @property |
364 | ++ def userdata_raw(self): |
365 | ++ return self.metadata['user-data'] or '' |
366 | ++ |
367 | ++ @property |
368 | ++ def availability_zone(self): |
369 | ++ return self.metadata['availability-zone'] |
370 | ++ |
371 | ++# Used to match classes to dependencies |
372 | ++datasources = [ |
373 | ++ (DataSourceGCE, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)), |
374 | ++] |
375 | ++ |
376 | ++ |
377 | ++# Return a list of data sources that match this set of dependencies |
378 | ++def get_datasource_list(depends): |
379 | ++ return sources.list_from_depends(depends, datasources) |
380 | |
381 | === modified file 'debian/patches/series' |
382 | --- debian/patches/series 2014-09-17 19:44:07 +0000 |
383 | +++ debian/patches/series 2014-10-10 08:21:23 +0000 |
384 | @@ -24,3 +24,4 @@ |
385 | lp-1302229-fix_futils_azure.patch |
386 | lp-1363260-add-cloudsigma_ds.patch |
387 | lp-1336855-grub_xvda.patch |
388 | +lp-1378441-backport-gce-data-source.patch |
2 nit picks, other than that, assuming this is tested it looks fine. dep.debian. net/deps/ dep3/
The headers you're putting on the patch are described at http://
so:
a.) add 'Origin: upstream'
you can probably remove 'Author:' here (i realize we're probably not consistent in other patches on this).
b.) the bug number you referenced is a private bug (1374600), while there is a public bug (bug 1378441). Seems to make sense to reference the public bug.
c.) reference the ubuntu bug in the changelog message.
so make those changes, and i'll upload for you.