yhkylin-backup-tools/backup-daemon/systembackupproxy.cpp

461 lines
14 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "systembackupproxy.h"
#include <QStorageInfo>
#include <QDateTime>
#include <QDebug>
#include <kysec/status.h>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
#include "myprocess/calcbackupsize.h"
IMPLEMENT_DYNCREATE(SystemBackupProxy)
SystemBackupProxy::SystemBackupProxy()
{
m_bSuccess = false;
m_p = nullptr;
m_size = 0;
}
SystemBackupProxy::~SystemBackupProxy()
{
delete m_p;
m_p = nullptr;
}
/**
* @brief 环境检测
* @return false,检测失败;true,检测成功
*/
bool SystemBackupProxy::checkEnvEx()
{
qDebug() << "SystemBackupProxy::checkEnv invoke begin";
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备都得保证/backup挂载上); 若没挂载,挂载
MyMountProxy mountProxy;
if ( MountResult::MOUNTED != mountProxy.mountBackupPartition() ) {
emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL));
return false;
}
// 2、判断备份是否增量备份
isIncBackup();
// 3、检测空间是否满足备份
bool result = checkFreeCapacity();
qDebug() << "SystemBackupProxy::checkEnv invoke end";
return result;
}
/**
* @brief 执行备份逻辑
*/
void SystemBackupProxy::doWorkEx()
{
qDebug() << "SystemBackupProxy::doWorkEx invoke begin";
// 环境检测
if (!checkEnvEx())
return ;
// 开始备份
doBackup();
qDebug() << "SystemBackupProxy::doWorkEx invoke end";
}
void SystemBackupProxy::cancelEx()
{}
/**
* @brief 判断是否增量备份
* @return true,增量备份; false全量备份
*/
bool SystemBackupProxy::isIncBackup()
{
QString backupPath;
ParseBackupList::BackupPoint point;
if (m_backupWrapper.m_uuid.isEmpty()) {
QString xmlPath(Utils::getSysRootPath() + BACKUP_XML_PATH);
xmlPath.replace("//", "/");
ParseBackupList parser(xmlPath);
point = parser.getLastSysBackupPoint();
if (point.m_uuid.isEmpty())
return false;
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + point.m_uuid + "/data";
} else {
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
}
backupPath.replace("//", "/");
if (Utils::isDirExist(backupPath)) {
m_backupWrapper.m_baseUuid = point.m_uuid;
m_backupWrapper.m_bIncrement = true;
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
return true;
}
return false;
}
/**
* @brief 校验剩余空间是否满足备份
*/
bool SystemBackupProxy::checkFreeCapacity()
{
qDebug() << "SystemBackupProxy::checkFreeCapacity invoke begin";
// 1、计算待备份数据的大小
qint64 itotalSize = calcSizeForBackup();
m_size = itotalSize;
// 备份过程中会有一些临时文件产生会占用一部分空间故我们预留500M的空间
itotalSize += 500 * MB;
// 2、计算备份分区剩余空间大小
QString backupPath(Utils::getSysRootPath() + BACKUP_PATH);
backupPath.replace("//", "/");
QStorageInfo backupDisk(backupPath);
qint64 freeSize = backupDisk.bytesFree();
// 3、校验空间是否足够
bool result = true;
if (itotalSize > freeSize) {
emit checkResult(int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH));
result = false;
} else {
emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
}
qDebug() << "SystemBackupProxy::checkFreeCapacity invoke end";
return result;
}
/**
* @brief 计算备份所需空间大小
* @return 计算备份所需空间大小,单位字节
*/
qint64 SystemBackupProxy::calcSizeForBackup()
{
QString destPath = Utils::getSysRootPath();
QStringList args;
if (m_backupWrapper.m_bIncrement) {
if (m_backupWrapper.m_uuid.isEmpty()) {
// 新增增量备份点场景
args = getRsyncArgs(SystemBackupScene::TRY_INC_SYSTEM_BACKUP);
destPath += CHECK_PATH;
} else {
// 在原来的备份点上增量备份场景
args = getRsyncArgs(SystemBackupScene::TRY_INC_SYSTEM_BACKUP_AT_BASE);
destPath += BACKUP_SNAPSHOTS_PATH;
destPath += "/";
destPath += m_backupWrapper.m_uuid;
destPath += "/data/";
}
} else {
// 全量备份场景
args = getRsyncArgs(SystemBackupScene::TRY_SYSTEM_BACKUP);
destPath += CHECK_PATH;
}
// 拼接备份源路径和目标路径
QString srcPath = Utils::getSysRootPath();
srcPath += "/";
srcPath.replace("//", "/");
args << srcPath;
destPath.replace("//", "/");
args << destPath;
Utils::mkpath(destPath);
CalcBackupSize calcator;
return calcator.start(args);
}
/**
* @brief 根据场景获取rsync命令参数
* @param scene场景
* @return rsync的参数信息
*/
QStringList SystemBackupProxy::getRsyncArgs(SystemBackupScene scene)
{
QStringList args;
switch (scene) {
case SystemBackupScene::SYSTEM_BACKUP :
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
break ;
case SystemBackupScene::INC_SYSTEM_BACKUP :
args << "-avAXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << QString("--link-dest=../../%1/data").arg(m_backupWrapper.m_baseUuid);
break ;
case SystemBackupScene::INC_SYSTEM_BACKUP_AT_BASE :
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
break ;
case SystemBackupScene::TRY_SYSTEM_BACKUP :
args << "-aAHXrn";
args << "--stats";
args << "--ignore-missing-args";
break ;
case SystemBackupScene::TRY_INC_SYSTEM_BACKUP :
args << "-aAXrn";
args << "--stats";
args << "--ignore-missing-args";
args << QString("--link-dest=../../%1/data").arg(m_backupWrapper.m_baseUuid);
break ;
case SystemBackupScene::TRY_INC_SYSTEM_BACKUP_AT_BASE :
args << "-aAHXrn";
args << "--stats";
args << "--ignore-missing-args";
args << "--delete";
break ;
case SystemBackupScene::EFI_BACKUP :
args << "-avAHXr";
args << "--info=progress2";
args << "--ignore-missing-args";
break ;
default:
return args;
}
if (SystemBackupScene::EFI_BACKUP != scene) {
// --exclude=排除路径设置
for (const QString & item : m_backupWrapper.m_backupExcludePaths) {
args << QString("--exclude=%1").arg(item);
}
}
// 系统更新备份不再备份用户数据目录
if (AUTO_BACKUP_UUID == m_curUuid) {
if (Utils::isHuawei990()) {
args << "/data";
} else {
args << "/data/usershare";
}
args << "/home";
args << "/data/home";
args << "/root";
args << "/data/root";
}
return args;
}
/**
* @brief 备份
*/
void SystemBackupProxy::doBackup()
{
qDebug() << "SystemBackupProxy::doBackup invoke begin";
// 准备
if (!doPrepare())
return ;
// 启动备份efi, 修改为和其它目录统一备份,不再单独进行备份
// if (!backupEfi()) {
// emit checkResult(int(BackupResult::EFI_RSYNC_FAIL));
// return ;
// }
// 启动系统备份
backupSystem();
qDebug() << "SystemBackupProxy::doBackup invoke end";
}
/**
* @brief 备份准备
* @return true,准备成功false准备失败
*/
bool SystemBackupProxy::doPrepare()
{
qDebug() << "SystemBackupProxy::doPrepare invoke begin";
m_bSuccess = false;
// 1、设置当前备份的Uuid
if (m_backupWrapper.m_uuid.isEmpty()) {
// 新增备份点不指定uuid的场景
m_curUuid += Utils::createUuid();
} else {
// 指定uuid备份的场景
m_curUuid = m_backupWrapper.m_uuid;
}
// 2、准备备份目录及文件
m_destPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/data";
m_destPath.replace("//", "/");
if (!Utils::mkpath(m_destPath)) {
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
qCritical() << QString("mkdir %1 failed !").arg(m_destPath) ;
return false;
}
QString userFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + PATHS_USER_FILE;
userFile.replace("//", "/");
if (!Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) {
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
qCritical() << QString("create file %1 failed !").arg(userFile) ;
return false;
}
QString excludeUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + EXCLUDE_PATHS_USER_FILE;
excludeUserFile.replace("//", "/");
if (!Utils::writeFileByLines(excludeUserFile, m_backupWrapper.m_backupExcludePaths)) {
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
qCritical() << QString("create file %1 failed !").arg(excludeUserFile) ;
return false;
}
// 3、记录/backup/snapshots/backuplist.xml文件
if (!recordBackupPoint()) {
qCritical() << "add or update item to backuplist.xml failed !";
return false;
}
qDebug() << "SystemBackupProxy::doPrepare invoke end";
return true;
}
/**
* @brief 记录/backup/snapshots/backuplist.xml文件
* @return true-成功false-失败
*/
bool SystemBackupProxy::recordBackupPoint()
{
m_backupPoint.m_backupName = m_backupWrapper.m_backupName;
m_backupPoint.m_uuid = m_curUuid;
m_backupPoint.m_iPosition = m_backupWrapper.m_iPosition;
m_backupPoint.m_type = m_backupWrapper.m_type;
m_backupPoint.m_size = Utils::StringBySize(m_size);
m_backupPoint.m_time = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss");
m_backupPoint.m_state = BACKUP_PARSE_STATE_FAIL_STRTING;
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
if (m_backupWrapper.m_uuid.isEmpty() || !m_backupWrapper.m_bIncrement) {
if (parse.addItem(m_backupPoint) != ParseBackupList::SUCCESS) {
emit checkResult(int(BackupResult::WRITE_STORAGEINFO_ADD_ITEM_FAIL));
return false;
}
} else {
if (parse.updateItem(m_backupPoint) != ParseBackupList::SUCCESS) {
emit checkResult(int(BackupResult::WRITE_STORAGEINFO_UPDATE_ITEM_FAIL));
return false;
}
}
return true;
}
/**
* @brief 备份/boot/efi
* @return true备份成功false备份失败
*/
bool SystemBackupProxy::backupEfi()
{
qDebug() << "SystemBackupProxy::backupEfi invoke begin";
// /boot/efi分区是自动挂载的这里不用去挂载
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
efiPath.replace("//", "/");
QStringList args;
if (Utils::isDirExist(efiPath)) {
args = getRsyncArgs(SystemBackupScene::EFI_BACKUP);
}
args << efiPath;
QString destPath = m_destPath + "/boot/efi";
destPath.replace("//", "/");
Utils::mkpath(destPath);
args << destPath;
m_p = new RsyncPathToDirProcess(this);
bool result = m_p->start(args);
delete m_p;
m_p = nullptr;
qDebug() << "SystemBackupProxy::backupEfi invoke end";
return result;
}
/**
* @brief 备份系统
* @return true备份成功false备份失败
*/
bool SystemBackupProxy::backupSystem()
{
qDebug() << "SystemBackupProxy::backupSystem invoke begin";
QStringList args;
if (m_backupWrapper.m_bIncrement) {
if (m_backupWrapper.m_uuid.isEmpty()) {
// 新增增量备份点场景
args = getRsyncArgs(SystemBackupScene::INC_SYSTEM_BACKUP);
} else {
// 在原来的备份点上增量备份场景
args = getRsyncArgs(SystemBackupScene::INC_SYSTEM_BACKUP_AT_BASE);
}
} else {
// 全量备份场景
args = getRsyncArgs(SystemBackupScene::SYSTEM_BACKUP);
}
// 拼接备份源路径和目标路径
QString srcPath = Utils::getSysRootPath();
srcPath += "/";
srcPath.replace("//", "/");
args << srcPath;
QString destPath = m_destPath + "/";
destPath.replace("//", "/");
args << destPath;
m_p = new RsyncPathToDirProcess(this);
connect(m_p, &RsyncPathToDirProcess::progress, this, &SystemBackupProxy::progress);
connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool result) {
if (result) {
m_backupPoint.m_state = BACKUP_PARSE_STATE_SUCCESS_STRTING;
m_backupPoint.m_size = Utils::StringBySize(Utils::getDirOrFileSize(m_destPath));
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
parse.updateItem(m_backupPoint);
Utils::writeBackupLog(m_backupPoint.m_time + ","
+ m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ","
+ m_backupWrapper.m_note + "," + m_backupPoint.m_size);
Utils::update_backup_unique_settings(m_curUuid, m_backupPoint.m_backupName);
m_bSuccess = true;
}
emit this->workResult(result);
});
m_p->start(args, false);
do_kylin_security(m_destPath);
qDebug() << "SystemBackupProxy::backupSystem invoke end";
return true;
}
void SystemBackupProxy::do_kylin_security(const QString& dstDir)
{
int ret = 0;
ret = kysec_getstatus();
if (ret > 0) {
QString seFilePath(dstDir + "/.exectl");
QFile file(seFilePath);
file.open(QIODevice::WriteOnly);
file.close();
}
}