44 */
55
66use std:: net:: Ipv4Addr ;
7+ use std:: path:: Path ;
78use std:: path:: PathBuf ;
89use std:: process:: Stdio ;
910use std:: time:: Duration ;
@@ -31,6 +32,11 @@ pub(crate) enum ScyllaCluster {
3132 tx : oneshot:: Sender < bool > ,
3233 } ,
3334 Stop ,
35+ Up {
36+ vs_uri : String ,
37+ conf : Option < Vec < u8 > > ,
38+ } ,
39+ Down ,
3440}
3541
3642pub ( crate ) trait ScyllaClusterExt {
@@ -45,6 +51,12 @@ pub(crate) trait ScyllaClusterExt {
4551
4652 /// Waits for the ScyllaDB cluster to be ready.
4753 async fn wait_for_ready ( & self ) -> bool ;
54+
55+ /// Starts a paused instance back again.
56+ async fn up ( & self , vs_uri : String , conf : Option < Vec < u8 > > ) ;
57+
58+ /// Pauses an instance
59+ async fn down ( & self ) ;
4860}
4961
5062impl ScyllaClusterExt for mpsc:: Sender < ScyllaCluster > {
@@ -81,6 +93,18 @@ impl ScyllaClusterExt for mpsc::Sender<ScyllaCluster> {
8193 rx. await
8294 . expect ( "ScyllaClusterExt::wait_for_ready: internal actor should send response" )
8395 }
96+
97+ async fn up ( & self , vs_uri : String , conf : Option < Vec < u8 > > ) {
98+ self . send ( ScyllaCluster :: Up { vs_uri, conf } )
99+ . await
100+ . expect ( "ScyllaClusterExt::up: internal actor should receive request" )
101+ }
102+
103+ async fn down ( & self ) {
104+ self . send ( ScyllaCluster :: Down )
105+ . await
106+ . expect ( "ScyllaClusterExt::down: internal actor should receive request" )
107+ }
84108}
85109
86110pub ( crate ) async fn new (
@@ -175,13 +199,26 @@ async fn process(msg: ScyllaCluster, state: &mut State) {
175199 tx. send ( wait_for_ready ( state) . await )
176200 . expect ( "process ScyllaCluster::WaitForReady: failed to send a response" ) ;
177201 }
202+
203+ ScyllaCluster :: Up { vs_uri, conf } => {
204+ up ( vs_uri, conf, state) . await ;
205+ }
206+
207+ ScyllaCluster :: Down => {
208+ down ( state) . await ;
209+ }
178210 }
179211}
180212
181- async fn start ( vs_uri : String , db_ip : Ipv4Addr , conf : Option < Vec < u8 > > , state : & mut State ) {
182- let workdir = TempDir :: new ( ) . expect ( "start: failed to create temporary directory for scylladb" ) ;
213+ async fn run_cluster (
214+ vs_uri : & String ,
215+ db_ip : & Ipv4Addr ,
216+ conf : & Option < Vec < u8 > > ,
217+ path : & Path ,
218+ state : & mut State ,
219+ ) {
183220 let conf = if let Some ( conf) = conf {
184- let conf_path = workdir . path ( ) . join ( "scylla.conf" ) ;
221+ let conf_path = path. join ( "scylla.conf" ) ;
185222 fs:: write ( & conf_path, conf)
186223 . await
187224 . expect ( "start: failed to write scylla config" ) ;
@@ -198,7 +235,7 @@ async fn start(vs_uri: String, db_ip: Ipv4Addr, conf: Option<Vec<u8>>, state: &m
198235 . arg ( "--options-file" )
199236 . arg ( & conf)
200237 . arg ( "--workdir" )
201- . arg ( workdir . path ( ) )
238+ . arg ( path)
202239 . arg ( "--listen-address" )
203240 . arg ( db_ip. to_string ( ) )
204241 . arg ( "--rpc-address" )
@@ -216,6 +253,11 @@ async fn start(vs_uri: String, db_ip: Ipv4Addr, conf: Option<Vec<u8>>, state: &m
216253 . spawn ( )
217254 . expect ( "start: failed to spawn scylladb" ) ,
218255 ) ;
256+ }
257+
258+ async fn start ( vs_uri : String , db_ip : Ipv4Addr , conf : Option < Vec < u8 > > , state : & mut State ) {
259+ let workdir = TempDir :: new ( ) . expect ( "start: failed to create temporary directory for scylladb" ) ;
260+ run_cluster ( & vs_uri, & db_ip, & conf, workdir. path ( ) , state) . await ;
219261 state. workdir = Some ( workdir) ;
220262 state. db_ip = Some ( db_ip) ;
221263}
@@ -236,6 +278,20 @@ async fn stop(state: &mut State) {
236278 state. db_ip = None ;
237279}
238280
281+ async fn down ( state : & mut State ) {
282+ let Some ( mut child) = state. child . take ( ) else {
283+ return ;
284+ } ;
285+ child
286+ . start_kill ( )
287+ . expect ( "stop: failed to send SIGTERM to scylladb process" ) ;
288+ child
289+ . wait ( )
290+ . await
291+ . expect ( "stop: failed to wait for scylladb process to exit" ) ;
292+ state. child = None ;
293+ }
294+
239295/// Waits for ScyllaDB to be ready by checking the nodetool status.
240296async fn wait_for_ready ( state : & State ) -> bool {
241297 let Some ( db_ip) = state. db_ip else {
@@ -262,3 +318,15 @@ async fn wait_for_ready(state: &State) -> bool {
262318 time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
263319 }
264320}
321+
322+ async fn up ( vs_uri : String , conf : Option < Vec < u8 > > , state : & mut State ) {
323+ let db_ip = state. db_ip . expect ( "State should have DB IP" ) ;
324+ let path = state
325+ . workdir
326+ . as_ref ( )
327+ . expect ( "State should have workdir" )
328+ . path ( )
329+ . to_path_buf ( ) ;
330+
331+ run_cluster ( & vs_uri, & db_ip, & conf, & path, state) . await ;
332+ }
0 commit comments