source: src-qt4/pc-installgui/wizardDisk.cpp @ 93572be

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1releng/10.1.1
Last change on this file since 93572be was 93572be, checked in by Kris Moore <kris@…>, 19 months ago

Welcome the new Life-Preserver restore ability to the Installer GUI

Now you can restore your entire system from a replicated life-preserver backup on a
remote machine

  • Property mode set to 100644
File size: 31.8 KB
Line 
1/****************************************************************************
2** ui.h extension file, included from the uic-generated form implementation.
3**
4** If you want to add, delete, or rename functions or slots, use
5** Qt Designer to update this file, preserving your code.
6**
7** You should not define a constructor or destructor in this file.
8** Instead, write your code in functions called init() and destroy().
9** These will automatically be called by the form's constructor and
10** destructor.
11*****************************************************************************/
12#include <QDebug>
13#include <QInputDialog>
14#include <QMessageBox>
15#include "wizardDisk.h"
16#include "ui_wizardDisk.h"
17
18void wizardDisk::programInit()
19{
20  prevID = 0;
21  restoreMode=false;
22
23  populateDiskInfo();
24
25  //connect(pushClose, SIGNAL(clicked()), this, SLOT(slotClose()));
26  connect(pushSwapSize, SIGNAL(clicked()), this, SLOT(slotSwapSize()));
27  connect(pushRemoveMount, SIGNAL(clicked()), this, SLOT(slotRemoveFS()));
28  connect(pushAddMount, SIGNAL(clicked()), this, SLOT(slotAddFS()));
29  connect(this,SIGNAL(currentIdChanged(int)),this,SLOT(slotCheckComplete()));
30  connect(lineZpoolName,SIGNAL(textChanged ( const QString & )),this,SLOT(slotCheckComplete()));
31  connect(groupZFSPool,SIGNAL( clicked(bool)),this,SLOT(slotCheckComplete()));
32  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
33  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotChangedDisk()));
34  connect(comboPartition,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
35  connect(treeMounts,SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),this,SLOT(slotTreeDiskChanged()));
36  treeMounts->setContextMenuPolicy(Qt::CustomContextMenu);
37  connect(treeMounts,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(slotTreeMountsRightClick()));
38  connect(pushTerminal, SIGNAL(clicked()), this, SLOT(slotTerminal()));
39
40  // ZFS Mode Page
41  connect(comboZFSMode,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
42  connect(groupZFSOpts,SIGNAL(clicked(bool)),this,SLOT(slotCheckComplete()));
43  connect(listZFSDisks,SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
44  connect(listZFSDisks,SIGNAL(itemActivated(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
45  connect(listZFSDisks,SIGNAL(itemChanged(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
46
47}
48
49void wizardDisk::populateDiskInfo()
50{
51  qDebug() << "Loading Disk Info";
52  sysDisks = Scripts::Backend::hardDrives();
53
54  // load drives
55  comboDisk->clear();
56  for (int i=0; i < sysDisks.count(); ++i) {
57    // Make sure to only add the drives to the comboDisk
58    if ( sysDisks.at(i).at(0) == "DRIVE" )
59      comboDisk->addItem(sysDisks.at(i).at(1) + " - " + sysDisks.at(i).at(2) + "MB " + sysDisks.at(i).at(3));
60  }
61
62  // Reload the slice list box
63  slotChangedDisk();
64}
65
66void wizardDisk::slotChangedDisk()
67{
68  QString ptag;
69
70  if ( comboDisk->currentText().isEmpty())
71    return;
72
73  comboPartition->clear();
74  comboPartition->addItem(tr("Use entire disk"));
75       
76  QString disk = comboDisk->currentText();
77  disk.truncate(disk.indexOf(" -"));
78  for (int i=0; i < sysDisks.count(); ++i) {
79    // Make sure to only add the slices to the listDiskSlices
80    if ( sysDisks.at(i).at(0) == "SLICE" && disk == sysDisks.at(i).at(1) && sysDisks.at(i).at(4) != "Unused Space") {
81      ptag = sysDisks.at(i).at(4).section(",", 0, 0);
82      ptag = ptag.section("/", 0, 0);
83      ptag.truncate(15);
84      if ( ptag.indexOf(")") == -1 )
85        ptag += ")";
86      comboPartition->addItem(sysDisks.at(i).at(2) + ": " +  sysDisks.at(i).at(3) + "MB " + ptag );
87    }
88  }
89
90}
91
92void wizardDisk::slotClose()
93{
94  close();
95}
96
97void wizardDisk::accept()
98{
99  bool useGRUB = true;
100  bool useGPT = false;
101  bool force4K = false;
102  QString zpoolName;
103  if (comboPartition->currentIndex() == 0 )
104    useGPT = checkGPT->isChecked();
105
106  // Are we installing GRUB?
107  useGRUB = checkGRUB->isChecked();
108     
109  // When doing advanced ZFS setups, make sure to use GPT
110  if ( radioAdvanced->isChecked() && groupZFSOpts->isChecked() )
111    useGPT = true;
112
113  // When doing advanced ZFS setups, check if 4K is enabled
114  if ( radioAdvanced->isChecked() && checkForce4K->isChecked() )
115    force4K = true;
116
117  if ( radioAdvanced->isChecked() && groupZFSPool->isChecked() )
118     zpoolName = lineZpoolName->text();
119
120  if ( radioExpert->isChecked() )
121    emit saved(sysFinalDiskLayout, false, false, zpoolName, force4K);
122  else
123    emit saved(sysFinalDiskLayout, useGRUB, useGPT, zpoolName, force4K);
124  close();
125}
126
127int wizardDisk::nextId() const
128{
129  switch (currentId()) {
130     case Page_Intro:
131       if (radioExpert->isChecked())
132         return Page_Expert;
133       if (radioBasic->isChecked()) {
134         checkGPT->setVisible(false);
135         checkGRUB->setVisible(false);
136         checkForce4K->setVisible(false);
137         groupZFSPool->setVisible(false);
138       }
139       if (radioAdvanced->isChecked()) {
140         checkGPT->setVisible(true);
141         checkGRUB->setVisible(true);
142         checkForce4K->setVisible(true);
143         groupZFSPool->setVisible(true);
144       }
145        break;
146     case Page_BasicDisk:
147       if (radioBasic->isChecked())
148         return Page_Confirmation;
149       if (comboPartition->currentIndex() != 0 ) {
150         groupZFSOpts->setEnabled(false);
151         return Page_Mounts;
152       } else {
153         groupZFSOpts->setEnabled(true);
154         return Page_ZFS;
155       }
156       break;
157     case Page_ZFS:
158       return Page_Mounts;
159       break;
160     case Page_Mounts:
161       return Page_Confirmation;
162       break;
163     case Page_Confirmation:
164       return -1;
165       break;
166     default:
167        return currentId() + 1;
168  }
169  return currentId() + 1;
170}
171
172// Logic checks to see if we are ready to move onto next page
173bool wizardDisk::validatePage()
174{
175  // Generate suggested disk layout and show disk tree
176  if ( prevID == Page_BasicDisk && currentId() == Page_Mounts) {
177    generateDiskLayout();
178    populateDiskTree();
179  }
180
181  // Generate suggested disk layout and show disk tree
182  if ( prevID == Page_ZFS && currentId() == Page_Mounts) {
183    generateDiskLayout();
184    populateDiskTree();
185  } 
186
187  // Show the other disks available
188  if ( prevID == Page_BasicDisk && currentId() == Page_ZFS)
189     populateZFSDisks();
190
191  // Basic mode, generate a disk layout and show summary
192  if ( prevID == Page_BasicDisk && currentId() == Page_Confirmation) {
193    generateDiskLayout();
194    generateConfirmationText();
195  }
196
197  // Create the final disk layout from user options
198  if ( prevID == Page_Mounts && currentId() == Page_Confirmation) {
199    generateCustomDiskLayout();
200    generateConfirmationText();
201  }
202
203  // Create the final disk layout from user options
204  if ( prevID == Page_Expert && currentId() == Page_Confirmation) {
205    generateConfirmationText();
206  }
207 
208 
209  // Reset the prevID
210  prevID = currentId();
211
212  switch (currentId()) {
213     case Page_Intro:
214         button(QWizard::NextButton)->setEnabled(true);
215         return true;
216     case Page_BasicDisk:
217         if ( comboPartition->currentIndex() == 0  && radioAdvanced->isChecked()) {
218           checkGPT->setVisible(true);
219           checkForce4K->setVisible(true);
220         } else {
221           checkGPT->setChecked(false);
222           checkGPT->setVisible(false);
223           checkForce4K->setVisible(false);
224           checkForce4K->setChecked(false);
225         }
226
227         // Doing a Advanced install
228         if ( radioAdvanced->isChecked() && groupZFSPool->isChecked() )
229         {
230            if ( lineZpoolName->text().isEmpty() ) {
231              button(QWizard::NextButton)->setEnabled(false);
232              return false;
233            }
234            if ( lineZpoolName->text() == "root" ) {
235              button(QWizard::NextButton)->setEnabled(false);
236              return false;
237            }
238            if ( lineZpoolName->text().contains(" ") ) {
239              button(QWizard::NextButton)->setEnabled(false);
240              return false;
241            }
242            QRegExp *re = new QRegExp("^[-'a-zA-Z]*$"); 
243            if (! re->exactMatch(lineZpoolName->text()) ) {
244              button(QWizard::NextButton)->setEnabled(false);
245              return false;
246            }
247
248         }
249
250         // If the select partition is just too small, we can stop here
251         if ( ! checkDiskSpace() ) {
252           button(QWizard::NextButton)->setEnabled(false);
253           return false;
254         }
255       
256         // if we get this far, all the fields are filled in
257         button(QWizard::NextButton)->setEnabled(true);
258         return true;
259     case Page_ZFS:
260         // Check if we have valid ZFS disk options specified
261         if ( ! groupZFSOpts->isChecked() ) {
262           button(QWizard::NextButton)->setEnabled(true);
263           return true;
264         }
265         // Need at least one other disk for mirroring
266         if ( comboZFSMode->currentText() == "mirror" ) {
267            labelZFSMsg->setText(tr("Please select at least 1 other drive for mirroring"));
268            for ( int i = 0; i < listZFSDisks->count(); ++i )
269            {
270                if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
271                   button(QWizard::NextButton)->setEnabled(true);
272                   return true;
273                }
274            }
275         }
276         if ( comboZFSMode->currentText() == "raidz1" ) {
277            labelZFSMsg->setText(tr("Please select 2 or 4 additional drives for raidz1"));
278            int numChecked = 0;
279            for ( int i = 0; i < listZFSDisks->count(); ++i )
280                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
281                   numChecked++;
282            if ( numChecked == 2 || numChecked == 4 ) {
283              button(QWizard::NextButton)->setEnabled(true);
284              return true;
285            }
286         }
287         if ( comboZFSMode->currentText() == "raidz2" ) {
288            labelZFSMsg->setText(tr("Please select 3, 5, or 9 additional drives for raidz2"));
289            int numChecked = 0;
290            for ( int i = 0; i < listZFSDisks->count(); ++i )
291                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
292                   numChecked++;
293            if ( numChecked == 3 || numChecked == 5 || numChecked == 9 ) {
294              button(QWizard::NextButton)->setEnabled(true);
295              return true;
296            }
297         }
298         if ( comboZFSMode->currentText() == "raidz3" ) {
299            labelZFSMsg->setText(tr("Please select 4, 6, or 10 additional drives for raidz3"));
300            int numChecked = 0;
301            for ( int i = 0; i < listZFSDisks->count(); ++i )
302                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
303                   numChecked++;
304            if ( numChecked == 4 || numChecked == 6 || numChecked == 10 ) {
305              button(QWizard::NextButton)->setEnabled(true);
306              return true;
307            }
308         }
309
310         // Disable the next button until we get a working config
311         button(QWizard::NextButton)->setEnabled(false);
312         return false;
313     case Page_Confirmation:
314         button(QWizard::FinishButton)->setEnabled(true);
315         return true;
316     default:
317         button(QWizard::NextButton)->setEnabled(true);
318         return true;
319  }
320
321  return true;
322}
323
324void wizardDisk::populateZFSDisks()
325{
326   qDebug() << "Adding ZFS disks...";
327   listZFSDisks->clear();
328
329   QString curDisk = comboDisk->currentText();
330   curDisk.truncate(curDisk.indexOf(" -"));
331
332   for (int z=0; z < sysDisks.count(); ++z)
333     if ( sysDisks.at(z).at(0) == "DRIVE" && sysDisks.at(z).at(1) != curDisk  )
334     {
335        QListWidgetItem *dItem = new QListWidgetItem(sysDisks.at(z).at(1) + " - " + sysDisks.at(z).at(2) + "MB " + sysDisks.at(z).at(3));
336        dItem->setCheckState(Qt::Unchecked);
337        listZFSDisks->addItem(dItem);
338     }
339}
340
341bool wizardDisk::checkDiskSpace()
342{
343  if ( getDiskSliceSize() < 4000 )
344    return false;
345
346  return true;
347}
348
349void wizardDisk::slotCheckComplete()
350{
351   // Validate this page
352   validatePage();
353}
354
355
356void wizardDisk::generateDiskLayout()
357{
358  QString targetType, tmp;
359  int targetLoc, totalSize = 0;
360  QString targetDisk, targetSlice, tmpPass, fsType, target;
361
362  // Clear out the original disk layout
363  sysFinalDiskLayout.clear();
364  QStringList fileSystem;
365  qDebug() << "Generating disk layout";
366
367  if ( comboPartition->currentIndex() == 0) {
368    targetType = "DRIVE";
369    targetSlice = "ALL";
370    targetDisk = comboDisk->currentText();
371    targetDisk.truncate(targetDisk.indexOf(" -"));
372    target = targetDisk;
373    targetLoc = 1;
374  } else {
375    targetType = "SLICE";
376    targetDisk = comboDisk->currentText();
377    targetDisk.truncate(targetDisk.indexOf(" -"));
378    targetSlice = comboPartition->currentText();
379    targetSlice.truncate(targetSlice.indexOf(":"));
380    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
381    target = targetDisk + targetSlice;
382    targetLoc = 2;
383  }
384
385  // Get the size of the slice we are working on
386  totalSize = getDiskSliceSize();
387
388  // Setup some swap space
389  if ( totalSize > 30000 ) {
390    // 2GB if over 30GB of disk space, 512MB otherwise
391    swapsize = 2000;
392  } else {
393    swapsize = 512;
394  }
395  totalSize = totalSize - swapsize;
396
397
398  if ( totalSize != -1 )
399  {
400     fsType= "ZFS";
401
402     // This lets the user do nifty stuff like a mirror/raid post-install with a single zpool command
403    fileSystem << targetDisk << targetSlice << "/,/tmp(compress=lzjb),/usr(canmount=off),/usr/home,/usr/jails,/usr/obj(compress=lzjb),/usr/pbi,/usr/ports(compress=gzip),/usr/ports/distfiles(compress=off),/usr/src(compress=gzip),/var(canmount=off),/var/audit(compress=lzjb),/var/log(compress=gzip),/var/tmp(compress=lzjb)" << fsType << tmp.setNum(totalSize) << "" << tmpPass;
404    sysFinalDiskLayout << fileSystem;
405    fileSystem.clear();
406
407    // Now add swap space
408    fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(swapsize) << "" << "";
409    sysFinalDiskLayout << fileSystem;
410    fileSystem.clear();
411
412    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
413  }
414 
415  qDebug() << "AutoLayout:" <<  sysFinalDiskLayout;
416}
417
418void wizardDisk::populateDiskTree()
419{
420  QStringList tmpList, zMnts;
421  QString tmp, opts;
422
423  treeMounts->clear();
424  treeMounts->setHeaderLabels(QStringList() << "ID" << tr("ZFS Mounts") << tr("ZFS Options") );
425  treeMounts->setColumnCount(3);
426  labelFreeSpace->setVisible(false);
427  lineFreeMB->setVisible(false);
428
429  treeMounts->header()->setSectionHidden(0, true);
430  treeMounts->header()->setDefaultSectionSize(150);
431
432
433  zMnts = sysFinalDiskLayout.at(0).at(2).split(",");
434
435  // Now loop through ZFS mounts
436  for (int i=0; i < zMnts.count(); ++i) {
437    tmpList.clear();
438    opts = zMnts.at(i).section("(", 1, 1).section(")", 0, 0); 
439    tmpList << tmp.setNum(i+1) << zMnts.at(i).split("(").at(0) << opts ;
440    QTreeWidgetItem *mItem = new QTreeWidgetItem(treeMounts, tmpList);
441    mItem->setToolTip(2, opts);
442  }
443
444  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
445  slotTreeDiskChanged(); 
446
447  if ( restoreMode ) {
448     treeMounts->setEnabled(false);
449     pushRemoveMount->setEnabled(false);
450     pushAddMount->setEnabled(false);
451     labelMounts->setText(tr("The original system datasets / mount-points will be automatically restored."));
452  }
453
454}
455
456int wizardDisk::getDiskSliceSize()
457{
458  bool ok;
459  QString disk = comboDisk->currentText();
460  disk.truncate(disk.indexOf(" -"));
461
462  int safeBuf = 10;
463
464  // Check the full disk
465  if ( comboPartition->currentIndex() == 0) {
466    for (int i=0; i < sysDisks.count(); ++i) {
467      // Make sure to only add the drives to the comboDiskList
468      if ( sysDisks.at(i).at(0) == "DRIVE" && sysDisks.at(i).at(1) == disk ) {
469        //qDebug() << "Selected Disk Size: " +  sysDisks.at(i).at(2);
470        sysDisks.at(i).at(2).toInt(&ok);
471        if( ok )
472          return sysDisks.at(i).at(2).toInt(&ok) - safeBuf;
473        else
474          return -1;
475      }
476    }
477  } else {
478    // Check the selected partition
479    QString slice = comboPartition->currentText();
480    slice.truncate(slice.indexOf(":"));
481    for (int i=0; i < sysDisks.count(); ++i) {
482      // Make sure to only add the slices to the listDiskSlices
483      if ( sysDisks.at(i).at(0) == "SLICE" && slice == sysDisks.at(i).at(2)) {
484        //qDebug() << "Selected Slice Size: " +  sysDisks.at(i).at(3);
485        sysDisks.at(i).at(3).toInt(&ok);
486        if( ok )
487          return sysDisks.at(i).at(3).toInt(&ok) - safeBuf;
488        else
489          return -1;
490      }
491    }
492  }
493
494  return -1;
495}
496
497void wizardDisk::slotTreeDiskChanged()
498{
499   if ( ! treeMounts->currentItem() )
500     return;
501
502   pushRemoveMount->setEnabled(true);
503   pushAddMount->setEnabled(true);
504
505   if ( treeMounts->currentItem()->text(1) == "/boot" || treeMounts->currentItem()->text(1) == "/")
506     pushRemoveMount->setEnabled(false);
507
508   if ( lineFreeMB->text() == "0" )
509     pushAddMount->setEnabled(false);
510}
511
512void wizardDisk::slotResizeFS()
513{
514  if ( ! treeMounts->currentItem() )
515  return;
516
517  QString mnt = treeMounts->currentItem()->text(1);
518  bool ok;
519  int curSize, availSize, minSize; 
520  curSize =  treeMounts->currentItem()->text(2).toInt(&ok);
521  availSize = curSize + lineFreeMB->text().toInt(&ok);
522
523  minSize = 100;
524
525  // See if we need some other sanity check on sizes
526  if ( mnt == "SWAP" )
527    minSize = 256;
528  if ( mnt == "/" )
529    minSize = 2000;
530  if ( mnt == "/boot" )
531    minSize = 1000;
532
533  addingMount="";
534  rFS = new dialogFSSize();
535  rFS->programInit(QString(tr("Resizing") + " " + mnt), curSize, availSize, minSize);
536  rFS->setWindowModality(Qt::ApplicationModal);
537  connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
538  rFS->show();
539  rFS->raise();
540}
541
542void wizardDisk::slotRemoveFS()
543{
544  if ( ! treeMounts->currentItem() )
545  return;
546
547  int ret = QMessageBox::question(this, tr("Remove mount-point"),
548              tr("Are you sure you want to remove this mount point?"),
549              QMessageBox::Yes | QMessageBox::No,
550              QMessageBox::No);
551
552  if ( ret != QMessageBox::Yes )
553    return;
554 
555  QTreeWidgetItem *rmItem = treeMounts->currentItem();
556  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
557
558  delete rmItem;
559}
560
561void wizardDisk::slotAddFS()
562{
563  bool ok;
564  QString tmp;
565  QString nMount = QInputDialog::getText(this, tr("Enter mount-point"),
566                                          tr("Please enter the new mount-point:"), QLineEdit::Normal,
567                                          "/", &ok);
568  if (!ok || nMount.isEmpty())
569    return;
570
571  // Sanity checks
572  ////////////////////////////////////////
573  if ( nMount.indexOf("/") != 0 ) {
574      QMessageBox::critical(this, tr("Invalid Mount"),
575              tr("Mount point should start with '/'"),
576              QMessageBox::Ok,
577              QMessageBox::Ok);
578      return;
579  }
580  // End sanity checks
581  ////////////////////////////////////////
582
583  // Make sure this mount doesn't already exist
584  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
585  for ( int i = 0; i < mItems.size(); ++i) {
586    if ( mItems.at(i)->text(1) == nMount )
587      return;
588  }
589
590  new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << nMount );
591}
592
593void wizardDisk::slotSaveFSResize(int newSize)
594{
595
596  QString tmp, tmp2;
597  bool ok;
598  int oSize, availSize, tSize, newAvailSize;
599
600  // If adding a new mount point
601  if ( ! addingMount.isEmpty() ) {
602    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
603    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << addingMount << tmp2.setNum(newSize) << "UFS+SUJ" );
604    addingMount="";
605    availSize = lineFreeMB->text().toInt(&ok); 
606    newAvailSize = availSize - newSize;
607    lineFreeMB->setText(tmp.setNum(newAvailSize));
608    return;
609  } 
610
611  if ( ! treeMounts->currentItem() )
612    return;
613
614  // Just resizing an existing partition
615  oSize = treeMounts->currentItem()->text(2).toInt(&ok); 
616  treeMounts->currentItem()->setText(2, tmp.setNum(newSize));
617
618  // Set the available size
619  if ( oSize > newSize ) {
620    tSize = oSize - newSize;
621    availSize = lineFreeMB->text().toInt(&ok); 
622    newAvailSize = availSize + tSize;
623  } else {
624    tSize = newSize - oSize;
625    availSize = lineFreeMB->text().toInt(&ok); 
626    newAvailSize = availSize - tSize;
627  }
628  lineFreeMB->setText(tmp.setNum(newAvailSize));
629
630  // Check if we need to enable the add button
631  if ( newAvailSize >= 100 )
632    pushAddMount->setEnabled(true);
633  else
634    pushAddMount->setEnabled(false);
635}
636
637void wizardDisk::slotTreeMountsRightClick()
638{
639  if ( ! treeMounts->currentItem() )
640    return;
641
642  popup = new QMenu();
643  popup->setTitle(tr("Editing:") + " " + treeMounts->currentItem()->text(1));
644  popup->addSeparator();
645
646  // Create atime sub-menu
647  popupAT = popup->addMenu("atime");
648  popupAT->addAction( "on", this, SLOT(slotZATON()));
649  popupAT->addAction( "off", this, SLOT(slotZATOFF()));
650
651  // Create canmount sub-menu
652  popupCM = popup->addMenu("canmount");
653  popupCM->addAction( "on", this, SLOT(slotZCMON()));
654  popupCM->addAction( "off", this, SLOT(slotZCMOFF()));
655  popupCM->addAction( "noauto", this, SLOT(slotZCMNOAUTO()));
656
657  // Create Checksum sub-menu
658  popupCH = popup->addMenu("checksum");
659  popupCH->addAction( "on", this, SLOT(slotZChkON()));
660  popupCH->addAction( "off", this, SLOT(slotZChkOFF()));
661
662  // Create compression sub-menu
663  popupCmp = popup->addMenu("compression");
664  popupCmp->addAction( "off", this, SLOT(slotZCmpOFF()));
665  popupCmp->addAction( "on", this, SLOT(slotZCmpON()));
666  popupCmp->addAction( "lz4", this, SLOT(slotZCmpLZ4()));
667  popupCmp->addAction( "lzjb", this, SLOT(slotZCmpLZJB()));
668  popupCmp->addAction( "gzip", this, SLOT(slotZCmpGZIP()));
669  popupCmp->addAction( "zle", this, SLOT(slotZCmpZLE()));
670
671  // Create dedup sub-menu
672  // dedup is disabled for now, until such time as it is safe in all cases
673  //popupDD = popup->addMenu("dedup");
674  //popupDD->addAction( "off", this, SLOT(slotZDDOFF()));
675  //popupDD->addAction( "on", this, SLOT(slotZDDON()));
676  //popupDD->addAction( "verify", this, SLOT(slotZDDVERIFY()));
677
678  // Create exec sub-menu
679  popupNE = popup->addMenu("exec");
680  popupNE->addAction( "on", this, SLOT(slotZEXON()));
681  popupNE->addAction( "off", this, SLOT(slotZEXOFF()));
682
683  popup->exec( QCursor::pos() );
684
685}
686
687void wizardDisk::slotZCMNOAUTO()
688{
689  toggleZFSOpt(QString("canmount=noauto"));
690}
691
692void wizardDisk::slotZCMOFF()
693{
694  toggleZFSOpt(QString("canmount=off"));
695}
696
697void wizardDisk::slotZCMON()
698{
699  toggleZFSOpt(QString("canmount=on"));
700}
701
702void wizardDisk::slotZDDVERIFY()
703{
704  toggleZFSOpt(QString("dedup=verify"));
705}
706
707void wizardDisk::slotZDDON()
708{
709  toggleZFSOpt(QString("dedup=on"));
710}
711
712void wizardDisk::slotZDDOFF()
713{
714  toggleZFSOpt(QString("dedup=off"));
715}
716
717void wizardDisk::slotZCmpZLE()
718{
719  toggleZFSOpt(QString("compress=zle"));
720}
721
722void wizardDisk::slotZCmpGZIP()
723{
724  toggleZFSOpt(QString("compress=gzip"));
725}
726
727void wizardDisk::slotZCmpLZ4()
728{
729  toggleZFSOpt(QString("compress=lz4"));
730}
731
732void wizardDisk::slotZCmpLZJB()
733{
734  toggleZFSOpt(QString("compress=lzjb"));
735}
736
737void wizardDisk::slotZCmpOFF()
738{
739  toggleZFSOpt(QString("compress=off"));
740}
741
742void wizardDisk::slotZCmpON()
743{
744  toggleZFSOpt(QString("compress=on"));
745}
746
747void wizardDisk::slotZChkOFF()
748{
749  toggleZFSOpt(QString("checksum=off"));
750}
751
752void wizardDisk::slotZChkON()
753{
754  toggleZFSOpt(QString("checksum=on"));
755}
756
757void wizardDisk::slotZATON()
758{
759  toggleZFSOpt(QString("atime=on"));
760}
761
762void wizardDisk::slotSwapSize()
763{
764  bool ok;
765  QString tmp;
766  int size = QInputDialog::getInt(this, tr("Enter SWAP size"),
767                                  tr("Size (MB)"), swapsize, 0, 1000000, 1, &ok);
768  if ( ok )
769    swapsize = size;
770}
771
772void wizardDisk::slotZATOFF()
773{
774  toggleZFSOpt(QString("atime=off"));
775}
776
777void wizardDisk::slotZEXOFF()
778{
779  toggleZFSOpt(QString("exec=off"));
780}
781
782void wizardDisk::slotZEXON()
783{
784  toggleZFSOpt(QString("exec=on"));
785}
786
787// Toggle an option being on / off for ZFS
788void wizardDisk::toggleZFSOpt(QString option)
789{
790  if ( ! treeMounts->currentItem() )
791    return;
792
793  bool found = false;
794  QString optTag = option.section("=", 0, 0);
795  QString tmpTag;
796  QStringList newOpts;
797  QStringList curOpts = treeMounts->currentItem()->text(2).split("|");
798  for (int i=0; i < curOpts.count(); ++i) {
799    tmpTag=curOpts.at(i).section("=", 0, 0);
800    if ( optTag == tmpTag ) {
801      found = true;
802      // Only save option if setting to new value
803      if ( option != curOpts.at(i) )
804        newOpts << option;
805    } else {
806      if ( !curOpts.at(i).isEmpty() )
807        newOpts << curOpts.at(i);
808    }
809  }
810
811  if ( ! found )
812      newOpts << option;
813
814  QString optString;
815  if ( newOpts.count() <= 1)
816    optString = newOpts.join("");
817  else
818    optString = newOpts.join("|");
819
820  treeMounts->currentItem()->setText(2, optString);
821  treeMounts->currentItem()->setToolTip(2, optString);
822}
823
824void wizardDisk::generateCustomDiskLayout()
825{
826  QString targetType, tmp;
827  int targetLoc;
828  QString targetDisk, targetSlice, tmpPass, fsType, target;
829
830  // Clear out the original disk layout
831  sysFinalDiskLayout.clear();
832  QStringList fileSystem;
833  qDebug() << "Generating custom disk layout";
834       
835  if ( comboPartition->currentIndex() == 0) {
836    targetType = "DRIVE";
837    targetSlice = "ALL";
838    targetDisk = comboDisk->currentText();
839    targetDisk.truncate(targetDisk.indexOf(" -"));
840    target = targetDisk;
841    targetLoc = 1;
842  } else {
843    targetType = "SLICE";
844    targetDisk = comboDisk->currentText();
845    targetDisk.truncate(targetDisk.indexOf(" -"));
846    targetSlice = comboPartition->currentText();
847    targetSlice.truncate(targetSlice.indexOf(":"));
848    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
849    target = targetDisk + targetSlice;
850    targetLoc = 2;
851  }
852
853  // Start building the ZFS file-systems
854  QStringList zMnts;
855  fsType = "ZFS";
856  int zpoolSize = getDiskSliceSize();
857
858  // Deduct any swap space
859  zpoolSize = zpoolSize - swapsize;
860
861  // Get the zfs mounts
862  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
863  for ( int i = 0; i < mItems.size(); ++i) {
864    if ( mItems.at(i)->text(2).isEmpty() )
865      zMnts << mItems.at(i)->text(1);
866    else
867      zMnts << mItems.at(i)->text(1) + "(" + mItems.at(i)->text(2) + ")";
868  }
869
870  // If we have any additional ZFS mirror / raidz devices set it up now
871  QString zOpts, zDisk;
872  if ( groupZFSOpts->isChecked() && comboPartition->currentIndex() == 0 ) {
873     zOpts = comboZFSMode->currentText() + ":";
874     for ( int i = 0; i < listZFSDisks->count(); ++i )
875        if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
876           zDisk = listZFSDisks->item(i)->text();
877           zDisk.truncate(zDisk.indexOf(" -"));
878           zOpts = zOpts + " " + zDisk;
879        }
880  }
881
882  // Save the final disk layout
883  fileSystem.clear();
884  fileSystem << targetDisk << targetSlice << zMnts.join(",") << fsType << tmp.setNum(zpoolSize) << zOpts << tmpPass;
885  sysFinalDiskLayout << fileSystem;
886
887  fileSystem.clear();
888  fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(swapsize) << "" << "";
889  sysFinalDiskLayout << fileSystem;
890
891  qDebug() <<"AutoLayout:" << sysFinalDiskLayout;
892}
893
894void wizardDisk::generateConfirmationText()
895{
896  // If running in expert mode, we just create a simple config / confirmation
897  if ( radioExpert->isChecked() ) {
898    QStringList filesystem;
899    filesystem << "MANUAL" << "/mnt" ;
900    sysFinalDiskLayout << filesystem;
901    textConfirmation->setText(tr("Installing to file-system mounted at /mnt"));
902    return;
903  }
904
905  QList<QStringList> copyList;
906  QStringList summaryList;
907  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
908  int disk = 0;
909
910  // Copy over the list to a new variable we can mangle without modifying the original
911  copyList = sysFinalDiskLayout;
912
913  // Start our summary
914  summaryList << "";
915  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
916
917  while ( ! copyList.empty() )
918  {
919    workingDisk = copyList.at(0).at(0);
920    workingSlice = copyList.at(0).at(1);
921    tmpSlice = workingSlice;
922
923    // Check if this is an install to "Unused Space"
924    for (int z=0; z < sysDisks.count(); ++z)
925      if ( sysDisks.at(z).at(0) == "SLICE" \
926        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
927        && sysDisks.at(z).at(4) == "Unused Space" )
928          tmpSlice = "free";
929
930    // Check for any mirror for this device
931    for (int i=0; i < copyList.count(); ++i) {
932       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
933       {
934         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
935         copyList.removeAt(i);
936         break;
937       }
938    }
939
940    // If after doing the mirror, our list is empty, break out
941    if ( copyList.empty() )
942      break;
943   
944    // If there is a dedicated /boot partition, need to list that first, see what is found
945    for (int i=0; i < copyList.count(); ++i) {
946      QStringList mounts = copyList.at(i).at(2).split(",");
947      for (int z = 0; z < mounts.size(); ++z) {
948        if ( copyList.at(i).at(0) == workingDisk \
949          && copyList.at(i).at(1) == workingSlice \
950          && mounts.at(z) == "/boot" )
951                startPart="/boot";
952      }
953    }
954
955    // If no dedicated /boot partition, then lets list "/" first
956    if(startPart.isEmpty())
957        startPart="/";
958
959    // Start by looking for the root partition
960    for (int i=0; i < copyList.count(); ++i) {
961      QStringList mounts = copyList.at(i).at(2).split(",");
962      for (int z = 0; z < mounts.size(); ++z) {
963        if ( copyList.at(i).at(0) == workingDisk \
964          && copyList.at(i).at(1) == workingSlice \
965          && mounts.at(z) == startPart ) {
966
967          // Check if we have any extra arguments to throw on the end
968          XtraTmp="";
969          if ( ! copyList.at(i).at(5).isEmpty() )
970            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
971
972          // Write the user summary
973          summaryList << "";
974          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
975          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
976          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
977
978          if ( copyList.at(i).at(3) == "ZFS" ) {
979            QStringList zDS = copyList.at(i).at(2).split(",/");
980            QString zTMP;
981            for (int ds = 0; ds < zDS.size(); ++ds) {
982              if ( zDS.at(ds) != "/" )
983                zDS.replace(ds, "/" + zDS.at(ds));
984              if ( zDS.at(ds).indexOf("(") != -1 ) {
985                zTMP = zDS.at(ds);
986                zTMP.replace("(", " (");
987                zDS.replace(ds, zTMP );
988              }
989            }
990            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
991          } else {
992            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
993          }
994          if ( ! XtraTmp.isEmpty() ) {
995            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
996          }
997
998          // Done with this item, remove it now
999          copyList.removeAt(i);
1000          break;
1001        }
1002      }
1003    }
1004
1005
1006    // Now look for SWAP
1007    for (int i=0; i < copyList.count(); ++i) {
1008      if ( copyList.at(i).at(0) == workingDisk \
1009        && copyList.at(i).at(1) == workingSlice \
1010        && copyList.at(i).at(2) == "SWAP" ) {
1011
1012        // Write the user summary
1013        summaryList << "";
1014        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1015        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1016        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1017
1018        // Done with this item, remove it now
1019        copyList.removeAt(i);
1020        break;
1021      }
1022    }
1023
1024 
1025    // Now look for any other partitions
1026    int count = copyList.count();
1027    for (int i=0; i < count; ++i) {
1028      if ( copyList.at(i).at(0) == workingDisk \
1029        && copyList.at(i).at(1) == workingSlice ) {
1030
1031        // Check if we have any extra arguments to throw on the end
1032        XtraTmp="";
1033        if ( ! copyList.at(i).at(5).isEmpty() )
1034          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1035
1036        // If we are working on the last partition, set the size to 0 to use remaining disk
1037        if ( i == (count - 1) ) 
1038                sliceSize = "0";
1039        else
1040                sliceSize=copyList.at(i).at(4);
1041
1042        // Write the user summary
1043        summaryList << "";
1044        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1045        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1046        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1047        summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1048        if ( ! XtraTmp.isEmpty() ) {
1049          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1050        }
1051
1052        // Done with this item, remove it now
1053        copyList.removeAt(i);
1054        i--;
1055        count--;
1056      }
1057    }
1058
1059    // Increment our disk counter
1060    disk++;
1061  }
1062
1063  textConfirmation->setText(summaryList.join("<br>"));
1064}
1065
1066void wizardDisk::slotTerminal()
1067{
1068  system("xterm &");
1069}
1070
1071void wizardDisk::setRestoreMode()
1072{
1073  restoreMode=true;
1074}
Note: See TracBrowser for help on using the repository browser.