From e806082972f6bb2e16ca2489ce8e992f36e3bb98 Mon Sep 17 00:00:00 2001 From: oEscal Date: Thu, 26 Aug 2021 20:23:54 +0000 Subject: [PATCH] deployment on Edge Controller and Edge Nodes with Ubuntu 20.04 --- .gitignore | 1 + .../controller_group/10-default.yml | 3 + .../group_vars/edgenode_group/10-default.yml | 6 + .../edgenode_vca_group/10-default.yml | 6 + network_edge_cleanup.yml | 3 +- roles/infrastructure/docker/tasks/main.yml | 145 +++++++++++++++++- .../infrastructure/docker/tasks/uninstall.yml | 13 +- .../docker/templates/daemon.json.j2 | 4 + roles/infrastructure/grub/tasks/main.yml | 21 ++- .../os_setup/tasks/add_yum_excludes.yml | 1 + .../tasks/change_default_sh_ubuntu.yml | 11 ++ .../os_setup/tasks/disable_fingerprint.yml | 27 ++-- .../os_setup/tasks/disable_selinux.yml | 2 + .../tasks/install_base_os_packages.yml | 45 +++++- .../tasks/install_epel_repository.yml | 4 +- .../tasks/install_firewalld_ubuntu.yml | 9 ++ roles/infrastructure/os_setup/tasks/main.yml | 4 +- .../reinstall_python_requests_if_needed.yml | 14 +- .../tasks/set_ssl_certificates_ubuntu.yml | 7 + .../infrastructure/ptp/common/tasks/main.yml | 2 + .../cni/calico/controlplane/tasks/main.yml | 2 + .../kubernetes/cni/calico/node/tasks/main.yml | 2 + .../cni/flannel/controlplane/tasks/main.yml | 2 + .../cni/flannel/node/tasks/main.yml | 2 + .../cni/kubeovn/controlplane/tasks/main.yml | 2 + .../cni/kubeovn/node/tasks/main.yml | 2 + .../cni/ovn4nfv/controlplane/tasks/main.yml | 2 + .../cni/weavenet/controlplane/tasks/main.yml | 2 + .../cni/weavenet/node/tasks/main.yml | 2 + roles/kubernetes/common/defaults/main.yml | 7 + roles/kubernetes/common/tasks/main.yml | 104 ++++++++----- roles/kubernetes/common/tasks/uninstall.yml | 51 ++++-- roles/kubernetes/dashboard/tasks/main.yml | 2 + roles/kubernetes/nfd/tasks/nfd.yml | 11 +- roles/kubernetes/node/defaults/main.yml | 2 +- .../node/tasks/customize_kubelet.yml | 7 + roles/telemetry/collectd/node/tasks/main.yml | 2 + roles/telemetry/grafana/tasks/main.yml | 14 +- .../telemetry/pcm/controlplane/tasks/main.yml | 2 + roles/telemetry/pcm/node/tasks/main.yml | 2 + roles/telemetry/prometheus/tasks/main.yml | 14 +- scripts/ansible-precheck.sh | 63 +++++--- 42 files changed, 524 insertions(+), 103 deletions(-) create mode 100644 roles/infrastructure/os_setup/tasks/change_default_sh_ubuntu.yml create mode 100644 roles/infrastructure/os_setup/tasks/install_firewalld_ubuntu.yml create mode 100644 roles/infrastructure/os_setup/tasks/set_ssl_certificates_ubuntu.yml diff --git a/.gitignore b/.gitignore index f89bd7ff..470f9e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.pyc /inventory/default/group_vars/*/30_*_flavor.yml /inventory/automated/ +*.log diff --git a/inventory/default/group_vars/controller_group/10-default.yml b/inventory/default/group_vars/controller_group/10-default.yml index 340baa45..571ba2c3 100644 --- a/inventory/default/group_vars/controller_group/10-default.yml +++ b/inventory/default/group_vars/controller_group/10-default.yml @@ -80,6 +80,9 @@ os_yum_base_packages: "git2u-all,jq,vim-common,curl,yum-utils,python2-pip,python3,wget,bridge-utils,rsync,\ device-mapper-persistent-data,lvm2,moreutils,gcc,python-devel,createrepo,psmisc,bash-completion,patch" +os_ubuntu_base_packages: + "jq,vim-common,curl,python3,wget,bridge-utils,rsync,lvm2,moreutils,gcc,python-dev-is-python2,psmisc,bash-completion,patch" + ## URLs to docker images saved with `docker save : | gzip > .tar.gz` that are going to be preloaded after docker setup docker_images: [] diff --git a/inventory/default/group_vars/edgenode_group/10-default.yml b/inventory/default/group_vars/edgenode_group/10-default.yml index 9017de05..4386780b 100644 --- a/inventory/default/group_vars/edgenode_group/10-default.yml +++ b/inventory/default/group_vars/edgenode_group/10-default.yml @@ -83,6 +83,12 @@ os_yum_base_packages: moreutils,jq,python-devel,createrepo,psmisc,bash-completion,rsync,patch,libselinux-python,libselinux-python3" _os_yum_exclude_rpm_packages: "exclude=kernel-3* kernel-rt* kernel-rt-kvm* kernel-rt-devel*" +os_ubuntu_base_packages: + "vim-common,curl,lvm2,python3,wget,bridge-utils,libboost-all-dev,libpcre3,libpcre3-dev,zlib1g-dev,libglib2.0-dev,\ + autoconf,automake,libtool,flex,bison,cmake,pciutils,python-websocket,libjsoncpp-dev,libfcgi-dev,libhiredis-dev,libnuma-dev,\ + build-essential,psmisc,python-httplib2,libpixman-1-dev,moreutils,jq,python-dev-is-python2,psmisc,bash-completion,rsync,\ + patch" + # URLs to docker images saved with `docker save : | gzip > .tar.gz` that are going to be preloaded after docker setup docker_images: [] diff --git a/inventory/default/group_vars/edgenode_vca_group/10-default.yml b/inventory/default/group_vars/edgenode_vca_group/10-default.yml index 8ed35b21..098dac3c 100644 --- a/inventory/default/group_vars/edgenode_vca_group/10-default.yml +++ b/inventory/default/group_vars/edgenode_vca_group/10-default.yml @@ -10,6 +10,12 @@ os_yum_base_packages: _os_yum_exclude_rpm_packages: "exclude=kernel-3* kernel-rt* kernel-rt-kvm* kernel-rt-devel*" os_remove_yum_plugins: true +os_ubuntu_base_packages: + "vim-common,curl,lvm2,wget,bridge-utils,libboost-all-dev,libpcre3,libpcre3-dev,zlib1g-dev,libglib2.0-dev,\ + autoconf,automake,libtool,flex,bison,cmake,pciutils,python-websocket,libjsoncpp-dev,libfcgi-dev,libhiredis-dev,\ + libnuma-dev,build-essential,psmisc,python-httplib2,libpixman-1-dev,moreutils,jq,python-dev-is-python2,psmisc,\ + sshpass,bash-completion,rsync" + ## URLs to docker images saved with `docker save : | gzip > .tar.gz` that are going to be preloaded after docker setup docker_images: [] diff --git a/network_edge_cleanup.yml b/network_edge_cleanup.yml index cf9604f5..78598396 100644 --- a/network_edge_cleanup.yml +++ b/network_edge_cleanup.yml @@ -213,11 +213,12 @@ - name: cleanup git repos include_tasks: ./roles/infrastructure/git_repo/tasks/cleanup.yml - - name: cleanup git + - name: cleanup git on CentOS yum: name: git* state: absent become: yes + when: ansible_distribution == 'CentOS' - name: rmd controller cleanup include_tasks: ./roles/kubernetes/rmd/common/tasks/cleanup.yml diff --git a/roles/infrastructure/docker/tasks/main.yml b/roles/infrastructure/docker/tasks/main.yml index 2e08e933..5711376f 100644 --- a/roles/infrastructure/docker/tasks/main.yml +++ b/roles/infrastructure/docker/tasks/main.yml @@ -2,7 +2,7 @@ # Copyright (c) 2019-2020 Intel Corporation --- -- name: add Docker repository +- name: add Docker repository in CentOs yum_repository: name: docker description: Docker CE repository @@ -14,14 +14,58 @@ retries: "{{ number_of_retries }}" until: result is succeeded delay: "{{ retry_delay }}" - when: not offline_enable + when: + - not offline_enable + - ansible_distribution == "CentOS" + +- name: Install aptitude on Ubuntu + apt: + name: aptitude + state: latest + update_cache: yes + force_apt_get: yes + when: ansible_distribution == "Ubuntu" + become: yes + +- name: Install required system packages on Ubuntu + apt: + name: "{{ item }}" + state: present + update_cache: yes + with_items: + - apt-transport-https + - ca-certificates + - curl + - software-properties-common + - python3-pip + - virtualenv + - libcurl4-gnutls-dev + - python3-setuptools + become: yes + when: ansible_distribution == "Ubuntu" + +- name: gather the package facts + package_facts: + manager: "apt" + when: ansible_distribution == "Ubuntu" + +- name: Install Docker in Ubuntu + apt: + name: docker.io + state: present + update_cache: yes + when: + - ansible_distribution == "Ubuntu" + become: yes - name: clear yum cache command: yum clean all args: warn: false changed_when: true - when: not offline_enable + when: + - not offline_enable + - ansible_distribution == "CentOS" - name: add group "docker" group: @@ -39,19 +83,29 @@ - name: reset connection meta: reset_connection -- name: install Docker CE +- name: install Docker CE for CentOS yum: name: "{{ _docker_packages }}" state: present become: yes notify: - enable and start docker service + when: ansible_distribution == "CentOS" - name: get runc version shell: set -o pipefail && runc --version | grep -oP '{{ _runc_ver_pattern }}\K(.+)' register: runc_rc_ver ignore_errors: true changed_when: false + when: ansible_distribution == "CentOS" + +- name: get runc for Ubuntu + apt: + name: runc + state: present + update_cache: yes + become: yes + when: ansible_distribution == "Ubuntu" - name: Check if offline mode set_fact: @@ -75,7 +129,10 @@ dest: /usr/bin/runc checksum: "sha256:{{ _runc_checksum }}" become: yes - when: runc_rc_ver.rc == 0 and runc_rc_ver.stdout|int < _runc_min_rc + when: + - ansible_distribution == "CentOS" + - runc_rc_ver.rc == 0 + - runc_rc_ver.stdout|int < _runc_min_rc - name: install pip dependencies block: @@ -83,11 +140,78 @@ copy: src: requirements.txt dest: /tmp/requirements.txt + - name: remove non working requirements in Ubuntu + lineinfile: + dest: /tmp/requirements.txt + state: absent + regexp: '^(perf==|pygobject==|python-linux-procfs==|schedutils==|urlgrabber==|yum-metadata-parser==|pycurl==)' + when: ansible_distribution == "Ubuntu" + - name: download and install python requirements that failed using pip on Ubuntu + vars: + packages: + python-linux-procfs: http://ftp.br.debian.org/debian/pool/main/p/python-linux-procfs/python-linux-procfs_0.6.1-1_amd64.deb + schedutils: http://ftp.br.debian.org/debian/pool/main/p/python-schedutils/python-schedutils_0.6-1_amd64.deb + urlgrabber: http://ftp.br.debian.org/debian/pool/main/u/urlgrabber/python-urlgrabber_3.10.2-1_all.deb + when: ansible_distribution == "Ubuntu" + block: + - name: download python packages on Ubuntu + get_url: + url: "{{ item.value }}" + dest: "/tmp/{{ item.key }}.deb" + loop: "{{ packages | dict2items }}" + - name: install python packages on Ubuntu + apt: "deb=/tmp/{{ item.key }}.deb" + loop: "{{ packages | dict2items }}" + become: yes + - name: install pygobject # 3.24 + block: + - name: install pygobject dependencies + apt: + name: + - pkg-config + - libglib2.0-0 + - libglib2.0-dev + - libgirepository1.0-dev + - libgtk-3-dev + - libcairo-gobject2 + - gir1.2-freedesktop + - python3-cairo + - python3-cairo-dev + - python3-cairo-doc + state: present + update_cache: yes + become: yes + - unarchive: + src: https://ftp-stud.hs-esslingen.de/pub/Mirrors/ftp.gnome.org/sources/pygobject/3.22/pygobject-3.22.0.tar.xz + dest: /tmp/ + remote_src: yes + - shell: ./configure; make; make install + args: + chdir: /tmp/pygobject-3.22.0/ + become: yes + - name: install pycurl + apt: + name: python-pycurl + update_cache: yes + become: yes + + - name: install some Ubuntu necessary dependencies + apt: + name: + - python-dev + - libattr1-dev # for pyxattr + - libgpgme11-dev # for pygpgme + - liblzma-dev # pyliblzma + state: present + update_cache: yes + become: yes + when: ansible_distribution == "Ubuntu" - name: install dependencies pip: requirements: /tmp/requirements.txt state: present extra_args: "{{ local_pip | default(omit) }}" + executable: pip2 register: result retries: "{{ number_of_retries }}" until: result is succeeded @@ -98,6 +222,7 @@ name: "{{ _docker_compose_package }}" state: present extra_args: "{{ local_pip | default(omit) }}" + executable: pip2 register: result retries: "{{ number_of_retries }}" until: result is succeeded @@ -140,6 +265,15 @@ when: item.stat.exists with_items: "{{ stats.results }}" +- name: install auditd on Ubuntu + apt: + name: + - auditd + - audispd-plugins + update-cache: yes + become: yes + when: ansible_distribution == 'Ubuntu' + - name: restart auditd command: service auditd restart # noqa 303 become: yes @@ -165,6 +299,7 @@ url: "{{ _docker_compose_completion_url }}" dest: "/etc/bash_completion.d" become: yes + - name: create the directory for docker images file: path: "{{ docker_images_dir }}" diff --git a/roles/infrastructure/docker/tasks/uninstall.yml b/roles/infrastructure/docker/tasks/uninstall.yml index 230113f1..fe38e562 100644 --- a/roles/infrastructure/docker/tasks/uninstall.yml +++ b/roles/infrastructure/docker/tasks/uninstall.yml @@ -6,6 +6,7 @@ file: name: "/etc/audit/rules.d/docker.rules" state: absent + become: yes - name: Restart auditd command: service auditd restart # noqa 303 @@ -22,11 +23,19 @@ ignore_errors: yes become: yes -- name: uninstall +- name: uninstall on CentOS yum: name: "{{ _docker_packages_to_remove }}" state: absent become: yes + when: ansible_distribution == "CentOS" + +- name: uninstall on Ubuntu + apt: + name: docker.io + state: absent + become: yes + when: ansible_distribution == "Ubuntu" - name: remove docker-compose pip: @@ -55,12 +64,14 @@ name: docker state: absent become: yes + when: ansible_distribution == "CentOS" - name: clear yum cache command: yum clean all args: warn: false changed_when: true + when: ansible_distribution == "CentOS" - name: remove group "docker" group: diff --git a/roles/infrastructure/docker/templates/daemon.json.j2 b/roles/infrastructure/docker/templates/daemon.json.j2 index 24befccc..28f6fc79 100644 --- a/roles/infrastructure/docker/templates/daemon.json.j2 +++ b/roles/infrastructure/docker/templates/daemon.json.j2 @@ -22,4 +22,8 @@ "Soft": 4096 } } +}{% if ansible_distribution == 'Ubuntu' %}, +{ + "dns": ["8.8.8.8"] } +{% endif %} diff --git a/roles/infrastructure/grub/tasks/main.yml b/roles/infrastructure/grub/tasks/main.yml index fc7b9e9a..87c0eba2 100644 --- a/roles/infrastructure/grub/tasks/main.yml +++ b/roles/infrastructure/grub/tasks/main.yml @@ -7,6 +7,12 @@ - name: set GRUB config path (BIOS) set_fact: grub_file_path: /boot/grub2/grub.cfg + when: ansible_distribution == "CentOS" + + - name: set GRUB config path (BIOS) + set_fact: + grub_file_path: /boot/grub/grub.cfg + when: ansible_distribution == "Ubuntu" - name: check if host is using EFI stat: @@ -40,25 +46,36 @@ command: grub2-mkconfig -o {{ grub_file_path }} changed_when: true become: yes + when: ansible_distribution == "CentOS" + +- name: regenerate grub.cfg + command: grub-mkconfig -o {{ grub_file_path }} + changed_when: true + become: yes + when: ansible_distribution == "Ubuntu" - name: get current CMDLINE command: cat /proc/cmdline register: current_cmdline changed_when: false -- name: get future cmdline +- name: get future cmdline CentOS shell: set -o pipefail && grubby --info=$(grubby --default-kernel) | grep args register: future_cmdline changed_when: false become: yes + when: ansible_distribution == "CentOS" - name: extract proper parts from the outputs set_fact: current_args: "{{ current_cmdline.stdout | regex_replace('BOOT_IMAGE=.*? root=.*? (.*)', '\\1') | trim }}" future_args: "{{ future_cmdline.stdout | regex_replace('args=\"(.*)\"', '\\1') | trim }}" + when: ansible_distribution == "CentOS" # role `conditional_reboot` checks if `perform_reboot` is defined, is so machine is rebooted - name: request reboot (will be performed by `conditional_reboot` role) set_fact: perform_reboot: "{{ perform_reboot|default([]) + [ 'grub' ] }}" - when: current_args != future_args + when: + - ansible_distribution == "CentOS" + - current_args != future_args diff --git a/roles/infrastructure/os_setup/tasks/add_yum_excludes.yml b/roles/infrastructure/os_setup/tasks/add_yum_excludes.yml index 5b4fd5fc..57a05511 100644 --- a/roles/infrastructure/os_setup/tasks/add_yum_excludes.yml +++ b/roles/infrastructure/os_setup/tasks/add_yum_excludes.yml @@ -10,4 +10,5 @@ when: - _os_yum_exclude_rpm_packages is defined - _os_yum_exclude_rpm_packages|length > 0 + - ansible_distribution == "CentOS" become: yes diff --git a/roles/infrastructure/os_setup/tasks/change_default_sh_ubuntu.yml b/roles/infrastructure/os_setup/tasks/change_default_sh_ubuntu.yml new file mode 100644 index 00000000..edad4ec4 --- /dev/null +++ b/roles/infrastructure/os_setup/tasks/change_default_sh_ubuntu.yml @@ -0,0 +1,11 @@ + +--- +- name: set bash as the default shell (sh) + when: ansible_distribution == 'Ubuntu' + become: yes + block: + - name: set dash/sh to false + shell: echo "dash dash/sh boolean false" | debconf-set-selections + + - name: set the default sh as bash on Ubuntu + shell: dpkg-reconfigure -p critical dash diff --git a/roles/infrastructure/os_setup/tasks/disable_fingerprint.yml b/roles/infrastructure/os_setup/tasks/disable_fingerprint.yml index 01822177..b3b3a4bd 100644 --- a/roles/infrastructure/os_setup/tasks/disable_fingerprint.yml +++ b/roles/infrastructure/os_setup/tasks/disable_fingerprint.yml @@ -2,14 +2,19 @@ # Copyright (c) 2019-2020 Intel Corporation --- - -- name: install authconfig - yum: - name: authconfig - state: present - become: yes - -- name: disable fingerprint to avoid ssh timeout issues - command: authconfig --disablefingerprint --update - changed_when: false - become: yes +- name: disable fingerprint on CentOS + when: ansible_distribution == "CentOS" + block: + - name: debug os distribution + debug: msg=" OS Distribution {{ansible_distribution}}" + + - name: install authconfig + yum: + name: authconfig + state: present + become: yes + + - name: disable fingerprint to avoid ssh timeout issues + command: authconfig --disablefingerprint --update + changed_when: false + become: yes diff --git a/roles/infrastructure/os_setup/tasks/disable_selinux.yml b/roles/infrastructure/os_setup/tasks/disable_selinux.yml index 25de3433..b34a8c8d 100644 --- a/roles/infrastructure/os_setup/tasks/disable_selinux.yml +++ b/roles/infrastructure/os_setup/tasks/disable_selinux.yml @@ -7,9 +7,11 @@ ignore_errors: true changed_when: false become: yes + when: ansible_distribution == "CentOS" - name: Set SELinux to permissive mode permanently (2/2) selinux: policy: targeted state: permissive become: yes + when: ansible_distribution == "CentOS" diff --git a/roles/infrastructure/os_setup/tasks/install_base_os_packages.yml b/roles/infrastructure/os_setup/tasks/install_base_os_packages.yml index b92bc038..9fab791e 100644 --- a/roles/infrastructure/os_setup/tasks/install_base_os_packages.yml +++ b/roles/infrastructure/os_setup/tasks/install_base_os_packages.yml @@ -3,14 +3,16 @@ --- - debug: - msg: "Installing the following packages: {{ os_yum_base_packages }}" + msg: "Installing the following packages: {{ os_yum_base_packages if ansible_distribution == 'CentOS' else os_ubuntu_base_packages }}" - name: install IUS repository yum: name: https://repo.ius.io/ius-release-el7.rpm state: present become: yes - when: not offline_enable + when: + - not offline_enable + - ansible_distribution == "CentOS" - name: Set empty local_pip var set_fact: @@ -24,6 +26,29 @@ _openssl_url: "https://{{ hostvars[groups['controller_group'][0]]['ansible_host'] }}/{{ _openssl_package_name }}.tar.gz" when: offline_enable +- name: install Python 2 and pip2 on Ubuntu + block: + - name: install Python 2 on Ubuntu + apt: + name: python2 + state: present + update_cache: yes + become: yes + when: ansible_distribution == "Ubuntu" + + - name: download pip2 on Ubuntu + get_url: + url: https://bootstrap.pypa.io/pip/2.7/get-pip.py + dest: /home/openness/get-pip.py + mode: '0777' + become: yes + when: ansible_distribution == "Ubuntu" + + - name: Install pip2 in Ubuntu + command: python2 /home/openness/get-pip.py + become: yes + when: ansible_distribution == "Ubuntu" + - name: install base OS rpm packages yum: name: "{{ os_yum_base_packages }}" @@ -31,6 +56,15 @@ enablerepo: "{{ omit if offline_enable else 'ius-archive' }}" skip_broken: yes become: yes + when: ansible_distribution == "CentOS" + +- name: install base OS Ubuntu packages + apt: + name: "{{ os_ubuntu_base_packages }}" + state: present + update_cache: yes + become: yes + when: ansible_distribution == "Ubuntu" - name: upgrade python2-pip version command: "python2 -m pip install {{ local_pip }} --upgrade pip=={{ _pip_version }}" @@ -40,6 +74,7 @@ until: result is succeeded changed_when: true become: yes + when: ansible_distribution == "CentOS" - name: get installed OpenSSL version command: "openssl version" @@ -95,3 +130,9 @@ path: "{{ tmp_dir.path }}" state: absent when: _openssl_version|string not in installed_openssl_version.stdout.split() + +- name: add bash-completion to bashrc on Ubuntu + lineinfile: + path: /etc/bash.bashrc + line: "source /usr/share/bash-completion/bash_completion" + become: yes diff --git a/roles/infrastructure/os_setup/tasks/install_epel_repository.yml b/roles/infrastructure/os_setup/tasks/install_epel_repository.yml index 0ba6efa7..64493b3b 100644 --- a/roles/infrastructure/os_setup/tasks/install_epel_repository.yml +++ b/roles/infrastructure/os_setup/tasks/install_epel_repository.yml @@ -7,4 +7,6 @@ name: epel-release state: present become: yes - when: not offline_enable + when: + - not offline_enable + - ansible_distribution == "CentOS" diff --git a/roles/infrastructure/os_setup/tasks/install_firewalld_ubuntu.yml b/roles/infrastructure/os_setup/tasks/install_firewalld_ubuntu.yml new file mode 100644 index 00000000..6e569d47 --- /dev/null +++ b/roles/infrastructure/os_setup/tasks/install_firewalld_ubuntu.yml @@ -0,0 +1,9 @@ + +--- +- name: install firewalld package on Ubuntu + apt: + name: firewalld + state: present + update_cache: yes + become: yes + when: ansible_distribution == "Ubuntu" diff --git a/roles/infrastructure/os_setup/tasks/main.yml b/roles/infrastructure/os_setup/tasks/main.yml index 29a60e4f..d807ac02 100644 --- a/roles/infrastructure/os_setup/tasks/main.yml +++ b/roles/infrastructure/os_setup/tasks/main.yml @@ -2,10 +2,12 @@ # Copyright (c) 2019-2020 Intel Corporation --- - - debug: msg: "Setting up OS" +- include_tasks: set_ssl_certificates_ubuntu.yml +- include_tasks: change_default_sh_ubuntu.yml +- include_tasks: install_firewalld_ubuntu.yml - include_tasks: disable_fingerprint.yml - include_tasks: disable_swap.yml - include_tasks: disable_selinux.yml diff --git a/roles/infrastructure/os_setup/tasks/reinstall_python_requests_if_needed.yml b/roles/infrastructure/os_setup/tasks/reinstall_python_requests_if_needed.yml index 55f75f3b..0b4a69b2 100644 --- a/roles/infrastructure/os_setup/tasks/reinstall_python_requests_if_needed.yml +++ b/roles/infrastructure/os_setup/tasks/reinstall_python_requests_if_needed.yml @@ -12,6 +12,7 @@ state: absent become: yes register: python_requests_removed + when: ansible_distribution == "CentOS" # ansible lint E503: https://ansible-lint.readthedocs.io/en/latest/default_rules.html#tasks-that-run-when-changed-should-likely-be-handlers # This task is a workaround for cloud-init systems, and it won't be reused anywhere in the code. @@ -20,4 +21,15 @@ name: requests state: present become: yes - when: python_requests_removed.changed # noqa 503 + when: + - python_requests_removed.changed # noqa 503 + - ansible_distribution == "CentOS" + +- name: install python-requests from pip2 + pip: + name: requests + state: present + executable: pip2 + become: yes + when: ansible_distribution == "Ubuntu" + diff --git a/roles/infrastructure/os_setup/tasks/set_ssl_certificates_ubuntu.yml b/roles/infrastructure/os_setup/tasks/set_ssl_certificates_ubuntu.yml new file mode 100644 index 00000000..eeed99ef --- /dev/null +++ b/roles/infrastructure/os_setup/tasks/set_ssl_certificates_ubuntu.yml @@ -0,0 +1,7 @@ + +--- +- name: set certificates directory on Ubuntu + lineinfile: + path: /etc/environment + line: SSL_CERT_DIR=/etc/ssl/certs + become: yes diff --git a/roles/infrastructure/ptp/common/tasks/main.yml b/roles/infrastructure/ptp/common/tasks/main.yml index c114eeba..3cb8beb8 100644 --- a/roles/infrastructure/ptp/common/tasks/main.yml +++ b/roles/infrastructure/ptp/common/tasks/main.yml @@ -52,6 +52,8 @@ - 319/udp - 320/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: Reload firewall rules command: firewall-cmd --reload diff --git a/roles/kubernetes/cni/calico/controlplane/tasks/main.yml b/roles/kubernetes/cni/calico/controlplane/tasks/main.yml index 02392368..2688c5eb 100644 --- a/roles/kubernetes/cni/calico/controlplane/tasks/main.yml +++ b/roles/kubernetes/cni/calico/controlplane/tasks/main.yml @@ -10,6 +10,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" # Starting with calico v3.16 the CNI is adding an accept rule at the end of FORWARD chain in filter table: # "Connections to services without endpoints are now properly rejected in iptables dataplane mode. diff --git a/roles/kubernetes/cni/calico/node/tasks/main.yml b/roles/kubernetes/cni/calico/node/tasks/main.yml index 6e555ea4..db2d9a9e 100644 --- a/roles/kubernetes/cni/calico/node/tasks/main.yml +++ b/roles/kubernetes/cni/calico/node/tasks/main.yml @@ -10,6 +10,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" # Starting with calico v3.16 the CNI is adding an accept rule at the end of FORWARD chain in filter table: # "Connections to services without endpoints are now properly rejected in iptables dataplane mode. diff --git a/roles/kubernetes/cni/flannel/controlplane/tasks/main.yml b/roles/kubernetes/cni/flannel/controlplane/tasks/main.yml index 51f79f24..0fddb1f7 100644 --- a/roles/kubernetes/cni/flannel/controlplane/tasks/main.yml +++ b/roles/kubernetes/cni/flannel/controlplane/tasks/main.yml @@ -10,6 +10,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: patch node's Pod CIDR # flannel's CIDR is read from node's PodCIDR diff --git a/roles/kubernetes/cni/flannel/node/tasks/main.yml b/roles/kubernetes/cni/flannel/node/tasks/main.yml index aa3a94d0..ac8bba54 100644 --- a/roles/kubernetes/cni/flannel/node/tasks/main.yml +++ b/roles/kubernetes/cni/flannel/node/tasks/main.yml @@ -10,6 +10,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: patch node's Pod CIDR command: kubectl patch node "{{ node_name }}" -p '{ "spec":{ "podCIDR":"{{ flannel_cidr | ipsubnet(24, groups['all'].index(inventory_hostname)) }}" }}' diff --git a/roles/kubernetes/cni/kubeovn/controlplane/tasks/main.yml b/roles/kubernetes/cni/kubeovn/controlplane/tasks/main.yml index bb8b58f4..b8abba9d 100644 --- a/roles/kubernetes/cni/kubeovn/controlplane/tasks/main.yml +++ b/roles/kubernetes/cni/kubeovn/controlplane/tasks/main.yml @@ -19,6 +19,8 @@ - 6642/tcp - 6081/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: Check if kube-ovn kubectl plugin exists stat: diff --git a/roles/kubernetes/cni/kubeovn/node/tasks/main.yml b/roles/kubernetes/cni/kubeovn/node/tasks/main.yml index 8a85b18a..48d5d53d 100644 --- a/roles/kubernetes/cni/kubeovn/node/tasks/main.yml +++ b/roles/kubernetes/cni/kubeovn/node/tasks/main.yml @@ -21,6 +21,8 @@ - 8285/udp - 8472/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: wait for OVS database block: diff --git a/roles/kubernetes/cni/ovn4nfv/controlplane/tasks/main.yml b/roles/kubernetes/cni/ovn4nfv/controlplane/tasks/main.yml index 2bba92ae..80a22eee 100644 --- a/roles/kubernetes/cni/ovn4nfv/controlplane/tasks/main.yml +++ b/roles/kubernetes/cni/ovn4nfv/controlplane/tasks/main.yml @@ -15,6 +15,8 @@ - 6642/tcp - 6081/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: ovn4nfv | Label control-plane node command: >- diff --git a/roles/kubernetes/cni/weavenet/controlplane/tasks/main.yml b/roles/kubernetes/cni/weavenet/controlplane/tasks/main.yml index 0fbe0e01..06c932e6 100644 --- a/roles/kubernetes/cni/weavenet/controlplane/tasks/main.yml +++ b/roles/kubernetes/cni/weavenet/controlplane/tasks/main.yml @@ -16,6 +16,8 @@ - 6783/udp - 6784/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: apply WeaveNet via the addon shell: set -o pipefail && kubectl apply -f "{{ _weavenet_yaml }}" diff --git a/roles/kubernetes/cni/weavenet/node/tasks/main.yml b/roles/kubernetes/cni/weavenet/node/tasks/main.yml index df569f2f..9532c89b 100644 --- a/roles/kubernetes/cni/weavenet/node/tasks/main.yml +++ b/roles/kubernetes/cni/weavenet/node/tasks/main.yml @@ -16,6 +16,8 @@ - 6783/udp - 6784/udp become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: patch node's Pod CIDR command: kubectl patch node "{{ node_name }}" -p '{ "spec":{ "podCIDR":"{{ weavenet_cidr }}" }}' diff --git a/roles/kubernetes/common/defaults/main.yml b/roles/kubernetes/common/defaults/main.yml index 2529b118..63755094 100644 --- a/roles/kubernetes/common/defaults/main.yml +++ b/roles/kubernetes/common/defaults/main.yml @@ -3,6 +3,7 @@ --- _kubernetes_version: "1.20.0" +_kubernetes_debian_version: "00" _kubernetes_packages: "kubelet-{{ _kubernetes_version }},kubeadm-{{ _kubernetes_version }},kubectl-{{ _kubernetes_version }}" @@ -11,4 +12,10 @@ _kubernetes_repository_key: - https://packages.cloud.google.com/yum/doc/yum-key.gpg - https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg + +_kubernetes_packages_ubuntu: "kubelet={{ _kubernetes_version }}-{{_kubernetes_debian_version}},kubeadm={{ _kubernetes_version }}-{{_kubernetes_debian_version}},kubectl={{ _kubernetes_version }}-{{_kubernetes_debian_version}}" + +_kubernetes_repository_ubuntu: "deb http://apt.kubernetes.io/ kubernetes-xenial main " +_kubernetes_repository_key_ubuntu: "https://packages.cloud.google.com/apt/doc/apt-key.gpg" + _kubernetes_packages_to_remove: "kubelet,kubeadm,kubectl" diff --git a/roles/kubernetes/common/tasks/main.yml b/roles/kubernetes/common/tasks/main.yml index bf0dbd09..22895615 100644 --- a/roles/kubernetes/common/tasks/main.yml +++ b/roles/kubernetes/common/tasks/main.yml @@ -2,48 +2,72 @@ # Copyright (c) 2019-2020 Intel Corporation --- -- name: import repository - yum_repository: - name: kubernetes - description: Kubernetes repository - baseurl: "{{ _kubernetes_repository_url }}" - enabled: true - become: yes - register: result - retries: "{{ number_of_retries }}" - until: result is succeeded - delay: "{{ retry_delay }}" - when: not offline_enable +- name: CentOS installation + when: ansible_distribution == "CentOS" + block: + - name: import repository + yum_repository: + name: kubernetes + description: Kubernetes repository + baseurl: "{{ _kubernetes_repository_url }}" + enabled: true + become: yes + register: result + retries: "{{ number_of_retries }}" + until: result is succeeded + delay: "{{ retry_delay }}" + when: not offline_enable -- name: edit repository - yum_repository: - name: kubernetes - description: Kubernetes repository - baseurl: "{{ _kubernetes_repository_url }}" - gpgkey: "{{ _kubernetes_repository_key }}" - gpgcheck: yes - enabled: true - become: yes - register: result - retries: "{{ number_of_retries }}" - until: result is succeeded - delay: "{{ retry_delay }}" - when: not offline_enable + - name: edit repository + yum_repository: + name: kubernetes + description: Kubernetes repository + baseurl: "{{ _kubernetes_repository_url }}" + gpgkey: "{{ _kubernetes_repository_key }}" + gpgcheck: yes + enabled: true + become: yes + register: result + retries: "{{ number_of_retries }}" + until: result is succeeded + delay: "{{ retry_delay }}" + when: not offline_enable + + - name: install packages + yum: + name: "{{ _kubernetes_packages }}" + state: present + skip_broken: yes + update_cache: yes + allow_downgrade: true + become: yes + register: result + retries: 20 + until: result is succeeded + delay: 10 + notify: + - enable and restart kubelet -- name: install packages - yum: - name: "{{ _kubernetes_packages }}" - state: present - skip_broken: yes - update_cache: yes - allow_downgrade: true +- name: Ubuntu installation become: yes - register: result - retries: 20 - until: result is succeeded - delay: 10 - notify: - - enable and restart kubelet + when: ansible_distribution == "Ubuntu" + block: + - name: add Google official GPG key + apt_key: + url: "{{ _kubernetes_repository_key_ubuntu }}" + state: present + - name: add Kubernetes repository + apt_repository: + repo: "{{ _kubernetes_repository_ubuntu }}" + update_cache: yes + state: present + filename: kuerbentes + mode: 0600 + - name: installing packages + apt: + name: "{{ _kubernetes_packages_ubuntu }}" + state: present + update_cache: yes - name: set up proxy include_tasks: proxy.yml @@ -80,6 +104,8 @@ - 6443/tcp - 2379-2380/tcp - 10250-10252/tcp + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: restart services if needed meta: flush_handlers diff --git a/roles/kubernetes/common/tasks/uninstall.yml b/roles/kubernetes/common/tasks/uninstall.yml index 376a9813..9f6e1d8b 100644 --- a/roles/kubernetes/common/tasks/uninstall.yml +++ b/roles/kubernetes/common/tasks/uninstall.yml @@ -39,27 +39,44 @@ state: absent become: yes -- name: uninstall packages - yum: - name: "{{ _kubernetes_packages_to_remove }}" - state: absent - become: yes - -- name: remove repository - yum_repository: - name: kubernetes - state: absent - become: yes +- name: uninstallation on CentOS + when: ansible_distribution == "CentOS" + block: + - name: uninstall packages + yum: + name: "{{ _kubernetes_packages_to_remove }}" + state: absent + become: yes + + - name: remove repository + yum_repository: + name: kubernetes + state: absent + become: yes + + - name: clear yum cache + command: yum clean metadata + args: + warn: false + changed_when: true -- name: clear yum cache - command: yum clean metadata - args: - warn: false - changed_when: true +- name: uninstallation on Ubuntu + when: ansible_distribution == "Ubuntu" + block: + - name: uninstall packages + apt: + name: "{{ _kubernetes_packages_ubuntu }}" + state: absent + become: yes + - name: remove repository + apt_repository: + repo: "{{ _kubernetes_repository_ubuntu }}" + state: absent + become: yes + - name: remove CNI directory file: name: /etc/cni/net.d state: absent become: yes - diff --git a/roles/kubernetes/dashboard/tasks/main.yml b/roles/kubernetes/dashboard/tasks/main.yml index c273e4b9..598ac915 100644 --- a/roles/kubernetes/dashboard/tasks/main.yml +++ b/roles/kubernetes/dashboard/tasks/main.yml @@ -19,6 +19,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: create Kubernetes Dashboard directories file: diff --git a/roles/kubernetes/nfd/tasks/nfd.yml b/roles/kubernetes/nfd/tasks/nfd.yml index e0f06fbd..589738a5 100644 --- a/roles/kubernetes/nfd/tasks/nfd.yml +++ b/roles/kubernetes/nfd/tasks/nfd.yml @@ -84,11 +84,20 @@ - name: apply CMK worker patch block: - - name: install patch utility + - name: install patch utility on CentOS yum: name: patch state: present become: yes + when: ansible_distribution == 'CentOS' + + - name: install patch utility on Ubuntu + apt: + name: patch + state: present + update_cache: yes + become: yes + when: ansible_distribution == 'Ubuntu' - name: apply CMK worker patch patch: diff --git a/roles/kubernetes/node/defaults/main.yml b/roles/kubernetes/node/defaults/main.yml index 7f485465..3a9d565e 100644 --- a/roles/kubernetes/node/defaults/main.yml +++ b/roles/kubernetes/node/defaults/main.yml @@ -3,7 +3,7 @@ --- -_kubernetes_env_file: "/etc/sysconfig/kubelet" +_kubernetes_env_file: "{{ '/etc/sysconfig/kubelet' if ansible_distribution == 'CentOS' else '/etc/default/kubelet' }}" _kubernetes_config_file: "/usr/lib/systemd/system/kubelet.service.d/kubelet_config.yml" cpu: diff --git a/roles/kubernetes/node/tasks/customize_kubelet.yml b/roles/kubernetes/node/tasks/customize_kubelet.yml index 93dfa101..9ea8cc50 100644 --- a/roles/kubernetes/node/tasks/customize_kubelet.yml +++ b/roles/kubernetes/node/tasks/customize_kubelet.yml @@ -2,6 +2,13 @@ # Copyright (c) 2019-2020 Intel Corporation --- +- name: creating the kubernetes env file in Ubuntu + file: + path: "{{ _kubernetes_env_file }}" + state: touch + become: yes + when: ansible_distribution == 'Ubuntu' + - name: setting KUBELET_EXTRA_ARGS lineinfile: path: "{{ _kubernetes_env_file }}" diff --git a/roles/telemetry/collectd/node/tasks/main.yml b/roles/telemetry/collectd/node/tasks/main.yml index e3b9d59e..e8fc940f 100644 --- a/roles/telemetry/collectd/node/tasks/main.yml +++ b/roles/telemetry/collectd/node/tasks/main.yml @@ -10,6 +10,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: download and patch ovs_pmd_stats.py script block: diff --git a/roles/telemetry/grafana/tasks/main.yml b/roles/telemetry/grafana/tasks/main.yml index eb9a7804..bf8dc36e 100644 --- a/roles/telemetry/grafana/tasks/main.yml +++ b/roles/telemetry/grafana/tasks/main.yml @@ -47,6 +47,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: check if Grafana release already exists command: helm status grafana -n telemetry @@ -188,10 +190,20 @@ src: example-dashboard.json dest: "{{ _grafana_dashboards_conf }}/example-dashboard.json" - - name: install patch utility + - name: install patch utility on CentOS yum: name: patch state: present + become: yes + when: ansible_distribution == 'CentOS' + + - name: install patch utility on Ubuntu + apt: + name: patch + state: present + update_cache: yes + become: yes + when: ansible_distribution == 'Ubuntu' - name: apply _pod.tpl patch patch: diff --git a/roles/telemetry/pcm/controlplane/tasks/main.yml b/roles/telemetry/pcm/controlplane/tasks/main.yml index fb3ecf11..4e289a8d 100644 --- a/roles/telemetry/pcm/controlplane/tasks/main.yml +++ b/roles/telemetry/pcm/controlplane/tasks/main.yml @@ -27,6 +27,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: check if pcm already exists command: helm status pcm --namespace telemetry diff --git a/roles/telemetry/pcm/node/tasks/main.yml b/roles/telemetry/pcm/node/tasks/main.yml index a3f236b3..8dc7bde6 100644 --- a/roles/telemetry/pcm/node/tasks/main.yml +++ b/roles/telemetry/pcm/node/tasks/main.yml @@ -28,6 +28,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: wait for pcm pod to be ready command: > diff --git a/roles/telemetry/prometheus/tasks/main.yml b/roles/telemetry/prometheus/tasks/main.yml index c6d680b4..1aa66d99 100644 --- a/roles/telemetry/prometheus/tasks/main.yml +++ b/roles/telemetry/prometheus/tasks/main.yml @@ -32,6 +32,8 @@ state: enabled immediate: yes become: yes + vars: + ansible_python_interpreter: "{{ '/usr/bin/python3' if ansible_distribution == 'Ubuntu' else '/usr/bin/python2' }}" - name: check if Prometheus release already exists command: helm status prometheus -n telemetry @@ -157,10 +159,20 @@ src: telemetry-certs-daemonset.yml.j2 dest: "{{ _prometheus_chart_dir }}/templates/telemetry-certs-daemonset.yaml" - - name: install patch utility + - name: install patch utility on CentOS yum: name: patch state: present + become: yes + when: ansible_distribution == 'CentOS' + + - name: install patch utility on Ubuntu + apt: + name: patch + state: present + update_cache: yes + become: yes + when: ansible_distribution == 'Ubuntu' - name: apply node-exporter-daemonset patch patch: diff --git a/scripts/ansible-precheck.sh b/scripts/ansible-precheck.sh index 8fe0e4e9..50f4bc4f 100755 --- a/scripts/ansible-precheck.sh +++ b/scripts/ansible-precheck.sh @@ -6,37 +6,64 @@ set -euxo pipefail PYTHON3_PKG=python3 PYTHON3_VERSION=3.6.8-18.el7 +PYTHON3_PKG_UBUNTU=python3 PYTHON_SH_PKG=python36-sh PYTHON_SH_VERSION=1.12.14-7.el7 +PYTHON_SH_PKG_UBUNTU=python3-sh PYTHON_NETADDR_PKG=python-netaddr PYTHON_NETADDR_VERSION=0.7.5-9.el7 +PYTHON_NETADDR_PKG_UBUNTU=python3-netaddr PYTHON_PYYAML_PKG=python36-PyYAML PYTHON_PYYAML_VERSION=3.13-1.el7 +PYTHON_PYYAML_PKG_UBUNTU=python-yaml ANSIBLE_PKG=ansible ANSIBLE_VERSION=2.9.18-1.el7 +ANSIBLE_PKG_UBUNTU=ansible ensure_installed () { - if [[ ${2-} ]] - then - package_name="$1-$2" - else - package_name="$1" - fi + if [[ -f /etc/redhat-release ]]; then + if [[ ${3-} ]] + then + package_name="$1-$3" + else + package_name="$1" + fi - if ! sudo rpm -qa | grep -q ^"$package_name"; then - echo "Instaling $package_name" - if ! sudo yum -y install "$package_name"; then - echo "ERROR: Failed to install package $package_name" - exit 1 + if ! sudo rpm -qa | grep -q ^"$package_name"; then + echo "Instaling $package_name" + if ! sudo yum -y install "$package_name"; then + echo "ERROR: Failed to install package $package_name" + exit 1 + else + echo "$package_name successfully installed" + fi else - echo "$package_name successfully installed" + echo "$package_name already installed" + fi + elif [[ -f /etc/debian_version ]]; then + if [[ ${2-} ]]; then + package_name="$2" + + if [ $(dpkg-query -W -f='${Status}' "$package_name" | grep -c "install ok installed") -eq 0 ]; then + echo "Installing $package_name" + if ! sudo apt install -y "$package_name"; then + echo "ERROR: Failed to install package $package_name" + exit 1 + else + echo "$package_name successfully installed" + fi + else + echo "$package_name already installed" + fi fi else - echo "$package_name already installed" + echo "Linux distribution not recognized" + uname -s + exit 1 fi } @@ -63,16 +90,16 @@ fi ensure_installed epel-release # Python 3 -ensure_installed $PYTHON3_PKG $PYTHON3_VERSION +ensure_installed $PYTHON3_PKG $PYTHON3_PKG_UBUNTU $PYTHON3_VERSION # ansible -ensure_installed $ANSIBLE_PKG $ANSIBLE_VERSION +ensure_installed $ANSIBLE_PKG $ANSIBLE_PKG_UBUNTU $ANSIBLE_VERSION # netaddr -ensure_installed $PYTHON_NETADDR_PKG $PYTHON_NETADDR_VERSION +ensure_installed $PYTHON_NETADDR_PKG $PYTHON_NETADDR_PKG_UBUNTU $PYTHON_NETADDR_VERSION # pyyaml -ensure_installed $PYTHON_PYYAML_PKG $PYTHON_PYYAML_VERSION +ensure_installed $PYTHON_PYYAML_PKG $PYTHON_PYYAML_PKG_UBUNTU $PYTHON_PYYAML_VERSION # sh -ensure_installed $PYTHON_SH_PKG $PYTHON_SH_VERSION +ensure_installed $PYTHON_SH_PKG $PYTHON_SH_PKG_UBUNTU $PYTHON_SH_VERSION