Skip to content
Merged
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
267 changes: 177 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,70 @@

# CoreSMD

## Summary of Repo

CoreSMD provides two plugins for [CoreDHCP](https://github.com/coredhcp/coredhcp) that integrate with [SMD](https://github.com/OpenCHAMI/smd). The first plugin, **coresmd**, uses SMD as a source of truth to provide DHCP leases. The second plugin, **bootloop**, dynamically assigns temporary IP addresses to unknown MACs until they can be updated in SMD.
# CoreSMD - Connect CoreDHCP/CoreDNS to SMD

## Contents

- [CoreSMD - Connect CoreDHCP/CoreDNS to SMD](#coresmd---connect-coredhcpcoredns-to-smd)
- [Contents](#contents)
- [Introduction](#introduction)
- [CoreDHCP](#coredhcp)
- [CoreDNS](#coredns)
- [Overview](#overview)
- [Build and Install](#build-and-install)
- [Build/Install with GoReleaser](#buildinstall-with-goreleaser)
- [Environment Variables](#environment-variables)
- [Building Locally with GoReleaser](#building-locally-with-goreleaser)
- [Building Locally on Bare Metal](#building-locally-on-bare-metal)
- [Building a Local Container](#building-a-local-container)
- [Testing](#testing)
- [CoreDHCP](#coredhcp-1)
- [CoreDNS](#coredns-1)
- [Running](#running)
- [Configuration](#configuration)
- [Preparation: SMD and BSS](#preparation-smd-and-bss)
- [Preparation: TFTP](#preparation-tftp)
- [Running](#running-1)
- [CoreDHCP](#coredhcp-2)
- [CoreDNS](#coredns-2)
- [More Reading](#more-reading)

---

## Table of Contents

- [About / Introduction](#about--introduction)
- [Overview](#overview)
- [Build / Install](#build--install)
- [Build/Install with GoReleaser](#buildinstall-with-goreleaser)
- [Environment Variables](#environment-variables)
- [Building Locally with GoReleaser](#building-locally-with-goreleaser)
- [Container](#container)
- [Bare Metal](#bare-metal)
- [Testing](#testing)
- [Running](#running)
- [Configuration](#configuration)
- [Preparation: SMD and BSS](#preparation-smd-and-bss)
- [Preparation: TFTP](#preparation-tftp)
- [Running CoreDHCP](#running-coredhcp)
- [More Reading](#more-reading)
## Introduction

---
CoreSMD provides plugins for both [CoreDHCP](https://github.com/coredhcp/coredhcp) and [CoreDNS](https://github.com/coredns/coredns) that allow DHCP requests and DNS lookups to use [SMD](https://github.com/OpenCHAMI/smd), the OpenCHAMI inventory service.

## About / Introduction
### CoreDHCP

CoreSMD provides two plugins. The first plugin, **coresmd**, uses SMD as a source of truth to provide DHCP leases. The second plugin, **bootloop**, dynamically assigns temporary IP addresses to unknown MACs until they can be updated in SMD.

This repository is part of the [OpenCHAMI](https://openchami.org) project. It extends CoreDHCP by integrating it with the SMD service so DHCP leases can be centrally managed. There are two primary plugins:

1. **coresmd**
1. **coresmd**
Provides DHCP leases based on data from SMD.

2. **bootloop**
2. **bootloop**
Assigns temporary IP addresses to unknown nodes. It also returns a DHCPNAK if it sees a node that has become known to SMD since its last lease, forcing a full DHCP handshake to get a new address (from **coresmd**).

The goal of **bootloop** is to ensure unknown nodes/BMCs continually attempt to get new IP addresses if they become known in SMD, while still having a short, discoverable address for tasks like [Magellan](https://github.com/OpenCHAMI/magellan).

See [**examples/coredhcp/**](https://github.com/OpenCHAMI/coresmd/tree/main/examples/coredhcp) for configuration examples.

### CoreDNS

The **coresmd** plugin allows hostnames/FQDNs for nodes and BMCs stored in SMD to be resolved to IP addresses.

See [**examples/coredns/**](https://github.com/OpenCHAMI/coresmd/tree/main/examples/coredns) for configuration examples.

---

## Overview

CoreSMD acts as a pull-through cache of DHCP information from SMD, ensuring that new or updated details in SMD can be reflected in DHCP lease assignments. This facilitates more dynamic environments where nodes might be added or changed frequently, and also simplifies discovery of unknown devices via the **bootloop** plugin.
CoreSMD acts as a pull-through cache of DHCP and DNS information from SMD, ensuring that new or updated details in SMD can be reflected in DHCP lease assignments and DNS records. This facilitates more dynamic environments where nodes might be added or changed frequently, and also simplifies discovery of unknown devices via the **bootloop** CoreDHCP plugin.

---

## Build / Install
## Build and Install

The plugins in this repository can be built into CoreDHCP either using a container-based approach (via the provided Dockerfile) or by statically compiling them into CoreDHCP on bare metal. Additionally, this project uses [GoReleaser](https://goreleaser.com/) to automate releases and include build metadata.
The plugins in this repository can be built into CoreDHCP/CoreDNS either using a container-based approach (via the provided Dockerfile) or by statically compiling them into CoreDHCP/CoreDNS on bare metal. Additionally, this project uses [GoReleaser](https://goreleaser.com/) to automate releases and include build metadata.

### Build/Install with GoReleaser

Expand All @@ -74,120 +89,192 @@ export BUILD_USER=$(whoami)
1. [Install GoReleaser](https://goreleaser.com/install/) if not already present.
2. Run GoReleaser in snapshot mode to produce a local build without publishing:
```bash
goreleaser release --snapshot --skip-publish --clean
goreleaser release --snapshot --clean --skip=publish
```
3. Check the `dist/` directory for the built binaries, which will include the embedded metadata.

#### Container
#### Building Locally on Bare Metal

This repository includes a `Dockerfile` that builds CoreDHCP (with its core plugins) plus **coresmd** and **bootloop**:
Simply run `go build` for each project:

```bash
docker build . --tag ghcr.io/openchami/coresmd:latest
go build ./build/coredhcp
go build ./build/coredns
```

#### Bare Metal
This will put `coredhcp` and `coredns` binaries in the repository root which can be used for building a container in the next step.

> [!NOTE]
> Certain source files in CoreDHCP only build on Linux. This may cause build errors on other platforms (e.g., macOS).
Verify that CoreDHCP contains the **coresmd** and **bootloop** plugins:

**Prerequisites**
- go >= 1.21
- git
- bash
- sed
```
$ ./coredhcp --plugins | grep -E 'coresmd|bootloop'
bootloop
coresmd
```

1. Create a clean directory for build artifacts:
```bash
mkdir build
```
2. Clone CoreSMD (this is **not strictly** required for building, but **is** needed if you want the plugin version included):
```bash
git clone https://github.com/openchami/coresmd
cd coresmd
./gen_version.bash
cd ..
```
3. Clone CoreDHCP and switch to the `coredhcp-generator` directory:
```bash
git clone https://github.com/coredhcp/coredhcp
cd coredhcp/cmds/coredhcp-generator
go mod download
go build
```
4. Run the generator to produce CoreDHCP with **coresmd** and **bootloop**:
```bash
./coredhcp-generator \
-f core-plugins.txt \
-t coredhcp.go.template \
-o ../../../build/coredhcp.go \
github.com/openchami/coresmd/coresmd \
github.com/openchami/coresmd/bootloop
```
5. Initialize the build directory as a Go module and build CoreDHCP:
```bash
cd ../../../build
go mod init coredhcp
go mod edit -go=1.21
go mod edit -replace=github.com/coredhcp/coredhcp=../coredhcp
go mod edit -replace=github.com/openchami/coresmd=../coresmd
go mod tidy
go build
```
...and that CoreDNS contains the **coresmd** plugin:

```
$ ./coredns --plugins | grep coresmd
coresmd
```

#### Building a Local Container

Your `coredhcp` binary (including these two plugins) will be in the `./build` directory.
To build a container that contains both CoreDHCP and CoreDNS, go through the [**Building Locally on Bare Metal**](#building-locally-on-bare-metal) step above, then run:

```bash
docker build . --tag ghcr.io/openchami/coresmd:latest
```

---

## Testing

### CoreDHCP

Currently, the repository does not include standalone test scripts for these plugins. However, once compiled into CoreDHCP, you can test the overall DHCP server behavior using tools like:

- [dhcping](https://github.com/rickardw/dhcping)
- [dnsmasq DHCP client testing](http://www.thekelleys.org.uk/dnsmasq/doc.html)

Because the plugins integrate with SMD, also verify that your SMD instance is returning correct data, and confirm the environment variables (if using GoReleaser) are correctly embedded in the binary.

### CoreDNS

See: <https://github.com/OpenCHAMI/coresmd/tree/main/examples/coredns#testing>

---

## Running

### Configuration

CoreDHCP requires a config file to run. See [`examples/coredhcp-config.yaml`](examples/coredhcp-config.yaml) for an example with detailed comments on how to enable and configure **coresmd** and **bootloop**.
CoreDHCP requires a config file to run. See [**examples/coredhcp/coredhcp.yaml**](examples/coredhcp-config.yaml) for an example with detailed comments on how to enable and configure **coresmd** and **bootloop**.

CoreDNS similarly has a **Corefile** to use. See [**examples/coredns/**](examples/coredns/) for examples of Corefiles.

### Preparation: SMD and BSS

Before running CoreDHCP, ensure the [OpenCHAMI](https://openchami.org) services (notably **BSS** and **SMD**) are configured and running. Their URLs should match what you configure in the CoreDHCP config file.
Before running CoreDHCP/CoreDNS, ensure the [OpenCHAMI](https://openchami.org) services (notably **BSS** and **SMD**) are configured and running. Their URLs should match what you configure in the CoreDHCP config file.

### Preparation: TFTP

By default, **coresmd** includes a built-in TFTP server with iPXE binaries for 32-/64-bit x86/ARM (EFI) and legacy x86. If you use the **bootloop** plugin and set the iPXE boot script path to `"default"`, it will serve a built-in reboot script to unknown nodes. Alternatively, you can point this to a custom TFTP path if different functionality is desired.

### Running CoreDHCP
### Running

Once all prerequisites are set, you can run CoreDHCP:
Once all prerequisites are set, you can run CoreDHCP or CoreDNS.

- **Docker**
Use host networking and mount your config file:
#### CoreDHCP

- **Podman CLI**
Use host networking and mount your config file (this example mounts in system certificate bundle):
```bash
docker run --rm \
--net=host \
-v /path/to/config.yaml:/etc/coredhcp/config.yaml:ro \
podman run \
--rm \
--name=coresmd-coredhcp \
--hostname=coresmd-coredhcp \
--cap-add=NET_ADMIN,NET_RAW \
--volume=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:/root_ca/root_ca.crt:ro,Z \
--volume=/etc/openchami/configs/coredhcp.yaml:/etc/coredhcp/config.yaml:ro,Z \
--network=host \
ghcr.io/openchami/coresmd:latest
```

- **Bare Metal**
> [!NOTE]
> `--cap-add` may or may not be needed on some distros.

- **Podman Quadlet**:
```ini
[Unit]
Description=The CoreSMD CoreDHCP container

[Container]
ContainerName=coresmd-coredhcp

HostName=coresmd-coredhcp
Image=ghcr.io/openchami/coresmd:latest

AddCapability=NET_ADMIN
AddCapability=NET_RAW

Volume=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:/root_ca/root_ca.crt:ro,Z
Volume=/etc/openchami/configs/coredhcp.yaml:/etc/coredhcp/config.yaml:ro,Z

Network=host

PodmanArgs=--http-proxy=false

[Service]
Restart=always
```

- **Bare Metal**
Execute the locally built binary:
```bash
./coredhcp -conf /path/to/config.yaml
```

#### CoreDNS

- **Podman CLI**
Use host networking and mount your config file (this example mounts in system certificate bundle):
```bash
podman run \
--rm \
--name=coresmd-coredns \
--hostname=coresmd-coredns \
--cap-add=NET_ADMIN,NET_RAW \
--volume=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:/root_ca/root_ca.crt:ro,Z \
--volume=/etc/openchami/configs/Corefile:/etc/coredhcp/Corefile:ro,Z \
--network=host \
ghcr.io/openchami/coresmd:latest \
/coredns
```

> [!NOTE]
> `--cap-add` may or may not be needed on some distros.

- **Podman Quadlet**:
```ini
[Unit]
Description=The CoreSMD CoreDNS container

[Container]
ContainerName=coresmd-coredns

HostName=coresmd-coredhcp
Image=ghcr.io/openchami/coredns:latest

Exec=/coredns

AddCapability=NET_ADMIN
AddCapability=NET_RAW

Volume=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:/root_ca/root_ca.crt:ro,Z
Volume=/etc/openchami/configs/Corefile

Network=host

PodmanArgs=--http-proxy=false

[Service]
Restart=always
```

- **Bare Metal**
Execute the locally built binary:
```bash
./cored-conf /path/to/config.yaml
```

---

## More Reading

- [CoreDHCP GitHub](https://github.com/coredhcp/coredhcp)
- [CoreDNS GitHub](https://github.com/coredns/coredns)
- [OpenCHAMI Project](https://openchami.org)
- [SMD GitHub](https://github.com/OpenCHAMI/smd)
- [GoReleaser Documentation](https://goreleaser.com/install/)
Expand Down
35 changes: 35 additions & 0 deletions examples/coredhcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CoreDHCP Configuration Examples for CoreSMD

This directory contains example CoreDHCP configurations for the CoreSMD plugin.

## Positional vs. Key-Value Format

Prior to CoreSMD v0.5.0, positional arguments were used to configure CoreSMD which made it difficult to match configuration values to configuration keys. An example of such configuration would be:

```yaml
plugins:
- coresmd: https://foobar.openchami.cluster http://172.16.0.253:8081 /root_ca/root_ca.crt 30s 1h false
```

With fresh eyes, it's difficult to see what these values mean. With CoreSMD v0.5.0 and beyond, key-value pairs are used instead. The format is `key=value` with no spaces on either side of the equal sign (think [Linux kernel command line](https://www.man7.org/linux/man-pages/man7/bootparam.7.html)).

To migrate the above configuration to the new format, it would become:

```yaml
plugins:
- coresmd: svc_base_uri=https://foobar.openchami.cluster ipxe_base_uri=http://172.16.0.253:8081 ca_cert=/root_ca/root_ca.crt cache_valid=30s lease_time=1h single_port=false
```

So as to not have an endless text line, a YAML multi-line string can also be used to separate the arguments:

```yaml
plugins:
- coresmd: |
svc_base_uri=https://foobar.openchami.cluster
ipxe_base_uri=http://172.16.0.253:8081
ca_cert=/root_ca/root_ca.crt
cache_valid=30s
lease_time=1h single_port=false
```

See [coredhcp.yaml](coredhcp.yaml) for a full example with documentation comments.
Loading
Loading