# Connection plugin with slow \_connect

**URL:** <https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481>\
**Category:** Ansible Developer\
**Tags:** ee\
**Created:** [July 8, 2021, 7:32pm UTC](https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481 "2021-07-08T19:32:25Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Roman\_Bolshakov](https://avatars.discourse-cdn.com/v4/letter/r/7ab992/32.png) [@Roman\_Bolshakov](https://forum.ansible.com/u/Roman_Bolshakov)\
**Post date:** [July 8, 2021, 7:32pm UTC](https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481/1 "2021-07-08T19:32:25Z")

</div>

Hi all,

I'm working on a guestfs [1] connection plugin and seeking for a design  
advice.

libguestfs provides a set of command line tools that can be used to  
operate on virtual machine disk images and modify its contents.

For every task, the connection plugin:

&nbsp;&nbsp;1. Starts guestfish in --remote mode on a remote host over ssh and adds  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a disk (passed as a parameter to guestfs connection).

&nbsp;&nbsp;2. Runs supermin applicance [2][3]. It typically takes two to four  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seconds to spin up the applicance VM.

&nbsp;&nbsp;3. Mounts root fs partition (partition number is passed as a parameter to the  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guestfs connection)

&nbsp;&nbsp;4. Performs the task:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some implementation details:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- put\_file/fetch\_file is implemented using copy-in/copy-out [4][5]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guestfish commands

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- there's intermediate copy to/from remote host over ssh (to enable  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remote guestfs operation)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- exec\_command is implemented using "command" [6] guestfish command

&nbsp;&nbsp;5. Stops supermin appliance/a guestfish instance

Here's an example how it looks in a playbook:

&nbsp;&nbsp;&nbsp;&nbsp;- name: Add disk image to inventory  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add\_host:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: "{{ vm\_disk\_path }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_host: "{{ ansible\_host }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_connection: guestfs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_guestfs\_disk\_path: "{{ vm\_disk\_path }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_guestfs\_root\_partnum: "{{ root\_partnum }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed\_when: false

&nbsp;&nbsp;&nbsp;&nbsp;- name: Test guestfs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ping:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate\_to: "{{ vm\_disk\_path }}"

The ping command is performed using the execution environment from  
within the disk image on remote host:

&nbsp;&nbsp;TASK [Add disk image to inventory] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;ok: [remote-hypervisor]

&nbsp;&nbsp;TASK [Test guestfs] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;ok: [remote-hypervisor -\> /home/user/test.qcow2]

Likewise, a role can be delegated to the guestfs disk image.

The problem is that \_connect() spins up supermin VM on every task and  
stops afterwards. So, it takes at least two seconds only to perform  
\_connect(). Obviously it's very slow for plays with a lot of tasks and  
roles.

The question is how it can be optimized to avoid costly \_connect caused  
by appliance start?

I think of the following approaches:

1. Introduce a separate module that starts up or stops guestfs appliance  
&nbsp;&nbsp;&nbsp;and remove the action from the connection plugin

&nbsp;&nbsp;&nbsp;Pros: similar to ldx, docker, virt connections that have separate  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tasks for start/stop of the conntainers/VMs  
&nbsp;&nbsp;&nbsp;Cons: extra tasks need to be added for every play to start/stop guestfish

2. Add a separate meta task that closes the connection and a connection  
&nbsp;&nbsp;&nbsp;flag that effectively doesn't stop guestfish after the first task

&nbsp;&nbsp;&nbsp;The meta task 'close\_connection' can either be added as a separate  
&nbsp;&nbsp;&nbsp;module or as an extension to builtin meta module.

&nbsp;&nbsp;&nbsp;Cons:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- it looks flaky - guestfish might be unintentionally left running  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;somewhere in the middle of the play in case of an error. Extra  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;care (i.e. blocks) might be needed to always close guestfs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.

3. Extend persistent connection framework [7]. There might be new mode  
&nbsp;&nbsp;&nbsp;that keeps connection open for a sequence of tasks running on the  
&nbsp;&nbsp;&nbsp;same connection without an explicit timeout. So this mode looks like  
&nbsp;&nbsp;&nbsp;this:

&nbsp;&nbsp;&nbsp;task 1 on a guestfs connection - implicit \_connect  
&nbsp;&nbsp;&nbsp;task 2 on the same guestfs connection - no \_connect  
&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;task n on the same guestfs connection - no \_connect  
&nbsp;&nbsp;&nbsp;task z on any other connection or the end of play - implicit close()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of the guestfs connection

&nbsp;&nbsp;&nbsp;Pros: reliable, tidy - no need of extra tasks/blocks  
&nbsp;&nbsp;&nbsp;Cons:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- need to modify ansible core - task\_executor, etc 🙂  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- not sure if ansible is able persist connections across the roles

Looking forward to a feedback on what of the approaches is the most  
solid/sane.

1. [https://libguestfs.org](https://libguestfs.org)  
2. [https://libguestfs.org/guestfs-internals.1.html#architecture](https://libguestfs.org/guestfs-internals.1.html#architecture)  
3. [https://libguestfs.org/supermin.1.html](https://libguestfs.org/supermin.1.html)  
4. [https://libguestfs.org/guestfish.1.html#copy-in](https://libguestfs.org/guestfish.1.html#copy-in)  
5. [https://libguestfs.org/guestfish.1.html#copy-out](https://libguestfs.org/guestfish.1.html#copy-out)  
6. [https://libguestfs.org/guestfish.1.html#command](https://libguestfs.org/guestfish.1.html#command)  
7. [https://www.ansible.com/deep-dive-with-network-connection-plugins](https://www.ansible.com/deep-dive-with-network-connection-plugins)

Thanks,  
Roman

---

<div class="post-metadata">

**Author:** ![Roman\_Bolshakov](https://avatars.discourse-cdn.com/v4/letter/r/7ab992/32.png) [@Roman\_Bolshakov](https://forum.ansible.com/u/Roman_Bolshakov)\
**Post date:** [July 9, 2021, 9:52am UTC](https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481/2 "2021-07-09T09:52:22Z")

</div>

> \> Hi all,  
> \>  
> \> I'm working on a guestfs [1] connection plugin and seeking for a design  
> \> advice.  
> \>  
> \> libguestfs provides a set of command line tools that can be used to  
> \> operate on virtual machine disk images and modify its contents.  
> \>  
> \> For every task, the connection plugin:  
> \>  
> \> 1. Starts guestfish in --remote mode on a remote host over ssh and adds  
> \> a disk (passed as a parameter to guestfs connection).  
> \>  
> \> 2. Runs supermin applicance [2][3]. It typically takes two to four  
> \> seconds to spin up the applicance VM.
> 
> Depending on the target, simply running something like
> 
> &nbsp;&nbsp;guestfish -a /dev/null run
> 
> will create and cache an appliance in /var/tmp/.guestfs-$UID/ (and  
> it's safe if two processes run in parallel). Once the appliance is  
> cached new libguestfs instances will use the cached appliance without  
> any delay.
> 
> Doesn't this mechanism work?

Hi Rich,

Appliance caching indeed works. If I remove it, it takes around 20  
seconds to rebuild new appliance. Then it's used for new libguestfs  
instances.

I was rather talking about the inherent latency caused by instance/VM  
start. In the current implementation of guestfs plugin, the appliance is  
started before each task and stopped afterwards.

My intent is to find a way to run multiple ansible tasks on the same  
libguestfs instance. That saves up to 2-4 seconds per task.

> Nevertheless for virt-v2v we have something similar because virt-v2v  
> is a long-running process that we want to start and query status from.  
> My colleague wrote a wrapper (essentially a sort of daemon) which  
> manages virt-v2v, and I guess may be useful to look at:
> 
> [https://github.com/ManageIQ/manageiq-v2v-conversion\_host/tree/master/wrapper](https://github.com/ManageIQ/manageiq-v2v-conversion_host/tree/master/wrapper)

I'm doing something similar, except I'm running guestfish ---remote  
under nohup, remember PID and then interact with it. If we find a way to  
pass PID associated to a connneciton from task to task in ansible and  
kill it when it's no longer needed (to be able to start a real VM with  
the disk image) then we can achieve very fast and reliable task  
execution on the disk images.

Thanks,  
Roman

---

<div class="post-metadata">

**Author:** ![Roman\_Bolshakov](https://avatars.discourse-cdn.com/v4/letter/r/7ab992/32.png) [@Roman\_Bolshakov](https://forum.ansible.com/u/Roman_Bolshakov)\
**Post date:** [July 9, 2021, 10:43am UTC](https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481/3 "2021-07-09T10:43:14Z")

</div>

> \> \> \> Hi all,  
> \> \> \>  
> \> \> \> I'm working on a guestfs [1] connection plugin and seeking for a design  
> \> \> \> advice.  
> \> \> \>  
> \> \> \> libguestfs provides a set of command line tools that can be used to  
> \> \> \> operate on virtual machine disk images and modify its contents.  
> \> \> \>  
> \> \> \> For every task, the connection plugin:  
> \> \> \>  
> \> \> \> 1. Starts guestfish in --remote mode on a remote host over ssh and adds  
> \> \> \> a disk (passed as a parameter to guestfs connection).  
> \> \> \>  
> \> \> \> 2. Runs supermin applicance [2][3]. It typically takes two to four  
> \> \> \> seconds to spin up the applicance VM.  
> \> \>  
> \> \> Depending on the target, simply running something like  
> \> \>  
> \> \> guestfish -a /dev/null run  
> \> \>  
> \> \> will create and cache an appliance in /var/tmp/.guestfs-$UID/ (and  
> \> \> it's safe if two processes run in parallel). Once the appliance is  
> \> \> cached new libguestfs instances will use the cached appliance without  
> \> \> any delay.  
> \> \>  
> \> \> Doesn't this mechanism work?  
> \>  
> \> Hi Rich,  
> \>  
> \> Appliance caching indeed works. If I remove it, it takes around 20  
> \> seconds to rebuild new appliance. Then it's used for new libguestfs  
> \> instances.  
> \>  
> \> I was rather talking about the inherent latency caused by instance/VM  
> \> start. In the current implementation of guestfs plugin, the appliance is  
> \> started before each task and stopped afterwards.
> 
> Oh I see, yes that's right.
> 
> \> My intent is to find a way to run multiple ansible tasks on the same  
> \> libguestfs instance. That saves up to 2-4 seconds per task.
> 
> You shouldn't really reuse the same appliance across trust boundaries  
> (eg. if processing two disks which are owned by different tenants of  
> your cloud), since it means one tenant would be able to interfere with  
> or extract secrets from the other tenant. The 2-4 seconds is the  
> price you pay here I'm afraid :-/
> 
> If all disks you are processing are owned by the same tenant then  
> there's no worry about security.

Right, I'm only trying to optimize access to the same disk by a set of  
consecutive ansible tasks in the same playbook (and typically belonging  
to a VM owned by a specific user) to ensure the trust boundaries.

Thanks,  
Roman

---

<div class="post-metadata">

**Author:** ![Roman\_Bolshakov](https://avatars.discourse-cdn.com/v4/letter/r/7ab992/32.png) [@Roman\_Bolshakov](https://forum.ansible.com/u/Roman_Bolshakov)\
**Post date:** [July 12, 2021, 6:15pm UTC](https://forum.ansible.com/t/connection-plugin-with-slow-connect/35481/4 "2021-07-12T18:15:27Z")

</div>

> Hi all,
> 
> I'm working on a guestfs [1] connection plugin and seeking for a design  
> advice.
> 
> libguestfs provides a set of command line tools that can be used to  
> operate on virtual machine disk images and modify its contents.
> 
> For every task, the connection plugin:
> 
> &nbsp;&nbsp;1. Starts guestfish in --remote mode on a remote host over ssh and adds  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a disk (passed as a parameter to guestfs connection).
> 
> &nbsp;&nbsp;2. Runs supermin applicance [2][3]. It typically takes two to four  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seconds to spin up the applicance VM.
> 
> &nbsp;&nbsp;3. Mounts root fs partition (partition number is passed as a parameter to the  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guestfs connection)
> 
> &nbsp;&nbsp;4. Performs the task:
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some implementation details:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- put\_file/fetch\_file is implemented using copy-in/copy-out [4][5]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guestfish commands
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- there's intermediate copy to/from remote host over ssh (to enable  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remote guestfs operation)
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- exec\_command is implemented using "command" [6] guestfish command
> 
> &nbsp;&nbsp;5. Stops supermin appliance/a guestfish instance
> 
> Here's an example how it looks in a playbook:
> 
> &nbsp;&nbsp;&nbsp;&nbsp;- name: Add disk image to inventory  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add\_host:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: "{{ vm\_disk\_path }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_host: "{{ ansible\_host }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_connection: guestfs  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_guestfs\_disk\_path: "{{ vm\_disk\_path }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_guestfs\_root\_partnum: "{{ root\_partnum }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed\_when: false
> 
> &nbsp;&nbsp;&nbsp;&nbsp;- name: Test guestfs  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ping:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate\_to: "{{ vm\_disk\_path }}"
> 
> The ping command is performed using the execution environment from  
> within the disk image on remote host:
> 
> &nbsp;&nbsp;TASK [Add disk image to inventory] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
> &nbsp;&nbsp;ok: [remote-hypervisor]
> 
> &nbsp;&nbsp;TASK [Test guestfs] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
> &nbsp;&nbsp;ok: [remote-hypervisor -\> /home/user/test.qcow2]
> 
> Likewise, a role can be delegated to the guestfs disk image.
> 
> The problem is that \_connect() spins up supermin VM on every task and  
> stops afterwards. So, it takes at least two seconds only to perform  
> \_connect(). Obviously it's very slow for plays with a lot of tasks and  
> roles.
> 
> The question is how it can be optimized to avoid costly \_connect caused  
> by appliance start?
> 
> I think of the following approaches:
> 
> 1. Introduce a separate module that starts up or stops guestfs appliance  
> &nbsp;&nbsp;&nbsp;and remove the action from the connection plugin
> 
> &nbsp;&nbsp;&nbsp;Pros: similar to ldx, docker, virt connections that have separate  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tasks for start/stop of the conntainers/VMs  
> &nbsp;&nbsp;&nbsp;Cons: extra tasks need to be added for every play to start/stop guestfish

Brian Coca from Ansible team told on IRC that this is the way to go.

I'm all set,  
Thanks!
