{"id":50388252,"url":"https://github.com/scality/disk-management-agent","last_synced_at":"2026-05-30T16:30:32.978Z","repository":{"id":357401410,"uuid":"1153613147","full_name":"scality/disk-management-agent","owner":"scality","description":"Kubernetes operator for RAID management","archived":false,"fork":false,"pushed_at":"2026-05-12T15:26:16.000Z","size":214,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-12T17:32:36.740Z","etag":null,"topics":["kubernetes","operator","raid-management"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scality.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-09T13:58:34.000Z","updated_at":"2026-04-16T16:08:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/scality/disk-management-agent","commit_stats":null,"previous_names":["scality/disk-management-agent"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/scality/disk-management-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scality%2Fdisk-management-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scality%2Fdisk-management-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scality%2Fdisk-management-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scality%2Fdisk-management-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scality","download_url":"https://codeload.github.com/scality/disk-management-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scality%2Fdisk-management-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33700863,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","operator","raid-management"],"created_at":"2026-05-30T16:30:32.275Z","updated_at":"2026-05-30T16:30:32.973Z","avatar_url":"https://github.com/scality.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# disk-management-agent\n\n[![Tests](https://github.com/scality/disk-management-agent/actions/workflows/test.yml/badge.svg)](https://github.com/scality/disk-management-agent/actions/workflows/test.yml)\n[![Lint](https://github.com/scality/disk-management-agent/actions/workflows/lint.yml/badge.svg)](https://github.com/scality/disk-management-agent/actions/workflows/lint.yml)\n[![Go Version](https://img.shields.io/github/go-mod/go-version/scality/disk-management-agent)](go.mod)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n\nA Kubernetes node agent that discovers physical HDD drives behind hardware RAID\ncontrollers and exposes them as cluster-scoped `DiscoveredPhysicalDisk` custom\nresources. Storage orchestration platforms (such as\n[MetalK8s](https://github.com/scality/metalk8s)) and operators can consume\nthese CRs to build a reliable, Kubernetes-native inventory of every physical\ndisk in the cluster.\n\nBuilt with [Operator SDK](https://sdk.operatorframework.io/) and\n[raidmgmt](https://github.com/scality/raidmgmt).\n\n## Features\n\n- **MegaRAID support** -- discovers drives via `storcli64` and `perccli64`\n  (Broadcom / Dell PERC controllers)\n- **HPE Smart Array support** -- discovers drives via `ssacli`\n- **Periodic discovery** -- scans every 5 minutes; new drives get CRs\n  automatically, existing CRs have their status refreshed\n- **Validating webhook** -- restricts CR creation and updates to the agent's own\n  service account\n- **Cluster-scoped CRD** -- immutable spec (node, controller, slot) with a\n  status sub-resource reflecting live hardware state\n- **Clean architecture** -- business logic is decoupled from Kubernetes and RAID\n  infrastructure through ports and adapters\n\n## Prerequisites\n\n| Requirement | Details |\n|---|---|\n| Kubernetes | v1.33+ |\n| cert-manager | Required for webhook TLS (installed by the default Kustomize overlay) |\n| RAID CLI tools | At least one of `storcli64`, `perccli64`, or `ssacli` installed on target nodes |\n| Container runtime | Docker or compatible (for building images) |\n\n## Quick Start\n\n### Install CRDs\n\n```bash\nmake install\n```\n\n### Build and push the container image\n\n```bash\nmake docker-build docker-push IMG=\u003cregistry\u003e/disk-management-agent:\u003ctag\u003e\n```\n\n### Deploy the agent\n\n```bash\nmake deploy IMG=\u003cregistry\u003e/disk-management-agent:\u003ctag\u003e\n```\n\nThis deploys a DaemonSet into the `disk-management-agent-system` namespace.\nAfter a few minutes you should see `DiscoveredPhysicalDisk` resources appear:\n\n```bash\nkubectl get discoveredphysicaldisks\n```\n\n### Generate a single install manifest\n\nIf you prefer applying a single YAML file instead of using `make deploy`:\n\n```bash\nmake build-installer IMG=\u003cregistry\u003e/disk-management-agent:\u003ctag\u003e\nkubectl apply -f dist/install.yaml\n```\n\n### Uninstall\n\n```bash\nmake undeploy\n```\n\n## How It Works\n\n```mermaid\nflowchart TD\n    subgraph Node[\"Node Agent (per node)\"]\n        Ticker[\"DiscoveryTicker\\n(every 5 min)\"]\n        DiscoverUC[\"DiscoverPhysicalDrives\\n(use case)\"]\n        Cache[\"InMemory Cache\"]\n        ReconcileUC[\"ReconcileDiscoveredPhysicalDisk\\n(use case)\"]\n        Reconciler[\"K8s Reconciler\"]\n    end\n\n    subgraph RAID[\"RAID CLI Tools\"]\n        Storcli[\"storcli64\"]\n        Perccli[\"perccli64\"]\n        Ssacli[\"ssacli\"]\n    end\n\n    subgraph K8s[\"Kubernetes API\"]\n        CRD[\"DiscoveredPhysicalDisk CRs\"]\n    end\n\n    Ticker --\u003e|\"triggers\"| DiscoverUC\n    DiscoverUC --\u003e|\"calls via raidmgmt\"| Storcli\n    DiscoverUC --\u003e|\"calls via raidmgmt\"| Perccli\n    DiscoverUC --\u003e|\"calls via raidmgmt\"| Ssacli\n    DiscoverUC --\u003e|\"Replace\"| Cache\n    DiscoverUC --\u003e|\"Get/Create\"| CRD\n    Ticker --\u003e|\"GenericEvent\"| Reconciler\n    Reconciler --\u003e|\"Execute\"| ReconcileUC\n    ReconcileUC --\u003e|\"Load\"| Cache\n    Reconciler --\u003e|\"Status Update\"| CRD\n```\n\nThe agent runs as a DaemonSet -- one pod per node. Each instance only manages\ndisks for its own node.\n\n1. A **DiscoveryTicker** fires every 5 minutes and runs the\n   **DiscoverPhysicalDrives** use case.\n2. The use case invokes every registered `PhysicalDriveDiscoverer` and\n   `LogicalVolumeDiscoverer` adapter (MegaRAID + Smart Array), keeps only HDD\n   drives, enriches device paths from logical volume metadata, replaces the\n   in-memory cache, and creates any missing `DiscoveredPhysicalDisk` CRs.\n3. For CRs that already exist the ticker sends a `GenericEvent` to the\n   **Reconciler**, which reads the latest snapshot from the cache and updates\n   the CR `.status` (vendor, model, serial, size, paths, etc.).\n4. A **validating webhook** restricts CR creation and updates to the agent's own\n   service account.\n\nIf a RAID CLI tool is not installed on a node (e.g. `storcli64` on a\nSmartArray-only host), the corresponding discoverer logs the error and is\nskipped -- it does not block other discoverers.\n\n## CRD Reference\n\n**Group:** `metalk8s.scality.com`\n**Version:** `v1alpha1`\n**Kind:** `DiscoveredPhysicalDisk`\n**Scope:** Cluster\n\n### Spec (immutable, set at creation)\n\n| Field | Type | Description |\n|---|---|---|\n| `spec.nodeName` | `string` | Node where the disk was discovered |\n| `spec.controller.type` | `string` | RAID controller type (`MegaRAID`, `SmartArray`) |\n| `spec.controller.id` | `int` | Controller index |\n| `spec.id` | `string` | Disk identifier as reported by the controller |\n| `spec.slot.port` | `string` | Port number |\n| `spec.slot.enclosure` | `string` | Enclosure number |\n| `spec.slot.bay` | `string` | Bay number |\n\n### Status (updated by the reconciler)\n\n| Field | Type | Description |\n|---|---|---|\n| `status.available` | `*bool` | Whether the drive is present in the slot |\n| `status.vendor` | `*string` | Disk manufacturer |\n| `status.model` | `*string` | Disk model name |\n| `status.serial` | `*string` | Disk serial number |\n| `status.wwn` | `*string` | World Wide Name |\n| `status.size` | `*uint64` | Capacity in bytes |\n| `status.type` | `*string` | Media type: `HDD`, `SSD`, or `NVMe` |\n| `status.jbod` | `*bool` | Whether the disk is in JBOD (passthrough) mode |\n| `status.status` | `*string` | Current disk status |\n| `status.reason` | `*string` | Additional context for the status |\n| `status.devicePath` | `*string` | OS device path (e.g. `/dev/sda`) |\n| `status.permanentPath` | `*string` | Stable device path (e.g. `/dev/disk/by-id/wwn-0x...`) |\n\n### Example\n\n```yaml\napiVersion: metalk8s.scality.com/v1alpha1\nkind: DiscoveredPhysicalDisk\nmetadata:\n  name: node1-megaraid-0-0-32-0\nspec:\n  nodeName: node1\n  controller:\n    type: MegaRAID\n    id: 0\n  id: \"0:32:0\"\n  slot:\n    port: \"0\"\n    enclosure: \"32\"\n    bay: \"0\"\nstatus:\n  available: true\n  vendor: SEAGATE\n  model: ST1000NX0453\n  serial: WFK1234\n  wwn: \"0x5000c500abcdef01\"\n  size: 1000204886016\n  type: HDD\n  jbod: true\n  status: Online\n  devicePath: /dev/sda\n  permanentPath: /dev/disk/by-id/wwn-0x5000c500abcdef01\n```\n\n## Configuration\n\nThe agent is configured through environment variables. When deployed via the\ndefault Kustomize manifests, `NODE_NAME`, `POD_NAMESPACE`, and\n`POD_SERVICE_ACCOUNT` are injected automatically.\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `NODE_NAME` | Yes | -- | Kubernetes node name (injected via the downward API) |\n| `POD_NAMESPACE` | No | -- | Pod namespace; used to build the webhook allowed service account |\n| `POD_SERVICE_ACCOUNT` | No | -- | Pod service account name; used for webhook authorization |\n| `STORCLI_PATH` | No | `/host/libexec/MegaRAID/storcli/storcli64` | Path to the `storcli64` binary |\n| `PERCCLI_PATH` | No | `/host/libexec/MegaRAID/perccli/perccli64` | Path to the `perccli64` binary |\n| `SSACLI_PATH` | No | `/host/libexec/ssacli` | Path to the `ssacli` binary |\n\nThe application version is injected at build time via `-ldflags` and defaults to\n`dev`.\n\n## Development\n\n```bash\nmake build                # Build the manager binary\nNODE_NAME=my-node make run  # Run locally against your current kubeconfig\nmake manifests            # Regenerate CRD, RBAC, and webhook manifests\nmake generate             # Regenerate DeepCopy methods\nmake fmt vet              # Format and vet\nmake lint                 # Run golangci-lint\nmake test                 # Unit + controller tests (envtest)\nmake test-e2e             # End-to-end tests (Kind)\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the full development guide, coding\nstandards, architecture overview, and pull request process.\n\n## Contributing\n\nContributions are welcome -- whether it is a bug fix, a new RAID controller\nadapter, documentation improvements, or anything else. See\n[CONTRIBUTING.md](CONTRIBUTING.md) to get started.\n\n## License\n\nThis project is licensed under the Apache License 2.0. See [LICENSE](LICENSE)\nfor details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscality%2Fdisk-management-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscality%2Fdisk-management-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscality%2Fdisk-management-agent/lists"}