本地备份数据还原

This commit is contained in:
zhaominyong 2021-12-28 16:51:35 +08:00
parent 11d0d3e9bb
commit 31a86f8b19
16 changed files with 1359 additions and 67 deletions

View File

@ -32,6 +32,7 @@ HEADERS += \
../common/utils.h \
backupmanager_adaptor.h \
databackupproxy.h \
datarestoreproxy.h \
deletebackupproxy.h \
mybackupmanager.h \
mymountproxy.h \
@ -56,6 +57,7 @@ SOURCES += \
../common/utils.cpp \
backupmanager_adaptor.cpp \
databackupproxy.cpp \
datarestoreproxy.cpp \
deletebackupproxy.cpp \
main.cpp \
mybackupmanager.cpp \

View File

@ -113,11 +113,19 @@ int ManagerAdaptor::goRestore(BackupWrapper backupWrapper)
return out0;
}
int ManagerAdaptor::cancel(BackupWrapper backupWrapper)
int ManagerAdaptor::cancel()
{
// handle method call com.kylin.backup.manager.goRestore
// handle method call com.kylin.backup.manager.cancel
int out0;
QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0));
return out0;
}
int ManagerAdaptor::reboot()
{
// handle method call com.kylin.backup.manager.reboot
int out0;
QMetaObject::invokeMethod(parent(), "reboot", Q_RETURN_ARG(int, out0));
return out0;
}

View File

@ -110,8 +110,6 @@ class ManagerAdaptor: public QDBusAbstractAdaptor
" </method>\n"
" <method name=\"cancel\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" </interface>\n"
"")
@ -131,7 +129,8 @@ public Q_SLOTS: // METHODS
int ghostBackup(BackupWrapper backupWrapper);
int goBackup(BackupWrapper backupWrapper);
int goRestore(BackupWrapper backupWrapper);
int cancel(BackupWrapper backupWrapper);
int cancel();
int reboot();
Q_SIGNALS: // SIGNALS
void backupFinished(bool result);
void progress(int in0, int in1);

View File

@ -0,0 +1,139 @@
#include "datarestoreproxy.h"
#include <QDateTime>
#include <QDir>
#include <QDebug>
#include <unistd.h>
#include <sys/reboot.h>
#include "../common/utils.h"
#include "mymountproxy.h"
IMPLEMENT_DYNCREATE(DataRestoreProxy)
/**
* @brief
*/
DataRestoreProxy::DataRestoreProxy()
{
m_bSuccess = false;
m_p = nullptr;
}
/**
* @brief
*/
DataRestoreProxy::~DataRestoreProxy()
{
delete m_p;
}
/**
* @brief
* @return false,;true,
*/
bool DataRestoreProxy::checkEnvEx()
{
qDebug() << "DataRestoreProxy::checkEnvEx invoke begin";
// 1、检测.user.txt是否存在
m_userFile = Utils::getSysRootPath() + 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 = Utils::getSysRootPath() + 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 = Utils::getSysRootPath() + 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;
}
emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
qDebug() << "DataRestoreProxy::checkEnvEx invoke end";
return true;
}
/**
* @brief
*/
void DataRestoreProxy::doWorkEx()
{
qDebug() << "DataRestoreProxy::doWorkEx invoke begin";
// 1、校验
if (!checkEnvEx())
return ;
// 2、还原数据
restoreData();
qDebug() << "DataRestoreProxy::doWorkEx invoke end";
}
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList DataRestoreProxy::getRsyncArgs(DataRestoreScene scene)
{
QStringList args;
args << "-avAHXr";
args << "--info=progress2";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
switch (scene) {
case DataRestoreScene::DATA_RESTORE :
args << "--files-from" << m_userFile;
break ;
default:
return args;
}
return args;
}
/**
* @brief
*/
void DataRestoreProxy::restoreData()
{
m_srcPath = m_backupPath;
QString destPath = Utils::getSysRootPath();
QStringList args = getRsyncArgs(DataRestoreScene::DATA_RESTORE);
args << m_srcPath + "/";
args << destPath + "/";
m_p = new RsyncPathToDirProcess(this);
connect(m_p, &RsyncPathToDirProcess::progress, this, &DataRestoreProxy::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));
}
emit this->workResult(result);
});
m_p->start(args, false);
}

View File

@ -0,0 +1,59 @@
#ifndef DATARESTOREPROXY_H
#define DATARESTOREPROXY_H
#include "workerfactory.h"
#include "myprocess/rsyncpathtodirprocess.h"
#include "parsebackuplist.h"
class DataRestoreProxy : public Worker
{
Q_OBJECT
DECLARE_DYNCREATE(DataRestoreProxy)
public:
// 数据还原的几种场景
enum DataRestoreScene {
DATA_RESTORE, // 数据还原
};
explicit DataRestoreProxy();
virtual ~DataRestoreProxy();
public:
// 环境检测
virtual bool checkEnvEx();
// 任务处理
virtual void doWorkEx();
private:
// 数据还原
void restoreData();
/**
* @brief rsync命令参数
* @param scene
* @return rsync的参数信息
*/
QStringList getRsyncArgs(DataRestoreScene scene);
// .user.txt文件路径
QString m_userFile;
// .exclude.user.txt文件路径
QString m_excludeUserFile;
// 备份数据所在的data目录
QString m_backupPath;
// 是否还原成功
bool m_bSuccess;
// 当前备份uuid
QString m_curUuid;
// 当前还原源目录
QString m_srcPath;
// 还原进程
RsyncPathToDirProcess *m_p;
// 当前备份节点
ParseBackupList::BackupPoint m_backupPoint;
};
#endif // DATARESTOREPROXY_H

View File

@ -4,6 +4,7 @@
#include <QTimer>
#include <mutex>
#include <sys/reboot.h>
#include <kysec/status.h>
#include "mybackupmanager.h"
#include "../common/utils.h"
@ -179,8 +180,7 @@ int MyBackupManager::goRestore(const BackupWrapper& backupWrapper)
switch (result) {
case int(BackupResult::CHECK_ENV_SUCCESS) :
case int(BackupResult::MKSQUASHFS_START_SUCCESS) :
case int(BackupResult::BACKUP_START_SUCCESS) :
case int(BackupResult::RESTORE_START_SUCCESS) :
break;
default:
this->finished();
@ -191,13 +191,12 @@ int MyBackupManager::goRestore(const BackupWrapper& backupWrapper)
emit this->progress(int(BackupState::WORKING), rate);
});
connect(worker, &Worker::workResult, this, [&] (bool result) {
emit this->backupFinished(result);
emit this->sendRestoreResult(result);
this->finished();
});
worker->moveToThread(&workerThread);
connect(&workerThread, &MyThread::started, worker, &Worker::doWork);
connect(&workerThread, &MyThread::finished, worker, &Worker::deleteLater);
connect(&workerThread, &MyThread::cancelWork, worker, &Worker::cancel);
workerThread.start();
@ -294,16 +293,23 @@ int MyBackupManager::getBackupState(bool& isActive)
/**
* @brief
*/
int MyBackupManager::cancel(const BackupWrapper& backupWrapper)
int MyBackupManager::cancel()
{
Q_UNUSED(backupWrapper)
if (workerThread.isRunning())
emit workerThread.cancelWork();
return 0;
}
/**
* @brief
* @return
*/
int MyBackupManager::reboot()
{
return ::reboot(RB_AUTOBOOT);;
}
/**
* @brief
*/

View File

@ -61,7 +61,9 @@ public slots:
// 获取备份状态
int getBackupState(bool& isActive);
// 取消操作
int cancel(const BackupWrapper& backupWrapper);
int cancel();
// 重启操作
int reboot();
// 任务结束
void finished();

View File

@ -126,6 +126,11 @@ public Q_SLOTS: // METHODS
return asyncCall(QStringLiteral("cancel"));
}
inline QDBusPendingReply<> reboot()
{
return asyncCall(QStringLiteral("reboot"));
}
Q_SIGNALS: // SIGNALS
void backupFinished(bool result);
void progress(int in0, int in1);

View File

@ -60,6 +60,7 @@ HEADERS += \
maindialog.h \
messageboxutils.h \
module/databackup.h \
module/datarestore.h \
module/managebackuppointlist.h \
module/selectrestorepoint.h \
module/systembackup.h \
@ -99,6 +100,7 @@ SOURCES += \
maindialog.cpp \
messageboxutils.cpp \
module/databackup.cpp \
module/datarestore.cpp \
module/managebackuppointlist.cpp \
module/selectrestorepoint.cpp \
module/systembackup.cpp \

View File

@ -11,8 +11,10 @@
#include "module/systembackup.h"
#include "module/systemrestore.h"
#include "module/databackup.h"
#include "module/datarestore.h"
#include "backup_manager_interface.h"
#include "globalbackupinfo.h"
#include "messageboxutils.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
@ -216,6 +218,10 @@ void MainDialog::selected(int func_type)
m_stackedWidget = new DataBackup(ui->centralwidget);
GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::BACKUP_DATA);
break;
case FuncTypeConverter::FunType::RESTORE_DATA:
m_stackedWidget = new DataRestore(ui->centralwidget);
GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::RESTORE_DATA);
break;
default:
m_stackedWidget = new SystemBackup(ui->centralwidget);
GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::BACKUP_SYSTEM);
@ -257,31 +263,23 @@ void MainDialog::mountBackupPartition()
reply.waitForFinished();
if (reply.isError()) {
// 挂载分区时出现异常
QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("An exception occurred when mounting backup partition."), QMessageBox::Ok, this);
// box.setStandardButtons(QMessageBox::Ok);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
QObject::tr("An exception occurred when mounting backup partition."),
QObject::tr("Ok"));
closeBtn();
} else if (int(MountResult::CANNOT_GET_BACKUPUUID) == reply.value()) {
// 没有找到备份分区,只能备份到移动设备中
QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("There's no backup partition, can only backup to removable device."), QMessageBox::Ok, this);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
QObject::tr("There's no backup partition, can only backup to removable device."),
QObject::tr("Ok"));
GlobelBackupInfo::inst().setHasBackupPartition(false);
} else if (int(MountResult::MOUNTED) != reply.value()) {
// 挂载备份分区失败
QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("Failed to mount backup partition."), QMessageBox::Ok, this);
// box.setStandardButtons(QMessageBox::Ok);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
QObject::tr("Failed to mount backup partition."),
QObject::tr("Ok"));
closeBtn();
}
@ -297,12 +295,10 @@ void MainDialog::umountBackupPartition()
void MainDialog::closeBtn()
{
if (GlobelBackupInfo::inst().isBusy()) {
QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("It's busy, please wait"), QMessageBox::Ok, this);
// box.setStandardButtons(QMessageBox::Ok);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
// 系统正忙,请稍等
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
QObject::tr("It's busy, please wait"),
QObject::tr("Ok"));
return;
}

View File

@ -1024,7 +1024,7 @@ void DataBackup::initForthWidget()
labelBackupName->setDeplayText(tr("Backup Name"));
MyLineEdit *editBackupName = new MyLineEdit(forth);
editBackupName->setGeometry(238, 172, 350, 40);
editBackupName->setMaxLength(100);
editBackupName->setMaxLength(64);
if (m_backupName.isEmpty())
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
else {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
#ifndef DATARESTORE_H
#define DATARESTORE_H
#include <QStackedWidget>
#include "../backup_manager_interface.h"
#include "../backup-daemon/parsebackuplist.h"
class DataRestore : public QStackedWidget
{
Q_OBJECT
public:
enum DataRestoreState
{
IDEL = 0, // 空闲
CHECKING, // 环境校验中
RESTORING // 还原中
};
enum DataRestorePage
{
HOME_PAGE, // 首页
CHECK_ENV_PAGE, // 环境检测页
RESTORE_PAGE, // 还原中页
LAST_PAGE, // 结束页
};
public:
explicit DataRestore(QWidget *parent = nullptr);
virtual ~DataRestore();
private:
void initFirstWidget();
void initSecondWidget();
void initThirdWidget();
void initLastWidget();
bool checkIsNeedReboot();
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);
void on_next_clicked(bool checked = false);
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);
void reboot();
private:
// dbus接口
ComKylinBackupManagerInterface *m_pInterface;
QString m_uuid; // 还原点的UUID
QString m_devPath; // 如果是从移动设备进行还原,此中保存移动设备挂载路径
// 系统备份状态
int m_dataRestoreState;
// 是否需要重启
bool m_bNeedReboot;
};
#endif // DATARESTORE_H

View File

@ -20,8 +20,8 @@ SelectRestorePoint::SelectRestorePoint(QWidget *parent, BackupPointType backupTy
initTableWidget();
// 刷新
MyPushButton * buttonRefresh = new MyPushButton;
buttonRefresh->setText(tr("Refresh"));
// MyPushButton * buttonRefresh = new MyPushButton;
// buttonRefresh->setText(tr("Refresh"));
// 确定按钮
MyPushButton * buttonOk = new MyPushButton;
@ -29,11 +29,11 @@ SelectRestorePoint::SelectRestorePoint(QWidget *parent, BackupPointType backupTy
this->setResult(QDialog::Rejected);
m_bottomLayout->addStretch();
m_bottomLayout->addWidget(buttonRefresh);
// m_bottomLayout->addWidget(buttonRefresh);
m_bottomLayout->addSpacing(10);
m_bottomLayout->addWidget(buttonOk);
connect(buttonRefresh, &MyPushButton::clicked, this, &SelectRestorePoint::initTableWidget);
// connect(buttonRefresh, &MyPushButton::clicked, this, &SelectRestorePoint::initTableWidget);
connect(this, &SelectRestorePoint::udiskChange, this, &SelectRestorePoint::initTableWidget);
connect(buttonOk, &MyPushButton::clicked, this, [=](){

View File

@ -613,7 +613,7 @@ void SystemBackup::initForthWidget()
labelBackupName->setDeplayText(tr("Backup Name"));
MyLineEdit *editBackupName = new MyLineEdit(forth);
editBackupName->setGeometry(238, 172, 350, 40);
editBackupName->setMaxLength(100);
editBackupName->setMaxLength(64);
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
// 支持输入中英文数字和部分字符
// QRegExp regx("^[\u4e00-\u9fa5a-zA-Z0-9~!@#$%^&*()-_+={}':;'\\[\\].<>/? ¥()——;《》‘’:“”、?]+$"); //其中匹配中文[\u4e00-\u9fa5]

View File

@ -82,33 +82,33 @@ void SystemRestore::initFirstWidget()
labelNote_firstPage->setScaledContents(true);
labelNote_firstPage->adjustSize();
// 多点还原
MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
iconMultiBackup_firstPage->setGeometry(41, 244, 180, 36);
iconMultiBackup_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic", ":/symbos/ukui-bf-many-spot-symbolic.png");
iconMultiBackup_firstPage->setDesplayText(tr("Multi-Spot"));
iconMultiBackup_firstPage->setEnabled(false);
// 操作简单
MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
iconSimple_firstPage->setGeometry(41, 244, 180, 36);
iconSimple_firstPage->setThemeIcon("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic.png");
iconSimple_firstPage->setDesplayText(tr("Simple"));
iconSimple_firstPage->setEnabled(false);
// 体积小
MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
iconSmallSize_firstPage->setGeometry(201, 244, 180, 36);
iconSmallSize_firstPage->setThemeIcon("ukui-bf-volume-symbolic", ":/symbos/ukui-bf-volume-symbolic.png");
iconSmallSize_firstPage->setDesplayText(tr("Small Size"));
iconSmallSize_firstPage->setEnabled(false);
// 安全
// 安全可靠
MyIconLabel *iconSecurity_firstPage = new MyIconLabel(first);
iconSecurity_firstPage->setGeometry(41, 296, 180, 36);
iconSecurity_firstPage->setGeometry(201, 244, 180, 36);
iconSecurity_firstPage->setThemeIcon("ukui-bf-security-symbolic", ":/symbos/ukui-bf-security-symbolic.png");
iconSecurity_firstPage->setDesplayText(tr("Security"));
iconSecurity_firstPage->setEnabled(false);
// 操作简单
MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
iconSimple_firstPage->setGeometry(201, 296, 180, 36);
iconSimple_firstPage->setThemeIcon("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic.png");
iconSimple_firstPage->setDesplayText(tr("Simple"));
iconSimple_firstPage->setEnabled(false);
// 修复系统损坏
MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
iconMultiBackup_firstPage->setGeometry(41, 296, 180, 36);
iconMultiBackup_firstPage->setThemeIcon("ukui-bf-damage-symbolic", ":/symbos/ukui-bf-damage-symbolic.png");
iconMultiBackup_firstPage->setDesplayText(tr("Repair"));
iconMultiBackup_firstPage->setEnabled(false);
// 自主操作
MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
iconSmallSize_firstPage->setGeometry(201, 296, 180, 36);
iconSmallSize_firstPage->setThemeIcon("document-properties-symbolic", ":/symbos/document-properties-symbolic.png");
iconSmallSize_firstPage->setDesplayText(tr("Independent"));
iconSmallSize_firstPage->setEnabled(false);
// 开始还原按钮
MyPushButton *beginRestore = new MyPushButton(first);
@ -345,7 +345,7 @@ void SystemRestore::initSecondWidget()
nextStep->setAutoRepeat(true);
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
this->on_next_clicked(checked);
this->startRestore();
emit this->startRestore();
});
hlayoutCenterFont5->addWidget(nextStep);
// 重新检测按钮
@ -797,7 +797,7 @@ void SystemRestore::initLastWidget()
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));
LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
QHBoxLayout *layoutLine1 = new QHBoxLayout;
layoutLine1->addStretch();
@ -946,7 +946,7 @@ void SystemRestore::initLastWidget()
connect(retry, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
this->setCurrentIndex(SystemRestorePage::RESTORE_PAGE);
this->startRestore();
emit this->startRestore();
});
addWidget(last);