diff --git a/docs/architecture/health_aggregation.md b/docs/architecture/health_aggregation.md index d2bfd071ee..c974166663 100644 --- a/docs/architecture/health_aggregation.md +++ b/docs/architecture/health_aggregation.md @@ -290,19 +290,24 @@ In certain conditions the scraping process will place a health alert on the host ## Health report overrides -Site administrators are able to update the health state of any NICo managed host via -the API calls `InsertHealthReportOverride` and `RemoveHealthReportOverride`. +Site administrators can inspect and update the health state of a NICo-managed host +through these REST operations: + +- `GET /v2/org/{org}/nico/machine/{machineId}/health-report` lists all reports. +- `PUT /v2/org/{org}/nico/machine/{machineId}/health-report` creates or updates an override. +- `DELETE /v2/org/{org}/nico/machine/{machineId}/health-report/{source}` removes an override. The override API offers 2 different modes of operation: -1. `merge` (default) - In this mode, any health probe alerts indicated in the override - will get merged with health probe alerts reported by builtin NICo tools in order + +1. `Merge` - In this mode, any health probe alerts indicated in the override + will get merged with health probe alerts reported by built-in NICo tools in order to derive the aggregate host health status. **This mode is meant to augment the internal health monitoring mechanism with additional sources of health data** -1. `replace` - In this mode, the health probe alerts reported by builtin NICo +2. `Replace` - In this mode, the health probe alerts reported by built-in NICo monitoring tools will be ignored. Only alerts that are passed as part of the override will be taken into account. If the override list is empty, the system will behave as if the Host would be fully healthy. **This mode is meant to bypass the internal health data in case the site operator desires a different behavior** -The API allows to apply multiple `merge` overrides to a hosts health at the same time by using a different `HealthReport::source` identifier. +The API allows multiple `Merge` overrides on a host at the same time by using a different `source` identifier for each report. This allows to integrate health information from multiple external systems and users which are not at risk of overriding each others data. E.g. health information from an external fleet health monitoring system and from SREs can be stored independently. If a ManagedHost's health is overridden, the remaining behavior is exactly the same diff --git a/docs/configuration/org-permissions.md b/docs/configuration/org-permissions.md index facd78a98d..d824e392df 100644 --- a/docs/configuration/org-permissions.md +++ b/docs/configuration/org-permissions.md @@ -53,9 +53,9 @@ Example response for a human user: Service accounts have empty `email`/`firstName`/`lastName`. Human users have those populated from the IdP. -This endpoint does not return role information directly -- roles are in the token and validated server-side. Confirm which roles you hold by attempting role-gated operations: `nicocli allocation list` requires Provider Admin; `nicocli tenant get-current-tenant` requires Tenant Admin. +This endpoint does not return role information directly -- roles are in the token and validated server-side. Confirm which roles you hold by attempting role-gated operations: `nicocli allocation list` requires Provider Admin; `nicocli tenant current` requires Tenant Admin. -If your deployment is configured for service-account auth, use `nicocli service-account get` to retrieve the current org's service-account status, including the auto-created provider and tenant IDs. +If your deployment is configured for service-account auth, use `nicocli service-account current` to retrieve the current org's service-account status, including the auto-created provider and tenant IDs. ## Listing Tenant Members @@ -77,5 +77,5 @@ Remove the role assignment (or org membership) in the identity provider. The cha 1. Create the IdP organization (or group) for the tenant. 2. Invite at least one user with `TENANT_ADMIN` so they can provision the tenant. 3. Invite additional team members with appropriate roles. -4. Verify from the tenant side: `nicocli user get` and `nicocli tenant get-current-tenant`. +4. Verify from the tenant side: `nicocli user get` and `nicocli tenant current`. 5. On the provider side, ensure at least one user holds `PROVIDER_ADMIN`. diff --git a/docs/configuration/tenant_management.md b/docs/configuration/tenant_management.md index be834eded7..519debc033 100644 --- a/docs/configuration/tenant_management.md +++ b/docs/configuration/tenant_management.md @@ -54,7 +54,7 @@ nicocli user get NICo uses a lazy creation model for tenants. There is no explicit "create tenant" API call. Instead, a tenant record is automatically created the first time a Tenant Admin retrieves the current tenant for their organization: ``` -nicocli tenant get-current-tenant +nicocli tenant current ``` If no tenant exists for the configured org, NICo creates one and returns it. If a tenant already exists, the same command returns the existing record. The operation is idempotent. @@ -78,7 +78,7 @@ If either condition is not met, the API returns HTTP 403. NICo trusts whatever t ### Worked Example ``` -$ nicocli tenant get-current-tenant +$ nicocli tenant current { "capabilities": { "targetedInstanceCreation": true @@ -96,14 +96,14 @@ $ nicocli tenant get-current-tenant | `id` | UUID identifier for the tenant, used in all subsequent API calls | | `org` | Organization name (matches your config `api.org`) | | `orgDisplayName` | Human-readable name pulled from the IdP's org metadata | -| `capabilities.targetedInstanceCreation` | Whether this tenant can specify a particular machine ID when creating instances. Set during initial tenant creation: lazy-create via `tenant get-current-tenant` typically leaves it `false`; the service-account bootstrap path (`service-account get`) sets it `true` for self-tenants. | +| `capabilities.targetedInstanceCreation` | Whether this tenant can specify a particular machine ID when creating instances. Set during initial tenant creation: lazy-create via `tenant current` typically leaves it `false`; the service-account bootstrap path (`service-account current`) sets it `true` for self-tenants. | ### Verifying the Tenant Check tenant health with the stats endpoint: -``` -nicocli tenant get-current-tenant-stats +```text +nicocli tenant stats ``` Example response for a tenant in active use: @@ -401,7 +401,7 @@ A tenant can have multiple allocations at the same site with different resource ### Allocation Workflow Summary -1. **Provision the tenant** -- `nicocli tenant get-current-tenant` +1. **Provision the tenant** -- `nicocli tenant current` 2. **Establish a tenant account** -- Provider admin links provider to tenant org 3. **Discover available resources** -- List sites, instance types, and IP blocks 4. **Create compute allocation(s)** -- One per instance type the tenant needs @@ -703,7 +703,7 @@ See the [Machine Reboot](../playbooks/machine_reboot.md) and [Force Delete](../p ### Viewing the Current Tenant ``` -nicocli tenant get-current-tenant +nicocli tenant current ``` For provider admins needing visibility across tenants, list tenant accounts (a filter flag is required): @@ -715,7 +715,7 @@ nicocli tenant-account list --infrastructure-provider-id --outpu ### Monitoring Tenant Health ``` -nicocli tenant get-current-tenant-stats +nicocli tenant stats ``` Non-zero `error` counts warrant investigation: @@ -762,7 +762,7 @@ This section ties together the full Day One workflow. The TUI flow is the recomm ### Step 1: Provision the Tenant (Tenant Admin) ``` -nicocli tenant get-current-tenant +nicocli tenant current ``` Idempotent -- creates the tenant lazily on first call. @@ -838,7 +838,7 @@ For automation, use `--data-file` -- see the Launching an Instance section above ### Step 10: Verify ``` -nicocli tenant get-current-tenant-stats +nicocli tenant stats nicocli instance list --output table nicocli instance status-history ``` @@ -869,7 +869,7 @@ The instance should reach `Ready` (or `BootCompleted` if `phoneHomeEnabled: true Use `--debug` on any command to see the full HTTP request and response. The token is redacted in the log; the path-rewriting from `nico` to whatever `api.name` is set to is visible. Real output: ``` -$ nicocli --debug tenant get-current-tenant +$ nicocli --debug tenant current time=... msg="API request: GET http:///v2/org///tenant/current" time=... msg="Request headers: {\"Accept\":[\"application/json\"],\"Authorization\":[\"Bearer \"]}" time=... msg="API response: ... -> 200 OK" @@ -908,9 +908,9 @@ Flag-first ordering -- always put flags before positional args. | Operation | Command | Role Required | |-----------|---------|--------------| | View current user | `nicocli user get` | Any authenticated user | -| View current tenant | `nicocli tenant get-current-tenant` | Tenant Admin | -| View tenant stats | `nicocli tenant get-current-tenant-stats` | Tenant Admin | -| Service-account status | `nicocli service-account get` | Any authenticated user | +| View current tenant | `nicocli tenant current` | Tenant Admin | +| View tenant stats | `nicocli tenant stats` | Tenant Admin | +| Service-account status | `nicocli service-account current` | Any authenticated user | | List tenant accounts | `nicocli tenant-account list --tenant-id ` (or `--infrastructure-provider-id`) | Provider or Tenant Admin | | Create tenant account | `nicocli tenant-account create --infrastructure-provider-id --tenant-org ` | Provider Admin | | Accept tenant account | `nicocli tenant-account update --data '{}' ` | Tenant Admin | diff --git a/docs/dpu-management/dpu-lifecycle-management.md b/docs/dpu-management/dpu-lifecycle-management.md index ad24e0ff48..ba92cb7c81 100644 --- a/docs/dpu-management/dpu-lifecycle-management.md +++ b/docs/dpu-management/dpu-lifecycle-management.md @@ -259,6 +259,30 @@ nico-admin-cli -a dpu reprovision set \ Firmware is always verified and updated during reprovisioning regardless of whether `--update-firmware` is passed. The `--update-firmware` flag is accepted but deprecated. +REST callers must create the same health precondition before starting reprovisioning: + +```bash +curl -X PUT "${BASE_URL}/v2/org/${ORG}/nico/machine/${MACHINE_ID}/health-report" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "source": "maintenance.dpu-reprovision", + "mode": "Merge", + "alerts": [{ + "id": "HostUpdateInProgress", + "message": "DPU reprovisioning in progress", + "classifications": ["PreventAllocations"] + }] + }' + +curl -X PATCH "${BASE_URL}/v2/org/${ORG}/nico/machine/${MACHINE_ID}/dpu/reprovision" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{"mode":"Set"}' +``` + +Use `Set` to start reprovisioning and `Clear` to remove a pending request. `Restart` accepts a host ID only and restarts DPUs that already have a reprovisioning request. If an Instance is attached to the Machine, also pass `"acknowledgeAttachedInstance": true`. The REST `updateFirmware` field is accepted for compatibility, but firmware is always verified and updated during reprovisioning. + ### Monitoring Reprovisioning Progress ```bash diff --git a/docs/manuals/building_nico_containers.md b/docs/manuals/building_nico_containers.md index e1650a7300..047c31863a 100644 --- a/docs/manuals/building_nico_containers.md +++ b/docs/manuals/building_nico_containers.md @@ -46,7 +46,7 @@ top of the repo with a single `make` command: ```sh make images # deployable stack: NICo Core (nico) + the REST service images -make images-all # the above plus the machine-validation and x86 boot-artifact images +make images-all # the above plus machine-validation and x86_64/aarch64 boot-artifact images ``` Images are tagged `localhost:5000/:latest` by default. Override the registry and diff --git a/docs/manuals/nicocli-reference.md b/docs/manuals/nicocli-reference.md index d4afcf4fb1..03e91a236f 100644 --- a/docs/manuals/nicocli-reference.md +++ b/docs/manuals/nicocli-reference.md @@ -6,6 +6,8 @@ The [Day One Operations](day_one_operations.md) guide uses this reference for al ## Installation +Building `nicocli` or `nico-mcp` requires Go 1.26.4 or newer. + Build and install from the `rest-api/` directory of the `infra-controller` repo: ``` @@ -256,7 +258,7 @@ After login, confirm nicocli can reach the API and your identity is correct: ``` nicocli site list # any list returns -> auth works nicocli user get # returns the caller's user record -nicocli service-account get # for service-account deployments only +nicocli service-account current # for service-account deployments only ``` `user get` returns the authenticated identity as NICo sees it. Service accounts have blank `email`/`firstName`/`lastName`; human users have those populated from the IdP. @@ -289,14 +291,16 @@ Run `nicocli --help` to enumerate available actions and sub-resources ### Action name resolution -The CLI's action-name resolver collapses `get-current-X` operation IDs to a short `get` action when there's no sibling collision. When two operation IDs would collide on the short form, both keep their full names. +The CLI's action-name resolver maps `get-current-X` operations to `current`. Current-resource statistics map to `stats`, so these operations stay distinct without exposing their full OpenAPI operation IDs. | Operation ID | Resource | Action name | |--------------|----------|-------------| -| `get-current-user` | `user` | `get` (no collision) | -| `get-current-service-account` | `service-account` | `get` (no collision) | -| `get-current-tenant` | `tenant` | `get-current-tenant` (collision with `get-current-tenant-stats`) | -| `get-current-tenant-stats` | `tenant` | `get-current-tenant-stats` (collision) | +| `get-user` | `user` | `get` | +| `get-current-service-account` | `service-account` | `current` | +| `get-current-tenant` | `tenant` | `current` | +| `get-current-tenant-stats` | `tenant` | `stats` | +| `get-current-infrastructure-provider` | `infrastructure-provider` | `current` | +| `get-current-infrastructure-provider-stats` | `infrastructure-provider` | `stats` | Use `--help` to confirm the actual action name for any resource if you're unsure. @@ -359,7 +363,7 @@ List and get commands support `--output `: ``` nicocli site list --output table -nicocli tenant get-current-tenant --output yaml +nicocli tenant current --output yaml nicocli audit list --output json --page-size 50 | jq '.[] | select(.statusCode >= 400)' ``` @@ -402,7 +406,7 @@ The `--query` flag is a **free-text search across `name`, `description`, and `st The global `--debug` flag logs the full HTTP request and response for the wrapped command. The bearer token is redacted; everything else is visible: ``` -$ nicocli --debug tenant get-current-tenant +$ nicocli --debug tenant current time=... msg="API request: GET https://nico.example.com/v2/org/my-org/nico/tenant/current" time=... msg="Request headers: {\"Accept\":[\"application/json\"],\"Authorization\":[\"Bearer \"]}" time=... msg="API response: ... -> 200 OK" @@ -446,6 +450,61 @@ Behavior: The TUI's interactive forms for `create` commands prompt for fields in order with type-aware pickers. For first-time operators this is significantly easier than constructing JSON bodies by hand. For scripts and automation, fall back to the non-interactive command form. +## MCP Server + +`nico-mcp` is a standalone server that exposes every `GET` operation in the embedded NICo OpenAPI specification as a Model Context Protocol tool over streamable HTTP. It is separate from `nicocli`; the `nicocli mcp` command prints build and run instructions but does not start the server. + +Build and run it from the `rest-api` directory: + +```bash +make nico-mcp +nico-mcp --listen :8080 --path /mcp \ + --base-url https://nico.example.com --org tester +``` + +The server has these properties: + +- Only OpenAPI `GET` operations are exposed. `POST`, `PATCH`, `PUT`, and `DELETE` operations are excluded. +- Tool names use `nico_`, such as `nico_get_all_site`. +- The streamable HTTP handler is stateless and returns one `application/json` response for each request. It does not retain MCP session state or emit server-sent events. +- An inbound `Authorization: Bearer ` header is forwarded to NICo REST. NICo REST remains responsible for authentication and authorization. + +### Server configuration + +| Flag | Environment variable | Description | +|------|----------------------|-------------| +| `--listen` | `NICO_MCP_LISTEN` | Listen address. Defaults to `:8080`. | +| `--path` | `NICO_MCP_PATH` | MCP handler path. Defaults to `/mcp`. | +| `--shutdown-timeout` | `NICO_MCP_SHUTDOWN_TIMEOUT` | Graceful shutdown timeout. Defaults to `10s`. | +| `--base-url` | `NICO_BASE_URL` | Default NICo REST base URL. | +| `--org` | `NICO_ORG` | Default organization for REST requests. | +| `--api-name` | `NICO_API_NAME` | API path segment. Defaults to `nico`. | +| `--token` | `NICO_TOKEN` | Default bearer token. | +| `--debug` | None | Log full HTTP requests and responses. | + +Every generated tool also accepts `org`, `base_url`, `api_name`, and `token` arguments. For each call, an explicit tool argument takes precedence over the inbound authorization header for `token`, followed by the server startup default. The server does not read `~/.nico/config.yaml`; `org` and `base_url` must resolve from a tool argument, startup flag, or environment variable. + +List the generated tools: + +```bash +curl -sS http://localhost:8080/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq +``` + +Call a tool while passing the caller's bearer token through to NICo REST: + +```bash +curl -sS http://localhost:8080/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"nico_get_all_site","arguments":{}}}' | jq +``` + +The `helm/rest/nico-mcp` chart deploys the same server as a `ClusterIP` service. Set `global.image.repository` and `global.image.tag` for the `nico-mcp` image. The chart accepts optional `config.baseURL`, `config.org`, and `config.apiName` defaults; bearer tokens are intentionally supplied per request rather than through chart values. + ## Quick Reference | Operation | Command | diff --git a/docs/provisioning/ingesting-hosts-rest-api.md b/docs/provisioning/ingesting-hosts-rest-api.md index 495450d358..b8254ba0ee 100644 --- a/docs/provisioning/ingesting-hosts-rest-api.md +++ b/docs/provisioning/ingesting-hosts-rest-api.md @@ -65,6 +65,9 @@ nicocli expected-machine create --data-file - <<'EOF' "defaultBmcUsername": "", "defaultBmcPassword": "", "chassisSerialNumber": "", + "hostLifecycleProfile": { + "disableLockdown": true + }, "fallbackDPUSerialNumbers": ["", ""], "labels": { "environment": "production", @@ -76,6 +79,8 @@ EOF `fallbackDPUSerialNumbers` is JSON-only (no flag form) and is needed for DGX-H100 or other machines where the NetworkAdapter serial number is not available in the host Redfish. +`hostLifecycleProfile` is also JSON-only. Set `disableLockdown` to `true` only when the host must remain unlocked during lifecycle management. When the profile is omitted or `disableLockdown` is `false`, NICo applies UEFI lockdown during `HostInit`. + ### Batch (Recommended for Full-Rack Onboarding) For multiple machines, prefer `batch-create`. The endpoint accepts up to 100 Expected Machines per request and validates the whole batch atomically: @@ -94,6 +99,9 @@ Where `expected-machines.json` is a JSON array of `ExpectedMachineCreateRequest` "defaultBmcUsername": "", "defaultBmcPassword": "", "chassisSerialNumber": "", + "hostLifecycleProfile": { + "disableLockdown": true + }, "rackId": "rack-01" }, { @@ -122,7 +130,7 @@ The high-level flow: 2. **Preingestion**: NICo runs a preingestion state machine against each discovered BMC endpoint (host and DPU). It checks BMC clock drift against site time, resetting the BMC if needed. For host endpoints, firmware components are upgraded to the minimum version required for ingestion. 3. **DPU-host pairing**: Site Explorer correlates host and DPU serial numbers to form matched pairs. Once DPUs are validated and paired, the `ManagedHost` object is created and the state machine starts. 4. **`DpuDiscoveringState` / `DPUInit`**: NICo configures Secure Boot on the DPU, installs the DPU OS (BFB image), and power-cycles the host to apply the new DPU configuration. -5. **`HostInit`**: NICo configures BIOS, sets the host boot order, optionally collects TPM attestation measurements, waits for hardware discovery via the `scout` agent, and applies UEFI lockdown. When `scout` reports back, NICo replaces the temporary predicted host ID (prefix `fm100p`) with a stable host ID (prefix `fm100h`) derived from the host's DMI serial data or TPM certificate. +5. **`HostInit`**: NICo configures BIOS, sets the host boot order, optionally collects TPM attestation measurements, waits for hardware discovery via the `scout` agent, and applies UEFI lockdown unless `hostLifecycleProfile.disableLockdown` is `true`. When `scout` reports back, NICo replaces the temporary predicted host ID (prefix `fm100p`) with a stable host ID (prefix `fm100h`) derived from the host's DMI serial data or TPM certificate. 6. **`BomValidating` / `Validation`**: NICo validates discovered hardware against the expected SKU. If hardware validation is enabled, the host is rebooted and tested before proceeding. 7. **`Ready`**: the host transitions through `HostInit/Discovered` and enters the available pool, ready for an instance to be assigned. diff --git a/rest-api/AGENTS.md b/rest-api/AGENTS.md index c53b725dac..972793d203 100644 --- a/rest-api/AGENTS.md +++ b/rest-api/AGENTS.md @@ -212,6 +212,8 @@ verification expectations. implementation details. - API-layer enum-like request constants exposed through JSON use CapitalCase values, for example `SiteWideRoot` and `BMCRoot`. +- When prose names exact API enum values, format the literals as code, for + example `Set`, `Clear`, and `Restart`, so they are distinct from verbs. - For disruptive machine operations, decide and encode the attached-Instance behavior explicitly. If an operation can power-cycle or otherwise disrupt a tenant workload, check `Machine.IsAssigned` (or the equivalent association) diff --git a/rest-api/api/pkg/api/handler/bmccredential.go b/rest-api/api/pkg/api/handler/bmccredential.go index 4d6a86fb81..72d9c95ec0 100644 --- a/rest-api/api/pkg/api/handler/bmccredential.go +++ b/rest-api/api/pkg/api/handler/bmccredential.go @@ -39,7 +39,7 @@ func NewCreateOrUpdateBMCCredentialHandler(dbSession *cdb.Session, scp *sc.Clien // Handle godoc // @Summary Create Or Update BMC Credential -// @Description Create or update a site-wide or per-BMC root credential. Equivalent to `carbide-admin-cli credential add-bmc`. +// @Description Create or update a site-wide or per-BMC root credential. Equivalent to `nico-admin-cli credential add-bmc`. // @Tags bmc-credential // @Accept json // @Produce json diff --git a/rest-api/api/pkg/api/handler/machinepower.go b/rest-api/api/pkg/api/handler/machinepower.go index 64333429c0..1567a78528 100644 --- a/rest-api/api/pkg/api/handler/machinepower.go +++ b/rest-api/api/pkg/api/handler/machinepower.go @@ -93,7 +93,7 @@ func (h MachinePowerControlHandler) Handle(c echo.Context) error { return cutil.NewAPIErrorResponse(c, http.StatusBadRequest, err.Error(), nil) } - provider, _, apiError := common.IsProviderOrTenant(ctx, logger, h.dbSession, org, dbUser, true, true) + provider, _, apiError := common.IsProviderOrTenant(ctx, logger, h.dbSession, org, dbUser, false, true) if apiError != nil { return cutil.NewAPIErrorResponse(c, apiError.Code, apiError.Message, apiError.Data) } diff --git a/rest-api/api/pkg/api/handler/machinepower_test.go b/rest-api/api/pkg/api/handler/machinepower_test.go index 4478b9eb0f..c36121a3d8 100644 --- a/rest-api/api/pkg/api/handler/machinepower_test.go +++ b/rest-api/api/pkg/api/handler/machinepower_test.go @@ -158,6 +158,18 @@ func TestMachinePowerControlHandlerRequiresProviderAdmin(t *testing.T) { assert.Empty(t, fixture.proxiedReq.FullMethod) } +func TestMachinePowerControlHandlerRejectsProviderViewer(t *testing.T) { + fixture := newMachinePowerHandlerFixture(t, nil) + fixture.user = &cdbm.User{OrgData: cdbm.OrgData{fixture.org: cdbm.Org{ + Name: fixture.org, + Roles: []string{authz.ProviderViewerRole}, + }}} + + rec := fixture.request(t, http.MethodPatch, "/", model.APIMachinePowerControlRequest{Action: model.MachinePowerActionOn}) + assert.Equal(t, http.StatusForbidden, rec.Code) + assert.Empty(t, fixture.proxiedReq.FullMethod) +} + func TestMachinePowerControlHandlerRejectsUnknownMachine(t *testing.T) { fixture := newMachinePowerHandlerFixture(t, nil) fixture.machineID = "missing-machine" diff --git a/rest-api/openapi/oasdiff-breaking-changes-ignore.txt b/rest-api/openapi/oasdiff-breaking-changes-ignore.txt index 7413818f4d..ba74577178 100644 --- a/rest-api/openapi/oasdiff-breaking-changes-ignore.txt +++ b/rest-api/openapi/oasdiff-breaking-changes-ignore.txt @@ -5,6 +5,7 @@ POST /v2/org/{org}/nico/instance/batch the `interfaces/items/virtualFunctionId` PATCH /v2/org/{org}/nico/instance/{instanceId} the `interfaces/items/virtualFunctionId` request property's max was decreased to `15.00` PATCH /v2/org/{org}/nico/machine/{machineId}/power removed the success response with the status `200` PUT /v2/org/{org}/nico/credential/bmc removed the success response with the status `200` +PUT /v2/org/{org}/nico/credential/bmc removed the success response with the status `202` GET /v2/org/{org}/nico/machine the `items/health/alerts/items/inAlertSince` response's property type/format changed from `string, null`/`` to `string, null`/`date-time` for status `200` GET /v2/org/{org}/nico/machine/{machineId} the `health/alerts/items/inAlertSince` response's property type/format changed from `string, null`/`` to `string, null`/`date-time` for status `200` PATCH /v2/org/{org}/nico/machine/{machineId} the `health/alerts/items/inAlertSince` response's property type/format changed from `string, null`/`` to `string, null`/`date-time` for status `200` diff --git a/rest-api/openapi/spec.yaml b/rest-api/openapi/spec.yaml index 550d418883..4930d16024 100644 --- a/rest-api/openapi/spec.yaml +++ b/rest-api/openapi/spec.yaml @@ -1183,18 +1183,20 @@ paths: schema: $ref: '#/components/schemas/BMCCredentialRequest' responses: - '202': - description: Machine power control request was accepted + '200': + description: BMC credential was created or updated content: application/json: schema: $ref: '#/components/schemas/BMCCredential' + '400': + $ref: '#/components/responses/ValidationError' '403': $ref: '#/components/responses/ForbiddenError' operationId: create-or-update-bmc-credential description: |- Create or update a site-wide or per-BMC root credential. Equivalent - to `carbide-admin-cli credential add-bmc`. + to `nico-admin-cli credential add-bmc`. User must have authorization role with `PROVIDER_ADMIN` suffix. '/v2/org/{org}/nico/allocation': @@ -9216,7 +9218,11 @@ paths: $ref: '#/components/responses/GenericHttpError' operationId: reset-machine-bmc description: |- - Reset BMC of a specific Machine. + Reset the BMC of a specific Machine. When an Instance is attached to the + Machine, `acknowledgeAttachedInstance` must be `true`. + + If `useIpmiTool` is `true`, the BMC reset request may be silently + ignored while the BMC is in lockdown mode. For Infrastructure Providers: Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. @@ -9266,7 +9272,11 @@ paths: $ref: '#/components/responses/GenericHttpError' operationId: reprovision-machine-dpu description: |- - Trigger DPU reprovisioning for a Machine. It may be necessary to create a `HostUpdateInProgress` health report for the Machine before DPU reprovisioning can be triggered. + Trigger DPU reprovisioning for a Machine. Before calling this operation, + create a Machine health report containing an alert whose ID is + `HostUpdateInProgress` and whose classifications include + `PreventAllocations`. When an Instance is attached to the Machine, + `acknowledgeAttachedInstance` must be `true`. For Infrastructure Providers: Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. @@ -9418,7 +9428,7 @@ paths: action: ForceRestart responses: '202': - description: Machine power control request was accepted + description: Machine power control request was accepted. The message is empty unless Core returns a power-manager warning. content: application/json: schema: @@ -9426,7 +9436,7 @@ paths: examples: example-1: value: - message: Power control accepted + message: '' '400': $ref: '#/components/responses/ValidationError' '403': @@ -9437,7 +9447,8 @@ paths: $ref: '#/components/responses/GenericHttpError' operationId: machine-power-control-machine description: |- - Execute power control actions for a specific Machine. + Execute power control actions for a specific Machine. When an Instance is + attached to the Machine, `acknowledgeAttachedInstance` must be `true`. Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. '/v2/org/{org}/nico/machine/{machineId}/status-history': @@ -13554,7 +13565,7 @@ components: useIpmiTool: type: boolean default: false - description: Reset the BMC via ipmitool instead of Redfish. + description: Reset the BMC via ipmitool instead of Redfish. The request may be silently ignored while the BMC is in lockdown mode. acknowledgeAttachedInstance: type: boolean description: Acknowledges that an Instance is currently attached to the Machine and this action may disrupt Tenant workload on the Instance. @@ -13569,7 +13580,7 @@ components: properties: mode: type: string - description: DPU reprovisioning mode. + description: Use `Set` to start reprovisioning, `Clear` to remove a pending request, or `Restart` to restart DPUs that already have a request. Restart accepts a host Machine ID only. enum: - Set - Clear @@ -13577,13 +13588,13 @@ components: updateFirmware: type: boolean default: false - description: Whether to update firmware during reprovisioning. + description: Deprecated compatibility field. Firmware is always verified and updated during reprovisioning. acknowledgeAttachedInstance: type: boolean description: Acknowledges that an Instance is currently attached to the Machine and this action may disrupt Tenant workload on the Instance. examples: - - mode: Restart - updateFirmware: true + - mode: Set + updateFirmware: false MachineHealthReportEntry: type: object title: MachineHealthReportEntry @@ -13619,15 +13630,15 @@ components: - Merge - Replace examples: - - source: overrides.sre + - source: maintenance.dpu-reprovision triggeredBy: operator observedAt: '2026-06-24T12:00:00Z' mode: Merge alerts: - - id: dpu.reprovision.in.progress + - id: HostUpdateInProgress message: DPU reprovisioning in progress classifications: - - maintenance + - PreventAllocations MachineHealthReportEntryRequest: type: object title: MachineHealthReportEntryRequest @@ -13656,13 +13667,13 @@ components: - Merge - Replace examples: - - source: overrides.sre + - source: maintenance.dpu-reprovision mode: Merge alerts: - - id: dpu.reprovision.in.progress + - id: HostUpdateInProgress message: DPU reprovisioning in progress classifications: - - maintenance + - PreventAllocations HostFirmwareArtifact: type: object title: HostFirmwareArtifact @@ -13964,7 +13975,7 @@ components: properties: action: type: string - description: Power control action to apply. + description: Redfish power control action to apply to the Machine. ACPowercycle is not supported on Viking systems. enum: - On - GracefulShutdown diff --git a/rest-api/sdk/standard/api_bmc_credential.go b/rest-api/sdk/standard/api_bmc_credential.go index 40d15b554d..31e449efcf 100644 --- a/rest-api/sdk/standard/api_bmc_credential.go +++ b/rest-api/sdk/standard/api_bmc_credential.go @@ -45,7 +45,7 @@ func (r ApiCreateOrUpdateBmcCredentialRequest) Execute() (*BMCCredential, *http. CreateOrUpdateBmcCredential Create Or Update BMC Credential Create or update a site-wide or per-BMC root credential. Equivalent -to `carbide-admin-cli credential add-bmc`. +to `nico-admin-cli credential add-bmc`. User must have authorization role with `PROVIDER_ADMIN` suffix. @@ -128,6 +128,17 @@ func (a *BMCCredentialAPIService) CreateOrUpdateBmcCredentialExecute(r ApiCreate body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v NICoAPIError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 403 { var v NICoAPIError err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) diff --git a/rest-api/sdk/standard/api_bmc_reset.go b/rest-api/sdk/standard/api_bmc_reset.go index 85133ae159..13530c5550 100644 --- a/rest-api/sdk/standard/api_bmc_reset.go +++ b/rest-api/sdk/standard/api_bmc_reset.go @@ -45,7 +45,11 @@ func (r ApiResetMachineBmcRequest) Execute() (*MessageResponse, *http.Response, /* ResetMachineBmc Reset Machine BMC -Reset BMC of a specific Machine. +Reset the BMC of a specific Machine. When an Instance is attached to the +Machine, `acknowledgeAttachedInstance` must be `true`. + +If `useIpmiTool` is `true`, the BMC reset request may be silently +ignored while the BMC is in lockdown mode. For Infrastructure Providers: Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. diff --git a/rest-api/sdk/standard/api_dpu_reprovision.go b/rest-api/sdk/standard/api_dpu_reprovision.go index 113c999a32..99c6bb32c1 100644 --- a/rest-api/sdk/standard/api_dpu_reprovision.go +++ b/rest-api/sdk/standard/api_dpu_reprovision.go @@ -45,7 +45,11 @@ func (r ApiReprovisionMachineDpuRequest) Execute() (*MessageResponse, *http.Resp /* ReprovisionMachineDpu Reprovision Machine DPUs -Trigger DPU reprovisioning for a Machine. It may be necessary to create a `HostUpdateInProgress` health report for the Machine before DPU reprovisioning can be triggered. +Trigger DPU reprovisioning for a Machine. Before calling this operation, +create a Machine health report containing an alert whose ID is +`HostUpdateInProgress` and whose classifications include +`PreventAllocations`. When an Instance is attached to the Machine, +`acknowledgeAttachedInstance` must be `true`. For Infrastructure Providers: Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. diff --git a/rest-api/sdk/standard/api_machine.go b/rest-api/sdk/standard/api_machine.go index 72413ff8c4..e60b75524b 100644 --- a/rest-api/sdk/standard/api_machine.go +++ b/rest-api/sdk/standard/api_machine.go @@ -1573,7 +1573,8 @@ func (r ApiMachinePowerControlMachineRequest) Execute() (*MessageResponse, *http /* MachinePowerControlMachine Machine power control -Execute power control actions for a specific Machine. +Execute power control actions for a specific Machine. When an Instance is +attached to the Machine, `acknowledgeAttachedInstance` must be `true`. Org must have an Infrastructure Provider entity and own the Site that the Machine belongs to. User must have authorization role with `PROVIDER_ADMIN` suffix. diff --git a/rest-api/sdk/standard/model_bmc_reset_request.go b/rest-api/sdk/standard/model_bmc_reset_request.go index 1f6c8e0d2d..8f67952c13 100644 --- a/rest-api/sdk/standard/model_bmc_reset_request.go +++ b/rest-api/sdk/standard/model_bmc_reset_request.go @@ -22,7 +22,7 @@ var _ MappedNullable = &BMCResetRequest{} // BMCResetRequest Request to reset a Machine BMC type BMCResetRequest struct { - // Reset the BMC via ipmitool instead of Redfish. + // Reset the BMC via ipmitool instead of Redfish. The request may be silently ignored while the BMC is in lockdown mode. UseIpmiTool *bool `json:"useIpmiTool,omitempty"` // Acknowledges that an Instance is currently attached to the Machine and this action may disrupt Tenant workload on the Instance. AcknowledgeAttachedInstance *bool `json:"acknowledgeAttachedInstance,omitempty"` diff --git a/rest-api/sdk/standard/model_dpu_reprovision_request.go b/rest-api/sdk/standard/model_dpu_reprovision_request.go index d7dfe30d0a..a84fb5382d 100644 --- a/rest-api/sdk/standard/model_dpu_reprovision_request.go +++ b/rest-api/sdk/standard/model_dpu_reprovision_request.go @@ -24,9 +24,9 @@ var _ MappedNullable = &DpuReprovisionRequest{} // DpuReprovisionRequest Request to trigger DPU reprovisioning for a Machine type DpuReprovisionRequest struct { - // DPU reprovisioning mode. + // Use `Set` to start reprovisioning, `Clear` to remove a pending request, or `Restart` to restart DPUs that already have a request. Restart accepts a host Machine ID only. Mode string `json:"mode"` - // Whether to update firmware during reprovisioning. + // Deprecated compatibility field. Firmware is always verified and updated during reprovisioning. UpdateFirmware *bool `json:"updateFirmware,omitempty"` // Acknowledges that an Instance is currently attached to the Machine and this action may disrupt Tenant workload on the Instance. AcknowledgeAttachedInstance *bool `json:"acknowledgeAttachedInstance,omitempty"` diff --git a/rest-api/sdk/standard/model_machine_power_control_request.go b/rest-api/sdk/standard/model_machine_power_control_request.go index a6ee1240d4..116430d691 100644 --- a/rest-api/sdk/standard/model_machine_power_control_request.go +++ b/rest-api/sdk/standard/model_machine_power_control_request.go @@ -24,7 +24,7 @@ var _ MappedNullable = &MachinePowerControlRequest{} // MachinePowerControlRequest Request to power control a Machine type MachinePowerControlRequest struct { - // Power control action to apply. + // Redfish power control action to apply to the Machine. ACPowercycle is not supported on Viking systems. Action string `json:"action"` // Acknowledges that an Instance is currently attached to the Machine and this action may disrupt Tenant workload on the Instance. AcknowledgeAttachedInstance *bool `json:"acknowledgeAttachedInstance,omitempty"`