5050
5151registered_nodes = []
5252util_threads = []
53+ tmp_dirs = []
5354last_assigned_port = int (random .random () * 16384 ) + 49152
5455pg_config_data = {}
56+ base_data_dir = None
5557
5658
5759class ClusterException (Exception ):
@@ -208,6 +210,7 @@ def __init__(self, name, port, base_dir=None, use_logging=False):
208210 self .port = port
209211 if base_dir is None :
210212 self .base_dir = tempfile .mkdtemp ()
213+ tmp_dirs .append (self .base_dir )
211214 else :
212215 self .base_dir = base_dir
213216 if not os .path .exists (self .logs_dir ):
@@ -246,6 +249,31 @@ def get_bin_path(self, filename):
246249 else :
247250 return os .path .join (pg_config .get ("BINDIR" ), filename )
248251
252+ def initdb (self , directory , initdb_params = []):
253+ initdb = self .get_bin_path ("initdb" )
254+ initdb_logfile = os .path .join (self .logs_dir , "initdb.log" )
255+
256+ with open (initdb_logfile , 'a' ) as file_out :
257+ ret = subprocess .call (
258+ [initdb , directory , "-N" ] + initdb_params ,
259+ stdout = file_out ,
260+ stderr = subprocess .STDOUT )
261+
262+ if ret :
263+ raise ClusterException ("Cluster initialization failed. You"
264+ " can find additional information at '%s'" % initdb_logfile )
265+
266+ def _setup_data_dir (self , data_dir ):
267+ global base_data_dir
268+
269+ if base_data_dir is None :
270+ base_data_dir = tempfile .mkdtemp ()
271+ tmp_dirs .append (base_data_dir )
272+ self .initdb (base_data_dir )
273+
274+ shutil .copytree (base_data_dir , data_dir )
275+
276+
249277 def init (self , allows_streaming = False , initdb_params = []):
250278 """ Performs initdb """
251279
@@ -258,19 +286,13 @@ def init(self, allows_streaming=False, initdb_params=[]):
258286 return self
259287
260288 # initialize cluster
261- os .makedirs (self .data_dir )
262- initdb = self .get_bin_path ("initdb" )
263- with open (os .path .join (self .logs_dir , "initdb.log" ), "a" ) as file_out :
264- ret = subprocess .call (
265- [initdb , self .data_dir , "-N" ] + initdb_params ,
266- stdout = file_out ,
267- stderr = subprocess .STDOUT
268- )
269- if ret :
270- raise ClusterException ("Cluster initialization failed" )
289+ if initdb_params :
290+ self .initdb (self .data_dir , initdb_params )
291+ else :
292+ self ._setup_data_dir (self .data_dir )
271293
272294 # add parameters to config file
273- with open (postgres_conf , "a " ) as conf :
295+ with open (postgres_conf , "w " ) as conf :
274296 conf .write (
275297 "fsync = off\n "
276298 "log_statement = all\n "
@@ -286,7 +308,6 @@ def init(self, allows_streaming=False, initdb_params=[]):
286308 "max_wal_senders = 5\n "
287309 "wal_keep_segments = 20\n "
288310 "max_wal_size = 128MB\n "
289- "shared_buffers = 1MB\n "
290311 "wal_log_hints = on\n "
291312 "hot_standby = on\n "
292313 "max_connections = 10\n " )
@@ -369,7 +390,9 @@ def pg_ctl(self, command, params={}, command_options=[]):
369390
370391 if res > 0 :
371392 with open (self .error_filename , "r" ) as errfile :
372- raise ClusterException (errfile .readlines ()[- 1 ])
393+ text = errfile .readlines ()[- 1 ]
394+ text += 'Logs at: %s' % self .logs_dir
395+ raise ClusterException (text )
373396
374397 def start (self , params = {}):
375398 """ Starts cluster """
@@ -434,7 +457,7 @@ def get_control_data(self):
434457 lines = subprocess .check_output (
435458 [pg_controldata ] + ["-D" , self .data_dir ],
436459 stderr = subprocess .STDOUT
437- ).splitlines ()
460+ ).decode ( "utf-8" ). splitlines ()
438461 except subprocess .CalledProcessError as e :
439462 raise PgcontroldataException (e .output , e .cmd )
440463
@@ -489,8 +512,7 @@ def cleanup(self):
489512 pass
490513
491514 # remove data directory
492- shutil .rmtree (self .data_dir )
493-
515+ shutil .rmtree (self .data_dir , ignore_errors = True )
494516 return self
495517
496518 def psql (self , dbname , query = None , filename = None , username = None ):
@@ -597,7 +619,7 @@ def backup(self, name):
597619 backup_path = os .path .join (self .base_dir , name )
598620 os .makedirs (backup_path )
599621 params = [pg_basebackup , "-D" , backup_path , "-p {}" .format (
600- self .port ), "-x " ]
622+ self .port ), "-X" , "fetch " ]
601623 with open (self .output_filename , "a" ) as file_out , \
602624 open (self .error_filename , "a" ) as file_err :
603625 ret = subprocess .call (
@@ -726,7 +748,16 @@ def clean_all():
726748 global registered_nodes
727749 for node in registered_nodes :
728750 node .cleanup ()
751+
752+ for cat in tmp_dirs :
753+ if os .path .exists ():
754+ shutil .rmtree (cat , ignore_errors = True )
755+
756+ if cat == base_data_dir :
757+ base_data_dir = None
758+
729759 registered_nodes = []
760+ tmp_dirs = []
730761
731762
732763def stop_all ():
0 commit comments