From dcbddc36354be7ab8fbb5d7dd3e99828e3cc730c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Doru=20Bl=C3=A2nzeanu?= Date: Mon, 18 Nov 2024 09:22:17 +0200 Subject: [PATCH] Add devcontainer config (#54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add dev container configuration The following dev container configuration can be found in the .devcontainer directory. It contains: - devcontainer.json a configuration file for the Dev container that puts everything toghether - create_env.sh script that is run on the host machine and creates a .devcontainer/.env file that contains the necessary group info for the container image build phase - Dockerfile.base config for a base container image that is pre-built by using the .github/workflows/CreateDevcontainerImage.yml action that is automatically triggered when a change is detected for Dockerfile.base or the workflow configuration. - Dockerfile config that uses the pre-build image as a base image, creates a group with the same GID of the device being passed to the docker container and adds the user to that group Note: The reason why the environment file generation is needed is because in order to access the device (/dev/kvm) inside the container, the user needs to belong to the correct group, so the group is created at image build time. Signed-off-by: Doru Blânzeanu * Change the link to GHCR image Signed-off-by: Doru Blânzeanu * Change device ownership inside the container - This avoids creating a new group in a new container image - Also there is no need for the environment file to be dynamically generated Signed-off-by: Doru Blânzeanu * Update Dockerfile in github action Signed-off-by: Doru Blânzeanu * Update GHCR link to use the hyperlight-dev container image Signed-off-by: Doru Blânzeanu * Add defaults to arguments of container image Dockerfile Signed-off-by: Doru Blânzeanu * Fix Dockerfile and update workflow to read the rust version Signed-off-by: Doru Blânzeanu * Add codespace reference to README.md Signed-off-by: Doru Blânzeanu * Remove unused persmission for gh workflow Signed-off-by: Doru Blânzeanu * Small changes to comments and bash script for consistency Signed-off-by: Doru Blânzeanu * Add gnuplot to devcontainer image Signed-off-by: Doru Blânzeanu --------- Signed-off-by: Doru Blânzeanu --- .devcontainer/Dockerfile | 63 ++++++++++++++++ .devcontainer/devcontainer.json | 33 +++++++++ .devcontainer/setup.sh | 5 ++ .github/workflows/CreateDevcontainerImage.yml | 71 +++++++++++++++++++ .gitignore | 2 +- README.md | 4 ++ 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/setup.sh create mode 100644 .github/workflows/CreateDevcontainerImage.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..0b002dab --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,63 @@ +## Dockerfile for devcontainer + +FROM mcr.microsoft.com/devcontainers/base:debian AS base + +ARG USER=vscode +ARG GROUP=vscode + +ENV HOME="/home/${USER}" +ENV PATH="$HOME/.cargo/bin:$PATH" + +# Install dependencies +RUN apt-get update \ + && apt-get -y install \ + build-essential \ + cmake \ + curl \ + git \ + gnupg \ + gnuplot \ + lsb-release \ + make \ + software-properties-common \ + sudo \ + wget + +ARG LLVM_VERSION=17 + +# Install llvm +RUN wget https://apt.llvm.org/llvm.sh \ + && chmod +x ./llvm.sh \ + && sudo ./llvm.sh ${LLVM_VERSION} all \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/clang-cl /usr/bin/clang-cl \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/llvm-lib /usr/bin/llvm-lib \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/lld-link /usr/bin/lld-link \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/llvm-ml /usr/bin/llvm-ml \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/ld.lld /usr/bin/ld.lld \ + && sudo ln -s /usr/lib/llvm-${LLVM_VERSION}/bin/clang /usr/bin/clang + +FROM base AS dev + +# Make sure the devcontainer user has sudo access +RUN chown -R "${USER}:${GROUP}" /home/${USER} \ + && echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Persist bash hystory +RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ + && mkdir /commandhistory \ + && touch /commandhistory/.bash_history \ + && chown -R "${USER}" /commandhistory \ + && echo "$SNIPPET" >> "/home/${USER}/.bashrc" + +USER $USER + +ARG RUST_TOOLCHAIN=1.81.0 + +# Install rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && rustup default ${RUST_TOOLCHAIN} \ + && rustup target add x86_64-unknown-linux-gnu \ + && rustup target add x86_64-unknown-none \ + && rustup target add x86_64-pc-windows-msvc \ + && cargo install just + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..d76b2985 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,33 @@ +// For more info on the configuration below, check out the link: +// https://code.visualstudio.com/docs/devcontainers/create-dev-container +{ + "name": "Hyperlight", + + "image": "ghcr.io/hyperlight-dev/hyperlight-devcontainer:latest", + + "containerUser": "vscode", + // Environment for the container also used by the `postCreateCommand` + "containerEnv": { + "DEVICE": "/dev/kvm", + "KVM_SHOULD_BE_PRESENT": "true", + "REMOTE_USER": "vscode", + "REMOTE_GROUP": "vscode" + }, + + "runArgs": [ + "--device=/dev/kvm" + ], + + // Use 'postCreateCommand' to run commands after the container is created + "postCreateCommand": "bash .devcontainer/setup.sh", + + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cmake-tools", + "rust-lang.rust-analyzer", + "vadimcn.vscode-lldb" + ] + } + } +} diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100644 index 00000000..db7b7196 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# Change device ownership +sudo chown -R $REMOTE_USER:$REMOTE_GROUP $DEVICE + diff --git a/.github/workflows/CreateDevcontainerImage.yml b/.github/workflows/CreateDevcontainerImage.yml new file mode 100644 index 00000000..de6fd4cb --- /dev/null +++ b/.github/workflows/CreateDevcontainerImage.yml @@ -0,0 +1,71 @@ +name: Create and publish devcontainer Docker image + +on: + push: + branches: + - "main" + paths: + - ".devcontainer/Dockerfile" + - ".github/workflows/CreateDevcontainerImage.yml" + - "rust-toolchain.toml" + +# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}-devcontainer + USER: vscode + GROUP: vscode + LLVM_VERSION: 17 + RUST_TOOLCHAIN_DEFAULT: 1.81.0 + RUST_TOOLCHAIN_FILE: rust-toolchain.toml + +# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. +jobs: + build-and-push-image: + runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Read Rust toolchain version from ${{ env.RUST_TOOLCHAIN_FILE }} + id: toolchain + run: | + version=$(cat ${{ env.RUST_TOOLCHAIN_FILE }} | sed -n '/\[toolchain\]/,/^\[/{/^\s*channel = /s/[^"]*"\([^"]*\)".*/\1/p}') + cat ${{ env.RUST_TOOLCHAIN_FILE }} | grep $version &> /dev/null \ + && echo "RUST_TOOLCHAIN=${version}" >> "$GITHUB_OUTPUT" \ + || echo "RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN_FILE }}" >> "$GITHUB_OUTPUT" + + # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@v1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: ./.devcontainer + push: true + tags: | + ${{ steps.meta.outputs.tags }} + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + labels: ${{ steps.meta.outputs.labels }} + build-args: | + USER=${{ env.USER }} + GROUP=${{ env.GROUP }} + LLVM_VERSION=${{ env.LLVM_VERSION }} + RUST_TOOLCHAIN=${{ steps.toolchain.outputs.RUST_TOOLCHAIN }} diff --git a/.gitignore b/.gitignore index 3a2238ee..fd2e45d7 100644 --- a/.gitignore +++ b/.gitignore @@ -474,4 +474,4 @@ hyperlight_guest.h # created by vs code c# extension .mono -!.gitkeep \ No newline at end of file +!.gitkeep diff --git a/README.md b/README.md index 1552ee0b..aa313e58 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,10 @@ If you get the error `Error: NoHypervisorFound` and KVM or mshv is set up then t For more details on how to verify that KVM is correctly installed and permissions are correct, follow the guide [here](https://help.ubuntu.com/community/KVM/Installation). +### Or you can use a codespace + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/hyperlight-dev/hyperlight) + ## Contributing to Hyperlight If you are interested in contributing to Hyperlight, running the entire test-suite is a good way to get started. To do so, on your console, run the following commands: