inventory: add titan-16 and stage rpi5/jetson classes
This commit is contained in:
parent
29a546179c
commit
34dfc165d6
@ -19,8 +19,127 @@ classes:
|
||||
hardware: rpi4
|
||||
node-role.kubernetes.io/worker: "true"
|
||||
root_overlay: overlays/rpi4-armbian-longhorn-root
|
||||
- name: rpi5-ubuntu-worker
|
||||
arch: arm64
|
||||
os: ubuntu-24.04-raspi
|
||||
image: ${METIS_IMAGE_RPI5_UBUNTU_WORKER}
|
||||
checksum: ${METIS_IMAGE_RPI5_UBUNTU_WORKER_SHA256}
|
||||
k3s_version: v1.31.5+k3s1
|
||||
default_labels:
|
||||
hardware: rpi5
|
||||
node-role.kubernetes.io/worker: "true"
|
||||
- name: jetson-ubuntu-accelerator
|
||||
arch: arm64
|
||||
os: ubuntu-20.04-tegra
|
||||
image: ${METIS_IMAGE_JETSON_UBUNTU_ACCELERATOR}
|
||||
checksum: ${METIS_IMAGE_JETSON_UBUNTU_ACCELERATOR_SHA256}
|
||||
k3s_version: v1.31.5+k3s1
|
||||
default_labels:
|
||||
hardware: jetson
|
||||
jetson: "true"
|
||||
node-role.kubernetes.io/accelerator: "true"
|
||||
- name: rpi5-ubuntu-control-plane
|
||||
arch: arm64
|
||||
os: ubuntu-24.04-raspi
|
||||
image: ${METIS_IMAGE_RPI5_UBUNTU_CONTROL}
|
||||
checksum: ${METIS_IMAGE_RPI5_UBUNTU_CONTROL_SHA256}
|
||||
k3s_version: v1.31.5+k3s1
|
||||
default_labels:
|
||||
hardware: rpi5
|
||||
node-role.kubernetes.io/control-plane: "true"
|
||||
default_taints:
|
||||
- node-role.kubernetes.io/control-plane:NoSchedule
|
||||
- name: amd64-debian-worker
|
||||
arch: amd64
|
||||
os: debian-13
|
||||
image: ${METIS_IMAGE_AMD64_DEBIAN_WORKER}
|
||||
checksum: ${METIS_IMAGE_AMD64_DEBIAN_WORKER_SHA256}
|
||||
k3s_version: v1.31.5+k3s1
|
||||
default_labels:
|
||||
hardware: amd64
|
||||
node-role.kubernetes.io/worker: "true"
|
||||
|
||||
nodes:
|
||||
- name: titan-04
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-04
|
||||
ip: 192.168.22.30
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-05
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-05
|
||||
ip: 192.168.22.31
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-06
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-06
|
||||
ip: 192.168.22.32
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-07
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-07
|
||||
ip: 192.168.22.33
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-08
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-08
|
||||
ip: 192.168.22.34
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-09
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-09
|
||||
ip: 192.168.22.35
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-10
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-10
|
||||
ip: 192.168.22.36
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-11
|
||||
class: rpi5-ubuntu-worker
|
||||
hostname: titan-11
|
||||
ip: 192.168.22.37
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-12
|
||||
class: rpi4-armbian-worker
|
||||
hostname: titan-12
|
||||
@ -31,6 +150,16 @@ nodes:
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-16
|
||||
class: rpi4-armbian-worker
|
||||
hostname: titan-16
|
||||
ip: 192.168.22.44
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-13
|
||||
class: rpi4-armbian-longhorn
|
||||
hostname: titan-13
|
||||
@ -119,3 +248,73 @@ nodes:
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-20
|
||||
class: jetson-ubuntu-accelerator
|
||||
hostname: titan-20
|
||||
ip: 192.168.22.20
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-21
|
||||
class: jetson-ubuntu-accelerator
|
||||
hostname: titan-21
|
||||
ip: 192.168.22.21
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-22
|
||||
class: amd64-debian-worker
|
||||
hostname: titan-22
|
||||
ip: 192.168.22.22
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-24
|
||||
class: amd64-debian-worker
|
||||
hostname: titan-24
|
||||
ip: 192.168.22.26
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-0a
|
||||
class: rpi5-ubuntu-control-plane
|
||||
hostname: titan-0a
|
||||
ip: 192.168.22.11
|
||||
k3s_role: server
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-0b
|
||||
class: rpi5-ubuntu-control-plane
|
||||
hostname: titan-0b
|
||||
ip: 192.168.22.12
|
||||
k3s_role: server
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-0c
|
||||
class: rpi5-ubuntu-control-plane
|
||||
hostname: titan-0c
|
||||
ip: 192.168.22.13
|
||||
k3s_role: server
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: ${METIS_K3S_TOKEN}
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
|
||||
@ -187,7 +187,7 @@ func (a *App) State(deviceHost string) PageState {
|
||||
DefaultFlashHost: a.settings.DefaultFlashHost,
|
||||
SelectedHost: deviceHost,
|
||||
FlashHosts: flashHosts,
|
||||
Nodes: append([]inventory.NodeSpec{}, a.inventory.Nodes...),
|
||||
Nodes: a.replacementNodes(),
|
||||
Jobs: jobs,
|
||||
Devices: devices,
|
||||
PreferredDevice: preferredDevice,
|
||||
@ -201,7 +201,7 @@ func (a *App) State(deviceHost string) PageState {
|
||||
|
||||
// Build starts a background image build for a node.
|
||||
func (a *App) Build(node string) (*Job, error) {
|
||||
if _, _, err := a.inventory.FindNode(node); err != nil {
|
||||
if err := a.ensureReplacementReady(node); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
job := a.newJob("build", node, "", "")
|
||||
@ -214,7 +214,7 @@ func (a *App) Replace(node, host, device string) (*Job, error) {
|
||||
if host == "" {
|
||||
host = a.settings.DefaultFlashHost
|
||||
}
|
||||
if _, _, err := a.inventory.FindNode(node); err != nil {
|
||||
if err := a.ensureReplacementReady(node); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := a.ensureDevice(host, device); err != nil {
|
||||
@ -405,6 +405,59 @@ func cachedImageName(source string) string {
|
||||
return strings.TrimSuffix(filepath.Base(source), ".xz")
|
||||
}
|
||||
|
||||
func (a *App) replacementNodes() []inventory.NodeSpec {
|
||||
nodes := make([]inventory.NodeSpec, 0, len(a.inventory.Nodes))
|
||||
for _, node := range a.inventory.Nodes {
|
||||
spec, class, err := a.inventory.FindNode(node.Name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if replacementReady(spec, class) {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
sort.Slice(nodes, func(i, j int) bool {
|
||||
return nodes[i].Name < nodes[j].Name
|
||||
})
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (a *App) ensureReplacementReady(nodeName string) error {
|
||||
node, class, err := a.inventory.FindNode(nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if replacementReady(node, class) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("node %s does not yet have a complete replacement definition", nodeName)
|
||||
}
|
||||
|
||||
func replacementReady(node *inventory.NodeSpec, class *inventory.NodeClass) bool {
|
||||
if node == nil || class == nil {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(class.Image) == "" || strings.TrimSpace(class.Checksum) == "" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(node.Name) == "" || strings.TrimSpace(node.Hostname) == "" || strings.TrimSpace(node.IP) == "" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(node.K3sRole) == "" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(node.K3sRole) != "server" && strings.TrimSpace(node.K3sURL) == "" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(node.K3sToken) == "" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(node.SSHUser) == "" || len(node.SSHAuthorized) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *App) flashHosts() []string {
|
||||
hosts := map[string]struct{}{}
|
||||
for _, host := range a.settings.FlashHosts {
|
||||
|
||||
@ -81,6 +81,75 @@ func TestStateJSONUsesLowerCaseNodeFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateFiltersNodesWithoutCompleteReplacementDefinition(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
baseImage := filepath.Join(dir, "base.img")
|
||||
if err := os.WriteFile(baseImage, []byte("test-image"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sum := sha256.Sum256([]byte("test-image"))
|
||||
inventoryPath := filepath.Join(dir, "inventory.yaml")
|
||||
inv := `
|
||||
classes:
|
||||
- name: ready
|
||||
arch: arm64
|
||||
os: armbian
|
||||
image: file://` + baseImage + `
|
||||
checksum: sha256:` + hex.EncodeToString(sum[:]) + `
|
||||
k3s_version: v1.31.5+k3s1
|
||||
- name: incomplete
|
||||
arch: arm64
|
||||
os: ubuntu
|
||||
image: file://` + baseImage + `
|
||||
nodes:
|
||||
- name: titan-ready
|
||||
class: ready
|
||||
hostname: titan-ready
|
||||
ip: 192.168.22.240
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: token
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
- name: titan-incomplete
|
||||
class: incomplete
|
||||
hostname: titan-incomplete
|
||||
ip: 192.168.22.241
|
||||
k3s_role: agent
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: token
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
`
|
||||
if err := os.WriteFile(inventoryPath, []byte(inv), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
settings := Settings{
|
||||
BindAddr: ":0",
|
||||
InventoryPath: inventoryPath,
|
||||
CacheDir: filepath.Join(dir, "cache"),
|
||||
ArtifactDir: filepath.Join(dir, "artifacts"),
|
||||
HistoryPath: filepath.Join(dir, "history.jsonl"),
|
||||
SnapshotsPath: filepath.Join(dir, "snapshots.json"),
|
||||
TargetsPath: filepath.Join(dir, "targets.json"),
|
||||
DefaultFlashHost: "titan-22",
|
||||
FlashHosts: []string{"titan-22"},
|
||||
LocalHost: "titan-22",
|
||||
AllowedGroups: []string{"admin", "maintenance"},
|
||||
MaxDeviceBytes: 300000000000,
|
||||
}
|
||||
app, err := NewApp(settings)
|
||||
if err != nil {
|
||||
t.Fatalf("new app: %v", err)
|
||||
}
|
||||
state := app.State("titan-22")
|
||||
if len(state.Nodes) != 1 || state.Nodes[0].Name != "titan-ready" {
|
||||
t.Fatalf("expected only titan-ready in state nodes, got %+v", state.Nodes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInternalSnapshotAndWatch(t *testing.T) {
|
||||
app := newTestApp(t)
|
||||
handler := app.Handler()
|
||||
@ -163,6 +232,8 @@ nodes:
|
||||
k3s_url: https://192.168.22.7:6443
|
||||
k3s_token: token
|
||||
ssh_user: atlas
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb8oMX6u0z3sH/p/WBGlvPXXdbGETCKzWYwR/dd6fZb titan-bastion
|
||||
`
|
||||
if err := os.WriteFile(inventoryPath, []byte(inv), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user