I feel like I must be missing something obvious here. So I'm hoping someone can tell me why I'm being dumb before I try to submit an official bug report.
I recently downloaded the OVA version of the Ubuntu 16.04 cloud image and am attempting to deploy it to my vSphere 6 based vCenter instance via the web client. The nice thing about the "cloud image" over a regular ISO based template is that it comes with cloud-init baked in by default. The OVA version of this image exposes a bunch of the cloud-init options as vApp Options that can be filled in at the end of the wizard like this:
For the most part, this is all working great and as expected. The hostname gets set to the value of hostname
. The default user's password gets set to the value of Default User's password
.
The problem is that I'm now trying to use the Encoded user-data
field to pass in a cloud config YAML file to do some additional tasks. For the moment, the simplest test I could think of was the following cloud-config script to create a single user named demo
:
#cloud-config
users:
- name: demo
The instructions on the Encoded user-data
field indicate I need to base64 encode the user data I'm passing in and it will then be decoded later. The example I found in the cloud-init source re-affirms this. So I did.
$ base64 -w0 cloud-config.txt && echo
I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGRlbW8K
And I pasted that encoded value into the Encoded user-data
field and finished the wizard. But sadly, once the VM was finished deploying and came up, there was no "demo" user to be found.
So I dug into /var/log/cloud-init.log
looking for clues and the only thing I found was a warning about the content-type of the user-data.
__init__.py[DEBUG]: Calling handler CloudConfigPartHandler: [['text/cloud-config-jsonp', 'text/cloud-config']] (__begin__, None, 3) with frequency always
__init__.py[DEBUG]: Calling handler BootHookPartHandler: [['text/cloud-boothook']] (__begin__, None, 2) with frequency always
__init__.py[DEBUG]: Calling handler ShellScriptPartHandler: [['text/x-shellscript']] (__begin__, None, 2) with frequency always
__init__.py[DEBUG]: {'MIME-Version': '1.0', 'Content-Disposition': 'attachment; filename="part-001"', 'Content-Type': 'text/x-not-multipart'}
__init__.py[WARNING]: Unhandled non-multipart (text/x-not-multipart) userdata: 'b'I2Nsb3VkLWNvbmZpZwp1c2Vy'...'
__init__.py[DEBUG]: Calling handler CloudConfigPartHandler: [['text/cloud-config-jsonp', 'text/cloud-config']] (__end__, None, 3) with frequency always
util.py[DEBUG]: Writing to /var/lib/cloud/instances/test01/cloud-config.txt - wb: [384] 0 bytes
__init__.py[DEBUG]: Calling handler BootHookPartHandler: [['text/cloud-boothook']] (__end__, None, 2) with frequency always
__init__.py[DEBUG]: Calling handler ShellScriptPartHandler: [['text/x-shellscript']] (__end__, None, 2) with frequency always
handlers.py[DEBUG]: finish: init-local/consume-user-data: SUCCESS: reading and applying user-data
handlers.py[DEBUG]: start: init-local/consume-vendor-data: reading and applying vendor-data
stages.py[DEBUG]: no vendordata from datasource
handlers.py[DEBUG]: finish: init-local/consume-vendor-data: SUCCESS: reading and applying vendor-data
I also looked for clues in /var/lib/cloud/instance
. The user-data.txt
file there contained the same base64 encoded value I had pasted into the wizard. There was also a user-data.txt.i
file that contained the following:
Content-Type: multipart/mixed; boundary="===============1746641247068827328=="
MIME-Version: 1.0
Number-Attachments: 1
--===============1746641247068827328==
MIME-Version: 1.0
Content-Type: text/x-not-multipart
Content-Disposition: attachment; filename="part-001"
I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGRlbW8K
--===============1746641247068827328==--
The warning in the log file makes it seem like the primary problem is not related to the base64 encoding, but to the text/x-not-multipart
that ends up in the user-data.txt.i
file. But I'm not sure how that mime type even gets set.
Does anyone have a clue what I'm doing wrong here?