@@ -30,7 +30,6 @@ use illumos_utils::link::VnicAllocator;
30
30
use illumos_utils:: opte:: { DhcpCfg , PortManager } ;
31
31
use illumos_utils:: running_zone:: { RunningZone , ZoneBuilderFactory } ;
32
32
use illumos_utils:: svc:: wait_for_service;
33
- use illumos_utils:: zone:: Zones ;
34
33
use illumos_utils:: zone:: PROPOLIS_ZONE_PREFIX ;
35
34
use nexus_client:: types:: HandleInstancePutResultResult ;
36
35
use omicron_common:: address:: NEXUS_INTERNAL_PORT ;
@@ -53,6 +52,11 @@ use std::sync::Arc;
53
52
use tokio:: sync:: { mpsc, oneshot} ;
54
53
use uuid:: Uuid ;
55
54
55
+ #[ cfg( test) ]
56
+ use illumos_utils:: zone:: MockZones as Zones ;
57
+ #[ cfg( not( test) ) ]
58
+ use illumos_utils:: zone:: Zones ;
59
+
56
60
// The depth of the request queue for the instance.
57
61
const QUEUE_SIZE : usize = 32 ;
58
62
@@ -1233,7 +1237,8 @@ impl InstanceRunner {
1233
1237
state : crate :: params:: InstanceStateRequested ,
1234
1238
) -> Result < SledInstanceState , Error > {
1235
1239
use propolis_client:: types:: InstanceStateRequested as PropolisRequest ;
1236
- let ( propolis_state, next_published, propolis_ensure_res) = match state {
1240
+ let ( propolis_state, next_published, propolis_ensure_res) = match state
1241
+ {
1237
1242
InstanceStateRequested :: MigrationTarget ( migration_params) => {
1238
1243
let res = self . propolis_ensure ( Some ( migration_params) ) . await ;
1239
1244
( None , None , Some ( res) )
@@ -1278,14 +1283,16 @@ impl InstanceRunner {
1278
1283
}
1279
1284
if let Some ( res) = propolis_ensure_res {
1280
1285
match res {
1281
- Ok ( ( ) ) => match self . nexus_client
1286
+ Ok ( ( ) ) => match self
1287
+ . nexus_client
1282
1288
. client ( )
1283
1289
. cpapi_handle_instance_put_success (
1284
1290
self . id ( ) ,
1285
1291
& self . current_state ( ) . await . into ( ) ,
1286
1292
)
1287
1293
. await ?
1288
- . into_inner ( ) {
1294
+ . into_inner ( )
1295
+ {
1289
1296
HandleInstancePutResultResult :: Ok => { }
1290
1297
HandleInstancePutResultResult :: TimedOut { generation } => {
1291
1298
error ! (
@@ -1296,15 +1303,17 @@ impl InstanceRunner {
1296
1303
) ;
1297
1304
self . terminate ( ) . await ;
1298
1305
}
1299
- }
1300
- Err ( instance_put_error) => match self . nexus_client
1306
+ } ,
1307
+ Err ( instance_put_error) => match self
1308
+ . nexus_client
1301
1309
. client ( )
1302
1310
. cpapi_handle_instance_put_failure (
1303
1311
self . id ( ) ,
1304
1312
& instance_put_error. to_string ( ) ,
1305
1313
)
1306
1314
. await ?
1307
- . into_inner ( ) {
1315
+ . into_inner ( )
1316
+ {
1308
1317
HandleInstancePutResultResult :: Ok => { }
1309
1318
HandleInstancePutResultResult :: TimedOut { generation } => {
1310
1319
error ! (
@@ -1315,7 +1324,7 @@ impl InstanceRunner {
1315
1324
) ;
1316
1325
self . terminate ( ) . await ;
1317
1326
}
1318
- }
1327
+ } ,
1319
1328
}
1320
1329
}
1321
1330
Ok ( self . state . sled_instance_state ( ) )
@@ -1642,11 +1651,11 @@ mod tests {
1642
1651
"couldn't send SledInstanceState to test driver" ,
1643
1652
)
1644
1653
} ) ?;
1645
- self . nexus_disposition
1646
- . borrow ( )
1647
- . as_ref ( )
1648
- . cloned ( )
1649
- . ok_or ( omicron_common :: api :: external :: Error :: unavail ( "did not set nexus_disposition in FakeNexusServer" ) )
1654
+ self . nexus_disposition . borrow ( ) . as_ref ( ) . cloned ( ) . ok_or (
1655
+ omicron_common :: api :: external :: Error :: unavail (
1656
+ "did not set nexus_disposition in FakeNexusServer" ,
1657
+ ) ,
1658
+ )
1650
1659
}
1651
1660
1652
1661
fn cpapi_handle_instance_put_failure (
@@ -1664,11 +1673,11 @@ mod tests {
1664
1673
"couldn't send error to test driver" ,
1665
1674
)
1666
1675
} ) ?;
1667
- self . nexus_disposition
1668
- . borrow ( )
1669
- . as_ref ( )
1670
- . cloned ( )
1671
- . ok_or ( omicron_common :: api :: external :: Error :: unavail ( "did not set nexus_disposition in FakeNexusServer" ) )
1676
+ self . nexus_disposition . borrow ( ) . as_ref ( ) . cloned ( ) . ok_or (
1677
+ omicron_common :: api :: external :: Error :: unavail (
1678
+ "did not set nexus_disposition in FakeNexusServer" ,
1679
+ ) ,
1680
+ )
1672
1681
}
1673
1682
}
1674
1683
@@ -1961,10 +1970,15 @@ mod tests {
1961
1970
let _mock_vnic_contexts = mock_vnic_contexts ( ) ;
1962
1971
let _mock_zone_contexts = mock_zone_contexts ( ) ;
1963
1972
1964
- let FakeNexusParts { nexus_client, nexus_server, mut state_rx, disp_tx } =
1965
- FakeNexusParts :: new ( & logctx) ;
1973
+ let FakeNexusParts {
1974
+ nexus_client,
1975
+ nexus_server,
1976
+ mut state_rx,
1977
+ disp_tx,
1978
+ } = FakeNexusParts :: new ( & logctx) ;
1966
1979
1967
- disp_tx. send ( Some ( HandleInstancePutResultResult :: Ok ) )
1980
+ disp_tx
1981
+ . send ( Some ( HandleInstancePutResultResult :: Ok ) )
1968
1982
. expect ( "couldn't send nexus_disposition" ) ;
1969
1983
1970
1984
let ( _dns_server, resolver, _dns_config_dir) =
@@ -2031,7 +2045,8 @@ mod tests {
2031
2045
let FakeNexusParts { nexus_client, nexus_server, state_rx, disp_tx } =
2032
2046
FakeNexusParts :: new ( & logctx) ;
2033
2047
2034
- disp_tx. send ( Some ( HandleInstancePutResultResult :: Ok ) )
2048
+ disp_tx
2049
+ . send ( Some ( HandleInstancePutResultResult :: Ok ) )
2035
2050
. expect ( "couldn't send nexus_disposition" ) ;
2036
2051
2037
2052
let ( _dns_server, resolver, _dns_config_dir) =
@@ -2094,18 +2109,15 @@ mod tests {
2094
2109
Ok ( ( ) )
2095
2110
} ) ;
2096
2111
let wait_ctx = illumos_utils:: svc:: wait_for_service_context ( ) ;
2097
- wait_ctx. expect ( ) . times ( ..) . returning ( |_, _, _| Ok ( ( ) ) ) ;
2112
+ wait_ctx. expect ( ) . times ( 1 ..) . returning ( |_, _, _| Ok ( ( ) ) ) ;
2098
2113
let zone_id_ctx = MockZones :: id_context ( ) ;
2099
- zone_id_ctx. expect ( ) . times ( ..) . returning ( |_| Ok ( Some ( 1 ) ) ) ;
2100
- let halt_rm_ctx = MockZones :: halt_and_remove_logged_context ( ) ;
2101
- halt_rm_ctx. expect ( ) . times ( ..) . returning ( |_, _| Ok ( ( ) ) ) ;
2114
+ zone_id_ctx. expect ( ) . times ( 1 ..) . returning ( |_| Ok ( Some ( 1 ) ) ) ;
2102
2115
2103
2116
let FakeNexusParts { nexus_client, nexus_server, state_rx, disp_tx } =
2104
2117
FakeNexusParts :: new ( & logctx) ;
2105
2118
2106
- disp_tx. send ( Some ( HandleInstancePutResultResult :: TimedOut {
2107
- generation : Generation ( 5 )
2108
- } ) )
2119
+ disp_tx
2120
+ . send ( Some ( HandleInstancePutResultResult :: Ok ) )
2109
2121
. expect ( "couldn't send nexus_disposition" ) ;
2110
2122
2111
2123
let ( _dns_server, resolver, _dns_config_dir) =
@@ -2152,16 +2164,112 @@ mod tests {
2152
2164
logctx. cleanup_successful ( ) ;
2153
2165
}
2154
2166
2167
+ // tests that we terminate the instance if nexus tells us it timed us out.
2155
2168
#[ tokio:: test]
2156
- async fn test_instance_manager_creation_nexus_timeout ( ) {
2169
+ async fn test_instance_create_timeout_from_nexus ( ) {
2157
2170
let logctx = omicron_test_utils:: dev:: test_setup_log (
2158
- "test_instance_manager_creation_nexus_timeout " ,
2171
+ "test_instance_create_timeout_from_nexus " ,
2159
2172
) ;
2160
2173
2174
+ let ( propolis_server, _propolis_client) =
2175
+ propolis_mock_server ( & logctx. log ) ;
2176
+ let propolis_addr = propolis_server. local_addr ( ) ;
2177
+
2178
+ // automock'd things used during this test
2179
+ let _mock_vnic_contexts = mock_vnic_contexts ( ) ;
2180
+ let _mock_zone_contexts = mock_zone_contexts ( ) ;
2181
+ let halt_rm_ctx = MockZones :: halt_and_remove_logged_context ( ) ;
2182
+ halt_rm_ctx. expect ( ) . times ( 1 ..) . returning ( |_, _| Ok ( ( ) ) ) ;
2183
+
2184
+ let FakeNexusParts {
2185
+ nexus_client,
2186
+ nexus_server,
2187
+ mut state_rx,
2188
+ disp_tx,
2189
+ } = FakeNexusParts :: new ( & logctx) ;
2190
+
2191
+ disp_tx
2192
+ . send ( Some ( HandleInstancePutResultResult :: TimedOut {
2193
+ generation : Generation :: from ( 5 ) ,
2194
+ } ) )
2195
+ . expect ( "couldn't send nexus_disposition" ) ;
2196
+
2197
+ let ( _dns_server, resolver, _dns_config_dir) =
2198
+ timeout ( TIMEOUT_DURATION , dns_server ( & logctx, & nexus_server) )
2199
+ . await
2200
+ . expect ( "timed out making DNS server and Resolver" ) ;
2201
+
2202
+ let nexus_client_with_resolver =
2203
+ NexusClientWithResolver :: new_with_client ( nexus_client, resolver) ;
2204
+
2161
2205
let storage_handle = fake_storage_manager_with_u2 ( ) . await ;
2162
2206
2163
- let FakeNexusParts { nexus_client, nexus_server, state_rx, disp_tx } =
2164
- FakeNexusParts :: new ( & logctx) ;
2207
+ let inst = timeout (
2208
+ TIMEOUT_DURATION ,
2209
+ instance_struct (
2210
+ & logctx,
2211
+ propolis_addr,
2212
+ nexus_client_with_resolver,
2213
+ storage_handle,
2214
+ ) ,
2215
+ )
2216
+ . await
2217
+ . expect ( "timed out creating Instance struct" ) ;
2218
+
2219
+ let ( put_tx, put_rx) = oneshot:: channel ( ) ;
2220
+
2221
+ inst. put_state ( put_tx, InstanceStateRequested :: Running )
2222
+ . await
2223
+ . expect ( "failed to send Instance::put_state" ) ;
2224
+
2225
+ timeout ( TIMEOUT_DURATION , put_rx)
2226
+ . await
2227
+ . expect ( "timed out waiting for Instance::put_state result" )
2228
+ . expect ( "failed to receive Instance::put_state result" )
2229
+ . expect ( "Instance::put_state failed" ) ;
2230
+
2231
+ timeout (
2232
+ TIMEOUT_DURATION ,
2233
+ state_rx. wait_for ( |maybe_state| match maybe_state {
2234
+ ReceivedInstanceState :: InstancePut ( sled_inst_state) => {
2235
+ sled_inst_state. vmm_state . state == InstanceState :: Destroyed
2236
+ }
2237
+ _ => false ,
2238
+ } ) ,
2239
+ )
2240
+ . await
2241
+ . expect ( "timed out waiting for InstanceState::Destroyed in FakeNexus" )
2242
+ . expect ( "failed to receive FakeNexus' InstanceState" ) ;
2243
+
2244
+ logctx. cleanup_successful ( ) ;
2245
+ }
2246
+
2247
+ #[ tokio:: test]
2248
+ async fn test_instance_manager_creation_timeout_from_nexus ( ) {
2249
+ let logctx = omicron_test_utils:: dev:: test_setup_log (
2250
+ "test_instance_manager_creation_timeout_from_nexus" ,
2251
+ ) ;
2252
+
2253
+ // automock'd things used during this test
2254
+ let _mock_vnic_contexts = mock_vnic_contexts ( ) ;
2255
+ let _mock_zone_contexts = mock_zone_contexts ( ) ;
2256
+ let halt_rm_ctx = MockZones :: halt_and_remove_logged_context ( ) ;
2257
+ halt_rm_ctx. expect ( ) . times ( 1 ..) . returning ( |_, _| Ok ( ( ) ) ) ;
2258
+
2259
+ let storage_handle = fake_storage_manager_with_u2 ( ) . await ;
2260
+
2261
+ let FakeNexusParts {
2262
+ nexus_client,
2263
+ nexus_server,
2264
+ mut state_rx,
2265
+ disp_tx,
2266
+ } = FakeNexusParts :: new ( & logctx) ;
2267
+
2268
+ disp_tx
2269
+ . send ( Some ( HandleInstancePutResultResult :: TimedOut {
2270
+ generation : Generation :: from ( 5 ) ,
2271
+ } ) )
2272
+ . expect ( "couldn't send nexus_disposition" ) ;
2165
2273
2166
2274
let ( _dns_server, resolver, _dns_config_dir) =
2167
2275
timeout ( TIMEOUT_DURATION , dns_server ( & logctx, & nexus_server) )
@@ -2201,10 +2309,6 @@ mod tests {
2201
2309
propolis_mock_server ( & logctx. log ) ;
2202
2310
let propolis_addr = propolis_server. local_addr ( ) ;
2203
2311
2204
- // automock'd things used during this test
2205
- let _mock_vnic_contexts = mock_vnic_contexts ( ) ;
2206
- let _mock_zone_contexts = mock_zone_contexts ( ) ;
2207
-
2208
2312
let instance_id = Uuid :: new_v4 ( ) ;
2209
2313
let propolis_id = Uuid :: new_v4 ( ) ;
2210
2314
let InstanceInitialState {
@@ -2225,7 +2329,22 @@ mod tests {
2225
2329
. await
2226
2330
. unwrap ( ) ;
2227
2331
2228
- todo ! ( ) ;
2332
+ mgr. ensure_state ( instance_id, InstanceStateRequested :: Running )
2333
+ . await
2334
+ . unwrap ( ) ;
2335
+
2336
+ timeout (
2337
+ TIMEOUT_DURATION ,
2338
+ state_rx. wait_for ( |maybe_state| match maybe_state {
2339
+ ReceivedInstanceState :: InstancePut ( sled_inst_state) => {
2340
+ sled_inst_state. vmm_state . state == InstanceState :: Destroyed
2341
+ }
2342
+ _ => false ,
2343
+ } ) ,
2344
+ )
2345
+ . await
2346
+ . expect ( "timed out waiting for InstanceState::Destroyed in FakeNexus" )
2347
+ . expect ( "failed to receive FakeNexus' InstanceState" ) ;
2229
2348
2230
2349
logctx. cleanup_successful ( ) ;
2231
2350
}
0 commit comments