@@ -248,6 +248,10 @@ pub(crate) struct InstanceAllocationRequest {
248248 pub ( crate ) allow_unhealthy_machine : bool ,
249249}
250250
251+ fn normalize_created_power_profile ( power_profile : Option < String > ) -> Option < String > {
252+ power_profile. filter ( |profile| !profile. is_empty ( ) )
253+ }
254+
251255impl TryFrom < rpc:: InstanceAllocationRequest > for InstanceAllocationRequest {
252256 type Error = CarbideError ;
253257
@@ -268,7 +272,10 @@ impl TryFrom<rpc::InstanceAllocationRequest> for InstanceAllocationRequest {
268272 . config
269273 . ok_or ( RpcDataConversionError :: MissingArgument ( "config" ) ) ?;
270274
271- let config = InstanceConfig :: try_from ( config) ?;
275+ let mut config = InstanceConfig :: try_from ( config) ?;
276+ // Empty power-policy values are clear sentinels only on update. During
277+ // creation there is no association to clear, so persist them as unset.
278+ config. power_profile = normalize_created_power_profile ( config. power_profile ) ;
272279
273280 // If the Tenant provides an instance ID use this one
274281 // Otherwise create a random ID
@@ -2381,6 +2388,22 @@ mod tests {
23812388
23822389 use super :: * ;
23832390
2391+ #[ test]
2392+ fn instance_creation_power_profile_semantics ( ) {
2393+ value_scenarios ! (
2394+ run = |power_profile| normalize_created_power_profile( power_profile) ;
2395+ "non-empty profile is preserved" {
2396+ Some ( "balanced" . to_string( ) ) => Some ( "balanced" . to_string( ) ) ,
2397+ }
2398+ "empty profile is treated as unset" {
2399+ Some ( String :: new( ) ) => None ,
2400+ }
2401+ "omitted profile remains unset" {
2402+ None => None ,
2403+ }
2404+ ) ;
2405+ }
2406+
23842407 #[ test]
23852408 fn build_requested_linknet_prefix_accepts_host_end_rejects_dpu_end ( ) {
23862409 // The host must take the odd (::1) end of the linknet; the even end is the
0 commit comments