I can agree on this. For example, imperative stuff like power management is already split into separate module vmware_guest_powerstate
. The explanation I was given by Abhijeet Kasurde on why power management was also kept in vmware_guest
is to not break compatibility for people who use this functionality in vmware_guest
.
Here are some scenarios that are problematic. It mostly boils down to being hard to maintain idempotency if vmware_guest
is to be replaced by some role.
Scenario 1 - VM provisioning (e.g. from template) and disk management is split into separate modules:
The problematic thing here is that VM comes with at least one disk (possibly multiple) in a template itself. Imagine your module for VM provisioning does not have any disk management at all. Once you provision a VM, you are expected to call another module to add additional disks and/or to manage template provided disk. Imagine you have multiple data stores and you keep the template on one but want some template provisioned disks to be on another data store and additional disks on yet another data store. If you provision a VM in this scenario, template provided disks will have to end up either on the same data store as template (if you have 0 disk management functionality in a module) or they will all end up on some other data store but still the same for all template provided disks. Once disk management module kicks in, it will have to move some template provided disks to desired data stores and, of course, add additional disks. So there could be some unnecessary disk migration involved. I’m not so familiar with vCenter API but it’s reasonable to assume that you can specify up front where each template provided disk will end up during VM provisioning without the need to move the disks afterwords. In other words, to avoid disk migration, you have to have some disk management functionality inside VM provisioning module itself and, if that is the case, why not let the module do all the disk management required?
Scenario 2 - VM provisioning (e.g. from template) and OS customization is split into separate modules:
You want to provision a VM and you rely on OS customization for network configuration (and also reconfiguration). If you provision a VM from scratch then steps are:
- Provision VM from template (module 1)
- Apply OS customization (module 2)
- Boot the VM (module 3)
OS customization will be done on first boot.
Now imagine you want to recustomize your already provisioned VM by just changing default GW of the primary network interface and running the same role/play. Now the steps look like this:
- Is OS recustomization requested? (some change happened?)
- Apply OS customization (module 2)
- Is VM powered on or off?
- If powered off, should I power on the VM to really apply OS customization and shut it down after? (module 3)
- If powered on, should I reboot the VM to really apply OS customization? (module 3)
- Wait for reconfiguration to happen
- Validate reconfiguration
If you want to idempotently support both cases (VM from scratch + reconfiguration) and always only describe the final desired state of the VM instead of doing imperative actions on a VM, then it becomes so much harder to do in Ansible tasks compared to Python code inside a module. Module can in general track VM state more efficiently compared to Ansible tasks.
What kills these scenarios even more are API quirks that possibly don’t present themselves when using separate modules but require workarounds when multiple modules are called one after the other.
Offtopic:
What happened with the original VMware WG mentioned here:
especially the leads and VMware and RedHat employees? Can they provide any insight into this problem?