source: src-qt4/life-preserver/lp-gui/LPGUtils.cpp @ 8b3a780

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 8b3a780 was 8b3a780, checked in by Ken Moore <ken@…>, 13 months ago

Clean up the LP waitbox, so that it no longer shows the "ok" button.

  • Property mode set to 100644
File size: 11.6 KB
Line 
1#include "LPGUtils.h"
2
3LPDataset LPGUtils::loadPoolData(QString zpool){
4  //Load the current information for the given zpool
5  qDebug() << "[DEBUG] New Dataset: " << zpool;
6  LPDataset DSC;
7  //List all the mountpoints in this dataset
8  qDebug() << "[DEBUG] list snapshots";
9  QStringList subsets = LPBackend::listDatasetSubsets(zpool);
10  QStringList lpsnaps = LPBackend::listLPSnapshots(zpool);
11  //populate the list of snapshots available for each mountpoint
12  for(int i=0; i<subsets.length(); i++){
13    //qDebug() << "Subset:" << subsets[i];
14    QStringList snaps = LPBackend::listSnapshots(subsets[i]);
15    //qDebug() << " - Snapshots:" << snaps;
16    if(snaps.isEmpty()){
17      //invalid subset - remove it from the list
18      subsets.removeAt(i);
19      i--;
20    }else{
21      QStringList subsnaps;
22      //only list the valid snapshots that life preserver created
23      for(int s=0; s<lpsnaps.length(); s++){
24        int index = snaps.indexOf(lpsnaps[s]);
25        if(index > -1){ subsnaps << lpsnaps[s]; snaps.removeAt(index); }
26      }
27      /*//Now list all the other available snapshots (no certain ordering)
28      if(!snaps.isEmpty()){try
29        subsnaps << "--"; //so we know that this is a divider between the sections
30        subsnaps << snaps;
31      }*/
32      DSC.subsetHash.insert(subsets[i],subsnaps); //add it to the internal container hash
33    }
34  }
35  //Parse "zpool status <pool>"
36  qDebug() << "[DEBUG] get zpool status";
37  QStringList zstat = LPBackend::getCmdOutput("zpool status "+zpool);
38  qDebug() << zstat.join("\n");
39  //qDebug() << "zpool status "+zpool+":\n" << zstat.join("\n");
40  bool atheader=false;
41  QStringList disks, diskstates, running, errors, finished;
42  for(int i=0; i<zstat.length(); i++){
43    if(zstat[i].isEmpty()){ continue; }
44    else if(zstat[i].startsWith("  scan:")){
45      QString line = zstat[i].section(":",1,50).replace("\t"," ").simplified();
46      if(line.contains("scrub repaired ")){
47        QString timestamp = line.section(" ",9,13,QString::SectionSkipEmpty);
48        QString numerrors = line.section(" ",6,6,QString::SectionSkipEmpty);
49        finished << QString(QObject::tr("Scrub Finished: %1 (%2 errors)")).arg(timestamp, numerrors);
50      }else if(line.contains("scrub cancel")){
51         QString timestamp = line.section(" ",3,7,QString::SectionSkipEmpty);     
52          finished << QString(QObject::tr("Scrub Cancelled: %1")).arg(timestamp);
53      }else if(line.contains("scrub")){
54        QString timestamp = line.section(" ",4,8,QString::SectionSkipEmpty);
55        running << QString(QObject::tr("Scrub Started: %1")).arg(timestamp);     
56      }else if(line.contains("resilvered")){
57        QString timestamp = line.section(" ",8,12,QString::SectionSkipEmpty);
58        QString numerrors = line.section(" ",5,5,QString::SectionSkipEmpty);
59        finished << QString(QObject::tr("Resilver Finished: %1 (%2 errors)")).arg(timestamp, numerrors);
60      }
61    }else if(zstat[i].contains("NAME") && zstat[i].contains("STATE") && zstat[i].contains("READ") ){
62      //qDebug() <<"Found header";
63      atheader=true;
64    }else if(zstat[i].startsWith("errors:")){ 
65      atheader=false; 
66    }else if(atheader){
67      QString line = zstat[i].replace("\t"," ").simplified();
68      QString dev = line.section(" ",0,0,QString::SectionSkipEmpty);
69      QString state = line.section(" ",1,1,QString::SectionSkipEmpty);
70      //qDebug() << "Found device:" << dev << state;
71      if(dev == zpool){
72        DSC.poolStatus = state;
73      }else if(line.contains("(resilvering)")){
74        disks << dev; diskstates << state; //record this disk and state
75        running << QString(QObject::tr("%1: Currently Resilvering")).arg(dev);
76      }else{
77        disks << dev; diskstates << state; //record this disk and state
78        if(state != "ONLINE"){
79          errors << QString(QObject::tr("%1: %2")).arg(dev, state);
80        }
81      }
82    }
83  }
84  qDebug() << "[DEBUG] Get latest snapshot/replication info";
85  //Now get the latest Snapshot/Replication information
86  QStringList lpstat = LPBackend::listCurrentStatus();
87  for(int i=0; i<lpstat.length(); i++){
88    if(lpstat[i].section(":::",0,0) == zpool){
89      QString lastSnap = lpstat[i].section(":::",1,1);
90      QString lastRep = lpstat[i].section(":::",2,2);
91      if(lastSnap=="-"){ DSC.latestSnapshot = QObject::tr("No Snapshots Available"); }
92      else{ DSC.latestSnapshot = lastSnap; }
93      if(lastRep!="-"){
94        finished << QString(QObject::tr("Latest Replication: %1")).arg(lastRep);
95      }else if(LPBackend::listReplicationTargets().contains(zpool) ){
96        errors << QObject::tr("No Successful Replication");
97      }
98    }
99  }
100  qDebug() << "[DEBUG] save info to the structure and finish";
101  //Now save the info to the dataset
102  DSC.harddisks = disks;
103  DSC.harddiskStatus = diskstates;
104  DSC.errorStatus = errors.join("\n");
105  DSC.runningStatus = running.join("\n");
106  DSC.finishedStatus = finished.join("\n");
107  //Return the dataset
108  return DSC;
109}
110
111QString LPGUtils::generateReversionFileName(QString fileName, QString destDir){
112  fileName = fileName.section("/",-1); //Make sure we only have the filename (no paths)
113  if( !destDir.endsWith("/") ){ destDir.append("/"); }
114  //Quick check if that file already exists in the destination directory
115  if( !QFile::exists(destDir+fileName) ){ return fileName; }
116  //Change the filename to prevent overwriting an existing file
117  QString ext = fileName.section(".",-1); //Get the extension for the filename
118  if( fileName != ext && fileName != ("."+ext) ){
119    //Extension found - need careful adjustment of filename
120    QString newFileName = fileName;
121    newFileName.replace("."+ext, "-reversion."+ext);
122    int i=2;
123    while( QFile::exists(destDir+newFileName) ){
124      //Also need to append a reversion number
125      newFileName = fileName; 
126      newFileName.replace("."+ext, "-reversion"+QString::number(i)+"."+ext);
127      i++; //for the next time around
128    }
129    fileName = newFileName;
130  }else{
131    //no extension - just append the reversion
132    fileName.append("-reversion");
133    if(QFile::exists(destDir+fileName) ){
134      //Also need to append a reversion number
135      int i=2;
136      while( QFile::exists(destDir+fileName+QString::number(i)) ){ i++; }
137      fileName.append( QString::number(i) );
138    }
139  }
140  return fileName;
141}
142
143bool LPGUtils::revertFile(QString oldPath, QString newPath){
144  bool ok = QFile::copy(oldPath,newPath);
145  //return the path to the new file if the copy was successful
146  if(ok){ 
147    //reset the permissions on the reverted file to match the original
148    QFile::setPermissions(newPath, QFile::permissions(oldPath));
149    QFileInfo FI(oldPath);
150      system( QString("chown "+FI.owner()+":"+FI.group()+" "+newPath).toUtf8() );
151  }
152  return ok;
153}
154
155QStringList LPGUtils::revertDir(QString oldPath, QString newPath){
156  //Note: this is a recursive function and can take quite a while to perform lots of file copies
157
158  //Load the directories and create it if necessary
159  QDir oDir(oldPath);
160  QDir nDir(newPath);
161  bool ok=true;
162  if( !nDir.exists() ){
163    //Create the new Directory
164    nDir.cdUp();
165    ok = nDir.mkdir(newPath.section("/",-1));
166    if(ok){ 
167      nDir.cd(newPath.section("/",-1)); 
168      QFile::setPermissions(newPath, QFile::permissions(oldPath)); //make sure the new dir has the old permissions
169      QFileInfo FI(oldPath);
170      system( QString("chown "+FI.owner()+":"+FI.group()+" "+newPath).toUtf8() );
171    }
172  }
173  //Get a list of any files that error
174  QStringList errors;
175  if(!ok){
176    errors << newPath;
177    return errors;
178  }
179  //Get a list of all the files in the old dir and copy them over
180  QStringList fList = oDir.entryList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name);
181  for(int i=0; i<fList.length(); i++){
182    if( !revertFile(oldPath+"/"+fList[i], newPath+"/"+fList[i]) ){
183       errors << newPath+"/"+fList[i];
184    }
185  }
186  //Now list all the directories in the old dir and recursively copy them over
187  fList = oDir.entryList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name);
188  for(int i=0; i<fList.length(); i++){
189    QStringList errs = revertDir(oldPath+"/"+fList[i], newPath+"/"+fList[i]);
190    if( !errs.isEmpty() ){ errors << errs; }
191  }
192  return errors;
193}
194
195QString LPGUtils::packageHomeDir(QString username, QString packageName){
196  //Check that the user directory exists
197  //qDebug() << "Start package dir:" << username << packageName;
198  if(!QFile::exists("/usr/home/"+username)){ return ""; }
199  //Check that the package has the right extension
200  if(!packageName.endsWith(".home.tar.gz")){ packageName.append(".home.tar.gz"); }
201  //Generate any additional files to be contained in the package
202 
203 
204  //Generate the command
205  QString cmd = "tar";
206  QStringList args;
207  args << "-czf" << "/usr/home/"+packageName << "-C" << "/usr/home" << username;
208  //Create the exclude list and skip these files
209  QStringList excludes;
210    excludes << "*flashplayer*" << "*/PBI-*.desktop"; //Don't include the flash plugin/PBI entries
211  for(int i=0; i<excludes.length(); i++){
212    args.prepend(excludes[i]); args.prepend("--exclude");
213  }
214  //Run the command
215  qDebug() << "Package command:" << cmd << args;
216  LPBackend::runCmd(cmd, args); //need to use this version due to the complex command
217
218  //Check that the package was created
219  QString packagePath;
220  if(QFile::exists("/usr/home/"+packageName)){ packagePath = "/usr/home/"+packageName; }
221  //Now return the path to the package file
222  return packagePath;
223}
224
225bool LPGUtils::checkPackageUserPath(QString packagePath, QString *user){
226  user->clear();
227  //Determine if the file exists
228  if( !QFile::exists(packagePath) ){ return false; }
229  //Check the username of the home dir in the package
230  QStringList ret = LPBackend::getCmdOutput("tar -tvf "+packagePath+" -q \"*/Desktop\"");
231  if(ret.isEmpty()){ return false; }
232  QString username = ret[0].section(" ",2,2,QString::SectionSkipEmpty).simplified();
233  QString dirname = ret[0].section(" ",8,8,QString::SectionSkipEmpty).section("/",0,0).simplified();
234  user->append(username); //additional output
235  //Now check for the user on the local system
236  //This is just a simple check that the user directory exists, and the user/directory are the same within the package
237  return (username == dirname && QFile::exists("/usr/home/"+dirname) ); 
238}
239
240bool LPGUtils::extractHomeDirPackage(QString packagePath){
241 //Determine if the file exists
242  if( !QFile::exists(packagePath) ){ return false; }
243  //Now extract the archive in the home directory
244  QString cmd = "tar -xpf "+packagePath+" -C /usr/home";
245  qDebug() << "Extract command:" << cmd;
246  int ret = LPBackend::runCmd(cmd);
247  return (ret == 0);
248}
249
250QStringList LPGUtils::listAvailableHardDisks(){
251  QDir dev("/dev");
252  QStringList filters;
253        filters << "ada*" << "da*";
254  QStringList devs = dev.entryList(filters, QDir::Files | QDir::System | QDir::NoDotAndDotDot, QDir::Name);
255  //Filter out all the partitions (only keep full devices)
256  for(int i=0; i<devs.length(); i++){
257    devs[i] = devs[i].section("s",0,0,QString::SectionSkipEmpty);
258  }
259  devs.removeDuplicates();
260  return devs;
261}
262
263QStringList LPGUtils::scanNetworkSSH(){
264  //Output format: <name>:::<address>::::<port>
265  QStringList out;
266  QStringList netout = LPBackend::getCmdOutput("avahi-browse -art");
267  for(int i=0; i<netout.length(); i++){
268    if(netout[i].startsWith("=") && netout[i].contains("local")){
269      QString name, address, port;
270      for(int j=0; j<3; j++){ //need the next 3 lines
271        i++; //Move to the next line
272        QString var = netout[i].section("=",0,0).replace("\t"," ").simplified();
273        QString val = netout[i].section("[",1,1).section("]",0,0).simplified();
274        if(var == "hostname"){ name = val.section(".local",0,0).simplified(); }
275        else if(var == "address"){ address = val; }
276        else if(var == "port"){ port = val; }
277      }
278      //Check that it is an SSH connection that is open (port 22)
279      if(port == "22"){ 
280         out << name+":::"+address+":::"+port;
281      }
282    }
283  }
284  return out;
285}
Note: See TracBrowser for help on using the repository browser.