@ornncompute/cli 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -23
- package/package.json +1 -1
- package/src/api-client.mjs +25 -0
- package/src/cli.mjs +619 -101
package/README.md
CHANGED
|
@@ -56,11 +56,13 @@ ornn nodes keys list <node-id> [--json]
|
|
|
56
56
|
ornn node health <node-id> [--json]
|
|
57
57
|
ornn node diagnose <node-id> [--json]
|
|
58
58
|
ornn node deenroll <node-id> [--reason <text>] [--keep-record] [--json]
|
|
59
|
-
ornn fleet clean <ip>... --operator <id-or-slug> --ib-island <name> --identity-file <path> --dry-run [--ssh-user ubuntu|admin|ornn] [--json]
|
|
60
|
-
ornn fleet clean <failed-fleet-id> --identity-file <path> --dry-run [--json]
|
|
61
|
-
ornn fleet clean <fleet-id> --identity-file <path> --confirm-clean <plan-hash> [--json]
|
|
59
|
+
ornn fleet clean <ip>... --operator <id-or-slug> --ib-island <name> --identity-file <path> --dry-run [--source-user <user>]... [--preserve-user <user>]... [--ssh-user ubuntu|admin|ornn] [--json]
|
|
60
|
+
ornn fleet clean <failed-fleet-id> --identity-file <path> --dry-run [--source-user <user>]... [--preserve-user <user>]... [--json]
|
|
61
|
+
ornn fleet clean <fleet-id> --identity-file <path> --confirm-clean <plan-hash> [--source-user <user>]... [--preserve-user <user>]... [--json]
|
|
62
62
|
ornn fleet enroll <fleet-id> --identity-file <path> [--confirm-takeover <ip[,ip...]>] [--json]
|
|
63
|
-
ornn
|
|
63
|
+
ornn reservations commerce list --tenant <email-or-id> [--fleet <fleet-id>] [--json]
|
|
64
|
+
ornn reservations commerce create --tenant <email> --listing <listing-id> --fleet <fleet-id> [--start-at <timestamp>] [--end-at <timestamp>] [--price-per-gpu-hour <rate>] [--json]
|
|
65
|
+
ornn fleet deploy <fleet-id> --tenant <contact-email> [--user <email-or-id>] --commerce-reservation <id> [--network public|private] [--json]
|
|
64
66
|
ornn ssh <node-or-reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
|
|
65
67
|
ornn metrics nodes [--json]
|
|
66
68
|
ornn metrics node <node-id> [--json]
|
|
@@ -103,9 +105,9 @@ ornn storage volumes create --name <name> [--source <drive-id>] [--json]
|
|
|
103
105
|
ornn storage volumes refresh <drive-id> [--json]
|
|
104
106
|
ornn storage volumes clear <drive-id> [--json]
|
|
105
107
|
ornn storage volumes delete <drive-id> [--json]
|
|
106
|
-
ornn storage
|
|
108
|
+
ornn storage files upload <drive-id> <local-file> [--destination <path>] [--content-type <type>] [--json]
|
|
109
|
+
ornn storage deploy <drive-id> --reservation <reservation-id> [--all-nodes] [--mount-path <path>] [--read-only|--read-write] [--json]
|
|
107
110
|
ornn storage deploy status --reservation <reservation-id> [--json]
|
|
108
|
-
ornn storage unmount --reservation <reservation-id> [--json]
|
|
109
111
|
ornn storage undeploy --reservation <reservation-id> [--json]
|
|
110
112
|
ornn storage buckets list [--json]
|
|
111
113
|
ornn storage buckets show <drive-id> [--json]
|
|
@@ -143,8 +145,23 @@ current user's complete reservation key set on those machines. Use
|
|
|
143
145
|
`ornn access keys push` to explicitly re-sync keys that are already attached.
|
|
144
146
|
|
|
145
147
|
`ornn storage deploy status` prints reconciled object and byte progress once the
|
|
146
|
-
managed transfer has reported progress
|
|
147
|
-
|
|
148
|
+
managed transfer has reported progress, plus the number of target nodes that
|
|
149
|
+
have acknowledged the mount. Internal placement bucket details are not shown.
|
|
150
|
+
AWS S3 and external GCS sources use the managed transfer path. Cloudflare R2
|
|
151
|
+
buckets can be connected and verified, but deployment support is coming soon.
|
|
152
|
+
|
|
153
|
+
`ornn storage files upload` adds a file to the drive's current colocated copy.
|
|
154
|
+
You can upload while a direct FUSE mount is active; every mounted node sees the
|
|
155
|
+
file on its next lookup without a remount. A direct FUSE drive attaches to one
|
|
156
|
+
reservation by default; pass `--all-nodes` on `ornn storage deploy` to fan the
|
|
157
|
+
same mount out across every compatible node in the node group. Avoid writing
|
|
158
|
+
the same file path concurrently from multiple nodes because object storage is
|
|
159
|
+
not a POSIX shared filesystem.
|
|
160
|
+
|
|
161
|
+
For a connected bucket, deploy once before uploading. The first deploy imports
|
|
162
|
+
the source into an Ornn-managed colocated working copy. That copy remains the
|
|
163
|
+
drive's durable data when you unmount, detach, or mount it elsewhere. Ornn
|
|
164
|
+
does not write changes back to the original connected bucket.
|
|
148
165
|
|
|
149
166
|
UI aliases are first-class in the CLI: `listings` maps to the older
|
|
150
167
|
`availability` command, `exchange` maps to `bid`, and `gpus` maps to
|
|
@@ -200,7 +217,7 @@ The operator resource commands share the same reviewer auth:
|
|
|
200
217
|
filtered to one operator.
|
|
201
218
|
- `ornn tokens list` lists enrollment tokens.
|
|
202
219
|
- `ornn tokens create --operator <id> [--facility <id>]
|
|
203
|
-
|
|
220
|
+
[--expires-in <seconds>] [--mode bare-metal|vm] [--ip <addr>]` mints an
|
|
204
221
|
enrollment token and prints a ready-to-run `curl … | sudo bash` install
|
|
205
222
|
command.
|
|
206
223
|
- `ornn tokens revoke <token-id>` revokes an enrollment token.
|
|
@@ -212,11 +229,17 @@ Fleet handoff is an ordered, Compute-backed workflow:
|
|
|
212
229
|
not trust a key first presented during cleanup.
|
|
213
230
|
- `fleet clean ... --dry-run` tries `ubuntu`, `admin`, then `ornn`, records each
|
|
214
231
|
host's hardware identity and exact deletion plan, and prints one fleet plan
|
|
215
|
-
hash.
|
|
232
|
+
hash. Repeat `--source-user` for Linux accounts owned by the departing tenant
|
|
233
|
+
(including an explicitly reviewed orphaned `/home/<user>` directory) and
|
|
234
|
+
`--preserve-user` for reviewed host accounts. Package/service-owned
|
|
235
|
+
accounts are protected automatically; any other account stops planning for
|
|
236
|
+
explicit review. Re-running with `--confirm-clean <plan-hash>` and the same
|
|
237
|
+
account flags removes the approved tenant
|
|
216
238
|
users, keys, containers/images/volumes/networks/build cache, workload paths,
|
|
217
|
-
mounts, services, and logs
|
|
218
|
-
|
|
219
|
-
|
|
239
|
+
mounts, services, and tenant-scoped logs. Apply refuses plans with running
|
|
240
|
+
containers, locks the management/root passwords, enforces key-only SSH, trims
|
|
241
|
+
supported filesystems, preserves existing root and management keys and host
|
|
242
|
+
logs, and stores per-node proof in Compute. A failed
|
|
220
243
|
cleanup can be dry-run again with the same fleet ID; only failed members are
|
|
221
244
|
replanned. Residual GPU
|
|
222
245
|
consumers or tenant/platform listeners fail verification instead of being
|
|
@@ -226,11 +249,22 @@ Fleet handoff is an ordered, Compute-backed workflow:
|
|
|
226
249
|
assigns the IB island, verifies the same management account still has
|
|
227
250
|
key-based SSH and passwordless sudo, and records the resulting GPU node IDs
|
|
228
251
|
in Compute. Generic enrollment tokens retain the legacy enrollment sanitizer.
|
|
229
|
-
- `
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
252
|
+
- `reservations commerce create --tenant <email> --listing <listing-id>
|
|
253
|
+
--fleet <fleet-id>` creates and activates the tenant's Commerce reservation.
|
|
254
|
+
GPU count comes from the enrolled fleet; start, end, and hourly rate default
|
|
255
|
+
from the listing. Start and end overrides must remain inside the listing's
|
|
256
|
+
allowed window; the hourly rate can also be overridden explicitly.
|
|
257
|
+
- `reservations commerce list --tenant <email-or-id> [--fleet <fleet-id>]`
|
|
258
|
+
lists active reservations in their live window; with `--fleet`, it returns
|
|
259
|
+
only reservations whose listing exactly matches that fleet's operator,
|
|
260
|
+
facility, GPU model, per-node size, and total GPU count.
|
|
261
|
+
- `fleet deploy <fleet-id> --tenant <contact-email>
|
|
262
|
+
[--user <email-or-id>] --commerce-reservation <id>` requires a live,
|
|
263
|
+
tenant-owned Commerce reservation whose listing exactly matches the fleet.
|
|
264
|
+
The user defaults to the tenant's primary administrator. Deployment succeeds
|
|
265
|
+
only after that user's SSH access and passwordless sudo are ready on every
|
|
266
|
+
node; Commerce is stamped only after the entire fleet reports deployed. A
|
|
267
|
+
Commerce reservation can be linked to only one fleet.
|
|
234
268
|
|
|
235
269
|
Compute Postgres is authoritative; the mode-0600 files under
|
|
236
270
|
`~/.config/ornn/fleets/` are only a secret-free cache. Cleanup proves “no
|
|
@@ -242,17 +276,22 @@ control-plane policy.
|
|
|
242
276
|
|
|
243
277
|
Reservation lifecycle verbs also run under the operator surface:
|
|
244
278
|
|
|
279
|
+
- `ornn reservations commerce create|list` creates or discovers a validated
|
|
280
|
+
Commerce reservation for an enrolled fleet. These actions require a staff
|
|
281
|
+
`ornn login`; the direct review-secret path cannot bypass Web validation.
|
|
245
282
|
- `ornn reservations withdraw <reservation-id>` withdraws a reservation's
|
|
246
283
|
acceptance, returning the node(s) to tenant inventory.
|
|
247
284
|
- `ornn reservations transfer <reservation-id> --target-tenant <id>
|
|
248
|
-
|
|
285
|
+
[--target-user <id>] [--node <id>] [--strategy reject|park] [--confirm]`
|
|
249
286
|
transfers a reservation to another tenant.
|
|
250
|
-
- `ornn reservations deploy <node-id> --target-tenant <id>
|
|
251
|
-
|
|
287
|
+
- `ornn reservations deploy <node-id> --target-tenant <id>
|
|
288
|
+
--commerce-reservation <id> [--target-user <id>] [--network public|private]`
|
|
289
|
+
deploys one node only after Web verifies that the live tenant-owned Commerce
|
|
290
|
+
reservation and listing match that node.
|
|
252
291
|
|
|
253
292
|
The tenant `ornn reservations list|show|checkout` verbs still use the tenant CLI
|
|
254
|
-
login and `/api/cli` proxy
|
|
255
|
-
|
|
293
|
+
login and `/api/cli` proxy. Staff Commerce actions use the Web operator proxy;
|
|
294
|
+
`withdraw|transfer|deploy` retain the operator path above.
|
|
256
295
|
|
|
257
296
|
Staff happy path:
|
|
258
297
|
|
package/package.json
CHANGED
package/src/api-client.mjs
CHANGED
|
@@ -271,6 +271,28 @@ export async function operatorRequest({
|
|
|
271
271
|
);
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Commerce-backed operator actions must cross the Web trust boundary. Web
|
|
276
|
+
* validates Commerce state before it forwards to Compute, so direct
|
|
277
|
+
* review-secret access is intentionally unavailable for these requests.
|
|
278
|
+
*/
|
|
279
|
+
export async function webOperatorRequest({
|
|
280
|
+
body,
|
|
281
|
+
endpoint,
|
|
282
|
+
env = process.env,
|
|
283
|
+
fetchImpl = fetch,
|
|
284
|
+
method = "GET",
|
|
285
|
+
} = {}) {
|
|
286
|
+
const session = await loadAuthSession({ env });
|
|
287
|
+
if (!session?.accessToken) {
|
|
288
|
+
throw new CliApiError(
|
|
289
|
+
"Commerce-backed deployment requires Ornn staff auth through Web. Run `ornn login` first.",
|
|
290
|
+
{ status: 401 },
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return operatorRequestViaStaffSession({ body, endpoint, env, fetchImpl, method });
|
|
294
|
+
}
|
|
295
|
+
|
|
274
296
|
export function computeEndpoint(path) {
|
|
275
297
|
const normalized = normalizeComputePath(path);
|
|
276
298
|
return `/api/cli/compute${normalized}`;
|
|
@@ -341,6 +363,9 @@ function detailMessage(detail) {
|
|
|
341
363
|
if (!detail || typeof detail !== "object") {
|
|
342
364
|
return "";
|
|
343
365
|
}
|
|
366
|
+
if (typeof detail.message === "string") {
|
|
367
|
+
return detail.message;
|
|
368
|
+
}
|
|
344
369
|
if (typeof detail.summary === "string") {
|
|
345
370
|
return detail.summary;
|
|
346
371
|
}
|