Conversation
raven-pan
marked this pull request as draft
September 15, 2026 07:53
raven-pan
force-pushed
the
feat/876-show-pgpu-device-profile
branch
2 times, most recently
from
September 16, 2026 07:55
ebead5d to
375374f
Compare
To attach a GPU to a VM the operator names that GPU in the flavor, and the property depends on the resource type. A vGPU card is named through `pci_passthrough:alias`, which the profiles table already shows in its Alias Name column. A pgpu card is named through `accel:device_profile`, and the UI showed that string nowhere -- the only way to read it was a root shell running `openstack accelerator device profile list`. The card now carries the name wherever it shows what it can serve: - The expanded row shows `Profiles / ID (1)` with an `Alias Name` column and a copy button. The string exists to be pasted into a flavor command. - The full-view modal's `Profiles / ID` tab shows the same name, one column, one row, no pagination and no copy button. The tab used to be locked for every pgpu card, so the modal dropped the name the row had just shown. Rendered from the card's `deviceProfile` alone, with no second check on the resource type. The spec reports null on every type but pgpu, so a check would only repeat what the value already says. Nothing renders when the value is null, and the modal's tab stays locked -- on a pgpu card that means the profile does not exist yet or could not be looked up. The API gives no reason for the absence and does not mark the card degraded, so a label with no value would tell the operator neither what to paste nor why it is missing. The expanded area was empty for a pgpu card until now: getProfilesByResourceType returns no profiles for one, so the profiles table never rendered, and a card with no VM attached showed nothing at all. Refs bigstack-oss/cubecos#876 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: raven-pan-bigstack <raven.pan@bigstack.co>
The Profiles / ID and Attached Instances tables sat 32px from their border, twice what the design says. `border-separate` puts `border-spacing` around the table's outer edge as well as between cells, and the box added `p-4` on top of it. Drop the box padding. The spacing now comes from one source, so the gap between the border and a cell is the same 16px as the gap between two cells. Measured against the design (Figma nodes 130:21557 and 130:21598): - Border to first cell: 32 -> 16 - Column gap, header to first row, title to table: already 16 / 16 / 8 The change reaches four call sites, all under NodeGpuResources: the two tables in an expanded row, the pgpu device profile block, and the confirm step of the Edit GPU Resource modal. Refs bigstack-oss/cubecos#876 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: raven-pan-bigstack <raven.pan@bigstack.co>
raven-pan
force-pushed
the
feat/876-show-pgpu-device-profile
branch
from
September 16, 2026 07:58
375374f to
f904150
Compare
A failed resource-type change told the operator nothing. The catch block only wrote to the console, and the modal stays open on its confirm step, so the screen looked the same before and after pressing Confirm -- the operator could not tell whether the request had run. The modal now renders the API message in a `CosInlineNotification` above the step content. The error belongs next to the button the operator is about to press again, which is why this is inline and not a toast: the surface is still on screen. A toast fits an action whose surface disappears, such as the GPU console link. `useCosMutationRequest` already carries `errorState` and `clearError`, so the modal needs no state of its own. `oversee` clears the error when the next request starts; `clearError` covers the two other ways the operator leaves the failed state -- Back to edit, and closing the modal. Refs bigstack-oss/cubecos#876 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: raven-pan-bigstack <raven.pan@bigstack.co>
raven-pan
marked this pull request as ready for review
September 16, 2026 08:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
/kind feature
What this PR does / why we need it
A pgpu (passthrough) card is scheduled by name: a flavor asks for it with
accel:device_profile=<name>, and Cyborg matches that name to the card. Untilnow the UI showed that name nowhere, so an operator had to read it off the
controller before they could write the flavor.
The card now carries the name in both places it can appear:
Profiles / ID, with a copy button.Profiles / IDtab shows it too. The tab used to belocked for a pgpu card.
Two bugs found on the way came along:
Profiles / IDandAttached Instancestables sat 32px from theirborder, twice what the design asks for.
Edit GPU Typewrote the reason to the console only, so the modallooked the same before and after pressing Confirm.
Screenshot placeholders — attach by hand
Full-view modal, pgpu card,
Profiles / IDtabExpanded row, both tables with the corrected padding
Full-view modal, MIG-backed vGPU, unchanged
Edit GPU Type modal, confirm step, API error shown
QA perspective
What changed on screen
Node Details page > GPU Resources table.
Profiles / IDsectionProfiles / ID (1)with anAlias Namecolumn, the device profile name and a copy buttonProfiles / IDtab locked, opens onAttached InstancesAlias Namecolumn, one row, no copy buttonProfiles / IDandAttached InstancesEdit GPU Typewhen the API rejects the changeA Passthrough card whose device profile is missing keeps the old behaviour: no
section in the row,
Profiles / IDtab locked, modal opens onAttached Instances.SR-IOV vGPU and MIG-backed vGPU cards keep the tables they had. Only their
padding changes.
Repo dependency
cube-cos-apisupplies thedeviceProfilefield onGET /nodes/{node}/gpuCards. Without an API build that carries it, the fieldarrives as
nulland the section stays hidden — that is the expectedfallback, not a defect.
cube-cos-openapiholds the contract. The field is already ondevelop, sothis PR moves no submodule.
cube-cos-ui(this repo) renders it.Check list
Profiles / ID (1)shows, column headerAlias Name, the device profile name below it.openstack flavor set --property accel:device_profile=<name>. The flavorschedules onto that card.
Profiles / IDand shows the same name, one column, one row, no copy button.Attached Instancestab and back. Both tabs stay clickable.VRAM,Counts,Alias Namecolumns.Remainingcolumn. Open its full view — five columns and pagination, asbefore.
as the gap between two columns.
Edit GPU Typeon a card the API will reject — for example a card aninstance still holds. Press Next, then Confirm. A red message shows the
API's own text above the confirm table. The modal stays open and Confirm
stays clickable.
Back to editin that state. The message disappears. Close andreopen the modal — no stale message.
the profile name and the API error text are not.
Developer perspective
The device profile (
fb6879e6)GpuDeviceProfile.tsx— new component. It returnsnullon a falsydeviceProfile, so it renders on a pgpu card only. The API reportsnullforevery other resource type, and for a pgpu card whose profile does not exist or
could not be read; it gives no reason for the absence, so a label with no
value would tell the operator neither what to paste nor why.
GetInfoTable, the same componentGpuDetails.tsxuses for the profiles and instances tables, with
scrollBehavior="vertical"and one row. Title and column header reuse
nodes.details.profilesIdList.titleandnodes.details.profilesIdList.aliasName.draft added
nodes.details.deviceProfile.title; it is not in this branch.If that row reached the translation sheet, delete it there, or the next
pnpm i18n:syncbrings it back.FullViewDeviceProfileTable.tsx— new component. OneAlias Namecolumnthrough
GetCosBasicTable, no pagination: a pgpu card has exactly one deviceprofile.
GpuDetailsFullViewModal.tsx— the tab is disabled only when a pgpu card hasno
deviceProfile, not for every pgpu card. The default tab follows the sameflag, so the modal opens on
Profiles / IDwhenever that tab has content.The padding (
f9041507)InfoTable.tsxsetborder-separate border-spacing-4on the table andp-4onthe box around it.
border-spacingalso applies at the table's outer edge, sothe two stacked: 16 + 16. Dropping the box padding leaves one source of
spacing.
Measured against the design (Figma nodes
130:21557and130:21598): border tofirst cell 32 -> 16. Column gap, header to first row and title to table were
already 16 / 16 / 8.
The change reaches four call sites, all under
NodeGpuResources: the two tablesin an expanded row, the pgpu block, and the confirm step of the Edit GPU
Resource modal.
The error message (
5c4ea995)EditGPUResourceModal.tsxonly wrote the failure to the console, and its catchdoes not close the modal, so the confirm step stayed on screen with no reason.
It now renders
errorStatein aCosInlineNotificationabove the step content.Inline, not a toast: the surface the action came from is still on screen, and
the operator can press Confirm again. That matches
VerifyEmailSenderModalandthe tunings / triggers forms. A toast fits an action whose surface disappears,
such as
GpuConsoleLink.useCosMutationRequestalready returnserrorStateandclearError, so themodal holds no state of its own.
overseeclears the error when the nextrequest starts;
clearErrorcoversBack to editand closing the modal.Mocks
src/mocks/gpu.tsalready carriesdeviceProfileon every card fromdevelop.handlers.tsis unchanged on this branch — registermockListNodeGpuCardslocally to see the cards without a GPU host.
Which issue(s) this PR fixes
Fixes bigstack-oss/cubecos#876
Special notes for your reviewer
message. The last two came out of reviewing the first.
(
.claude/settings.json,.playwright-mcp/, two throwaway.mjsprobes) isgone -- its message claimed an openapi submodule bump it never contained --
and the rest squashed into the two commits above.
pnpm test: 7 files, 121 tests pass.pnpm lint:tscclean for every package. Prettier flags.impeccable/hook.cache.json, a local tool cache outside this branch.because
primary-body5has a 15px line height. Not addressed here.Additional documentation
🤖 Generated with Claude Code