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
    tasks:

      # Task1 - Install the dependent packages to build Python 3.6 from source
      - name: Install dependencies before downloading python
        yum:
          name: "{{ item }}"
          state: latest
        with_items:
          - 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
        shell:
          /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
        get_url:
          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
        copy:
          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
        stat:
          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
        unarchive:
          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
        stat:
          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 }}
        with_items:
          - ./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
        stat:
          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
        pip:
          name: "{{ item }}"
          executable: /usr/local/bin/pip3.6
        with_items:
          - 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
        tags:
          - 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 )

Google photo

You are commenting using your Google 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