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
2 changes: 1 addition & 1 deletion .clang-format-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
22
39 changes: 34 additions & 5 deletions .github/workflows/clang-format-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,40 @@ jobs:
set -euo pipefail
REQUIRED_CLANG_FORMAT_VERSION="$(tr -d '[:space:]' < .clang-format-version)"

CLANG_FORMAT_BIN=""
if [[ -n "${REQUIRED_CLANG_FORMAT_VERSION}" ]] && command -v "clang-format-${REQUIRED_CLANG_FORMAT_VERSION}" >/dev/null 2>&1; then
CLANG_FORMAT_BIN="$(command -v "clang-format-${REQUIRED_CLANG_FORMAT_VERSION}")"
elif command -v clang-format >/dev/null 2>&1; then
CLANG_FORMAT_BIN="$(command -v clang-format)"
resolve_clang_format_bin() {
CLANG_FORMAT_BIN=""
if [[ -n "${REQUIRED_CLANG_FORMAT_VERSION}" ]] && command -v "clang-format-${REQUIRED_CLANG_FORMAT_VERSION}" >/dev/null 2>&1; then
CLANG_FORMAT_BIN="$(command -v "clang-format-${REQUIRED_CLANG_FORMAT_VERSION}")"
elif command -v clang-format >/dev/null 2>&1; then
CLANG_FORMAT_BIN="$(command -v clang-format)"
fi
}

clang_format_major_version() {
"${CLANG_FORMAT_BIN}" --version | sed -nE 's/.* ([0-9]+)(\.[0-9]+)+.*/\1/p' | head -n 1
}

resolve_clang_format_bin

if [[ -n "${REQUIRED_CLANG_FORMAT_VERSION}" ]]; then
current_major=""
if [[ -n "${CLANG_FORMAT_BIN}" ]]; then
current_major="$(clang_format_major_version)"
fi

if [[ "${current_major}" != "${REQUIRED_CLANG_FORMAT_VERSION}" ]]; then
command -v python3 >/dev/null 2>&1 || {
echo "python3 is required to install clang-format ${REQUIRED_CLANG_FORMAT_VERSION}" >&2
exit 1
}

next_version="$((REQUIRED_CLANG_FORMAT_VERSION + 1))"
python3 -m pip install --user --upgrade \
"clang-format>=${REQUIRED_CLANG_FORMAT_VERSION}.0,<${next_version}.0"

export PATH="$(python3 -m site --user-base)/bin:${PATH}"
resolve_clang_format_bin
fi
fi

[[ -n "${CLANG_FORMAT_BIN}" ]] || {
Expand Down
96 changes: 96 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,99 @@ jobs:
rpmbuild -ba ~/rpmbuild/SPECS/opencattus.spec
ls -l ~/rpmbuild/RPMS/*/opencattus-installer*.rpm
'

deb-build:
name: DEB Build (Ubuntu 24.04)
needs: fast-tests
runs-on:
- self-hosted
- Linux
- X64
timeout-minutes: 60

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Verify Podman runner state
run: |
set -euo pipefail
command -v podman >/dev/null || {
echo "Missing required command on self-hosted runner: podman" >&2
exit 1
}

podman system migrate || true
podman info >/dev/null

- name: Prepare Conan cache
run: |
set -euo pipefail
mkdir -p "${HOME}/.cache/opencattus/conan/ubuntu24"
mkdir -p "${HOME}/.cache/opencattus/cpm/ubuntu24"
mkdir -p "${HOME}/.cache/opencattus/sources/ubuntu24"

- name: Build DEB in Ubuntu 24.04 container
run: |
set -euo pipefail
podman run --rm \
-v "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:z" \
-v "${HOME}/.cache/opencattus/conan/ubuntu24:/root/.conan2:z" \
-v "${HOME}/.cache/opencattus/cpm/ubuntu24:/root/.cache/CPM:z" \
-v "${HOME}/.cache/opencattus/sources/ubuntu24:/root/.cache/opencattus/sources:z" \
-w "${GITHUB_WORKSPACE}" \
docker.io/library/ubuntu:24.04 \
bash -lc '
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt update
apt install -y ca-certificates curl git dpkg-dev \
build-essential cmake ninja-build \
pkg-config python3 python3-pip python3-venv \
autoconf automake libtool meson perl \
libglibmm-2.4-dev libnewt-dev libsystemd-dev
export OPENCATTUS_SOURCE_CACHE="/root/.cache/opencattus/sources"
mkdir -p "${OPENCATTUS_SOURCE_CACHE}"
fetch_source() {
local url="$1"
local path="$2"
local tmp="${path}.tmp"

if [ -s "${path}" ] && python3 -m zipfile -t "${path}" >/dev/null 2>&1; then
return 0
fi

rm -f "${path}" "${tmp}"
for attempt in 1 2 3 4 5; do
if curl --fail --location --retry 8 --retry-delay 5 \
--connect-timeout 20 --output "${tmp}" "${url}" &&
python3 -m zipfile -t "${tmp}" >/dev/null 2>&1; then
mv "${tmp}" "${path}"
return 0
fi

rm -f "${tmp}"
sleep 5
done

echo "Failed to fetch ${url}" >&2
return 1
}
export OPENCATTUS_FARGS_ARCHIVE="${OPENCATTUS_SOURCE_CACHE}/cmake-forward-arguments-8c50d1f956172edb34e95efa52a2d5cb1f686ed2.zip"
export OPENCATTUS_YCM_ARCHIVE="${OPENCATTUS_SOURCE_CACHE}/ycm-v0.13.0.zip"
fetch_source \
"https://github.com/polysquare/cmake-forward-arguments/archive/8c50d1f956172edb34e95efa52a2d5cb1f686ed2.zip" \
"${OPENCATTUS_FARGS_ARCHIVE}"
fetch_source \
"https://github.com/robotology/ycm/archive/refs/tags/v0.13.0.zip" \
"${OPENCATTUS_YCM_ARCHIVE}"
python3 -m venv /tmp/conan-venv
/tmp/conan-venv/bin/pip install conan
export PATH="/tmp/conan-venv/bin:${PATH}"
conan profile detect --force
git config --global --add safe.directory "$(pwd)"
cmake -S . -B build-deb -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=OFF
cmake --build build-deb --target opencattus -j"$(nproc)"
scripts/build-deb.sh build-deb out/deb
ls -l out/deb/opencattus-installer*.deb
'
2 changes: 1 addition & 1 deletion ansible/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ FROM vagrantlibvirt/vagrant-libvirt:latest
ENV VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT=1
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=America/Sao_Paulo
RUN apt-get update -y && apt-get install ansible -y
RUN apt update -y && apt install ansible -y
RUN vagrant plugin install vagrant-scp
1 change: 0 additions & 1 deletion format-changed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ resolve_clang_format_bin() {
candidates+=("/opt/homebrew/opt/llvm@${required_version}/bin/clang-format")
fi

candidates+=("clang-format-19")
candidates+=("clang-format")

for candidate in "${candidates[@]}"; do
Expand Down
8 changes: 4 additions & 4 deletions include/opencattus/models/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ class OS {
* @enum Platform
* @brief Enumeration representing different platforms of the OS.
*/
enum class Platform { el8, el9, el10 };
enum class Platform { el8, el9, el10, ubuntu24 };

/**
* @enum Distro
* @brief Enumeration representing different distributions of the OS.
*/
enum class Distro { RHEL, OL, Rocky, AlmaLinux };
enum class Distro { RHEL, OL, Rocky, AlmaLinux, Ubuntu };

/**
* @enum PackageManager
Expand All @@ -68,8 +68,8 @@ class OS {
std::variant<std::monostate, Platform> m_platform;
std::variant<std::monostate, Distro> m_distro;
std::optional<std::string> m_kernel; // kernel version may be uninitialized
unsigned m_majorVersion {};
unsigned m_minorVersion {};
unsigned m_majorVersion { };
unsigned m_minorVersion { };

void setMajorVersion(unsigned int majorVersion);

Expand Down
9 changes: 7 additions & 2 deletions include/opencattus/services/xcat.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace opencattus::services {
class XCAT : public Provisioner<XCAT> {
public:
struct Image {
std::vector<std::string_view> otherpkgs = {};
std::vector<std::string_view> otherpkgs = { };
// @TODO: We need to support more than one osimage (:
// this can be a default osimage though
std::string osimage;
Expand Down Expand Up @@ -230,6 +230,11 @@ class XCAT : public Provisioner<XCAT> {
*/
static void configureEL9();

/**
* @brief Configures xCAT netboot templates for Ubuntu 24.04.
*/
static void configureUbuntu24();

public:
XCAT();

Expand Down Expand Up @@ -275,7 +280,7 @@ class XCAT : public Provisioner<XCAT> {
*/
void createImage(ImageType = ImageType::Netboot,
NodeType = NodeType::Compute,
const std::vector<ScriptBuilder>& customizations = {});
const std::vector<ScriptBuilder>& customizations = { });

/**
* @brief Adds nodes to the provisioning system.
Expand Down
62 changes: 62 additions & 0 deletions scripts/build-deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

set -Eeuo pipefail

build_dir=${1:-build-host}
output_dir=${2:-out/deb}
package_name=${OPENCATTUS_DEB_PACKAGE_NAME:-opencattus-installer-debug}

version=$(awk '/^Version:/ {print $2; exit}' rpmspecs/opencattus.spec)
release=$(awk '/^Release:/ {print $2; exit}' rpmspecs/opencattus.spec)
architecture=$(dpkg --print-architecture)
package_root="${output_dir}/${package_name}_${version}-${release}_${architecture}"
binary_path="${build_dir}/src/opencattus"

[[ -x "${binary_path}" ]] || {
echo "OpenCATTUS binary not found or not executable: ${binary_path}" >&2
exit 1
}

rm -rf "${package_root}"
install -d \
"${package_root}/DEBIAN" \
"${package_root}/usr/bin" \
"${package_root}/opt/opencattus/conf/repos"

install -m 755 "${binary_path}" "${package_root}/usr/bin/opencattus"
install -m 644 repos/repos.conf "${package_root}/opt/opencattus/conf/repos/repos.conf"
install -m 644 repos/alma.conf "${package_root}/opt/opencattus/conf/repos/alma.conf"
install -m 644 repos/rhel.conf "${package_root}/opt/opencattus/conf/repos/rhel.conf"
install -m 644 repos/oracle.conf "${package_root}/opt/opencattus/conf/repos/oracle.conf"
install -m 644 repos/rocky-upstream.conf \
"${package_root}/opt/opencattus/conf/repos/rocky-upstream.conf"
install -m 644 repos/rocky-vault.conf \
"${package_root}/opt/opencattus/conf/repos/rocky-vault.conf"

depends=""
if command -v dpkg-shlibdeps >/dev/null 2>&1; then
depends=$(dpkg-shlibdeps -O -e"${package_root}/usr/bin/opencattus" 2>/dev/null \
| sed -n 's/^shlibs:Depends=//p' || true)
fi

if [[ -z "${depends}" ]]; then
depends="libnewt0.52"
fi

installed_size=$(du -sk "${package_root}" | awk '{print $1}')
cat >"${package_root}/DEBIAN/control" <<EOF
Package: ${package_name}
Version: ${version}-${release}
Section: admin
Priority: optional
Architecture: ${architecture}
Maintainer: VersatusHPC <vinicius@ferrao.net.br>
Depends: ${depends}
Installed-Size: ${installed_size}
Homepage: https://github.com/versatushpc/opencattus
Description: OpenCATTUS Installer
OpenCATTUS installs and configures an HPC cluster from a single
head node.
EOF

dpkg-deb --build --root-owner-group "${package_root}" "${output_dir}"
60 changes: 55 additions & 5 deletions src/NFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,28 @@ opencattus::services::ScriptBuilder NFS::installScript(const OS& osinfo)
{
using namespace opencattus;
services::ScriptBuilder builder(osinfo);
const auto nfsServerPackage
= osinfo.getPackageType() == OS::PackageType::DEB
? std::string_view("nfs-kernel-server")
: std::string_view("nfs-utils");
const auto nfsServerServices
= osinfo.getPackageType() == OS::PackageType::DEB
? std::string_view("rpcbind nfs-kernel-server")
: std::string_view("rpcbind nfs-server");
builder.addNewLine()
.addCommand("# Variables")
.addCommand("HEADNODE=$(hostname -s)")
.addNewLine()
.addCommand("# install packages")
.addPackage("nfs-utils")
.addPackage(nfsServerPackage)
.addNewLine()
.addCommand("# Add exports to /etc/exports")
.addLineToFile("/etc/exports", "/home",
.addLineToFile("/etc/exports", "^/home[[:space:]]",
"/home *(rw,no_subtree_check,fsid={},no_root_squash)", 10)
.addLineToFile("/etc/exports", "/opt/ohpc/pub",
"/opt/ohpc/pub *(ro,no_subtree_check,fsid={})", 11)
.addLineToFile("/etc/exports", "/opt/spack", "/opt/spack *(ro)");
.addLineToFile(
"/etc/exports", "/opt/spack", "/opt/spack *(ro,no_subtree_check)");
if (utils::singleton::answerfile()->system.provisioner == "xcat") {
builder
.addLineToFile("/etc/exports", "/tftpboot",
Expand All @@ -66,7 +75,7 @@ opencattus::services::ScriptBuilder NFS::installScript(const OS& osinfo)
"/install *(rw,no_root_squash,sync,no_subtree_check)")
.addNewLine();
}
builder.enableService("rpcbind nfs-server")
builder.enableService(nfsServerServices)
.addCommand("exportfs -a > /dev/null 2>&1 || :")
.addNewLine()
.addCommand(R"(# Update firewall rules
Expand All @@ -82,6 +91,10 @@ opencattus::services::ScriptBuilder NFS::imageInstallScript(
{
using namespace opencattus;
services::ScriptBuilder builder(osinfo);
const auto nfsClientPackage
= osinfo.getPackageType() == OS::PackageType::DEB
? std::string_view("nfs-common")
: std::string_view("nfs-utils");
builder.addNewLine()
.addCommand("# Define variables (for shell script execution)")
.addCommand("IMAGE=\"{}\"", args.imageName)
Expand All @@ -96,7 +109,7 @@ opencattus::services::ScriptBuilder NFS::imageInstallScript(
.addCommand("chmod +x \"${{POSTINSTALL}}\"")
.addNewLine()
.addCommand("# Add required packages to the image")
.addLineToFile("${PKGLIST}", "nfs-utils", "nfs-utils")
.addLineToFile("${PKGLIST}", nfsClientPackage, "{}", nfsClientPackage)
.addLineToFile("${PKGLIST}", "autofs", "autofs")
.addNewLine()
.addCommand("# Configure autofs")
Expand Down Expand Up @@ -144,7 +157,9 @@ TEST_CASE("installScript")
CHECK(script.contains("systemctl is-active --quiet firewalld.service"));
CHECK(
script.contains("/home *(rw,no_subtree_check,fsid=10,no_root_squash)"));
CHECK(script.contains(R"(grep -q "^/home[[:space:]]" "/etc/exports")"));
CHECK(script.contains("/opt/ohpc/pub *(ro,no_subtree_check,fsid=11)"));
CHECK(script.contains("/opt/spack *(ro,no_subtree_check)"));
CHECK(script.contains(
"/tftpboot *(rw,no_root_squash,sync,no_subtree_check)"));
CHECK(
Expand Down Expand Up @@ -185,6 +200,41 @@ TEST_CASE("installImageScript")
R"(chdef -t osimage ${IMAGE} postinstall="${POSTINSTALL}")"));
};

TEST_CASE("installImageScript uses Debian package names for Ubuntu images")
{
const OS osinfo
= opencattus::models::OS(OS::Distro::Ubuntu, OS::Platform::ubuntu24, 4);
const auto builder = NFS::imageInstallScript(osinfo,
{ .imageName = "ubuntu24.04-x86_64-netboot-compute",
.rootfs = "/install/netboot/ubuntu24.04/x86_64/compute/rootimg",
.postinstall = "/install/custom/netboot/compute.postinstall",
.pkglist = "/install/custom/netboot/compute.otherpkglist" });
const std::string script = builder.toString();
CHECK(script.contains(R"(echo "nfs-common" >> "${PKGLIST}")"));
CHECK_FALSE(script.contains(R"(echo "nfs-utils" >> "${PKGLIST}")"));
};

TEST_CASE("installScript uses Debian NFS server package names on Ubuntu")
{
const OS osinfo
= opencattus::models::OS(OS::Distro::Ubuntu, OS::Platform::ubuntu24, 4);
opencattus::services::initializeSingletonsOptions(
std::make_unique<const Options>());
opencattus::Singleton<const models::AnswerFile>::init(
[]() -> std::unique_ptr<const models::AnswerFile> {
auto answerfile = std::make_unique<models::AnswerFile>(
"test/sample/answerfile/rocky9-xcat.ini");
return answerfile;
});
const auto builder = NFS::installScript(osinfo);
const auto scriptStr = builder.toString();
const auto script = std::string_view(scriptStr);

CHECK(script.contains("DEBIAN_FRONTEND=noninteractive apt install -y "
"nfs-kernel-server"));
CHECK(script.contains("systemctl enable --now rpcbind nfs-kernel-server"));
}

}

TEST_SUITE_END();
Loading
Loading