<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Nov 21, 2019 at 6:43 PM Cole Robinson <<a href="mailto:crobinso@redhat.com">crobinso@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 11/21/19 5:28 AM, Daniel P. Berrangé wrote:<br>
> On Wed, Nov 20, 2019 at 05:49:45PM -0500, Cole Robinson wrote:<br>
>> Hi all. The purpose of this mail is to get some feedback on pending<br>
>> cloud-init support in virt-install. If you're on the CC list here, I<br>
>> either pulled your email from a cloud-init discussion on the the<br>
>> virt-tools-list mailing list, or from the CC list of this virt-install bug:<br>
>><br>
>> RFE: Provide cloud-init integration for VMs<br>
>> <a href="https://bugzilla.redhat.com/show_bug.cgi?id=981693" rel="noreferrer" target="_blank">https://bugzilla.redhat.com/show_bug.cgi?id=981693</a><br>
>><br>
>> For GSOC 2019 Athina Plaskasoviti completed some cloud-init integration<br>
>> work in virt-install. You can read her wrap up here:<br>
>> <a href="https://athinapl.home.blog/2019/08/25/gsoc-2019-cloud-init-configuration-for-virt-manager-virt-install/" rel="noreferrer" target="_blank">https://athinapl.home.blog/2019/08/25/gsoc-2019-cloud-init-configuration-for-virt-manager-virt-install/</a><br>
>><br>
>> Right now the code is sitting in a virt-manager.git branch, not yet<br>
>> pushed to master:<br>
>> <a href="https://github.com/virt-manager/virt-manager/tree/cloudinit" rel="noreferrer" target="_blank">https://github.com/virt-manager/virt-manager/tree/cloudinit</a><br>
>><br>
>> I'll summarize the current behavior, and then ask some questions.<br>
>><br>
>><br>
>> The branch adds a new 'virt-install --cloud-init' argument with several<br>
>> sub options. When specified, virt-install generates an empty meta-data<br>
>> file, a user-data file with the requested changes, stuffs them both into<br>
>> a cidata iso, which is used for the first VM boot and then deleted.<br>
>><br>
>> This behavior is only triggered when --cloud-init is specified in some<br>
>> form, there's no automagic invocation of this support.<br>
>><br>
>> The command sub options are:<br>
>><br>
>> $ ./virt-install --cloud-init=help<br>
>> --cloud-init options:<br>
>>   disable<br>
>>   root-password-file<br>
>>   root-password-generate<br>
>>   ssh-key<br>
>>   user-data<br>
>><br>
>> Their behavior:<br>
>><br>
>> * disable=yes: boolean option to disable cloud-init in the VM for<br>
>> subsequent boots. Adds this block to user-data:<br>
>>   runcmd:<br>
>>   - [ sudo, touch, /etc/cloud/cloud-init.disabled ]<br>
>><br>
>> * root-password-file=/MY/PATH: set the desired root password from the<br>
>> content of /MY/PATH on the host<br>
>><br>
>> * root-password-generate=yes: boolean option, generate a random root<br>
>> password, set it in user-data, print it to the host text console and<br>
>> pause for a bit for the user to see and copy it. sorta inspired by<br>
>> virt-builder<br>
>><br>
>> * ssh-key=/MY/KEY.pub: inject the ssh key from /MY/KEY.pub on the host<br>
>> into the cloud-init user-data<br>
>><br>
>> * user-data=/PATH/TO/user-data: ignore all other options and copy this<br>
>> file to the .iso as user-data<br>
>><br>
>> When bare '--cloud-init' is specified, we default to generating a random<br>
>> root password and disabling cloud-init for subsequent boots:<br>
>> --cloud-init root-password-generate=yes,disable=yes<br>
>><br>
>> We've explicitly rejected something like root-password=MY-PASSWORD<br>
>> because of the security implications of encouraging a password to end up<br>
>> in command line history. We've already had a CVE for something similar<br>
>> in virt-install.<br>
>><br>
>> Also, I don't want virt-install to be in the business of specifying<br>
>> every cloud-init option under the sun, there's gotta be a better tool<br>
>> for that already. So I'd like to keep --cloud-init suboptions<br>
>> specifically targeted to expected virt use cases, and anything else can<br>
>> be served with custom user-data=<br>
>><br>
>> One more point: my main interaction with cloud-init has historically<br>
>> been by grabbing a Fedora/RHEL cloud image, passing it to<br>
>> virt-install/virt-manager, and watching the boot hang, because there's<br>
>> no data provider and cloud-init times out talking to the network, and<br>
>> then I can't log in. I expect many people have hit this issue before.<br>
>> I've always worked around this by using 'virt-customize' to disable<br>
>> cloud-init and reset the root password. That's about the extent of my<br>
>> usage here, which is broadly why the bare `--cloud-init` is the way it was.<br>
>><br>
>> I'm also thinking to the future, if one day virt-install can detect that<br>
>> it was passed a distro cloud-init image, perhaps we can invoke some<br>
>> default behavior that gives the user a better chance of this config<br>
>> being usable out of the box. I figure that will match whatever we choose<br>
>> for the bare '--cloud-init' behavior<br>
> <br>
> One option is to take the lazy approach and always enable cloud init<br>
> if we are given a pre-built disk image.<br>
> <br>
>  * If the disk image doesn't support cloud init, then its fairly<br>
>    harmless to provide cloud-init data.<br>
> <br>
>  * If the disk image does support cloud init but has already been<br>
>    booted, and the user has marked cloud init as disable, then it<br>
>    is again harmless to provide cloud-init data<br>
> <br>
>  * If the disk image does support cloud init but has already been<br>
>    booted, and the user left cloud init enabled so that it runs on<br>
>    every boot, then passing cloud init data is probably good thing.<br>
> <br>
>  * If the disk image does support cloud init and has never been<br>
>    booted, then obviously providing cloud init data is good<br>
>    <br>
<br>
If we had a SMBIOS or -fw_cfg option, then maybe this is an option. But<br>
I don't think I could stomach doing this by default with the current<br>
'cdrom' approach, surely there would be complications, and at minimum<br>
complaints about a needless attached CDROM device.<br>
<br>
>> * What are the usecases you see for virt-install cloud-init support?<br>
> <br>
> To me the critical use case is simply providing a way for the user to<br>
> login to the guest. This is covered by password and/or SSH key inject.<br>
> Once they have that working, anything else is just nice to have.<br>
> <br>
>> * Does the above meet your expectations?<br>
> <br>
> Yep<br>
> <br>
>> * Are we missing anything vital?<br>
> <br>
> Probably the main question will be around the transport for providing<br>
> the metadata.<br>
> <br>
> The impl does config-drive:<br>
> <br>
>   <a href="https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html" rel="noreferrer" target="_blank">https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html</a><br>
> <br>
> As you see from the above list, there are many other approaches<br>
> possible, though the majority of them end up being based on a<br>
> magic IP address.<br>
> <br>
> The main downside of using a config-drive is that it is visible<br>
> to the guest as as new disk. In simple cases this is no big deal,<br>
> but if the user is setting up a VM with multiple disks, it can be<br>
> annoying to have an extra disk added for cloud-init, as it can<br>
> cause the drive-letters to be reshuffled.  OpenStack tried to<br>
> mitigate this by making the cloud-init config drive the very<br>
> last one to be added.<br>
> <br>
> This isn't perfect though. eg consider you boot the VM with<br>
> config drive, then hotplug a disk, now reboot the VM. The config<br>
> drive disk is now gone, and the hotplugged disk may well have<br>
> changed its drive letter.<br>
> <br>
> This is one reason for the use of the IP based metadata service.<br>
> <br>
> The challenge in any of the IP based solutions is that something on<br>
> the host needs to provide a server to listen for these requests.<br>
> <br>
> I think that providing such a server is out of scope for virt-install.<br>
> <br>
> I could see value in someone creating a new project that provides a<br>
> simple self-contained metadata server, as all the currentl metadata<br>
> server impls are part of some larger project codebase and can't be<br>
> used independantly (AFAIK - someone correct me if a simple standalone<br>
> impl already exists somewhere).<br>
> <br>
> In any case if someone wants to use a network metadata server, then<br>
> virt-install doesn't need todo anything at all. Any config is entirely<br>
> respponsibility of whomever is running that service.<br>
> <br>
> <br>
> If neither config drive, or IP based solutions are viable, then you<br>
> are left with platform specific options. Ignition uses fw_cfg however<br>
> this is really frowned upon by QEMU maintainers, as fw_cfg is not<br>
> intended for general purpose application usage.  The suggested replacement<br>
> for fw_cfg for app usage is the SMBIOS OEM strings table.<br>
> <br>
> Neither of these are platform portable, just x86 + aarch64 right now.<br>
> <br>
<br>
Thanks for the breakdown. There's obviously a lot to consider here and a<br>
large test matrix to consider if we go with the non-cdrom case.<br>
<br>
I think the 'cdrom' case is good enough for a first crack at this and<br>
anything else can build on that initial support. I think the command<br>
line is flexible enough that in the future we could have a --cloud-init<br>
method=SMBIOS/... for users to explicitly choose what injection method<br>
they want, but otherwise virt-install will choose a default, which may<br>
be different depending on the arch.<br>
<br>
> <br>
>> * Do you have an opinion of what behavior bare '--cloud-init' should give?<br>
> <br>
> My feeling is that a bare --cloud-init should inject the current user's<br>
> SSH identity and/or authorized keys list.<br>
> <br>
> ie either we grab $HOME/.ssh/id_rsa.pub, or we grab all the keys from<br>
> the SSH agent connection (ie ssh-add -l)<br>
> <br>
> Given that virt-intsall is run as root, there probably isn't a<br>
> /root/.ssh/id_rsa.pub file for most people. Grabbing the ssh-agent<br>
> authorized keys is probably best default approach.<br>
<br>
How to handle ssh keys kinda makes my head spin. I've shrunk the CC list<br>
on this mail to just the folks that mentioned ssh in some way in their<br>
replies<br>
<br>
If I'm thinking of the ideal interactive virt-install UI, it would be:<br>
<br>
$ virt-install --name MYVM --disk Fedora-Cloud-...qcow2 --cloud-init<br>
INFO: SSH keys added to MYVM<br>
INFO: Connecting to MYVM with: ssh fedora@192.168.122.XXX<br>
...<br>
[fedora@localhost:~] $<br>
<br>
<br>
If all the pieces come together, that's pretty nice. But there's a lot<br>
of missing pieces needed for that, and some unclear bits:<br>
<br>
* What is the cloud-init user name? Passing in an ssh key gives access<br>
to the default cloud-init configured username, which is different<br>
depending on the distro (might be fedora, ubuntu, etc). To properly<br>
handle this, we either need libosinfo distro detection, or use<br>
libguestfs to fish the default user out of /etc/cloud/cloud.cfg in the<br>
VM. And root account is typically locked, and ssh access disabled, and<br>
even if we could hack things to give root ssh access it seems like going<br>
against the grain WRT cloud images.<br></blockquote><div><br></div><div>We've had a similar discussion for multipass here, I've pointed out</div><div>a few options, one using the ssh_redirect_user</div><div><br></div><div> <a href="https://github.com/CanonicalLtd/multipass/issues/929">https://github.com/CanonicalLtd/multipass/issues/929</a></div><div><br></div><div>Currently cloud-init does not interact with the host in a way that this</div><div>information is easily discoverable; ideally, cloud-init could emit some</div><div>of this information to the platform; similar to how cloud-init publishes</div><div>ssh public host keys to console, and on GCE to the metadata service,</div><div>cloud-init could publish information like what's the default user.</div><div><br></div><div>That still leaves the existing and older images which need something.</div><div><br></div><div>Ryan</div></div></div>