|
| 1 | +# Design Proposal: Remote KVM Operations via orch-cli |
| 2 | + |
| 3 | +Author(s): Edge Infrastructure Manager Team |
| 4 | + |
| 5 | +Last updated: 11/11/2025 |
| 6 | + |
| 7 | +## Abstract |
| 8 | + |
| 9 | +Remote KVM (Keyboard-Video-Mouse) enables administrators to remotely view |
| 10 | +and control the display and input devices of Intel AMT-enabled edge nodes. |
| 11 | +This capability is essential for out-of-band troubleshooting, recovery |
| 12 | +operations, and system management when SSH or other in-band access methods |
| 13 | +are unavailable. |
| 14 | + |
| 15 | +This document describes the design proposal for integrating remote KVM |
| 16 | +operations into the Edge Manageability Framework/vPRO through orch-cli or |
| 17 | +web ui. The implementation leverages existing MPS infrastructure and |
| 18 | +maintains full multi-tenancy support. |
| 19 | + |
| 20 | +**Note:** This proposal focuses on KVM session initiation and management |
| 21 | +through orch-cli. The underlying KVM redirection capability is already |
| 22 | +provided by MPS and Intel AMT, requiring only the addition of an |
| 23 | +authorization and session management layer. |
| 24 | + |
| 25 | +## Proposal |
| 26 | + |
| 27 | +### KVM Operation Flow |
| 28 | + |
| 29 | +Remote KVM operations follow the desired/current state reconciliation. When a |
| 30 | +user requests KVM access through orch-cli, the system updates the host's |
| 31 | +`desiredKvmState` field, triggering the dm-manager reconciler to establish a |
| 32 | +session with MPS and return connection details. |
| 33 | + |
| 34 | +The following diagram illustrates the KVM session establishment flow: |
| 35 | + |
| 36 | +### KVM Session Flow |
| 37 | + |
| 38 | +TBD |
| 39 | + |
| 40 | +```mermaid |
| 41 | +sequenceDiagram |
| 42 | + participant CLI as orch-cli |
| 43 | + participant APIV2 as apiv2<br/>(infra-core) |
| 44 | + participant INV as inventory<br/>(infra-core) |
| 45 | + participant DM as dm-manager<br/>(infra-external) |
| 46 | + participant MPS as MPS |
| 47 | + participant AMT as AMT Device |
| 48 | +``` |
| 49 | + |
| 50 | +### KVM Session States |
| 51 | + |
| 52 | +The KVM state machine: |
| 53 | + |
| 54 | +| State | Description | |
| 55 | +|-------|-------------| |
| 56 | +| `KVM_STATE_IDLE` | No active session, default state | |
| 57 | +| `KVM_STATE_REQUESTED` | User requested KVM access (desired state) | |
| 58 | +| `KVM_STATE_ACTIVE` | Session established with valid token | |
| 59 | +| `KVM_STATE_STOPPED` | User requested session termination | |
| 60 | +| `KVM_STATE_ERROR` | Error occurred during session establishment | |
| 61 | + |
| 62 | +### orch-cli Commands |
| 63 | + |
| 64 | +**Command structure**: |
| 65 | + |
| 66 | +- `set host <host-id> --kvm start`: Requests KVM session by setting |
| 67 | + desiredKvmState to KVM_STATE_REQUESTED |
| 68 | +- `set host <host-id> --kvm stop`: Terminates KVM session by setting |
| 69 | + desiredKvmState to KVM_STATE_STOPPED |
| 70 | +- `get host <host-id>`: Query current KVM state and session details |
| 71 | +- Uses standard flags: `--project`, `--api-endpoint` |
| 72 | + |
| 73 | +#### 1. Start KVM Session |
| 74 | + |
| 75 | +```bash |
| 76 | +# First, authenticate with Keycloak |
| 77 | +orch-cli login <keycloakuser> <userpassword> \ |
| 78 | + --keycloak https://api.${CLUSTER}/realms/master |
| 79 | + |
| 80 | +# Start KVM session |
| 81 | +orch-cli set host <host-resource-id> --project <project name> \ |
| 82 | + --api-endpoint "https://api.${CLUSTER}" \ |
| 83 | + --kvm start |
| 84 | +``` |
| 85 | + |
| 86 | +**Output**: |
| 87 | + |
| 88 | +```text |
| 89 | +KVM Session Requested: |
| 90 | + Host: <host-resource-id> |
| 91 | + Session URL: wss://mps.${CLUSTER}/kvm/<session-id> |
| 92 | + Expires: |
| 93 | + |
| 94 | +Open the URL in a browser to access the KVM console. |
| 95 | +``` |
| 96 | + |
| 97 | +#### 2. Stop KVM Session |
| 98 | + |
| 99 | +```bash |
| 100 | +# Stop active KVM session |
| 101 | +orch-cli set host <host-resource-id> --project <project name> \ |
| 102 | + --api-endpoint "https://api.${CLUSTER}" \ |
| 103 | + --kvm stop |
| 104 | +``` |
| 105 | + |
| 106 | +**Output**: |
| 107 | + |
| 108 | +```text |
| 109 | +KVM Session Stopped: |
| 110 | + Host: <host-resource-id> |
| 111 | + Status: Session terminated |
| 112 | +``` |
| 113 | + |
| 114 | +#### 3. Check KVM Status |
| 115 | + |
| 116 | +```bash |
| 117 | +# Query current KVM state |
| 118 | +orch-cli get host <host-resource-id> --project <project name> \ |
| 119 | + --api-endpoint "https://api.${CLUSTER}" |
| 120 | +``` |
| 121 | + |
| 122 | +**Output**: |
| 123 | + |
| 124 | +```json |
| 125 | +{ |
| 126 | + "host_id": "abc-123", |
| 127 | + "desired_state": "KVM_STATE_ACTIVE", |
| 128 | + "current_state": "KVM_STATE_ACTIVE", |
| 129 | + "kvm_url": "wss://", |
| 130 | + "session_token": "", |
| 131 | + "last_updated": "" |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +**Note**: KVM desired/current state: |
| 136 | + |
| 137 | +- `desiredKvmState`: KVM_STATE_REQUESTED, KVM_STATE_STOPPED |
| 138 | +- `currentKvmState`: KVM_STATE_IDLE, KVM_STATE_ACTIVE, KVM_STATE_ERROR |
| 139 | + |
| 140 | +**Authentication Requirements**: |
| 141 | + |
| 142 | +- Keycloak JWT token obtained via `orch-cli login` and stored for |
| 143 | + subsequent commands |
| 144 | +- User must belong to tenant that owns the project |
| 145 | +- User must have appropriate RBAC permissions for host management |
| 146 | + |
| 147 | +### Component Architecture |
| 148 | + |
| 149 | +The KVM operation involves the following EMF components: |
| 150 | + |
| 151 | +- **infra-core/apiv2**: REST API layer that handles host resource PATCH |
| 152 | + requests with KVM state changes |
| 153 | +- **infra-core/inventory**: PostgreSQL database storing host resources |
| 154 | + including KVM state fields |
| 155 | +- **infra-external/dm-manager**: Reconciler service that detects KVM state |
| 156 | + mismatches and orchestrates MPS calls |
| 157 | +- **mps**: Management Presence Server that generates KVM authorization |
| 158 | + tokens and provides WebSocket endpoints |
| 159 | +- **rps**: Remote Provisioning Server that enables KVM during device |
| 160 | + activation |
| 161 | + |
| 162 | +### API Design |
| 163 | + |
| 164 | +**API Endpoint**: `PATCH /compute/hosts/{resourceId}` |
| 165 | + |
| 166 | +**Request Body** (to start KVM session): |
| 167 | + |
| 168 | +```json |
| 169 | +{ |
| 170 | + "desiredKvmState": "KVM_STATE_REQUESTED" |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +**Request Body** (to stop KVM session): |
| 175 | + |
| 176 | +```json |
| 177 | +{ |
| 178 | + "desiredKvmState": "KVM_STATE_STOPPED" |
| 179 | +} |
| 180 | +``` |
| 181 | + |
| 182 | +#### orch-utils Tenancy API Mapping |
| 183 | + |
| 184 | +To enable KVM operations through the Edge Manageability Framework with |
| 185 | +Keycloak JWT authentication, the MPS API endpoints must be registered in the |
| 186 | +tenancy API mapping configuration. |
| 187 | + |
| 188 | +MPS OpenAPI spec: |
| 189 | +<https://github.com/open-edge-platform/orch-utils/tenancy-api-mapping/downloads/amc-opendmt-mps-openapi_2.13.0.yaml> |
| 190 | + |
| 191 | +#### MPS KVM API Endpoints |
| 192 | + |
| 193 | +MPS Swagger documentation: |
| 194 | +<https://github.com/device-management-toolkit/mps/blob/main/swagger.yaml> |
| 195 | + |
| 196 | +##### A. Authorization Endpoint (Token Generation) |
| 197 | + |
| 198 | +TBD |
| 199 | + |
| 200 | +##### B. WebSocket Relay Endpoint (KVM Session) |
| 201 | + |
| 202 | +**Endpoint**: `WSS /relay/webrelay.ashx` |
| 203 | + |
| 204 | +**Purpose**: Establishes WebSocket connection for KVM/SOL/IDER redirection |
| 205 | +to AMT device |
| 206 | + |
| 207 | +##### C. KVM Display Settings Endpoints |
| 208 | + |
| 209 | +**Endpoint**: `GET /api/v1/amt/kvm/displays/{guid}` |
| 210 | + |
| 211 | +**Summary**: Get number of displays information from AMT |
| 212 | + |
| 213 | +**Description**: Retrieve all display information of KVM from AMT |
| 214 | + |
| 215 | +**Request**: |
| 216 | + |
| 217 | +- Method: GET |
| 218 | +- Path parameter: `guid` (device UUID) |
| 219 | + - Example: `123e4567-e89b-12d3-a456-426614174000` |
| 220 | + |
| 221 | +**Response** (200 OK): |
| 222 | + |
| 223 | +```json |
| 224 | +{ |
| 225 | + "displays": [ |
| 226 | + { |
| 227 | + "displayIndex": 0, |
| 228 | + "isActive": true, |
| 229 | + "upperLeftX": 1, |
| 230 | + "upperLeftY": 2, |
| 231 | + "resolutionX": 3, |
| 232 | + "resolutionY": 4, |
| 233 | + "isDefault": true, |
| 234 | + "role": "primary" |
| 235 | + } |
| 236 | + ] |
| 237 | +} |
| 238 | +``` |
| 239 | + |
| 240 | +**Response Schema** (`GetDisplaysResponse`): |
| 241 | + |
| 242 | +- `displays` (array): List of display configurations |
| 243 | + - `displayIndex` (integer): Index of the display |
| 244 | + - `isActive` (boolean): Whether the display is currently active |
| 245 | + - `upperLeftX` (integer): X coordinate of the upper left corner |
| 246 | + - `upperLeftY` (integer): Y coordinate of the upper left corner |
| 247 | + - `resolutionX` (integer): Horizontal resolution in pixels |
| 248 | + - `resolutionY` (integer): Vertical resolution in pixels |
| 249 | + - `isDefault` (boolean): Whether this is the default display |
| 250 | + - `role` (string, enum): Display role - `primary`, `secondary`, `tertiary`, |
| 251 | + `quaternary` |
| 252 | + |
| 253 | +**Error Responses**: |
| 254 | + |
| 255 | +- 404: Device not found |
| 256 | +- 500: Internal server error |
| 257 | + |
| 258 | +--- |
| 259 | + |
| 260 | +**Endpoint**: `PUT /api/v1/amt/kvm/displays/{guid}` |
| 261 | + |
| 262 | +**Summary**: Put the changed settings for KVM in AMT |
| 263 | + |
| 264 | +**Description**: Modify screen settings for KVM in AMT device |
| 265 | + |
| 266 | +**Request**: |
| 267 | + |
| 268 | +- Method: PUT |
| 269 | +- Path parameter: `guid` (device UUID) |
| 270 | + - Example: `123e4567-e89b-12d3-a456-426614174000` |
| 271 | + |
| 272 | +**Request Body** (`UpdateDisplaySettingsRequest`): |
| 273 | + |
| 274 | +```json |
| 275 | +{ |
| 276 | + "displayIndex": 0 |
| 277 | +} |
| 278 | +``` |
| 279 | + |
| 280 | +**Response** (200 OK): |
| 281 | + |
| 282 | +- Returns: `UpdateDisplaySettingsResponse` schema |
| 283 | + |
| 284 | +**Error Responses**: |
| 285 | + |
| 286 | +- 404: Device not found |
| 287 | +- 500: Internal server error |
| 288 | + |
| 289 | +--- |
| 290 | + |
| 291 | +## Implementation Design |
| 292 | + |
| 293 | +## Affected components |
| 294 | + |
| 295 | +## Test plan |
| 296 | + |
| 297 | +## Architecture Open (if applicable) |
0 commit comments