GPU VM
Quy ước chung
- Base URL:
BASE_API_URL - Path:
/bff/v1/gpu-vm/{orgIdentifier}/workspaces/{workspaceIdentifier}/{action} - Method: Tất cả đều POST.
- Header riêng của service:
X-Region: <region> - Header chung (apiClient):
x-scope: workspace,X-Org-Id,X-Workspace-Id,X-User-Id - Response envelope:
{ "code": "", "message": "", "data": ..., "total": 0 }
Cách lấy Token và Header
- Đăng nhập vào Portal, mở trang GPU Virtual Machine.
- Mở Network tab trong DevTools của trình duyệt, chọn request
gpu-vm.listđể lấy định dạng API path (bao gồmorgIdentifiervàworkspaceIdentifier). - Lấy các giá trị Request Header sau:
cookie,x-env,x-org-id,x-region,x-user-id,x-workspace-id.
Danh sách endpoint
Flavor / Image / Storage policy
| # | Action | Query param | Body | Mục đích |
|---|---|---|---|---|
| 1 | gpu-vm.flavor.list | search, region | {} | Danh sách flavor (GPU instance) |
| 2 | gpu-vm.image.list | — | {} | Danh sách OS image |
| 3 | gpu-vm.storagepolicy.listoption | flavor_id | {} | Danh sách storage policy |
Virtual machine
| # | Action | Query param | Body | Mục đích |
|---|---|---|---|---|
| 4 | gpu-vm.list | search, region | {} | Danh sách VM |
| 5 | gpu-vm.listoption | region, storage_type | {} | Danh sách VM dạng option (chọn VM để attach) |
| 6 | gpu-vm.get | — | { virtual_machine_id } | Chi tiết VM |
| 7 | gpu-vm.create | — | Xem bên dưới | Tạo VM |
| 8 | gpu-vm.start | region | { virtual_machine_id } | Power on |
| 9 | gpu-vm.stop | — | { virtual_machine_id } | Power off |
| 10 | gpu-vm.reboot | — | { virtual_machine_id } | Reboot |
| 11 | gpu-vm.delete | — | { virtual_machine_id } | Xoá VM |
| 12 | gpu-vm.monitor | virtual_machine_id | { virtual_machine_id } | Lấy URL monitor |
| 13 | gpu-vm.console | — | { virtual_machine_id } | Lấy URL console |
| 14 | gpu-vm.calculateprice | — | { flavor_id, storage_items[] } | Tính giá VM |
| 15 | gpu-vm.port.edit.exposedports | — | { virtual_machine_id, ports: number[] } | Cập nhật exposed ports |
| 16 | gpu-vm.securitygroup.listbyvm | search, region | { virtual_machine_id } | Security group đang áp dụng cho VM |
Storage (disk)
| # | Action | Query param | Body | Mục đích |
|---|---|---|---|---|
| 17 | gpu-vm.storage.list | search, region, volume_type, storage_tier, status | {} | Danh sách storage |
| 18 | gpu-vm.storage.listbyvm | search, region | { virtual_machine_id } | Storage của một VM |
| 19 | gpu-vm.storage.get | — | { storage_id } | Chi tiết storage |
| 20 | gpu-vm.storage.checkname | name | { name } | Kiểm tra trùng tên |
| 21 | gpu-vm.storage.create | — | Xem bên dưới | Tạo storage |
| 22 | gpu-vm.storage.edit | — | Xem bên dưới | Sửa storage |
| 23 | gpu-vm.storage.attach | — | { storage_id, virtual_machine_id } | Gắn storage vào VM |
| 24 | gpu-vm.storage.detach | — | { storage_id } | Gỡ storage khỏi VM |
| 25 | gpu-vm.storage.delete | — | { storage_id } | Xoá storage |
| 26 | gpu-vm.storage.calculateprice | — | { type, quantity } | Tính giá storage |
Security group
| # | Action | Query param | Body | Mục đích |
|---|---|---|---|---|
| 27 | gpu-vm.securitygroup.list | search, region | {} | Danh sách security group |
| 28 | gpu-vm.securitygroup.listoption | search, region | {} | Danh sách dạng option |
| 29 | gpu-vm.securitygroup.checkname | sg_name | { sg_name } | Kiểm tra trùng tên |
| 30 | gpu-vm.securitygroup.get | security_group_id | { security_group_id } | Chi tiết (kèm rule) |
| 31 | gpu-vm.securitygroup.create | — | Xem bên dưới | Tạo security group |
| 32 | gpu-vm.securitygroup.rule.edit | — | Xem bên dưới | Sửa rule / tên / apply_to |
| 33 | gpu-vm.securitygroup.delete | — | { security_group_id } | Xoá security group |
Request body
7. gpu-vm.create
Mọi field optional theo type.
{
"name": "my-vm",
"flavor_id": "...",
"image_id": "...",
"expose_ports": [22, 8888],
"security_group_id": "...",
"storage_type": "NVME | BLOCK",
"nvme_storages": [{ "id": "", "name": "", "storage_policy_id": "", "storage_policy_name": "", "disk_size_gb": 100, "description": "", "price": 0, "price_text": "" }],
"block_storages": [{ "id": "", "volume_type": "", "storage_policy_id": "", "storage_policy_name": "", "disk_size_gb": 100, "name": "", "price": 0, "price_text": "", "is_boot": true }],
"boot_volume": { "name": "boot", "storage_policy_id": "...", "disk_size_gb": 100 },
"data_volumes": [{ "name": "data", "storage_policy_id": "...", "disk_size_gb": 500 }],
"authentication_type": "SSH_KEY | PASSWORD",
"ssh_public_key": "ssh-ed25519 AAAA...",
"root_username": "root",
"root_password": "",
"cloud_init_script": "",
"billing_plan": "PAYG"
}
Response: { id, name, gpu_id, gpu_flavor_id, image_id, public_ip, private_ip, status, created_at }.
14. gpu-vm.calculateprice
{ "flavor_id": "...", "storage_items": [{ "storage_type": "BLOCK", "storage_policy_id": "...", "disk_size_gb": 100 }] }
Response: { total_credit, total_currency, total_unit, credit_items: [{ sku, currency, credit, unit }] }.
15. gpu-vm.port.edit.exposedports
Response: { ports_added: number[], ports_deleted: number[] }.
21. gpu-vm.storage.create
{ "name": "disk-1", "virtual_machine_id": null, "storage_type": "...", "storage_policy_id": "...", "disk_size_gb": 100 }
22. gpu-vm.storage.edit
{ "storage_id": "...", "storage_policy_id": "...", "disk_size_gb": 200 }
23 / 24. gpu-vm.storage.attach / gpu-vm.storage.detach
Response: { ports_added, ports_deleted }.
26. gpu-vm.storage.calculateprice
Response: { name, quantity, credit, credit_unit, credit_currency }.
31. gpu-vm.securitygroup.create / 32. gpu-vm.securitygroup.rule.edit
Thêm security_group_id vào body khi edit.
{
"name": "sg-1",
"apply_to": ["<vm_id>"],
"inbound_rules": [{ "id": "", "type": "", "protocol": "TCP", "ip_type": "", "sources": ["0.0.0.0/0"], "port_ranges": ["22"], "action": "", "description": "" }],
"outbound_rules": [{ "id": "", "type": "", "protocol": "TCP", "ip_type": "", "destinations": ["0.0.0.0/0"], "port_ranges": ["All"], "action": "", "description": "" }]
}
Response: { id, name, display_name, status }.
Response chính
| Action | Response |
|---|---|
gpu-vm.flavor.list | [{ id, name, description, type, gpu_id, gpu_name, info{cpu, ram, gpu, gpu_ram, storage_policy, volume_capacity, nvme_volume_type}, price_info{currency, value, unit}, display_order, is_nvme, is_nvme_available, is_block_storage_available, supported_storage_types[], is_available, images[{id, display_name}], region }] |
gpu-vm.image.list | [{ id, catalog, template, name, display_name, description, tooltip_data, logo, support_flavor_gpu[], min_boot_size_gb, region }] |
gpu-vm.storagepolicy.listoption | [{ id, name, storage_type, free_storage_size_gb, price_info, setting_data{free_block_storage_size_gb}, region }] |
gpu-vm.list | [{ id, name, os_image, root_disk, disk_type, billing_plan, flavor_type, flavor, status, created_at, created_by, updated_at, public_ip, private_ip, ports[], region }] |
gpu-vm.listoption | [{ id, name, region, vpc_id, status }] |
gpu-vm.get | { id, name, image_name, image_display_name, flavor_id, gpu_flavor_id, flavor, flavor_type, storage_type, storage_capacity, created_at, created_by, updated_at, updated_by, private_ip, public_ip, user_name, ssh_key, status, billing_plan, ports[{port, status}], region } |
gpu-vm.start / stop / reboot | VirtualMachineDetail (như gpu-vm.get) |
gpu-vm.monitor | { url } |
gpu-vm.console | { console_url } |
gpu-vm.securitygroup.listbyvm | [{ id, name, display_name, status, created_at, updated_at }] |
gpu-vm.storage.list / listbyvm | [{ id, name, volume_type, storage_type, storage_policy_id, storage_policy_name, disk_size_gb, region, vpc_id, attach_to{id, name}, status, created_at, created_by, updated_at, updated_by }] |
gpu-vm.storage.get | { id, user_id, virtual_machine_id, name, volume_type, storage_type, storage_policy_id, disk_size_gb, created_at, created_by, updated_at, updated_by } |
gpu-vm.storage.create / edit | { id, name, virtual_machine_id, storage_type, storage_policy_id, disk_size_gb } |
gpu-vm.storage.checkname, gpu-vm.securitygroup.checkname | { is_duplicate: boolean } |
gpu-vm.securitygroup.list | [{ id, name, display_name, apply_to[{id, name}], is_default, status, created_at, created_by, updated_at, total_of_rule, total_of_virtual_machine, region }] |
gpu-vm.securitygroup.listoption | [{ id, name, display_name, region, is_default }] |
gpu-vm.securitygroup.get | { id, name, region, display_name, apply_to[], is_default, created_at, created_by, inbound_rules[], outbound_rules[], status } |
gpu-vm.delete, gpu-vm.storage.delete | Không dùng body trả về. |
Mã lỗi
Định dạng lỗi
Khi lỗi, HTTP status ≠ 2xx và body có dạng:
{ "code": "GPU-VM-VM-00001", "message": "...", "params": { "port": 80 }, "role_based": false }
role_based: true— thông báo phụ thuộc vai trò (MANAGEMENT/WS_ADMIN/MEMBER).- HTTP 401 — tự đăng xuất và chuyển về trang login.
Mã lỗi chung (gateway / BFF / billing)
| Code | Ý nghĩa |
|---|---|
INSUFFICIENT_BALANCE | Không đủ credit. Role MANAGEMENT sẽ tự mở modal top-up, các role khác được yêu cầu liên hệ owner. |
INSUFFICIENT_PERMISSIONS | Không có quyền thực hiện thao tác. |
EQ-RESOURCE-SYSTEM-LIMIT | Đã đạt quota của resource (params.name). |
BFF-CREATING-CONCURRENCY | Đang có resource khác được tạo trong workspace/service này, chờ hoàn tất rồi thử lại. |
route_not_found | Endpoint không tồn tại. |
method_not_allowed | Sai method (chỉ dùng POST). |
request_too_large | Body vượt 64 KB. |
invalid_token | Token không hợp lệ hoặc hết hạn. |
gateway_internal_error | Lỗi nội bộ gateway. |
upstream_unavailable | Service phía sau tạm thời không khả dụng. |
gateway_timeout | Service phía sau timeout. |
Mã lỗi GPU VM
Chung (GPU-VM-COMMON-*)
| Code | Thông báo |
|---|---|
GPU-VM-COMMON-0001 | Something went wrong. Please try again later. |
GPU-VM-COMMON-0002 | Missing required headers: {{headers}} |
GPU-VM-COMMON-0003 | Invalid UUID format for header {{headerName}}: {{headerValue}} |
GPU-VM-COMMON-0004 | Invalid role value in X-Portal-Roles header: {{role}} |
GPU-VM-COMMON-0005 | Workspace admin access required. |
GPU-VM-COMMON-0006 | Workspace member access required. |
GPU-VM-COMMON-0007 | Request validation error. |
Virtual machine (GPU-VM-VM-*)
| Code | Thông báo |
|---|---|
GPU-VM-VM-00001 | Virtual machine not found. |
GPU-VM-VM-00002 | Virtual machine status is invalid. |
GPU-VM-VM-00003 | No available resources to create this VM. Please try a smaller flavor or contact FPT Support. |
GPU-VM-VM-00004 | The port is being deleted. Please try again later. |
GPU-VM-VM-00005 | Image not found. |
GPU-VM-VM-00006 | Flavor not found. |
GPU-VM-VM-00007 | Image is not supported. |
GPU-VM-VM-00008 | The selected VM no longer exists. Please refresh and try again. |
GPU-VM-VM-00009 | Virtual machine name is required. Please enter a valid name. |
GPU-VM-VM-00010 | Invalid name. Name limits up to 40 characters. Only letters, numbers, and hyphens are allowed. |
GPU-VM-VM-00011 | GPU flavor is required. |
GPU-VM-VM-00012 | OS image is required. |
GPU-VM-VM-00013 | Expose ports is required. |
GPU-VM-VM-00014 | Expose port {{port}} is invalid. |
GPU-VM-VM-00015 | Only one data volume is allowed. |
GPU-VM-VM-00016 | Authentication type is required. |
GPU-VM-VM-00017 | Authentication type is invalid. |
GPU-VM-VM-00018 | SSH public key is required. |
GPU-VM-VM-00019 | SSH public key is invalid format. |
GPU-VM-VM-00020 | Password is required. |
GPU-VM-VM-00021 | cloud_init_script is invalid. |
GPU-VM-VM-00022 | Billing plan is invalid. |
GPU-VM-VM-00023 | Port {{port}} is invalid. |
Security group (GPU-VM-SG-*)
| Code | Thông báo |
|---|---|
GPU-VM-SG-00001 | Security group not found. |
GPU-VM-SG-00002 | The name already exists. Please enter a different one. |
GPU-VM-SG-00003 | Invalid virtual machine ID. |
GPU-VM-SG-00004 | Cannot delete the default security group. |
GPU-VM-SG-00005 | Please detach this security group from any virtual machines before deleting. |
GPU-VM-SG-00006 | Name is required. Please enter a valid name. |
GPU-VM-SG-00007 | Invalid name. Name limits up to 32 characters. Only letters, numbers, and hyphens are allowed. |
GPU-VM-SG-00008 | Duplicate rules. |
GPU-VM-SG-00009 | Rule type is required. |
GPU-VM-SG-00010 | Rule type is invalid. |
GPU-VM-SG-00011 | Rule protocol is required. |
GPU-VM-SG-00012 | Rule protocol is invalid. It must be one of: All, ICMP, TCP, UDP. |
GPU-VM-SG-00013 | Rule IP type is required. |
GPU-VM-SG-00014 | Rule IP type is invalid. Only IPv4 & IPv6 is supported. |
GPU-VM-SG-00015 | Rule IP type is invalid. Only IPv4 & IPv6 is supported for outbound rules. |
GPU-VM-SG-00016 | Rule source is required. |
GPU-VM-SG-00017 | Rule destination is required. |
GPU-VM-SG-00018 | Rule port range is required. |
GPU-VM-SG-00019 | Rule action is required. |
GPU-VM-SG-00020 | Rule action is invalid. |
GPU-VM-SG-00021 | Rule protocol or port range does not match the selected type. Rule type '{{ruleType}}' requires protocol '{{expectedProtocol}}' and port range '{{expectedPortRange}}', but got protocol '{{actualProtocol}}' and port range '{{actualPortRange}}'. |
GPU-VM-SG-00022 | Rule source is invalid: {{source}}. |
GPU-VM-SG-00023 | Rule destination is invalid: {{destination}}. |
GPU-VM-SG-00024 | Rule port range is invalid: {{port}}. |
GPU-VM-SG-00025 | Custom rule port range: cannot be 'All'. |
GPU-VM-SG-00026 | Rule description is invalid: {{description}}. |
Storage (GPU-VM-SR-*)
| Code | Thông báo |
|---|---|
GPU-VM-SR-00001 | Storage disk not found. |
GPU-VM-SR-00002 | Storage policy not found. |
GPU-VM-SR-00003 | Storage policy is invalid. |
GPU-VM-SR-00004 | A volume with this name already exists in the region. |
GPU-VM-SR-00005 | Storage disk has not been detached yet. |
GPU-VM-SR-00006 | Another virtual machine has already been attached to this storage. |
GPU-VM-SR-00007 | Storage disk status is invalid for update. |
GPU-VM-SR-00008 | Storage disk status is invalid for attachment. |
GPU-VM-SR-00009 | Storage disk status is invalid for detachment. |
GPU-VM-SR-00010 | Storage disk status is invalid for deletion. |
GPU-VM-SR-00011 | Only data volume is allowed to update. |
GPU-VM-SR-00012 | Only block storage disks can be resized or changed to another storage tier. |
GPU-VM-SR-00013 | Only data volume is allowed to attach. |
GPU-VM-SR-00014 | Only data volume is allowed to detach. |
GPU-VM-SR-00015 | Only data volume is allowed to delete. |
GPU-VM-SR-00016 | The new capacity must be greater than current size. |
GPU-VM-SR-00017 | Boot storage size must be between {{minSizeGb}} GB and {{maxSizeGb}} GB. |
GPU-VM-SR-00018 | Data storage size must be between {{minSizeGb}} GB and {{maxSizeGb}} GB. |
GPU-VM-SR-00019 | Name is required. Please enter a valid name. |
GPU-VM-SR-00020 | Name limits up to {{maxLength}} characters. |
GPU-VM-SR-00021 | Only lowercase letters, numbers, and hyphens are allowed. Must start with a letter. |
GPU-VM-SR-00022 | Minimum capacity is {{minSizeGb}} GB, Maximum capacity is {{maxSizeGb}} GB. Please enter a valid number. |