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

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

Remove the swap-on-zfs by default in the installer

  • Property mode set to 100644
File size: 39.1 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
22  populateDiskInfo();
23
24  //connect(pushClose, SIGNAL(clicked()), this, SLOT(slotClose()));
25  connect(pushSizeMount, SIGNAL(clicked()), this, SLOT(slotResizeFS()));
26  connect(pushRemoveMount, SIGNAL(clicked()), this, SLOT(slotRemoveFS()));
27  connect(pushAddMount, SIGNAL(clicked()), this, SLOT(slotAddFS()));
28  connect(this,SIGNAL(currentIdChanged(int)),this,SLOT(slotCheckComplete()));
29  connect(lineEncPW,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckComplete()));
30  connect(lineEncPW2,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckComplete()));
31  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
32  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotChangedDisk()));
33  connect(comboPartition,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
34  connect(groupEncryption,SIGNAL(toggled(bool)),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  // Get the system arch type
48  QProcess m;
49  m.start(QString("uname"), QStringList() << "-m");
50  while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
51     m.waitForFinished(200);
52     QCoreApplication::processEvents();
53  }
54  // Get output
55  QString Arch = m.readLine().simplified();
56
57  // Set the suggested FileSystem
58  systemMemory = Scripts::Backend::systemMemory();
59  if ( systemMemory > 2028 && Arch != "i386" )
60    radioZFS->setChecked(true);
61  else
62    radioUFS->setChecked(true);
63 
64  // If less than 768 MB, disable ZFS completely
65  if ( systemMemory < 768 )
66    radioZFS->setEnabled(false);
67
68}
69
70void wizardDisk::populateDiskInfo()
71{
72  qDebug() << "Loading Disk Info";
73  sysDisks = Scripts::Backend::hardDrives();
74
75  // load drives
76  comboDisk->clear();
77  for (int i=0; i < sysDisks.count(); ++i) {
78    // Make sure to only add the drives to the comboDisk
79    if ( sysDisks.at(i).at(0) == "DRIVE" )
80      comboDisk->addItem(sysDisks.at(i).at(1) + " - " + sysDisks.at(i).at(2) + "MB " + sysDisks.at(i).at(3));
81  }
82
83  // Reload the slice list box
84  slotChangedDisk();
85}
86
87void wizardDisk::slotChangedDisk()
88{
89  QString ptag;
90
91  if ( comboDisk->currentText().isEmpty())
92    return;
93
94  comboPartition->clear();
95  comboPartition->addItem(tr("Use entire disk"));
96       
97  QString disk = comboDisk->currentText();
98  disk.truncate(disk.indexOf(" -"));
99  for (int i=0; i < sysDisks.count(); ++i) {
100    // Make sure to only add the slices to the listDiskSlices
101    if ( sysDisks.at(i).at(0) == "SLICE" && disk == sysDisks.at(i).at(1) && sysDisks.at(i).at(4) != "Unused Space") {
102      ptag = sysDisks.at(i).at(4).section(",", 0, 0);
103      ptag = ptag.section("/", 0, 0);
104      ptag.truncate(15);
105      if ( ptag.indexOf(")") == -1 )
106        ptag += ")";
107      comboPartition->addItem(sysDisks.at(i).at(2) + ": " +  sysDisks.at(i).at(3) + "MB " + ptag );
108    }
109  }
110
111}
112
113void wizardDisk::slotClose()
114{
115  close();
116}
117
118void wizardDisk::accept()
119{
120  bool useGPT = false;
121  if (comboPartition->currentIndex() == 0 )
122    useGPT = checkGPT->isChecked();
123
124  // When doing advanced ZFS setups, make sure to use GPT
125  if ( radioAdvanced->isChecked() && groupZFSOpts->isChecked() )
126    useGPT = true;
127
128  if ( radioExpert->isChecked() )
129    emit saved(sysFinalDiskLayout, false, false);
130  else
131    emit saved(sysFinalDiskLayout, checkMBR->isChecked(), useGPT);
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       if (radioAdvanced->isChecked())
144         checkGPT->setVisible(true);
145        break;
146     case Page_BasicDisk:
147       if (radioBasic->isChecked())
148         return Page_BasicEnc;
149       return Page_FS;
150       break;
151     case Page_FS:
152       if (radioZFS->isChecked() ) {
153         // Only enable ZFS mirror / raidz when doing full disk install
154         if (comboPartition->currentIndex() != 0 )
155           groupZFSOpts->setEnabled(false);
156         else
157           groupZFSOpts->setEnabled(true);
158         return Page_ZFS;
159       }
160       return Page_Mounts;
161       break;
162     case Page_ZFS:
163       // If we are using ZFS raidz / mirror, skip encryption
164       if ( groupZFSOpts->isChecked() )
165          return Page_Mounts;
166       return Page_BasicEnc;
167       break;
168     case Page_BasicEnc:
169       if (radioBasic->isChecked())
170         return Page_Confirmation;
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  // Generate suggested disk layout and show disk tree
189  if ( prevID == Page_FS && currentId() == Page_Mounts) {
190    generateDiskLayout();
191    populateDiskTree();
192  }
193
194  // Generate suggested disk layout and show disk tree
195  if ( prevID == Page_ZFS && currentId() == Page_Mounts) {
196    generateDiskLayout();
197    populateDiskTree();
198  } 
199
200  // Generate suggested disk layout and show disk tree
201  if ( prevID == Page_BasicEnc && currentId() == Page_Mounts) {
202    generateDiskLayout();
203    populateDiskTree();
204  }
205
206  // Show the other disks available
207  if ( prevID == Page_FS && currentId() == Page_ZFS)
208     populateZFSDisks();
209
210  // Basic mode, generate a disk layout and show summary
211  if ( prevID == Page_BasicEnc && currentId() == Page_Confirmation) {
212    generateDiskLayout();
213    generateConfirmationText();
214  }
215
216  // Create the final disk layout from user options
217  if ( prevID == Page_Mounts && currentId() == Page_Confirmation) {
218    generateCustomDiskLayout();
219    generateConfirmationText();
220  }
221
222  // Create the final disk layout from user options
223  if ( prevID == Page_Expert && currentId() == Page_Confirmation) {
224    generateConfirmationText();
225  }
226 
227 
228  // Reset the prevID
229  prevID = currentId();
230
231  switch (currentId()) {
232     case Page_Intro:
233         button(QWizard::NextButton)->setEnabled(true);
234         return true;
235     case Page_BasicDisk:
236         if ( comboPartition->currentIndex() == 0  && radioAdvanced->isChecked())
237           checkGPT->setVisible(true);
238         else
239           checkGPT->setVisible(false);
240
241         // Comment out this disk space check
242         // We will warn the user right before install if the selected
243         // Disk / partition looks too small
244         //if ( ! checkDiskSpace() ) {
245         //  button(QWizard::NextButton)->setEnabled(false);
246         //  return false;
247         //}
248       
249         // if we get this far, all the fields are filled in
250         button(QWizard::NextButton)->setEnabled(true);
251         return true;
252     case Page_BasicEnc:
253         if ( groupEncryption->isChecked() && (lineEncPW->text() != lineEncPW2->text() || lineEncPW->text().isEmpty()) ) {
254           button(QWizard::NextButton)->setEnabled(false);
255           return false;
256         }
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() < 10000 )
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, mntsize;
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 doing ZFS advanced setup, disable encryption
368  if ( groupZFSOpts->isChecked() )
369    groupEncryption->setChecked(false);
370
371  if ( comboPartition->currentIndex() == 0) {
372    targetType = "DRIVE";
373    targetSlice = "ALL";
374    targetDisk = comboDisk->currentText();
375    targetDisk.truncate(targetDisk.indexOf(" -"));
376    target = targetDisk;
377    targetLoc = 1;
378  } else {
379    targetType = "SLICE";
380    targetDisk = comboDisk->currentText();
381    targetDisk.truncate(targetDisk.indexOf(" -"));
382    targetSlice = comboPartition->currentText();
383    targetSlice.truncate(targetSlice.indexOf(":"));
384    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
385    target = targetDisk + targetSlice;
386    targetLoc = 2;
387  }
388 
389
390  totalSize = getDiskSliceSize();
391  if ( totalSize != -1 )
392  {
393     // We got a valid size for this disk / slice, lets generate the layout now
394     mntsize = 2048;
395
396     // This is set automatically if in basic mode
397     if ( radioUFS->isChecked() ) {
398
399       fsType="UFS+SUJ";
400
401       fileSystem << targetDisk << targetSlice << "/" << fsType << tmp.setNum(mntsize) << "" << "";
402       totalSize = totalSize - mntsize;
403       //qDebug() << "Auto-Gen FS:" <<  fileSystem;
404       sysFinalDiskLayout << fileSystem;
405       fileSystem.clear();
406     
407
408       // Figure out the swap size, try for 2xPhysMem first, fallback to 256 if not enough space
409       mntsize = systemMemory * 2;
410       if ( totalSize - mntsize < 3000 )
411          mntsize = 256;
412
413       // Cap the swap size to 2GB
414       if ( mntsize > 2000 )
415          mntsize = 2000;
416
417       fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(mntsize) << "" << "";
418       totalSize = totalSize - mntsize;
419       //qDebug() << "Auto-Gen FS:" <<  fileSystem;
420       sysFinalDiskLayout << fileSystem;
421       fileSystem.clear();
422
423       // If less than 3GB, skip /var and leave on /
424       if ( totalSize > 3000 ) {
425         // Figure out the default size for /var if we are on FreeBSD / PC-BSD
426         mntsize = 2048;
427         fileSystem << targetDisk << targetSlice << "/var" << fsType << tmp.setNum(mntsize) << "" << "";
428         totalSize = totalSize - mntsize;
429         //qDebug() << "Auto-Gen FS:" <<  fileSystem;
430         sysFinalDiskLayout << fileSystem;
431         fileSystem.clear();
432       }
433
434       // See if using encryption for this partition
435       if ( groupEncryption->isChecked() ) {
436         fsType+= ".eli";
437         tmpPass=lineEncPW->text();
438       }
439
440       // Now use the rest of the disk / slice for /usr
441       fileSystem << targetDisk << targetSlice << "/usr" << fsType << tmp.setNum(totalSize) << "" << tmpPass;
442       sysFinalDiskLayout << fileSystem;
443       fileSystem.clear();
444
445     } else {
446        // Using ZFS
447
448       // If encryption is enabled, we need a ufs /boot partition
449       if ( groupEncryption->isChecked() ) {
450         totalSize = totalSize - 2048;
451         fileSystem << targetDisk << targetSlice << "/boot" << "UFS+SUJ" << tmp.setNum(2048) << "" << "";
452         sysFinalDiskLayout << fileSystem;
453         fileSystem.clear();
454       }
455
456       // See if using encryption for this partition
457       if ( groupEncryption->isChecked() ) {
458         fsType= "ZFS.eli";
459         tmpPass=lineEncPW->text();
460       } else {
461         fsType= "ZFS";
462       }
463
464       // This lets the user do nifty stuff like a mirror/raid post-install with a single zpool command
465       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;
466       //qDebug() << "Auto-Gen FS:" <<  fileSystem;
467       sysFinalDiskLayout << fileSystem;
468       fileSystem.clear();
469     }
470  }
471 
472  qDebug() << "AutoLayout:" <<  sysFinalDiskLayout;
473}
474
475void wizardDisk::populateDiskTree()
476{
477  QStringList tmpList, zMnts;
478  QString tmp, opts;
479  int usedSpace = 0;
480  bool ok;
481
482  // If doing ZFS advanced setup, disable encryption
483  if ( groupZFSOpts->isChecked() )
484    groupEncryption->setChecked(false);
485
486  treeMounts->clear();
487  if (radioUFS->isChecked()) {
488    treeMounts->setHeaderLabels(QStringList() << "ID" << tr("Mount") << tr("Size") << tr("Type") << "Pass" );
489    treeMounts->header()->setSectionHidden(4, true);
490    treeMounts->setColumnCount(5);
491    labelFreeSpace->setVisible(true);
492    lineFreeMB->setVisible(true);
493    pushSizeMount->setVisible(true);
494  } else {
495    treeMounts->setHeaderLabels(QStringList() << "ID" << tr("ZFS Mounts") << tr("ZFS Options") );
496    treeMounts->setColumnCount(3);
497    labelFreeSpace->setVisible(false);
498    lineFreeMB->setVisible(false);
499    pushSizeMount->setVisible(false);
500  }
501
502  treeMounts->header()->setSectionHidden(0, true);
503  treeMounts->header()->setDefaultSectionSize(150);
504
505  if (radioUFS->isChecked()) {
506    for (int i=0; i < sysFinalDiskLayout.count(); ++i) {
507      // Start adding the disk items to our tree widget
508      new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(i) << sysFinalDiskLayout.at(i).at(2) << sysFinalDiskLayout.at(i).at(4) << sysFinalDiskLayout.at(i).at(3) << sysFinalDiskLayout.at(i).at(6));
509      usedSpace = usedSpace +  sysFinalDiskLayout.at(i).at(4).toInt(&ok);
510    }
511   
512    // Now lets show how much is free to play with
513    lineFreeMB->setText(QString().setNum(getDiskSliceSize() - usedSpace));
514
515  } else {
516    // Show ZFS stuff
517
518    // If using encryption, skip the /boot UFS partition
519    if ( groupEncryption->isChecked())
520      zMnts = sysFinalDiskLayout.at(1).at(2).split(",");
521    else
522      zMnts = sysFinalDiskLayout.at(0).at(2).split(",");
523
524    // Now loop through ZFS mounts
525    for (int i=0; i < zMnts.count(); ++i) {
526      tmpList.clear();
527      opts = zMnts.at(i).section("(", 1, 1).section(")", 0, 0); 
528      tmpList << tmp.setNum(i+1) << zMnts.at(i).split("(").at(0) << opts ;
529      QTreeWidgetItem *mItem = new QTreeWidgetItem(treeMounts, tmpList);
530      mItem->setToolTip(2, opts);
531    }
532  }
533
534  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
535  slotTreeDiskChanged(); 
536
537}
538
539int wizardDisk::getDiskSliceSize()
540{
541  bool ok;
542  QString disk = comboDisk->currentText();
543  disk.truncate(disk.indexOf(" -"));
544
545  int safeBuf = 10;
546
547  // Check the full disk
548  if ( comboPartition->currentIndex() == 0) {
549    for (int i=0; i < sysDisks.count(); ++i) {
550      // Make sure to only add the drives to the comboDiskList
551      if ( sysDisks.at(i).at(0) == "DRIVE" && sysDisks.at(i).at(1) == disk ) {
552        //qDebug() << "Selected Disk Size: " +  sysDisks.at(i).at(2);
553        sysDisks.at(i).at(2).toInt(&ok);
554        if( ok )
555          return sysDisks.at(i).at(2).toInt(&ok) - safeBuf;
556        else
557          return -1;
558      }
559    }
560  } else {
561    // Check the selected partition
562    QString slice = comboPartition->currentText();
563    slice.truncate(slice.indexOf(":"));
564    for (int i=0; i < sysDisks.count(); ++i) {
565      // Make sure to only add the slices to the listDiskSlices
566      if ( sysDisks.at(i).at(0) == "SLICE" && slice == sysDisks.at(i).at(2)) {
567        //qDebug() << "Selected Slice Size: " +  sysDisks.at(i).at(3);
568        sysDisks.at(i).at(3).toInt(&ok);
569        if( ok )
570          return sysDisks.at(i).at(3).toInt(&ok) - safeBuf;
571        else
572          return -1;
573      }
574    }
575  }
576
577  return -1;
578}
579
580void wizardDisk::slotTreeDiskChanged()
581{
582   if ( ! treeMounts->currentItem() )
583     return;
584
585   pushRemoveMount->setEnabled(true);
586   pushAddMount->setEnabled(true);
587   pushSizeMount->setEnabled(true);
588
589   if ( treeMounts->currentItem()->text(1) == "/boot" || treeMounts->currentItem()->text(1) == "/")
590     pushRemoveMount->setEnabled(false);
591
592   if ( lineFreeMB->text() == "0" )
593     pushAddMount->setEnabled(false);
594}
595
596void wizardDisk::slotResizeFS()
597{
598  if ( ! treeMounts->currentItem() )
599  return;
600
601  QString mnt = treeMounts->currentItem()->text(1);
602  bool ok;
603  int curSize, availSize, minSize; 
604  curSize =  treeMounts->currentItem()->text(2).toInt(&ok);
605  availSize = curSize + lineFreeMB->text().toInt(&ok);
606
607  minSize = 100;
608
609  // See if we need some other sanity check on sizes
610  if ( mnt == "SWAP" )
611    minSize = 256;
612  if ( mnt == "/" )
613    minSize = 2000;
614  if ( mnt == "/boot" )
615    minSize = 1000;
616
617  addingMount="";
618  rFS = new dialogFSSize();
619  rFS->programInit(QString(tr("Resizing") + " " + mnt), curSize, availSize, minSize);
620  rFS->setWindowModality(Qt::ApplicationModal);
621  connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
622  rFS->show();
623  rFS->raise();
624}
625
626void wizardDisk::slotRemoveFS()
627{
628  if ( ! treeMounts->currentItem() )
629  return;
630
631  int ret = QMessageBox::question(this, tr("Remove mount-point"),
632              tr("Are you sure you want to remove this mount point?"),
633              QMessageBox::Yes | QMessageBox::No,
634              QMessageBox::No);
635
636  if ( ret != QMessageBox::Yes )
637    return;
638 
639  QTreeWidgetItem *rmItem = treeMounts->currentItem();
640  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
641
642  // If editing UFS, lets adjust the available size
643  if (radioUFS->isChecked()) {
644    bool ok;
645    QString tmp;
646    int fSize = rmItem->text(2).toInt(&ok);
647    int newAvailSize = lineFreeMB->text().toInt(&ok) + fSize; 
648    lineFreeMB->setText(tmp.setNum(newAvailSize));
649  }
650
651  delete rmItem;
652}
653
654void wizardDisk::slotAddFS()
655{
656  bool ok;
657  QString tmp;
658  QString nMount = QInputDialog::getText(this, tr("Enter mount-point"),
659                                          tr("Please enter the new mount-point:"), QLineEdit::Normal,
660                                          "/", &ok);
661  if (!ok || nMount.isEmpty())
662    return;
663
664  // Sanity checks
665  ////////////////////////////////////////
666  if (nMount == "/boot" && radioZFS->isChecked() && groupEncryption->isChecked() ) {
667      QMessageBox::critical(this, tr("Invalid Mount"),
668              tr("Cannot create /boot dataset on ZFS with encryption enabled!"),
669              QMessageBox::Ok,
670              QMessageBox::Ok);
671      return;
672  }
673  if ( nMount.indexOf("/") != 0 ) {
674      QMessageBox::critical(this, tr("Invalid Mount"),
675              tr("Mount point should start with '/'"),
676              QMessageBox::Ok,
677              QMessageBox::Ok);
678      return;
679  }
680  // End sanity checks
681  ////////////////////////////////////////
682
683  // Make sure this mount doesn't already exist
684  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
685  for ( int i = 0; i < mItems.size(); ++i) {
686    if ( mItems.at(i)->text(1) == nMount )
687      return;
688  }
689
690  if  ( radioUFS->isChecked() ) {
691    // Doing UFS mount, lets get a size from the user
692    addingMount = nMount;
693    int availSize = lineFreeMB->text().toInt(&ok); 
694    rFS = new dialogFSSize();
695    rFS->programInit(QString(tr("Specify a size for the mount") + " " + addingMount), 100, availSize, 100);
696    rFS->setWindowModality(Qt::ApplicationModal);
697    connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
698    rFS->show();
699    rFS->raise();
700  } else {
701    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << nMount );
702  }
703}
704
705void wizardDisk::slotSaveFSResize(int newSize)
706{
707
708  QString tmp, tmp2;
709  bool ok;
710  int oSize, availSize, tSize, newAvailSize;
711
712  // If adding a new mount point
713  if ( ! addingMount.isEmpty() ) {
714    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
715    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << addingMount << tmp2.setNum(newSize) << "UFS+SUJ" );
716    addingMount="";
717    availSize = lineFreeMB->text().toInt(&ok); 
718    newAvailSize = availSize - newSize;
719    lineFreeMB->setText(tmp.setNum(newAvailSize));
720    return;
721  } 
722
723  if ( ! treeMounts->currentItem() )
724    return;
725
726  // Just resizing an existing partition
727  oSize = treeMounts->currentItem()->text(2).toInt(&ok); 
728  treeMounts->currentItem()->setText(2, tmp.setNum(newSize));
729
730  // Set the available size
731  if ( oSize > newSize ) {
732    tSize = oSize - newSize;
733    availSize = lineFreeMB->text().toInt(&ok); 
734    newAvailSize = availSize + tSize;
735  } else {
736    tSize = newSize - oSize;
737    availSize = lineFreeMB->text().toInt(&ok); 
738    newAvailSize = availSize - tSize;
739  }
740  lineFreeMB->setText(tmp.setNum(newAvailSize));
741
742  // Check if we need to enable the add button
743  if ( newAvailSize >= 100 )
744    pushAddMount->setEnabled(true);
745  else
746    pushAddMount->setEnabled(false);
747}
748
749void wizardDisk::slotTreeMountsRightClick()
750{
751  if ( ! treeMounts->currentItem() )
752    return;
753
754  popup = new QMenu();
755  popup->setTitle(tr("Editing:") + " " + treeMounts->currentItem()->text(1));
756  popup->addSeparator();
757
758  if  ( radioUFS->isChecked() ) {
759    // No options to change for / or /boot
760    if ( treeMounts->currentItem()->text(1) == "/" )
761      return;
762    if ( treeMounts->currentItem()->text(1) == "/boot" )
763      return;
764
765    if ( treeMounts->currentItem()->text(3).indexOf(".eli") != -1 )
766      popup->addAction( tr("Disable Encryption"), this, SLOT(slotUEnc()));
767    else
768      popup->addAction( tr("Enable Encryption"), this, SLOT(slotUEnc()));
769
770    // End of UFS options
771  } else {
772    // No options to change for /swap
773    if ( treeMounts->currentItem()->text(1) == "/swap" ) {
774      popup->addAction( "Change size", this, SLOT(slotZSwapSize()));
775      popup->exec( QCursor::pos() );
776      return;
777    }
778
779    // Create atime sub-menu
780    popupAT = popup->addMenu("atime");
781    popupAT->addAction( "on", this, SLOT(slotZATON()));
782    popupAT->addAction( "off", this, SLOT(slotZATOFF()));
783
784    // Create canmount sub-menu
785    popupCM = popup->addMenu("canmount");
786    popupCM->addAction( "on", this, SLOT(slotZCMON()));
787    popupCM->addAction( "off", this, SLOT(slotZCMOFF()));
788    popupCM->addAction( "noauto", this, SLOT(slotZCMNOAUTO()));
789
790    // Create Checksum sub-menu
791    popupCH = popup->addMenu("checksum");
792    popupCH->addAction( "on", this, SLOT(slotZChkON()));
793    popupCH->addAction( "off", this, SLOT(slotZChkOFF()));
794
795    // Create compression sub-menu
796    popupCmp = popup->addMenu("compression");
797    popupCmp->addAction( "off", this, SLOT(slotZCmpOFF()));
798    popupCmp->addAction( "lzjb", this, SLOT(slotZCmpLZJB()));
799    popupCmp->addAction( "gzip", this, SLOT(slotZCmpGZIP()));
800    popupCmp->addAction( "zle", this, SLOT(slotZCmpZLE()));
801
802    // Create dedup sub-menu
803    // dedup is disabled for now, until such time as it is safe in all cases
804    //popupDD = popup->addMenu("dedup");
805    //popupDD->addAction( "off", this, SLOT(slotZDDOFF()));
806    //popupDD->addAction( "on", this, SLOT(slotZDDON()));
807    //popupDD->addAction( "verify", this, SLOT(slotZDDVERIFY()));
808
809    // Create exec sub-menu
810    popupNE = popup->addMenu("exec");
811    popupNE->addAction( "on", this, SLOT(slotZEXON()));
812    popupNE->addAction( "off", this, SLOT(slotZEXOFF()));
813
814  }
815  popup->exec( QCursor::pos() );
816
817}
818
819void wizardDisk::slotZCMNOAUTO()
820{
821  toggleZFSOpt(QString("canmount=noauto"));
822}
823
824void wizardDisk::slotZCMOFF()
825{
826  toggleZFSOpt(QString("canmount=off"));
827}
828
829void wizardDisk::slotZCMON()
830{
831  toggleZFSOpt(QString("canmount=on"));
832}
833
834void wizardDisk::slotZDDVERIFY()
835{
836  toggleZFSOpt(QString("dedup=verify"));
837}
838
839void wizardDisk::slotZDDON()
840{
841  toggleZFSOpt(QString("dedup=on"));
842}
843
844void wizardDisk::slotZDDOFF()
845{
846  toggleZFSOpt(QString("dedup=off"));
847}
848
849void wizardDisk::slotZCmpZLE()
850{
851  toggleZFSOpt(QString("compress=zle"));
852}
853
854void wizardDisk::slotZCmpGZIP()
855{
856  toggleZFSOpt(QString("compress=gzip"));
857}
858
859void wizardDisk::slotZCmpLZJB()
860{
861  toggleZFSOpt(QString("compress=lzjb"));
862}
863
864void wizardDisk::slotZCmpOFF()
865{
866  toggleZFSOpt(QString("compress=off"));
867}
868
869void wizardDisk::slotZChkOFF()
870{
871  toggleZFSOpt(QString("checksum=off"));
872}
873
874void wizardDisk::slotZChkON()
875{
876  toggleZFSOpt(QString("checksum=on"));
877}
878
879void wizardDisk::slotZATON()
880{
881  toggleZFSOpt(QString("atime=on"));
882}
883
884void wizardDisk::slotZSwapSize()
885{
886  bool ok;
887  QString tmp;
888  int size = QInputDialog::getInt(this, tr("Enter SWAP size"),
889                                  tr("Size (MB)"), 2048, 0, 1000000, 1, &ok);
890  if ( ok )
891  {
892    tmp.setNum(size);
893    QString optString = "volsize=" + tmp + "M|org.freebsd:swap=on|checksum=off";
894    treeMounts->currentItem()->setText(2, optString);
895    treeMounts->currentItem()->setToolTip(2, optString);
896  }
897}
898
899void wizardDisk::slotZATOFF()
900{
901  toggleZFSOpt(QString("atime=off"));
902}
903
904void wizardDisk::slotZEXOFF()
905{
906  toggleZFSOpt(QString("exec=off"));
907}
908
909void wizardDisk::slotZEXON()
910{
911  toggleZFSOpt(QString("exec=on"));
912}
913
914// Toggle an option being on / off for ZFS
915void wizardDisk::toggleZFSOpt(QString option)
916{
917  if ( ! treeMounts->currentItem() )
918    return;
919
920  bool found = false;
921  QString optTag = option.section("=", 0, 0);
922  QString tmpTag;
923  QStringList newOpts;
924  QStringList curOpts = treeMounts->currentItem()->text(2).split("|");
925  for (int i=0; i < curOpts.count(); ++i) {
926    tmpTag=curOpts.at(i).section("=", 0, 0);
927    if ( optTag == tmpTag ) {
928      found = true;
929      // Only save option if setting to new value
930      if ( option != curOpts.at(i) )
931        newOpts << option;
932    } else {
933      if ( !curOpts.at(i).isEmpty() )
934        newOpts << curOpts.at(i);
935    }
936  }
937
938  if ( ! found )
939      newOpts << option;
940
941  QString optString;
942  if ( newOpts.count() <= 1)
943    optString = newOpts.join("");
944  else
945    optString = newOpts.join("|");
946
947  treeMounts->currentItem()->setText(2, optString);
948  treeMounts->currentItem()->setToolTip(2, optString);
949}
950
951void wizardDisk::generateCustomDiskLayout()
952{
953  QString targetType, tmp;
954  int targetLoc;
955  QString targetDisk, targetSlice, tmpPass, fsType, target;
956
957  // If doing ZFS advanced setup, disable encryption
958  if ( groupZFSOpts->isChecked() )
959    groupEncryption->setChecked(false);
960       
961  // Clear out the original disk layout
962  sysFinalDiskLayout.clear();
963  QStringList fileSystem;
964  qDebug() << "Generating custom disk layout";
965       
966  if ( comboPartition->currentIndex() == 0) {
967    targetType = "DRIVE";
968    targetSlice = "ALL";
969    targetDisk = comboDisk->currentText();
970    targetDisk.truncate(targetDisk.indexOf(" -"));
971    target = targetDisk;
972    targetLoc = 1;
973  } else {
974    targetType = "SLICE";
975    targetDisk = comboDisk->currentText();
976    targetDisk.truncate(targetDisk.indexOf(" -"));
977    targetSlice = comboPartition->currentText();
978    targetSlice.truncate(targetSlice.indexOf(":"));
979    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
980    target = targetDisk + targetSlice;
981    targetLoc = 2;
982  }
983
984  if (radioUFS->isChecked() )
985  {
986    // Start building the UFS file-systems
987    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
988    for ( int i = 0; i < mItems.size(); ++i) {
989      fileSystem.clear();
990      fsType=mItems.at(i)->text(3);
991      if ( fsType.indexOf(".eli") != -1 && mItems.at(i)->text(1) != "SWAP" )
992        tmpPass=mItems.at(i)->text(4);
993      else
994        tmpPass="";
995
996      fileSystem << targetDisk << targetSlice << mItems.at(i)->text(1) << fsType << mItems.at(i)->text(2) << "" << tmpPass;
997      sysFinalDiskLayout << fileSystem;
998    }
999  } else {
1000    // Start building the ZFS file-systems
1001    QStringList zMnts;
1002    QString fsType = "ZFS";
1003    int zpoolSize = getDiskSliceSize();
1004
1005    // Check if we need a UFS /boot for encryption
1006    if ( groupEncryption->isChecked()) {
1007      fileSystem << targetDisk << targetSlice << "/boot" << "UFS+SUJ" << "2048" << "" << "";
1008      sysFinalDiskLayout << fileSystem;
1009      zpoolSize = zpoolSize - 2048;
1010      fsType="ZFS.eli";
1011      tmpPass=lineEncPW->text();
1012    }
1013
1014    // Get the zfs mounts
1015    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
1016    for ( int i = 0; i < mItems.size(); ++i) {
1017      if ( mItems.at(i)->text(2).isEmpty() )
1018        zMnts << mItems.at(i)->text(1);
1019      else
1020        zMnts << mItems.at(i)->text(1) + "(" + mItems.at(i)->text(2) + ")";
1021    }
1022
1023    // If we have any additional ZFS mirror / raidz devices set it up now
1024    QString zOpts, zDisk;
1025    if ( groupZFSOpts->isChecked() ) {
1026       zOpts = comboZFSMode->currentText() + ":";
1027       for ( int i = 0; i < listZFSDisks->count(); ++i )
1028          if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
1029             zDisk = listZFSDisks->item(i)->text();
1030             zDisk.truncate(zDisk.indexOf(" -"));
1031             zOpts = zOpts + " " + zDisk;
1032          }
1033    }
1034
1035    // Save the final disk layout
1036    fileSystem.clear();
1037    fileSystem << targetDisk << targetSlice << zMnts.join(",") << fsType << tmp.setNum(zpoolSize) << zOpts << tmpPass;
1038    sysFinalDiskLayout << fileSystem;
1039  }
1040
1041  qDebug() <<"AutoLayout:" << sysFinalDiskLayout;
1042}
1043
1044void wizardDisk::generateConfirmationText()
1045{
1046  // If running in expert mode, we just create a simple config / confirmation
1047  if ( radioExpert->isChecked() ) {
1048    QStringList filesystem;
1049    filesystem << "MANUAL" << "/mnt" ;
1050    sysFinalDiskLayout << filesystem;
1051    textConfirmation->setText(tr("Installing to file-system mounted at /mnt"));
1052    return;
1053  }
1054
1055  QList<QStringList> copyList;
1056  QStringList summaryList;
1057  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
1058  int disk = 0;
1059
1060  // Copy over the list to a new variable we can mangle without modifying the original
1061  copyList = sysFinalDiskLayout;
1062
1063  // Start our summary
1064  summaryList << "";
1065  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
1066
1067  while ( ! copyList.empty() )
1068  {
1069    workingDisk = copyList.at(0).at(0);
1070    workingSlice = copyList.at(0).at(1);
1071    tmpSlice = workingSlice;
1072
1073    // Check if this is an install to "Unused Space"
1074    for (int z=0; z < sysDisks.count(); ++z)
1075      if ( sysDisks.at(z).at(0) == "SLICE" \
1076        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1077        && sysDisks.at(z).at(4) == "Unused Space" )
1078          tmpSlice = "free";
1079
1080    // Check for any mirror for this device
1081    for (int i=0; i < copyList.count(); ++i) {
1082       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
1083       {
1084         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
1085         copyList.removeAt(i);
1086         break;
1087       }
1088    }
1089
1090    // If after doing the mirror, our list is empty, break out
1091    if ( copyList.empty() )
1092      break;
1093   
1094    // If there is a dedicated /boot partition, need to list that first, see what is found
1095    for (int i=0; i < copyList.count(); ++i) {
1096      QStringList mounts = copyList.at(i).at(2).split(",");
1097      for (int z = 0; z < mounts.size(); ++z) {
1098        if ( copyList.at(i).at(0) == workingDisk \
1099          && copyList.at(i).at(1) == workingSlice \
1100          && mounts.at(z) == "/boot" )
1101                startPart="/boot";
1102      }
1103    }
1104
1105    // If no dedicated /boot partition, then lets list "/" first
1106    if(startPart.isEmpty())
1107        startPart="/";
1108
1109    // Start by looking for the root partition
1110    for (int i=0; i < copyList.count(); ++i) {
1111      QStringList mounts = copyList.at(i).at(2).split(",");
1112      for (int z = 0; z < mounts.size(); ++z) {
1113        if ( copyList.at(i).at(0) == workingDisk \
1114          && copyList.at(i).at(1) == workingSlice \
1115          && mounts.at(z) == startPart ) {
1116
1117          // Check if we have any extra arguments to throw on the end
1118          XtraTmp="";
1119          if ( ! copyList.at(i).at(5).isEmpty() )
1120            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1121
1122          // Write the user summary
1123          summaryList << "";
1124          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1125          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1126          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1127
1128          if ( copyList.at(i).at(3) == "ZFS" ) {
1129            QStringList zDS = copyList.at(i).at(2).split(",/");
1130            QString zTMP;
1131            for (int ds = 0; ds < zDS.size(); ++ds) {
1132              if ( zDS.at(ds) != "/" )
1133                zDS.replace(ds, "/" + zDS.at(ds));
1134              if ( zDS.at(ds).indexOf("(") != -1 ) {
1135                zTMP = zDS.at(ds);
1136                zTMP.replace("(", " (");
1137                zDS.replace(ds, zTMP );
1138              }
1139            }
1140            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
1141          } else {
1142            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1143          }
1144          if ( ! XtraTmp.isEmpty() ) {
1145            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1146          }
1147
1148          // Done with this item, remove it now
1149          copyList.removeAt(i);
1150          break;
1151        }
1152      }
1153    }
1154
1155
1156    // Now look for SWAP
1157    for (int i=0; i < copyList.count(); ++i) {
1158      if ( copyList.at(i).at(0) == workingDisk \
1159        && copyList.at(i).at(1) == workingSlice \
1160        && copyList.at(i).at(2) == "SWAP" ) {
1161
1162        // Write the user summary
1163        summaryList << "";
1164        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1165        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1166        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1167
1168        // Done with this item, remove it now
1169        copyList.removeAt(i);
1170        break;
1171      }
1172    }
1173
1174 
1175    // Now look for any other partitions
1176    int count = copyList.count();
1177    for (int i=0; i < count; ++i) {
1178      if ( copyList.at(i).at(0) == workingDisk \
1179        && copyList.at(i).at(1) == workingSlice ) {
1180
1181        // Check if we have any extra arguments to throw on the end
1182        XtraTmp="";
1183        if ( ! copyList.at(i).at(5).isEmpty() )
1184          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1185
1186        // If we are working on the last partition, set the size to 0 to use remaining disk
1187        if ( i == (count - 1) ) 
1188                sliceSize = "0";
1189        else
1190                sliceSize=copyList.at(i).at(4);
1191
1192        // Write the user summary
1193        summaryList << "";
1194        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1195        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1196        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1197        summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1198        if ( ! XtraTmp.isEmpty() ) {
1199          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1200        }
1201
1202        // Done with this item, remove it now
1203        copyList.removeAt(i);
1204        i--;
1205        count--;
1206      }
1207    }
1208
1209    // Increment our disk counter
1210    disk++;
1211  }
1212
1213  textConfirmation->setText(summaryList.join("<br>"));
1214}
1215
1216void wizardDisk::slotTerminal()
1217{
1218  system("xterm &");
1219}
1220
1221void wizardDisk::slotUEnc()
1222{
1223  if ( ! treeMounts->currentItem() )
1224    return;
1225
1226  if ( treeMounts->currentItem()->text(3).indexOf(".eli") != -1 )
1227    treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3).replace(".eli", "") );
1228  else {
1229    bool ok;
1230
1231    // If on /swap, we don't need password
1232    if ( treeMounts->currentItem()->text(1) == "SWAP" ) {
1233      treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3) + ".eli" );
1234      return;
1235    }
1236
1237    QString text = QInputDialog::getText(this, tr("Please enter the password for this partition:"),
1238                                         tr("Password:"), QLineEdit::Password,
1239                                         QString(), &ok);
1240    if (!ok || text.isEmpty())
1241      return;
1242
1243    QString text2 = QInputDialog::getText(this, tr("Please confirm the password for this partition:"),
1244                                         tr("Confirm Password:"), QLineEdit::Password,
1245                                         QString(), &ok);
1246    if (!ok || text.isEmpty())
1247      return;
1248
1249    if ( text != text2 ) {
1250      QMessageBox::critical(this, tr("Password Mismatch"),
1251              tr("The passwords entered do not match!"),
1252              QMessageBox::Ok,
1253              QMessageBox::Ok);
1254      return; 
1255    }
1256
1257    // Save the password
1258    treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3) + ".eli" );
1259    treeMounts->currentItem()->setText(4, text);
1260  }
1261
1262}
Note: See TracBrowser for help on using the repository browser.