@@ -1172,6 +1172,179 @@ def test_external_dir_is_symlink(self):
11721172# Clean after yourself
11731173self .del_test_dir (module_name ,fname )
11741174
1175+ # @unittest.expectedFailure
1176+ # @unittest.skip("skip")
1177+ def test_external_dir_contain_symlink_on_dir (self ):
1178+ """
1179+ Check that backup works correctly if external dir is symlink,
1180+ symlink pointing to external dir should be followed,
1181+ but restored as directory
1182+ """
1183+ fname = self .id ().split ('.' )[3 ]
1184+ backup_dir = os .path .join (self .tmp_path ,module_name ,fname ,'backup' )
1185+ core_dir = os .path .join (self .tmp_path ,module_name ,fname )
1186+ shutil .rmtree (core_dir ,ignore_errors = True )
1187+ node = self .make_simple_node (
1188+ base_dir = os .path .join (module_name ,fname ,'node' ),
1189+ set_replication = True ,
1190+ initdb_params = ['--data-checksums' ])
1191+
1192+ self .init_pb (backup_dir )
1193+ self .add_instance (backup_dir ,'node' ,node )
1194+ node .slow_start ()
1195+
1196+ external_dir = self .get_tblspace_path (node ,'external_dir' )
1197+ dir_in_external_dir = os .path .join (external_dir ,'dir' )
1198+
1199+ node .pgbench_init (scale = 3 )
1200+
1201+ # temp FULL backup
1202+ backup_id = self .backup_node (
1203+ backup_dir ,'node' ,node ,options = ["-j" ,"4" ,"--stream" ])
1204+
1205+ # fill some directory with data
1206+ core_dir = os .path .join (self .tmp_path ,module_name ,fname )
1207+ symlinked_dir = os .path .join (core_dir ,'symlinked' )
1208+
1209+ self .restore_node (
1210+ backup_dir ,'node' ,node ,
1211+ data_dir = symlinked_dir ,options = ["-j" ,"4" ])
1212+
1213+ # drop temp FULL backup
1214+ self .delete_pb (backup_dir ,'node' ,backup_id = backup_id )
1215+
1216+ # create symlink to directory in external directory
1217+ print (symlinked_dir )
1218+ print (dir_in_external_dir )
1219+ os .mkdir (external_dir )
1220+ os .symlink (symlinked_dir ,dir_in_external_dir )
1221+
1222+ # FULL backup with external directories
1223+ backup_id = self .backup_node (
1224+ backup_dir ,'node' ,node ,
1225+ options = [
1226+ "-j" ,"4" ,"--stream" ,
1227+ "-E" ,"{0}" .format (
1228+ external_dir )])
1229+
1230+ pgdata = self .pgdata_content (
1231+ node .base_dir ,exclude_dirs = ['logs' ])
1232+
1233+ node_restored = self .make_simple_node (
1234+ base_dir = os .path .join (module_name ,fname ,'node_restored' ))
1235+
1236+ # RESTORE
1237+ node_restored .cleanup ()
1238+
1239+ external_dir_new = self .get_tblspace_path (
1240+ node_restored ,'external_dir' )
1241+
1242+ self .restore_node (
1243+ backup_dir ,'node' ,node_restored ,
1244+ options = [
1245+ "-j" ,"4" ,"--external-mapping={0}={1}" .format (
1246+ external_dir ,external_dir_new )])
1247+
1248+ pgdata_restored = self .pgdata_content (
1249+ node_restored .base_dir ,exclude_dirs = ['logs' ])
1250+
1251+ self .compare_pgdata (pgdata ,pgdata_restored )
1252+
1253+ self .assertEqual (
1254+ external_dir ,
1255+ self .show_pb (
1256+ backup_dir ,'node' ,
1257+ backup_id = backup_id )['external-dirs' ])
1258+
1259+ # Clean after yourself
1260+ self .del_test_dir (module_name ,fname )
1261+
1262+ # @unittest.expectedFailure
1263+ # @unittest.skip("skip")
1264+ def test_external_dir_contain_symlink_on_file (self ):
1265+ """
1266+ Check that backup works correctly if external dir is symlink,
1267+ symlink pointing to external dir should be followed,
1268+ but restored as directory
1269+ """
1270+ fname = self .id ().split ('.' )[3 ]
1271+ backup_dir = os .path .join (self .tmp_path ,module_name ,fname ,'backup' )
1272+ core_dir = os .path .join (self .tmp_path ,module_name ,fname )
1273+ shutil .rmtree (core_dir ,ignore_errors = True )
1274+ node = self .make_simple_node (
1275+ base_dir = os .path .join (module_name ,fname ,'node' ),
1276+ set_replication = True ,
1277+ initdb_params = ['--data-checksums' ])
1278+
1279+ self .init_pb (backup_dir )
1280+ self .add_instance (backup_dir ,'node' ,node )
1281+ node .slow_start ()
1282+
1283+ external_dir = self .get_tblspace_path (node ,'external_dir' )
1284+ file_in_external_dir = os .path .join (external_dir ,'file' )
1285+
1286+ node .pgbench_init (scale = 3 )
1287+
1288+ # temp FULL backup
1289+ backup_id = self .backup_node (
1290+ backup_dir ,'node' ,node ,options = ["-j" ,"4" ,"--stream" ])
1291+
1292+ # fill some directory with data
1293+ core_dir = os .path .join (self .tmp_path ,module_name ,fname )
1294+ symlinked_dir = os .path .join (core_dir ,'symlinked' )
1295+
1296+ self .restore_node (
1297+ backup_dir ,'node' ,node ,
1298+ data_dir = symlinked_dir ,options = ["-j" ,"4" ])
1299+
1300+ # drop temp FULL backup
1301+ self .delete_pb (backup_dir ,'node' ,backup_id = backup_id )
1302+
1303+ # create symlink to directory in external directory
1304+ src_file = os .path .join (symlinked_dir ,'postgresql.conf' )
1305+ os .mkdir (external_dir )
1306+ os .symlink (src_file ,file_in_external_dir )
1307+
1308+ # FULL backup with external directories
1309+ backup_id = self .backup_node (
1310+ backup_dir ,'node' ,node ,
1311+ options = [
1312+ "-j" ,"4" ,"--stream" ,
1313+ "-E" ,"{0}" .format (
1314+ external_dir )])
1315+
1316+ pgdata = self .pgdata_content (
1317+ node .base_dir ,exclude_dirs = ['logs' ])
1318+
1319+ node_restored = self .make_simple_node (
1320+ base_dir = os .path .join (module_name ,fname ,'node_restored' ))
1321+
1322+ # RESTORE
1323+ node_restored .cleanup ()
1324+
1325+ external_dir_new = self .get_tblspace_path (
1326+ node_restored ,'external_dir' )
1327+
1328+ self .restore_node (
1329+ backup_dir ,'node' ,node_restored ,
1330+ options = [
1331+ "-j" ,"4" ,"--external-mapping={0}={1}" .format (
1332+ external_dir ,external_dir_new )])
1333+
1334+ pgdata_restored = self .pgdata_content (
1335+ node_restored .base_dir ,exclude_dirs = ['logs' ])
1336+
1337+ self .compare_pgdata (pgdata ,pgdata_restored )
1338+
1339+ self .assertEqual (
1340+ external_dir ,
1341+ self .show_pb (
1342+ backup_dir ,'node' ,
1343+ backup_id = backup_id )['external-dirs' ])
1344+
1345+ # Clean after yourself
1346+ self .del_test_dir (module_name ,fname )
1347+
11751348# @unittest.expectedFailure
11761349# @unittest.skip("skip")
11771350def test_external_dir_is_tablespace (self ):