New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SRU] Custom vendor data causes cloud-init failure on 0.7.5 #2565
Comments
Launchpad user Scott Moser(smoser) wrote on 2015-07-10T18:08:19.431199+00:00 marking trunk fix-released and ubuntu fixed-released per bug openers suggestion that it was fixed in 0.7.7 . I have not reproduced though. |
Launchpad user Edmund Rhudy(erhudy) wrote on 2015-07-22T15:46:15.301377+00:00 I can reliably reproduce this issue via the following steps:
from nova.api.metadata import base class CustomVendordata(base.VendorDataDriver):
[DEFAULT]
2015-07-22 15:30:56,075 - util.py[WARNING]: Running ssh-authkey-fingerprints (<module 'cloudinit.config.cc_ssh_authkey_fingerprints' from '/usr/lib/python2.7/dist-packages/cloudinit/config/cc_ssh_authkey_fingerprints.pyc'>) failed |
Launchpad user Edmund Rhudy(erhudy) wrote on 2015-07-22T16:15:27.272942+00:00 Just doing something simple like data = str(util.decomp_gzip(raw_data)) causes it to work, because data's now a string and hashable and so the range data[0:4096] works (whether the content is actually what it's supposed to be is another question). |
Launchpad user Edmund Rhudy(erhudy) wrote on 2015-07-23T14:16:41.225726+00:00 Screwed up the above script, it should be from nova.api.metadata import base class CustomVendordata(base.VendorDataDriver):
|
Launchpad user Edmund Rhudy(erhudy) wrote on 2015-07-23T14:57:01.299847+00:00 Changing the class to return a string rather than a dictionary avoids the cloud-init explosion. That runs counter to all the documentation that says "use JSON", but it's the workaround we'll use for now (serializing to YAML). |
Launchpad user Felipe Reyes(freyes) wrote on 2015-07-23T19:22:52.749881+00:00 A vendor data file should be a dict with a cloud-init key and the value for that key is expected to be a string or a list[0], the docs provide a simple example[1] Here is another example that will add a user called cloudy, upgrade the system and install htop: {"cloud-init": "#cloud-config\nusers:\n - name: cloudy\n ssh-import-id: cloudy\npackage_upgrade: True\npackages:\n - htop"} So a yaml cloud-config compatible has to be passed a string. [0] http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/cloudinit/sources/helpers/openstack.py#L470 |
Launchpad user Felipe Reyes(freyes) wrote on 2015-07-28T01:24:36.109812+00:00 cloud-init misbehaves when a vendor data json comes with information that won't be consumed by it, a fix was added in rev 1013[0]. I backported this patch to Trusty and prepared a patched image, having a custom vendor data doesn't break cloud-init functionality. I'll submit a SRU to fix this in Trusty as soon as possible. [0] http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/revision/1013 |
Launchpad user Felipe Reyes(freyes) wrote on 2015-07-28T01:25:09.974689+00:00 Utopic is already EOL, so I'm marking it as Invalid |
Launchpad user Felipe Reyes(freyes) wrote on 2015-07-28T03:18:29.196456+00:00 |
Launchpad user Felipe Reyes(freyes) wrote on 2015-09-10T15:54:44.390965+00:00 Rebased patch on top of latest cloud-init available in trusty-updates. |
Launchpad user Chris J Arges(arges) wrote on 2015-09-16T15:47:04.780721+00:00 Hello Edmund, or anyone else affected, Accepted cloud-init into trusty-proposed. The package will build now and be available at https://launchpad.net/ubuntu/+source/cloud-init/0.7.5-0ubuntu1.11 in a few hours, and then in the -proposed repository. Please help us by testing this new package. See https://wiki.ubuntu.com/Testing/EnableProposed for documentation how to enable and use -proposed. Your feedback will aid us getting this update out to other Ubuntu users. If this package fixes the bug for you, please add a comment to this bug, mentioning the version of the package you tested, and change the tag from verification-needed to verification-done. If it does not fix the bug for you, please add a comment stating that, and change the tag to verification-failed. In either case, details of your testing will help us make a better decision. Further information regarding the verification process can be found at https://wiki.ubuntu.com/QATeam/PerformingSRUVerification . Thank you in advance! |
Launchpad user Felipe Reyes(freyes) wrote on 2015-09-22T02:43:34.306970+00:00 The package available in trusty-proposed fixes this bug. $nova console-log 7a2e57a7-df5c-4c61-8f69-c98a41a1de5f $ nova console-log trusty-patched |
Launchpad user Stéphane Graber(stgraber) wrote on 2015-09-22T16:37:21.923910+00:00 The verification of the Stable Release Update for cloud-init has completed successfully and the package has now been released to -updates. Subsequently, the Ubuntu Stable Release Updates Team is being unsubscribed and will not receive messages about this bug report. In the event that you encounter a regression using the package from -updates please report a new bug using ubuntu-bug and tag the bug report regression-update so we can easily find any regressions. |
Launchpad user Launchpad Janitor(janitor) wrote on 2015-09-22T16:47:19.905185+00:00 This bug was fixed in the package cloud-init - 0.7.5-0ubuntu1.11 cloud-init (0.7.5-0ubuntu1.11) trusty; urgency=medium [ Felipe Reyes ]
[ Scott Moser ]
-- Scott Moser smoser@ubuntu.com Fri, 11 Sep 2015 20:22:00 -0400 |
This bug was originally filed in Launchpad as LP: #1469260
Launchpad details
Launchpad user Edmund Rhudy(erhudy) wrote on 2015-06-26T18:24:12.953850+00:00
[Impact]
When a vendor data json provides a dictionary without a 'cloud-init' key, cloud-init renders a non functional user-data, so any configuration (i.e. ssh public keys to use) is missed.
This prevents cloud providers from publishing a vendor data that is not intended to be consumed by cloud-init.
This patch checks for the existence of 'cloud-init' key and tries to get None, a string or a list as value, if this process fails or cloud-init key is missing the vendor data is set to None.
[Test Case]
vendordata_driver=nova.api.metadata.vendordata_json.JsonFileVendorData
vendordata_jsonfile_path=/etc/nova/vendordata.json
{"custom": {"a": 1, "b": [2, 3]}}
Expected result:
Actual result:
[Regression Potential]
[Other Info]
I encountered this issue when adding custom vendor data via nova-compute. Originally the bug manifested as SSH host key generation failing to fire when vendor data was present (example vendor data below).
{"msg": "", "uuid": "4996e2b67d2941818646481453de1efe", "users": [{"username": "erhudy", "sshPublicKeys": [], "uuid": "erhudy"}], "name": "TestTenant"}
I launched a volume-backed instance, waited for it to fail, then terminated it and mounted its root volume to examine the logs. What I found was that cloud-init was failing to process vendor-data into MIME multipart (note the absence of the line that indicates that cloud-init is writing vendor-data.txt.i):
2015-06-25 21:41:02,178 - util.py[DEBUG]: Writing to /var/lib/cloud/instance/obj.pkl - wb: [256] 9751 bytes
2015-06-25 21:41:02,178 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/65c9fb0c-0700-4f87-a22f-c59534e98dfb/user-data.txt - wb: [384] 0 bytes
2015-06-25 21:41:02,184 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/65c9fb0c-0700-4f87-a22f-c59534e98dfb/user-data.txt.i - wb: [384] 345 bytes
2015-06-25 21:41:02,185 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/65c9fb0c-0700-4f87-a22f-c59534e98dfb/vendor-data.txt - wb: [384] 234 bytes
2015-06-25 21:41:02,185 - util.py[DEBUG]: Reading from /proc/uptime (quiet=False)
After following the call chain all the way down, I found the problematic code in user_data.py:
Coverts a raw string into a mime message
def convert_string(raw_data, headers=None):
if not raw_data:
raw_data = ''
if not headers:
headers = {}
data = util.decomp_gzip(raw_data)
if "mime-version:" in data[0:4096].lower():
msg = email.message_from_string(data)
for (key, val) in headers.iteritems():
_replace_header(msg, key, val)
else:
mtype = headers.get(CONTENT_TYPE, NOT_MULTIPART_TYPE)
maintype, subtype = mtype.split("/", 1)
msg = MIMEBase(maintype, subtype, *headers)
msg.set_payload(data)
return msg
raw_data in the case that is failing is a dictionary rather than the expected string, so slicing into data causes a TypeError: unhashable type exception.
I think this bug was fixed after a fashion in 0.7.7, where the call to util.decomp_gzip() is now wrapped by util.decode_binary(), which appears to always return a string.
The text was updated successfully, but these errors were encountered: