ugos-client 0.14.2

Rust client library for the UGREEN NAS (UGOS) API: authentication, KVM virtual machine management, snapshots, networks, storage, and images
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
//! KVM-specific types for virtual machine management.

use serde::{Deserialize, Serialize};

// ── VM ──────────────────────────────────────────────────────────────

/// Summary of a VM as returned by `ShowLocalVirtualList`.
///
/// Only the two identity fields are required. Everything else is telemetry
/// that UGOS has already changed once between releases (`virID` disappeared),
/// so a missing field must not fail the whole listing.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmSummary {
    /// VM UUID (used as the API identifier).
    pub vir_name: String,
    /// Human-readable display name.
    pub vir_display_name: String,
    /// Numeric VM ID. Absent since UGOS 1.4.
    #[serde(default, rename = "virID")]
    pub vir_id: i64,
    /// Storage volume name.
    #[serde(default)]
    pub storage_name: String,
    /// OS type: "linux", "windows", "other".
    #[serde(default)]
    pub system_type: String,
    /// OS version (e.g. "win11", or empty).
    #[serde(default)]
    pub system_version: String,
    /// Graphics card type.
    #[serde(default)]
    pub graphic: String,
    /// Guest CPU usage percentage.
    #[serde(default)]
    pub guest_cpu_percent: i64,
    /// Guest total memory in KiB.
    #[serde(default)]
    pub guest_total_memory: i64,
    /// Guest used memory in KiB.
    #[serde(default)]
    pub guest_used_memory: i64,
    /// Host CPU usage percentage.
    #[serde(default)]
    pub host_cpu_percent: i64,
    /// Host used memory in KiB.
    #[serde(default)]
    pub host_used_memory: i64,
    /// Host total memory in KiB.
    #[serde(default)]
    pub host_total_memory: i64,
    /// Upload bytes/s.
    #[serde(default)]
    pub upload: i64,
    /// Download bytes/s.
    #[serde(default)]
    pub download: i64,
    /// VM status: "running" or "shutoff".
    #[serde(default)]
    pub status: String,
    /// Process status (e.g. "createSuccess").
    #[serde(default)]
    pub process_status: String,
    /// Progress percentage (0-100).
    #[serde(default)]
    pub progress: i64,
    /// Unix timestamp of creation.
    #[serde(default)]
    pub create_time: i64,
}

/// Detailed VM configuration from `ShowLocalVirtualMachine`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmDetail {
    /// VM UUID.
    pub virtual_machine_name: String,
    /// Human-readable display name.
    pub virtual_machine_display_name: String,
    /// OS type.
    pub system_type: String,
    /// OS version.
    pub system_version: String,
    /// CPU core allocation.
    pub core: VmResource,
    /// Memory allocation in KiB.
    pub memory: VmResource,
    /// Attached ISO images.
    pub images: Vec<VmImage>,
    /// Attached disks.
    pub dists: Vec<VmDisk>,
    /// Network interfaces.
    pub networks: Vec<VmNetwork>,
    /// Device configuration.
    pub device: VmDevice,
    /// Other configuration options.
    pub other_config: VmOtherConfig,
    /// Storage volume name.
    pub storage_name: String,
    /// Storage volume UUID.
    ///
    /// Required by `CreateVirtualMachine`: without it the endpoint answers
    /// with code 3000, "Fail to create virtual machine" (verified against
    /// UGOS on 2026-08-17). [`KvmApi::vm_create`] fills it in from
    /// [`storage_name`] when it is empty.
    ///
    /// [`KvmApi::vm_create`]: crate::api::kvm::KvmApi::vm_create
    /// [`storage_name`]: Self::storage_name
    #[serde(default, rename = "storageUUID")]
    pub storage_uuid: String,
}

/// A simple `{value: N}` resource field.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VmResource {
    /// The resource value.
    pub value: i64,
}

/// An ISO image attached to a VM.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VmImage {
    /// File path on the NAS.
    pub path: String,
    /// Device name (e.g. "hda").
    pub dev: String,
    /// Boot order.
    pub order: i64,
}

/// A virtual disk attached to a VM.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VmDisk {
    /// Bus type (e.g. "virtio").
    pub bus: String,
    /// Disk size in KiB.
    pub size: i64,
    /// Device name (e.g. "vda").
    ///
    /// Omitted from the request when empty: UGOS rejects an update whose newly
    /// added disk carries a device name (`3002`) and assigns one itself.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub dev: String,
    /// File path to the qcow2 image. Empty, and omitted, for a disk UGOS has
    /// yet to create.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub path: String,
    /// Boot order.
    pub order: i64,
}

/// A network interface attached to a VM.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmNetwork {
    /// Network name (e.g. "vnet-bridge0").
    pub name: String,
    /// MAC address.
    pub mac_address: String,
    /// NIC type (e.g. "virtio").
    #[serde(rename = "type")]
    pub nic_type: String,
}

/// Device configuration for a VM.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmDevice {
    /// Number of USB controllers.
    pub usb_controller: i64,
    /// Attached USB devices.
    pub usb_devices: Vec<serde_json::Value>,
    /// Graphics card type (e.g. "virtio").
    pub graphics_card: String,
    /// Boot type: "uefi" or "bios".
    pub boot_type: String,
}

/// Other VM configuration options.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmOtherConfig {
    /// Whether the VM starts automatically on NAS boot.
    pub auto_matic_start_up: bool,
    /// Keyboard language (e.g. "de").
    pub keyboard_language: String,
    /// Shared directories.
    pub share_directory: Vec<serde_json::Value>,
}

// ── Overview ────────────────────────────────────────────────────────

/// Dashboard payload from `ShowOverview`: host load plus every VM in one call.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Overview {
    /// Host-wide CPU and memory figures.
    #[serde(default)]
    pub host_stats: HostStats,
    /// The same summaries `ShowLocalVirtualList` returns.
    #[serde(default)]
    pub vm_list: Vec<VmSummary>,
}

/// Host load figures from `ShowOverview`.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HostStats {
    /// Host CPU utilisation in percent.
    #[serde(default)]
    pub cpu_util: f64,
    /// Total host memory in bytes.
    #[serde(default)]
    pub host_total_mem: i64,
    /// Memory used by everything except VMs, in bytes.
    #[serde(default)]
    pub other_used_mem: i64,
    /// Total memory in use, in bytes.
    #[serde(default)]
    pub total_used_mem: i64,
    /// Memory used by VMs, in bytes.
    #[serde(default)]
    pub vm_used_mem: i64,
}

// ── Storage usage ───────────────────────────────────────────────────

/// Volume usage from `ShowLocalStorageUsageList`, broken down per VM.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StorageUsage {
    /// Volume name (e.g. "volume1").
    #[serde(default)]
    pub name: String,
    /// Display label (e.g. "Volume 1").
    #[serde(default)]
    pub label: String,
    /// Filesystem type.
    #[serde(default)]
    pub filesystem: String,
    /// Total capacity in bytes.
    #[serde(default)]
    pub total_capacity: i64,
    /// Available capacity in bytes.
    #[serde(default)]
    pub available_capacity: i64,
    /// Capacity used by KVM, in bytes.
    #[serde(default)]
    pub used_capacity: i64,
    /// Share of the volume used by KVM, in percent.
    #[serde(default)]
    pub used_percent: f64,
    /// Number of VMs on this volume.
    #[serde(default)]
    pub vir_count: i64,
    /// Per-VM breakdown.
    #[serde(default)]
    pub vm_usages: Vec<VmUsage>,
}

/// One VM's share of a volume.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VmUsage {
    /// VM display name.
    #[serde(default)]
    pub vir_display_name: String,
    /// VM UUID.
    #[serde(default)]
    pub vir_name: String,
    /// Bytes used by this VM.
    #[serde(default)]
    pub used_capacity: i64,
    /// Share of the volume, in percent.
    #[serde(default)]
    pub used_percent: f64,
}

// ── Snapshot ────────────────────────────────────────────────────────

/// A VM snapshot as returned by `ShowListSnapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Snapshot {
    /// Internal identifier, `<vm-uuid>_<unix-timestamp>`.
    pub name: String,
    /// Display name, which UGOS sets to the creation time.
    #[serde(default)]
    pub display_name: String,
    /// Creation time as `YYYY-MM-DD HH:MM:SS` — a string, not a timestamp.
    #[serde(default)]
    pub create_time: String,
    /// Free-text description, set via `EditSnapshot`.
    #[serde(default)]
    pub description: String,
    /// Numeric id within the VM.
    #[serde(default)]
    pub id: i64,
    /// UUID of the VM the snapshot belongs to.
    #[serde(default)]
    pub vir_name: String,
    /// Screenshot path, if UGOS captured one.
    #[serde(default)]
    pub screenshot: String,
}

// ── Network ─────────────────────────────────────────────────────────

/// Summary of a KVM network from `ShowNetworkList`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NetworkSummary {
    /// Network name (e.g. "vnet-bridge0").
    pub network_name: String,
    /// Network UUID.
    #[serde(rename = "networkUUID")]
    pub network_uuid: String,
    /// Display label (e.g. "VBR-LAN1").
    pub network_label: String,
    /// Whether the network is valid/active.
    pub network_valid: bool,
    /// Network type: "bridge", "nat", "none".
    pub network_type: String,
    /// Network mode.
    pub network_mode: String,
    /// Host interface name.
    pub interface_name: String,
    /// VMs using this network.
    pub virtual_display_names: Vec<String>,
    /// Whether this is a system-managed network.
    pub system_network: bool,
}

/// Detailed network configuration from `GetNetworkByName`.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(clippy::struct_excessive_bools)]
pub struct NetworkDetail {
    /// Network UUID.
    #[serde(rename = "networkUUID")]
    pub network_uuid: String,
    /// Network name.
    pub network_name: String,
    /// Network type.
    pub network_type: String,
    /// Network mode.
    pub network_mode: String,
    /// Mapped host network interface.
    pub mapping_network: String,
    /// IPv4 enabled.
    pub enable_ipv4: bool,
    /// IPv4 DHCP allocation enabled.
    pub allocate_ipv4: bool,
    /// IPv4 subnet.
    pub ipv4_subnet: String,
    /// IPv4 gateway.
    pub ipv4_gateway: String,
    /// IPv4 DHCP range start.
    #[serde(rename = "ipv4DHCPStartIp")]
    pub ipv4_dhcp_start_ip: String,
    /// IPv4 DHCP range end.
    #[serde(rename = "ipv4DHCPEndIp")]
    pub ipv4_dhcp_end_ip: String,
    /// IPv6 enabled.
    pub enable_ipv6: bool,
    /// IPv6 subnet.
    pub ipv6_subnet: String,
    /// IPv6 gateway.
    pub ipv6_gateway: String,
    /// IPv6 DHCP range start.
    #[serde(rename = "ipv6DHCPStartIp")]
    pub ipv6_dhcp_start_ip: String,
    /// IPv6 DHCP range end.
    #[serde(rename = "ipv6DHCPEndIp")]
    pub ipv6_dhcp_end_ip: String,
    /// IPv6 DHCP allocation enabled.
    pub allocate_ipv6: bool,
}

// ── Storage ─────────────────────────────────────────────────────────

/// Storage volume info from `ShowStorageList`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageInfo {
    /// Volume name (e.g. "volume1").
    pub name: String,
    /// Display label (e.g. "Volume 1").
    pub label: String,
    /// Health status code.
    pub health: i64,
    /// Status code.
    pub status: i64,
    /// Total capacity in bytes.
    #[serde(rename = "totalCapacity")]
    pub total_capacity: i64,
    /// Available capacity in bytes.
    #[serde(rename = "availableCapacity")]
    pub available_capacity: i64,
    /// Volume UUID.
    pub uuid: String,
    /// Mount path.
    pub path: String,
    /// Filesystem type (e.g. "btrfs").
    pub filesystem: String,
    /// Number of VMs stored on this volume.
    ///
    /// Only `ShowLocalStorageList` reports this; `ShowStorageList` omits it,
    /// so it defaults to 0 there.
    #[serde(default, rename = "virCount")]
    pub vir_count: i64,
}

// ── Image ───────────────────────────────────────────────────────────

/// ISO/disk image info from `ShowImageList`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ImageInfo {
    /// Image ID.
    pub id: i64,
    /// File name on disk.
    pub file_name: String,
    /// Display name.
    pub image_name: String,
    /// File size in bytes.
    pub file_size: i64,
    /// Upload/processing progress.
    pub progress: i64,
    /// State (e.g. "completed").
    pub state: String,
    /// Image type (e.g. "iso").
    pub image_type: String,
    /// Full path on the NAS.
    pub path: String,
}

// ── USB ─────────────────────────────────────────────────────────────

/// USB device info from `USBList`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UsbDevice {
    /// Vendor ID (e.g. "0x8087").
    #[serde(rename = "vendorID")]
    pub vendor_id: String,
    /// Vendor name.
    pub vendor_name: String,
    /// Product ID (e.g. "0x0033").
    #[serde(rename = "productID")]
    pub product_id: String,
    /// Product name.
    pub product_name: String,
    /// USB bus ID.
    #[serde(rename = "busID")]
    pub bus_id: i64,
    /// USB device ID.
    #[serde(rename = "deviceID")]
    pub device_id: i64,
    /// VM currently using this device (empty if unused).
    pub used_by: String,
}

// ── Host ────────────────────────────────────────────────────────────

/// Host hardware info from `ShowNativeInfo`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostInfo {
    /// Number of CPU cores.
    pub cores: i64,
    /// Total memory in bytes.
    pub memory: i64,
}

// ── VNC ─────────────────────────────────────────────────────────────

/// VNC link info from `ListAllLink`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VncLink {
    /// Link URL or identifier.
    #[serde(default)]
    pub link: String,
    /// Link type.
    #[serde(default, rename = "type")]
    pub link_type: i64,
    /// Password (if set).
    #[serde(default)]
    pub password: String,
    /// API key.
    #[serde(default)]
    pub api_key: String,
}

// ── Logs ────────────────────────────────────────────────────────────

/// A KVM log entry from `PageSearchLogs`.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogEntry {
    /// Log ID.
    #[serde(default)]
    pub id: i64,
    /// Operator username.
    #[serde(default)]
    pub operator: String,
    /// Operation description.
    #[serde(default)]
    pub content: String,
    /// Creation timestamp.
    #[serde(default)]
    pub create_time: String,
}

/// Paginated log search result.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogPage {
    /// Log entries.
    #[serde(default)]
    pub list: Vec<LogEntry>,
    /// Total number of entries.
    #[serde(default)]
    pub total: i64,
}