55
55
# You can lookup error message and cmdline in exception object attributes
56
56
class ProbackupException (Exception ):
57
57
def __init__ (self ,message ,cmd ):
58
- # print message
59
- # self.message = repr(message).strip("'")
60
58
self .message = message
61
59
self .cmd = cmd
62
60
#need that to make second raise
@@ -138,24 +136,31 @@ def __init__(self, *args, **kwargs):
138
136
139
137
self .helpers_path = os .path .dirname (os .path .realpath (__file__ ))
140
138
self .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' ))
141
140
try :
142
- os .makedirs (os .path .join (self .dir_path ," tmp_dirs" ))
141
+ os .makedirs (os .path .join (self .dir_path ,' tmp_dirs' ))
143
142
except :
144
143
pass
145
144
self .probackup_path = os .path .abspath (os .path .join (
146
- self .dir_path ,
147
- "../pg_probackup"
148
- ))
145
+ self .dir_path ,"../pg_probackup" ))
149
146
150
147
def arcwal_dir (self ,node ):
151
148
return "%s/backup/wal" % node .base_dir
152
149
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
155
155
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 )
159
164
shutil .rmtree (real_base_dir ,ignore_errors = True )
160
165
161
166
node = get_new_node ('test' ,base_dir = real_base_dir )
@@ -173,9 +178,6 @@ def make_simple_node(self, base_dir=None, set_replication=False,
173
178
# Allow replication in pg_hba.conf
174
179
if set_replication :
175
180
node .set_replication_conf ()
176
- # Setup archiving for node
177
- if set_archiving :
178
- self .set_archiving_conf (node ,self .arcwal_dir (node ))
179
181
return node
180
182
181
183
def create_tblspace_in_node (self ,node ,tblspc_name ,cfs = False ):
@@ -301,6 +303,7 @@ def check_ptrack_clean(self, idx_dict, size):
301
303
def run_pb (self ,command ,async = False ):
302
304
try :
303
305
self .cmd = [' ' .join (map (str ,[self .probackup_path ]+ command ))]
306
+ print self .cmd
304
307
if async is True :
305
308
return subprocess .Popen (
306
309
[self .probackup_path ]+ command ,
@@ -319,44 +322,55 @@ def run_pb(self, command, async=False):
319
322
for line in self .output .splitlines ():
320
323
if 'INFO: Backup' and 'completed' in line :
321
324
return line .split ()[2 ]
322
- # backup_id = line.split()[2]
323
- # return {'cmd': cmd, 'output': output, 'backup_id': backup_id}
324
325
else :
325
326
return self .output
326
- # return {'cmd': cmd, 'output': output}
327
327
except subprocess .CalledProcessError as e :
328
- raise ProbackupException (e .output ,e .cmd )
328
+ raise ProbackupException (e .output ,self .cmd )
329
329
330
- def init_pb (self ,node ):
330
+ def init_pb (self ,backup_dir ):
331
331
332
332
return self .run_pb ([
333
333
"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 ,
335
352
"-D" ,node .data_dir
336
353
])
337
354
338
355
def clean_pb (self ,node ):
339
356
shutil .rmtree (self .backup_dir (node ),ignore_errors = True )
340
357
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 ):
346
359
347
360
cmd_list = [
348
361
"backup" ,
349
362
"-B" ,backup_dir ,
350
- "-D" ,data_dir ,
363
+ "-D" ,node . data_dir ,
351
364
"-p" ,"%i" % node .port ,
352
- "-d" ,"postgres"
365
+ "-d" ,"postgres" ,
366
+ "--instance={0}" .format (instance )
353
367
]
354
368
if backup_type :
355
369
cmd_list += ["-b" ,backup_type ]
356
370
357
371
return self .run_pb (cmd_list + options ,async )
358
372
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 = []):
360
374
if data_dir is None :
361
375
data_dir = node .data_dir
362
376
if backup_dir is None :
@@ -365,30 +379,35 @@ def restore_pb(self, node=None, backup_dir=None, data_dir=None, id=None, options
365
379
cmd_list = [
366
380
"restore" ,
367
381
"-B" ,backup_dir ,
368
- "-D" ,data_dir
382
+ "-D" ,data_dir ,
383
+ "--instance={0}" .format (instance )
369
384
]
370
385
if id :
371
386
cmd_list += ["-i" ,id ]
372
387
373
388
return self .run_pb (cmd_list + options )
374
389
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
+
376
392
backup_list = []
377
393
specific_record = {}
378
394
cmd_list = [
379
395
"show" ,
380
- "-B" ,self . backup_dir ( node ) ,
396
+ "-B" ,backup_dir ,
381
397
]
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 ]
384
403
385
404
if as_text :
386
405
# You should print it when calling as_text=true
387
406
return self .run_pb (cmd_list + options )
388
407
389
408
# get show result as list of lines
390
409
show_splitted = self .run_pb (cmd_list + options ).splitlines ()
391
- if id is None :
410
+ if instance is not None and backup_id is None :
392
411
# cut header(ID, Mode, etc) from show as single string
393
412
header = show_splitted [1 :2 ][0 ]
394
413
# 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):
430
449
specific_record [name .strip ()]= var
431
450
return specific_record
432
451
433
- def validate_pb (self ,node ,id = None ,options = []):
452
+ def validate_pb (self ,backup_dir ,instance = None ,id = None ,options = []):
453
+
434
454
cmd_list = [
435
455
"validate" ,
436
- "-B" ,self . backup_dir ( node ) ,
456
+ "-B" ,backup_dir ,
437
457
]
458
+ if instance :
459
+ cmd_list += ["--instance={0}" .format (instance )]
438
460
if id :
439
461
cmd_list += ["-i" ,id ]
440
462
441
- # print(cmd_list)
442
463
return self .run_pb (cmd_list + options )
443
464
444
- def delete_pb (self ,node ,id = None ,options = []):
465
+ def delete_pb (self ,backup_dir , instance = None ,id = None ,options = []):
445
466
cmd_list = [
446
467
"delete" ,
447
468
"-B" ,self .backup_dir (node ),
448
469
]
470
+ if instance :
471
+ cmd_list += ["--instance={0}" .format (instance )]
449
472
if id :
450
473
cmd_list += ["-i" ,id ]
451
474
452
475
# print(cmd_list)
453
476
return self .run_pb (cmd_list + options )
454
477
455
- def delete_expired (self ,node ,options = []):
478
+ def delete_expired (self ,backup_dir , instance = None ,options = []):
456
479
cmd_list = [
457
480
"delete" ,"--expired" ,
458
481
"-B" ,self .backup_dir (node ),
459
482
]
460
483
return self .run_pb (cmd_list + options )
461
484
462
- def show_config (self ,node ):
485
+ def show_config (self ,backup_dir , instance = None ):
463
486
out_dict = {}
464
487
cmd_list = [
465
488
"show-config" ,
@@ -484,9 +507,7 @@ def get_recovery_conf(self, node):
484
507
out_dict [key .strip ()]= value .strip (" '" ).replace ("'\n " ,"" )
485
508
return out_dict
486
509
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 ):
490
511
491
512
if replica :
492
513
archive_mode = 'always'
@@ -505,8 +526,8 @@ def set_archiving_conf(self, node, archive_dir=False, replica=False):
505
526
if os .name == 'posix' :
506
527
node .append_conf (
507
528
"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 ) )
510
531
#elif os.name == 'nt':
511
532
# node.append_conf(
512
533
# "postgresql.auto.conf",