diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 970b86e92c..0cb85955ac 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -34,7 +34,7 @@ jobs: - name: Update PATH run: echo "$PWD/out/cockroachdb/bin:$PWD/out/clickhouse" >> "$GITHUB_PATH" - name: Install Pre-Requisites - run: ./tools/install_prerequisites.sh -y + run: ./tools/install_builder_prerequisites.sh -y - name: Check build of deployed Omicron packages run: cargo run --bin omicron-package -- check @@ -52,7 +52,7 @@ jobs: - name: Update PATH run: echo "$PWD/out/cockroachdb/bin:$PWD/out/clickhouse" >> "$GITHUB_PATH" - name: Install Pre-Requisites - run: ./tools/install_prerequisites.sh -y + run: ./tools/install_builder_prerequisites.sh -y - name: Run Clippy Lints # # Clippy's style nits are useful, but not worth keeping in CI. This @@ -75,7 +75,7 @@ jobs: - name: Update PATH run: echo "$PWD/out/cockroachdb/bin:$PWD/out/clickhouse" >> "$GITHUB_PATH" - name: Install Pre-Requisites - run: ./tools/install_prerequisites.sh -y + run: ./tools/install_builder_prerequisites.sh -y - name: Test build documentation run: cargo doc @@ -117,7 +117,7 @@ jobs: - name: Update PATH run: echo "$PWD/out/cockroachdb/bin:$PWD/out/clickhouse" >> "$GITHUB_PATH" - name: Install Pre-Requisites - run: ./tools/install_prerequisites.sh -y + run: ./tools/install_builder_prerequisites.sh -y - name: Create temporary directory for test outputs run: mkdir -p $OMICRON_TMP - name: Build diff --git a/Dockerfile b/Dockerfile index 7fde038a9e..b7e4963c5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ WORKDIR /usr/src/omicron # sudo and path thing are only needed to get prereqs script to run ENV PATH=/usr/src/omicron/out/cockroachdb/bin:/usr/src/omicron/out/clickhouse:${PATH} RUN apt-get update && apt-get install -y sudo --no-install-recommends && rm -rf /var/lib/apt/lists/* -RUN tools/install_prerequisites.sh -y +RUN tools/install_builder_prerequisites.sh -y RUN cargo build --release diff --git a/deploy/src/bin/thing-flinger.rs b/deploy/src/bin/thing-flinger.rs index 2b354847df..2d4e549cb7 100644 --- a/deploy/src/bin/thing-flinger.rs +++ b/deploy/src/bin/thing-flinger.rs @@ -274,27 +274,27 @@ fn do_install_prereqs(config: &Config) -> Result<()> { // run install_prereqs on each server let builder = &config.servers[&config.builder.server]; - let build_server = (builder, &config.builder.omicron_path); - let all_servers = std::iter::once(build_server).chain( - config.servers.iter().filter_map(|(name, server)| { - // skip running prereq installing on a deployment target if it is - // also the builder, because we're already running it on the builder - if *name == config.builder.server { - None - } else { - Some((server, &config.deployment.staging_dir)) - } - }), + let all_servers = config + .servers + .iter() + .map(|(_name, server)| (server, &config.deployment.staging_dir)); + + // -y: assume yes instead of prompting + // -p: skip check that deps end up in $PATH + let cmd = format!( + "cd {} && mkdir -p out && pfexec ./tools/install_builder_prerequisites.sh -y -p", + config.builder.omicron_path.display() ); + println!("install builder prerequisites on {}", builder.addr); + ssh_exec(builder, &cmd, false)?; for (server, root_path) in all_servers { // -y: assume yes instead of prompting - // -p: skip check that deps end up in $PATH let cmd = format!( - "cd {} && mkdir -p out && pfexec ./tools/install_prerequisites.sh -y -p", + "cd {} && mkdir -p out && pfexec ./tools/install_runner_prerequisites.sh -y", root_path.display() ); - println!("install prerequisites on {}", server.addr); + println!("install runner prerequisites on {}", server.addr); ssh_exec(server, &cmd, false)?; } diff --git a/docs/how-to-run-simulated.adoc b/docs/how-to-run-simulated.adoc index 0a1b4a086c..4f9186c390 100644 --- a/docs/how-to-run-simulated.adoc +++ b/docs/how-to-run-simulated.adoc @@ -27,7 +27,7 @@ Prerequisite software may be installed with the following script: [source,text] ---- -$ ./tools/install_prerequisites.sh +$ ./tools/install_builder_prerequisites.sh ---- == Running diff --git a/docs/how-to-run.adoc b/docs/how-to-run.adoc index de8840f99e..7a8a821986 100644 --- a/docs/how-to-run.adoc +++ b/docs/how-to-run.adoc @@ -25,6 +25,18 @@ Any additional prerequisite software may be installed with the following script: $ ./tools/install_prerequisites.sh ---- +This script expects that you are both attempting to compile code and execute +it on the same machine. If you'd like to have a different machine for a "builder" +and a "runner", you can use the two more fine-grained scripts: + +[source,text] +---- +# To be invoked on the machine building Omicron +$ ./tools/install_builder_prerequisites.sh +# To be invoked on the machine running Omicron +$ ./tools/install_runner_prerequisites.sh +---- + === Make (or unmake) me a Gimlet! The sled agent expects to manage a real Gimlet. However, until those are built, diff --git a/tools/install_builder_prerequisites.sh b/tools/install_builder_prerequisites.sh new file mode 100755 index 0000000000..ae46b7224e --- /dev/null +++ b/tools/install_builder_prerequisites.sh @@ -0,0 +1,200 @@ +#!/bin/bash + +set -eu + +MARKER=/etc/opt/oxide/NO_INSTALL +if [[ -f "$MARKER" ]]; then + echo "This system has the marker file $MARKER, aborting." >&2 + exit 1 +fi + +# Set the CWD to Omicron's source. +SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +cd "${SOURCE_DIR}/.." + +function on_exit +{ + echo "Something went wrong, but this script is idempotent - If you can fix the issue, try re-running" +} + +trap on_exit ERR + +# Parse command line options: +# +# -y Assume "yes" intead of showing confirmation prompts. +# -p Skip checking paths +ASSUME_YES="false" +SKIP_PATH_CHECK="false" +while getopts yp flag +do + case "${flag}" in + y) ASSUME_YES="true" ;; + p) SKIP_PATH_CHECK="true" ;; + esac +done + +# Offers a confirmation prompt, unless we were passed `-y`. +# +# Args: +# $1: Text to be displayed +function confirm +{ + if [[ "${ASSUME_YES}" == "true" ]]; then + response=y + else + read -r -p "$1 (y/n): " response + fi + case $response in + [yY]) + true + ;; + *) + false + ;; + esac +} + +# Packages to be installed on all OSes: +# +# - libpq, the PostgreSQL client lib. +# We use Diesel's PostgreSQL support to connect to CockroachDB (which is +# wire-compatible with PostgreSQL). Diesel uses the native libpq to do this. +# `pg_config` is a utility which may be used to query for the installed +# PostgreSQL libraries, and is expected by the Omicron build to exist in +# the developer's PATH variable. +# - pkg-config, a tool for querying installed libraries. +# +# Packages to be installed on Helios only: +# +# - pkg, the IPS client (though likely it will just be updated) +# - build-essential: Common development tools +# - brand/omicron1/tools: Oxide's omicron1-brand Zone + +HOST_OS=$(uname -s) +if [[ "${HOST_OS}" == "Linux" ]]; then + packages=( + 'libpq-dev' + 'pkg-config' + 'xmlsec1' + 'libxmlsec1-dev' + 'libxmlsec1-openssl' + 'libclang-dev' + 'libsqlite3-dev' + ) + sudo apt-get update + if [[ "${ASSUME_YES}" == "true" ]]; then + sudo apt-get install -y ${packages[@]} + else + confirm "Install (or update) [${packages[*]}]?" && sudo apt-get install ${packages[@]} + fi +elif [[ "${HOST_OS}" == "SunOS" ]]; then + packages=( + 'pkg:/package/pkg' + 'build-essential' + 'library/postgresql-13' + 'pkg-config' + 'library/libxmlsec1' + # "bindgen leverages libclang to preprocess, parse, and type check C and C++ header files." + 'pkg:/ooce/developer/clang-120' + ) + + # Install/update the set of packages. + # Explicitly manage the return code using "rc" to observe the result of this + # command without exiting the script entirely (due to bash's "errexit"). + rc=0 + confirm "Install (or update) [${packages[*]}]?" && { pfexec pkg install -v "${packages[@]}" || rc=$?; } + # Return codes: + # 0: Normal Success + # 4: Failure because we're already up-to-date. Also acceptable. + if [[ "$rc" -ne 4 ]] && [[ "$rc" -ne 0 ]]; then + exit "$rc" + fi + + pkg list -v "${packages[@]}" +elif [[ "${HOST_OS}" == "Darwin" ]]; then + packages=( + 'postgresql' + 'pkg-config' + 'libxmlsec1' + ) + confirm "Install (or update) [${packages[*]}]?" && brew install ${packages[@]} +else + echo "Unsupported OS: ${HOST_OS}" + exit -1 +fi + +# CockroachDB and Clickhouse are used by Omicron for storage of +# control plane metadata and metrics. +# +# They are used in a couple of spots within Omicron: +# +# - Test Suite: The test suite, regardless of host OS, builds temporary +# databases for testing, and expects `cockroach` and `clickhouse` to +# exist as a part of the PATH. +# - Packaging: When constructing packages on Helios, these utilities +# are packaged into zones which may be launched by the sled agent. + +./tools/ci_download_cockroachdb +./tools/ci_download_clickhouse + +# Install static console assets. These are used when packaging Nexus. +./tools/ci_download_console + +# Download the OpenAPI spec for maghemite. This is required to build the +# ddm-admin-api crate. +./tools/ci_download_maghemite_openapi + +# Validate the PATH: +expected_in_path=( + 'pg_config' + 'pkg-config' + 'cockroach' + 'clickhouse' +) + +function show_hint +{ + case "$1" in + "pg_config") + if [[ "${HOST_OS}" == "SunOS" ]]; then + echo "On illumos, $1 is typically found in '/opt/ooce/bin'" + fi + ;; + "pkg-config") + if [[ "${HOST_OS}" == "SunOS" ]]; then + echo "On illumos, $1 is typically found in '/usr/bin'" + fi + ;; + "cockroach") + echo "$1 should have been installed to '$PWD/out/cockroachdb/bin'" + ;; + "clickhouse") + echo "$1 should have been installed to '$PWD/out/clickhouse'" + ;; + *) + ;; + esac +} + +# Check all paths before returning an error, unless we were told not too. +if [[ "$SKIP_PATH_CHECK" == "true" ]]; then + echo "All prerequisites installed successfully" + exit 0 +fi + +ANY_PATH_ERROR="false" +for command in "${expected_in_path[@]}"; do + rc=0 + which "$command" &> /dev/null || rc=$? + if [[ "$rc" -ne 0 ]]; then + echo "ERROR: $command seems installed, but was not found in PATH. Please add it." + show_hint "$command" + ANY_PATH_ERROR="true" + fi +done + +if [[ "$ANY_PATH_ERROR" == "true" ]]; then + exit -1 +fi + +echo "All builder prerequisites installed successfully, and PATH looks valid" diff --git a/tools/install_prerequisites.sh b/tools/install_prerequisites.sh index 5c8ddf795f..0323f44890 100755 --- a/tools/install_prerequisites.sh +++ b/tools/install_prerequisites.sh @@ -2,208 +2,9 @@ set -eu -MARKER=/etc/opt/oxide/NO_INSTALL -if [[ -f "$MARKER" ]]; then - echo "This system has the marker file $MARKER, aborting." >&2 - exit 1 -fi - # Set the CWD to Omicron's source. SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" cd "${SOURCE_DIR}/.." -function on_exit -{ - echo "Something went wrong, but this script is idempotent - If you can fix the issue, try re-running" -} - -trap on_exit ERR - -# Parse command line options: -# -# -y Assume "yes" intead of showing confirmation prompts. -ASSUME_YES="false" -SKIP_PATH_CHECK="false" -while getopts yp flag -do - case "${flag}" in - y) ASSUME_YES="true" ;; - p) SKIP_PATH_CHECK="true" ;; - esac -done - -# Offers a confirmation prompt, unless we were passed `-y`. -# -# Args: -# $1: Text to be displayed -function confirm -{ - if [[ "${ASSUME_YES}" == "true" ]]; then - response=y - else - read -r -p "$1 (y/n): " response - fi - case $response in - [yY]) - true - ;; - *) - false - ;; - esac -} - -# Packages to be installed on all OSes: -# -# - libpq, the PostgreSQL client lib. -# We use Diesel's PostgreSQL support to connect to CockroachDB (which is -# wire-compatible with PostgreSQL). Diesel uses the native libpq to do this. -# `pg_config` is a utility which may be used to query for the installed -# PostgreSQL libraries, and is expected by the Omicron build to exist in -# the developer's PATH variable. -# - pkg-config, a tool for querying installed libraries. -# -# Packages to be installed on Helios only: -# -# - pkg, the IPS client (though likely it will just be updated) -# - build-essential: Common development tools -# - brand/omicron1/tools: Oxide's omicron1-brand Zone - -HOST_OS=$(uname -s) -if [[ "${HOST_OS}" == "Linux" ]]; then - packages=( - 'libpq-dev' - 'pkg-config' - 'xmlsec1' - 'libxmlsec1-dev' - 'libxmlsec1-openssl' - 'libclang-dev' - 'libsqlite3-dev' - ) - sudo apt-get update - if [[ "${ASSUME_YES}" == "true" ]]; then - sudo apt-get install -y ${packages[@]} - else - confirm "Install (or update) [${packages[*]}]?" && sudo apt-get install ${packages[@]} - fi -elif [[ "${HOST_OS}" == "SunOS" ]]; then - packages=( - 'pkg:/package/pkg' - 'build-essential' - 'library/postgresql-13' - 'pkg-config' - 'brand/omicron1/tools' - 'library/libxmlsec1' - # "bindgen leverages libclang to preprocess, parse, and type check C and C++ header files." - 'pkg:/ooce/developer/clang-120' - ) - - # Install/update the set of packages. - # Explicitly manage the return code using "rc" to observe the result of this - # command without exiting the script entirely (due to bash's "errexit"). - rc=0 - confirm "Install (or update) [${packages[*]}]?" && { pfexec pkg install -v "${packages[@]}" || rc=$?; } - # Return codes: - # 0: Normal Success - # 4: Failure because we're already up-to-date. Also acceptable. - if [[ "$rc" -ne 4 ]] && [[ "$rc" -ne 0 ]]; then - exit "$rc" - fi - - pkg list -v "${packages[@]}" -elif [[ "${HOST_OS}" == "Darwin" ]]; then - packages=( - 'postgresql' - 'pkg-config' - 'libxmlsec1' - ) - confirm "Install (or update) [${packages[*]}]?" && brew install ${packages[@]} -else - echo "Unsupported OS: ${HOST_OS}" - exit -1 -fi - -# CockroachDB and Clickhouse are used by Omicron for storage of -# control plane metadata and metrics. -# -# They are used in a couple of spots within Omicron: -# -# - Test Suite: The test suite, regardless of host OS, builds temporary -# databases for testing, and expects `cockroach` and `clickhouse` to -# exist as a part of the PATH. -# - Packaging: When constructing packages on Helios, these utilities -# are packaged into zones which may be launched by the sled agent. - -./tools/ci_download_cockroachdb -./tools/ci_download_clickhouse - -# Install static console assets. These are used when packaging Nexus. -./tools/ci_download_console - -# Download the OpenAPI spec for maghemite. This is required to build the -# ddm-admin-api crate. -./tools/ci_download_maghemite_openapi - -# Install OPTE -# -# OPTE is a Rust package that is consumed by a kernel module called xde. This -# installs the `xde` driver and some kernel bits required to work with that -# driver. -if [[ "${HOST_OS}" == "SunOS" ]]; then - ./tools/install_opte.sh -fi - -# Validate the PATH: -expected_in_path=( - 'pg_config' - 'pkg-config' - 'cockroach' - 'clickhouse' -) - -function show_hint -{ - case "$1" in - "pg_config") - if [[ "${HOST_OS}" == "SunOS" ]]; then - echo "On illumos, $1 is typically found in '/opt/ooce/bin'" - fi - ;; - "pkg-config") - if [[ "${HOST_OS}" == "SunOS" ]]; then - echo "On illumos, $1 is typically found in '/usr/bin'" - fi - ;; - "cockroach") - echo "$1 should have been installed to '$PWD/out/cockroachdb/bin'" - ;; - "clickhouse") - echo "$1 should have been installed to '$PWD/out/clickhouse'" - ;; - *) - ;; - esac -} - -# Check all paths before returning an error, unless we were told not too. -if [[ "$SKIP_PATH_CHECK" == "true" ]]; then - echo "All prerequisites installed successfully" - exit 0 -fi - -ANY_PATH_ERROR="false" -for command in "${expected_in_path[@]}"; do - rc=0 - which "$command" &> /dev/null || rc=$? - if [[ "$rc" -ne 0 ]]; then - echo "ERROR: $command seems installed, but was not found in PATH. Please add it." - show_hint "$command" - ANY_PATH_ERROR="true" - fi -done - -if [[ "$ANY_PATH_ERROR" == "true" ]]; then - exit -1 -fi - -echo "All prerequisites installed successfully, and PATH looks valid" +./tools/install_builder_prerequisites.sh "$@" +./tools/install_runner_prerequisites.sh "$@" diff --git a/tools/install_runner_prerequisites.sh b/tools/install_runner_prerequisites.sh new file mode 100755 index 0000000000..a24d3f9a95 --- /dev/null +++ b/tools/install_runner_prerequisites.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +set -eu + +MARKER=/etc/opt/oxide/NO_INSTALL +if [[ -f "$MARKER" ]]; then + echo "This system has the marker file $MARKER, aborting." >&2 + exit 1 +fi + +# Set the CWD to Omicron's source. +SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +cd "${SOURCE_DIR}/.." + +function on_exit +{ + echo "Something went wrong, but this script is idempotent - If you can fix the issue, try re-running" +} + +trap on_exit ERR + +# Parse command line options: +# +# -y Assume "yes" intead of showing confirmation prompts. +# -p Skip checking paths (currently unused) +ASSUME_YES="false" +while getopts yp flag +do + case "${flag}" in + y) ASSUME_YES="true" ;; + p) continue ;; + esac +done + +# Offers a confirmation prompt, unless we were passed `-y`. +# +# Args: +# $1: Text to be displayed +function confirm +{ + if [[ "${ASSUME_YES}" == "true" ]]; then + response=y + else + read -r -p "$1 (y/n): " response + fi + case $response in + [yY]) + true + ;; + *) + false + ;; + esac +} + +# Packages to be installed Helios: +# +# - libpq, the PostgreSQL client lib. +# We use Diesel's PostgreSQL support to connect to CockroachDB (which is +# wire-compatible with PostgreSQL). Diesel uses the native libpq to do this. +# `pg_config` is a utility which may be used to query for the installed +# PostgreSQL libraries, and is expected by the Omicron build to exist in +# the developer's PATH variable. +# - pkg-config, a tool for querying installed libraries. +# - pkg, the IPS client (though likely it will just be updated) +# - brand/omicron1/tools: Oxide's omicron1-brand Zone +HOST_OS=$(uname -s) +if [[ "${HOST_OS}" == "SunOS" ]]; then + packages=( + 'pkg:/package/pkg' + 'library/postgresql-13' + 'pkg-config' + 'brand/omicron1/tools' + 'library/libxmlsec1' + ) + + # Install/update the set of packages. + # Explicitly manage the return code using "rc" to observe the result of this + # command without exiting the script entirely (due to bash's "errexit"). + rc=0 + confirm "Install (or update) [${packages[*]}]?" && { pfexec pkg install -v "${packages[@]}" || rc=$?; } + # Return codes: + # 0: Normal Success + # 4: Failure because we're already up-to-date. Also acceptable. + if [[ "$rc" -ne 4 ]] && [[ "$rc" -ne 0 ]]; then + exit "$rc" + fi + + pkg list -v "${packages[@]}" +else + echo "Unsupported OS: ${HOST_OS}" + exit -1 +fi + +# Install OPTE +# +# OPTE is a Rust package that is consumed by a kernel module called xde. This +# installs the `xde` driver and some kernel bits required to work with that +# driver. +if [[ "${HOST_OS}" == "SunOS" ]]; then + ./tools/install_opte.sh +fi + +echo "All runner prerequisites installed successfully"