Skip to content

Commit 138e11c

Browse files
authored
Merge pull request #134 from Dstack-TEE/teepod-ui-opt
teepod: Optimize UI
2 parents fc84ce1 + 411d257 commit 138e11c

File tree

4 files changed

+759
-140
lines changed

4 files changed

+759
-140
lines changed

teepod/rpc/proto/teepod_rpc.proto

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,33 @@ message UpgradeAppRequest {
9898
bytes encrypted_env = 3;
9999
// Optional update user config. Leave empty to not update.
100100
string user_config = 4;
101+
// Optional update port mapping.
102+
bool update_ports = 5;
103+
// Port mapping
104+
repeated PortMapping ports = 7;
105+
}
106+
107+
// Message for Status request
108+
message StatusRequest {
109+
// List of VM IDs
110+
repeated string ids = 1;
111+
// Brief (Don't include VM configuration)
112+
bool brief = 2;
113+
// Filter by keyword
114+
string keyword = 3;
115+
// Page number
116+
uint32 page = 4;
117+
// Page size
118+
uint32 page_size = 5;
101119
}
102120

103-
// Message for VM list response
104121
message StatusResponse {
105122
// List of VMs
106123
repeated VmInfo vms = 1;
107124
// Port mapping enabled
108125
bool port_mapping_enabled = 2;
126+
// Total number of VMs
127+
uint32 total = 3;
109128
}
110129

111130
message ImageListResponse {
@@ -206,7 +225,7 @@ service Teepod {
206225
rpc ResizeVm(ResizeVmRequest) returns (google.protobuf.Empty);
207226

208227
// RPC to list all VMs
209-
rpc Status(google.protobuf.Empty) returns (StatusResponse);
228+
rpc Status(StatusRequest) returns (StatusResponse);
210229
// RPC to list all available images
211230
rpc ListImages(google.protobuf.Empty) returns (ImageListResponse);
212231

teepod/src/app.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::net::IpAddr;
1616
use std::path::{Path, PathBuf};
1717
use std::sync::{Arc, Mutex, MutexGuard};
1818
use supervisor_client::SupervisorClient;
19-
use teepod_rpc::{self as pb, GpuInfo, VmConfiguration};
19+
use teepod_rpc::{self as pb, GpuInfo, StatusRequest, StatusResponse, VmConfiguration};
2020
use tracing::{error, info};
2121

2222
pub use image::{Image, ImageInfo};
@@ -122,6 +122,7 @@ impl App {
122122
&self,
123123
work_dir: impl AsRef<Path>,
124124
cids_assigned: &HashMap<String, u32>,
125+
auto_start: bool,
125126
) -> Result<()> {
126127
let vm_work_dir = VmWorkDir::new(work_dir.as_ref());
127128
let manifest = vm_work_dir.manifest().context("Failed to read manifest")?;
@@ -160,6 +161,9 @@ impl App {
160161
}
161162
teapot.add(VmState::new(vm_config));
162163
};
164+
if auto_start && vm_work_dir.started().unwrap_or_default() {
165+
self.start_vm(&vm_id).await?;
166+
}
163167
Ok(())
164168
}
165169

@@ -285,7 +289,7 @@ impl App {
285289
let entry = entry.context("Failed to read directory entry")?;
286290
let vm_path = entry.path();
287291
if vm_path.is_dir() {
288-
if let Err(err) = self.load_vm(vm_path, &occupied_cids).await {
292+
if let Err(err) = self.load_vm(vm_path, &occupied_cids, true).await {
289293
error!("Failed to load VM: {err:?}");
290294
}
291295
}
@@ -302,7 +306,7 @@ impl App {
302306
Ok(())
303307
}
304308

305-
pub async fn list_vms(&self) -> Result<Vec<pb::VmInfo>> {
309+
pub async fn list_vms(&self, request: StatusRequest) -> Result<StatusResponse> {
306310
let vms = self
307311
.supervisor
308312
.list()
@@ -315,19 +319,43 @@ impl App {
315319
let mut infos = self
316320
.lock()
317321
.iter_vms()
322+
.filter(|vm| {
323+
if !request.ids.is_empty() && !request.ids.contains(&vm.config.manifest.id) {
324+
return false;
325+
}
326+
if request.keyword.is_empty() {
327+
true
328+
} else {
329+
vm.config.manifest.name.contains(&request.keyword)
330+
|| vm.config.manifest.id.contains(&request.keyword)
331+
|| vm.config.manifest.app_id.contains(&request.keyword)
332+
|| vm.config.manifest.image.contains(&request.keyword)
333+
}
334+
})
335+
.cloned()
336+
.collect::<Vec<_>>();
337+
infos.sort_by(|a, b| {
338+
a.config
339+
.manifest
340+
.created_at_ms
341+
.cmp(&b.config.manifest.created_at_ms)
342+
});
343+
344+
let total = infos.len() as u32;
345+
let vms = paginate(infos, request.page, request.page_size)
318346
.map(|vm| {
319347
vm.merged_info(
320348
vms.get(&vm.config.manifest.id),
321349
&self.work_dir(&vm.config.manifest.id),
322350
)
323351
})
352+
.map(|info| info.to_pb(&self.config.gateway))
324353
.collect::<Vec<_>>();
325-
326-
infos.sort_by(|a, b| a.manifest.created_at_ms.cmp(&b.manifest.created_at_ms));
327-
let gw = &self.config.gateway;
328-
329-
let lst = infos.into_iter().map(|info| info.to_pb(gw)).collect();
330-
Ok(lst)
354+
Ok(StatusResponse {
355+
vms,
356+
port_mapping_enabled: self.config.cvm.port_mapping.enabled,
357+
total,
358+
})
331359
}
332360

333361
pub fn list_images(&self) -> Result<Vec<(String, ImageInfo)>> {
@@ -579,6 +607,21 @@ impl App {
579607
}
580608
}
581609

610+
fn paginate<T>(items: Vec<T>, page: u32, page_size: u32) -> impl Iterator<Item = T> {
611+
let skip;
612+
let take;
613+
if page == 0 || page_size == 0 {
614+
skip = 0;
615+
take = items.len();
616+
} else {
617+
let page = page - 1;
618+
let start = page * page_size;
619+
skip = start as usize;
620+
take = page_size as usize;
621+
}
622+
items.into_iter().skip(skip).take(take)
623+
}
624+
582625
#[derive(Clone)]
583626
pub struct VmState {
584627
pub(crate) config: Arc<VmConfig>,

0 commit comments

Comments
 (0)