I want to run a specific command on an ansible group. However this command (device upgrade) makes this device unavailable, also it makes child devices unavailable as well.
Is it somehow possible in Ansible to define a depedency list, ie. device topology and run commands in that order, and more importantly, do not fail because another parent device become unavailable?
Practically: R1 -> SW1 -> SW2 : Upgrade should start from SW2, and then SW1. R1 can't be updated until at least SW1 is up, because uplink is received from SW1, so it should wait for SW1.
Ps.: I have read all other threads on this, I need to do this on multiple group of devices, so creating specific playbooks with hard coded groups is not that ideal.
There are at least two relatively simple ways to achieve that. One would look a bit kludgy but it's both fast and safe, another is more elegant, but contains some caveats.
The most straightforward one would be to organize your inventory so that the hierarchy is reflected in the group names. If we consider the deepness of the dependency limited, we can simply have a number of plays that corresponds to the maximum deepness (see the note on the hardcoding below). If we define
level_1as the highest one (R1in your example), our inventory will be "open-ended" so we can refine as many levels as we want. We can also skip some levels and/or make them empty. Of course, you can use more meaningful names instead of level numbers:Before commenting on hardcoding: yes, but this makes perfect sense as Ansible runs the tasks within the group in parallel, and the plays are executed sequentially. If the hierarchy is defined and it's limited, I'd recommend this solution.
However, we can try a different approach. Ansible offers several options to
orderthe execution based on inventory. Note that while there is an option to use the order in which the hosts are defined, it's not guaranteed in general. It usually works for simple cases, though, but usingsortedorreverse_sortedorder that relies on host names in more reliable. So, instead of defing generic levels, we can define the sets of the dependent devices:Of course, these examples are only intended to show the options of ordering, and in real life
wait_forwill most likely be required. Besides, you should be aware of some nuances:SW[150:155]), Ansible will add some of the subsequent hosts to the batch so the "dependency" order may be violated.An optimal solution could be a combination of these approaches, where the inventory would contain a number of upper-level groups to control the devices like
SW2,SW3and so on in parallel, and the bottom-level would be upgrades one by one.In theory, it is also possible to define the hierarchy level as a group/host variable as well. But one will need to implement an extremely complex logic to control the execution flow, and the built-in parallelism features could be (and most likely - will be) lost. It's not possible to define the batch size as an inventory variable and we can't add the plays to the playbook dynamically.
serialcan be set fromhostvarsbut since we don't have theinventory_hostnameat that point it's useless in this case, not to say we have to calculate the batch size first. I tried to implement it and I wouldn't recommend to repeat the attempt :)