阶段提交
This commit is contained in:
parent
c2ba01b07e
commit
c1e7f440bd
|
@ -43,6 +43,7 @@ HEADERS += \
|
|||
systembackupproxy.h \
|
||||
systemrestoreproxy.h \
|
||||
udisksystembackupproxy.h \
|
||||
udisksystemrestoreproxy.h \
|
||||
workerfactory.h
|
||||
|
||||
SOURCES += \
|
||||
|
@ -65,6 +66,7 @@ SOURCES += \
|
|||
systembackupproxy.cpp \
|
||||
systemrestoreproxy.cpp \
|
||||
udisksystembackupproxy.cpp \
|
||||
udisksystemrestoreproxy.cpp \
|
||||
workerfactory.cpp
|
||||
|
||||
# Default rules for deployment.
|
||||
|
|
|
@ -4,24 +4,6 @@
|
|||
#include "../common/mydefine.h"
|
||||
#include "backupmanager_adaptor.h"
|
||||
|
||||
// test begin
|
||||
#include <QDebug>
|
||||
#include "../common/reflect.h"
|
||||
#include "mymountproxy.h"
|
||||
#include "parsebackuplist.h"
|
||||
|
||||
void testXml()
|
||||
{
|
||||
ParseBackupList parse("/backup/snapshots/backuplist.xml");
|
||||
}
|
||||
|
||||
void testLog()
|
||||
{
|
||||
Utils::getBackupLogList();
|
||||
}
|
||||
|
||||
// test end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 以防客户端传入的参数中的中文信息乱码
|
||||
|
@ -37,24 +19,6 @@ int main(int argc, char *argv[])
|
|||
qInstallMessageHandler(Utils::customMessageHandler);
|
||||
Utils::initSystemInfo();
|
||||
|
||||
// test begin
|
||||
qDebug() << QString("测试 begin");
|
||||
|
||||
// MyMountProxy * proxy = (MyMountProxy*)Reflect::createObject("MyMountProxy");
|
||||
// proxy->mountBackupPartition();
|
||||
|
||||
// BackupWrapper backupWrapper;
|
||||
// backupWrapper.m_backupName = "赵民勇test";
|
||||
// backupWrapper.m_backupPaths << "/";
|
||||
// backupWrapper.m_backupExcludePaths = Utils::getFromExcludePathsFile();
|
||||
// MyBackupManager manager;
|
||||
// manager.goBackup(backupWrapper);
|
||||
|
||||
testLog();
|
||||
|
||||
qDebug() << QString("测试 end");
|
||||
// test end
|
||||
|
||||
MyBackupManager* backup_deamon = new MyBackupManager;
|
||||
new ManagerAdaptor(backup_deamon);
|
||||
QDBusConnection conn = QDBusConnection::systemBus();
|
||||
|
|
|
@ -35,12 +35,12 @@ bool MountBackupProcess::Do(const QString& diskUuid)
|
|||
|
||||
m_p->start("mount", arguments);
|
||||
if (!m_p->waitForStarted()) {
|
||||
qFatal("mount rw /backup process start failed!");
|
||||
qCritical("mount rw /backup process start failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_p->waitForFinished()) {
|
||||
qFatal("mount rw backup process end failed!");
|
||||
qCritical("mount rw backup process end failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -53,12 +53,55 @@ bool MountBackupProcess::umountBackupPartition()
|
|||
arguments << QString("/backup");
|
||||
m_p->start("umount", arguments);
|
||||
if (!m_p->waitForStarted()) {
|
||||
qFatal("mount ro backup process start failed!");
|
||||
qCritical("mount ro backup process start failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_p->waitForFinished()) {
|
||||
qFatal("mount ro backup process end failed!");
|
||||
qCritical("mount ro backup process end failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 卸载目录挂载
|
||||
* @param mountPath,挂载的目录
|
||||
* @return
|
||||
*/
|
||||
bool MountBackupProcess::umount(const QString& mountPath)
|
||||
{
|
||||
if (0 == ::umount(mountPath.toUtf8().data()))
|
||||
return true;
|
||||
|
||||
qCritical() << QString("%1 umount failed, error is %2(%3)").arg(mountPath).arg(strerror(errno)).arg(QString::number(errno));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 挂载
|
||||
* @param source 源
|
||||
* @param target 目标目录
|
||||
* @return
|
||||
*/
|
||||
bool MountBackupProcess::mount(const QString& source, const QString& target, const QString& options)
|
||||
{
|
||||
QStringList arguments;
|
||||
if (!options.isEmpty())
|
||||
arguments << options;
|
||||
arguments << source;
|
||||
arguments << target;
|
||||
|
||||
m_p->start("mount", arguments);
|
||||
if (!m_p->waitForStarted()) {
|
||||
qCritical("mount process start failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_p->waitForFinished()) {
|
||||
qCritical("mount process end failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define MOUNTBACKUPPROCESS_H
|
||||
|
||||
#include <QProcess>
|
||||
#include <sys/mount.h>
|
||||
|
||||
class MountBackupProcess : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -12,6 +13,9 @@ public:
|
|||
|
||||
bool umountBackupPartition();
|
||||
|
||||
static bool umount(const QString& mountPath);
|
||||
bool mount(const QString& source, const QString& target, const QString& options = "");
|
||||
|
||||
private:
|
||||
|
||||
QProcess* m_p;
|
||||
|
|
|
@ -146,6 +146,20 @@ void SystemRestoreProxy::remountEfi()
|
|||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
void SystemRestoreProxy::remountBoot()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 同步efi
|
||||
*/
|
||||
|
@ -292,6 +306,9 @@ void SystemRestoreProxy::restoreSystem()
|
|||
m_srcPath = m_backupPath;
|
||||
QString destPath = Utils::getSysRootPath();
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
remountBoot();
|
||||
|
||||
QStringList args;
|
||||
// 自动更新的备份还原时保留用户数据
|
||||
if (m_curUuid == AUTO_BACKUP_UUID || m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
|
||||
|
@ -316,7 +333,7 @@ void SystemRestoreProxy::restoreSystem()
|
|||
QFileInfo file(fileIfSync);
|
||||
QDateTime beginTime = file.fileTime(QFileDevice::FileModificationTime);
|
||||
if (Utils::isHuawei990() && FACTORY_BACKUP_UUID == m_curUuid && m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM) {
|
||||
// 出厂还原有的机器上删除/home/xxx有残留,故在此再强制删除一下,妈的sudo rm -rf命令一遍还删除不了(报错:无法删除/home/xx/.config:目录非空,应该是删除后又自动生成了),多删除几次还不是非常干净,贱 ^_^
|
||||
// 出厂还原有的机器上删除/home/xxx有残留,故在此再强制删除一下,sudo rm -rf命令一遍还删除不了(报错:无法删除/home/xx/.config:目录非空,应该是删除后又自动生成了),多删除几次还不是非常干净,^_^
|
||||
removeHome(Utils::getSysRootPath() + "/home");
|
||||
removeHome(Utils::getSysRootPath() + "/data/home");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ private:
|
|||
void repairEfi();
|
||||
// 以读写方式重新挂载efi分区
|
||||
void remountEfi();
|
||||
// 以读写方式重新挂载boot分区
|
||||
void remountBoot();
|
||||
// 同步efi
|
||||
bool rsyncEfi();
|
||||
// 系统还原
|
||||
|
|
|
@ -0,0 +1,418 @@
|
|||
#include "udisksystemrestoreproxy.h"
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <unistd.h>
|
||||
#include <sys/reboot.h>
|
||||
#include "../common/utils.h"
|
||||
#include "mymountproxy.h"
|
||||
#include "myprocess/mksquashfsprocess.h"
|
||||
|
||||
IMPLEMENT_DYNCREATE(UDiskSystemRestoreProxy)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
UDiskSystemRestoreProxy::UDiskSystemRestoreProxy()
|
||||
{
|
||||
m_isFinished = false;
|
||||
m_p = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
UDiskSystemRestoreProxy::~UDiskSystemRestoreProxy()
|
||||
{
|
||||
delete m_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 环境检测
|
||||
* @return false,检测失败;true,检测成功
|
||||
*/
|
||||
bool UDiskSystemRestoreProxy::checkEnvEx()
|
||||
{
|
||||
qDebug() << "UDiskSystemRestoreProxy::checkEnvEx invoke begin";
|
||||
|
||||
// 1、检测.user.txt是否存在
|
||||
m_userFile = m_backupWrapper.m_prefixDestPath + 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;
|
||||
}
|
||||
|
||||
// 2、检测.exclude.user.txt是否存在
|
||||
m_excludeUserFile = m_backupWrapper.m_prefixDestPath + 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;
|
||||
}
|
||||
|
||||
// 3、检测还原点是否存在
|
||||
m_backupPath = m_backupWrapper.m_prefixDestPath + 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;
|
||||
}
|
||||
|
||||
qDebug() << "UDiskSystemRestoreProxy::checkEnvEx invoke end";
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行还原逻辑
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::doWorkEx()
|
||||
{
|
||||
qDebug() << "UDiskSystemRestoreProxy::doWorkEx invoke begin";
|
||||
|
||||
// 1、校验
|
||||
if (!checkEnvEx())
|
||||
return ;
|
||||
|
||||
// 2、还原efi(兼容旧版本的备份)
|
||||
if (!restoreEfi()) {
|
||||
qCritical("/boot/efi目录同步失败");
|
||||
emit checkResult(int(BackupResult::EFI_RSYNC_FAIL));
|
||||
return ;
|
||||
}
|
||||
|
||||
// 3、还原系统
|
||||
if (doPrepare())
|
||||
restoreSystem();
|
||||
|
||||
qDebug() << "UDiskSystemRestoreProxy::doWorkEx invoke end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 还原efi(兼容旧版本的备份)
|
||||
* @return
|
||||
*/
|
||||
bool UDiskSystemRestoreProxy::restoreEfi()
|
||||
{
|
||||
qDebug() << "UDiskSystemRestoreProxy::restoreEfi invoke begin";
|
||||
|
||||
// 是否有/boot/efi目录
|
||||
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
efiPath.replace("//", "/");
|
||||
if (!Utils::isDirEmpty(efiPath)) {
|
||||
// 1、修复源数据
|
||||
repairEfi();
|
||||
|
||||
// 2、重新rw读写挂载
|
||||
remountEfi();
|
||||
|
||||
// 3、同步efi
|
||||
return rsyncEfi();
|
||||
}
|
||||
|
||||
qDebug() << "UDiskSystemRestoreProxy::restoreEfi invoke end";
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 修复efi目录
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::repairEfi()
|
||||
{
|
||||
QString qsEfiPath = m_backupPath + "/efi";
|
||||
if (!Utils::isDirEmpty(qsEfiPath)) {
|
||||
// 存在/efi说明是老备份数据,尽量修正老数据
|
||||
QStringList args;
|
||||
args << "-f";
|
||||
args << qsEfiPath;
|
||||
QString newPath = m_backupPath + "/boot";
|
||||
args << newPath;
|
||||
QProcess::execute("mv", args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载efi分区
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::remountEfi()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::remountBoot()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 同步efi
|
||||
*/
|
||||
bool UDiskSystemRestoreProxy::rsyncEfi()
|
||||
{
|
||||
QString efiPath = m_backupPath + "/boot/efi/";
|
||||
if (Utils::isDirEmpty(efiPath))
|
||||
efiPath = efiPath = m_backupPath + "/efi/";
|
||||
if (Utils::isDirEmpty(efiPath))
|
||||
return true;
|
||||
|
||||
QStringList args = getRsyncArgs(SystemRestoreScene::EFI_RESTORE);
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot/efi/";
|
||||
mountPath.replace("//", "/");
|
||||
|
||||
args << efiPath << mountPath;
|
||||
|
||||
m_p = new RsyncPathToDirProcess(this);
|
||||
bool result = m_p->start(args);
|
||||
delete m_p;
|
||||
m_p = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
* @param scene,场景
|
||||
* @return 组装好的rsync的参数信息
|
||||
*/
|
||||
QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
|
||||
{
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << "--info=progress2";
|
||||
args << "--no-inc-recursive";
|
||||
args << "--ignore-missing-args";
|
||||
args << "--delete";
|
||||
|
||||
QDir dataDir(m_srcPath + "/data");
|
||||
QFile file(m_srcPath + "/etc/uid_list");
|
||||
QDir efiDir(m_srcPath + "/boot/efi");
|
||||
QStringList excludes;
|
||||
|
||||
switch (scene) {
|
||||
case SystemRestoreScene::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";
|
||||
|
||||
// 以前的出厂备份和grub备份没有备份/data,还原时需要判断/data是否存在,如不存在需要屏蔽掉,不然会将主机上的/data删除,造成问题
|
||||
// 此为兼容以前备份的老数据而改,等以后老的备份估计不存在了可已去掉
|
||||
if (!dataDir.exists()) {
|
||||
args << "--exclude=/data";
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
args << "--exclude=/etc/uid_list";
|
||||
}
|
||||
|
||||
// 为兼容以前的老备份数据,增加下面几行
|
||||
if (efiDir.isEmpty()) {
|
||||
args << QString("--exclude=/boot/efi");
|
||||
}
|
||||
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上,实际文件是存放在/data/home /data/root下面
|
||||
Utils::excludeFstabBindPath(excludes);
|
||||
for (const QString& item : excludes) {
|
||||
QDir itemDir(m_srcPath + item);
|
||||
// 以后统一用/home /root这种路径, 兼容老备份数据(原来的U盘备份,在mksquashfs时排除bind挂载的任意一方时,都备份不上)
|
||||
if (item == "/data/home") {
|
||||
QDir homeDir(m_srcPath + "/home");
|
||||
if (!homeDir.isEmpty()) {
|
||||
args << QString("--exclude=/data/home");
|
||||
} else if (!itemDir.isEmpty()) {
|
||||
args << QString("--exclude=/home");
|
||||
} else {
|
||||
args << QString("--exclude=/data/home");
|
||||
args << QString("--exclude=/home");
|
||||
}
|
||||
continue;
|
||||
} else if (item == "/data/root") {
|
||||
QDir homeDir(m_srcPath + "/root");
|
||||
if (!homeDir.isEmpty()) {
|
||||
args << QString("--exclude=/data/root");
|
||||
} else if (!itemDir.isEmpty()) {
|
||||
args << QString("--exclude=/root");
|
||||
} else {
|
||||
args << QString("--exclude=/data/root");
|
||||
args << QString("--exclude=/root");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
args << QString("--exclude=") + item;
|
||||
}
|
||||
|
||||
args << "--exclude-from" << m_excludeUserFile;
|
||||
args << "--files-from" << m_userFile;
|
||||
|
||||
break ;
|
||||
case SystemRestoreScene::EFI_RESTORE :
|
||||
break ;
|
||||
default:
|
||||
return args;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 还原前准备
|
||||
* @return
|
||||
*/
|
||||
bool UDiskSystemRestoreProxy::doPrepare()
|
||||
{
|
||||
// 移动设备系统备份如果有img,则需要先将img挂载到/backup/imgbackup目录
|
||||
QString imgPath = m_backupPath + UDISK_MKSQUASHFS_IMG_NAME;
|
||||
if (Utils::filsExists(imgPath)) {
|
||||
// 1、检测目录/backup/imgbackup是否存在,不存在则创建此目录
|
||||
QString dstImgMountPath = Utils::getSysRootPath() + BACKUP_IMGBACKUP_PATH;
|
||||
dstImgMountPath.replace("//", "/");
|
||||
Utils::mkpath(dstImgMountPath);
|
||||
|
||||
// 2、先卸载/backup/imgbackup上的mount
|
||||
MountBackupProcess::umount(dstImgMountPath);
|
||||
|
||||
// 3、将img文件挂载到/backup/imgbackup上
|
||||
MountBackupProcess *processMount = new MountBackupProcess;
|
||||
if (processMount->mount(imgPath, dstImgMountPath)) {
|
||||
emit checkResult(int(BackupResult::RESTOREDIR_PREPARE_FAILED));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_srcPath = dstImgMountPath;
|
||||
} else
|
||||
m_srcPath = m_backupPath;
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
remountBoot();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 系统还原
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::restoreSystem()
|
||||
{
|
||||
QString destPath = Utils::getSysRootPath();
|
||||
|
||||
QStringList args = getRsyncArgs(SystemRestoreScene::SYSTEM_RESTORE);
|
||||
|
||||
args << m_srcPath + "/";
|
||||
args << destPath + "/";
|
||||
|
||||
m_p = new RsyncPathToDirProcess(this);
|
||||
connect(m_p, &RsyncPathToDirProcess::progress, this, &UDiskSystemRestoreProxy::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::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;
|
||||
}
|
||||
|
||||
if (m_backupWrapper.m_isOtherMachine) {
|
||||
Utils::wait(20);
|
||||
updateGrubUUid();
|
||||
sync();
|
||||
Utils::wait(5);
|
||||
}
|
||||
|
||||
emit this->workResult(result);
|
||||
Utils::wait(2);
|
||||
reboot(RB_AUTOBOOT);
|
||||
}
|
||||
|
||||
if (Utils::isDirEmpty(m_backupPath))
|
||||
result = false;
|
||||
emit this->workResult(result);
|
||||
m_isFinished = true;
|
||||
});
|
||||
|
||||
QTimer::singleShot(1*1000, this, &UDiskSystemRestoreProxy::checkUdiskExists);
|
||||
m_isFinished = false;
|
||||
m_p->start(args, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 异机还原时更新grub.cfg中的分区UUID
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::updateGrubUUid()
|
||||
{
|
||||
QString srcFstab = Utils::getSysRootPath() + BACKUP_IMGBACKUP_PATH;
|
||||
srcFstab += FSTAB_PATH;
|
||||
srcFstab.replace("//", "/");
|
||||
QHash<QString, QString> srcPartToUuid = Utils::getPartUuidMap(srcFstab);
|
||||
QString destFstab = Utils::getSysRootPath() + FSTAB_PATH;
|
||||
QHash<QString, QString> destPartToUuid = Utils::getPartUuidMap(destFstab);
|
||||
|
||||
QString findGrub = Utils::executeCmd("find /boot -name grub.cfg");
|
||||
QStringList grubs = findGrub.split("\n");
|
||||
for (const QString &grub : grubs) {
|
||||
if (grub.isEmpty())
|
||||
continue;
|
||||
QString root = QString("sed -i 's/%1/%2/g' %3").arg(srcPartToUuid.value("/")).arg(destPartToUuid.value("/")).arg(grub);
|
||||
qDebug() << Utils::executeCmd(root);
|
||||
|
||||
QString boot = QString("sed -i 's/%1/%2/g' %3").arg(srcPartToUuid.value("/boot")).arg(destPartToUuid.value("/boot")).arg(grub);
|
||||
qDebug() << Utils::executeCmd(boot);
|
||||
|
||||
QString swap = QString("sed -i 's/%1/%2/g' %3").arg(srcPartToUuid.value("swap")).arg(destPartToUuid.value("swap")).arg(grub);
|
||||
qDebug() << Utils::executeCmd(swap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 监控移动设备是否还在
|
||||
* @return true-在;false-不在
|
||||
*/
|
||||
bool UDiskSystemRestoreProxy::checkUdiskExists()
|
||||
{
|
||||
if (!m_isFinished) {
|
||||
if (Utils::isDirEmpty(m_backupPath) && m_p != nullptr)
|
||||
m_p->stop();
|
||||
else
|
||||
QTimer::singleShot(1*1000, this, &UDiskSystemRestoreProxy::checkUdiskExists);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef UDISKSYSTEMRESTOREPROXY_H
|
||||
#define UDISKSYSTEMRESTOREPROXY_H
|
||||
|
||||
#include "workerfactory.h"
|
||||
#include "myprocess/rsyncpathtodirprocess.h"
|
||||
#include "parsebackuplist.h"
|
||||
|
||||
class UDiskSystemRestoreProxy : public Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
DECLARE_DYNCREATE(UDiskSystemRestoreProxy)
|
||||
public:
|
||||
// 系统还原的几种场景
|
||||
enum SystemRestoreScene {
|
||||
SYSTEM_RESTORE, // 系统还原
|
||||
EFI_RESTORE, // efi还原
|
||||
};
|
||||
|
||||
explicit UDiskSystemRestoreProxy();
|
||||
virtual ~UDiskSystemRestoreProxy();
|
||||
|
||||
public:
|
||||
// 环境检测
|
||||
virtual bool checkEnvEx();
|
||||
|
||||
// 任务处理
|
||||
virtual void doWorkEx();
|
||||
|
||||
private slots:
|
||||
bool checkUdiskExists();
|
||||
|
||||
private:
|
||||
// 还原efi
|
||||
bool restoreEfi();
|
||||
// 修复efi目录
|
||||
void repairEfi();
|
||||
// 以读写方式重新挂载efi分区
|
||||
void remountEfi();
|
||||
// 以读写方式重新挂载boot分区
|
||||
void remountBoot();
|
||||
// 同步efi
|
||||
bool rsyncEfi();
|
||||
// 系统还原
|
||||
void restoreSystem();
|
||||
// 还原前准备
|
||||
bool doPrepare();
|
||||
// 异机还原时更新grub.cfg中的分区UUID
|
||||
void updateGrubUUid();
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
* @param scene,场景
|
||||
* @return 组装好的rsync的参数信息
|
||||
*/
|
||||
QStringList getRsyncArgs(SystemRestoreScene scene);
|
||||
|
||||
// .user.txt文件路径
|
||||
QString m_userFile;
|
||||
// .exclude.user.txt文件路径
|
||||
QString m_excludeUserFile;
|
||||
// 备份数据所在的data目录
|
||||
QString m_backupPath;
|
||||
|
||||
// 是否还原结束
|
||||
bool m_isFinished;
|
||||
// 当前备份uuid
|
||||
QString m_curUuid;
|
||||
// 当前还原源目录
|
||||
QString m_srcPath;
|
||||
// 备份进程
|
||||
RsyncPathToDirProcess *m_p;
|
||||
// 当前备份节点
|
||||
ParseBackupList::BackupPoint m_backupPoint;
|
||||
};
|
||||
|
||||
#endif // UDISKSYSTEMRESTOREPROXY_H
|
|
@ -8,7 +8,7 @@ QDBusArgument &operator<<(QDBusArgument &argument, const BackupWrapper &backupWr
|
|||
argument << backupWrapper.m_type << backupWrapper.m_iPosition << backupWrapper.m_comment << backupWrapper.m_backupName
|
||||
<< backupWrapper.m_uuid << backupWrapper.m_backupPaths << backupWrapper.m_backupExcludePaths << backupWrapper.m_prefixDestPath
|
||||
<< backupWrapper.m_note << backupWrapper.m_frontUserName << backupWrapper.m_frontUid
|
||||
<< backupWrapper.m_gid;
|
||||
<< backupWrapper.m_gid << backupWrapper.m_isOtherMachine;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, BackupWrapper &ba
|
|||
argument >> backupWrapper.m_type >> backupWrapper.m_iPosition >> backupWrapper.m_comment >> backupWrapper.m_backupName
|
||||
>> backupWrapper.m_uuid >> backupWrapper.m_backupPaths >> backupWrapper.m_backupExcludePaths >> backupWrapper.m_prefixDestPath
|
||||
>> backupWrapper.m_note >> backupWrapper.m_frontUserName >> backupWrapper.m_frontUid
|
||||
>> backupWrapper.m_gid;
|
||||
>> backupWrapper.m_gid >> backupWrapper.m_isOtherMachine;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,9 @@ void RingsProgressbar::paintEvent(QPaintEvent *)
|
|||
p.setBrush(QBrush(QColor(COLOR_BLUE)));
|
||||
|
||||
//画圆弧
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
p.setPen(pen);
|
||||
// pen.setCapStyle(Qt::RoundCap);
|
||||
// pen.setColor(QColor(COLOR_BLUE));
|
||||
// p.setPen(pen);
|
||||
p.drawPie(QRectF(5 , 5, side - 10, side - 10), (90-m_rotateAngle)*16, m_rotateAngle*16);
|
||||
|
||||
//画遮罩
|
||||
|
|
|
@ -96,7 +96,7 @@ void SelectRestorePoint::insertLines(const QList<ParseBackupList::BackupPoint> &
|
|||
continue;
|
||||
|
||||
//hide factory backup
|
||||
if (backupPoint.m_uuid == FACTORY_BACKUP_UUID)
|
||||
if (backupPoint.m_uuid == FACTORY_BACKUP_UUID && Utils::isHuawei990())
|
||||
continue;
|
||||
|
||||
//udisk unique
|
||||
|
|
|
@ -779,6 +779,7 @@ void SystemBackup::initFifthWidget()
|
|||
labelTip->setGeometry(101, 261, 520, 30);
|
||||
labelTip->setAlignment(Qt::AlignCenter);
|
||||
labelTip->setFontWordWrap(true);
|
||||
// 不要使用电脑,以防数据丢失
|
||||
labelTip->setDeplayText(tr("Do not use computers in case of data loss"));
|
||||
connect(this, &SystemBackup::backupWarnning, labelTip, [=](const QString& msg) {
|
||||
labelTip->setDeplayText(msg);
|
||||
|
|
|
@ -31,6 +31,8 @@ SystemRestore::SystemRestore(QWidget *parent) :
|
|||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initThirdWidget();
|
||||
initLastWidget();
|
||||
}
|
||||
|
||||
SystemRestore::~SystemRestore()
|
||||
|
@ -184,12 +186,6 @@ void SystemRestore::on_next_clicked(bool checked)
|
|||
*/
|
||||
void SystemRestore::on_button_beginRestore_clicked(bool checked)
|
||||
{
|
||||
on_next_clicked();
|
||||
emit this->startCheckEnv();
|
||||
return;
|
||||
|
||||
// -------以上为测试代码-------
|
||||
|
||||
Q_UNUSED(checked)
|
||||
|
||||
// 出厂还原,不用去选择备份点
|
||||
|
@ -221,7 +217,7 @@ void SystemRestore::on_button_beginRestore_clicked(bool checked)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第二界面
|
||||
* @brief 初始化第二界面--检测中
|
||||
*/
|
||||
void SystemRestore::initSecondWidget()
|
||||
{
|
||||
|
@ -340,6 +336,7 @@ void SystemRestore::initSecondWidget()
|
|||
nextStep->setAutoRepeat(true);
|
||||
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
|
||||
this->on_next_clicked(checked);
|
||||
this->startRestore();
|
||||
});
|
||||
hlayoutCenterFont5->addWidget(nextStep);
|
||||
// 重新检测按钮
|
||||
|
@ -348,10 +345,6 @@ void SystemRestore::initSecondWidget()
|
|||
recheck->setText(tr("recheck"));
|
||||
recheck->setEnabled(true);
|
||||
recheck->setAutoRepeat(true);
|
||||
connect(recheck, &MyPushButton::clicked, this, [=](bool checked) {
|
||||
Q_UNUSED(checked)
|
||||
emit this->startCheckEnv();
|
||||
});
|
||||
hlayoutCenterFont5->addWidget(recheck);
|
||||
hlayoutCenterFont5->addStretch();
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
|
||||
|
@ -449,6 +442,12 @@ void SystemRestore::initSecondWidget()
|
|||
preStep->setVisible(true);
|
||||
});
|
||||
|
||||
// 重新检查
|
||||
connect(recheck, &MyPushButton::clicked, this, [=](bool checked) {
|
||||
Q_UNUSED(checked)
|
||||
emit this->startCheckEnv();
|
||||
});
|
||||
|
||||
addWidget(second);
|
||||
}
|
||||
|
||||
|
@ -501,35 +500,29 @@ void SystemRestore::on_checkEnv_end(int result)
|
|||
// 没有找到相应的处理逻辑
|
||||
errTip = tr("No processing logic was found in the service");
|
||||
break;
|
||||
case int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL):
|
||||
// 备份分区挂载失败
|
||||
errMsg = tr("Failed to mount the backup partition");
|
||||
// 检查是否有备份分区
|
||||
errTip = tr("Check whether there is a backup partition");
|
||||
case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
|
||||
// ".user.txt文件不存在"
|
||||
errMsg = tr(".user.txt file is not exists");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::UDISK_FILESYSTEM_TYPE_IS_VFAT):
|
||||
// 移动设备的文件系统是vfat格式
|
||||
errMsg = tr("The filesystem of device is vfat format");
|
||||
// 请换成ext4、ntfs等格式
|
||||
errTip = tr("Please change filesystem format to ext3、ext4 or ntfs");
|
||||
case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
|
||||
// .exclude.user.txt文件不存在
|
||||
errMsg = tr(".exclude.user.txt file is not exists");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::UDISK_FILESYSTEM_IS_READONLY):
|
||||
// 移动设备是只读的
|
||||
errMsg = tr("The device is read only");
|
||||
// 请修改为可读写权限的
|
||||
errTip = tr("Please chmod to rw");
|
||||
case int(BackupResult::INC_NOT_FOUND_DIR):
|
||||
// 备份点数据目录不存在
|
||||
errMsg = tr("The backup point data directory does not exist");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH):
|
||||
// 备份空间不足
|
||||
errMsg = tr("The storage for backup is not enough");
|
||||
// 建议释放空间后重试
|
||||
errTip = tr("Retry after release space");
|
||||
break;
|
||||
case int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING):
|
||||
// 其它备份还原等操作正在执行
|
||||
errMsg = tr("Other backup or restore task is being performed");
|
||||
// 请稍后重试
|
||||
errTip = tr("Please try again later");
|
||||
case int(BackupResult::EFI_RSYNC_FAIL):
|
||||
// 同步/boot/efi失败
|
||||
errMsg = tr("Failed to rsync /boot/efi");
|
||||
// 请检查/boot/efi分区挂载方式
|
||||
errTip = tr("Check the mounting mode of the /boot/efi partition");
|
||||
break;
|
||||
default:
|
||||
bRst = true;
|
||||
|
@ -543,4 +536,408 @@ void SystemRestore::on_checkEnv_end(int result)
|
|||
m_pInterface = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 第三个页面-还原中
|
||||
*/
|
||||
void SystemRestore::initThirdWidget()
|
||||
{
|
||||
QWidget *third = new QWidget;
|
||||
|
||||
// 流程进度提示栏
|
||||
CircleLable *one = new CircleLable("1", third, 24, QColor(COLOR_BLUE));
|
||||
LineLabel *line1 = new LineLabel(third, QColor(COLOR_BLUE), QSize(200, 24));
|
||||
CircleLable *two = new CircleLable("2", third, 24, QColor(COLOR_BLUE));
|
||||
LineLabel *line2 = new LineLabel(third, QColor(COLOR_GRAY), QSize(200, 24));
|
||||
CircleLable *three = new CircleLable("3", third);
|
||||
QHBoxLayout *layoutLine1 = new QHBoxLayout;
|
||||
layoutLine1->addStretch();
|
||||
layoutLine1->addWidget(one);
|
||||
layoutLine1->addWidget(line1);
|
||||
layoutLine1->addWidget(two);
|
||||
layoutLine1->addWidget(line2);
|
||||
layoutLine1->addWidget(three);
|
||||
layoutLine1->addStretch();
|
||||
|
||||
MyLabel *label1 = new MyLabel(tr("checking"), third);
|
||||
label1->setIsOriginal(true);
|
||||
label1->setFontColor(QColor(COLOR_BLUE));
|
||||
MyLabel *label2 = new MyLabel(tr("restoring"), third);
|
||||
label2->setIsOriginal(true);
|
||||
label2->setFontColor(QColor(COLOR_BLUE));
|
||||
MyLabel *label3 = new MyLabel(tr("finished"), third);
|
||||
label3->setIsOriginal(true);
|
||||
QHBoxLayout *layoutLine2 = new QHBoxLayout;
|
||||
layoutLine2->addSpacing(100);
|
||||
layoutLine2->addWidget(label1);
|
||||
layoutLine2->addStretch();
|
||||
layoutLine2->addWidget(label2);
|
||||
layoutLine2->addStretch();
|
||||
layoutLine2->addWidget(label3);
|
||||
layoutLine2->addSpacing(100);
|
||||
|
||||
// ------------ 中部布局begin-------------
|
||||
QWidget *centerFont = new QWidget(third);
|
||||
QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
|
||||
|
||||
// 中部第一行
|
||||
QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
|
||||
// 检测等待图标
|
||||
QLabel *loadingGif = new QLabel(centerFont);
|
||||
// 环境检测等待动画
|
||||
QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), centerFont);
|
||||
loadingGif->setMovie(movie);
|
||||
// 进度条
|
||||
RingsProgressbar *progressBar = new RingsProgressbar(centerFont);
|
||||
progressBar->setFixedSize(100, 100);
|
||||
hlayoutCenterFont1->addStretch();
|
||||
hlayoutCenterFont1->addWidget(loadingGif);
|
||||
hlayoutCenterFont1->addWidget(progressBar);
|
||||
hlayoutCenterFont1->addStretch();
|
||||
|
||||
// 第二行
|
||||
QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
|
||||
// 提醒
|
||||
MyLabel *labelTip = new MyLabel(centerFont);
|
||||
labelTip->setAlignment(Qt::AlignCenter);
|
||||
labelTip->setIsOriginal(true);
|
||||
labelTip->setFontWordWrap(true);
|
||||
// 不要使用电脑,以防数据丢失
|
||||
labelTip->setDeplayText(tr("Do not use computers in case of data loss"));
|
||||
hlayoutCenterFont2->addStretch();
|
||||
hlayoutCenterFont2->addWidget(labelTip);
|
||||
hlayoutCenterFont2->addStretch();
|
||||
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont1);
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont2);
|
||||
vlayoutCenterFont->addStretch();
|
||||
centerFont->setLayout(vlayoutCenterFont);
|
||||
|
||||
// ------------ 中部布局end-------------
|
||||
QHBoxLayout *layoutLine3 = new QHBoxLayout;
|
||||
layoutLine3->addStretch();
|
||||
layoutLine3->addSpacing(80);
|
||||
layoutLine3->addWidget(centerFont);
|
||||
layoutLine3->addStretch();
|
||||
|
||||
// 布局
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
vlayout->addSpacing(40);
|
||||
vlayout->addLayout(layoutLine1);
|
||||
vlayout->addLayout(layoutLine2);
|
||||
vlayout->addSpacing(50);
|
||||
vlayout->addLayout(layoutLine3);
|
||||
vlayout->addStretch();
|
||||
third->setLayout(vlayout);
|
||||
|
||||
// 开始备份
|
||||
connect(this, &SystemRestore::startRestore, this, [=] {
|
||||
progressBar->setPersent(20);
|
||||
movie->start();
|
||||
|
||||
// 开始备份
|
||||
this->on_restore_start();
|
||||
});
|
||||
|
||||
// 进度
|
||||
connect(this, &SystemRestore::progress, this, [=](int state, int rate) {
|
||||
Q_UNUSED(state)
|
||||
progressBar->setPersent(rate);
|
||||
});
|
||||
|
||||
addWidget(third);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开始还原
|
||||
*/
|
||||
void SystemRestore::on_restore_start()
|
||||
{
|
||||
GlobelBackupInfo::inst().setIsBusy(true);
|
||||
m_systemRestoreState = SystemRestoreState::RESTORING;
|
||||
m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
|
||||
connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
|
||||
connect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
|
||||
connect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
|
||||
|
||||
// 是否已存在备份、还原等操作
|
||||
bool isActive = false;
|
||||
if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
|
||||
on_checkEnv_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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_prefixDestPath = m_devPath;
|
||||
backupWrapper.m_isOtherMachine = m_isOtherMachine ? 1 : 0;
|
||||
backupWrapper.m_frontUid = getuid();
|
||||
backupWrapper.m_gid = getgid();
|
||||
m_pInterface->goRestore(backupWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 系统还原校验结果处理
|
||||
* @param result
|
||||
*/
|
||||
void SystemRestore::on_checkRestore_end(int result)
|
||||
{
|
||||
bool bRst = false;
|
||||
QString errMsg, errTip;
|
||||
switch (result) {
|
||||
case int(BackupResult::LOCK_PROGRAM_FAIL):
|
||||
// 程序锁定失败,请重试
|
||||
errMsg = tr("Program lock failed, please retry");
|
||||
// 可能有其它备份/还原等任务在执行
|
||||
errTip = tr("There may be other backups or restores being performed");
|
||||
break;
|
||||
case int(BackupResult::NO_FOUND_DEALCLASS):
|
||||
// 不支持的任务类型
|
||||
errMsg = tr("Unsupported task type");
|
||||
// 没有找到相应的处理逻辑
|
||||
errTip = tr("No processing logic was found in the service");
|
||||
break;
|
||||
case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
|
||||
// ".user.txt文件不存在"
|
||||
errMsg = tr("The .user.txt file is not exists");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
|
||||
// .exclude.user.txt文件不存在
|
||||
errMsg = tr("The .exclude.user.txt file is not exists");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::INC_NOT_FOUND_DIR):
|
||||
// 备份点数据目录不存在
|
||||
errMsg = tr("The backup point data directory does not exist");
|
||||
// 备份点可能被损坏
|
||||
errTip = tr("Backup points may be corrupted");
|
||||
break;
|
||||
case int(BackupResult::EFI_RSYNC_FAIL):
|
||||
// 同步/boot/efi失败
|
||||
errMsg = tr("Failed to rsync /boot/efi");
|
||||
// 请检查/boot/efi分区挂载方式
|
||||
errTip = tr("Check the mounting mode of the /boot/efi partition");
|
||||
break;
|
||||
case int(BackupResult::RESTOREDIR_PREPARE_FAILED):
|
||||
// 还原目录准备失败
|
||||
errMsg = tr("Failed to prepare the restore directory");
|
||||
// 更多信息请参考日志/var/log/backup.log
|
||||
errTip = tr("Refer to log :/var/log/backup.log for more information");
|
||||
break;
|
||||
default:
|
||||
bRst = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bRst) {
|
||||
GlobelBackupInfo::inst().setIsBusy(false);
|
||||
m_systemRestoreState = SystemRestoreState::IDEL;
|
||||
this->on_next_clicked(true);
|
||||
emit this->checkRestoreResult(bRst, errMsg, errTip);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
|
||||
delete m_pInterface;
|
||||
m_pInterface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 系统还原结束
|
||||
* @param result-false 失败; true 成功
|
||||
*/
|
||||
void SystemRestore::on_restore_end(bool result)
|
||||
{
|
||||
m_systemRestoreState = SystemRestoreState::IDEL;
|
||||
|
||||
this->on_next_clicked(true);
|
||||
if (result) {
|
||||
emit checkRestoreResult(result);
|
||||
} else {
|
||||
// 还原过程中出现错误
|
||||
QString errMsg = tr("An error occurred during restore");
|
||||
// 错误信息参考日志文件:/var/log/backup.log
|
||||
QString errTip = tr("Error messages refer to log file : /var/log/backup.log");
|
||||
emit checkRestoreResult(result, errMsg, errTip);
|
||||
}
|
||||
|
||||
GlobelBackupInfo::inst().setIsBusy(false);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
|
||||
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
|
||||
delete m_pInterface;
|
||||
m_pInterface = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化最后一页
|
||||
*/
|
||||
void SystemRestore::initLastWidget()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
|
||||
// 流程进度提示栏
|
||||
CircleLable *one = new CircleLable("1", last, 24, QColor(COLOR_BLUE));
|
||||
LineLabel *line1 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
|
||||
CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
|
||||
LineLabel *line2 = new LineLabel(last, QColor(COLOR_GRAY), QSize(200, 24));
|
||||
CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
|
||||
QHBoxLayout *layoutLine1 = new QHBoxLayout;
|
||||
layoutLine1->addStretch();
|
||||
layoutLine1->addWidget(one);
|
||||
layoutLine1->addWidget(line1);
|
||||
layoutLine1->addWidget(two);
|
||||
layoutLine1->addWidget(line2);
|
||||
layoutLine1->addWidget(three);
|
||||
layoutLine1->addStretch();
|
||||
|
||||
MyLabel *label1 = new MyLabel(tr("checking"), last);
|
||||
label1->setIsOriginal(true);
|
||||
label1->setFontColor(QColor(COLOR_BLUE));
|
||||
MyLabel *label2 = new MyLabel(tr("restoring"), last);
|
||||
label2->setIsOriginal(true);
|
||||
label2->setFontColor(QColor(COLOR_BLUE));
|
||||
MyLabel *label3 = new MyLabel(tr("finished"), last);
|
||||
label3->setIsOriginal(true);
|
||||
label3->setFontColor(QColor(COLOR_BLUE));
|
||||
QHBoxLayout *layoutLine2 = new QHBoxLayout;
|
||||
layoutLine2->addSpacing(100);
|
||||
layoutLine2->addWidget(label1);
|
||||
layoutLine2->addStretch();
|
||||
layoutLine2->addWidget(label2);
|
||||
layoutLine2->addStretch();
|
||||
layoutLine2->addWidget(label3);
|
||||
layoutLine2->addSpacing(100);
|
||||
|
||||
// ------------ 中部布局begin-------------
|
||||
QWidget *centerFont = new QWidget(last);
|
||||
QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
|
||||
|
||||
// 中部第一行
|
||||
QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
|
||||
// 备份结果对错图标
|
||||
QLabel *resultLogo = new QLabel(centerFont);
|
||||
resultLogo->setFixedSize(20,20);
|
||||
hlayoutCenterFont1->addWidget(resultLogo);
|
||||
// 检测中大标题
|
||||
MyLabel *bigTitle = new MyLabel(centerFont);
|
||||
bigTitle->setFontSize(24);
|
||||
bigTitle->setMaximumWidth(700);
|
||||
hlayoutCenterFont1->addWidget(bigTitle);
|
||||
hlayoutCenterFont1->addStretch();
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont1);
|
||||
|
||||
// 第二行
|
||||
QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
|
||||
hlayoutCenterFont2->addSpacing(10);
|
||||
// 备份结果错误提示:黑点和文字
|
||||
CircleLable *dot1 = new CircleLable(QString(""), centerFont, 6, Qt::black);
|
||||
hlayoutCenterFont2->addWidget(dot1);
|
||||
hlayoutCenterFont2->addSpacing(5);
|
||||
MyLabel *labelError1 = new MyLabel(centerFont);
|
||||
labelError1->setMinimumWidth(400);
|
||||
labelError1->setMaximumWidth(600);
|
||||
labelError1->setIsOriginal(true);
|
||||
labelError1->setWordWrap(true);
|
||||
labelError1->adjustSize();
|
||||
hlayoutCenterFont2->addWidget(labelError1);
|
||||
hlayoutCenterFont2->addStretch();
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont2);
|
||||
|
||||
// 第三行
|
||||
QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
|
||||
hlayoutCenterFont3->addSpacing(10);
|
||||
// 检测中的记录:黑点2和文字2
|
||||
CircleLable *dot2 = new CircleLable(QString(""), centerFont, 6, Qt::black);
|
||||
hlayoutCenterFont3->addWidget(dot2);
|
||||
hlayoutCenterFont3->addSpacing(5);
|
||||
MyLabel *labelError2 = new MyLabel(centerFont);
|
||||
//labelError2->setMinimumWidth(400);
|
||||
//labelError2->setMaximumWidth(600);
|
||||
labelError2->setIsOriginal(true);
|
||||
labelError2->setWordWrap(true);
|
||||
labelError2->adjustSize();
|
||||
hlayoutCenterFont3->addWidget(labelError2);
|
||||
hlayoutCenterFont3->addStretch();
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont3);
|
||||
|
||||
// 第四行
|
||||
vlayoutCenterFont->addSpacing(30);
|
||||
|
||||
// 第五行
|
||||
QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
|
||||
hlayoutCenterFont5->addSpacing(100);
|
||||
// 再试一次
|
||||
MyPushButton *retry = new MyPushButton(centerFont);
|
||||
retry->setFixedSize(97, 36);
|
||||
retry->setText(tr("retry"));
|
||||
retry->setEnabled(true);
|
||||
retry->setAutoRepeat(true);
|
||||
hlayoutCenterFont5->addWidget(retry);
|
||||
hlayoutCenterFont5->addStretch();
|
||||
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
|
||||
|
||||
vlayoutCenterFont->addStretch();
|
||||
centerFont->setLayout(vlayoutCenterFont);
|
||||
// ------------ 中部布局end-------------
|
||||
|
||||
QHBoxLayout *layoutLine3 = new QHBoxLayout;
|
||||
layoutLine3->addStretch();
|
||||
layoutLine3->addWidget(centerFont);
|
||||
layoutLine3->addStretch();
|
||||
|
||||
// 布局
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
vlayout->addSpacing(40);
|
||||
vlayout->addLayout(layoutLine1);
|
||||
vlayout->addLayout(layoutLine2);
|
||||
vlayout->addSpacing(50);
|
||||
vlayout->addLayout(layoutLine3);
|
||||
vlayout->addStretch();
|
||||
last->setLayout(vlayout);
|
||||
|
||||
// 还原检测结果
|
||||
connect(this, &SystemRestore::checkRestoreResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
|
||||
if (result) {
|
||||
QIcon icon = QIcon::fromTheme("ukui-dialog-success", QIcon(":/symbos/ukui-dialog-success.png"));
|
||||
resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
|
||||
resultLogo->setVisible(true);
|
||||
// 系统还原成功
|
||||
bigTitle->setDeplayText(tr("Successfully restoring the system"));
|
||||
dot1->setVisible(true);
|
||||
dot2->setVisible(false);
|
||||
labelError1->setVisible(true);
|
||||
// 系统将自动重启
|
||||
labelError1->setDeplayText(tr("The system will automatically reboot"));
|
||||
labelError2->setVisible(false);
|
||||
retry->setVisible(false);
|
||||
} else {
|
||||
QIcon icon = QIcon::fromTheme("dialog-error.png", QIcon(":/symbos/dialog-error.png"));
|
||||
resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
|
||||
resultLogo->setVisible(true);
|
||||
// 系统还原失败
|
||||
bigTitle->setDeplayText(tr("Restoring the system failed"));
|
||||
dot1->setVisible(true);
|
||||
dot2->setVisible(true);
|
||||
labelError1->setDeplayText(errMsg);
|
||||
labelError2->setDeplayText(errTip);
|
||||
retry->setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
// 再试一次
|
||||
connect(retry, &MyPushButton::clicked, this, [=](bool checked) {
|
||||
Q_UNUSED(checked)
|
||||
this->setCurrentIndex(SystemRestorePage::RESTORE_PAGE);
|
||||
this->startRestore();
|
||||
});
|
||||
|
||||
addWidget(last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ public:
|
|||
{
|
||||
IDEL = 0, // 空闲
|
||||
CHECKING, // 环境校验中
|
||||
BACKUPING // 备份中
|
||||
RESTORING // 还原中
|
||||
};
|
||||
|
||||
enum SystemRestorePage
|
||||
{
|
||||
HOME_PAGE, // 首页
|
||||
CHECK_ENV_PAGE, // 环境检测页
|
||||
BACKUP_PAGE, // 还原中页
|
||||
RESTORE_PAGE, // 还原中页
|
||||
LAST_PAGE, // 结束页
|
||||
};
|
||||
|
||||
|
@ -31,10 +31,15 @@ public:
|
|||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initThirdWidget();
|
||||
void initLastWidget();
|
||||
|
||||
signals:
|
||||
void startCheckEnv();
|
||||
void checkEnvResult(bool result, const QString &errMsg = "", const QString &errTip = "");
|
||||
void startRestore();
|
||||
void progress(int state, int rate);
|
||||
void checkRestoreResult(bool result, const QString &errMsg = "", const QString &errTip = "");
|
||||
|
||||
public slots:
|
||||
void on_pre_clicked(bool checked = false);
|
||||
|
@ -42,6 +47,9 @@ public slots:
|
|||
void on_button_beginRestore_clicked(bool checked = false);
|
||||
void on_checkEnv_start();
|
||||
void on_checkEnv_end(int result);
|
||||
void on_restore_start();
|
||||
void on_checkRestore_end(int result);
|
||||
void on_restore_end(bool result);
|
||||
|
||||
private:
|
||||
// 是否保留用户数据
|
||||
|
@ -54,7 +62,7 @@ private:
|
|||
|
||||
QString m_uuid; // 还原点的UUID
|
||||
QString m_devPath; // 如果是从移动设备进行还原,此中保存移动设备挂载路径
|
||||
bool m_isOtherMachine;
|
||||
bool m_isOtherMachine; // 是否异机备份点还原
|
||||
// 系统备份状态
|
||||
int m_systemRestoreState;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue