Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 14 additions & 163 deletions 01_install_requirements.sh
Original file line number Diff line number Diff line change
@@ -1,179 +1,30 @@
#!/usr/bin/env bash
set -ex

# Wrapper script to run the Ansible playbook
# This replaces the original 01_install_requirements.sh

set -ex

# Source the original environment setup
source logging.sh
source common.sh
source sanitychecks.sh
source utils.sh
source validation.sh

early_deploy_validation true

if [ -z "${METAL3_DEV_ENV}" ]; then
export REPO_PATH=${WORKING_DIR}
sync_repo_and_patch metal3-dev-env https://github.com/metal3-io/metal3-dev-env.git
pushd ${METAL3_DEV_ENV_PATH}
# Pin to a specific metal3-dev-env commit to ensure we catch breaking
# changes before they're used by everyone and CI.
# TODO -- come up with a plan for continuously updating this
# Note we only do this in the case where METAL3_DEV_ENV is
# unset, to enable developer testing of local checkouts
git reset c60510f410173ddf01a29b87c889249b0f263c9f --hard

popd
fi

# This must be aligned with the metal3-dev-env pinned version above, see
# https://github.com/metal3-io/metal3-dev-env/blob/master/lib/common.sh
# Export environment variables that the playbook expects
export WORKING_DIR=${WORKING_DIR:-$(pwd)}
export METAL3_DEV_ENV_PATH=${METAL3_DEV_ENV_PATH:-"${WORKING_DIR}/metal3-dev-env"}
export ANSIBLE_VERSION=${ANSIBLE_VERSION:-"8.0.0"}

# Speed up dnf downloads
sudo sh -c "echo 'fastestmirror=1' >> /etc/dnf/dnf.conf"
sudo sh -c "echo 'max_parallel_downloads=8' >> /etc/dnf/dnf.conf"

# Refresh dnf data
# We could also use --refresh to just force metadata update
# in the upgrade command,but this is more explicit and complete
sudo dnf -y clean all

old_version=$(sudo dnf info NetworkManager | grep Version | cut -d ':' -f 2)

# Update to latest packages first
sudo dnf -y upgrade --nobest

new_version=$(sudo dnf info NetworkManager | grep Version | cut -d ':' -f 2)
# If NetworkManager was upgraded it needs to be restarted
if [ "$old_version" != "$new_version" ]; then
sudo systemctl restart NetworkManager
fi

# Install additional repos as needed for each OS version
# shellcheck disable=SC1091
source /etc/os-release

# NOTE(elfosardo): Hacks required for legacy and missing things due to bump in
#metal3-dev-env commit hash.
# All of those are needed because we're still behind for OS support.
# passlib needs to be installed as system dependency
if [[ -x "/usr/libexec/platform-python" ]]; then
sudo /usr/libexec/platform-python -m pip install passlib || sudo dnf -y install python3-pip && sudo /usr/libexec/platform-python -m pip install passlib
fi

# Install ansible, other packages are installed via
# vm-setup/install-package-playbook.yml
case $DISTRO in
"centos8"|"rhel8"|"almalinux8"|"rocky8")
# install network-scripts package to be able to use legacy network commands
sudo dnf install -y network-scripts
if [[ $DISTRO == "centos8" ]] && [[ "$NAME" != *"Stream"* ]]; then
echo "CentOS is not supported, please switch to CentOS Stream / RHEL / Rocky / Alma"
exit 1
fi
if [[ $DISTRO == "centos8" || $DISTRO == "almalinux8" || $DISTRO == "rocky8" ]]; then
sudo dnf -y install epel-release dnf --enablerepo=extras
elif [[ $DISTRO == "rhel8" ]]; then
# Enable EPEL for python3-passlib and python3-bcrypt required by metal3-dev-env
sudo dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
if sudo subscription-manager repos --list-enabled 2>&1 | grep "ansible-2-for-rhel-8-$(uname -m)-rpms"; then
# The packaged 2.x ansible is too old for compatibility with metal3-dev-env
sudo dnf erase -y ansible
sudo subscription-manager repos --disable=ansible-2-for-rhel-8-$(uname -m)-rpms
fi
fi
# Note recent ansible needs python >= 3.8 so we install 3.9 here
sudo dnf -y install python39
sudo alternatives --set python /usr/bin/python3.9
sudo alternatives --set python3 /usr/bin/python3.9
sudo update-alternatives --install /usr/bin/pip3 pip3 /usr/bin/pip3.9 1
PYTHON_DEVEL="python39-devel"
;;
"centos9"|"rhel9"|"almalinux9"|"rocky9")
sudo dnf -y install python3-pip
if [[ $DISTRO == "centos9" || $DISTRO == "almalinux9" || $DISTRO == "rocky9" ]] ; then
sudo dnf config-manager --set-enabled crb
sudo dnf -y install epel-release
elif [[ $DISTRO == "rhel9" ]]; then
# NOTE(raukadah): If a system is subscribed to RHEL subscription then
# sudo subscription-manager identity will return exit 0 else 1.
if sudo subscription-manager identity > /dev/null 2>&1; then
# NOTE(elfosardo): a valid RHEL subscription is needed to be able to
# enable the CRB repository
sudo subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
fi
sudo dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
fi
sudo ln -s /usr/bin/python3 /usr/bin/python || true
PYTHON_DEVEL="python3-devel"
;;
*)
echo -n "CentOS or RHEL version not supported"
exit 1
;;
esac

# We use yq in a few places for processing YAML but it isn't packaged
# for CentOS/RHEL so we have to install from pip. We do not want to
# overwrite an existing installation of the golang version, though,
# so check if we have a yq before installing.
if ! which yq 2>&1 >/dev/null; then
sudo python -m pip install 'yq>=3,<4'
else
echo "Using yq from $(which yq)"
fi

GO_VERSION=${GO_VERSION:-1.22.3}

GOARCH=$(uname -m)
if [[ $GOARCH == "aarch64" ]]; then
GOARCH="arm64"
sudo dnf -y install $PYTHON_DEVEL libxml2-devel libxslt-devel
elif [[ $GOARCH == "x86_64" ]]; then
GOARCH="amd64"
fi
export GO_VERSION=${GO_VERSION:-"1.22.3"}

# Also need the 3.9 version of netaddr for ansible.netcommon
# and lxml for the pyxpath script
sudo python -m pip install netaddr lxml
sudo python -m pip install netaddr lxml ansible=="${ANSIBLE_VERSION}"

sudo python -m pip install ansible=="${ANSIBLE_VERSION}"

pushd ${METAL3_DEV_ENV_PATH}
ansible-galaxy install -r vm-setup/requirements.yml
# Let's temporarily pin these collections to the latest compatible with ansible-2.15
#ansible-galaxy collection install --upgrade ansible.netcommon ansible.posix ansible.utils community.general
ansible-galaxy collection install 'ansible.netcommon<8.0.0' ansible.posix 'ansible.utils<6.0.0' community.general
# Run the Ansible playbook
ANSIBLE_FORCE_COLOR=true ansible-playbook \
-e "working_dir=$WORKING_DIR" \
-e "virthost=$HOSTNAME" \
-e "go_version=$GO_VERSION" \
-e "GOARCH=$GOARCH" \
$ALMA_PYTHON_OVERRIDE \
-i vm-setup/inventory.ini \
-b -vvv vm-setup/install-package-playbook.yml
popd

if [ -n "${KNI_INSTALL_FROM_GIT}" ]; then
# zip is required for building the installer from source
sudo dnf -y install zip
fi

# Install nfs for persistent volumes
if [ "${PERSISTENT_IMAGEREG}" == true ] ; then
sudo dnf -y install nfs-utils
fi

if [[ "${NODES_PLATFORM}" == "baremetal" ]] ; then
sudo dnf -y install ipmitool
fi

# needed if we are using locally built images
# We stop any systemd service so we can run in a container, since
# there's no RPM/systemd version available for RHEL8
if sudo systemctl is-active docker-distribution.service; then
sudo systemctl disable --now docker-distribution.service
fi
-i inventory.ini \
-b -vvv install_requirements.yml

retry_with_timeout 5 60 "curl -L $OPENSHIFT_CLIENT_TOOLS_URL | sudo tar -U -C /usr/local/bin -xzf -"
sudo chmod +x /usr/local/bin/oc
oc version --client -o json
echo "Installation completed successfully!"
99 changes: 99 additions & 0 deletions README_ansible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Metal3 Requirements Installation - Ansible Version

This directory contains the Ansible playbook version of the original `01_install_requirements.sh` script. The playbook provides the same functionality but with better organization, error handling, and idempotency.

## Files

- `install_requirements.yml` - Main Ansible playbook
- `tasks/` - Directory containing individual task files
- `inventory.ini` - Simple localhost inventory
- `run_install_requirements.sh` - Wrapper script (optional)
- `README_ansible.md` - This documentation

## Requirements

- Ansible installed on the system
- Root/sudo access
- RHEL/CentOS 8 or 9 (or compatible distributions like AlmaLinux, Rocky Linux)

## Usage

### Option 1: Direct Ansible Playbook

```bash
ansible-playbook -i inventory.ini install_requirements.yml -v
```

### Option 2: Using the Wrapper Script

```bash
./run_install_requirements.sh
```

## Environment Variables

The playbook respects the same environment variables as the original script:

- `WORKING_DIR` - Working directory (default: current directory)
- `METAL3_DEV_ENV_PATH` - Path to metal3-dev-env repository
- `METAL3_DEV_ENV` - If set, skips repo cloning
- `ANSIBLE_VERSION` - Ansible version to install (default: 8.0.0)
- `GO_VERSION` - Go version for the metal3 playbook (default: 1.22.3)
- `OPENSHIFT_CLIENT_TOOLS_URL` - URL for OpenShift client tools
- `KNI_INSTALL_FROM_GIT` - Install additional packages for git-based installation
- `PERSISTENT_IMAGEREG` - Install NFS utilities for persistent image registry
- `NODES_PLATFORM` - Install platform-specific tools (e.g., 'baremetal' installs ipmitool)
- `ALMA_PYTHON_OVERRIDE` - Python override for AlmaLinux

## Task Organization

The playbook is organized into the following tasks:

1. **early_deploy_validation.yml** - Basic validation checks
2. **setup_metal3_repo.yml** - Clone and setup metal3-dev-env repository
3. **configure_dnf.yml** - Configure DNF for faster downloads
4. **upgrade_packages.yml** - Upgrade system packages
5. **install_passlib.yml** - Install passlib with platform-python
6. **setup_rhel8_repos.yml** - Configure repositories for RHEL/CentOS 8
7. **setup_rhel9_repos.yml** - Configure repositories for RHEL/CentOS 9
8. **install_yq.yml** - Install yq YAML processor
9. **install_dev_packages.yml** - Install development packages
10. **install_python_packages.yml** - Install Python dependencies
11. **install_ansible.yml** - Install Ansible and galaxy requirements
12. **run_metal3_playbook.yml** - Run the metal3 installation playbook
13. **install_optional_packages.yml** - Install optional packages based on environment
14. **handle_docker_distribution.yml** - Handle docker-distribution service
15. **install_oc_tools.yml** - Install OpenShift client tools

## Features

- **Idempotent**: Can be run multiple times safely
- **Better Error Handling**: Ansible provides better error reporting
- **Modular**: Tasks are organized in separate files for maintainability
- **OS Detection**: Automatically detects RHEL/CentOS version and architecture
- **Conditional Logic**: Only runs tasks relevant to the current environment

## Differences from Original Script

1. **Structured Tasks**: Logic is organized into reusable task files
2. **Fact Gathering**: Uses Ansible facts instead of shell commands where possible
3. **Package Management**: Uses Ansible's dnf module instead of shell commands
4. **Service Management**: Uses Ansible's systemd module for service operations
5. **File Operations**: Uses Ansible modules for file and directory operations

## Troubleshooting

- Ensure you have sudo privileges
- Check that your OS is supported (RHEL/CentOS 8 or 9)
- Verify network connectivity for package downloads
- Check Ansible version compatibility

## Migration from Bash Script

To migrate from the bash script:

1. Ensure all environment variables are set as needed
2. Run the Ansible playbook instead of the bash script
3. The playbook will perform the same operations with better error handling

For any issues, compare the task outputs with the original script behavior.
94 changes: 94 additions & 0 deletions install_requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
- name: Install Metal3 Development Environment Requirements
hosts: localhost
become: yes
environment:
PATH: "/usr/local/bin:{{ ansible_env.PATH }}"
gather_facts: yes
vars:
ansible_version: "{{ ansible_version_override | default('8.0.0') }}"
go_version: "{{ go_version_override | default('1.22.3') }}"
metal3_dev_env_commit: "c60510f410173ddf01a29b87c889249b0f263c9f"
metal3_dev_env_repo: "https://github.com/metal3-io/metal3-dev-env.git"
working_dir: "{{ lookup('env', 'WORKING_DIR') | default(ansible_env.HOME + '/metal3') }}"
metal3_dev_env_path: "{{ lookup('env', 'METAL3_DEV_ENV_PATH') | default(working_dir + '/metal3-dev-env') }}"
metal3_dev_env: "{{ lookup('env', 'METAL3_DEV_ENV') }}"
openshift_client_tools_url: "{{ lookup('env', 'OPENSHIFT_CLIENT_TOOLS_URL') }}"
kni_install_from_git: "{{ lookup('env', 'KNI_INSTALL_FROM_GIT') }}"
persistent_imagereg: "{{ lookup('env', 'PERSISTENT_IMAGEREG') | bool }}"
nodes_platform: "{{ lookup('env', 'NODES_PLATFORM') | default('libvirt') }}"
alma_python_override: "{{ lookup('env', 'ALMA_PYTHON_OVERRIDE') }}"
container_runtime: "{{ lookup('env', 'CONTAINER_RUNTIME') | default('podman') }}"

pre_tasks:
- name: Load OS information
setup:
gather_subset: distribution

- name: Set distribution facts
set_fact:
distro: "{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
arch: "{{ ansible_architecture }}"

- name: Set Go architecture
set_fact:
goarch: "{{ 'arm64' if arch == 'aarch64' else 'amd64' }}"

- name: Fail if unsupported OS
fail:
msg: "CentOS or RHEL version not supported"
when: distro not in ['centos8', 'rhel8', 'almalinux8', 'rocky8', 'centos9', 'rhel9', 'almalinux9', 'rocky9']

- name: Check for CentOS 8 (non-Stream) and fail
fail:
msg: "CentOS is not supported, please switch to CentOS Stream / RHEL / Rocky / Alma"
when:
- distro == "centos8"
- '"Stream" not in ansible_distribution_version'

tasks:
- name: Run early deployment validation
include_tasks: tasks/early_deploy_validation.yml
when: lookup('env', 'SKIP_VALIDATION') != 'true'

- name: Setup Metal3 development environment repository
include_tasks: tasks/setup_metal3_repo.yml
when: metal3_dev_env == ""

- name: Configure DNF for faster downloads
include_tasks: tasks/configure_dnf.yml

- name: Upgrade system packages and handle NetworkManager restart
include_tasks: tasks/upgrade_packages.yml

- name: Install passlib with platform-python if available
include_tasks: tasks/install_passlib.yml

- name: Configure repositories and Python for RHEL/CentOS 8
include_tasks: tasks/setup_rhel8_repos.yml
when: distro in ['centos8', 'rhel8', 'almalinux8', 'rocky8']

- name: Configure repositories and Python for RHEL/CentOS 9
include_tasks: tasks/setup_rhel9_repos.yml
when: distro in ['centos9', 'rhel9', 'almalinux9', 'rocky9']

- name: Install yq if not present
include_tasks: tasks/install_yq.yml

- name: Install architecture-specific development packages
include_tasks: tasks/install_dev_packages.yml

- name: Install Python packages
include_tasks: tasks/install_python_packages.yml

- name: Run Metal3 package installation playbook
include_tasks: tasks/run_metal3_playbook.yml

- name: Install optional packages based on environment
include_tasks: tasks/install_optional_packages.yml

- name: Handle docker-distribution service
include_tasks: tasks/handle_docker_distribution.yml

- name: Install OpenShift client tools
include_tasks: tasks/install_oc_tools.yml
2 changes: 2 additions & 0 deletions inventory.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[local]
localhost ansible_connection=local
Loading