10237 【备份还原】增加可自定义路径

This commit is contained in:
zhaominyong 2022-04-26 16:06:54 +08:00
parent d1e9b967df
commit b0952490c2
42 changed files with 2328 additions and 898 deletions

View File

@ -31,7 +31,10 @@ HEADERS += \
../common/spinlock_mutex.h \
../common/utils.h \
backupmanager_adaptor.h \
customizedatabackupproxy.h \
customizeghostImageproxy.h \
customizesystembackupproxy.h \
customizesystemrestoreproxy.h \
databackupproxy.h \
datarestoreproxy.h \
deletebackupproxy.h \
@ -60,7 +63,10 @@ SOURCES += \
../common/reflect.cpp \
../common/utils.cpp \
backupmanager_adaptor.cpp \
customizedatabackupproxy.cpp \
customizeghostImageproxy.cpp \
customizesystembackupproxy.cpp \
customizesystemrestoreproxy.cpp \
databackupproxy.cpp \
datarestoreproxy.cpp \
deletebackupproxy.cpp \

View File

@ -0,0 +1,461 @@
#include "customizedatabackupproxy.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(CustomizeDataBackupProxy)
CustomizeDataBackupProxy::CustomizeDataBackupProxy()
{
m_isOnlyCheck = true;
m_bSuccess = false;
m_isFinished = false;
m_p = nullptr;
m_size = 0;
m_calc = new CalcBackupSize(this);
connect(this, &CustomizeDataBackupProxy::cancel, this, &CustomizeDataBackupProxy::cancelEx);
}
CustomizeDataBackupProxy::~CustomizeDataBackupProxy()
{
delete m_p;
m_p = nullptr;
delete m_calc;
m_calc = nullptr;
}
/**
* @brief
* @return false,;true,
*/
bool CustomizeDataBackupProxy::checkEnvEx()
{
qDebug() << "CustomizeDataBackupProxy::checkEnv invoke begin";
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备都得保证/backup挂载上); 若没挂载,挂载
MyMountProxy mountProxy;
MountResult result = mountProxy.mountBackupPartition();
// 无备份分区
if (MountResult::CANNOT_GET_BACKUPUUID == result) {
qInfo() << "There is no backup partition!";
QString snapshotsPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
snapshotsPath.replace("//", "/");
Utils::mkpath(snapshotsPath);
Utils::generateExcludePathsFile();
} else if (MountResult::MOUNTED != result) {
emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL));
return false;
}
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
Utils::mkpath(m_backupWrapper.m_prefixDestPath);
}
// 2、判断备份是否增量备份
isIncBackup();
// 3、检测空间是否满足备份
calcSizeForBackup();
qDebug() << "CustomizeDataBackupProxy::checkEnv invoke end";
return true;
}
/**
* @brief
*/
void CustomizeDataBackupProxy::doWorkEx()
{
qDebug() << "CustomizeDataBackupProxy::doWorkEx invoke begin";
m_isOnlyCheck = false;
// 环境检测
checkEnvEx();
qDebug() << "CustomizeDataBackupProxy::doWorkEx invoke end";
}
/**
* @brief
*/
void CustomizeDataBackupProxy::cancelEx()
{
m_bCancel = true;
if (!m_isFinished) {
emit this->checkResult(int(BackupResult::START_CANCEL));
if (m_calc)
m_calc->stop();
if (m_p)
m_p->stop();
QProcess::execute("sync");
Utils::wait(5);
deleteFailedData();
emit this->checkResult(int(BackupResult::CANCEL_SUCCESS));
}
}
/**
* @brief
*/
void CustomizeDataBackupProxy::deleteFailedData()
{
if (m_curUuid.isEmpty())
return;
// 1、删除备份目录
QString destPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid;
destPath.replace("//", "/");
QStringList args;
args << "-rf";
args << destPath;
QProcess::execute("rm", args);
// 2、删除xml文件中的备份项
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
parse.deleteItem(m_curUuid);
}
/**
* @brief
* @return true, false
*/
bool CustomizeDataBackupProxy::isIncBackup()
{
QString backupPath;
ParseBackupList::BackupPoint point;
if (m_backupWrapper.m_uuid.isEmpty()) {
return false;
} else {
backupPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
}
backupPath.replace("//", "/");
if (Utils::isDirExist(backupPath)) {
m_backupWrapper.m_bIncrement = true;
m_backupWrapper.m_type = BackupType::INC_BACKUP_DATA;
return true;
}
return false;
}
/**
* @brief
*/
bool CustomizeDataBackupProxy::checkFreeCapacity(qint64 itotalSize)
{
qDebug() << "CustomizeDataBackupProxy::checkFreeCapacity invoke begin";
// 如果是取消了操作,则不再发送其它信息
if (m_bCancel)
return false;
// 1、计算待备份数据的大小
m_size = itotalSize;
// 备份过程中会有一些临时文件产生会占用一部分空间故我们预留5M的空间
itotalSize += 5 * MB;
// 2、计算备份分区剩余空间大小
QString backupPath(m_backupWrapper.m_prefixDestPath);
backupPath.replace("//", "/");
QStorageInfo backupDisk(backupPath);
qint64 freeSize = backupDisk.bytesAvailable();
// 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));
}
if (m_isOnlyCheck)
return result;
// 开始备份
doBackup();
qDebug() << "CustomizeDataBackupProxy::checkFreeCapacity invoke end";
return result;
}
/**
* @brief
* @return ,
*/
void CustomizeDataBackupProxy::calcSizeForBackup()
{
QString destPath = Utils::getSysRootPath();
QStringList args;
if (m_backupWrapper.m_bIncrement) {
// 在原来的备份点上增量备份场景
args = getRsyncArgs(CustomizeDataBackupScene::TRY_INC_DATA_BACKUP);
destPath = m_backupWrapper.m_prefixDestPath;
destPath += BACKUP_SNAPSHOTS_PATH;
destPath += "/";
destPath += m_backupWrapper.m_uuid;
destPath += "/data/";
} else {
// 全量备份场景
args = getRsyncArgs(CustomizeDataBackupScene::TRY_DATA_BACKUP);
destPath += CHECK_PATH;
}
// 拼接备份源路径和目标路径
QString srcPath = Utils::getSysRootPath();
srcPath += "/";
srcPath.replace("//", "/");
args << srcPath;
destPath.replace("//", "/");
args << destPath;
Utils::mkpath(destPath);
connect(m_calc, &CalcBackupSize::finished, this, &CustomizeDataBackupProxy::checkFreeCapacity);
m_calc->start(args, false);
}
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList CustomizeDataBackupProxy::getRsyncArgs(CustomizeDataBackupScene scene)
{
QStringList args;
QString backupFile = "/tmp/.backup.user";
Utils::writeFileByLines(backupFile, m_backupWrapper.m_backupPaths);
switch (scene) {
case CustomizeDataBackupScene::DATA_BACKUP :
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
args << "--files-from" << backupFile;
break ;
case CustomizeDataBackupScene::INC_DATA_BACKUP :
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
args << "--files-from" << backupFile;
break ;
case CustomizeDataBackupScene::TRY_DATA_BACKUP :
args << "-aAHXrn";
args << "--stats";
args << "--ignore-missing-args";
args << "--files-from" << backupFile;
break ;
case CustomizeDataBackupScene::TRY_INC_DATA_BACKUP :
args << "-aAHXrn";
args << "--stats";
args << "--ignore-missing-args";
args << "--delete";
args << "--files-from" << backupFile;
break ;
default:
return args;
}
return args;
}
/**
* @brief
*/
void CustomizeDataBackupProxy::doBackup()
{
qDebug() << "CustomizeDataBackupProxy::doBackup invoke begin";
// 准备
if (!doPrepare())
return ;
// 启动数据备份
backupData();
qDebug() << "CustomizeDataBackupProxy::doBackup invoke end";
}
/**
* @brief
* @return true,false
*/
bool CustomizeDataBackupProxy::doPrepare()
{
qDebug() << "CustomizeDataBackupProxy::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 = m_backupWrapper.m_prefixDestPath + 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;
}
m_userFile = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + PATHS_USER_FILE;
m_userFile.replace("//", "/");
if (!Utils::writeFileByLines(m_userFile, m_backupWrapper.m_backupPaths)) {
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
qCritical() << QString("create file %1 failed !").arg(m_userFile) ;
return false;
}
m_excludeUserFile = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + EXCLUDE_PATHS_USER_FILE;
m_excludeUserFile.replace("//", "/");
if (!Utils::writeFileByLines(m_excludeUserFile, m_backupWrapper.m_backupExcludePaths)) {
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
qCritical() << QString("create file %1 failed !").arg(m_excludeUserFile) ;
return false;
}
// 3、记录/backup/snapshots/backuplist.xml文件
if (!recordBackupPoint()) {
qCritical() << "add or update item to backuplist.xml failed !";
return false;
}
qDebug() << "CustomizeDataBackupProxy::doPrepare invoke end";
return true;
}
/**
* @brief /backup/snapshots/backuplist.xml文件
* @return true-false-
*/
bool CustomizeDataBackupProxy::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;
if (0 < m_backupWrapper.m_frontUid)
m_backupPoint.m_userId = QString::number(m_backupWrapper.m_frontUid);
m_backupPoint.m_os = SystemInfo::m_os;
m_backupPoint.m_arch = SystemInfo::m_arch;
m_backupPoint.m_archdetect = SystemInfo::m_archDetect;
m_backupPoint.m_path = m_backupWrapper.m_prefixDestPath;
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
if (m_backupWrapper.m_bIncrement) {
if (parse.updateItem(m_backupPoint) != ParseBackupList::SUCCESS) {
emit checkResult(int(BackupResult::WRITE_STORAGEINFO_UPDATE_ITEM_FAIL));
return false;
}
} else {
if (parse.addItem(m_backupPoint) != ParseBackupList::SUCCESS) {
emit checkResult(int(BackupResult::WRITE_STORAGEINFO_ADD_ITEM_FAIL));
return false;
}
}
return true;
}
/**
* @brief
* @return truefalse
*/
bool CustomizeDataBackupProxy::backupData()
{
qDebug() << "CustomizeDataBackupProxy::backupData invoke begin";
QStringList args;
if (m_backupWrapper.m_bIncrement) {
// 在原来的备份点上增量备份场景
args = getRsyncArgs(CustomizeDataBackupScene::INC_DATA_BACKUP);
} else {
// 全量备份场景
args = getRsyncArgs(CustomizeDataBackupScene::DATA_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, &CustomizeDataBackupProxy::progress);
connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool result) {
// 如果是取消了操作,则不再发送其它信息
if (m_bCancel)
return ;
m_isFinished = true;
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(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ","+ m_backupWrapper.m_note + "," + m_backupPoint.m_size+ "," + QString::number(m_backupWrapper.m_frontUid));
Utils::writeBackupLog(m_backupPoint.m_time + ","
+ m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ","
+ m_backupWrapper.m_note + "," + m_backupPoint.m_size
+ "," + QString::number(m_backupWrapper.m_frontUid)
+ "," + m_backupWrapper.m_backupName);
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() << "CustomizeDataBackupProxy::backupData invoke end";
return true;
}
void CustomizeDataBackupProxy::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();
}
}

View File

@ -0,0 +1,99 @@
#ifndef CUSTOMIZEDATABACKUPPROXY_H
#define CUSTOMIZEDATABACKUPPROXY_H
#include "workerfactory.h"
#include "myprocess/calcbackupsize.h"
#include "myprocess/rsyncpathtodirprocess.h"
#include "parsebackuplist.h"
class CustomizeDataBackupProxy : public Worker
{
Q_OBJECT
DECLARE_DYNCREATE(CustomizeDataBackupProxy)
public:
// 系统备份的几种场景
enum CustomizeDataBackupScene {
DATA_BACKUP, // 系统备份
INC_DATA_BACKUP, // 增量系统备份
TRY_DATA_BACKUP, // 测试系统备份,可用于计算备份传输数据大小
TRY_INC_DATA_BACKUP, // 测试增量系统备份,可用于计算备份传输数据大小
};
explicit CustomizeDataBackupProxy();
virtual ~CustomizeDataBackupProxy();
public:
// 环境检测
virtual bool checkEnvEx();
// 任务处理
virtual void doWorkEx();
public slots:
// 任务取消
virtual void cancelEx();
private slots:
// 校验剩余空间是否满足备份
bool checkFreeCapacity(qint64 itotalSize);
// 备份
void doBackup();
private:
// 计算备份所需空间大小
void calcSizeForBackup();
/**
* @brief /backup/snapshots/backuplist.xml文件
* @return true-false-
*/
bool recordBackupPoint();
// 备份准备
bool doPrepare();
// 备份系统
bool backupData();
protected:
// 判断是否增量备份
bool isIncBackup();
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList getRsyncArgs(CustomizeDataBackupScene scene);
void do_kylin_security(const QString& dstDir);
// 失败则删除相应数据
virtual void deleteFailedData();
// 计算备份空间大小的进程
CalcBackupSize *m_calc;
// 是否只是检测
bool m_isOnlyCheck;
// 是否完成
bool m_isFinished;
// 是否成功
bool m_bSuccess;
// 当前备份uuid
QString m_curUuid;
// 当前备份目标目录
QString m_destPath;
// 当前备份所需空间大小
qint64 m_size;
// 备份点用户备份路径文件
QString m_userFile;
// 备份点排除备份路径文件
QString m_excludeUserFile;
// 备份进程
RsyncPathToDirProcess *m_p;
// 当前备份节点
ParseBackupList::BackupPoint m_backupPoint;
};
#endif // CUSTOMIZEDATABACKUPPROXY_H

View File

@ -0,0 +1,225 @@
#include "customizeghostImageproxy.h"
#include <QStorageInfo>
#include <QFileInfo>
#include <QDateTime>
#include <QTimer>
#include <QDebug>
#include <kysec/status.h>
#include <unistd.h>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
#include "myprocess/calcbackupsize.h"
IMPLEMENT_DYNCREATE(CustomizeGhostImageProxy)
CustomizeGhostImageProxy::CustomizeGhostImageProxy()
{
m_p = nullptr;
m_bSuccess = false;
m_isFinished = false;
m_isForce = false;
connect(this, &CustomizeGhostImageProxy::cancel, this, &CustomizeGhostImageProxy::cancelEx);
}
CustomizeGhostImageProxy::~CustomizeGhostImageProxy()
{
// 不成功则删除中间文件
if (!m_bSuccess) {
deleteFailedData();
}
}
/**
* @brief
*/
bool CustomizeGhostImageProxy::checkEnvEx()
{
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备都得保证/backup挂载上); 若没挂载,挂载
MyMountProxy mountProxy;
MountResult result = mountProxy.mountBackupPartition();
// 无备份分区
if (MountResult::CANNOT_GET_BACKUPUUID == result) {
qInfo() << "There is no backup partition!";
QString snapshotsPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
snapshotsPath.replace("//", "/");
Utils::mkpath(snapshotsPath);
Utils::generateExcludePathsFile();
} else if (MountResult::MOUNTED != result) {
emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL));
return false;
}
// 2、校验backuppoint.xml中相应的备份节点是否存在
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList xmlParse(xmlPath);
m_backupPoint = xmlParse.findBackupPointByUuid(m_backupWrapper.m_uuid);
if (m_backupPoint.m_backupName.isEmpty()) {
emit checkResult(int(BackupResult::GHOST_CANNOT_FIND_BACKUPPOINT));
return false;
}
// 3、校验备份数据是否存在
m_srcPath = m_backupPoint.m_path + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
m_srcPath.replace("//", "/");
if (Utils::isDirEmpty(m_srcPath)) {
emit checkResult(int(BackupResult::GHOST_SRC_DIRECTORY_IS_NOT_EXIST));
return false;
}
m_imgDst = m_srcPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
if (!Utils::filsExists(m_imgDst)) {
emit checkResult(int(BackupResult::GHOST_SRC_DIRECTORY_IS_NOT_EXIST));
return false;
}
// 4、校验空间是否充足
QFileInfo backup(m_srcPath);
qint64 itotalSize = backup.size();
m_destPath = m_backupWrapper.m_prefixDestPath + GHOST_PATH;
m_destPath.replace("//", "/");
Utils::mkpath(m_destPath);
m_kyimg = m_destPath + "/" + m_backupWrapper.m_backupName;
m_kyimg.replace("//", "/");
QFile kyimg(m_kyimg);
if (kyimg.exists())
kyimg.remove();
QStorageInfo storageInfo(m_destPath);
qint64 sizeAvailable = storageInfo.bytesAvailable();
if (sizeAvailable <= itotalSize) {
emit checkResult(int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH));
return false;
}
emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
return true;
}
/**
* @brief
*/
void CustomizeGhostImageProxy::doWorkEx()
{
if (!checkEnvEx())
return ;
doGhostImage();
}
/**
* @brief
*/
void CustomizeGhostImageProxy::cancelEx()
{
m_bCancel = true;
if (!m_isFinished) {
emit this->checkResult(int(BackupResult::START_CANCEL));
if (m_p)
m_p->stop();
QProcess::execute("sync");
Utils::wait(5);
deleteFailedData();
emit this->checkResult(int(BackupResult::CANCEL_SUCCESS));
}
}
/**
* @brief
*/
void CustomizeGhostImageProxy::deleteFailedData()
{
// 1、删除临时镜像文件
QFile kyimg(m_destPath + "/" + UDISK_MKSQUASHFS_IMG_NAME);
if (kyimg.exists())
kyimg.remove();
// 2、删除目标镜像文件
if (!m_kyimg.isEmpty()) {
QFile kyimgDest(m_kyimg);
if (kyimgDest.exists())
kyimgDest.remove();
}
}
/**
* @brief ghost镜像
*/
void CustomizeGhostImageProxy::doGhostImage()
{
// 同步到U盘
m_p = new RsyncPathToDirProcess(this);
connect(m_p, &RsyncPathToDirProcess::progress, this, &CustomizeGhostImageProxy::progress);
connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool resultRsync) {
// 如果是取消了操作,则不再发送其它信息
if (m_bCancel)
return ;
m_isForce = false;
m_isFinished = true;
if (resultRsync) {
// 文件更名
QString imgFileName = m_destPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
if (Utils::filsExists(imgFileName)) {
QStringList args;
args << imgFileName;
args << m_kyimg;
QProcess::execute("mv", args);
chown(m_kyimg.toLocal8Bit().data(), m_backupWrapper.m_frontUid, m_backupWrapper.m_gid);
m_bSuccess = true;
resultRsync = true;
} else {
resultRsync = false;
}
}
emit this->workResult(resultRsync);
});
QStringList arguments;
arguments << "-av";
arguments << "--info=progress2";
arguments << m_imgDst;
arguments << m_destPath + "/";
QTimer::singleShot(1*1000, this, &CustomizeGhostImageProxy::checkDestDirExists);
m_p->start(arguments, false);
}
/**
* @brief
* @return: bool,truefalse
* @author: zhaominyong
* @since: 2021/05/24
* @note:
* add by zhaominyong at 2021/05/24 for bug:54377 U盘的过程中拔出U盘
*/
bool CustomizeGhostImageProxy::checkDestDirExists()
{
if (!m_isFinished)
{
// 拔掉U盘后没有响应的场景怀疑可能是某应用程序关闭引起希望不是dbus服务关掉了
if (m_isForce) {
emit this->workResult(false);
return false;
}
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
if (m_p)
m_p->stop();
// 10s钟后如果还没有退出则强制退出
QTimer::singleShot(10*1000, this, &CustomizeGhostImageProxy::checkDestDirExists);
m_isForce = true;
} else {
QTimer::singleShot(1*1000, this, &CustomizeGhostImageProxy::checkDestDirExists);
}
}
return true;
}

View File

@ -0,0 +1,53 @@
#ifndef CUSTOMIZEGHOSTIMAGEPROXY_H
#define CUSTOMIZEGHOSTIMAGEPROXY_H
#include "workerfactory.h"
#include "myprocess/rsyncpathtodirprocess.h"
#include "parsebackuplist.h"
class CustomizeGhostImageProxy : public Worker
{
Q_OBJECT
DECLARE_DYNCREATE(CustomizeGhostImageProxy)
public:
explicit CustomizeGhostImageProxy();
virtual ~CustomizeGhostImageProxy();
public:
// 环境检测
virtual bool checkEnvEx();
// 任务处理
virtual void doWorkEx();
// 任务取消
virtual void cancelEx();
private:
void doGhostImage();
bool checkDestDirExists();
void deleteFailedData();
ParseBackupList::BackupPoint m_backupPoint;
// 存放.kyimg文件的目录
QString m_destPath;
// .kyimg文件
QString m_kyimg;
// 源文件dst.img文件所在目录
QString m_srcPath;
// dst.img文件
QString m_imgDst;
// 备份进程
RsyncPathToDirProcess *m_p;
// 是否成功
bool m_bSuccess;
// 是否结束
bool m_isFinished;
// 强制结束标志(stop后没反应的情况系统处于睡眠状态)
bool m_isForce;
};
#endif // CUSTOMIZEGHOSTIMAGEPROXY_H

View File

@ -19,7 +19,6 @@ CustomizeSystemBackupProxy::CustomizeSystemBackupProxy()
m_calc = new CalcBackupSize(this);
m_isOnlyCheck = true;
m_mksquashfs = nullptr;
m_isForce = false;
connect(this, &CustomizeSystemBackupProxy::cancel, this, &CustomizeSystemBackupProxy::cancelEx);
}
@ -32,9 +31,10 @@ CustomizeSystemBackupProxy::~CustomizeSystemBackupProxy()
delete m_mksquashfs;
m_mksquashfs = nullptr;
QString rm("rm -rf ");
rm += m_imgPath;
QProcess::execute(rm);
// 如果备份失败,则删除备份数据
if (!m_bSuccess) {
deleteFailedData();
}
}
/**
@ -45,30 +45,26 @@ bool CustomizeSystemBackupProxy::checkEnvEx()
{
qDebug() << "CustomizeSystemBackupProxy::checkEnv invoke begin";
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备都得保证/backup挂载上); 若没挂载,挂载
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备都得保证/backup挂载上); 若没挂载,挂载
MyMountProxy mountProxy;
if ( MountResult::MOUNTED != mountProxy.mountBackupPartition() ) {
MountResult result = mountProxy.mountBackupPartition();
// 无备份分区
if (MountResult::CANNOT_GET_BACKUPUUID == result) {
qInfo() << "There is no backup partition!";
QString snapshotsPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
snapshotsPath.replace("//", "/");
Utils::mkpath(snapshotsPath);
Utils::generateExcludePathsFile();
} else if (MountResult::MOUNTED != result) {
emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL));
return false;
}
QString backupPath(m_backupWrapper.m_prefixDestPath);
backupPath.replace("//", "/");
QStorageInfo udisk(backupPath);
QString udisk_type = udisk.fileSystemType();
if (udisk_type == "vfat") {
qCritical() << m_backupWrapper.m_prefixDestPath + " udisk's filesystemtype is vfat";
emit checkResult(int(BackupResult::UDISK_FILESYSTEM_TYPE_IS_VFAT));
return false;
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
Utils::mkpath(m_backupWrapper.m_prefixDestPath);
}
if (udisk.isReadOnly()) {
// 只读挂载的U盘
qCritical() << QString("udisk(%s) is readonly filesystem").arg(m_backupWrapper.m_prefixDestPath);
emit checkResult(int(BackupResult::UDISK_FILESYSTEM_IS_READONLY));
return false;
}
QTimer::singleShot(1*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
// 2、计算备份大小
calcSizeForBackup();
@ -125,42 +121,12 @@ void CustomizeSystemBackupProxy::deleteFailedData()
QProcess::execute("rm", args);
// 2、删除xml文件中的备份项
QString xmlPath = m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH;
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
parse.deleteItem(m_curUuid);
}
/**
* @brief
* @return true, false
*/
bool CustomizeSystemBackupProxy::isIncBackup()
{
QString backupPath;
ParseBackupList::BackupPoint point;
if (m_backupWrapper.m_uuid.isEmpty()) {
QString xmlPath(m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH);
xmlPath.replace("//", "/");
ParseBackupList parser(xmlPath);
point = parser.getLastSysBackupPoint();
if (point.m_uuid.isEmpty())
return false;
backupPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + point.m_uuid + "/data";
} else {
backupPath = m_backupWrapper.m_prefixDestPath + 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
*/
@ -172,16 +138,12 @@ void CustomizeSystemBackupProxy::checkFreeCapacity(qint64 itotalSize)
if (m_bCancel)
return ;
// 拔掉U盘的场景
if (m_isForce) {
emit this->checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
return ;
}
// 1、计算待备份数据的大小
m_size = itotalSize;
// 备份过程中会有一些临时文件产生会占用一部分空间故我们预留500M的空间
itotalSize += 500 * MB;
// 判断是否需要先压缩成img文件压缩后一般小于原大小的70%
itotalSize = itotalSize * 7 / 10;
// 2、计算备份分区剩余空间大小
QString backupPath(m_backupWrapper.m_prefixDestPath);
@ -199,29 +161,12 @@ void CustomizeSystemBackupProxy::checkFreeCapacity(qint64 itotalSize)
if (m_isOnlyCheck)
return ;
// 4、判断是否需要先压缩成img文件压缩后一般小于原大小的70%
itotalSize = itotalSize * 7 / 10;
QHash<QString, QString> hash = Utils::getLeftSizeOfPartitions();
for (QHash<QString, QString>::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) {
QString path = it.key();
QString size = it.value();
if (size.endsWith("G")) {
size.replace("G", "");
qint64 leftSize = size.toLongLong() * 1000 * 1000 * 1000;
if (itotalSize < leftSize) {
m_imgPath = path + IMGBACKUP_PATH;
m_imgPath.replace("//", "/");
break ;
}
}
}
// 4、准备
if (!doPrepare())
return ;
// 5、开始制作img或开始备份
if (m_imgPath.isEmpty()) {
doBackup();
} else {
// 5、开始制作img
doMksqushfs();
}
qDebug() << "CustomizeSystemBackupProxy::checkFreeCapacity invoke end";
}
@ -260,12 +205,6 @@ QStringList CustomizeSystemBackupProxy::getRsyncArgs(CustomizeSystemBackupScene
QStringList excludes;
switch (scene) {
case CustomizeSystemBackupScene::SYSTEM_BACKUP :
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
break ;
case CustomizeSystemBackupScene::TRY_SYSTEM_BACKUP :
args << "-aAHXrn";
args << "--stats";
@ -283,7 +222,6 @@ QStringList CustomizeSystemBackupProxy::getRsyncArgs(CustomizeSystemBackupScene
args << "-e" << item;
}
args << "-e" << m_imgPath;
return args;
default:
return args;
@ -311,26 +249,40 @@ void CustomizeSystemBackupProxy::doMksqushfs()
if (m_bCancel)
return ;
if (result && !m_isForce) {
// 开始备份
doBackup();
} else {
m_isFinished = true;
emit checkResult(int(BackupResult::MKSQUASHFS_DO_FAIL));
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);
if (ParseBackupList::ParseResult::SUCCESS != parse.updateItem(m_backupPoint)) {
qCritical() << "update backuplist.xml error in sendBackupResult";
result = false;
} else {
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ","+ m_backupWrapper.m_note + "," + m_backupPoint.m_size+ "," + QString::number(m_backupWrapper.m_frontUid));
Utils::writeBackupLog(m_backupPoint.m_time + ","
+ m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ","
+ m_backupWrapper.m_note + "," + m_backupPoint.m_size
+ ",," + m_backupWrapper.m_backupName);
Utils::update_backup_unique_settings(m_curUuid, m_backupPoint.m_backupName);
m_bSuccess = true;
}
}
emit this->workResult(result);
});
Utils::mkpath(m_imgPath);
QString srcPath = Utils::getSysRootPath();
srcPath += "/";
srcPath.replace("//", "/");
QString dstImg = m_imgPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
QString dstImg = m_destPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
QStringList args;
args << srcPath << dstImg;
args.append(getRsyncArgs(CustomizeSystemBackupScene::MKSQUASHFS));
if (m_mksquashfs->start(args)) {
emit checkResult(int(BackupResult::MKSQUASHFS_START_SUCCESS));
do_kylin_security(m_destPath);
} else {
emit checkResult(int(BackupResult::MKSQUASHFS_DO_FAIL));
}
@ -338,35 +290,6 @@ void CustomizeSystemBackupProxy::doMksqushfs()
qDebug() << "CustomizeSystemBackupProxy::doMksqushfs invoke end";
}
/**
* @brief
*/
void CustomizeSystemBackupProxy::doBackup()
{
qDebug() << "CustomizeSystemBackupProxy::doBackup invoke begin";
// 准备
if (!doPrepare())
return ;
// 启动备份efi, 修改为和其它目录统一备份,不再单独进行备份
// if (!backupEfi()) {
// emit checkResult(int(BackupResult::EFI_RSYNC_FAIL));
// return ;
// }
if (m_imgPath.isEmpty()) {
// 启动系统备份
backupSystem();
} else {
// 备份img文件
backupImg();
}
qDebug() << "CustomizeSystemBackupProxy::doBackup invoke end";
}
/**
* @brief
* @return true,false
@ -431,82 +354,18 @@ bool CustomizeSystemBackupProxy::recordBackupPoint()
m_backupPoint.m_os = SystemInfo::m_os;
m_backupPoint.m_arch = SystemInfo::m_arch;
m_backupPoint.m_archdetect = SystemInfo::m_archDetect;
QString xmlPath = m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH;
m_backupPoint.m_path = m_backupWrapper.m_prefixDestPath;
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
* @return truefalse
*/
bool CustomizeSystemBackupProxy::backupSystem()
{
qDebug() << "CustomizeSystemBackupProxy::backupSystem invoke begin";
// 全量备份场景
QStringList args = getRsyncArgs(CustomizeSystemBackupScene::SYSTEM_BACKUP);
// 拼接备份源路径和目标路径
QString srcPath = Utils::getSysRootPath();
srcPath += "/";
srcPath.replace("//", "/");
args << srcPath;
QString destPath = m_destPath + "/";
destPath.replace("//", "/");
args << destPath;
return backup(args);
}
/**
* @brief img文件
* @return truefalse
*/
bool CustomizeSystemBackupProxy::backupImg()
{
qDebug() << "CustomizeSystemBackupProxy::backupImg invoke";
QStringList args;
QString srcPath = m_imgPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
QString destPath = m_destPath + "/";
destPath.replace("//", "/");
args << srcPath << destPath;
return backup(args);
}
/**
* @brief
* @param args
* @return truefalse
*/
bool CustomizeSystemBackupProxy::backup(const QStringList &args)
{
qDebug() << "CustomizeSystemBackupProxy::backup invoke begin";
emit checkResult(int(BackupResult::BACKUP_START_SUCCESS));
do_kylin_security(m_destPath);
qDebug() << "CustomizeSystemBackupProxy::backup invoke end";
return true;
}
void CustomizeSystemBackupProxy::do_kylin_security(const QString& dstDir)
{
int ret = 0;
@ -519,38 +378,3 @@ void CustomizeSystemBackupProxy::do_kylin_security(const QString& dstDir)
}
}
/**
* @brief
* @return: bool,truefalse
* @author: zhaominyong
* @since: 2021/05/24
* @note:
* add by zhaominyong at 2021/05/24 for bug:54377 U盘的过程中拔出U盘
*/
bool CustomizeSystemBackupProxy::checkDestDirExists()
{
if (!m_isFinished)
{
// 拔掉U盘后没有响应的场景怀疑可能是某应用程序关闭引起希望不是dbus服务关掉了
if (m_isForce) {
emit this->workResult(false);
return false;
}
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
m_isForce = true;
if (m_calc != nullptr)
m_calc->stop();
if (m_mksquashfs != nullptr)
m_mksquashfs->stop();
// 10s钟后如果还没有退出则强制退出
QTimer::singleShot(10*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
} else {
QTimer::singleShot(1*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
}
}
return true;
}

View File

@ -14,7 +14,6 @@ class CustomizeSystemBackupProxy : public Worker
public:
// 系统备份的几种场景
enum CustomizeSystemBackupScene {
SYSTEM_BACKUP, // 系统备份
TRY_SYSTEM_BACKUP, // 测试系统备份,可用于计算备份传输数据大小
MKSQUASHFS, // 生成img文件
};
@ -38,26 +37,10 @@ private slots:
// mksqushfs
void doMksqushfs();
// 备份
void doBackup();
// 任务取消
virtual void cancelEx();
/**
* @brief
* @return: bool,truefalse
* @author: zhaominyong
* @since: 2021/05/24
* @note:
* add by zhaominyong at 2021/05/24 for bug:54377 U盘的过程中拔出U盘
*/
bool checkDestDirExists();
private:
// 判断是否增量备份
bool isIncBackup();
// 计算备份所需空间大小
void calcSizeForBackup();
@ -77,12 +60,6 @@ private:
// 备份准备
bool doPrepare();
// 备份系统
bool backupSystem();
// 备份img文件
bool backupImg();
bool backup(const QStringList &args);
void do_kylin_security(const QString& dstDir);
@ -109,10 +86,6 @@ private:
ParseBackupList::BackupPoint m_backupPoint;
// 是否只是检测
bool m_isOnlyCheck;
// img文件存放路径
QString m_imgPath;
// 强制结束标志(stop后没反应的情况系统处于睡眠状态)
bool m_isForce;
};
#endif // CUSTOMIZESYSTEMBACKUPPROXY_H

View File

@ -0,0 +1,315 @@
#include "customizesystemrestoreproxy.h"
#include <QDateTime>
#include <QDir>
#include <QDebug>
#include <unistd.h>
#include <sys/reboot.h>
#include "../common/utils.h"
#include "mymountproxy.h"
IMPLEMENT_DYNCREATE(CustomizeSystemRestoreProxy)
/**
* @brief
*/
CustomizeSystemRestoreProxy::CustomizeSystemRestoreProxy()
{
m_bSuccess = false;
m_p = nullptr;
}
/**
* @brief
*/
CustomizeSystemRestoreProxy::~CustomizeSystemRestoreProxy()
{
delete m_p;
}
/**
* @brief
* @return false,;true,
*/
bool CustomizeSystemRestoreProxy::checkEnvEx()
{
qDebug() << "CustomizeSystemRestoreProxy::checkEnvEx invoke begin";
// 1、检测xml中的还原点是否还存在
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
m_backupPoint = parse.findBackupPointByUuid(m_backupWrapper.m_uuid);
if (m_backupPoint.m_uuid.isEmpty()) {
qCritical("xml中还原点不存在");
emit checkResult(int(BackupResult::INC_NOT_FOUND_DIR));
return false;
}
// 2、检测.user.txt是否存在
m_userFile = m_backupPoint.m_path + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + PATHS_USER_FILE;
m_userFile.replace("//", "/");
if (!Utils::filsExists(m_userFile)) {
qCritical(".user.txt文件不存在");
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
return false;
}
// 3、检测.exclude.user.txt是否存在
m_excludeUserFile = m_backupPoint.m_path + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + EXCLUDE_PATHS_USER_FILE;
m_excludeUserFile.replace("//", "/");
if (!Utils::filsExists(m_excludeUserFile)) {
qCritical(".exclude.user.txt文件不存在");
emit checkResult(int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED));
return false;
}
// 4、检测还原点是否存在
m_backupPath = m_backupPoint.m_path + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
m_backupPath.replace("//", "/");
if (Utils::isDirEmpty(m_backupPath)) {
qCritical("还原点{uuid}/data目录不存在");
emit checkResult(int(BackupResult::INC_NOT_FOUND_DIR));
return false;
}
m_imgFileName = m_backupPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
if (!Utils::filsExists(m_imgFileName)) {
qCritical("还原点{uuid}/data/dst.img文件不存在");
emit checkResult(int(BackupResult::INC_NOT_FOUND_DIR));
return false;
}
m_curUuid = m_backupWrapper.m_uuid;
emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
qDebug() << "CustomizeSystemRestoreProxy::checkEnvEx invoke end";
return true;
}
/**
* @brief
*/
void CustomizeSystemRestoreProxy::doWorkEx()
{
qDebug() << "CustomizeSystemRestoreProxy::doWorkEx invoke begin";
// 1、校验
if (!checkEnvEx())
return ;
// 2、还原系统
restoreSystem();
qDebug() << "CustomizeSystemRestoreProxy::doWorkEx invoke end";
}
/**
* @brief
* @return true,false
*/
bool CustomizeSystemRestoreProxy::doPrepare()
{
qDebug() << "CustomizeSystemRestoreProxy::doPrepare invoke begin";
// 1、dst.img文件需要挂载到目录
if (!mountImg())
return false;
// 2、停止安全防护
QProcess::execute("systemctl stop kysec-init.service");
// 3、以读写方式重新挂载boot分区因为有的机器默认以只读挂载
remountBoot();
// 4、是否有/boot/efi目录有则认为有efi分区需重新rw挂载
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
efiPath.replace("//", "/");
if (!Utils::isDirEmpty(efiPath)) {
// 重新rw读写挂载
remountEfi();
}
qDebug() << "CustomizeSystemRestoreProxy::doPrepare invoke end";
return true;
}
/**
* @brief dst.img文件挂载到/backup/imgbackup目录
* @return
*/
bool CustomizeSystemRestoreProxy::mountImg()
{
// 自定义路径系统备份需要先将dst.img文件挂载到/backup/imgbackup目录
// 1、检测目录/backup/imgbackup是否存在不存在则创建此目录
QString dstImgMountPath = Utils::getSysRootPath() + BACKUP_IMGBACKUP_PATH;
dstImgMountPath.replace("//", "/");
Utils::mkpath(dstImgMountPath);
// 2、先卸载/backup/imgbackup上的mount
MountBackupProcess *processMount = new MountBackupProcess(this);
processMount->umount(dstImgMountPath);
// 3、将img文件挂载到/backup/imgbackup上
if (!processMount->mount(m_imgFileName, dstImgMountPath)) {
emit checkResult(int(BackupResult::RESTOREDIR_PREPARE_FAILED));
return false;
}
m_srcPath = dstImgMountPath;
return true;
}
/**
* @brief rw读写挂载efi分区
*/
void CustomizeSystemRestoreProxy::remountEfi()
{
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief rw读写挂载boot分区
*/
void CustomizeSystemRestoreProxy::remountBoot()
{
QString mountPath = Utils::getSysRootPath() + "/boot";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList CustomizeSystemRestoreProxy::getRsyncArgs(CustomizeSystemRestoreScene scene)
{
QStringList args;
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
QStringList excludes;
// 自定义备份的路径也需要跳过,不进行还原
Utils::excludeCustomizePath(excludes);
switch (scene) {
case CustomizeSystemRestoreScene::RESTORE_SYSTEM_WITH_DATA :
args << "--exclude=/home";
args << "--exclude=/root";
if (Utils::isHuawei990()) {
args << "--exclude=/data";
} else {
args << "--exclude=/data/usershare";
}
// 保留指纹数据,用户密码、角色、权限、生物识别等信息不需要改变
args << "--exclude=/var/lib/biometric-auth";
args << "--exclude=/data/sec_storage_data";
args << "--exclude=/etc/passwd";
args << "--exclude=/etc/shadow";
args << "--exclude=/etc/group";
args << "--exclude=/etc/gshadow";
args << "--exclude=/etc/sudoers";
args << "--exclude=/data/home";
args << "--exclude=/data/root";
// 云桌面背景路径属于用户数据
args << "--exclude=/var/lib/AccountsService";
// 此处不要break因为还需要排除SYSTEM_RESTORE中的项
case CustomizeSystemRestoreScene::SYSTEM_RESTORE :
// 还原工具不还原自身
args << "--exclude=/usr/bin/backup-daemon";
args << "--exclude=/usr/bin/kybackup";
args << "--exclude=/usr/bin/mount_fstab_efi";
args << "--exclude=/usr/bin/backup-auto-efi";
args << "--exclude=/usr/bin/backup-auto";
args << "--exclude=/usr/bin/rsync";
args << "--exclude=/usr/share/rsync";
args << "--exclude=/usr/share/initramfs-tools/hooks/kybackup-hooks";
args << "--exclude=/usr/share/initramfs-tools/scripts/local-bottom/kybackup";
for (const QString& item : excludes) {
args << QString("--exclude=") + item;
}
args << "--exclude-from" << m_excludeUserFile;
args << "--files-from" << m_userFile;
break ;
default:
return args;
}
return args;
}
/**
* @brief
*/
void CustomizeSystemRestoreProxy::restoreSystem()
{
// 还原前准备
doPrepare();
QString destPath = Utils::getSysRootPath();
QStringList args;
// 保留用户数据还原
if ( m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
args = getRsyncArgs(CustomizeSystemRestoreScene::RESTORE_SYSTEM_WITH_DATA);
} else {
args = getRsyncArgs(CustomizeSystemRestoreScene::SYSTEM_RESTORE);
}
args << m_srcPath + "/";
destPath += "/";
destPath.replace("//", "/");
args << destPath;
m_p = new RsyncPathToDirProcess(this);
connect(m_p, &RsyncPathToDirProcess::progress, this, &CustomizeSystemRestoreProxy::progress);
connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool result) {
if (result) {
QString time = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss");
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,,," + m_backupPoint.m_backupName);
Utils::updateSyncFile();
QString fileIfSync = Utils::getSysRootPath() + FILE_IF_SYNC;
fileIfSync.replace("//", "/");
QFileInfo file(fileIfSync);
QDateTime beginTime = file.fileTime(QFileDevice::FileModificationTime);
Utils::wait(10);
Utils::updateSyncFile();
while (1) {
Utils::wait(2);
QFileInfo file1(fileIfSync);
QDateTime UpdateTime = file1.fileTime(QFileDevice::FileModificationTime);
if (UpdateTime > beginTime)
break;
}
emit this->workResult(result);
Utils::wait(2);
reboot(RB_AUTOBOOT);
}
emit this->workResult(result);
});
m_p->start(args, false);
}

View File

@ -0,0 +1,73 @@
#ifndef CUSTOMIZESYSTEMRESTOREPROXY_H
#define CUSTOMIZESYSTEMRESTOREPROXY_H
#include "workerfactory.h"
#include "myprocess/rsyncpathtodirprocess.h"
#include "parsebackuplist.h"
class CustomizeSystemRestoreProxy : public Worker
{
Q_OBJECT
DECLARE_DYNCREATE(CustomizeSystemRestoreProxy)
public:
// 系统还原的几种场景
enum CustomizeSystemRestoreScene {
SYSTEM_RESTORE, // 系统还原
RESTORE_SYSTEM_WITH_DATA, // 保留用户数据还原
};
explicit CustomizeSystemRestoreProxy();
virtual ~CustomizeSystemRestoreProxy();
public:
// 环境检测
virtual bool checkEnvEx();
// 任务处理
virtual void doWorkEx();
private:
// 将img文件挂载到/backup/imgbackup目录
bool mountImg();
// 以读写方式重新挂载efi分区
void remountEfi();
// 以读写方式重新挂载boot分区
void remountBoot();
// 还原前准备
bool doPrepare();
// 系统还原
void restoreSystem();
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList getRsyncArgs(CustomizeSystemRestoreScene scene);
// .user.txt文件路径
QString m_userFile;
// .exclude.user.txt文件路径
QString m_excludeUserFile;
// 备份数据所在的data目录
QString m_backupPath;
// 压缩的img文件全名
QString m_imgFileName;
// 是否还原成功
bool m_bSuccess;
// 当前备份uuid
QString m_curUuid;
// 当前还原源目录
QString m_srcPath;
// 备份进程
RsyncPathToDirProcess *m_p;
// 当前备份节点
ParseBackupList::BackupPoint m_backupPoint;
};
#endif // CUSTOMIZESYSTEMRESTOREPROXY_H

View File

@ -35,8 +35,13 @@ bool DataRestoreProxy::checkEnvEx()
{
qDebug() << "DataRestoreProxy::checkEnvEx invoke begin";
if (m_backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
m_prePath = m_backupWrapper.m_prefixDestPath;
else
m_prePath = Utils::getSysRootPath();
// 1、检测.user.txt是否存在
m_userFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + PATHS_USER_FILE;
m_userFile = m_prePath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + PATHS_USER_FILE;
m_userFile.replace("//", "/");
if (!Utils::filsExists(m_userFile)) {
qCritical(".user.txt文件不存在");
@ -45,7 +50,7 @@ bool DataRestoreProxy::checkEnvEx()
}
// 2、检测.exclude.user.txt是否存在
m_excludeUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + EXCLUDE_PATHS_USER_FILE;
m_excludeUserFile = m_prePath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + EXCLUDE_PATHS_USER_FILE;
m_excludeUserFile.replace("//", "/");
if (!Utils::filsExists(m_excludeUserFile)) {
qCritical(".exclude.user.txt文件不存在");
@ -54,7 +59,7 @@ bool DataRestoreProxy::checkEnvEx()
}
// 3、检测还原点是否存在
m_backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
m_backupPath = m_prePath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
m_backupPath.replace("//", "/");
if (Utils::isDirEmpty(m_backupPath)) {
qCritical("还原点{uuid}/data目录不存在");

View File

@ -42,6 +42,8 @@ private:
QString m_excludeUserFile;
// 备份数据所在的data目录
QString m_backupPath;
// 备份点前缀路径
QString m_prePath;
// 是否还原成功
bool m_bSuccess;

View File

@ -34,7 +34,7 @@ void DeleteBackupProxy::doWorkEx()
bool DeleteBackupProxy::deleteXmlBackupPoint()
{
QString xmlPath;
if (m_backupWrapper.m_iPosition == BackupPosition::LOCAL)
if (m_backupWrapper.m_iPosition == BackupPosition::LOCAL || m_backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
else
xmlPath = m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH;
@ -60,8 +60,10 @@ bool DeleteBackupProxy::deleteXmlBackupPoint()
void DeleteBackupProxy::deleteBackupPointDir()
{
QString uuidPath;
if (m_backupWrapper.m_iPosition == BackupPosition::LOCAL)
if (m_backupPoint.m_iPosition == BackupPosition::LOCAL)
uuidPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid;
else if (m_backupPoint.m_iPosition == BackupPosition::CUSTOMIZE)
uuidPath = m_backupPoint.m_path + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid;
else
uuidPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid;

View File

@ -115,9 +115,11 @@ void GhostImageProxy::cancelEx()
void GhostImageProxy::deleteFailedData()
{
// 1、删除镜像文件
if (!m_kyimg.isEmpty()) {
QFile kyimg(m_kyimg);
if (kyimg.exists())
kyimg.remove();
}
}
/**

View File

@ -34,6 +34,7 @@
#define OS "OS"
#define ARCH "Arch"
#define ARCHDETECT "ArchDetect"
#define PREFIXDESTPATH "PrefixDestPath"
#define STATUE_BACKUP_FINESHED "backup finished"
@ -279,7 +280,32 @@ void ParseBackupList::getXmlUuidNameMap(QMap<QString, QString> &uuid_name)
}
/**
* @brief
* @brief
* @param customizePaths
*/
void ParseBackupList::getCustomizePaths(QStringList &customizePaths)
{
QDomDocument doc;
if (!Doc_setContent(doc))
return ;
QDomElement root = doc.documentElement();
QDomNodeList list = root.childNodes();
for (int i = 0; i < list.count(); i++) {
QDomNode node = list.at(i);
if (!node.isElement())
continue;
QDomElement elePrefixPath = node.firstChildElement(PREFIXDESTPATH);
if (!elePrefixPath.isNull()) {
customizePaths << elePrefixPath.text();
}
}
}
/**
* @brief
* @return
*/
ParseBackupList::BackupPoint ParseBackupList::getLastSysBackupPoint()
@ -306,10 +332,13 @@ ParseBackupList::BackupPoint ParseBackupList::getLastSysBackupPoint()
continue;
QDomElement eleState = node.firstChildElement(STATE);
QString type = eleState.text();
if (eleState.isNull() || eleState.text() != QString(STATUE_BACKUP_FINESHED))
continue;
QDomElement elePosition = node.firstChildElement(POSITION);
if (!elePosition.isNull() && elePosition.text().toInt() == BackupPosition::CUSTOMIZE)
continue;
elementNodeToBackupPoint(node.toElement(), backupPoint);
}
@ -369,8 +398,13 @@ void ParseBackupList::elementNodeToBackupPoint(const QDomElement& node, BackupPo
if (!eleArchDetect.isNull())
backupPoint.m_archdetect = eleArchDetect.text();
QDomElement elePrefixPath = node.firstChildElement(PREFIXDESTPATH);
if (!elePrefixPath.isNull()) {
backupPoint.m_path = elePrefixPath.text();
} else {
backupPoint.m_path = m_xmlPath;
backupPoint.m_path.replace(BACKUP_XML_PATH, "");
}
}
/**
@ -399,6 +433,9 @@ void ParseBackupList::backupPointToElementNode(const BackupPoint& backupPoint, Q
if (!backupPoint.m_archdetect.isEmpty()) {
node.appendChild(createTextElement(doc, ARCHDETECT, backupPoint.m_archdetect));
}
if (!backupPoint.m_path.isEmpty()) {
node.appendChild(createTextElement(doc, PREFIXDESTPATH, backupPoint.m_path));
}
}
/**

View File

@ -41,7 +41,7 @@ public:
QString m_arch;
// 备份机器引导方式
QString m_archdetect;
// 备份点所在设备挂载路径(这个暂只在查询中界面展示选择中使用)
// 备份点所在设备挂载路径(这个暂只在查询中界面展示选择中使用)或自定义的备份路径
QString m_path;
bool isNull() { return m_uuid.isEmpty(); }
@ -87,6 +87,12 @@ public:
*/
BackupPoint getLastSysBackupPoint();
/**
* @brief
* @param customizePaths
*/
void getCustomizePaths(QStringList &customizePaths);
/**
* @brief
* @param backupPoint,

View File

@ -271,6 +271,8 @@ QStringList SystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
}
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上实际文件是存放在/data/home /data/root下面
Utils::excludeFstabBindPath(excludes);
// 自定义备份的路径也需要跳过,不进行还原
Utils::excludeCustomizePath(excludes);
for (const QString& item : excludes) {
QDir itemDir(m_srcPath + item);
// 以后统一用/home /root这种路径 兼容老备份数据原来的U盘备份在mksquashfs时排除bind挂载的任意一方时都备份不上

View File

@ -162,9 +162,11 @@ void UDiskGhostImageProxy::cancelEx()
void UDiskGhostImageProxy::deleteFailedData()
{
// 1、删除临时镜像文件
if (!m_kyimg.isEmpty()) {
QFile kyimg(m_kyimg);
if (kyimg.exists())
kyimg.remove();
}
// 2、删除目标镜像文件
QString kyimgFile = m_destPath + "/" + m_backupWrapper.m_backupName;

View File

@ -276,6 +276,8 @@ QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
}
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上实际文件是存放在/data/home /data/root下面
Utils::excludeFstabBindPath(excludes);
// 自定义备份的路径也需要跳过,不进行还原
Utils::excludeCustomizePath(excludes);
for (const QString& item : excludes) {
QDir itemDir(m_srcPath + item);
// 以后统一用/home /root这种路径 兼容老备份数据原来的U盘备份在mksquashfs时排除bind挂载的任意一方时都备份不上
@ -334,7 +336,7 @@ bool UDiskSystemRestoreProxy::doPrepare()
Utils::mkpath(dstImgMountPath);
// 2、先卸载/backup/imgbackup上的mount
MountBackupProcess *processMount = new MountBackupProcess;
MountBackupProcess *processMount = new MountBackupProcess(this);
processMount->umount(dstImgMountPath);
// 3、将img文件挂载到/backup/imgbackup上

View File

@ -62,7 +62,7 @@ Worker * WorkerFactory::createWorker(int type, int position)
break;
case BackupType::RESTORE_SYSTEM:
case BackupType::RESTORE_SYSTEM_WITH_DATA:
if (BackupPosition::UDISK == position) {
if (BackupPosition::UDISK == position || BackupPosition::OTHER == position) {
className = "UDiskSystemRestoreProxy";
} else if (BackupPosition::CUSTOMIZE == position) {
className = "CustomizeSystemRestoreProxy";
@ -83,8 +83,6 @@ Worker * WorkerFactory::createWorker(int type, int position)
case BackupType::RESTORE_DATA:
if (BackupPosition::UDISK == position) {
className = "UDiskDataRestoreProxy";
} else if (BackupPosition::CUSTOMIZE == position) {
className = "CustomizeDataRestoreProxy";
} else {
className = "DataRestoreProxy";
}

View File

@ -416,6 +416,19 @@ void Utils::excludeSomeHomePath(QStringList &excludes)
}
}
/**
* @brief
* @param excludes
*/
void Utils::excludeCustomizePath(QStringList &excludes)
{
// 本地xml文件中的信息
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
parse.getCustomizePaths(excludes);
}
/**
* @brief rsync --exclude-from排除路径规则文件
* @return
@ -463,6 +476,7 @@ bool Utils::generateExcludePathsFile()
QStringList excludes;
Utils::excludeFstabBindPath(excludes);
Utils::excludeSomeHomePath(excludes);
Utils::excludeCustomizePath(excludes);
for (const QString& item : excludes) {
in << item << END_LINE;
}
@ -518,6 +532,7 @@ QStringList Utils::getFromExcludePathsFile()
QStringList excludes;
Utils::excludeFstabBindPath(excludes);
Utils::excludeSomeHomePath(excludes);
Utils::excludeCustomizePath(excludes);
for (const QString& item : excludes) {
list << item;
}
@ -704,6 +719,8 @@ QHash<QString, QString> Utils::getRemovableStorages()
QString result = process_lsblk.readAllStandardOutput();
/*
result like bellow :
PATH="/dev/sda" RM="0" TYPE="disk" MOUNTPOINT="" TRAN="sata"
PATH="/dev/sda1" RM="0" TYPE="part" MOUNTPOINT="/media/zhaominyong/DATA1" TRAN=""
PATH="/dev/sdb" RM="1" TYPE="disk" MOUNTPOINT="" TRAN="usb"
PATH="/dev/sdb4" RM="1" TYPE="part" MOUNTPOINT="/media/zhaominyong/31 GB" TRAN=""
PATH="/dev/sr0" RM="1" TYPE="rom" MOUNTPOINT="/media/zhaominyong/Kylin-Desktop-V10-SP1" TRAN=""
@ -743,7 +760,6 @@ QHash<QString, QString> Utils::getRemovableStorages()
continue;
QString mount_point = storageAttrs.at(3);
mount_point = mount_point.replace("MOUNTPOINT=\"", "");
mount_point = mount_point.left(mount_point.length() - 1);
removalbeStorages.insert(path, mount_point);
}
}
@ -751,6 +767,78 @@ QHash<QString, QString> Utils::getRemovableStorages()
return removalbeStorages;
}
/**
* @brief
* @return
*/
QList<QString> Utils::getLocalDisks()
{
QList<QString> localDisks;
QProcess process_lsblk;
process_lsblk.start("lsblk -P -o PATH,RM,TYPE,MOUNTPOINT,TRAN");
if (!process_lsblk.waitForStarted(-1)) {
return localDisks;
}
if (!process_lsblk.waitForFinished(-1)) {
return localDisks;
}
QString result = process_lsblk.readAllStandardOutput();
QString userName = qgetenv("USER");
QString mountPointPre("/media/");
mountPointPre += userName;
/*
result like bellow :
PATH="/dev/sda" RM="0" TYPE="disk" MOUNTPOINT="" TRAN="sata"
PATH="/dev/sda1" RM="0" TYPE="part" MOUNTPOINT="/media/zhaominyong/DATA1" TRAN=""
PATH="/dev/sdb" RM="1" TYPE="disk" MOUNTPOINT="" TRAN="usb"
PATH="/dev/sdb4" RM="1" TYPE="part" MOUNTPOINT="/media/zhaominyong/31 GB" TRAN=""
PATH="/dev/sr0" RM="1" TYPE="rom" MOUNTPOINT="/media/zhaominyong/Kylin-Desktop-V10-SP1" TRAN=""
*/
QStringList items = result.split("\n");
QStringList usbDevs;
for (QStringList::const_iterator it = items.constBegin(); it != items.constEnd(); ++it) {
const QString &line = (*it);
if (line.contains(QRegularExpression(" TRAN=\".+\"")) && !line.contains(" TRAN=\"usb\"")) {
QStringList storageAttrs = line.split("\" ");
if (5 != storageAttrs.size())
continue ;
QString path = storageAttrs.at(0);
path = path.replace("PATH=\"", "");
usbDevs.append(path);
continue;
}
if (line.contains(" TYPE=\"part\" ") && line.contains(mountPointPre)) {
if (line.contains(" MOUNTPOINT=\"\""))
continue;
// "PATH RM TYPE MOUNTPOINT TRAN" for each row, split by "\" "
QStringList storageAttrs = line.split("\" ");
if (5 != storageAttrs.size())
continue ;
QString path = storageAttrs.at(0);
path = path.replace("PATH=\"", "");
bool isSubPart = false;
for (const QString& usbDev : usbDevs) {
if (path.contains(usbDev)) {
isSubPart = true;
break;
}
}
if (!isSubPart)
continue;
// 默认挂载的内部磁盘不太可能使用中文字符等,暂不考虑挂载路径被转义的场景
QString mount_point = storageAttrs.at(3);
mount_point = mount_point.replace("MOUNTPOINT=\"", "");
localDisks << mount_point;
}
}
return localDisks;
}
/**
* @brief
* @param enabletruefalse

View File

@ -110,6 +110,12 @@ public:
*/
static void excludeSomeHomePath(QStringList &excludes);
/**
* @brief
* @param excludes
*/
static void excludeCustomizePath(QStringList &excludes);
/**
* @brief rsync --exclude-from排除路径规则文件
* @return
@ -196,6 +202,12 @@ public:
*/
static QHash<QString, QString> getRemovableStorages();
/**
* @brief
* @return
*/
static QList<QString> getLocalDisks();
/**
* @brief
* @param enabletruefalse

View File

@ -0,0 +1,26 @@
#include "backuppositionselectdialog.h"
#include "filefilterproxymodelforbackup.h"
#include "../../common/utils.h"
BackupPositionSelectDialog::BackupPositionSelectDialog(QWidget* parent) :
QFileDialog(parent)
{
setWindowTitle(tr("Please select a path"));
setViewMode(QFileDialog::List);
setFileMode(QFileDialog::DirectoryOnly);
setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QList<QUrl> siderUrls;
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
QList<QString> localDisks = Utils::getLocalDisks();
for (const QString& path: localDisks) {
siderUrls << QUrl::fromLocalFile(path);
}
setSidebarUrls(siderUrls);
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
setProxyModel(proxy);
}
BackupPositionSelectDialog::~BackupPositionSelectDialog()
{}

View File

@ -0,0 +1,15 @@
#ifndef BACKUPPOSITIONSELECTDIALOG_H
#define BACKUPPOSITIONSELECTDIALOG_H
#include <QFileDialog>
class BackupPositionSelectDialog : public QFileDialog {
Q_OBJECT
public:
explicit BackupPositionSelectDialog(QWidget* parent = nullptr);
virtual ~BackupPositionSelectDialog();
};
#endif // BACKUPPOSITIONSELECTDIALOG_H

View File

@ -1,6 +1,8 @@
#include "filefilterproxymodelforbackup.h"
#include <QFileSystemModel>
#include <QDir>
#include "../../common/mydefine.h"
#include "../../common/utils.h"
FileFilterProxyModeForBackup::FileFilterProxyModeForBackup(QObject *parent) :
QSortFilterProxyModel(parent)
@ -31,10 +33,14 @@ bool FileFilterProxyModeForBackup::filterAcceptsRow(int sourceRow, const QModelI
return false;
QString filePath = fileModel->filePath(index0);
if (fileName == "backup") {
if (Utils::isDirExist(filePath + "/snapshots"))
return false;
}
return !(filePath.endsWith(BACKUP_SNAPSHOTS_PATH) || filePath == BACKUP_PATH);
} else {
return false;
return true;
}
}

View File

@ -27,3 +27,6 @@ void MyFileSelect::goAccept()
{
QDialog::accept();
}
MyFileSelect::~MyFileSelect()
{}

View File

@ -7,6 +7,7 @@ class MyFileSelect : public QFileDialog {
Q_OBJECT
public:
explicit MyFileSelect(QWidget* parent = nullptr);
virtual ~MyFileSelect();
public slots:
void goAccept();

View File

@ -149,7 +149,7 @@ void DeleteBackupDialog::deleteBackupPoint()
QString udiskPrePath = Utils::getSysRootPath();
udiskPrePath += "/media";
udiskPrePath.replace("//", "/");
backupWrapper.m_iPosition = m_backupPonit.m_path.startsWith(udiskPrePath) ? BackupPosition::UDISK : BackupPosition::LOCAL;
backupWrapper.m_iPosition = m_backupPonit.m_iPosition;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_gid = getgid();
m_pInterface->deleteBackupPoint(backupWrapper);

View File

@ -39,6 +39,7 @@ HEADERS += \
backup_manager_interface.h \
backuppointlistdialog.h \
component/backuplistwidget.h \
component/backuppositionselectdialog.h \
component/circlelabel.h \
component/clicklabel.h \
component/filefilterproxymodelforbackup.h \
@ -87,6 +88,7 @@ SOURCES += \
backup_manager_interface.cpp \
backuppointlistdialog.cpp \
component/backuplistwidget.cpp \
component/backuppositionselectdialog.cpp \
component/circlelabel.cpp \
component/clicklabel.cpp \
component/filefilterproxymodelforbackup.cpp \

View File

@ -8,6 +8,7 @@
#include <QVBoxLayout>
#include <unistd.h>
#include "../component/backuppositionselectdialog.h"
#include "../component/clicklabel.h"
#include "../component/circlelabel.h"
#include "../component/myiconlabel.h"
@ -29,6 +30,7 @@
DataBackup::DataBackup(QWidget *parent /*= nullptr*/) :
QStackedWidget(parent),
m_udector(new UdiskDetector()),
m_isLock(false),
m_isLocal(true),
m_DataBackupState(DataBackupState::IDEL),
m_pInterface(nullptr)
@ -169,12 +171,10 @@ void DataBackup::initFirstWidget()
this->m_uuid = backupPoint.m_uuid;
this->m_backupName = backupPoint.m_backupName;
this->m_prefixDestPath = backupPoint.m_path;
this->m_isLocal = backupPoint.m_iPosition == BackupPosition::UDISK || backupPoint.m_iPosition == BackupPosition::OTHER ? false : true;
});
if (QDialog::Accepted == selectDialog->exec()) {
QString udiskFlag = Utils::getSysRootPath() + "/media";
udiskFlag.replace("//", "/");
this->m_isLocal = this->m_prefixDestPath.startsWith(udiskFlag) ? false : true;
this->m_isIncrement = true;
this->setCurrentIndex(INC_SELECT_PATH_PAGE);
emit this->initIncListWidget();
@ -277,30 +277,11 @@ void DataBackup::initSecondWidget()
hlayoutLine2->addSpacing(40);
// 备份路径选择框
QComboBox* comboSelect = new QComboBox(second);
QPalette palette = comboSelect->palette();
comboSelect->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
// 添加本地默认路径、移动设备目录
connect(m_udector, &UdiskDetector::udiskListChanged, this, [=](QList<QStorageInfo> diskList) {
comboSelect->clear();
this->m_udiskPaths.clear();
QIcon iconFolder = QIcon::fromTheme("insync-folder.png", QIcon(":/images/folder.png"));
// 如果有备份分区,则将本地默认分区备份路径放在第一个
if (GlobelBackupInfo::inst().hasBackupPartition()) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
this->m_udiskPaths << "";
comboSelect->addItem(iconFolder, tr("local default path : ") + qsLocalDefaultPath);
}
QString qsPreDevPath(tr("removable devices path : "));
for (QStorageInfo& disk : diskList) {
this->m_udiskPaths << disk.rootPath();
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
}
});
m_udector->getStorageInfo();
QPushButton *buttonBrowse = new QPushButton;
buttonBrowse->setText(tr("Browse..."));
hlayoutLine2->addWidget(comboSelect);
hlayoutLine2->addWidget(buttonBrowse);
hlayoutLine2->addSpacing(40);
vlayout->addLayout(hlayoutLine2);
vlayout->addSpacing(32);
@ -404,17 +385,6 @@ void DataBackup::initSecondWidget()
nextStep->setEnabled(false);
nextStep->setAutoRepeat(true);
nextStep->setProperty("isImportant", true);
connect(nextStep, &MyPushButton::clicked, this, [=]() {
// 备份路径选择索引
int index = comboSelect->currentIndex();
// 第一个选项是本地系统备份
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
this->m_prefixDestPath = this->m_udiskPaths.at(index);
this->m_backupPaths.clear();
this->m_backupPaths.append(listWidget->getBackupPaths());
this->setCurrentIndex(CHECK_ENV_PAGE);
emit this->startCheckEnv();
});
hlayoutLastLine->addWidget(preStep);
hlayoutLastLine->addSpacing(16);
hlayoutLastLine->addWidget(nextStep);
@ -425,6 +395,101 @@ void DataBackup::initSecondWidget()
vlayout->addSpacing(40);
second->setLayout(vlayout);
addWidget(second);
// 添加本地默认路径、移动设备目录
connect(m_udector, &UdiskDetector::udiskListChanged, this, [=](QList<QStorageInfo> diskList) {
m_isLock = true;
comboSelect->clear();
this->m_udiskPaths.clear();
QIcon iconFolder = QIcon::fromTheme("insync-folder.png", QIcon(":/images/folder.png"));
// 如果有备份分区,则将本地默认分区备份路径放在第一个
if (GlobelBackupInfo::inst().hasBackupPartition()) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
this->m_udiskPaths << "";
comboSelect->addItem(iconFolder, tr("local default path : ") + qsLocalDefaultPath);
}
QString qsPreDevPath(tr("removable devices path : "));
for (QStorageInfo& disk : diskList) {
this->m_udiskPaths << disk.rootPath();
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
}
if (!this->m_customizePath.isEmpty()) {
comboSelect->setCurrentIndex(-1);
QLineEdit * edit = new QLineEdit;
comboSelect->setLineEdit(edit);
edit->setText(tr("customize path : ") + this->m_customizePath + BACKUP_SNAPSHOTS_PATH);
edit->setReadOnly(true);
} else if (comboSelect->count() > 0 && listWidget->getBackupPaths().size() > 0) {
nextStep->setEnabled(true);
} else {
nextStep->setEnabled(false);
}
m_isLock = false;
});
connect(comboSelect, QOverload<int>::of(&QComboBox::activated), this, [=]() {
if (!m_isLock) {
this->m_customizePath = "";
if (listWidget->getBackupPaths().size() > 0)
nextStep->setEnabled(true);
}
});
m_udector->getStorageInfo();
connect(buttonBrowse, &QPushButton::clicked, this, [=](){
// 是否自定义路径?自定义路径备份文件不受保护,可能导致备份文件丢失或损坏
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(GlobelBackupInfo::inst().getMainWidget(), QObject::tr("Information"),
QObject::tr("Are you sure to continue customizing the path?\nThe custom path backup file is not protected, which may cause the backup file to be lost or damaged"),
QObject::tr("Ok"), QObject::tr("Cancel")))
{
return ;
}
BackupPositionSelectDialog fileDialog(this);
if (fileDialog.exec() == QDialog::Accepted) {
QStringList selectFiles = fileDialog.selectedFiles();
if (!selectFiles.isEmpty()) {
comboSelect->setCurrentIndex(-1);
QString fileName = selectFiles.at(0);
this->m_customizePath = fileName;
QLineEdit * edit = new QLineEdit;
comboSelect->setLineEdit(edit);
edit->setText(tr("customize path : ") + fileName + BACKUP_SNAPSHOTS_PATH);
edit->setReadOnly(true);
if (listWidget->getBackupPaths().size() > 0)
nextStep->setEnabled(true);
}
}
});
connect(nextStep, &MyPushButton::clicked, this, [=]() {
// 备份路径选择索引
int index = comboSelect->currentIndex();
if (index >= 0) {
// 第一个选项是本地系统备份
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
this->m_prefixDestPath = this->m_udiskPaths.at(index);
} else if (this->m_customizePath.isEmpty()) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::inst().getMainWidget(), QObject::tr("Warning"),
QObject::tr("Please select backup position"),
QObject::tr("Ok"));
return ;
} else {
// 自定义备份位置的场景
this->m_isLocal = true;
this->m_prefixDestPath = this->m_customizePath;
}
this->m_backupPaths.clear();
this->m_backupPaths.append(listWidget->getBackupPaths());
this->setCurrentIndex(CHECK_ENV_PAGE);
emit this->startCheckEnv();
});
connect(buttonAdd, &PixmapLabel::clicked, this, [=]() {
if (editSelect->text().isEmpty())
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
@ -456,6 +521,8 @@ void DataBackup::initSecondWidget()
nextStep->setEnabled(false);
});
connect(listWidget, &BackupListWidget::addedItem, this, [=](){
int index = comboSelect->currentIndex();
if (index >= 0 || !this->m_customizePath.isEmpty())
nextStep->setEnabled(true);
});
@ -463,10 +530,8 @@ void DataBackup::initSecondWidget()
editSelect->setText("");
this->m_backupPaths.clear();
listWidget->clearData();
comboSelect->setCurrentIndex(0);
this->m_udector->getStorageInfo();
});
addWidget(second);
}
/**
@ -531,15 +596,6 @@ void DataBackup::initSecondWidget_inc()
// 默认备份位置展示
MyLabel* labelBackupPosition = new MyLabel(second);
labelBackupPosition->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
if (m_isLocal) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
QString defaultPath = tr("local default path : ") + qsLocalDefaultPath;
labelBackupPosition->setDeplayText(defaultPath);
} else {
QString defaultPath = tr("removable devices path : ") + m_prefixDestPath;
labelBackupPosition->setDeplayText(defaultPath);
}
labelBackupPosition->setEnabled(false);
hlayoutLine2->addWidget(labelBackupPosition);
hlayoutLine2->addSpacing(40);
@ -704,6 +760,19 @@ void DataBackup::initSecondWidget_inc()
emit this->reset();
this->addOldBackupPaths(listWidget);
nextStep->setEnabled(true);
if (this->m_isLocal && !this->m_prefixDestPath.isEmpty()) {
QString defaultPath = tr("customize path : ") + this->m_prefixDestPath + BACKUP_SNAPSHOTS_PATH;
labelBackupPosition->setDeplayText(defaultPath);
} else if (this->m_isLocal) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
QString defaultPath = tr("local default path : ") + qsLocalDefaultPath;
labelBackupPosition->setDeplayText(defaultPath);
} else {
QString defaultPath = tr("removable devices path : ") + this->m_prefixDestPath + BACKUP_SNAPSHOTS_PATH;
labelBackupPosition->setDeplayText(defaultPath);
}
});
connect(this, &DataBackup::reset, this, [=]() {
@ -1016,7 +1085,7 @@ void DataBackup::on_checkEnv_start()
BackupWrapper backupWrapper;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_type = m_isIncrement ? BackupType::INC_BACKUP_DATA : BackupType::BACKUP_DATA;
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_isLocal ? (this->m_prefixDestPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::CUSTOMIZE) : BackupPosition::UDISK;
backupWrapper.m_backupPaths << m_backupPaths;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_frontUid = getuid();
@ -1511,7 +1580,7 @@ void DataBackup::on_backup_start()
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_type = m_isIncrement ? BackupType::INC_BACKUP_DATA : BackupType::BACKUP_DATA;
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_isLocal ? (this->m_prefixDestPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::CUSTOMIZE) : BackupPosition::UDISK;
backupWrapper.m_backupPaths << m_backupPaths;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_frontUid = getuid();

View File

@ -75,6 +75,8 @@ private:
UdiskDetector* m_udector;
// U盘挂载路径列表
QStringList m_udiskPaths;
// U盘列表变化时先锁定
bool m_isLock;
// 是否本地备份
bool m_isLocal;
// 备份路径列表
@ -83,6 +85,8 @@ private:
int m_DataBackupState;
// 增量备份选择的备份点uuid
QString m_uuid;
// 自定义备份路径
QString m_customizePath;
// 选中的备份目标路径前缀暂指udisk挂载路径
QString m_prefixDestPath;
// dbus接口

View File

@ -166,6 +166,7 @@ void DataRestore::on_button_beginRestore_clicked(bool checked)
connect(selectRestoreDialog, &SelectRestorePoint::selected, this, [=](ParseBackupList::BackupPoint backupPoint){
this->m_uuid = backupPoint.m_uuid;
this->m_devPath = backupPoint.m_path;
this->m_iPosition = backupPoint.m_iPosition;
});
if (QDialog::Rejected == selectRestoreDialog->exec()) {
@ -478,7 +479,7 @@ void DataRestore::on_checkEnv_start()
BackupWrapper backupWrapper;
backupWrapper.m_type = BackupType::RESTORE_DATA;
backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_frontUid = getuid();
@ -671,7 +672,7 @@ void DataRestore::on_restore_start()
BackupWrapper backupWrapper;
backupWrapper.m_type = BackupType::RESTORE_DATA;
backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_frontUid = getuid();

View File

@ -60,6 +60,8 @@ private:
QString m_uuid; // 还原点的UUID
QString m_devPath; // 如果是从移动设备进行还原,此中保存移动设备挂载路径
// 本地备份还是U盘备份: 0-本地备份1-移动设备备份2-异机备份仅用于业务场景标记不用于持久化记录3-自定义路径备份
int m_iPosition;
// 系统备份状态
int m_dataRestoreState;
// 是否需要重启

View File

@ -31,6 +31,8 @@ GhostImage::GhostImage(QWidget *parent) :
m_ghostImageState(GhostImageState::IDEL),
m_pInterface(nullptr)
{
m_iPosition = BackupPosition::LOCAL;
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
@ -138,13 +140,11 @@ void GhostImage::initFirstWidget()
connect(selectDialog, &SelectRestorePoint::selected, this, [=](ParseBackupList::BackupPoint backupPoint){
this->m_uuid = backupPoint.m_uuid;
this->m_backupName = backupPoint.m_backupName;
this->m_prefixDestPath = backupPoint.m_path;
this->m_iPosition = backupPoint.m_iPosition;
});
if (QDialog::Accepted == selectDialog->exec()) {
QString udiskFlag = Utils::getSysRootPath() + "/media";
udiskFlag.replace("//", "/");
this->m_isLocal = this->m_prefixDestPath.startsWith(udiskFlag) ? false : true;
this->m_isLocal = true;
this->setCurrentIndex(SELECT_PATH_PAGE);
}
selectDialog->deleteLater();
@ -543,7 +543,7 @@ void GhostImage::on_checkEnv_start()
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_type = BackupType::GHOST_IMAGE;
backupWrapper.m_backupName = createGhostImageName(m_backupName);
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
@ -839,7 +839,7 @@ void GhostImage::on_ghost_start()
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_type = BackupType::GHOST_IMAGE;
backupWrapper.m_backupName = createGhostImageName(m_backupName);
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");

View File

@ -69,6 +69,8 @@ private:
QString m_uuid;
// 选中的备份目标路径前缀暂指udisk挂载路径
QString m_prefixDestPath;
// 本地备份还是U盘备份: 0-本地备份1-移动设备备份2-异机备份仅用于业务场景标记不用于持久化记录3-自定义路径备份
int m_iPosition;
// dbus接口
ComKylinBackupManagerInterface *m_pInterface;
// 备份点名称

View File

@ -58,6 +58,9 @@ ManageBackupPointList::ManageBackupPointList(QWidget *parent, BackupPointType ba
backupPoint.m_uuid = this->text(curRow, Column_Index::UUID);
backupPoint.m_time = this->text(curRow, Column_Index::Backup_Time);
backupPoint.m_path = this->text(curRow, Column_Index::Prefix_Path);
QString position = this->text(curRow, Column_Index::Backup_Device);
backupPoint.m_iPosition = position.startsWith(QObject::tr("Customize:")) ? BackupPosition::CUSTOMIZE :
(position.startsWith(QObject::tr("Local Disk:")) ? BackupPosition::LOCAL : BackupPosition::UDISK);
m_deleteRow = curRow;
emit selected(backupPoint);
@ -136,7 +139,9 @@ void ManageBackupPointList::insertLines(const QList<ParseBackupList::BackupPoint
setItem(indexOfRow, Column_Index::Backup_Size, backupPoint.m_size);
QString prefixPath_to_device;
if (backupPoint.m_path.startsWith(preDevPath)) {
if (backupPoint.m_iPosition == BackupPosition::CUSTOMIZE) {
prefixPath_to_device = QObject::tr("Customize:") + backupPoint.m_path + BACKUP_SNAPSHOTS_PATH;
} else if (backupPoint.m_path.startsWith(preDevPath)) {
QStorageInfo storage(backupPoint.m_path);
QString udiskName = storage.rootPath();
prefixPath_to_device = QObject::tr("Udisk Device:") + " " + udiskName + BACKUP_SNAPSHOTS_PATH;

View File

@ -60,8 +60,14 @@ SelectRestorePoint::SelectRestorePoint(QWidget *parent, BackupPointType backupTy
backupPoint.m_time = this->text(curRow, Column_Index::Backup_Time);
backupPoint.m_path = this->text(curRow, Column_Index::Prefix_Path);
QString dev = this->text(curRow, Column_Index::Backup_Device);
if (dev.startsWith(tr("Udisk Device:")))
if (dev.startsWith(tr("Other machine:")))
backupPoint.m_iPosition = BackupPosition::OTHER;
else if (dev.startsWith(tr("Customize:")))
backupPoint.m_iPosition = BackupPosition::CUSTOMIZE;
else if (dev.startsWith(tr("Udisk Device:")))
backupPoint.m_iPosition = BackupPosition::UDISK;
else
backupPoint.m_iPosition = BackupPosition::LOCAL;
emit this->selected(backupPoint);
this->accept();
@ -152,7 +158,9 @@ void SelectRestorePoint::insertLines(const QList<ParseBackupList::BackupPoint> &
setItem(indexOfRow, Column_Index::Backup_Size, backupPoint.m_size);
QString prefixPath_to_device;
if (backupPoint.m_path.startsWith(preDevPath)) {
if (backupPoint.m_iPosition == BackupPosition::CUSTOMIZE) {
prefixPath_to_device = QObject::tr("Customize:") + backupPoint.m_path + BACKUP_SNAPSHOTS_PATH;
} else if (backupPoint.m_path.startsWith(preDevPath)) {
QStorageInfo storage(backupPoint.m_path);
QString udiskName = storage.rootPath();
if (isOther)

View File

@ -9,9 +9,9 @@
#include <QtGlobal>
#include <unistd.h>
#include "../component/backuppositionselectdialog.h"
#include "../component/clicklabel.h"
#include "../component/circlelabel.h"
#include "../component/filefilterproxymodelforbackup.h"
#include "../component/myiconlabel.h"
#include "../component/mylabel.h"
#include "../component/mylineedit.h"
@ -28,6 +28,7 @@
SystemBackup::SystemBackup(QWidget *parent /*= nullptr*/) :
QStackedWidget(parent),
m_udector(new UdiskDetector()),
m_isLock(false),
m_isLocal(true),
m_systemBackupState(SystemBackupState::IDEL),
m_pInterface(nullptr)
@ -230,67 +231,8 @@ void SystemBackup::initSecondWidget()
// 备份路径选择框
QComboBox* comboSelect = new QComboBox(second);
comboSelect->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
// 添加本地默认路径、移动设备目录
connect(m_udector, &UdiskDetector::udiskListChanged, this, [=](QList<QStorageInfo> diskList) {
comboSelect->clear();
this->m_udiskPaths.clear();
QIcon iconFolder = QIcon::fromTheme("insync-folder.png", QIcon(":/images/folder.png"));
// 如果有备份分区,则将本地默认分区备份路径放在第一个
if (GlobelBackupInfo::inst().hasBackupPartition()) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
this->m_udiskPaths << "";
comboSelect->addItem(iconFolder, tr("local default path : ") + qsLocalDefaultPath);
}
QString qsPreDevPath(tr("removable devices path : "));
for (QStorageInfo& disk : diskList) {
this->m_udiskPaths << disk.rootPath();
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
}
});
connect(comboSelect, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]() {
this->m_prefixDestPath = "";
});
m_udector->getStorageInfo();
QPushButton *buttonBrowse = new QPushButton;
buttonBrowse->setText(tr("Browse..."));
connect(buttonBrowse, &QPushButton::clicked, this, [=](){
// 是否自定义路径?自定义路径备份文件不受保护,可能导致备份文件丢失或损坏
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Information"),
QObject::tr("Are you sure to continue customizing the path\n"
"The custom path backup file is not protected, which may cause the backup file to be lost or damaged"),
QObject::tr("Ok"), QObject::tr("Cancel")))
{
return ;
}
QFileDialog fileDialog(this);
fileDialog.setWindowTitle(tr("Please select a path"));
fileDialog.setViewMode(QFileDialog::List);
fileDialog.setFileMode(QFileDialog::DirectoryOnly);
fileDialog.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QList<QUrl> siderUrls;
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
fileDialog.setSidebarUrls(siderUrls);
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
fileDialog.setProxyModel(proxy);
if (fileDialog.exec() == QDialog::Accepted) {
QStringList selectFiles = fileDialog.selectedFiles();
if (!selectFiles.isEmpty()) {
comboSelect->setCurrentIndex(-1);
QString fileName = selectFiles.at(0);
this->m_prefixDestPath = fileName;
QLineEdit * edit = new QLineEdit;
comboSelect->setLineEdit(edit);
edit->setText(tr("customize path : ") + fileName + BACKUP_SNAPSHOTS_PATH);
edit->setReadOnly(true);
}
}
});
hlayoutLine2->addWidget(comboSelect);
hlayoutLine2->addWidget(buttonBrowse);
hlayoutLine2->addSpacing(40);
@ -312,23 +254,9 @@ void SystemBackup::initSecondWidget()
// 下一步按钮
MyPushButton *nextStep = new MyPushButton(second);
nextStep->setText(tr("Next"));
nextStep->setEnabled(true);
nextStep->setEnabled(false);
nextStep->setAutoRepeat(true);
nextStep->setProperty("isImportant", true);
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
// 备份路径选择索引
int index = comboSelect->currentIndex();
if (index >= 0) {
// 第一个选项是本地系统备份
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
this->m_prefixDestPath = this->m_udiskPaths.at(index);
} else {
// 自定义备份位置的场景
this->m_isLocal = true;
}
this->on_next_clicked(checked);
emit this->startCheckEnv();
});
hlayoutLine3->addWidget(nextStep);
hlayoutLine3->addStretch();
hlayoutLine3->setAlignment(Qt::AlignCenter);
@ -338,6 +266,94 @@ void SystemBackup::initSecondWidget()
second->setLayout(vlayout);
addWidget(second);
// 添加本地默认路径、移动设备目录
connect(m_udector, &UdiskDetector::udiskListChanged, this, [=](QList<QStorageInfo> diskList) {
m_isLock = true;
comboSelect->clear();
this->m_udiskPaths.clear();
QIcon iconFolder = QIcon::fromTheme("insync-folder.png", QIcon(":/images/folder.png"));
// 如果有备份分区,则将本地默认分区备份路径放在第一个
if (GlobelBackupInfo::inst().hasBackupPartition()) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
this->m_udiskPaths << "";
comboSelect->addItem(iconFolder, tr("local default path : ") + qsLocalDefaultPath);
}
QString qsPreDevPath(tr("removable devices path : "));
for (QStorageInfo& disk : diskList) {
this->m_udiskPaths << disk.rootPath();
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
}
if (!this->m_customizePath.isEmpty()) {
comboSelect->setCurrentIndex(-1);
QLineEdit * edit = new QLineEdit;
comboSelect->setLineEdit(edit);
edit->setText(tr("customize path : ") + this->m_customizePath + BACKUP_SNAPSHOTS_PATH);
edit->setReadOnly(true);
} else if (comboSelect->count() > 0) {
nextStep->setEnabled(true);
} else {
nextStep->setEnabled(false);
}
m_isLock = false;
});
connect(comboSelect, QOverload<int>::of(&QComboBox::activated), this, [=]() {
if (!m_isLock) {
this->m_customizePath = "";
nextStep->setEnabled(true);
}
});
m_udector->getStorageInfo();
connect(buttonBrowse, &QPushButton::clicked, this, [=](){
// 是否自定义路径?自定义路径备份文件不受保护,可能导致备份文件丢失或损坏
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(GlobelBackupInfo::inst().getMainWidget(), QObject::tr("Information"),
QObject::tr("Are you sure to continue customizing the path?\nThe custom path backup file is not protected, which may cause the backup file to be lost or damaged"),
QObject::tr("Ok"), QObject::tr("Cancel")))
{
return ;
}
BackupPositionSelectDialog fileDialog(this);
if (fileDialog.exec() == QDialog::Accepted) {
QStringList selectFiles = fileDialog.selectedFiles();
if (!selectFiles.isEmpty()) {
comboSelect->setCurrentIndex(-1);
QString fileName = selectFiles.at(0);
this->m_customizePath = fileName;
QLineEdit * edit = new QLineEdit;
comboSelect->setLineEdit(edit);
edit->setText(tr("customize path : ") + fileName + BACKUP_SNAPSHOTS_PATH);
edit->setReadOnly(true);
nextStep->setEnabled(true);
}
}
});
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
// 备份路径选择索引
int index = comboSelect->currentIndex();
if (index >= 0) {
// 第一个选项是本地系统备份
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
this->m_prefixDestPath = this->m_udiskPaths.at(index);
} else if (this->m_customizePath.isEmpty()) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::inst().getMainWidget(), QObject::tr("Warning"),
QObject::tr("Please select backup position"),
QObject::tr("Ok"));
return ;
} else {
// 自定义备份位置的场景
this->m_isLocal = true;
this->m_prefixDestPath = this->m_customizePath;
}
this->on_next_clicked(checked);
emit this->startCheckEnv();
});
}
/**
@ -622,6 +638,8 @@ void SystemBackup::on_checkEnv_start()
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
@ -1126,6 +1144,8 @@ void SystemBackup::on_backup_start()
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();

View File

@ -62,14 +62,18 @@ public slots:
private:
// U盘探测
UdiskDetector* m_udector;
// U盘挂载路径列表
QStringList m_udiskPaths;
// U盘列表变化时先锁定
bool m_isLock;
// 是否本地备份
bool m_isLocal;
// 系统备份状态
int m_systemBackupState;
// 自定义路径
QString m_customizePath;
// 选中的备份目标路径前缀暂指udisk挂载路径
QString m_prefixDestPath;
// U盘挂载路径列表
QStringList m_udiskPaths;
// dbus接口
ComKylinBackupManagerInterface *m_pInterface;
// 备份点名称

View File

@ -29,6 +29,7 @@ SystemRestore::SystemRestore(QWidget *parent) :
m_isRetainUserData = false;
m_isFactoryRestore = false;
m_pInterface = nullptr;
m_iPosition = BackupPosition::LOCAL;
// 界面手写代码创建,作为练手
initFirstWidget();
@ -196,7 +197,8 @@ void SystemRestore::on_button_beginRestore_clicked(bool checked)
this->m_uuid = "";
this->m_devPath = "";
this->m_backupName = "";
this->m_isOtherMachine = "";
this->m_isOtherMachine = false;
this->m_iPosition = BackupPosition::LOCAL;
// 出厂还原,不用去选择备份点
if (m_isFactoryRestore) {
@ -220,6 +222,7 @@ void SystemRestore::on_button_beginRestore_clicked(bool checked)
this->m_devPath = backupPoint.m_path;
this->m_backupName = backupPoint.m_backupName;
this->m_isOtherMachine = backupPoint.m_iPosition == BackupPosition::OTHER ? true : false;
this->m_iPosition = backupPoint.m_iPosition == BackupPosition::OTHER ? BackupPosition::UDISK : backupPoint.m_iPosition;
});
if (QDialog::Rejected == selectRestoreDialog->exec()) {
@ -497,7 +500,7 @@ void SystemRestore::on_checkEnv_start()
BackupWrapper backupWrapper;
backupWrapper.m_type = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_prefixDestPath = m_devPath;
@ -697,7 +700,7 @@ void SystemRestore::on_restore_start()
BackupWrapper backupWrapper;
backupWrapper.m_type = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_prefixDestPath = m_devPath;

View File

@ -64,6 +64,8 @@ private:
QString m_devPath; // 如果是从移动设备进行还原,此中保存移动设备挂载路径
QString m_backupName; // 还原点的备份点名称
bool m_isOtherMachine; // 是否异机备份点还原
// 本地备份还是U盘备份: 0-本地备份1-移动设备备份2-异机备份仅用于业务场景标记不用于持久化记录3-自定义路径备份
int m_iPosition;
// 系统备份状态
int m_systemRestoreState;
};

File diff suppressed because it is too large Load Diff