Merge branch 'cfs'

This commit is contained in:
Grigory Smolkin
2017-10-19 18:19:20 +03:00
6 changed files with 1362 additions and 4 deletions
+790
View File
@@ -0,0 +1,790 @@
import os
import unittest
import random
from .helpers.cfs_helpers import find_by_extensions, find_by_name, find_by_pattern, corrupt_file
from .helpers.ptrack_helpers import ProbackupTest, ProbackupException
module_name = 'cfs_backup'
tblspace_name = 'cfs_tblspace'
class CfsBackupNoEncTest(ProbackupTest, unittest.TestCase):
# --- Begin --- #
def setUp(self):
self.fname = self.id().split('.')[3]
self.backup_dir = os.path.join(self.tmp_path, module_name, self.fname, 'backup')
self.node = self.make_simple_node(
base_dir="{0}/{1}/node".format(module_name, self.fname),
set_replication=True,
initdb_params=['--data-checksums'],
pg_options={
'wal_level': 'replica',
'ptrack_enable': 'on',
'cfs_encryption': 'off',
'max_wal_senders': '2'
}
)
self.init_pb(self.backup_dir)
self.add_instance(self.backup_dir, 'node', self.node)
self.set_archiving(self.backup_dir, 'node', self.node)
self.node.start()
self.create_tblspace_in_node(self.node, tblspace_name, True)
tblspace = self.node.safe_psql(
"postgres",
"SELECT * FROM pg_tablespace WHERE spcname='{0}'".format(tblspace_name)
)
self.assertTrue(
tblspace_name in tblspace and "compression=true" in tblspace,
"ERROR: The tablespace not created or it create without compressions"
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found"
)
# --- Section: Full --- #
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace(self):
"""
Case: Check fullbackup empty compressed tablespace
"""
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Full backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([os.path.join(self.backup_dir, 'backups', 'node', backup_id)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace_stream(self):
"""
Case: Check fullbackup empty compressed tablespace with options stream
"""
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Full backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([os.path.join(self.backup_dir, 'backups', 'node', backup_id)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
# PGPRO-1018 invalid file size
def test_fullbackup_after_create_table(self):
"""
Case: Make full backup after created table in the tablespace
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {0}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Full backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([os.path.join(self.backup_dir, 'backups', 'node', backup_id)], ['pg_compression']),
"ERROR: File pg_compression not found in {0}".format(os.path.join(self.backup_dir, 'node', backup_id))
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
# PGPRO-1018 invalid file size
def test_fullbackup_after_create_table_stream(self):
"""
Case: Make full backup after created table in the tablespace with option --stream
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Full backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([os.path.join(self.backup_dir, 'backups', 'node', backup_id)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# --- Section: Incremental from empty tablespace --- #
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace_ptrack_after_create_table(self):
"""
Case: Make full backup before created table in the tablespace.
Make ptrack backup after create table
"""
try:
self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='ptrack')
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Incremental backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found"
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace_ptrack_after_create_table_stream(self):
"""
Case: Make full backup before created table in the tablespace.
Make ptrack backup after create table
"""
try:
self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='ptrack', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Incremental backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found"
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace_page_after_create_table(self):
"""
Case: Make full backup before created table in the tablespace.
Make page backup after create table
"""
try:
self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='page')
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Incremental backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found"
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_empty_tablespace_page_after_create_table_stream(self):
"""
Case: Make full backup before created table in the tablespace.
Make page backup after create table
"""
try:
self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id = None
try:
backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='page', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup = self.show_pb(self.backup_dir, 'node', backup_id)
self.assertEqual(
"OK",
show_backup["status"],
"ERROR: Incremental backup status is not valid. \n Current backup status={0}".format(show_backup["status"])
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found"
)
self.assertTrue(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['.cfm']),
"ERROR: .cfm files not found in backup dir"
)
self.assertFalse(
find_by_extensions([os.path.join(self.backup_dir, 'node', backup_id)], ['_ptrack']),
"ERROR: _ptrack files was found in backup dir"
)
# --- Section: Incremental from fill tablespace --- #
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_after_create_table_ptrack_after_create_table(self):
"""
Case: Make full backup before created table in the tablespace.
Make ptrack backup after create table.
Check: incremental backup will not greater as full
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id_full = None
try:
backup_id_full = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,25) i'.format('t2', tblspace_name)
)
backup_id_ptrack = None
try:
backup_id_ptrack = self.backup_node(self.backup_dir, 'node', self.node, backup_type='ptrack')
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup_full = self.show_pb(self.backup_dir, 'node', backup_id_full)
show_backup_ptrack = self.show_pb(self.backup_dir, 'node', backup_id_ptrack)
self.assertGreater(
show_backup_ptrack["data-bytes"],
show_backup_full["data-bytes"],
"ERROR: Size of incremental backup greater as full. \n INFO: {0} >{1}".format(
show_backup_ptrack["data-bytes"],
show_backup_full["data-bytes"]
)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_after_create_table_ptrack_after_create_table_stream(self):
"""
Case: Make full backup before created table in the tablespace(--stream).
Make ptrack backup after create table(--stream).
Check: incremental backup will not greater as full
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id_full = None
try:
backup_id_full = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,25) i'.format('t2', tblspace_name)
)
backup_id_ptrack = None
try:
backup_id_ptrack = self.backup_node(self.backup_dir, 'node', self.node, backup_type='ptrack', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup_full = self.show_pb(self.backup_dir, 'node', backup_id_full)
show_backup_ptrack = self.show_pb(self.backup_dir, 'node', backup_id_ptrack)
self.assertGreater(
show_backup_ptrack["data-bytes"],
show_backup_full["data-bytes"],
"ERROR: Size of incremental backup greater as full. \n INFO: {0} >{1}".format(
show_backup_ptrack["data-bytes"],
show_backup_full["data-bytes"]
)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_after_create_table_page_after_create_table(self):
"""
Case: Make full backup before created table in the tablespace.
Make ptrack backup after create table.
Check: incremental backup will not greater as full
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id_full = None
try:
backup_id_full = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,25) i'.format('t2', tblspace_name)
)
backup_id_page = None
try:
backup_id_page = self.backup_node(self.backup_dir, 'node', self.node, backup_type='page')
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup_full = self.show_pb(self.backup_dir, 'node', backup_id_full)
show_backup_page = self.show_pb(self.backup_dir, 'node', backup_id_page)
self.assertGreater(
show_backup_page["data-bytes"],
show_backup_full["data-bytes"],
"ERROR: Size of incremental backup greater as full. \n INFO: {0} >{1}".format(
show_backup_page["data-bytes"],
show_backup_full["data-bytes"]
)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_fullbackup_after_create_table_page_after_create_table_stream(self):
"""
Case: Make full backup before created table in the tablespace(--stream).
Make ptrack backup after create table(--stream).
Check: incremental backup will not greater as full
"""
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
backup_id_full = None
try:
backup_id_full = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,25) i'.format('t2', tblspace_name)
)
backup_id_page = None
try:
backup_id_page = self.backup_node(self.backup_dir, 'node', self.node, backup_type='page', options=['--stream'])
except ProbackupException as e:
self.fail(
"ERROR: Incremental backup failed.\n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
show_backup_full = self.show_pb(self.backup_dir, 'node', backup_id_full)
show_backup_page = self.show_pb(self.backup_dir, 'node', backup_id_page)
self.assertGreater(
show_backup_page["data-bytes"],
show_backup_full["data-bytes"],
"ERROR: Size of incremental backup greater as full. \n INFO: {0} >{1}".format(
show_backup_page["data-bytes"],
show_backup_full["data-bytes"]
)
)
# --- Make backup with not valid data(broken .cfm) --- #
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_delete_random_cfm_file_from_tablespace_dir(self):
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
list_cmf = find_by_extensions([self.get_tblspace_path(self.node,tblspace_name)],['.cfm'])
self.assertTrue(
list_cmf,
"ERROR: .cfm-files not found into tablespace dir"
)
os.remove(random.choice(list_cmf))
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_delete_file_pg_compression_from_tablespace_dir(self):
os.remove(find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression'])[0])
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_delete_random_data_file_from_tablespace_dir(self):
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
list_data_files = find_by_pattern([self.get_tblspace_path(self.node,tblspace_name)],'^.*/\d+$')
self.assertTrue(
list_data_files,
"ERROR: Files of data not found into tablespace dir"
)
os.remove(random.choice(list_data_files))
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_broken_random_cfm_file_into_tablespace_dir(self):
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
list_cmf = find_by_extensions([self.get_tblspace_path(self.node,tblspace_name)],['.cfm'])
self.assertTrue(
list_cmf,
"ERROR: .cfm-files not found into tablespace dir"
)
corrupt_file(random.choice(list_cmf))
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_broken_random_data_file_into_tablespace_dir(self):
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,256) i'.format('t1', tblspace_name)
)
list_data_files = find_by_pattern([self.get_tblspace_path(self.node,tblspace_name)],'^.*/\d+$')
self.assertTrue(
list_data_files,
"ERROR: Files of data not found into tablespace dir"
)
corrupt_file(random.choice(list_data_files))
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_broken_file_pg_compression_into_tablespace_dir(self):
corrupted_file = find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression'])[0]
self.assertTrue(
corrupt_file(corrupted_file),
"ERROR: File is not corrupted or it missing"
)
self.assertRaises(
ProbackupException,
self.backup_node,self.backup_dir, 'node', self.node, backup_type='full'
)
# --- End ---#
def tearDown(self):
self.node.cleanup()
self.del_test_dir(module_name, self.fname)
class CfsBackupEncTest(CfsBackupNoEncTest):
# --- Begin --- #
def setUp(self):
os.environ["PG_CIPHER_KEY"] = "super_secret_cipher_key"
super(CfsBackupEncTest, self).setUp()
+452
View File
@@ -0,0 +1,452 @@
"""
restore
Syntax:
pg_probackup restore -B backupdir --instance instance_name
[-D datadir]
[ -i backup_id | [{--time=time | --xid=xid } [--inclusive=boolean]]][--timeline=timeline] [-T OLDDIR=NEWDIR]
[-j num_threads] [--progress] [-q] [-v]
"""
import os
import unittest
import shutil
from .helpers.cfs_helpers import find_by_name
from .helpers.ptrack_helpers import ProbackupTest, ProbackupException
module_name = 'cfs_restore'
tblspace_name = 'cfs_tblspace'
tblspace_name_new = 'cfs_tblspace_new'
class CfsRestoreBase(ProbackupTest, unittest.TestCase):
def setUp(self):
self.fname = self.id().split('.')[3]
self.backup_dir = os.path.join(self.tmp_path, module_name, self.fname, 'backup')
self.node = self.make_simple_node(
base_dir="{0}/{1}/node".format(module_name, self.fname),
set_replication=True,
initdb_params=['--data-checksums'],
pg_options={
'wal_level': 'replica',
'ptrack_enable': 'on',
'cfs_encryption': 'off',
'max_wal_senders': '2'
}
)
self.init_pb(self.backup_dir)
self.add_instance(self.backup_dir, 'node', self.node)
self.set_archiving(self.backup_dir, 'node', self.node)
self.node.start()
self.create_tblspace_in_node(self.node, tblspace_name, True)
self.add_data_in_cluster()
self.backup_id = None
try:
self.backup_id = self.backup_node(self.backup_dir, 'node', self.node, backup_type='full')
except ProbackupException as e:
self.fail(
"ERROR: Full backup failed \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
def add_data_in_cluster(self):
pass
def tearDown(self):
self.node.cleanup()
self.del_test_dir(module_name, self.fname)
class CfsRestoreNoencEmptyTablespaceTest(CfsRestoreBase):
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_empty_tablespace_from_fullbackup(self):
"""
Case: Restore empty tablespace from valid full backup.
"""
self.node.stop({"-m": "immediate"})
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
try:
self.restore_node(self.backup_dir, 'node', self.node, backup_id=self.backup_id)
except ProbackupException as e:
self.fail(
"ERROR: Restore failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ["pg_compression"]),
"ERROR: Restored data is not valid. pg_compression not found in tablespace dir."
)
try:
self.node.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
tblspace = self.node.safe_psql(
"postgres",
"SELECT * FROM pg_tablespace WHERE spcname='{0}'".format(tblspace_name)
)
self.assertTrue(
tblspace_name in tblspace and "compression=true" in tblspace,
"ERROR: The tablespace not restored or it restored without compressions"
)
class CfsRestoreNoencTest(CfsRestoreBase):
def add_data_in_cluster(self):
self.node.safe_psql(
"postgres",
'CREATE TABLE {0} TABLESPACE {1} \
AS SELECT i AS id, MD5(i::text) AS text, \
MD5(repeat(i::text,10))::tsvector AS tsvector \
FROM generate_series(0,1e5) i'.format('t1', tblspace_name)
)
self.table_t1 = self.node.safe_psql(
"postgres",
"SELECT * FROM t1"
)
# --- Restore from full backup ---#
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_old_location(self):
"""
Case: Restore instance from valid full backup to old location.
"""
self.node.stop()
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
try:
self.restore_node(self.backup_dir, 'node', self.node, backup_id=self.backup_id)
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found in tablespace dir"
)
try:
self.node.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_old_location_3_jobs(self):
"""
Case: Restore instance from valid full backup to old location.
"""
self.node.stop(['-m', 'immediate'])
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
try:
self.restore_node(self.backup_dir, 'node', self.node, backup_id=self.backup_id, options=['-j', '3'])
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
try:
self.node.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_new_location(self):
"""
Case: Restore instance from valid full backup to new location.
"""
self.node.stop(['-m', 'immediate'])
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
self.node_new = self.make_simple_node(base_dir="{0}/{1}/node_new_location".format(module_name, self.fname))
try:
self.restore_node(self.backup_dir, 'node', self.node_new, backup_id=self.backup_id)
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node_new, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
try:
self.node_new.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
self.node_new.cleanup()
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_new_location_5_jobs(self):
"""
Case: Restore instance from valid full backup to new location.
"""
self.node.stop(['-m', 'immediate'])
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
self.node_new = self.make_simple_node(base_dir="{0}/{1}/node_new_location".format(module_name, self.fname))
try:
self.restore_node(self.backup_dir, 'node', self.node_new, backup_id=self.backup_id, options=['-j', '5'])
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node_new, tblspace_name)], ['pg_compression']),
"ERROR: File pg_compression not found in backup dir"
)
try:
self.node_new.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
self.node_new.cleanup()
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_old_location_tablespace_new_location(self):
self.node.stop(['-m', 'immediate'])
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
os.mkdir(self.get_tblspace_path(self.node, tblspace_name_new))
try:
self.restore_node(
self.backup_dir,
'node', self.node,
backup_id=self.backup_id,
options=[
"-T %s = %s".format(
self.get_tblspace_path(self.node, tblspace_name),
self.get_tblspace_path(self.node, tblspace_name_new)
)
]
)
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name_new)], ['pg_compression']),
"ERROR: File pg_compression not found in new tablespace location"
)
try:
self.node.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_restore_from_fullbackup_to_old_location_tablespace_new_location_3_jobs(self):
self.node.stop(['-m', 'immediate'])
self.node.cleanup()
shutil.rmtree(self.get_tblspace_path(self.node, tblspace_name))
os.mkdir(self.get_tblspace_path(self.node, tblspace_name_new))
try:
self.restore_node(
self.backup_dir,
'node', self.node,
backup_id=self.backup_id,
options=[
"j",
"3",
"-T %s = %s".format(
self.get_tblspace_path(self.node, tblspace_name),
self.get_tblspace_path(self.node, tblspace_name_new)
)
]
)
except ProbackupException as e:
self.fail(
"ERROR: Restore from full backup failed. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertTrue(
find_by_name([self.get_tblspace_path(self.node, tblspace_name_new)], ['pg_compression']),
"ERROR: File pg_compression not found in new tablespace location"
)
try:
self.node.start()
except ProbackupException as e:
self.fail(
"ERROR: Instance not started after restore. \n {0} \n {1}".format(
repr(self.cmd),
repr(e.message)
)
)
self.assertEqual(
repr(self.node.safe_psql("postgres", "SELECT * FROM %s" % 't1')),
repr(self.table_t1)
)
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_fullbackup_to_new_location_tablespace_new_location(self):
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_fullbackup_to_new_location_tablespace_new_location_5_jobs(self):
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_ptrack(self):
"""
Case: Restore from backup to old location
"""
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_ptrack_jobs(self):
"""
Case: Restore from backup to old location, four jobs
"""
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_ptrack_new_jobs(self):
pass
# --------------------------------------------------------- #
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_page(self):
"""
Case: Restore from backup to old location
"""
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_page_jobs(self):
"""
Case: Restore from backup to old location, four jobs
"""
pass
# @unittest.expectedFailure
@unittest.skip("skip")
def test_restore_from_page_new_jobs(self):
"""
Case: Restore from backup to new location, four jobs
"""
pass
class CfsRestoreEncEmptyTablespaceTest(CfsRestoreNoencEmptyTablespaceTest):
# --- Begin --- #
def setUp(self):
os.environ["PG_CIPHER_KEY"] = "super_secret_cipher_key"
super(CfsRestoreNoencEmptyTablespaceTest, self).setUp()
class CfsRestoreEncTest(CfsRestoreNoencTest):
# --- Begin --- #
def setUp(self):
os.environ["PG_CIPHER_KEY"] = "super_secret_cipher_key"
super(CfsRestoreNoencTest, self).setUp()
+25
View File
@@ -0,0 +1,25 @@
import os
import unittest
import random
from .helpers.cfs_helpers import find_by_extensions, find_by_name, find_by_pattern, corrupt_file
from .helpers.ptrack_helpers import ProbackupTest, ProbackupException
module_name = 'cfs_validate_backup'
tblspace_name = 'cfs_tblspace'
class CfsValidateBackupNoenc(ProbackupTest,unittest.TestCase):
def setUp(self):
pass
def test_validate_fullbackup_empty_tablespace_after_delete_pg_compression(self):
pass
def tearDown(self):
pass
class CfsValidateBackupNoenc(CfsValidateBackupNoenc):
os.environ["PG_CIPHER_KEY"] = "super_secret_cipher_key"
super(CfsValidateBackupNoenc).setUp()
+1 -1
View File
@@ -1,2 +1,2 @@
__all__ = ['ptrack_helpers', 'expected_errors']
__all__ = ['ptrack_helpers', 'cfs_helpers', 'expected_errors']
#from . import *
+91
View File
@@ -0,0 +1,91 @@
import os
import re
import random
import string
def find_by_extensions(dirs=None, extensions=None):
"""
find_by_extensions(['path1','path2'],['.txt','.log'])
:return:
Return list of files include full path by file extensions
"""
files = []
new_dirs = []
if dirs is not None and extensions is not None:
for d in dirs:
try:
new_dirs += [os.path.join(d, f) for f in os.listdir(d)]
except OSError:
if os.path.splitext(d)[1] in extensions:
files.append(d)
if new_dirs:
files.extend(find_by_extensions(new_dirs, extensions))
return files
def find_by_pattern(dirs=None, pattern=None):
"""
find_by_pattern(['path1','path2'],'^.*/*.txt')
:return:
Return list of files include full path by pattern
"""
files = []
new_dirs = []
if dirs is not None and pattern is not None:
for d in dirs:
try:
new_dirs += [os.path.join(d, f) for f in os.listdir(d)]
except OSError:
if re.match(pattern,d):
files.append(d)
if new_dirs:
files.extend(find_by_pattern(new_dirs, pattern))
return files
def find_by_name(dirs=None, filename=None):
files = []
new_dirs = []
if dirs is not None and filename is not None:
for d in dirs:
try:
new_dirs += [os.path.join(d, f) for f in os.listdir(d)]
except OSError:
if os.path.basename(d) in filename:
files.append(d)
if new_dirs:
files.extend(find_by_name(new_dirs, filename))
return files
def corrupt_file(filename):
file_size = None
try:
file_size = os.path.getsize(filename)
except OSError:
return False
try:
with open(filename, "rb+") as f:
f.seek(random.randint(int(0.1*file_size),int(0.8*file_size)))
f.write(random_string(0.1*file_size))
f.close()
except OSError:
return False
return True
def random_string(n):
a = string.ascii_letters + string.digits
return ''.join([random.choice(a) for i in range(int(n)+1)])
+3 -3
View File
@@ -4,7 +4,7 @@ from sys import exit, argv, version_info
import subprocess
import shutil
import six
from testgres import get_new_node, clean_all, version_to_num
import testgres
import hashlib
import re
import pwd
@@ -159,7 +159,7 @@ class ProbackupTest(object):
real_base_dir = os.path.join(self.tmp_path, base_dir)
shutil.rmtree(real_base_dir, ignore_errors=True)
node = get_new_node('test', base_dir=real_base_dir)
node = testgres.get_new_node('test', base_dir=real_base_dir)
node.init(initdb_params=initdb_params)
# Sane default parameters, not a shit with fsync = off from testgres
@@ -598,7 +598,7 @@ class ProbackupTest(object):
def del_test_dir(self, module_name, fname):
""" Del testdir and optimistically try to del module dir"""
try:
clean_all()
testgres.clean_all()
except:
pass