Exemple #1
0
def test_get_latest_backup(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    assert instance.get_latest_backup() == BinlogCopy(
        host='master1',
        name='mysqlbin005.bin',
        created_at=100504
    )
Exemple #2
0
def test_serialize_doesnt_change_orignal(raw_binlog_status):

    status_original = BinlogStatus(content=raw_binlog_status)
    status_original_before = deepcopy(status_original)

    assert status_original == status_original_before
    status_original.serialize()
    assert status_original == status_original_before
Exemple #3
0
def test_remove_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    copy = BinlogCopy(host='master1',
                      name='mysqlbin001.bin',
                      created_at=100500)
    assert copy in instance
    instance.remove("master1/binlog/mysqlbin001.bin")
    assert copy not in instance
Exemple #4
0
def test_remove_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    copy = BinlogCopy(
        host='master1',
        name='mysqlbin001.bin',
        created_at=100500
    )
    assert copy in instance
    instance.remove("master1/binlog/mysqlbin001.bin")
    assert copy not in instance
Exemple #5
0
def backup_binlogs(run_type, config):  # pylint: disable=too-many-locals
    """Copy MySQL binlog files to the backup destination.

    :param run_type: Run type
    :type run_type: str
    :param config: Tool configuration
    :type config: TwinDBBackupConfig
    """
    if config.mysql is None:
        LOG.debug("No MySQL config, not copying binlogs")
        return

    dst = config.destination()
    status = BinlogStatus(dst=dst)
    mysql_client = MySQLClient(defaults_file=config.mysql.defaults_file)

    # last_copy = status.latest_backup
    LOG.debug("Latest copied binlog %s", status.latest_backup)
    with mysql_client.cursor() as cur:
        cur.execute("FLUSH BINARY LOGS")
        backup_set = binlogs_to_backup(
            cur,
            last_binlog=status.latest_backup.name
            if status.latest_backup else None,
        )
        cur.execute("SELECT @@log_bin_basename")
        row = cur.fetchone()
        if row["@@log_bin_basename"]:
            binlog_dir = osp.dirname(row["@@log_bin_basename"])
        else:
            return

    for binlog_name in backup_set:
        src = BinlogSource(run_type, mysql_client, binlog_name)
        binlog_copy = BinlogCopy(
            src.host,
            binlog_name,
            BinlogParser(osp.join(binlog_dir, binlog_name)).created_at,
        )
        _backup_stream(config, src, dst)
        status.add(binlog_copy)

    try:
        expire_log_days = config.mysql.expire_log_days
    except (configparser.NoSectionError, configparser.NoOptionError):
        expire_log_days = 7

    for copy in status:
        now = int(time.time())
        LOG.debug("Reviewing copy %s. Now: %d", copy, now)

        if copy.created_at < now - expire_log_days * 24 * 3600:
            LOG.debug(
                "Deleting copy that was taken %d seconds ago",
                now - copy.created_at,
            )
            dst.delete(copy.key + ".gz")
            status.remove(copy.key)

    status.save(dst)
Exemple #6
0
def test_add_to_empty_status():
    instance = BinlogStatus()

    instance.add(BinlogCopy("host", "foo/bar", 100500))
    assert BinlogCopy("host", "foo/bar", 100500) in instance

    instance.add(BinlogCopy("host", "foo/bar-2", 100501))
    assert BinlogCopy("host", "foo/bar", 100500) in instance
    assert BinlogCopy("host", "foo/bar-2", 100501) in instance
Exemple #7
0
def test_load(status_json, copies):
    status = BinlogStatus()
    assert status._load(status_json) == copies
Exemple #8
0
def test_remove_non_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    with pytest.raises(StatusKeyNotFound):
        instance.remove("foo")
Exemple #9
0
def test_ne(raw_binlog_status):
    status_1 = BinlogStatus(raw_binlog_status)
    status_2 = BinlogStatus()

    assert status_1 != status_2
Exemple #10
0
def test_get_item_not_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    with pytest.raises(StatusKeyNotFound):
        # noinspection PyStatementEffect
        instance["foo/bar"]
Exemple #11
0
def test_eq(raw_binlog_status):
    status_1 = BinlogStatus(raw_binlog_status)
    status_2 = BinlogStatus(raw_binlog_status)

    assert status_1 == status_2
Exemple #12
0
def test_init_not_empty(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    assert instance.version == 1
    assert len(instance) == 5
Exemple #13
0
def test_init_empty():
    instance = BinlogStatus()
    assert len(instance) == 0
Exemple #14
0
def test_load(status_json, copies):
    status = BinlogStatus()
    assert status._load(status_json) == copies
Exemple #15
0
def test_remove_non_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    with pytest.raises(StatusKeyNotFound):
        instance.remove("foo")
Exemple #16
0
def test_get_item_existing_copy(raw_binlog_status):
    instance = BinlogStatus(raw_binlog_status)
    copy = instance["master1/binlog/mysqlbin001.bin"]
    assert copy is not None
Exemple #17
0
def test_serialize(raw_binlog_status):
    status_original = BinlogStatus(raw_binlog_status)
    status_converted = status_original.serialize()

    assert BinlogStatus(content=status_converted) == status_original
Exemple #18
0
def backup_binlogs(run_type, config):  # pylint: disable=too-many-locals
    """Copy MySQL binlog files to the backup destination.

    :param run_type: Run type
    :type run_type: str
    :param config: Tool configuration
    :type config: TwinDBBackupConfig
    """
    if config.mysql is None:
        LOG.debug('No MySQL config, not copying binlogs')
        return

    dst = config.destination()
    status = BinlogStatus(dst=dst)
    mysql_client = MySQLClient(
        defaults_file=config.mysql.defaults_file
    )

    # last_copy = status.latest_backup
    LOG.debug('Latest copied binlog %s', status.latest_backup)
    with mysql_client.cursor() as cur:
        cur.execute("FLUSH BINARY LOGS")
        backup_set = binlogs_to_backup(
            cur,
            last_binlog=status.latest_backup.name
            if status.latest_backup else None
        )
        cur.execute("SELECT @@log_bin_basename")
        row = cur.fetchone()
        binlog_dir = osp.dirname(row['@@log_bin_basename'])

    for binlog_name in backup_set:
        src = BinlogSource(run_type, mysql_client, binlog_name)
        binlog_copy = BinlogCopy(
            src.host,
            binlog_name,
            BinlogParser(
                osp.join(
                    binlog_dir,
                    binlog_name
                )
            ).created_at
        )
        _backup_stream(config, src, dst)
        status.add(binlog_copy)

    try:
        expire_log_days = config.mysql.expire_log_days
    except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
        expire_log_days = 7

    for copy in status:
        now = int(time.time())
        LOG.debug('Reviewing copy %s. Now: %d', copy, now)

        if copy.created_at < now - expire_log_days * 24 * 3600:
            LOG.debug(
                'Deleting copy that was taken %d seconds ago',
                now - copy.created_at
            )
            dst.delete(copy.key + ".gz")
            status.remove(copy.key)

    status.save(dst)
Exemple #19
0
def test_init_restores_name(raw_binlog_status):
    status = BinlogStatus(raw_binlog_status)
    copy = status['master1/binlog/mysqlbin001.bin']
    assert copy.name == 'mysqlbin001.bin'
Exemple #20
0
def test_basename():
    assert BinlogStatus().basename == 'binlog-status'