source: src-qt4/pc-installgui/wizardDisk.cpp @ 4fb8829

9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 4fb8829 was 4fb8829, checked in by Kris Moore <kris@…>, 6 months ago

Add option to enable installing to a SSD, which will disable SWAP / atime

Trac Ticket: https://trac.pcbsd.org/ticket/740

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