@@ -1611,8 +1611,7 @@ pub async fn sandbox_create(
16111611 gateway_name : & str ,
16121612 upload : Option < & ( String , Option < String > , bool ) > ,
16131613 keep : bool ,
1614- gpu : bool ,
1615- gpu_device : Option < & str > ,
1614+ resource_requirements : Option < ResourceRequirements > ,
16161615 cpu : Option < & str > ,
16171616 memory : Option < & str > ,
16181617 editor : Option < Editor > ,
@@ -1665,9 +1664,13 @@ pub async fn sandbox_create(
16651664 }
16661665 None => None ,
16671666 } ;
1668- let requested_gpu = gpu
1669- || gpu_device. is_some_and ( |device_id| !device_id. is_empty ( ) )
1670- || image. as_deref ( ) . is_some_and ( image_requests_gpu) ;
1667+ let resource_requirements = resource_requirements. or_else ( || {
1668+ resource_requirements_from_cli ( image. as_deref ( ) . is_some_and ( image_requests_gpu) , None , None )
1669+ } ) ;
1670+ let requested_gpu = resource_requirements
1671+ . as_ref ( )
1672+ . and_then ( |requirements| requirements. gpu . as_ref ( ) )
1673+ . is_some ( ) ;
16711674
16721675 let inferred_types: Vec < String > = inferred_provider_type ( command) . into_iter ( ) . collect ( ) ;
16731676 let configured_providers = ensure_required_providers (
@@ -1693,7 +1696,7 @@ pub async fn sandbox_create(
16931696
16941697 let request = CreateSandboxRequest {
16951698 spec : Some ( SandboxSpec {
1696- placement : resource_requirements_from_cli ( requested_gpu , gpu_device ) ,
1699+ resource_requirements ,
16971700 policy,
16981701 providers : configured_providers,
16991702 template,
@@ -2083,16 +2086,25 @@ pub async fn sandbox_create(
20832086 }
20842087}
20852088
2086- fn resource_requirements_from_cli (
2089+ pub fn resource_requirements_from_cli (
20872090 requested_gpu : bool ,
20882091 gpu_device : Option < & str > ,
2092+ gpu_count : Option < u32 > ,
20892093) -> Option < ResourceRequirements > {
2094+ let requested_gpu = requested_gpu
2095+ || gpu_device. is_some_and ( |device_id| !device_id. is_empty ( ) )
2096+ || gpu_count. is_some ( ) ;
20902097 requested_gpu. then ( || ResourceRequirements {
20912098 gpu : Some ( GpuSpec {
2092- device_ids : gpu_device
2093- . filter ( |device_id| !device_id. is_empty ( ) )
2094- . map ( |device_id| vec ! [ device_id. to_string( ) ] )
2095- . unwrap_or_default ( ) ,
2099+ device_ids : if gpu_count. is_none ( ) {
2100+ gpu_device
2101+ . filter ( |device_id| !device_id. is_empty ( ) )
2102+ . map ( |device_id| vec ! [ device_id. to_string( ) ] )
2103+ . unwrap_or_default ( )
2104+ } else {
2105+ Vec :: new ( )
2106+ } ,
2107+ count : gpu_count,
20962108 } ) ,
20972109 } )
20982110}
@@ -6296,7 +6308,7 @@ mod tests {
62966308 parse_credential_pairs, plaintext_gateway_is_remote, progress_step_from_metadata,
62976309 provisioning_timeout_message, ready_false_condition_message, resolve_from,
62986310 resource_requirements_from_cli, sandbox_should_persist, service_expose_status_error,
6299- service_url_for_gateway, source_requests_gpu ,
6311+ service_url_for_gateway,
63006312 } ;
63016313 use crate :: TEST_ENV_LOCK ;
63026314 use hyper:: StatusCode ;
@@ -6644,32 +6656,54 @@ mod tests {
66446656 }
66456657
66466658 #[ test]
6647- fn source_requests_gpu_detects_known_community_gpu_name ( ) {
6648- assert ! ( source_requests_gpu ( "nvidia-gpu" ) ) ;
6649- assert ! ( !source_requests_gpu ( "base" ) ) ;
6659+ fn image_requests_gpu_detects_known_community_gpu_name ( ) {
6660+ assert ! ( image_requests_gpu ( "nvidia-gpu" ) ) ;
6661+ assert ! ( !image_requests_gpu ( "base" ) ) ;
66506662 }
66516663
66526664 #[ test]
66536665 fn resource_requirements_from_cli_uses_presence_with_empty_device_ids_for_default_gpu ( ) {
6654- let request = resource_requirements_from_cli ( true , None )
6666+ let request = resource_requirements_from_cli ( true , None , None )
66556667 . expect ( "resource requirements should be present" ) ;
66566668 let gpu = request. gpu . expect ( "gpu request should be present" ) ;
66576669
66586670 assert ! ( gpu. device_ids. is_empty( ) ) ;
6671+ assert_eq ! ( gpu. count, None ) ;
66596672 }
66606673
66616674 #[ test]
66626675 fn resource_requirements_from_cli_maps_gpu_device_to_one_device_id ( ) {
6663- let request = resource_requirements_from_cli ( true , Some ( "0000:2d:00.0" ) )
6676+ let request = resource_requirements_from_cli ( true , Some ( "0000:2d:00.0" ) , None )
6677+ . expect ( "resource requirements should be present" ) ;
6678+ let gpu = request. gpu . expect ( "gpu request should be present" ) ;
6679+
6680+ assert_eq ! ( gpu. device_ids, vec![ "0000:2d:00.0" ] ) ;
6681+ assert_eq ! ( gpu. count, None ) ;
6682+ }
6683+
6684+ #[ test]
6685+ fn resource_requirements_from_cli_maps_gpu_device_without_explicit_gpu_flag ( ) {
6686+ let request = resource_requirements_from_cli ( false , Some ( "0000:2d:00.0" ) , None )
66646687 . expect ( "resource requirements should be present" ) ;
66656688 let gpu = request. gpu . expect ( "gpu request should be present" ) ;
66666689
66676690 assert_eq ! ( gpu. device_ids, vec![ "0000:2d:00.0" ] ) ;
6691+ assert_eq ! ( gpu. count, None ) ;
6692+ }
6693+
6694+ #[ test]
6695+ fn resource_requirements_from_cli_maps_gpu_count ( ) {
6696+ let request = resource_requirements_from_cli ( false , None , Some ( 2 ) )
6697+ . expect ( "resource requirements should be present" ) ;
6698+ let gpu = request. gpu . expect ( "gpu request should be present" ) ;
6699+
6700+ assert ! ( gpu. device_ids. is_empty( ) ) ;
6701+ assert_eq ! ( gpu. count, Some ( 2 ) ) ;
66686702 }
66696703
66706704 #[ test]
6671- fn resource_requirements_from_cli_omits_placement_when_not_requested ( ) {
6672- assert ! ( resource_requirements_from_cli( false , Some ( "0" ) ) . is_none( ) ) ;
6705+ fn resource_requirements_from_cli_omits_requirements_when_not_requested ( ) {
6706+ assert ! ( resource_requirements_from_cli( false , None , None ) . is_none( ) ) ;
66736707 }
66746708
66756709 #[ test]
0 commit comments