5555# You can lookup error message and cmdline in exception object attributes
5656class ProbackupException (Exception ):
5757def __init__ (self ,message ,cmd ):
58- # print message
59- # self.message = repr(message).strip("'")
6058self .message = message
6159self .cmd = cmd
6260#need that to make second raise
@@ -138,24 +136,31 @@ def __init__(self, *args, **kwargs):
138136
139137self .helpers_path = os .path .dirname (os .path .realpath (__file__ ))
140138self .dir_path = os .path .abspath (os .path .join (self .helpers_path ,os .pardir ))
139+ self .tmp_path = os .path .abspath (os .path .join (self .dir_path ,'tmp_dirs' ))
141140try :
142- os .makedirs (os .path .join (self .dir_path ," tmp_dirs" ))
141+ os .makedirs (os .path .join (self .dir_path ,' tmp_dirs' ))
143142except :
144143pass
145144self .probackup_path = os .path .abspath (os .path .join (
146- self .dir_path ,
147- "../pg_probackup"
148- ))
145+ self .dir_path ,"../pg_probackup" ))
149146
150147def arcwal_dir (self ,node ):
151148return "%s/backup/wal" % node .base_dir
152149
153- def backup_dir (self ,node ):
154- return os .path .abspath ("%s/backup" % node .base_dir )
150+ def backup_dir (self ,node = None ,path = None ):
151+ if node :
152+ return os .path .abspath ("{0}/backup" .format (node .base_dir ))
153+ if path :
154+ return
155155
156- def make_simple_node (self ,base_dir = None ,set_replication = False ,
157- set_archiving = False ,initdb_params = [],pg_options = {}):
158- real_base_dir = os .path .join (self .dir_path ,base_dir )
156+ def make_simple_node (
157+ self ,
158+ base_dir = None ,
159+ set_replication = False ,
160+ initdb_params = [],
161+ pg_options = {}):
162+
163+ real_base_dir = os .path .join (self .tmp_path ,base_dir )
159164shutil .rmtree (real_base_dir ,ignore_errors = True )
160165
161166node = get_new_node ('test' ,base_dir = real_base_dir )
@@ -173,9 +178,6 @@ def make_simple_node(self, base_dir=None, set_replication=False,
173178# Allow replication in pg_hba.conf
174179if set_replication :
175180node .set_replication_conf ()
176- # Setup archiving for node
177- if set_archiving :
178- self .set_archiving_conf (node ,self .arcwal_dir (node ))
179181return node
180182
181183def create_tblspace_in_node (self ,node ,tblspc_name ,cfs = False ):
@@ -301,6 +303,7 @@ def check_ptrack_clean(self, idx_dict, size):
301303def run_pb (self ,command ,async = False ):
302304try :
303305self .cmd = [' ' .join (map (str ,[self .probackup_path ]+ command ))]
306+ print self .cmd
304307if async is True :
305308return subprocess .Popen (
306309 [self .probackup_path ]+ command ,
@@ -319,44 +322,55 @@ def run_pb(self, command, async=False):
319322for line in self .output .splitlines ():
320323if 'INFO: Backup' and 'completed' in line :
321324return line .split ()[2 ]
322- # backup_id = line.split()[2]
323- # return {'cmd': cmd, 'output': output, 'backup_id': backup_id}
324325else :
325326return self .output
326- # return {'cmd': cmd, 'output': output}
327327except subprocess .CalledProcessError as e :
328- raise ProbackupException (e .output ,e .cmd )
328+ raise ProbackupException (e .output ,self .cmd )
329329
330- def init_pb (self ,node ):
330+ def init_pb (self ,backup_dir ):
331331
332332return self .run_pb ([
333333"init" ,
334- "-B" ,self .backup_dir (node ),
334+ "-B" ,backup_dir
335+ ])
336+
337+ def add_instance (self ,backup_dir ,instance ,node ):
338+
339+ return self .run_pb ([
340+ "add-instance" ,
341+ "--instance={0}" .format (instance ),
342+ "-B" ,backup_dir ,
343+ "-D" ,node .data_dir
344+ ])
345+
346+ def del_instance (self ,backup_dir ,instance ,node ):
347+
348+ return self .run_pb ([
349+ "del-instance" ,
350+ "--instance={0}" .format (instance ),
351+ "-B" ,backup_dir ,
335352"-D" ,node .data_dir
336353 ])
337354
338355def clean_pb (self ,node ):
339356shutil .rmtree (self .backup_dir (node ),ignore_errors = True )
340357
341- def backup_pb (self ,node = None ,data_dir = None ,backup_dir = None ,backup_type = "full" ,options = [],async = False ):
342- if data_dir is None :
343- data_dir = node .data_dir
344- if backup_dir is None :
345- backup_dir = self .backup_dir (node )
358+ def backup_node (self ,backup_dir ,instance ,node ,backup_type = "full" ,options = [],async = False ):
346359
347360cmd_list = [
348361"backup" ,
349362"-B" ,backup_dir ,
350- "-D" ,data_dir ,
363+ "-D" ,node . data_dir ,
351364"-p" ,"%i" % node .port ,
352- "-d" ,"postgres"
365+ "-d" ,"postgres" ,
366+ "--instance={0}" .format (instance )
353367 ]
354368if backup_type :
355369cmd_list += ["-b" ,backup_type ]
356370
357371return self .run_pb (cmd_list + options ,async )
358372
359- def restore_pb (self ,node = None , backup_dir = None ,data_dir = None ,id = None ,options = []):
373+ def restore_node (self ,backup_dir , instance ,data_dir = None ,id = None ,options = []):
360374if data_dir is None :
361375data_dir = node .data_dir
362376if backup_dir is None :
@@ -365,30 +379,35 @@ def restore_pb(self, node=None, backup_dir=None, data_dir=None, id=None, options
365379cmd_list = [
366380"restore" ,
367381"-B" ,backup_dir ,
368- "-D" ,data_dir
382+ "-D" ,data_dir ,
383+ "--instance={0}" .format (instance )
369384 ]
370385if id :
371386cmd_list += ["-i" ,id ]
372387
373388return self .run_pb (cmd_list + options )
374389
375- def show_pb (self ,node ,id = None ,options = [],as_text = False ):
390+ def show_pb (self ,backup_dir ,instance = None ,backup_id = None ,options = [],as_text = False ):
391+
376392backup_list = []
377393specific_record = {}
378394cmd_list = [
379395"show" ,
380- "-B" ,self . backup_dir ( node ) ,
396+ "-B" ,backup_dir ,
381397 ]
382- if id :
383- cmd_list += ["-i" ,id ]
398+ if instance :
399+ cmd_list += ["--instance={0}" .format (instance )]
400+
401+ if backup_id :
402+ cmd_list += ["-i" ,backup_id ]
384403
385404if as_text :
386405# You should print it when calling as_text=true
387406return self .run_pb (cmd_list + options )
388407
389408# get show result as list of lines
390409show_splitted = self .run_pb (cmd_list + options ).splitlines ()
391- if id is None :
410+ if instance is not None and backup_id is None :
392411# cut header(ID, Mode, etc) from show as single string
393412header = show_splitted [1 :2 ][0 ]
394413# cut backup records from show as single list with string for every backup record
@@ -430,36 +449,40 @@ def show_pb(self, node, id=None, options=[], as_text=False):
430449specific_record [name .strip ()]= var
431450return specific_record
432451
433- def validate_pb (self ,node ,id = None ,options = []):
452+ def validate_pb (self ,backup_dir ,instance = None ,id = None ,options = []):
453+
434454cmd_list = [
435455"validate" ,
436- "-B" ,self . backup_dir ( node ) ,
456+ "-B" ,backup_dir ,
437457 ]
458+ if instance :
459+ cmd_list += ["--instance={0}" .format (instance )]
438460if id :
439461cmd_list += ["-i" ,id ]
440462
441- # print(cmd_list)
442463return self .run_pb (cmd_list + options )
443464
444- def delete_pb (self ,node ,id = None ,options = []):
465+ def delete_pb (self ,backup_dir , instance = None ,id = None ,options = []):
445466cmd_list = [
446467"delete" ,
447468"-B" ,self .backup_dir (node ),
448469 ]
470+ if instance :
471+ cmd_list += ["--instance={0}" .format (instance )]
449472if id :
450473cmd_list += ["-i" ,id ]
451474
452475# print(cmd_list)
453476return self .run_pb (cmd_list + options )
454477
455- def delete_expired (self ,node ,options = []):
478+ def delete_expired (self ,backup_dir , instance = None ,options = []):
456479cmd_list = [
457480"delete" ,"--expired" ,
458481"-B" ,self .backup_dir (node ),
459482 ]
460483return self .run_pb (cmd_list + options )
461484
462- def show_config (self ,node ):
485+ def show_config (self ,backup_dir , instance = None ):
463486out_dict = {}
464487cmd_list = [
465488"show-config" ,
@@ -484,9 +507,7 @@ def get_recovery_conf(self, node):
484507out_dict [key .strip ()]= value .strip (" '" ).replace ("'\n " ,"" )
485508return out_dict
486509
487- def set_archiving_conf (self ,node ,archive_dir = False ,replica = False ):
488- if not archive_dir :
489- archive_dir = self .arcwal_dir (node )
510+ def set_archiving (self ,backup_dir ,instance ,node ,replica = False ):
490511
491512if replica :
492513archive_mode = 'always'
@@ -505,8 +526,8 @@ def set_archiving_conf(self, node, archive_dir=False, replica=False):
505526if os .name == 'posix' :
506527node .append_conf (
507528"postgresql.auto.conf" ,
508- "archive_command = 'test ! -f {0}/%f && cp %p{0}/ %f'" .format (archive_dir )
509- )
529+ "archive_command = '{0} archive-push -B {1} --instance={2} --wal-file-path %p--wal-file-name %f'" .format (
530+ self . probackup_path , backup_dir , instance ) )
510531#elif os.name == 'nt':
511532# node.append_conf(
512533# "postgresql.auto.conf",