Unattended Python3 installation on Centos and RHEL VMs

If you are a Centos or RHEL Linux administrator or a developer using these OS platform then you know that the python version which ships with the original OS build image is 2.7.X

To do unattended / automated installation of Python 3.x and additional packages on multiple Linux nodes; use the below Ansible Playbook.

  # Python 3.6.x and packages unattended installation playbook
  # Make sure Repos are configured properly before running this playbook
  # Check internet connectivity and sufficient disk space on managed nodes
  - name: Install Python 3 and packages along with dependencies on Centos/Redhat
    hosts: all
    gather_facts: no
    become: true

      # Task1 - Install the dependent packages to build Python 3.6 from source
      - name: Install dependencies before downloading python
          name: "{{ item }}"
          state: latest
          - zlib-devel
          - gcc
          - openssl-devel
          - bzip2-devel
          - python-setuptools

      # Task2 - Check if Python ver 3.6 exists on the managed nodes
      - name: Check Python 3.6 exists or not
          /usr/local/bin/python3.6 -V
        register: output
        ignore_errors: yes
        changed_when: false
      - debug:
          var: output

      # Task3 - Get Python source file from the internet (3.6.8)
      - name: Copy Python source archive file only if not installed already from the internet
          url: https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tgz
          dest: /usr/src
          mode: 0644
        register: download
        ignore_errors: yes

      # Task4 - Copy manually already downloaded file if Task3 failed
      - name: Copy of the manually already downloaded file if Task3 failed due to internet connectivity issue
          src: "Python-3.6.8.tgz"
          dest: /usr/src
          mode: 0644
        when: output.rc > 0 and download.rc > 0
        ignore_errors: yes

      # Task5 - Check file downloaded to managed node or not alternatively
      # unarchive can be used to copy and unzip on managed nodes directly
      - name: Check file downloaded successfully or not
          path: /usr/src/Python-3.6.8.tgz
        register: python_archive

      # Task6 - Unarchive the Python source file to destination /usr/src
      - name: Unarchive Python source archive file
          src: /usr/src/Python-3.6.8.tgz
          dest: /usr/src
          remote_src: yes
        when: python_archive.stat.exists

      # Task7 - Using stat module to check unarchive was success or not
      - name: Check python unzipped to folder successfully
          path: /usr/src/Python-3.6.8
        register: python_dir

      # Task8 - Command module is not idempotent to skip this task added
      # when condition to check if Python exists or not before install
      - name: Install Python by building it from source
        command: chdir=/usr/src/Python-3.6.8 {{ item }}
          - ./configure
          - make altinstall
        when: python_dir.stat.exists == true and output.rc > 0

      # Task9 - After building python from source check whether its installed and available in the right path
      - name: Check Python installed successfully or not
          path: /usr/local/bin/python3.6
        register: check
      - debug:
          msg: "Python3.6 installed installed successfully"
        when: check.stat.exists

      # Task10 - Install Python packages using pip
      - name: pip
          name: "{{ item }}"
          executable: /usr/local/bin/pip3.6
          - paramiko
          - netmiko
          - requests
          - xlrd
          - xlsxwriter
          - slacker
          - pandas
          - mysql-connector
          - Flask
          - Flask-Mail
          - duallog
          - emails
          - pymysql
          - sqlalchemy
        ignore_errors: yes
        when: check.stat.exists
        register: pip_install
          - pip
      - debug:
          var: pip_install
# Playbook End #

Note: I’m using Ansible 2.3 so you may use loop or list method instead of item for installing packages using yum module.

Explanation of the above playbook:

There are 10 tasks in the above playbooks.

  • Task 1 – Download and install dependency packages using YUM module
  • Task 2 – Check Python 3 already installed or not using SHELL and REGISTER modules
  • Task 3 – Download Python3 source tarball from Python FTP/ Hosting site using GET_URL module. Ignore errors if unable to download.
  • Task 4 – If Step 3 fails use the already downloaded source tarball located in Control node and copy to manage nodes using COPY module
  • Task 5 – Check Source tarball file downloaded successfully or not using STAT and DEBUG module. Both these modules are used multiple times along with WHEN conditional validation
  • Task 6 – Unarchive the source tarball into /usr/src directory using UNARCHIVE module. We can use UNARCHIVE to do both copy and extract but here Task5 is doing the copy part.
  • Task 7 – Check unarchive succeeded or not using STAT module
  • Task 8 – Using the Python Source files configure and build the Python using SHELL module
  • Task 9 – Check Python build succeeded or not and in the right directory path using STAT module
  • Task10 – Install additional Python packages {add your list of packages if not there already) using PIP module only when Python3 successfully installed.

Thanks for stopping by, please share your comments and ideas to improve this blog. Keep watching for more use cases using Ansible and Python automation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s