Open m-kratochvil opened 1 year ago
Hi @m-kratochvil,
I tested the following playbook with f5networks.f5_modules version 1.26.0 on device using BIG-IP v17.1 with success.
- hosts: all
collections:
- f5networks.f5_modules
connection: local
vars:
provider:
server: "X.X.X.X"
user: "admin"
password: "mysecretpassword"
server_port: 443
validate_certs: no
no_f5_teem: yes
tasks:
- name: Install AS3
f5networks.f5_modules.bigip_lx_package:
package: f5-appsvcs-3.47.0-8.noarch.rpm
provider: "{{ provider }}"
delegate_to: localhost
Hi @pgouband thanks for the feedback. I believe it's working for you because you are using the connection: local
and delegate_to: localhost
in your playbook. I don't use these options, I execute the module on the Big-IP itself. Can you try the same and see if it works that way for you? I noticed you are using a bit newer collection version, I'll see if I can upgrade and re-test.
Hi @m-kratochvil,
Can you check you are using python3 because the error looks like python2 is used?
I am using python 3.10.6
on the ansible controller. I initially also thought it may be an issue with python2 because that is what runs on the Big-IP but as this module was executing fine recently against TMOS version 15.1.3, it should not be a problem against TMOS version 17.1.0.1 where the same python version (2.7
) is used.
I think the problem is indeed that you try to run the task on the BIGIP itself. The python on the BIGIP is quite limited, and is probably missing the http.client. Easiest way to fix the issue is to add the delegate_to: localhost to the task, as adding python modules to BIGIP is not a good idea. I had the same issue on bigip_routedomain module because I forgot to add delegate_to... Also, all example tasks on https://docs.ansible.com/ansible/latest/collections/f5networks/f5_modules/bigip_lx_package_module.html use the delegate_to: localhost.
Hi @m-kratochvil,
Can you test adding delegate_to?
When you said "I execute the module on the Big-IP itself", that means you have installed ansible on the device?
Appreciate your feedback @jussisjostrom @pgouband
When you said "I execute the module on the Big-IP itself", that means you have installed ansible on the device?
No, that was just poor choice of words, I meant I execute the module without delegate_to
If I add delegate_to: localhost
, the module fails with "The specified LX package was not found at
because the module is looking for the rpm package on the Ansible controller.
I understand your suggestion to run with delegate_to
, since it is the standard way to run the imperative f5 modules.
But the bigip_lx_package
is an exception. I asked for the option to run it without delegate_to
back in 2020, it was implemented via #1717 and was working fine, without any issue, since 2020 until now.
The obvious question is what has recently changed - and nothing comes to my mind, we run same ansible version, same python version on the controller, same f5 collection version. The playbook fails against both our TMOS versions 15.1.3 and 17.1.0.1
It may be worth mentioning that there was already an issue (#2176) with running this module without delegate_to
which was resolved by adding no_f5_teem: True
to the provider
dict.
I am really out of any ideas why this has suddenly started to fail.
Hi @m-kratochvil,
Adding delegate_to is impossible in your environment?
@pgouband It is technically possible but we really want to avoid that. Reason is that we currently store the AS3 rpm packages in central, controlled storage and each Big-IP downloads it from there during installation.
If we use delegate_to
, every user will have to download the package to their local ansible environment, which we wanted to avoid, for I think obvious reasons..
Hi @m-kratochvil,
The answer is to use delegate_to and the file needs to be on the ansible client. What was actually implemented for the 1717 is the retain_package_file option which specifies whether the package file should be deleted or not after successful installation.
Hi @pgouband the fix/feature for Issue 1717 was implemented via https://github.com/F5Networks/f5-ansible/commit/7257354e6952a4b2fdbdaa3eabb159f352cd2bba and if you look in the diff at a file test/integration/targets/bigip_lx_package/tasks/issue-01717.yaml
, you can clearly see that the bigip_lx_package
module is used without delegate_to
. I believe it works via the function check_file_exists_on_device
.
This is exactly the way we used the module, and again, it worked fine until around Sept 2023.
The answer is to use delegate_to and the file needs to be on the ansible client.
That is for sure one option to install AS3 with Ansible, and then there is the other option, without having to upload the AS3 package from the ansible client, and that's what I am after, as it is much better fit to our environment. We are a team of 20 people, managing well over 500 Big-IPs, it is way more practical and safe for use to use central storage for such files.
I hope it clarifies things, and thanks for looking into it.
Hi @m-kratochvil , the test/integration/targets/bigip_lx_package/tasks/issue-01717.yaml
is part of a role for which the entry point is test/integration/bigip_lx_package.yaml
, there you can see connection: local
on line 24, which does the same job as delegate_to
.
Hi @urohit011 thanks for the hint, I have missed that. But I can also see that in test/integration/targets/bigip_lx_package/tasks/issue-01717.yaml
the AS3 package is fetched from GitHub, which means the sub-sequent bigip_lx_package
module is not supposed to look for it on the ansible controller but instead it should look for it in the target Big-IP's local /var/tmp/
directory.
If connection: local
is the same as delegate_to
, then the module will search for the package on the ansible controller.
I'm not sure I understand then how this integration test is working, or perhaps connection: local
is not the same as delegate_to
..?
Anyway, I stress again, it was working for us fine for several years, the question is why it suddenly stopped. Plus, it actually still works without the connection: local
or delegate_to
, if I make the adjustments described in my initial post.
I realized I didn't share the actual playbook we have used, so here it is:
Role entry point:
- name: AS3 package management.
hosts: bigips
gather_facts: false
vars_files:
- vault
- global_vars
tasks:
- name: Call the role to manage the AS3 package.
ansible.builtin.include_role:
name: as3
Role as3
- tasks/main.yaml
:
- name: Download and install AS3.
block:
- name: Download the AS3 package from Swift object storage.
ansible.builtin.get_url:
backup: no
dest: /var/config/rest/downloads/
force: no
url: "https://storage.swift.abc/loadbalancer/f5-appsvcs-3.5.0-3.noarch.rpm"
use_proxy: no
validate_certs: no
- name: Install the downloaded AS3 package.
f5networks.f5_modules.bigip_lx_package:
provider: "{{ provider }}"
package: "/var/config/rest/downloads/f5-appsvcs-3.5.0-3.noarch.rpm"
retain_package_file: yes
In the tasks/main.yaml
you just shared above the first task is doing the job of downloading the AS3 package from Swift storage to the controller and it is using the built-in ansible module get_url
. So the bigip_lx_package
never does the job of transferring RPM package from swift storage to BIGIP box. Second thing is the modulenotfounderror
could be fixed if we explicitly set the ansible_pathon_interpreter
to python3 to make sure you're not using python2.
@urohit011 I respectfully disagree. The get_url
module downloads the file from Swift to the Big-IP, not to my ansible controller (for that I would have to use connection: local
or delegate_to: localhost
with the task). This is my understanding of how the ansible modules work, and for get_url
module, even the docu suggest this:
The remote server must have direct access to the remote resource.
Regarding ansible_python_interpreter
, I have tried that. Since there is no connection: local
or delegate_to: localhost
used, ansible always uses python 2.7 as it executes on the Big-IP, and that is the default python version there.
As far as my ansible controller, I don't have python 2 installed (but that should not be important anyway in context of this issue).
@m-kratochvil , yes I agree that get_url
will download the rpm on the bigip box, I was wrong earlier. The workaround I can suggest is use get_url
to download the rpm on the controller and and use bigip_lx_package
to upload it and add another task to delete the rpm from the controller. The reason I suggest this is, bigip_lx_package
should run with local or localhost, if it runs on the box you'll get modulenotfound error for the packaging
module.
I have tested my original playbook with various older version of the f5networks.f5_modules
collection and I can confirm that collection version 1.22.0
is where the failure was introduced. On collection versions prior to that the playbook works fine.
It would perhaps suggest that support for python2.7 was dropped in that collection version, can anybody confirm? The release notes of collection version 1.22.0
do not list any such change.
For now, I downgraded to collection version 1.21.0
and everything is working fine for me. I admit I could've thought of this test earlier..
Same issue here when upgrading to 1.25.1
Ended up adding connetion:local
to the playbook. Note that the Anisble host must have RPM installed. From the module docs:
Requires the RPM tool be installed on the host. This can be accomplished in different ways on each platform. On Debian based systems with apt; apt-get install rpm. On Mac with brew; brew install rpm. This command is already present on RedHat based systems
COMPONENT NAME
f5networks.f5_modules.bigip_lx_package
Environment
ANSIBLE VERSION
BIGIP VERSION
OS / ENVIRONMENT
Ubuntu 22.04 VM Python 3.10.6
SUMMARY
Playbook to install AS3 plugin used to work, suddenly it fails. Other playbooks/modules might be affected, I only ran into this issue with the particular module specified below.
STEPS TO REPRODUCE
Run a playbook to install an AS3 package, using following module:
EXPECTED RESULTS
Playbook should run and complete without failure, installing the AS3 package.
ACTUAL RESULTS
The playbook failed with following error:
To resolve on short-term, I went into the following file:
and removed references to
http.client
Then the playbook failed with different error:
I went into the following file:
and removed references to
packaging.version
After that the playbook executed correctly.