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
34 changes: 34 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ updates:
patterns:
- "*"

- package-ecosystem: "pip"
directory: "/doc"
ignore:
# Pinned intentionally: myst-parser v5.0.0 causes version conflicts.
- dependency-name: "myst-parser"
versions: [">=5.0.0"]
labels: []
schedule:
interval: "weekly"
target-branch: "main"
cooldown:
default-days: 7
groups:
pip:
patterns:
- "*"

- package-ecosystem: "github-actions"
directories:
- "/"
Expand Down Expand Up @@ -55,3 +72,20 @@ updates:
gomod:
patterns:
- "*"

- package-ecosystem: "pip"
directory: "/doc"
ignore:
# Pinned intentionally: myst-parser v5.0.0 causes version conflicts.
- dependency-name: "myst-parser"
versions: [">=5.0.0"]
labels: []
schedule:
interval: "weekly"
target-branch: "v2-edge"
cooldown:
default-days: 7
groups:
pip:
patterns:
- "*"
10 changes: 5 additions & 5 deletions api/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func statusGet(sh *service.Handler) endpointHandler {
err = cluster.Query(r.Context(), true, func(ctx context.Context, c *microClient.Client) error {
memberStatuses, err := client.GetStatus(ctx, c)
if err != nil {
logger.Error("Failed to get status for cluster member", logger.Ctx{"error": err, "address": c.URL()})
logger.Error("Failed to get status for cluster member", logger.Ctx{"err": err, "address": c.URL()})

return nil
}
Expand Down Expand Up @@ -90,7 +90,7 @@ func statusGet(sh *service.Handler) endpointHandler {
case types.LXD:
clusterMembers, err := lxdStatus(r.Context(), s)
if err != nil {
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name})
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err})
}

statusMu.Lock()
Expand All @@ -99,7 +99,7 @@ func statusGet(sh *service.Handler) endpointHandler {
case types.MicroCeph:
clusterMembers, osds, cephServices, err := cephStatus(r.Context(), s)
if err != nil {
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name})
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err})
}

status.OSDs = osds
Expand All @@ -111,7 +111,7 @@ func statusGet(sh *service.Handler) endpointHandler {
case types.MicroOVN:
clusterMembers, ovnServices, err := ovnStatus(r.Context(), s)
if err != nil {
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name})
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err})
}

status.OVNServices = ovnServices
Expand All @@ -127,7 +127,7 @@ func statusGet(sh *service.Handler) endpointHandler {

clusterMembers, err := microStatus(r.Context(), microClient, s)
if err != nil {
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name})
logger.Error("Failed to get service status", logger.Ctx{"type": s.Type(), "name": sh.Name, "err": err})
}

statusMu.Lock()
Expand Down
10 changes: 9 additions & 1 deletion cmd/microcloud/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func main() {

asker, err := setupAsker(ctx)
if err != nil {
fmt.Println(err.Error())
fmt.Fprintf(os.Stderr, "Failed setting up asker: %v\n", err)
os.Exit(1)
}

Expand All @@ -62,6 +62,14 @@ func main() {

app.SetVersionTemplate("{{.Version}}\n")

// Don't display the --state-dir flag in the help output.
// It is used by the snaps "microcloud" wrapper command but never by the user directly.
err = app.PersistentFlags().MarkHidden("state-dir")
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot hide --state-dir flag: %v\n", err)
os.Exit(1)
}

var cmdInit = cmdInit{common: &commonCmd}
app.AddCommand(cmdInit.command())

Expand Down
23 changes: 13 additions & 10 deletions cmd/microcloud/main_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,8 +885,18 @@ func (c *initConfig) setupCluster(s *service.Handler) error {

fmt.Println("Configuring cluster-wide devices ...")

var ovnConfig string
if s.Services[types.MicroOVN] != nil {
// Update LXD's global config.
server, _, err := lxdClient.GetServer()
if err != nil {
return err
}

config := make(map[string]string)

// LXD can dynamically determine the OVN northbound DB connection string from MicroOVN's `ovn.env` file.
// This feature was added with the ovn_dynamic_northbound_connection API extension.
// Only set the connection string in case of an older LXD.
if s.Services[types.MicroOVN] != nil && !lxdClient.HasExtension("ovn_dynamic_northbound_connection") {
serviceOVN := s.Services[types.MicroOVN].(*service.OVNService)

services, err := serviceOVN.GetServices(context.Background())
Expand All @@ -911,14 +921,7 @@ func (c *initConfig) setupCluster(s *service.Handler) error {
}
}

ovnConfig = strings.Join(conns, ",")
}

config := map[string]string{"network.ovn.northbound_connection": ovnConfig}
// Update LXD's global config.
server, _, err := lxdClient.GetServer()
if err != nil {
return err
config["network.ovn.northbound_connection"] = strings.Join(conns, ",")
}

newServer := server.Writable()
Expand Down
7 changes: 0 additions & 7 deletions cmd/microcloud/preseed.go
Original file line number Diff line number Diff line change
Expand Up @@ -918,13 +918,6 @@ func (p *Preseed) Parse(s *service.Handler, c *initConfig, installedServices map
directLocal = sys.Storage.Local
directCeph = sys.Storage.Ceph
}

for _, disk := range directCeph {
_, err := os.Stat(disk.Path)
if err != nil {
return nil, fmt.Errorf("Failed to find specified disk path: %w", err)
}
}
}

// Setup directly specified disks for ZFS pool.
Expand Down
42 changes: 35 additions & 7 deletions doc/how-to/initialize.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,7 @@ If you want to automate the initialization process, you can provide a preseed co
cat <preseed_file> | microcloud preseed

Make sure to distribute and run the same preseed configuration on all systems that should be part of the MicroCloud.

The preseed YAML file must use the following syntax:

```{literalinclude} preseed.yaml
:language: YAML
:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-87
```
See the {ref}`full reference <ref-preseed-full-configuration-example>` for possible configuration options or the minimal example below.

### Minimal preseed using multicast discovery

Expand Down Expand Up @@ -239,6 +233,40 @@ ovn:
If you initialized MicroCloud without local storage _and_ with CephFS storage, continue to the section below to complete your initialization.
```

### Use storage disk filters

You may not know the exact disk paths used for local and remote storage when crafting the preseed file.
In such cases, you can add disk filters for local and remote storage configuration.
By using those filters, you can narrow down the list of available disks to the ones eligible based on the given rules.

For example you might want to use all disks for local storage which are of type `nvme` and use a model description `<vendor>`:

```yaml
storage:
local:
- find: type == nvme && model == "<vendor>"
```

As another example, you can filter for remote (Ceph) storage disks with size greater than 1TiB and model description `<vendor2>`, and ensure there are at least six disks (maximum eight) selected across all members:

```yaml
storage:
ceph:
- find: size > 1TiB && model == "<vendor2>"
find_min: 6
find_max: 8
```

See the {ref}`list of filters <ref-preseed-filters>` for a full reference.

```{admonition} Finding the right filters
:class: note
If you want to see the actual filter values for your system(s) for further refinement of the preseed file, you can run `lxc query /1.0/resources | jq .storage.disks` on any of the MicroCloud members prior to initialization.

The response will show all the disks available to MicroCloud on this member.
Repeat the command on every member for a full list of disks across the cluster.
```

(howto-initialize-images-backups)=
## Configure `backups_volume` and `images_volume`

Expand Down
8 changes: 1 addition & 7 deletions doc/how-to/member_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,7 @@ In the list of systems, include only the new machine and set either `initiator`
that is already part of the MicroCloud.

Distribute and run the same preseed configuration on both the machine being added, and the cluster member used for the `initiator` or `initiator_address`.

The preseed YAML file must use the following syntax:

```{literalinclude} preseed.yaml
:language: YAML
:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-88
```
See the {ref}`full reference <ref-preseed-full-configuration-example>` for possible configuration options or the minimal example below.

### Minimal preseed using multicast discovery

Expand Down
10 changes: 10 additions & 0 deletions doc/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ Consult this command reference to work with MicroCloud through the CLI.
/reference/commands
```

## Preseed

Consult this preseed reference for a detailed explanation of the various configuration options.

```{toctree}
:maxdepth: 1

/reference/preseed
```

## Requirements and releases

```{toctree}
Expand Down
100 changes: 100 additions & 0 deletions doc/reference/preseed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
(ref-preseed)=
# Preseed configuration options

MicroCloud preseed allows the unattended (non-interactive) deployment of a cluster using a pre-configured file.
See below for detailed descriptions of the main building blocks of the file, followed by a {ref}`full configuration example <ref-preseed-full-configuration-example>` file.

(ref-preseed-filters)=
## Storage disk filters

Explicitly setting the storage disks per system under `systems.[*].storage` is optional.
Use filters if the exact disk paths are unknown when crafting the preseed file.
This also makes the preseed file generic enough to be usable across various MicroCloud deployments.

Filters allow MicroCloud to make a selection from a list of all disks available on the systems.
These filters correspond to the YAML field names of the disk resources returned from LXD's `/1.0/resources` endpoint.

The following table lists all of the available filters:

```{table}
:align: left

| Filter | Example |
| ------------------ | ------------------------------------------- |
| `id` | `nvme0n1` |
| `device` | `259:0` |
| `model` | `<Vendor>` |
| `type` | `nvme` |
| `read_only` | `false` |
| `mounted` | `false` |
| `size` | `1024209543168` (size of the disk in bytes) |
| `removable` | `false` |
| `wwn` | `eui.00xxxxxxxxxxxxxx` |
| `numa_node` | `0` |
| `device_path` | `pci-0000:04:00.0-nvme-1` |
| `block_size` | `512` |
| `firmware_version` | `4L2XXXXX` |
| `rpm` | `0` |
| `serial` | `S7XKXXXXXXXXXX` |
| `device_id` | `nvme-eui.00xxxxxxxxxxxxxx` |
| `pci_address` | `0000:04:00.0` |
| `used_by` | `bcache` |
```

When using the `size` filter, its value can be compared against a user-defined number using byte suffixes in either units of 1000 or 1024:

`B`, `kB`, `MB`, `GB`, `TB`, `EB`, `KiB`, `MiB`, `GiB`, `TiB`, `PiB`, `EiB`

### Filter operands

All filters can use the following operands to compare against defined values:

`&&`, `||`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `!`

Furthermore the following restrictions apply:

* Filters are checked in order of appearance
* String values must not be in quotes unless the string contains a space
* Single quotes are fine, but double quotes must be escaped


Multiple filters can be added to a single section:

```yaml
storage:
ceph:
- find: <filters>
- find: <filters>
```

### Limit filtered disks

In addition to finding disks by filter, the minimum and maximum number of disks can also be specified.
For this, the `find_min` and `find_max` settings can be added to the relevant section:

```yaml
storage:
ceph:
- find: <filters>
find_min: 1
find_max: 2
```

The example above will make sure that the filters select at least one, but not more than two, disks for remote (Ceph) storage.

```{note}
For local storage there can only ever be one disk per system.
If the filters return more than one disk, only one of them will be used.

For remote storage the filters apply for all disks across all systems.
```

(ref-preseed-full-configuration-example)=
## Full configuration example

The preseed YAML file must use the following syntax:

```{literalinclude} preseed.yaml
:language: YAML
:emphasize-lines: 1-4,7-10,13-14,17-19,22,25-27,30-35,63-66,72,79-88
```
File renamed without changes.
8 changes: 8 additions & 0 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,11 @@ EVACUATION_COUNTS=0 ./run mc
# do multuple rolling reboots/evacuation tests:
EVACUATION_COUNTS=5 ./run mc
```

### HTML report

Passing `--report` to the `run` script will generate a brief HTML report upon completion (whether the tests pass or fail). The report file is created in the current directory.

```sh
./run --report mc
```
Loading
Loading