@@ -16,7 +16,7 @@ use std::net::IpAddr;
1616use std:: path:: { Path , PathBuf } ;
1717use std:: sync:: { Arc , Mutex , MutexGuard } ;
1818use supervisor_client:: SupervisorClient ;
19- use teepod_rpc:: { self as pb, GpuInfo , VmConfiguration } ;
19+ use teepod_rpc:: { self as pb, GpuInfo , StatusRequest , StatusResponse , VmConfiguration } ;
2020use tracing:: { error, info} ;
2121
2222pub 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 ) ]
583626pub struct VmState {
584627 pub ( crate ) config : Arc < VmConfig > ,
0 commit comments