Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Remove the lp-gui and lp-tray from the projects tree, it is in the ma…

…in src-qt4 tree now.
  • Loading branch information...
commit 541f93150f1a9e583916e09826424e246d98cdbf 1 parent eb30fda
@beanpole135 beanpole135 authored
Showing with 0 additions and 27,167 deletions.
  1. +0 −357 lp-gui/LPBackend.cpp
  2. +0 −53 lp-gui/LPBackend.h
  3. +0 −171 lp-gui/LPConfig.cpp
  4. +0 −39 lp-gui/LPConfig.h
  5. +0 −397 lp-gui/LPConfig.ui
  6. +0 −33 lp-gui/LPContainers.h
  7. +0 −254 lp-gui/LPGUtils.cpp
  8. +0 −28 lp-gui/LPGUtils.h
  9. +0 −671 lp-gui/LPMain.cpp
  10. +0 −84 lp-gui/LPMain.h
  11. +0 −654 lp-gui/LPMain.ui
  12. +0 −58 lp-gui/LPWizard.cpp
  13. +0 −35 lp-gui/LPWizard.h
  14. +0 −627 lp-gui/LPWizard.ui
  15. +0 −439 lp-gui/i18n/LifePreserver_af.ts
  16. +0 −439 lp-gui/i18n/LifePreserver_ar.ts
  17. +0 −439 lp-gui/i18n/LifePreserver_az.ts
  18. +0 −439 lp-gui/i18n/LifePreserver_bg.ts
  19. +0 −439 lp-gui/i18n/LifePreserver_bn.ts
  20. +0 −439 lp-gui/i18n/LifePreserver_bs.ts
  21. +0 −439 lp-gui/i18n/LifePreserver_ca.ts
  22. +0 −439 lp-gui/i18n/LifePreserver_cs.ts
  23. +0 −439 lp-gui/i18n/LifePreserver_cy.ts
  24. +0 −439 lp-gui/i18n/LifePreserver_da.ts
  25. +0 −439 lp-gui/i18n/LifePreserver_de.ts
  26. +0 −439 lp-gui/i18n/LifePreserver_el.ts
  27. +0 −439 lp-gui/i18n/LifePreserver_en_GB.ts
  28. +0 −439 lp-gui/i18n/LifePreserver_en_US.ts
  29. +0 −439 lp-gui/i18n/LifePreserver_en_ZA.ts
  30. +0 −439 lp-gui/i18n/LifePreserver_es.ts
  31. +0 −439 lp-gui/i18n/LifePreserver_et.ts
  32. +0 −439 lp-gui/i18n/LifePreserver_eu.ts
  33. +0 −439 lp-gui/i18n/LifePreserver_fa.ts
  34. +0 −439 lp-gui/i18n/LifePreserver_fi.ts
  35. +0 −439 lp-gui/i18n/LifePreserver_fr.ts
  36. +0 −439 lp-gui/i18n/LifePreserver_fr_CA.ts
  37. +0 −439 lp-gui/i18n/LifePreserver_fur.ts
  38. +0 −439 lp-gui/i18n/LifePreserver_gl.ts
  39. +0 −439 lp-gui/i18n/LifePreserver_he.ts
  40. +0 −439 lp-gui/i18n/LifePreserver_hi.ts
  41. +0 −439 lp-gui/i18n/LifePreserver_hr.ts
  42. +0 −439 lp-gui/i18n/LifePreserver_hu.ts
  43. +0 −439 lp-gui/i18n/LifePreserver_id.ts
  44. +0 −439 lp-gui/i18n/LifePreserver_is.ts
  45. +0 −439 lp-gui/i18n/LifePreserver_it.ts
  46. +0 −439 lp-gui/i18n/LifePreserver_ja.ts
  47. +0 −439 lp-gui/i18n/LifePreserver_ka.ts
  48. +0 −439 lp-gui/i18n/LifePreserver_ko.ts
  49. +0 −439 lp-gui/i18n/LifePreserver_lt.ts
  50. +0 −439 lp-gui/i18n/LifePreserver_lv.ts
  51. +0 −439 lp-gui/i18n/LifePreserver_mk.ts
  52. +0 −439 lp-gui/i18n/LifePreserver_mn.ts
  53. +0 −439 lp-gui/i18n/LifePreserver_ms.ts
  54. +0 −439 lp-gui/i18n/LifePreserver_mt.ts
  55. +0 −439 lp-gui/i18n/LifePreserver_nb.ts
  56. +0 −439 lp-gui/i18n/LifePreserver_ne.ts
  57. +0 −439 lp-gui/i18n/LifePreserver_nl.ts
  58. +0 −439 lp-gui/i18n/LifePreserver_pa.ts
  59. +0 −439 lp-gui/i18n/LifePreserver_pl.ts
  60. +0 −439 lp-gui/i18n/LifePreserver_pt.ts
  61. +0 −439 lp-gui/i18n/LifePreserver_pt_BR.ts
  62. +0 −439 lp-gui/i18n/LifePreserver_ro.ts
  63. +0 −439 lp-gui/i18n/LifePreserver_ru.ts
  64. +0 −439 lp-gui/i18n/LifePreserver_sa.ts
  65. +0 −439 lp-gui/i18n/LifePreserver_sk.ts
  66. +0 −439 lp-gui/i18n/LifePreserver_sl.ts
  67. +0 −439 lp-gui/i18n/LifePreserver_sr.ts
  68. +0 −439 lp-gui/i18n/LifePreserver_sv.ts
Sorry, we could not display the entire diff because it was too big.
View
357 lp-gui/LPBackend.cpp
@@ -1,357 +0,0 @@
-#include "LPBackend.h"
-
-// ==============
-// Informational
-// ==============
-QStringList LPBackend::listPossibleDatasets(){
- QString cmd = "zpool list -H -o name";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output (one dataset per line - no headers)
- QStringList list;
- for(int i=0; i<out.length(); i++){
- QString ds = out[i].section("/",0,0).simplified();
- if(!ds.isEmpty()){ list << ds; }
- }
- list.removeDuplicates();
-
- return list;
-}
-
-QStringList LPBackend::listDatasets(){
- QString cmd = "lpreserver listcron";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- QStringList list;
- for(int i=2; i<out.length(); i++){ //skip the first two lines (headers)
- QString ds = out[i].section(" - ",0,0).simplified();
- if(!ds.isEmpty()){ list << ds; }
- }
-
- return list;
-}
-
-QStringList LPBackend::listDatasetSubsets(QString dataset){
- QString cmd = "zfs list -H -t filesystem -o name,mountpoint,mounted";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output (one dataset per line - no headers)
- QStringList list;
- for(int i=0; i<out.length(); i++){
- if(out[i].startsWith(dataset+"/")){
- if(out[i].section("\t",2,2,QString::SectionSkipEmpty).simplified() == "yes"){
- QString ds = out[i].section("\t",1,1).simplified(); //save the mountpoint
- if(!ds.isEmpty()){ list << ds; }
- }
- }
- }
- list.removeDuplicates();
-
- return list;
-}
-
-QStringList LPBackend::listSnapshots(QString dsmountpoint){
- //List all the snapshots available for the given dataset mountpoint
- QDir dir(dsmountpoint+"/.zfs/snapshot");
- QStringList list;
- if(dir.exists()){
- list = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time | QDir::Reversed);
- }
- return list;
-}
-
-QStringList LPBackend::listLPSnapshots(QString dataset){
- QString cmd = "lpreserver listsnap "+dataset;
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- QStringList list;
- for(int i=0; i<out.length(); i++){ //oldest ->newest
- if(out[i].startsWith(dataset+"@")){
- QString snap = out[i].section("@",1,3).section(" ",0,0).simplified();;
- if(!snap.isEmpty()){ list << snap; }
- }
- }
-
- return list;
-}
-
-QStringList LPBackend::listReplicationTargets(){
- QString cmd = "lpreserver replicate list";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- QStringList list;
- for(int i=0; i<out.length(); i++){
- if(out[i].contains("->")){
- QString ds = out[i].section("->",0,0).simplified();
- if(!ds.isEmpty()){ list << ds; }
- }
- }
-
- return list;
-}
-
-QStringList LPBackend::listCurrentStatus(){
- QString cmd = "lpreserver status";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- QStringList list;
- for(int i=2; i<out.length(); i++){ //first 2 lines are headers
- //Format: <dataset>:::<lastsnapshot | NONE>:::<lastreplication | NONE>
- if(out[i].isEmpty()){ continue; }
- QString ds = out[i].section(" - ",0,0).simplified();
- QString snap = out[i].section(" - ",1,1).simplified();
- QString rep = out[i].section(" - ",2,2).simplified();
- if(snap == "NONE"){ snap = "-"; }
- if(rep == "NONE"){ rep = "-"; }
- list << ds +":::"+ snap+":::"+rep;
- }
-
- return list;
-}
-
-// ==================
-// Dataset Management
-// ==================
-bool LPBackend::setupDataset(QString dataset, int time, int numToKeep){
- //Configure inputs
- QString freq;
- if(time == -30){ freq = "30min"; }
- else if(time == -10){ freq = "10min"; }
- else if(time == -5){ freq = "5min"; }
- else if(time >= 0 && time < 24){ freq = "daily@"+QString::number(time); }
- else{ freq = "hourly"; }
-
- //Create the command
- QString cmd = "lpreserver cronsnap "+dataset+" start "+freq+" "+QString::number(numToKeep);
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-bool LPBackend::removeDataset(QString dataset){
- QString cmd = "lpreserver cronsnap "+dataset+" stop";
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-bool LPBackend::datasetInfo(QString dataset, int& time, int& numToKeep){
- QString cmd = "lpreserver listcron";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- bool ok = false;
- for(int i=0; i<out.length(); i++){
- if(out[i].section(" - ",0,0).simplified() == dataset){
- //Get time schedule (in integer format)
- QString sch = out[i].section(" - ",1,1).simplified();
- if(sch.startsWith("daily@")){ time = sch.section("@",1,1).simplified().toInt(); }
- else if(sch=="5min"){time = -5;}
- else if(sch=="10min"){time = -10;}
- else if(sch=="30min"){time = -30;}
- else{ time = -60; } //hourly
- //Get total snapshots
- numToKeep = out[i].section("- total:",1,1).simplified().toInt();
- ok=true;
- break;
- }
- }
- //qDebug() << "lpreserver cronsnap:\n" << out << QString::number(time) << QString::number(numToKeep);
-
- return ok;
-}
-
-// ==================
-// Snapshop Management
-// ==================
-void LPBackend::newSnapshot(QString dataset, QString snapshotname){
- //This needs to run externally - since the snapshot is simply added to the queue, and the replication
- // afterwards may take a long time.
- QString cmd = "lpreserver mksnap --replicate "+dataset+" "+snapshotname;
- QProcess::startDetached(cmd);
-
- return;
-}
-
-bool LPBackend::removeSnapshot(QString dataset, QString snapshot){
- QString cmd = "lpreserver rmsnap "+dataset +" "+snapshot;
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-bool LPBackend::revertSnapshot(QString dataset, QString snapshot){
- QString cmd = "lpreserver revertsnap "+dataset +" "+snapshot;
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-// ==================
-// Replication Management
-// ==================
-bool LPBackend::setupReplication(QString dataset, QString remotehost, QString user, int port, QString remotedataset, int time){
- QString stime = "sync"; //synchronize on snapshot creation (default)
- if(time >= 0 && time < 24){ stime = QString::number(time); } //daily at a particular hour (24 hour notation)
-
-
- QString cmd = "lpreserver replicate add "+remotehost+" "+user+" "+ QString::number(port)+" "+dataset+" "+remotedataset+" "+stime;
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-bool LPBackend::removeReplication(QString dataset){
- QString cmd = "lpreserver replicate remove "+dataset;
- int ret = LPBackend::runCmd(cmd);
-
- return (ret == 0);
-}
-
-bool LPBackend::replicationInfo(QString dataset, QString& remotehost, QString& user, int& port, QString& remotedataset, int& time){
- QString cmd = "lpreserver replicate list";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- bool ok = false;
- for(int i=0; i<out.length(); i++){
- if(out[i].contains("->") && out[i].startsWith(dataset)){
- QString data = out[i].section("->",1,1);
- user = data.section("@",0,0);
- remotehost = data.section("@",1,1).section("[",0,0);
- port = data.section("[",1,1).section("]",0,0).toInt();
- remotedataset = data.section(":",1,1).section(" Time",0,0);
- QString synchro = data.section("Time:",1,1).simplified();
- if(synchro == "sync"){ time = -1; }
- else{ time = synchro.toInt(); }
- ok = true;
- break;
- }
- }
-
- return ok;
-}
-
-// ======================
-// SSH Key Management
-// ======================
-bool LPBackend::setupSSHKey(QString remoteHost, QString remoteUser, int remotePort){
- QString LPPATH = "/usr/local/share/lifePreserver";
- QString cmd = "xterm -e \""+LPPATH+"/scripts/setup-ssh-keys.sh "+remoteUser+" "+remoteHost+" "+QString::number(remotePort)+"\"";
- int ret = LPBackend::runCmd(cmd);
- return (ret == 0);
-}
-
-QStringList LPBackend::findValidUSBDevices(){
- //Return format: "<mountpoint> (<device node>")
- QString cmd = "mount";
- QStringList out = LPBackend::getCmdOutput(cmd);
- //Now process the output
- QStringList list;
- for(int i=0; i<out.length(); i++){
- if(out[i].startsWith("/dev/da") && out[i].contains("(msdosfs,")){
- QString mountpoint = out[i].section(" on ",1,1).section("(",0,0).simplified();
- QString devnode = out[i].section(" on ",0,0).section("/",-1).simplified();
- list << mountpoint +" ("+devnode+")";
- }
- }
- return list;
-}
-
-bool LPBackend::copySSHKey(QString mountPath, QString localHost){
- QString publicKey = "/root/.ssh/id_rsa";
- //copy the file onto the designated USB stick
- if(!mountPath.endsWith("/")){ mountPath.append("/"); }
- QDir lDir=mountPath + "lpreserver";
- if ( ! lDir.exists() )
- lDir.mkdir(lDir.path());
-
- mountPath.append("lpreserver/"+localHost+"-id_rsa");
-
- bool ok = QFile::copy(publicKey, mountPath);
- return ok;
-}
-
-// ======================
-// USB Device Management
-// ======================
-QStringList LPBackend::listDevices(){
- //Scan the system for all valid da* and ada* devices (USB/SCSI, SATA)
- //Return format: "<device node> (<device information>)"
- QDir devDir("/dev");
- QStringList devs = devDir.entryList(QStringList() << "da*"<<"ada*", QDir::System | QDir::NoSymLinks, QDir::Name);
- QStringList camOut = LPBackend::getCmdOutput("camcontrol devlist");
- QStringList output, flist;
- for(int i=0; i<devs.length(); i++){
- flist = camOut.filter("("+devs[i]+",");
- //still need to add an additional device filter to weed out devices currently in use.
- if(!flist.isEmpty()){ output << devs[i] + " ("+flist[0].section(">",0,0).remove("<").simplified()+")"; }
- }
- return output;
-}
-
-bool LPBackend::isMounted(QString device){
- qDebug() << "Device mount check not implemented yet:" << device;
- return false;
-}
-
-bool LPBackend::unmountDevice(QString device){
- qDebug() << "Device unmounting not implemented yet:" << device;
- return false;
-}
-
-// ======================
-// ZPOOL Disk Management
-// ======================
-bool LPBackend::attachDisk(QString pool, QString disk){
- if( !disk.startsWith("/dev/") ){ disk.prepend("/dev/"); } //make sure it is the full disk path
- if( !QFile::exists(disk) ){ return false; } //make sure the disk exists
- QString cmd = "lpreserver zpool attach "+pool+" "+disk;
- //Run the command
- int ret = LPBackend::runCmd(cmd);
- return (ret ==0);
-}
-
-bool LPBackend::detachDisk(QString pool, QString disk){
- QString cmd = "lpreserver zpool detach "+pool+" "+disk;
- //Run the command
- int ret = LPBackend::runCmd(cmd);
- return (ret ==0);
-}
-
-bool LPBackend::setDiskOnline(QString pool, QString disk){
- QString cmd = "lpreserver zpool online "+pool+" "+disk;
- //Run the command
- int ret = LPBackend::runCmd(cmd);
- return (ret ==0);
-}
-
-bool LPBackend::setDiskOffline(QString pool, QString disk){
- QString cmd = "lpreserver zpool offline "+pool+" "+disk;
- //Run the command
- int ret = LPBackend::runCmd(cmd);
- return (ret ==0);
-}
-
-// =========================
-// PRIVATE FUNCTIONS
-// =========================
-QStringList LPBackend::getCmdOutput(QString cmd){
- QProcess *proc = new QProcess;
- proc->setProcessChannelMode(QProcess::MergedChannels);
- proc->start(cmd);
- while(!proc->waitForFinished(300)){
- QCoreApplication::processEvents();
- }
- QStringList out = QString(proc->readAllStandardOutput()).split("\n");
- delete proc;
- return out;
-}
-
-int LPBackend::runCmd(QString cmd){
- QProcess *proc = new QProcess;
- proc->setProcessChannelMode(QProcess::MergedChannels);
- proc->start(cmd);
- while(!proc->waitForFinished(300)){
- QCoreApplication::processEvents();
- }
- int ret = proc->exitCode();
- delete proc;
- return ret;
-}
View
53 lp-gui/LPBackend.h
@@ -1,53 +0,0 @@
-#ifndef _LP_BACKEND_H
-#define _LP_BACKEND_H
-
-#include <QProcess>
-#include <QString>
-#include <QStringList>
-#include <QDebug>
-#include <QDir>
-#include <QCoreApplication>
-
-//Class of static functions for using the "lpreserver" backend
-class LPBackend{
-
-public:
- //Informational
- static QStringList listPossibleDatasets(); //list all possible datasets on the system
- static QStringList listDatasets(); //list all current lifepreserver datasets
- static QStringList listDatasetSubsets(QString dataset); //list all subsets of the main dataset
- static QStringList listSnapshots(QString dsmountpoint); //list all snapshots for a particular dataset mountpoint
- static QStringList listLPSnapshots(QString dataset); //list all snapshots created by life preserver
- static QStringList listReplicationTargets(); //list all datasets with replication enabled
- static QStringList listCurrentStatus(); //list the current snapshot/replication status
- //Dataset Management
- static bool setupDataset(QString dataset, int time, int numToKeep); //add or configure dataset
- static bool removeDataset(QString dataset);
- static bool datasetInfo(QString dataset, int& time, int& numToKeep); //get current settings for a dataset
- //Snapshop Management
- static void newSnapshot(QString dataset, QString snapshotname);
- static bool removeSnapshot(QString dataset, QString snapshot);
- static bool revertSnapshot(QString dataset, QString snapshot); //revert to given snapshot
- //Replication Management
- static bool setupReplication(QString dataset, QString remotehost, QString user, int port, QString remotedataset, int time);
- static bool removeReplication(QString dataset);
- static bool replicationInfo(QString dataset, QString& remotehost, QString& user, int& port, QString& remotedataset, int& time);
- //SSH Key Management
- static bool setupSSHKey(QString remoteHost, QString remoteUser, int remotePort);
- static QStringList findValidUSBDevices();
- static bool copySSHKey(QString mountPath, QString localHost);
- //USB Device Management
- static QStringList listDevices();
- static bool isMounted(QString device);
- static bool unmountDevice(QString device);
- //Zpool disk Management
- static bool attachDisk(QString pool, QString disk);
- static bool detachDisk(QString pool, QString disk);
- static bool setDiskOnline(QString pool, QString disk);
- static bool setDiskOffline(QString pool, QString disk);
- //General utility functions
- static QStringList getCmdOutput(QString);
- static int runCmd(QString);
-
-};
-#endif
View
171 lp-gui/LPConfig.cpp
@@ -1,171 +0,0 @@
-#include "LPConfig.h"
-#include "ui_LPConfig.h"
-
-LPConfig::LPConfig(QWidget *parent) : QDialog(parent), ui(new Ui::LPConfig){
- ui->setupUi(this); //initialize the designer UI
- qDebug() << "Initializing Configuration Dialog";
- //initialize the output variables as necessary
- localChanged = false;
- remoteChanged = false;
- //Variables that will be changed when loading the dataset properties
-
- //now connect the buttons
- connect(ui->tool_apply,SIGNAL(clicked()), this,SLOT(slotApplyChanges()) );
- connect(ui->tool_cancel,SIGNAL(clicked()), this, SLOT(slotCancelConfig()) );
-}
-
-LPConfig::~LPConfig(){
-
-}
-
-void LPConfig::loadDataset(QString ds, bool replicated){
- ui->label_dataset->setText(ds);
- loadDatasetConfiguration(ds, replicated);
-}
-
-//==========
-// PRIVATE
-// ==========
-void LPConfig::loadDatasetConfiguration(QString dataset, bool replicated){
- qDebug() <<" - Loading dataset configuration:" << dataset;
- //Load the dataset values
- isReplicated = replicated;
- // - Local settings
- if( !LPBackend::datasetInfo(dataset, localSchedule, localSnapshots) ){
- localSchedule = 1; //daily at 1 AM
- localSnapshots = 7;
- }
- // - Replication settings
- bool ok=false;
- if(isReplicated){
- ok = LPBackend::replicationInfo(dataset, remoteHost, remoteUser, remotePort, remoteDataset, remoteFreq);
- }
- if(!ok){
- isReplicated = false;
- remotePort = 22;
- remoteFreq = -1; //sync
- remoteHost = "";
- remoteUser = "";
- remoteDataset = "";
- }
- //Now put the values into the UI
- // - local settings
- if(localSchedule == -5){ //5 minutes
- ui->combo_local_schedule->setCurrentIndex(4);
- }else if(localSchedule == -10){ //10 minutes
- ui->combo_local_schedule->setCurrentIndex(3);
- }else if(localSchedule == -30){ //30 minutes
- ui->combo_local_schedule->setCurrentIndex(2);
- }else if(localSchedule > 0 && localSchedule < 24){ //daily @ hour
- ui->combo_local_schedule->setCurrentIndex(0);
- ui->time_local_daily->setTime( QTime(localSchedule, 0) );
- }else{ //assume hourly
- localSchedule = -60;
- ui->combo_local_schedule->setCurrentIndex(1);
- }
- setLocalKeepNumber();
-
- // - Replication settings
- ui->groupReplicate->setChecked(isReplicated);
- ui->lineHostName->setText(remoteHost);
- ui->lineUserName->setText(remoteUser);
- ui->lineRemoteDataset->setText(remoteDataset);
- ui->spinPort->setValue(remotePort);
- if(remoteFreq >=0 && remoteFreq < 24){
- ui->radioRepTime->setChecked(true);
- ui->time_replicate->setTime( QTime(remoteFreq,0) );
- }else{
- ui->radioSYNC->setChecked(true);
- }
-
-}
-
-void LPConfig::checkForChanges(){
- //Checks for changes to the settings while also updating the output variables to match the GUI
-
- localChanged = false;
- remoteChanged = false;
- //Local Settings
- int nSchedule;
- int schint = ui->combo_local_schedule->currentIndex();
- if(schint == 0){ nSchedule = ui->time_local_daily->time().hour(); } //daily @ hour
- else if(schint == 1){ nSchedule = -60; } //hourly
- else if(schint == 2){ nSchedule = -30; } //30 min
- else if(schint == 3){ nSchedule = -10; } //10 min
- else{ nSchedule = -5; } //5 min
- int nTotSnaps;
- if( ui->combo_local_keepunits->currentIndex() == 0 && (schint != 0) ){ //days
- int numperday = 1440/(-nSchedule);
- nTotSnaps = numperday * ui->spin_local_numkeep->value();
- }else{ //total number (or daily snapshots)
- nTotSnaps = ui->spin_local_numkeep->value();
- }
- if(nSchedule != localSchedule){localChanged = true; localSchedule = nSchedule; }
- if(nTotSnaps != localSnapshots){ localChanged = true; localSnapshots = nTotSnaps; }
-
- //Replication Settings
- bool updateSSHKey = false;
- if(isReplicated != ui->groupReplicate->isChecked()){
- remoteChanged = true;
- isReplicated = ui->groupReplicate->isChecked();
- if(isReplicated){ updateSSHKey = true; }
- }
- QString tmp = ui->lineHostName->text().simplified();
- if( tmp != remoteHost ){ remoteChanged = true; remoteHost = tmp; updateSSHKey=true;}
- tmp = ui->lineUserName->text().simplified();
- if( tmp != remoteUser ){ remoteChanged = true; remoteUser = tmp; updateSSHKey=true;}
- tmp = ui->lineRemoteDataset->text().simplified();
- if( tmp != remoteDataset ){ remoteChanged = true; remoteDataset = tmp; }
- if( ui->spinPort->value() != remotePort){ remoteChanged = true; remotePort = ui->spinPort->value(); updateSSHKey=true;}
- int nFreq = -1;
- if(ui->radioRepTime->isChecked()){
- nFreq = ui->time_replicate->time().hour();
- }
- if(nFreq < 0){
- if( remoteFreq >= 0 && remoteFreq < 24){remoteChanged = true; remoteFreq = nFreq;}
- }else{
- if( nFreq != remoteFreq ){ remoteChanged = true; remoteFreq = nFreq; }
- }
- if(updateSSHKey){
- //Prompt for the SSH key generation
- LPBackend::setupSSHKey(remoteHost, remoteUser, remotePort);
- }
-}
-
-void LPConfig::setLocalKeepNumber(){
- if(localSchedule >=0){
- ui->combo_local_keepunits->setCurrentIndex(0); //num days
- ui->spin_local_numkeep->setValue(localSnapshots);
- }else{
- int numperday = 1440/(-localSchedule);
- if( localSnapshots % numperday == 0 ){
- //daily
- ui->combo_local_keepunits->setCurrentIndex(0); //num days
- ui->spin_local_numkeep->setValue(localSnapshots/numperday);
- }else{
- //odd number of snapshots - must be total
- ui->combo_local_keepunits->setCurrentIndex(1); //num total
- ui->spin_local_numkeep->setValue(localSnapshots);
- }
- }
-}
-
-// =============
-// PRIVATE SLOTS
-// =============
-void LPConfig::slotApplyChanges(){
- checkForChanges();
- this->close();
-}
-
-void LPConfig::slotCancelConfig(){
- //Make sure it is flagged as unchanged before closing
- localChanged = false;
- remoteChanged = false;
- this->close();
-}
-
-void LPConfig::on_combo_local_schedule_currentIndexChanged(int index){
- //Adjust whether the daily time box is visible
- ui->time_local_daily->setVisible( (index == 0) );
-}
View
39 lp-gui/LPConfig.h
@@ -1,39 +0,0 @@
-#ifndef _LP_CONFIG_H
-#define _LP_CONFIG_H
-
-#include <QDialog>
-#include <QString>
-#include <QDebug>
-
-#include "LPBackend.h"
-
-namespace Ui{
- class LPConfig;
-}
-
-class LPConfig : public QDialog{
- Q_OBJECT
-public:
- LPConfig(QWidget* parent = 0);
- ~LPConfig();
-
- void loadDataset(QString, bool);
-
- //Output variables
- bool localChanged, remoteChanged, isReplicated;
- int localSchedule, localSnapshots, remotePort, remoteFreq;
- QString remoteHost, remoteUser, remoteDataset;
-
-private:
- Ui::LPConfig *ui;
- void loadDatasetConfiguration(QString, bool);
- void checkForChanges();
- void setLocalKeepNumber();
-
-private slots:
- void slotApplyChanges();
- void slotCancelConfig();
- void on_combo_local_schedule_currentIndexChanged(int);
-};
-
-#endif
View
397 lp-gui/LPConfig.ui
@@ -1,397 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LPConfig</class>
- <widget class="QDialog" name="LPConfig">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>374</width>
- <height>327</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Configure Dataset</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Data Set:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="label_dataset">
- <property name="text">
- <string notr="true">sample</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab_local">
- <attribute name="title">
- <string>Local Snapshots</string>
- </attribute>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Schedule:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QComboBox" name="combo_local_schedule">
- <item>
- <property name="text">
- <string>Daily</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Hourly</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>30 minutes</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>10 minutes</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>5 minutes</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <widget class="QTimeEdit" name="time_local_daily">
- <property name="maximumTime">
- <time>
- <hour>23</hour>
- <minute>0</minute>
- <second>0</second>
- </time>
- </property>
- <property name="minimumTime">
- <time>
- <hour>1</hour>
- <minute>0</minute>
- <second>0</second>
- </time>
- </property>
- <property name="displayFormat">
- <string>@ h AP</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QSpinBox" name="spin_local_numkeep">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>800</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="combo_local_keepunits">
- <item>
- <property name="text">
- <string>Days</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Total</string>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Keep:</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_remote">
- <attribute name="title">
- <string>Replication</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QGroupBox" name="groupReplicate">
- <property name="title">
- <string>Replicate on a Remote System</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_8">
- <item>
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Host Name</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="lineHostName"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <item>
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>User Name</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="lineUserName"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QLabel" name="label_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>SSH Port</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QSpinBox" name="spinPort">
- <property name="maximum">
- <number>999999</number>
- </property>
- <property name="value">
- <number>22</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <item>
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Remote Dataset</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="lineRemoteDataset"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Frequency</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QRadioButton" name="radioSYNC">
- <property name="text">
- <string>With snapshot creation (Best for daily snapshots)</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QRadioButton" name="radioRepTime">
- <property name="text">
- <string>Daily at:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTimeEdit" name="time_replicate">
- <property name="displayFormat">
- <string>h AP</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_9">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QToolButton" name="tool_apply">
- <property name="text">
- <string>Apply</string>
- </property>
- <property name="icon">
- <iconset resource="lPreserve.qrc">
- <normaloff>:/images/backup-ok.png</normaloff>:/images/backup-ok.png</iconset>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_cancel">
- <property name="text">
- <string>Cancel</string>
- </property>
- <property name="icon">
- <iconset resource="lPreserve.qrc">
- <normaloff>:/images/application-exit.png</normaloff>:/images/application-exit.png</iconset>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources>
- <include location="lPreserve.qrc"/>
- </resources>
- <connections/>
-</ui>
View
33 lp-gui/LPContainers.h
@@ -1,33 +0,0 @@
-#ifndef _LP_CONTAINERS_H
-#define _LP_CONTAINERS_H
-
-#include <QHash>
-#include <QStringList>
-#include <QString>
-
-
-class LPDataset{
-public:
- LPDataset(){}
- ~LPDataset(){}
-
- //Information needed on each dataset
- QString finishedStatus, runningStatus, errorStatus;
- QString latestSnapshot;
- QStringList harddisks;
- QStringList harddiskStatus;
- QString poolStatus;
- QHash<QString,QStringList> subsetHash; //<subset, snapshot list> (complete dataset name should be <ds><subset>)
-
- //Simplification functions for getting info from the hash
- QStringList subsets(){ return QStringList(subsetHash.keys()); }
- QStringList snapshots(QString subset){
- if(subsetHash.contains(subset)){
- return subsetHash[subset];
- }else{
- return QStringList();
- }
- }
-};
-
-#endif
View
254 lp-gui/LPGUtils.cpp
@@ -1,254 +0,0 @@
-#include "LPGUtils.h"
-
-LPDataset LPGUtils::loadPoolData(QString zpool){
- //Load the current information for the given zpool
- qDebug() << "New Dataset: " << zpool;
- LPDataset DSC;
- //List all the mountpoints in this dataset
- QStringList subsets = LPBackend::listDatasetSubsets(zpool);
- QStringList lpsnaps = LPBackend::listLPSnapshots(zpool);
- //populate the list of snapshots available for each mountpoint
- for(int i=0; i<subsets.length(); i++){
- //qDebug() << "Subset:" << subsets[i];
- QStringList snaps = LPBackend::listSnapshots(subsets[i]);
- //qDebug() << " - Snapshots:" << snaps;
- if(snaps.isEmpty()){
- //invalid subset - remove it from the list
- subsets.removeAt(i);
- i--;
- }else{
- QStringList subsnaps;
- //only list the valid snapshots that life preserver created
- for(int s=0; s<lpsnaps.length(); s++){
- int index = snaps.indexOf(lpsnaps[s]);
- if(index > -1){ subsnaps << lpsnaps[s]; snaps.removeAt(index); }
- }
- /*//Now list all the other available snapshots (no certain ordering)
- if(!snaps.isEmpty()){try
- subsnaps << "--"; //so we know that this is a divider between the sections
- subsnaps << snaps;
- }*/
- DSC.subsetHash.insert(subsets[i],subsnaps); //add it to the internal container hash
- }
- }
- //Parse "zpool status <pool>"
- QStringList zstat = LPBackend::getCmdOutput("zpool status "+zpool);
- //qDebug() << "zpool status "+zpool+":\n" << zstat.join("\n");
- bool atheader=false;
- QStringList disks, diskstates, running, errors, finished;
- for(int i=0; i<zstat.length(); i++){
- if(zstat[i].isEmpty()){ continue; }
- else if(zstat[i].startsWith(" scan:")){
- QString line = zstat[i].section(":",1,50).replace("\t"," ").simplified();
- if(line.contains("scrub repaired ")){
- QString timestamp = line.section(" ",9,13,QString::SectionSkipEmpty);
- QString numerrors = line.section(" ",6,6,QString::SectionSkipEmpty);
- finished << QString(QObject::tr("Scrub Finished: %1 (%2 errors)")).arg(timestamp, numerrors);
- }else if(line.contains("scrub cancel")){
- QString timestamp = line.section(" ",3,7,QString::SectionSkipEmpty);
- finished << QString(QObject::tr("Scrub Cancelled: %1")).arg(timestamp);
- }else if(line.contains("scrub")){
- QString timestamp = line.section(" ",4,8,QString::SectionSkipEmpty);
- running << QString(QObject::tr("Scrub Started: %1")).arg(timestamp);
- }else if(line.contains("resilvered")){
- QString timestamp = line.section(" ",8,12,QString::SectionSkipEmpty);
- QString numerrors = line.section(" ",5,5,QString::SectionSkipEmpty);
- finished << QString(QObject::tr("Resilver Finished: %1 (%2 errors)")).arg(timestamp, numerrors);
- }
- }else if(zstat[i].contains("NAME") && zstat[i].contains("STATE") && zstat[i].contains("READ") ){
- //qDebug() <<"Found header";
- atheader=true;
- }else if(zstat[i].startsWith("errors:")){
- atheader=false;
- }else if(atheader){
- QString line = zstat[i].replace("\t"," ").simplified();
- QString dev = line.section(" ",0,0,QString::SectionSkipEmpty);
- QString state = line.section(" ",1,1,QString::SectionSkipEmpty);
- //qDebug() << "Found device:" << dev << state;
- if(dev == zpool){
- DSC.poolStatus = state;
- }else if(line.contains("(resilvering)")){
- disks << dev; diskstates << state; //record this disk and state
- running << QString(QObject::tr("%1: Currently Resilvering")).arg(dev);
- }else{
- disks << dev; diskstates << state; //record this disk and state
- if(state != "ONLINE"){
- errors << QString(QObject::tr("%1: %2")).arg(dev, state);
- }
- }
- }
- }
- //Now get the latest Snapshot/Replication information
- QStringList lpstat = LPBackend::listCurrentStatus();
- for(int i=0; i<lpstat.length(); i++){
- if(lpstat[i].section(":::",0,0) == zpool){
- QString lastSnap = lpstat[i].section(":::",1,1);
- QString lastRep = lpstat[i].section(":::",2,2);
- if(lastSnap=="-"){ DSC.latestSnapshot = QObject::tr("No Snapshots Available"); }
- else{ DSC.latestSnapshot = lastSnap; }
- if(lastRep!="-"){
- finished << QString(QObject::tr("Latest Replication: %1")).arg(lastRep);
- }else if(LPBackend::listReplicationTargets().contains(zpool) ){
- errors << QObject::tr("No Successful Replication");
- }
- }
- }
- //Now save the info to the dataset
- DSC.harddisks = disks;
- DSC.harddiskStatus = diskstates;
- DSC.errorStatus = errors.join("\n");
- DSC.runningStatus = running.join("\n");
- DSC.finishedStatus = finished.join("\n");
- //Return the dataset
- return DSC;
-}
-
-QString LPGUtils::generateReversionFileName(QString fileName, QString destDir){
- fileName = fileName.section("/",-1); //Make sure we only have the filename (no paths)
- if( !destDir.endsWith("/") ){ destDir.append("/"); }
- //Quick check if that file already exists in the destination directory
- if( !QFile::exists(destDir+fileName) ){ return fileName; }
- //Change the filename to prevent overwriting an existing file
- QString ext = fileName.section(".",-1); //Get the extension for the filename
- if( fileName != ext && fileName != ("."+ext) ){
- //Extension found - need careful adjustment of filename
- QString newFileName = fileName;
- newFileName.replace("."+ext, "-reversion."+ext);
- int i=2;
- while( QFile::exists(destDir+newFileName) ){
- //Also need to append a reversion number
- newFileName = fileName;
- newFileName.replace("."+ext, "-reversion"+QString::number(i)+"."+ext);
- i++; //for the next time around
- }
- fileName = newFileName;
- }else{
- //no extension - just append the reversion
- fileName.append("-reversion");
- if(QFile::exists(destDir+fileName) ){
- //Also need to append a reversion number
- int i=2;
- while( QFile::exists(destDir+fileName+QString::number(i)) ){ i++; }
- fileName.append( QString::number(i) );
- }
- }
- return fileName;
-}
-
-bool LPGUtils::revertFile(QString oldPath, QString newPath){
- bool ok = QFile::copy(oldPath,newPath);
- //return the path to the new file if the copy was successful
- if(ok){
- //reset the permissions on the reverted file to match the original
- QFile::setPermissions(newPath, QFile::permissions(oldPath));
- QFileInfo FI(oldPath);
- system( QString("chown "+FI.owner()+":"+FI.group()+" "+newPath).toUtf8() );
- }
- return ok;
-}
-
-QStringList LPGUtils::revertDir(QString oldPath, QString newPath){
- //Note: this is a recursive function and can take quite a while to perform lots of file copies
-
- //Load the directories and create it if necessary
- QDir oDir(oldPath);
- QDir nDir(newPath);
- bool ok=true;
- if( !nDir.exists() ){
- //Create the new Directory
- nDir.cdUp();
- ok = nDir.mkdir(newPath.section("/",-1));
- if(ok){
- nDir.cd(newPath.section("/",-1));
- QFile::setPermissions(newPath, QFile::permissions(oldPath)); //make sure the new dir has the old permissions
- QFileInfo FI(oldPath);
- system( QString("chown "+FI.owner()+":"+FI.group()+" "+newPath).toUtf8() );
- }
- }
- //Get a list of any files that error
- QStringList errors;
- if(!ok){
- errors << newPath;
- return errors;
- }
- //Get a list of all the files in the old dir and copy them over
- QStringList fList = oDir.entryList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name);
- for(int i=0; i<fList.length(); i++){
- if( !revertFile(oldPath+"/"+fList[i], newPath+"/"+fList[i]) ){
- errors << newPath+"/"+fList[i];
- }
- }
- //Now list all the directories in the old dir and recursively copy them over
- fList = oDir.entryList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name);
- for(int i=0; i<fList.length(); i++){
- QStringList errs = revertDir(oldPath+"/"+fList[i], newPath+"/"+fList[i]);
- if( !errs.isEmpty() ){ errors << errs; }
- }
- return errors;
-}
-
-QString LPGUtils::packageHomeDir(QString username, QString packageName){
- //Check that the user directory exists
- //qDebug() << "Start package dir:" << username << packageName;
- if(!QFile::exists("/usr/home/"+username)){ return ""; }
- //Check that the package has the right extension
- if(!packageName.endsWith(".home.tar.gz")){ packageName.append(".home.tar.gz"); }
- //Generate any additional files to be contained in the package
-
-
- //Generate the command
- QString cmd = "tar -czf /usr/home/"+packageName+" -C /usr/home "+username;
- //Create the exclude list and skip these files
- QStringList excludes;
- excludes << "*flashplayer*"; //Don't overwrite the flash plugin
- for(int i=0; i<excludes.length(); i++){
- cmd.replace("-czf /usr/home", " --exclude \'"+excludes[i]+"\' -czf /usr/home");
- }
- //Run the command
- qDebug() << "Package command:" << cmd;
- system(cmd.toUtf8()); //need to be careful with the exclude syntax (quotes) so use system command
- //qDebug() << "Command return:" << QString::number(ret);
- //Check that the package was created
- QString packagePath;
- if(QFile::exists("/usr/home/"+packageName)){ packagePath = "/usr/home/"+packageName; }
- //Now return the path to the package file
- return packagePath;
-}
-
-bool LPGUtils::checkPackageUserPath(QString packagePath, QString *user){
- user->clear();
- //Determine if the file exists
- if( !QFile::exists(packagePath) ){ return false; }
- //Check the username of the home dir in the package
- QStringList ret = LPBackend::getCmdOutput("tar -tvf "+packagePath);
- if(ret.isEmpty()){ return false; }
- QString username = ret[0].section(" ",2,2,QString::SectionSkipEmpty).simplified();
- QString dirname = ret[0].section(" ",8,8,QString::SectionSkipEmpty).section("/",0,0).simplified();
- user->append(username); //additional output
- //Now check for the user on the local system
- //This is just a simple check that the user directory exists, and the user/directory are the same within the package
- return (username == dirname && QFile::exists("/usr/home/"+dirname) );
-}
-
-bool LPGUtils::extractHomeDirPackage(QString packagePath){
- //Determine if the file exists
- if( !QFile::exists(packagePath) ){ return false; }
- //Now extract the archive in the home directory
- QString cmd = "tar -xpf "+packagePath+" -C /usr/home";
- qDebug() << "Extract command:" << cmd;
- int ret = LPBackend::runCmd(cmd);
- return (ret == 0);
-}
-
-QStringList LPGUtils::listAvailableHardDisks(){
- QDir dev("/dev");
- QStringList filters;
- filters << "ada*" << "da*";
- QStringList devs = dev.entryList(filters, QDir::Files | QDir::System | QDir::NoDotAndDotDot, QDir::Name);
- //Filter out all the partitions (only keep full devices)
- for(int i=0; i<devs.length(); i++){
- devs[i] = devs[i].section("s",0,0,QString::SectionSkipEmpty);
- }
- devs.removeDuplicates();
- return devs;
-}
View
28 lp-gui/LPGUtils.h
@@ -1,28 +0,0 @@
-#ifndef _LP_GUTILS_H
-#define _LP_GUTILS_H
-
-#include <QMessageBox>
-#include <QDialog>
-#include <QStringList>
-#include <QString>
-#include <QFile>
-#include <QDir>
-
-#include "LPBackend.h"
-#include "LPContainers.h"
-
-class LPGUtils{
-public:
- static LPDataset loadPoolData(QString zpool); //Load backend data into container
- static QString generateReversionFileName(QString filename, QString destDir);
- static bool revertFile(QString oldPath, QString newPath); //copy a file out of a snapshot
- static QStringList revertDir(QString oldPath, QString newPath); //copy a dir out of a snapshot
- //Functions for packaging up a user's home directory and extracting it later
- static QString packageHomeDir(QString username, QString packageName);
- static bool checkPackageUserPath(QString packagePath, QString *user);
- static bool extractHomeDirPackage(QString packagePath);
- //Function to scan the system for available harddisks/devices
- static QStringList listAvailableHardDisks();
-};
-
-#endif
View
671 lp-gui/LPMain.cpp
@@ -1,671 +0,0 @@
-#include "LPMain.h"
-#include "ui_LPMain.h"
-
-LPMain::LPMain(QWidget *parent) : QMainWindow(parent), ui(new Ui::LPMain){
- ui->setupUi(this); //load the Qt-designer UI file
- //Create the basic/advanced view options
- viewBasic = new QRadioButton(tr("Basic"), ui->menuView);
- QWidgetAction *WABasic = new QWidgetAction(this); WABasic->setDefaultWidget(viewBasic);
- ui->menuView->addAction(WABasic);
- viewAdvanced = new QRadioButton(tr("Advanced"), ui->menuView);
- QWidgetAction *WAAdv = new QWidgetAction(this); WAAdv->setDefaultWidget(viewAdvanced);
- ui->menuView->addAction(WAAdv);
- connect(viewBasic, SIGNAL(toggled(bool)), this, SLOT(viewChanged()) );
- //Now set the default view type
- viewBasic->setChecked(true); //will automatically call the "viewChanged" function
- //Create the filesystem model and tie it to the treewidget
- fsModel = new QFileSystemModel(this);
- fsModel->setReadOnly(true);
- ui->treeView->setModel(fsModel);
- //Connect the UI to all the functions
- connect(ui->tool_refresh, SIGNAL(clicked()), this, SLOT(updatePoolList()) );
- connect(ui->combo_pools, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTabs()) );
- connect(ui->combo_datasets, SIGNAL(currentIndexChanged(int)), this, SLOT(updateDataset()) );
- connect(ui->slider_snapshots, SIGNAL(valueChanged(int)), this, SLOT(updateSnapshot()) );
- connect(ui->push_prevsnap, SIGNAL(clicked()), this, SLOT(prevSnapshot()) );
- connect(ui->push_nextsnap, SIGNAL(clicked()), this, SLOT(nextSnapshot()) );
- connect(ui->check_hidden, SIGNAL(stateChanged(int)), this, SLOT(setFileVisibility()) );
- connect(ui->push_restore, SIGNAL(clicked()), this, SLOT(restoreFiles()) );
- connect(ui->push_configure, SIGNAL(clicked()), this, SLOT(openConfigGUI()) );
- //Connect the Menu buttons
- connect(ui->menuManage_Pool, SIGNAL(triggered(QAction*)), this, SLOT(menuAddPool(QAction*)) );
- connect(ui->menuUnmanage_Pool, SIGNAL(triggered(QAction*)), this, SLOT(menuRemovePool(QAction*)) );
- connect(ui->action_SaveKeyToUSB, SIGNAL(triggered()), this, SLOT(menuSaveSSHKey()) );
- connect(ui->actionClose_Window, SIGNAL(triggered()), this, SLOT(menuCloseWindow()) );
- connect(ui->menuCompress_Home_Dir, SIGNAL(triggered(QAction*)), this, SLOT(menuCompressHomeDir(QAction*)) );
- connect(ui->actionExtract_Home_Dir, SIGNAL(triggered()), this, SLOT(menuExtractHomeDir()) );
- connect(ui->actionAdd_Disk, SIGNAL(triggered()), this, SLOT(menuAddDisk()) );
- connect(ui->menuRemove_Disk, SIGNAL(triggered(QAction*)), this, SLOT(menuRemoveDisk(QAction*)) );
- connect(ui->menuSet_Disk_Offline, SIGNAL(triggered(QAction*)), this, SLOT(menuOfflineDisk(QAction*)) );
- connect(ui->menuSet_Disk_Online, SIGNAL(triggered(QAction*)), this, SLOT(menuOnlineDisk(QAction*)) );
- connect(ui->action_startScrub, SIGNAL(triggered()), this, SLOT(menuStartScrub()) );
- connect(ui->action_stopScrub, SIGNAL(triggered()), this, SLOT(menuStopScrub()) );
- connect(ui->action_newSnapshot, SIGNAL(triggered()), this, SLOT(menuNewSnapshot()) );
- connect(ui->menuDelete_Snapshot, SIGNAL(triggered(QAction*)), this, SLOT(menuRemoveSnapshot(QAction*)) );
- //Update the interface
- QTimer::singleShot(0,this,SLOT(updatePoolList()) );
-
- //Make sure the status tab is shown initially
- ui->tabWidget->setCurrentWidget(ui->tab_status);
-}
-
-LPMain::~LPMain(){
-
-}
-
-// ==============
-// PUBLIC SLOTS
-// ==============
-void LPMain::slotSingleInstance(){
- this->raise();
- this->show();
-}
-
-// ==============
-// PRIVATE
-// ==============
-void LPMain::showErrorDialog(QString title, QString message, QString errors){
- QMessageBox MB(QMessageBox::Warning, title, message, QMessageBox::Ok, this);
- MB.setDetailedText(errors);
- MB.exec();
-}
-
-void LPMain::showWaitBox(QString message){
- if(waitBox == 0){
- qDebug() << "New Wait Box";
- waitBox = new QMessageBox(QMessageBox::NoIcon, tr("Please Wait"), message, QMessageBox::NoButton, this);
- waitBox->setWindowModality(Qt::WindowModal);
- }else{
- qDebug() << "Update Wait Box:" << message;
- waitBox->setText(message);
- }
- if(!waitBox->isVisible()){ waitBox->show(); waitBox->raise(); }
- QCoreApplication::processEvents();
-}
-
-void LPMain::hideWaitBox(){
- if(waitBox != 0){
- if(waitBox->isVisible()){ waitBox->hide(); }
- }
-
-}
-
-// ==============
-// PRIVATE SLOTS
-// ==============
-void LPMain::updatePoolList(){
- //Get the currently selected pool (if there is one)
- qDebug() << "Update Pool List";
- QString cPool;
- if(ui->combo_pools->currentIndex() != -1){ cPool = ui->combo_pools->currentText(); }
- //Get the list of managed pools
- QStringList pools = LPBackend::listDatasets();
- QStringList poolsAvail = LPBackend::listPossibleDatasets();
- //Now put the lists into the UI
- ui->combo_pools->clear();
- if(!pools.isEmpty()){ ui->combo_pools->addItems(pools); }
- //Now set the currently selected pools
- if(pools.length() > 0){
- poolSelected=true;
- int index = pools.indexOf(cPool);
- if(index < 0){ ui->combo_pools->setCurrentIndex(0); }
- else{ ui->combo_pools->setCurrentIndex(index); }
- }else{
- //No managed pools
- poolSelected=false;
- ui->combo_pools->addItem("No Managed Pools!");
- ui->combo_pools->setCurrentIndex(0);
- }
- //Now update the add/remove pool menu's
- ui->menuManage_Pool->clear();
- for( int i=0; i<poolsAvail.length(); i++){
- if(pools.contains(poolsAvail[i])){ continue; } //already managed
- ui->menuManage_Pool->addAction(poolsAvail[i]);
- }
- ui->menuManage_Pool->setEnabled( !ui->menuManage_Pool->isEmpty() );
- ui->menuUnmanage_Pool->clear();
- for( int i=0; i<pools.length(); i++){
- ui->menuUnmanage_Pool->addAction(pools[i]);
- }
- ui->menuUnmanage_Pool->setEnabled( !ui->menuUnmanage_Pool->isEmpty() );
- //Now update the user's that are available for home-dir packaging
- QDir hdir("/usr/home");
- QStringList users = hdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
- ui->menuCompress_Home_Dir->clear();
- for(int i=0; i<users.length(); i++){
- ui->menuCompress_Home_Dir->addAction(users[i]);
- }
- //Now update the interface appropriately
- ui->combo_pools->setEnabled(poolSelected);
- updateTabs();
-}
-
-void LPMain::viewChanged(){
- ui->menuView->hide();
- ui->menubar->clear();
- if(viewBasic->isChecked()){
- ui->menubar->addMenu(ui->menuFile);
- ui->menubar->addMenu(ui->menuView);
- ui->menubar->addMenu(ui->menuClassic_Backups);
- }else{
- ui->menubar->addMenu(ui->menuFile);
- ui->menubar->addMenu(ui->menuView);
- ui->menubar->addMenu(ui->menuClassic_Backups);
- ui->menubar->addMenu(ui->menuSnapshots);
- ui->menubar->addMenu(ui->menuDisks);
- }
-}
-
-void LPMain::updateTabs(){
- //qDebug() << "Update Tabs" << poolSelected;
- viewChanged();
- ui->tabWidget->setEnabled(poolSelected);
- ui->menuView->setEnabled(poolSelected);
- ui->menuDisks->setEnabled(poolSelected);
- ui->menuSnapshots->setEnabled(poolSelected);
- ui->push_configure->setVisible(poolSelected);
- ui->action_SaveKeyToUSB->setEnabled(poolSelected);
- if(poolSelected){
- showWaitBox(tr("Loading zpool information"));
- POOLDATA = LPGUtils::loadPoolData(ui->combo_pools->currentText());
- hideWaitBox();
- //Now list the status information
- ui->label_status->setText(POOLDATA.poolStatus);
- ui->label_numdisks->setText( QString::number(POOLDATA.harddisks.length()) );
- ui->label_latestsnapshot->setText(POOLDATA.latestSnapshot);
- if(POOLDATA.finishedStatus.isEmpty()){ ui->label_finishedstat->setVisible(false); }
- else{
- ui->label_finishedstat->setText(POOLDATA.finishedStatus);
- ui->label_finishedstat->setVisible(true);
- }
- if(POOLDATA.runningStatus.isEmpty()){ ui->label_runningstat->setVisible(false); }
- else{
- ui->label_runningstat->setText(POOLDATA.runningStatus);
- ui->label_runningstat->setVisible(true);
- }
- if(POOLDATA.errorStatus.isEmpty()){ ui->label_errorstat->setVisible(false); }
- else{
- ui->label_errorstat->setText(POOLDATA.errorStatus);
- ui->label_errorstat->setVisible(true);
- }
- //Now list the data restore options
- QString cds = ui->combo_datasets->currentText();
- ui->combo_datasets->clear();
- QStringList dslist = POOLDATA.subsets();
- ui->combo_datasets->addItems(dslist);
- int dsin = dslist.indexOf(cds);
- if(dsin >= 0){ ui->combo_datasets->setCurrentIndex(dsin); }
- else if( !dslist.isEmpty() ){ ui->combo_datasets->setCurrentIndex(0); }
- else{ ui->combo_datasets->addItem(tr("No datasets available")); }
- //NOTE: this automatically calls the "updateDataset()" function in a new thread
-
- //Now update the snapshot removal menu list
- QStringList snaps = LPBackend::listLPSnapshots(ui->combo_pools->currentText());
- ui->menuDelete_Snapshot->clear();
- for(int i=0; i<snaps.length(); i++){
- ui->menuDelete_Snapshot->addAction(snaps[i]);
- }
- ui->menuDelete_Snapshot->setEnabled( !ui->menuDelete_Snapshot->isEmpty() );
- //Now update the disk menu items
- ui->menuRemove_Disk->clear();
- ui->menuSet_Disk_Offline->clear();
- ui->menuSet_Disk_Online->clear();
- for(int i=0; i<POOLDATA.harddisks.length(); i++){
- ui->menuRemove_Disk->addAction(POOLDATA.harddisks[i]);
- if(POOLDATA.harddiskStatus[i] == "OFFLINE"){
- ui->menuSet_Disk_Online->addAction(POOLDATA.harddisks[i]);
- }else{
- ui->menuSet_Disk_Offline->addAction(POOLDATA.harddisks[i]);
- }
- }
- ui->menuRemove_Disk->setEnabled(!ui->menuRemove_Disk->isEmpty());
- ui->menuSet_Disk_Offline->setEnabled(!ui->menuSet_Disk_Offline->isEmpty());
- ui->menuSet_Disk_Online->setEnabled(!ui->menuSet_Disk_Online->isEmpty());
- }else{
- //No Pool selected
- ui->label_numdisks->clear();
- ui->label_latestsnapshot->clear();
- ui->label_status->clear();
- ui->label_errorstat->setVisible(false);
- ui->label_runningstat->setVisible(false);
- ui->label_finishedstat->setVisible(false);
- }
-
-}
-
-void LPMain::updateDataset(){
- //Update the snapshots for the currently selected dataset
- QString cds = ui->combo_datasets->currentText();
- if(POOLDATA.subsets().indexOf(cds) >= 0){
- QStringList snaps = POOLDATA.snapshots(cds);
- qDebug() << "Update Dataset";
- ui->slider_snapshots->setEnabled(true);
- ui->slider_snapshots->setMinimum(0);
- int max = snaps.length() -1;
- if(max < 0){ max = 0; ui->slider_snapshots->setEnabled(false); }
- ui->slider_snapshots->setMaximum(max);
- ui->slider_snapshots->setValue(max); //most recent snapshot
- updateSnapshot();
- }else{
- ui->slider_snapshots->setEnabled(false);
- ui->label_snapshot->clear();
- ui->push_nextsnap->setEnabled(false);
- ui->push_prevsnap->setEnabled(false);
- }
-
-}
-
-void LPMain::updateSnapshot(){
- int sval = ui->slider_snapshots->value();
- QStringList snaps = POOLDATA.snapshots(ui->combo_datasets->currentText());
- //qDebug() << "Update Snapshot";
- //Update the previous/next buttons
- if(sval == ui->slider_snapshots->minimum() ){ ui->push_prevsnap->setEnabled(false); }
- else{ ui->push_prevsnap->setEnabled(true); }
- if(sval == ui->slider_snapshots->maximum() ){ ui->push_nextsnap->setEnabled(false); }
- else{ ui->push_nextsnap->setEnabled(true); }
- //Now update the snapshot viewer
- if(snaps.isEmpty()){ ui->label_snapshot->clear(); ui->slider_snapshots->setEnabled(false); }
- else{
- QString snap = snaps.at(sval);
- QString path = ui->combo_datasets->currentText() + "/.zfs/snapshot/"+snap;
- //qDebug() << "Snapshot path:" << path;
- ui->label_snapshot->setText(snap);
- //Now update the snapshot view
- ui->treeView->setRootIndex( fsModel->setRootPath(path) );
-
- }
-}
-
-void LPMain::nextSnapshot(){
- ui->slider_snapshots->setValue( ui->slider_snapshots->value()+1 );
-}
-
-void LPMain::prevSnapshot(){
- ui->slider_snapshots->setValue( ui->slider_snapshots->value()-1 );
-}
-
-void LPMain::setFileVisibility(){
- if(ui->check_hidden->isChecked()){
- fsModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden );
- }else{
- fsModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot );
- }
-}
-
-void LPMain::restoreFiles(){
- QString filePath = fsModel->filePath( ui->treeView->currentIndex() );
- qDebug() << " Restore file(s):" << filePath;
- QString destDir = filePath.remove("/.zfs/snapshot/"+ui->label_snapshot->text());
- destDir.chop( filePath.section("/",-1).size()+1 ); //get rid of the filename at the end
- while(!QFile::exists(destDir)){ destDir.chop( destDir.section("/",-1).size() +1); }
- QString newFilePath = destDir+"/"+LPGUtils::generateReversionFileName(filePath, destDir);
- //qDebug() << "Destination:" << newFilePath;
- //Perform the reversion(s)
- QStringList errors;
- if(QFileInfo(filePath).isDir()){
- //Is a directory
- showWaitBox( QString(tr("Restoring Directory: %1")).arg(newFilePath) );
- errors = LPGUtils::revertDir(filePath, newFilePath);
- hideWaitBox();
- if(!errors.isEmpty()){
- qDebug() << "Failed Reversions:" << errors;
- errors.prepend(tr("File destination(s) that could not be restored:")+"\n");
- showErrorDialog(tr("Reversion Error"), tr("Some files could not be restored from the snapshot."), errors.join("\n") );
- }else{
- qDebug() << "Reversion successful";
- QMessageBox::information(this,tr("Restore Successful"),QString(tr("The following directory was succesfully restored: %1")).arg(newFilePath) );
- }
- }else{
- //Just a single file
- showWaitBox( QString(tr("Restoring file: %1")).arg(newFilePath) );
- bool ok = LPGUtils::revertFile(filePath, newFilePath);
- hideWaitBox();
- if( !ok ){
- qDebug() << "Failed Reversion:" << newFilePath;
- errors << QString(tr("Snapshot file: %1")).arg(filePath);
- errors << QString(tr("Destination: %1")).arg(newFilePath);
- errors << tr("Please check that the destination directory exists and is writable");
- showErrorDialog(tr("Reversion Error"), tr("The file could not be restored from the snapshot."), errors.join("\n") );
- }else{
- qDebug() << "Reversion successful";
- QMessageBox::information(this,tr("Restore Successful"),QString(tr("The following file was succesfully restored: %1")).arg(newFilePath) );
- }
- }
-
-}
-
-void LPMain::openConfigGUI(){
- qDebug() << "Open Configuration UI";
- QString ds = ui->combo_pools->currentText();
- if(ds.isEmpty()){ return; }
- LPConfig CFG(this);
- CFG.loadDataset(ds, LPBackend::listReplicationTargets().contains(ds));
- CFG.exec();
- //Now check for return values and update appropriately
- bool change = false;
- if(CFG.localChanged){
- ui->statusbar->showMessage(QString(tr("Configuring dataset: %1")).arg(ds),0);
- LPBackend::setupDataset(ds, CFG.localSchedule, CFG.localSnapshots);
- ui->statusbar->clearMessage();
- change = true;
- }
- if(CFG.remoteChanged){
- change = true;
- if(CFG.isReplicated){
- ui->statusbar->showMessage(QString(tr("Configuring replication: %1")).arg(ds),0);
- LPBackend::setupReplication(ds, CFG.remoteHost, CFG.remoteUser, CFG.remotePort, CFG.remoteDataset, CFG.remoteFreq);
- QMessageBox::information(this,tr("Reminder"),tr("Don't forget to save your SSH key to a USB stick so that you can restore your system from the remote host later!!"));
- }else{
- ui->statusbar->showMessage(QString(tr("Removing replication: %1")).arg(ds),0);
- LPBackend::removeReplication(ds);
- }
- ui->statusbar->clearMessage();
- }
- //Now update the UI if appropriate
- if(change){
- updateTabs();
- }
-}
-
-// -----------------------------------------------
-// MENU SLOTS
-// -----------------------------------------------
-// ==== File Menu ====
-void LPMain::menuAddPool(QAction *act){
- QString dataset = act->text();
- qDebug() << "Start Wizard for new managing pool:" << dataset;
- LPWizard wiz(this);
- wiz.setDataset(dataset);
- wiz.exec();
- //See if the wizard was cancelled or not
- if(!wiz.cancelled){
- ui->statusbar->showMessage(QString(tr("Enabling dataset management: %1")).arg(dataset),0);
- //run the proper commands to get the dataset enabled
- if( LPBackend::setupDataset(dataset, wiz.localTime, wiz.totalSnapshots) ){
- if(wiz.enableReplication){
- LPBackend::setupReplication(dataset, wiz.remoteHost, wiz.remoteUser, wiz.remotePort, wiz.remoteDataset, wiz.remoteTime);
- QMessageBox::information(this,tr("Reminder"),tr("Don't forget to save your SSH key to a USB stick so that you can restore your system from the remote host later!!"));
- }
- }
- ui->statusbar->clearMessage();
- //Now update the list of pools
- updatePoolList();
- }
-}
-
-void LPMain::menuRemovePool(QAction *act){
- QString ds = act->text();
- qDebug() << "Remove Pool:" << ds;
- if(!ds.isEmpty()){
- //Verify the removal of the dataset
- if( QMessageBox::Yes == QMessageBox::question(this,tr("Verify Dataset Backup Removal"),tr("Are you sure that you wish to cancel automated snapshots and/or replication of the following dataset?")+"\n\n"+ds,QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- //verify the removal of all the snapshots for this dataset
- QStringList snaps = LPBackend::listLPSnapshots(ds);
- if(!snaps.isEmpty()){
- if( QMessageBox::Yes == QMessageBox::question(this,tr("Verify Snapshot Deletion"),tr("Do you wish to remove the local snapshots for this dataset?")+"\n"+tr("WARNING: This is a permanant change that cannot be reversed"),QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- //Remove all the snapshots
- ui->statusbar->showMessage(QString(tr("%1: Removing snapshots")).arg(ds),0);
- showWaitBox(tr("Removing snapshots"));
- for(int i=0; i<snaps.length(); i++){
- LPBackend::removeSnapshot(ds,snaps[i]);
- }
- ui->statusbar->clearMessage();
- }
- }
- //Remove the dataset from life-preserver management
- if(LPBackend::listReplicationTargets().contains(ds)){
- ui->statusbar->showMessage(QString(tr("%1: Disabling Replication")).arg(ds),0);
- showWaitBox(tr("Disabling Replication"));
- LPBackend::removeReplication(ds);
- ui->statusbar->clearMessage();
- }
- ui->statusbar->showMessage(QString(tr("%1: Disabling Life-Preserver Management")).arg(ds),0);
- showWaitBox(tr("Removing Life Preserver Schedules"));
- LPBackend::removeDataset(ds);
- ui->statusbar->clearMessage();
- updatePoolList();
- hideWaitBox();
- }
- } //end check for empty ds
-
-}
-
-void LPMain::menuSaveSSHKey(){
- QString ds = ui->combo_pools->currentText();
- qDebug() << "Save SSH Key:" << ds;
- if(ds.isEmpty()){ return; }
- //Get the local hostname
- char host[1023] = "\0";
- gethostname(host,1023);
- QString localHost = QString(host).simplified();
- qDebug() << " - hostname:" << localHost;
- //Scan for mounted USB devices
- QStringList devs = LPBackend::findValidUSBDevices();
- qDebug() << " - devs:" << devs;
- if(devs.isEmpty()){
- QMessageBox::warning(this,tr("No Valid USB Devices"), tr("No valid USB devices could be found. Please mount a FAT32 formatted USB stick and try again."));
- return;
- }
- //Ask the user which one to save the file to
- bool ok;
- QString dev = QInputDialog::getItem(this, tr("Select USB Device"), tr("Available USB Devices:"), devs,0,false,&ok);
- if(!ok or dev.isEmpty()){ return; } //cancelled
- QString devPath = dev.section("(",0,0).simplified();
- //Now copy the file over
- ok = LPBackend::copySSHKey(devPath, localHost);
- if(ok){
- QMessageBox::information(this,tr("Success"), tr("The public SSH key file was successfully copied onto the USB device."));
- }else{
- QMessageBox::information(this,tr("Failure"), tr("The public SSH key file could not be copied onto the USB device."));
- }
-}
-
-void LPMain::menuCloseWindow(){
- this->close();
-}
-
-// ==== Classic Backups Menu ====
-void LPMain::menuCompressHomeDir(QAction* act){
- QString user = act->text();
- qDebug() << "Compress Home Dir:" << user;
- //Prompt for the package name
- QString pkgName = user+"-"+QDateTime::currentDateTime().toString("yyyyMMdd-hhmm");
- bool ok;
- pkgName = QInputDialog::getText(this, tr("Package Name"), tr("Name of the package to create:"), QLineEdit::Normal, pkgName, &ok);
- if(!ok || pkgName.isEmpty() ){ return; } //cancelled
- //Now create the package
- showWaitBox(tr("Packaging home directory"));
- QString pkgPath = LPGUtils::packageHomeDir(user, pkgName);
- hideWaitBox();
- //Now inform the user of the result
- if(pkgPath.isEmpty()){
- qDebug() << "No Package created";
- QMessageBox::warning(this,tr("Package Failure"), tr("The home directory package could not be created."));
- }else{
- qDebug() << "Package created at:" << pkgPath;
- QMessageBox::information(this,tr("Package Success"), tr("The home directory package was successfully created.")+"\n\n"+pkgPath);
- }
-}
-
-void LPMain::menuExtractHomeDir(){
- qDebug() << "Extract Home Dir";
- //Get the file path from the user
- QString filePath = QFileDialog::getOpenFileName(this,tr("Find Home Dir Package"), "/usr/home", tr("Home Dir Package (*.home.tar.gz)") );
- if(filePath.isEmpty() || !QFile::exists(filePath)){ return; } //cancelled
- //Now check if the user in the package is also on the system
- QString username;
- bool ok = LPGUtils::checkPackageUserPath(filePath, &username);
- if(!ok){
- QMessageBox::warning(this,tr("User Missing"),QString(tr("The user (%1) does not exist on this system. Please create this user first and then try again.")).arg(username) );
- return;
- }
- //Now extract the package
- showWaitBox(tr("Extracting Home Directory"));
- ok = LPGUtils::extractHomeDirPackage(filePath);
- hideWaitBox();
- //Now report the results
- if(ok){
- QMessageBox::information(this,tr("Package Extracted"), QString(tr("The package was successfully extracted within %1")).arg("/usr/home/"+username) );
- }else{
- QMessageBox::warning(this, tr("Package Failure"), QString(tr("The package could not be extracted within %1")).arg("/usr/home/"+username) );
- }
-
-}
-
-// ==== Disks Menu ====
-void LPMain::menuAddDisk(){
- QString pool = ui->combo_pools->currentText();
- //Get the available disks and remove the current disks
- QStringList adisks = LPGUtils::listAvailableHardDisks();
- for(int i=0; i<POOLDATA.harddisks.length(); i++){
- adisks.removeAll( POOLDATA.harddisks[i].section("s",0,0,QString::SectionSkipEmpty) );
- }
- if(adisks.isEmpty()){
- QMessageBox::information(this,tr("Attach New Disk"), tr("No available disks could be found"));
- return;
- }
- //Find a disk that can be added to the system
- bool ok=false;
- QString disk = QInputDialog::getItem(this, tr("Attach New Disk"),tr("Detected Disks:"), adisks,0,false, &ok);
- if( !ok || disk.isEmpty() ){ return; }
- qDebug() << "Add Disk:" << disk << pool;
- showWaitBox(tr("Attaching disk"));
- ok = LPBackend::attachDisk(pool, disk);
- hideWaitBox();
- if(ok){
- QMessageBox::information(this,tr("Disk Attached"),QString(tr("Success: %1 was added to %2")).arg(disk,pool) );
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Disk Attach Error"),QString(tr("Failure: %1 could not be attached to %2.")).arg(disk,pool) );
- }
-}
-
-void LPMain::menuRemoveDisk(QAction *act){
- QString disk = act->text();
- QString pool = ui->combo_pools->currentText();
- //Verify action
- if(QMessageBox::Yes != QMessageBox::question(this,tr("Verify Disk Removal"),QString(tr("Are you sure that you want to remove %1 from %2?")).arg(disk,pool) + "\n\n" + tr("CAUTION: This disk can only be re-attached later as a brand new disk"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- return; //cancelled
- }
- qDebug() << "Remove Disk:" << disk << pool;
- showWaitBox(tr("Detaching disk"));
- bool ok = LPBackend::detachDisk(pool, disk);
- hideWaitBox();
- if(ok){
- QMessageBox::information(this,tr("Disk Removal Success"),QString(tr("Success: %1 was removed from %2")).arg(disk, pool) );
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Disk Removal Failure"),QString(tr("Failure: %1 could not be removed from %2 at this time.")).arg(disk, pool) );
- }
-}
-
-void LPMain::menuOfflineDisk(QAction *act){
- QString disk = act->text();
- QString pool = ui->combo_pools->currentText();
- //Verify action
- if(QMessageBox::Yes != QMessageBox::question(this,tr("Verify Disk Offline"),QString(tr("Are you sure you wish to set %1 offline?")).arg(disk), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- return; //cancelled
- }
- qDebug() << "Offline Disk:" << disk << pool;
- showWaitBox(tr("Setting disk offline"));
- bool ok = LPBackend::setDiskOffline(pool, disk);
- hideWaitBox();
- if(ok){
- QMessageBox::information(this,tr("Disk Offline Success"),QString(tr("Success: %1 has been taken offline.")).arg(disk) );
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Disk Offline Failure"),QString(tr("Failure: %1 could not be taken offline at this time.")).arg(disk) );
- }
-}
-
-void LPMain::menuOnlineDisk(QAction *act){
- QString disk = act->text();
- QString pool = ui->combo_pools->currentText();
- //Verify action
- if(QMessageBox::Yes != QMessageBox::question(this,tr("Verify Disk Online"),QString(tr("Are you sure you wish to set %1 online?")).arg(disk), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- return; //cancelled
- }
- qDebug() << "Online Disk:" << disk << pool;
- showWaitBox(tr("Setting disk online"));
- bool ok = LPBackend::setDiskOnline(pool, disk);
- hideWaitBox();
- if(ok){
- QMessageBox::information(this,tr("Disk Online Success"),QString(tr("Success: %1 has been set online.")).arg(disk) );
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Disk Online Failure"),QString(tr("Failure: %1 could not be set online at this time.")).arg(disk) );
- }
-}
-
-void LPMain::menuStartScrub(){
- QString pool = ui->combo_pools->currentText();
- //Verify starting a scrub
- if( QMessageBox::Yes != QMessageBox::question(this,tr("Verify Scrub"),QString(tr("Are you sure you want to start a scrub on %1?")).arg(pool) + "\n"+tr("NOTE: This may take quite a while to complete"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- return; //cancelled
- }
- qDebug() << "Start Scrub:" << pool;
- QString cmd = "zpool scrub "+pool;
- showWaitBox(tr("Trying to start a scrub"));
- int ret = system(cmd.toUtf8());
- hideWaitBox();
- if(ret == 0){
- //Now let te user know that one has been triggered
- QMessageBox::information(this,tr("Scrub Started"),QString(tr("A scrub has just been started on %1")).arg(pool));
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Scrub Not Started"), QString(tr("A scrub on %1 could not be started at this time.")).arg(pool) + "\n"+tr("Please wait until any current resilvering or scrubs are finished before trying again.") );
- }
-}
-
-void LPMain::menuStopScrub(){
- QString pool = ui->combo_pools->currentText();
- //Verify stopping a scrub
- if( QMessageBox::Yes != QMessageBox::question(this,tr("Verify Scrub"),QString(tr("Are you sure you want to stop the scrub on %1?")).arg(pool), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- return; //cancelled
- }
- qDebug() << "Stop Scrub:" << pool;
- QString cmd = "zpool scrub -s "+pool;
- showWaitBox(tr("Trying to stop scrub"));
- int ret = system(cmd.toUtf8());
- hideWaitBox();
- if(ret == 0){
- //Now let te user know that one has been triggered
- QMessageBox::information(this,tr("Scrub Stopped"),QString(tr("The scrub on %1 has been stopped.")).arg(pool));
- QTimer::singleShot(0,this,SLOT(updateTabs()) );
- }else{
- QMessageBox::warning(this,tr("Scrub Not Running"), QString(tr("There was no scrub running on %1.")).arg(pool) );
- }
-}
-
-// ==== Snapshots Menu ====
-void LPMain::menuNewSnapshot(){
- qDebug() << "New Snapshot";
- QString ds = ui->combo_pools->currentText();
- if(ds.isEmpty()){return; }
- //Get the new snapshot name from the user
- bool ok;
- QString name = QInputDialog::getText(this,tr("New Snapshot Name"), tr("Snapshot Name:"), QLineEdit::Normal, tr("Name"), &ok, 0, Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly | Qt::ImhDigitsOnly );
- if(!ok || name.isEmpty()){ return; } //cancelled
- qDebug() << "Creating a new snapshot:" << ds << name;
- //Now create the new snapshot
- LPBackend::newSnapshot(ds,name);
- QMessageBox::information(this,tr("Snapshot Pending"), tr("The new snapshot creation has been added to the queue"));
- updateTabs();
-}
-
-void LPMain::menuRemoveSnapshot(QAction *act){
- QString snapshot = act->text();
- QString pool = ui->combo_pools->currentText();
- qDebug() << "Remove Snapshot:" << snapshot;
- //verify snapshot removal
- if( QMessageBox::Yes == QMessageBox::question(this,tr("Verify Snapshot Deletion"),QString(tr("Do you wish to delete this snapshot? %1")).arg(pool+"/"+snapshot)+"\n"+tr("WARNING: This is a permanant change that cannot be reversed"),QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
- bool ok = LPBackend::removeSnapshot(ui->combo_pools->currentText(), snapshot);
- if(ok){
- QMessageBox::information(this,tr("Snapshot Removed"),tr("The snapshot was successfully deleted"));
- }else{
- QMessageBox::information(this,tr("Snapshot Removal Failure"),tr("The snapshot removal experienced an error and it not be completed at this time."));
- }
- updateTabs();
- }
-}
View
84 lp-gui/LPMain.h
@@ -1,84 +0,0 @@
-#ifndef _LP_MAIN_H
-#define _LP_MAIN_H
-
-#include <QMainWindow>
-#include <QComboBox>
-#include <QToolButton>
-#include <QLabel>
-#include <QString>
-#include <QStringList>
-#include <QRadioButton>
-#include <QWidgetAction>
-#include <QFileSystemModel>
-#include <QInputDialog>
-#include <QDateTime>
-#include <QTimer>
-#include <QFileDialog>
-
-#include "LPBackend.h"
-#include "LPContainers.h"
-#include "LPGUtils.h"
-#include "LPWizard.h"
-#include "LPConfig.h"
-
-namespace Ui{
- class LPMain;
-};
-
-class LPMain : public QMainWindow{
- Q_OBJECT
-public:
- LPMain(QWidget *parent = 0);
- ~LPMain();
-
-public slots:
- void slotSingleInstance();
-
-private:
- Ui::LPMain *ui;
- QRadioButton *viewBasic, *viewAdvanced;
- QFileSystemModel *fsModel;
- bool poolSelected;
- LPDataset POOLDATA;
- QMessageBox *waitBox;
-
- void showErrorDialog(QString title, QString message, QString errors);
- void showWaitBox(QString message);
- void hideWaitBox();
-
-private slots:
- void updatePoolList(); //re-load available pools
- void viewChanged();
- void updateTabs(); //load current pool info and update tabs
- void updateDataset(); //restore dataset changed
- void updateSnapshot(); //selected snapshot changed
- void nextSnapshot();
- void prevSnapshot();
- void setFileVisibility();
- void restoreFiles();
- void openConfigGUI();
- // -- Menu Actions --
- //File Menu
- void menuAddPool(QAction*);
- void menuRemovePool(QAction*);
- void menuSaveSSHKey();
- void menuCloseWindow();
- //Classic Backups
- void menuCompressHomeDir(QAction*);
- void menuExtractHomeDir();
- //Disk Menu
- void menuAddDisk();
- void menuRemoveDisk(QAction*);
- void menuOfflineDisk(QAction*);
- void menuOnlineDisk(QAction*);
- void menuStartScrub();
- void menuStopScrub();
- //Snapshots Menu
- void menuNewSnapshot();
- void menuRemoveSnapshot(QAction*);
-
-protected:
-
-};
-
-#endif
View
654 lp-gui/LPMain.ui
@@ -1,654 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LPMain</class>
- <widget class="QMainWindow" name="LPMain">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>459</width>
- <height>396</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Life Preserver</string>
- </property>
- <property name="windowIcon">
- <iconset resource="lPreserve.qrc">
- <normaloff>:/images/tray-icon-idle.png</normaloff>:/images/tray-icon-idle.png</iconset>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QToolButton" name="tool_refresh">
- <property name="statusTip">
- <string>Refresh the UI</string>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- <property name="icon">
- <iconset resource="lPreserve.qrc">
- <normaloff>:/images/refresh.png</normaloff>:/images/refresh.png</iconset>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="combo_pools">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="sizeAdjustPolicy">
- <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="push_configure">
- <property name="statusTip">
- <string>Configure snapshot and replication schedules</string>
- </property>
- <property name="text">
- <string>Configure</string>
- </property>
- <property name="icon">
- <iconset resource="lPreserve.qrc">
- <normaloff>:/images/configure.png</normaloff>:/images/configure.png</iconset>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex"