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

9.1-release9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 12 months ago

Initial import of PC-BSD /current/ SVN repo

  • Property mode set to 100644
File size: 39.2 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       // Add the main zfs pool with standard partitions including a /swap on ZFS
465       // This lets the user do nifty stuff like a mirror/raid post-install with a single zpool command
466       fileSystem << targetDisk << targetSlice << "/,/swap(volsize=2G|org.freebsd:swap=on|checksum=off),/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;
467       //qDebug() << "Auto-Gen FS:" <<  fileSystem;
468       sysFinalDiskLayout << fileSystem;
469       fileSystem.clear();
470     }
471  }
472 
473  qDebug() << "AutoLayout:" <<  sysFinalDiskLayout;
474}
475
476void wizardDisk::populateDiskTree()
477{
478  QStringList tmpList, zMnts;
479  QString tmp, opts;
480  int usedSpace = 0;
481  bool ok;
482
483  // If doing ZFS advanced setup, disable encryption
484  if ( groupZFSOpts->isChecked() )
485    groupEncryption->setChecked(false);
486
487  treeMounts->clear();
488  if (radioUFS->isChecked()) {
489    treeMounts->setHeaderLabels(QStringList() << "ID" << tr("Mount") << tr("Size") << tr("Type") << "Pass" );
490    treeMounts->header()->setSectionHidden(4, true);
491    treeMounts->setColumnCount(5);
492    labelFreeSpace->setVisible(true);
493    lineFreeMB->setVisible(true);
494    pushSizeMount->setVisible(true);
495  } else {
496    treeMounts->setHeaderLabels(QStringList() << "ID" << tr("ZFS Mounts") << tr("ZFS Options") );
497    treeMounts->setColumnCount(3);
498    labelFreeSpace->setVisible(false);
499    lineFreeMB->setVisible(false);
500    pushSizeMount->setVisible(false);
501  }
502
503  treeMounts->header()->setSectionHidden(0, true);
504  treeMounts->header()->setDefaultSectionSize(150);
505
506  if (radioUFS->isChecked()) {
507    for (int i=0; i < sysFinalDiskLayout.count(); ++i) {
508      // Start adding the disk items to our tree widget
509      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));
510      usedSpace = usedSpace +  sysFinalDiskLayout.at(i).at(4).toInt(&ok);
511    }
512   
513    // Now lets show how much is free to play with
514    lineFreeMB->setText(QString().setNum(getDiskSliceSize() - usedSpace));
515
516  } else {
517    // Show ZFS stuff
518
519    // If using encryption, skip the /boot UFS partition
520    if ( groupEncryption->isChecked())
521      zMnts = sysFinalDiskLayout.at(1).at(2).split(",");
522    else
523      zMnts = sysFinalDiskLayout.at(0).at(2).split(",");
524
525    // Now loop through ZFS mounts
526    for (int i=0; i < zMnts.count(); ++i) {
527      tmpList.clear();
528      opts = zMnts.at(i).section("(", 1, 1).section(")", 0, 0); 
529      tmpList << tmp.setNum(i+1) << zMnts.at(i).split("(").at(0) << opts ;
530      QTreeWidgetItem *mItem = new QTreeWidgetItem(treeMounts, tmpList);
531      mItem->setToolTip(2, opts);
532    }
533  }
534
535  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
536  slotTreeDiskChanged(); 
537
538}
539
540int wizardDisk::getDiskSliceSize()
541{
542  bool ok;
543  QString disk = comboDisk->currentText();
544  disk.truncate(disk.indexOf(" -"));
545
546  int safeBuf = 10;
547
548  // Check the full disk
549  if ( comboPartition->currentIndex() == 0) {
550    for (int i=0; i < sysDisks.count(); ++i) {
551      // Make sure to only add the drives to the comboDiskList
552      if ( sysDisks.at(i).at(0) == "DRIVE" && sysDisks.at(i).at(1) == disk ) {
553        //qDebug() << "Selected Disk Size: " +  sysDisks.at(i).at(2);
554        sysDisks.at(i).at(2).toInt(&ok);
555        if( ok )
556          return sysDisks.at(i).at(2).toInt(&ok) - safeBuf;
557        else
558          return -1;
559      }
560    }
561  } else {
562    // Check the selected partition
563    QString slice = comboPartition->currentText();
564    slice.truncate(slice.indexOf(":"));
565    for (int i=0; i < sysDisks.count(); ++i) {
566      // Make sure to only add the slices to the listDiskSlices
567      if ( sysDisks.at(i).at(0) == "SLICE" && slice == sysDisks.at(i).at(2)) {
568        //qDebug() << "Selected Slice Size: " +  sysDisks.at(i).at(3);
569        sysDisks.at(i).at(3).toInt(&ok);
570        if( ok )
571          return sysDisks.at(i).at(3).toInt(&ok) - safeBuf;
572        else
573          return -1;
574      }
575    }
576  }
577
578  return -1;
579}
580
581void wizardDisk::slotTreeDiskChanged()
582{
583   if ( ! treeMounts->currentItem() )
584     return;
585
586   pushRemoveMount->setEnabled(true);
587   pushAddMount->setEnabled(true);
588   pushSizeMount->setEnabled(true);
589
590   if ( treeMounts->currentItem()->text(1) == "/boot" || treeMounts->currentItem()->text(1) == "/")
591     pushRemoveMount->setEnabled(false);
592
593   if ( lineFreeMB->text() == "0" )
594     pushAddMount->setEnabled(false);
595}
596
597void wizardDisk::slotResizeFS()
598{
599  if ( ! treeMounts->currentItem() )
600  return;
601
602  QString mnt = treeMounts->currentItem()->text(1);
603  bool ok;
604  int curSize, availSize, minSize; 
605  curSize =  treeMounts->currentItem()->text(2).toInt(&ok);
606  availSize = curSize + lineFreeMB->text().toInt(&ok);
607
608  minSize = 100;
609
610  // See if we need some other sanity check on sizes
611  if ( mnt == "SWAP" )
612    minSize = 256;
613  if ( mnt == "/" )
614    minSize = 2000;
615  if ( mnt == "/boot" )
616    minSize = 1000;
617
618  addingMount="";
619  rFS = new dialogFSSize();
620  rFS->programInit(QString(tr("Resizing") + " " + mnt), curSize, availSize, minSize);
621  rFS->setWindowModality(Qt::ApplicationModal);
622  connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
623  rFS->show();
624  rFS->raise();
625}
626
627void wizardDisk::slotRemoveFS()
628{
629  if ( ! treeMounts->currentItem() )
630  return;
631
632  int ret = QMessageBox::question(this, tr("Remove mount-point"),
633              tr("Are you sure you want to remove this mount point?"),
634              QMessageBox::Yes | QMessageBox::No,
635              QMessageBox::No);
636
637  if ( ret != QMessageBox::Yes )
638    return;
639 
640  QTreeWidgetItem *rmItem = treeMounts->currentItem();
641  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
642
643  // If editing UFS, lets adjust the available size
644  if (radioUFS->isChecked()) {
645    bool ok;
646    QString tmp;
647    int fSize = rmItem->text(2).toInt(&ok);
648    int newAvailSize = lineFreeMB->text().toInt(&ok) + fSize; 
649    lineFreeMB->setText(tmp.setNum(newAvailSize));
650  }
651
652  delete rmItem;
653}
654
655void wizardDisk::slotAddFS()
656{
657  bool ok;
658  QString tmp;
659  QString nMount = QInputDialog::getText(this, tr("Enter mount-point"),
660                                          tr("Please enter the new mount-point:"), QLineEdit::Normal,
661                                          "/", &ok);
662  if (!ok || nMount.isEmpty())
663    return;
664
665  // Sanity checks
666  ////////////////////////////////////////
667  if (nMount == "/boot" && radioZFS->isChecked() && groupEncryption->isChecked() ) {
668      QMessageBox::critical(this, tr("Invalid Mount"),
669              tr("Cannot create /boot dataset on ZFS with encryption enabled!"),
670              QMessageBox::Ok,
671              QMessageBox::Ok);
672      return;
673  }
674  if ( nMount.indexOf("/") != 0 ) {
675      QMessageBox::critical(this, tr("Invalid Mount"),
676              tr("Mount point should start with '/'"),
677              QMessageBox::Ok,
678              QMessageBox::Ok);
679      return;
680  }
681  // End sanity checks
682  ////////////////////////////////////////
683
684  // Make sure this mount doesn't already exist
685  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
686  for ( int i = 0; i < mItems.size(); ++i) {
687    if ( mItems.at(i)->text(1) == nMount )
688      return;
689  }
690
691  if  ( radioUFS->isChecked() ) {
692    // Doing UFS mount, lets get a size from the user
693    addingMount = nMount;
694    int availSize = lineFreeMB->text().toInt(&ok); 
695    rFS = new dialogFSSize();
696    rFS->programInit(QString(tr("Specify a size for the mount") + " " + addingMount), 100, availSize, 100);
697    rFS->setWindowModality(Qt::ApplicationModal);
698    connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
699    rFS->show();
700    rFS->raise();
701  } else {
702    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << nMount );
703  }
704}
705
706void wizardDisk::slotSaveFSResize(int newSize)
707{
708
709  QString tmp, tmp2;
710  bool ok;
711  int oSize, availSize, tSize, newAvailSize;
712
713  // If adding a new mount point
714  if ( ! addingMount.isEmpty() ) {
715    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
716    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << addingMount << tmp2.setNum(newSize) << "UFS+SUJ" );
717    addingMount="";
718    availSize = lineFreeMB->text().toInt(&ok); 
719    newAvailSize = availSize - newSize;
720    lineFreeMB->setText(tmp.setNum(newAvailSize));
721    return;
722  } 
723
724  if ( ! treeMounts->currentItem() )
725    return;
726
727  // Just resizing an existing partition
728  oSize = treeMounts->currentItem()->text(2).toInt(&ok); 
729  treeMounts->currentItem()->setText(2, tmp.setNum(newSize));
730
731  // Set the available size
732  if ( oSize > newSize ) {
733    tSize = oSize - newSize;
734    availSize = lineFreeMB->text().toInt(&ok); 
735    newAvailSize = availSize + tSize;
736  } else {
737    tSize = newSize - oSize;
738    availSize = lineFreeMB->text().toInt(&ok); 
739    newAvailSize = availSize - tSize;
740  }
741  lineFreeMB->setText(tmp.setNum(newAvailSize));
742
743  // Check if we need to enable the add button
744  if ( newAvailSize >= 100 )
745    pushAddMount->setEnabled(true);
746  else
747    pushAddMount->setEnabled(false);
748}
749
750void wizardDisk::slotTreeMountsRightClick()
751{
752  if ( ! treeMounts->currentItem() )
753    return;
754
755  popup = new QMenu();
756  popup->setTitle(tr("Editing:") + " " + treeMounts->currentItem()->text(1));
757  popup->addSeparator();
758
759  if  ( radioUFS->isChecked() ) {
760    // No options to change for / or /boot
761    if ( treeMounts->currentItem()->text(1) == "/" )
762      return;
763    if ( treeMounts->currentItem()->text(1) == "/boot" )
764      return;
765
766    if ( treeMounts->currentItem()->text(3).indexOf(".eli") != -1 )
767      popup->addAction( tr("Disable Encryption"), this, SLOT(slotUEnc()));
768    else
769      popup->addAction( tr("Enable Encryption"), this, SLOT(slotUEnc()));
770
771    // End of UFS options
772  } else {
773    // No options to change for /swap
774    if ( treeMounts->currentItem()->text(1) == "/swap" ) {
775      popup->addAction( "Change size", this, SLOT(slotZSwapSize()));
776      popup->exec( QCursor::pos() );
777      return;
778    }
779
780    // Create atime sub-menu
781    popupAT = popup->addMenu("atime");
782    popupAT->addAction( "on", this, SLOT(slotZATON()));
783    popupAT->addAction( "off", this, SLOT(slotZATOFF()));
784
785    // Create canmount sub-menu
786    popupCM = popup->addMenu("canmount");
787    popupCM->addAction( "on", this, SLOT(slotZCMON()));
788    popupCM->addAction( "off", this, SLOT(slotZCMOFF()));
789    popupCM->addAction( "noauto", this, SLOT(slotZCMNOAUTO()));
790
791    // Create Checksum sub-menu
792    popupCH = popup->addMenu("checksum");
793    popupCH->addAction( "on", this, SLOT(slotZChkON()));
794    popupCH->addAction( "off", this, SLOT(slotZChkOFF()));
795
796    // Create compression sub-menu
797    popupCmp = popup->addMenu("compression");
798    popupCmp->addAction( "off", this, SLOT(slotZCmpOFF()));
799    popupCmp->addAction( "lzjb", this, SLOT(slotZCmpLZJB()));
800    popupCmp->addAction( "gzip", this, SLOT(slotZCmpGZIP()));
801    popupCmp->addAction( "zle", this, SLOT(slotZCmpZLE()));
802
803    // Create dedup sub-menu
804    // dedup is disabled for now, until such time as it is safe in all cases
805    //popupDD = popup->addMenu("dedup");
806    //popupDD->addAction( "off", this, SLOT(slotZDDOFF()));
807    //popupDD->addAction( "on", this, SLOT(slotZDDON()));
808    //popupDD->addAction( "verify", this, SLOT(slotZDDVERIFY()));
809
810    // Create exec sub-menu
811    popupNE = popup->addMenu("exec");
812    popupNE->addAction( "on", this, SLOT(slotZEXON()));
813    popupNE->addAction( "off", this, SLOT(slotZEXOFF()));
814
815  }
816  popup->exec( QCursor::pos() );
817
818}
819
820void wizardDisk::slotZCMNOAUTO()
821{
822  toggleZFSOpt(QString("canmount=noauto"));
823}
824
825void wizardDisk::slotZCMOFF()
826{
827  toggleZFSOpt(QString("canmount=off"));
828}
829
830void wizardDisk::slotZCMON()
831{
832  toggleZFSOpt(QString("canmount=on"));
833}
834
835void wizardDisk::slotZDDVERIFY()
836{
837  toggleZFSOpt(QString("dedup=verify"));
838}
839
840void wizardDisk::slotZDDON()
841{
842  toggleZFSOpt(QString("dedup=on"));
843}
844
845void wizardDisk::slotZDDOFF()
846{
847  toggleZFSOpt(QString("dedup=off"));
848}
849
850void wizardDisk::slotZCmpZLE()
851{
852  toggleZFSOpt(QString("compress=zle"));
853}
854
855void wizardDisk::slotZCmpGZIP()
856{
857  toggleZFSOpt(QString("compress=gzip"));
858}
859
860void wizardDisk::slotZCmpLZJB()
861{
862  toggleZFSOpt(QString("compress=lzjb"));
863}
864
865void wizardDisk::slotZCmpOFF()
866{
867  toggleZFSOpt(QString("compress=off"));
868}
869
870void wizardDisk::slotZChkOFF()
871{
872  toggleZFSOpt(QString("checksum=off"));
873}
874
875void wizardDisk::slotZChkON()
876{
877  toggleZFSOpt(QString("checksum=on"));
878}
879
880void wizardDisk::slotZATON()
881{
882  toggleZFSOpt(QString("atime=on"));
883}
884
885void wizardDisk::slotZSwapSize()
886{
887  bool ok;
888  QString tmp;
889  int size = QInputDialog::getInt(this, tr("Enter SWAP size"),
890                                  tr("Size (MB)"), 2048, 0, 1000000, 1, &ok);
891  if ( ok )
892  {
893    tmp.setNum(size);
894    QString optString = "volsize=" + tmp + "M|org.freebsd:swap=on|checksum=off";
895    treeMounts->currentItem()->setText(2, optString);
896    treeMounts->currentItem()->setToolTip(2, optString);
897  }
898}
899
900void wizardDisk::slotZATOFF()
901{
902  toggleZFSOpt(QString("atime=off"));
903}
904
905void wizardDisk::slotZEXOFF()
906{
907  toggleZFSOpt(QString("exec=off"));
908}
909
910void wizardDisk::slotZEXON()
911{
912  toggleZFSOpt(QString("exec=on"));
913}
914
915// Toggle an option being on / off for ZFS
916void wizardDisk::toggleZFSOpt(QString option)
917{
918  if ( ! treeMounts->currentItem() )
919    return;
920
921  bool found = false;
922  QString optTag = option.section("=", 0, 0);
923  QString tmpTag;
924  QStringList newOpts;
925  QStringList curOpts = treeMounts->currentItem()->text(2).split("|");
926  for (int i=0; i < curOpts.count(); ++i) {
927    tmpTag=curOpts.at(i).section("=", 0, 0);
928    if ( optTag == tmpTag ) {
929      found = true;
930      // Only save option if setting to new value
931      if ( option != curOpts.at(i) )
932        newOpts << option;
933    } else {
934      if ( !curOpts.at(i).isEmpty() )
935        newOpts << curOpts.at(i);
936    }
937  }
938
939  if ( ! found )
940      newOpts << option;
941
942  QString optString;
943  if ( newOpts.count() <= 1)
944    optString = newOpts.join("");
945  else
946    optString = newOpts.join("|");
947
948  treeMounts->currentItem()->setText(2, optString);
949  treeMounts->currentItem()->setToolTip(2, optString);
950}
951
952void wizardDisk::generateCustomDiskLayout()
953{
954  QString targetType, tmp;
955  int targetLoc;
956  QString targetDisk, targetSlice, tmpPass, fsType, target;
957
958  // If doing ZFS advanced setup, disable encryption
959  if ( groupZFSOpts->isChecked() )
960    groupEncryption->setChecked(false);
961       
962  // Clear out the original disk layout
963  sysFinalDiskLayout.clear();
964  QStringList fileSystem;
965  qDebug() << "Generating custom disk layout";
966       
967  if ( comboPartition->currentIndex() == 0) {
968    targetType = "DRIVE";
969    targetSlice = "ALL";
970    targetDisk = comboDisk->currentText();
971    targetDisk.truncate(targetDisk.indexOf(" -"));
972    target = targetDisk;
973    targetLoc = 1;
974  } else {
975    targetType = "SLICE";
976    targetDisk = comboDisk->currentText();
977    targetDisk.truncate(targetDisk.indexOf(" -"));
978    targetSlice = comboPartition->currentText();
979    targetSlice.truncate(targetSlice.indexOf(":"));
980    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
981    target = targetDisk + targetSlice;
982    targetLoc = 2;
983  }
984
985  if (radioUFS->isChecked() )
986  {
987    // Start building the UFS file-systems
988    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
989    for ( int i = 0; i < mItems.size(); ++i) {
990      fileSystem.clear();
991      fsType=mItems.at(i)->text(3);
992      if ( fsType.indexOf(".eli") != -1 && mItems.at(i)->text(1) != "SWAP" )
993        tmpPass=mItems.at(i)->text(4);
994      else
995        tmpPass="";
996
997      fileSystem << targetDisk << targetSlice << mItems.at(i)->text(1) << fsType << mItems.at(i)->text(2) << "" << tmpPass;
998      sysFinalDiskLayout << fileSystem;
999    }
1000  } else {
1001    // Start building the ZFS file-systems
1002    QStringList zMnts;
1003    QString fsType = "ZFS";
1004    int zpoolSize = getDiskSliceSize();
1005
1006    // Check if we need a UFS /boot for encryption
1007    if ( groupEncryption->isChecked()) {
1008      fileSystem << targetDisk << targetSlice << "/boot" << "UFS+SUJ" << "2048" << "" << "";
1009      sysFinalDiskLayout << fileSystem;
1010      zpoolSize = zpoolSize - 2048;
1011      fsType="ZFS.eli";
1012      tmpPass=lineEncPW->text();
1013    }
1014
1015    // Get the zfs mounts
1016    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
1017    for ( int i = 0; i < mItems.size(); ++i) {
1018      if ( mItems.at(i)->text(2).isEmpty() )
1019        zMnts << mItems.at(i)->text(1);
1020      else
1021        zMnts << mItems.at(i)->text(1) + "(" + mItems.at(i)->text(2) + ")";
1022    }
1023
1024    // If we have any additional ZFS mirror / raidz devices set it up now
1025    QString zOpts, zDisk;
1026    if ( groupZFSOpts->isChecked() ) {
1027       zOpts = comboZFSMode->currentText() + ":";
1028       for ( int i = 0; i < listZFSDisks->count(); ++i )
1029          if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
1030             zDisk = listZFSDisks->item(i)->text();
1031             zDisk.truncate(zDisk.indexOf(" -"));
1032             zOpts = zOpts + " " + zDisk;
1033          }
1034    }
1035
1036    // Save the final disk layout
1037    fileSystem.clear();
1038    fileSystem << targetDisk << targetSlice << zMnts.join(",") << fsType << tmp.setNum(zpoolSize) << zOpts << tmpPass;
1039    sysFinalDiskLayout << fileSystem;
1040  }
1041
1042  qDebug() <<"AutoLayout:" << sysFinalDiskLayout;
1043}
1044
1045void wizardDisk::generateConfirmationText()
1046{
1047  // If running in expert mode, we just create a simple config / confirmation
1048  if ( radioExpert->isChecked() ) {
1049    QStringList filesystem;
1050    filesystem << "MANUAL" << "/mnt" ;
1051    sysFinalDiskLayout << filesystem;
1052    textConfirmation->setText(tr("Installing to file-system mounted at /mnt"));
1053    return;
1054  }
1055
1056  QList<QStringList> copyList;
1057  QStringList summaryList;
1058  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
1059  int disk = 0;
1060
1061  // Copy over the list to a new variable we can mangle without modifying the original
1062  copyList = sysFinalDiskLayout;
1063
1064  // Start our summary
1065  summaryList << "";
1066  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
1067
1068  while ( ! copyList.empty() )
1069  {
1070    workingDisk = copyList.at(0).at(0);
1071    workingSlice = copyList.at(0).at(1);
1072    tmpSlice = workingSlice;
1073
1074    // Check if this is an install to "Unused Space"
1075    for (int z=0; z < sysDisks.count(); ++z)
1076      if ( sysDisks.at(z).at(0) == "SLICE" \
1077        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1078        && sysDisks.at(z).at(4) == "Unused Space" )
1079          tmpSlice = "free";
1080
1081    // Check for any mirror for this device
1082    for (int i=0; i < copyList.count(); ++i) {
1083       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
1084       {
1085         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
1086         copyList.removeAt(i);
1087         break;
1088       }
1089    }
1090
1091    // If after doing the mirror, our list is empty, break out
1092    if ( copyList.empty() )
1093      break;
1094   
1095    // If there is a dedicated /boot partition, need to list that first, see what is found
1096    for (int i=0; i < copyList.count(); ++i) {
1097      QStringList mounts = copyList.at(i).at(2).split(",");
1098      for (int z = 0; z < mounts.size(); ++z) {
1099        if ( copyList.at(i).at(0) == workingDisk \
1100          && copyList.at(i).at(1) == workingSlice \
1101          && mounts.at(z) == "/boot" )
1102                startPart="/boot";
1103      }
1104    }
1105
1106    // If no dedicated /boot partition, then lets list "/" first
1107    if(startPart.isEmpty())
1108        startPart="/";
1109
1110    // Start by looking for the root partition
1111    for (int i=0; i < copyList.count(); ++i) {
1112      QStringList mounts = copyList.at(i).at(2).split(",");
1113      for (int z = 0; z < mounts.size(); ++z) {
1114        if ( copyList.at(i).at(0) == workingDisk \
1115          && copyList.at(i).at(1) == workingSlice \
1116          && mounts.at(z) == startPart ) {
1117
1118          // Check if we have any extra arguments to throw on the end
1119          XtraTmp="";
1120          if ( ! copyList.at(i).at(5).isEmpty() )
1121            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1122
1123          // Write the user summary
1124          summaryList << "";
1125          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1126          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1127          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1128
1129          if ( copyList.at(i).at(3) == "ZFS" ) {
1130            QStringList zDS = copyList.at(i).at(2).split(",/");
1131            QString zTMP;
1132            for (int ds = 0; ds < zDS.size(); ++ds) {
1133              if ( zDS.at(ds) != "/" )
1134                zDS.replace(ds, "/" + zDS.at(ds));
1135              if ( zDS.at(ds).indexOf("(") != -1 ) {
1136                zTMP = zDS.at(ds);
1137                zTMP.replace("(", " (");
1138                zDS.replace(ds, zTMP );
1139              }
1140            }
1141            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
1142          } else {
1143            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1144          }
1145          if ( ! XtraTmp.isEmpty() ) {
1146            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1147          }
1148
1149          // Done with this item, remove it now
1150          copyList.removeAt(i);
1151          break;
1152        }
1153      }
1154    }
1155
1156
1157    // Now look for SWAP
1158    for (int i=0; i < copyList.count(); ++i) {
1159      if ( copyList.at(i).at(0) == workingDisk \
1160        && copyList.at(i).at(1) == workingSlice \
1161        && copyList.at(i).at(2) == "SWAP" ) {
1162
1163        // Write the user summary
1164        summaryList << "";
1165        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1166        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1167        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1168
1169        // Done with this item, remove it now
1170        copyList.removeAt(i);
1171        break;
1172      }
1173    }
1174
1175 
1176    // Now look for any other partitions
1177    int count = copyList.count();
1178    for (int i=0; i < count; ++i) {
1179      if ( copyList.at(i).at(0) == workingDisk \
1180        && copyList.at(i).at(1) == workingSlice ) {
1181
1182        // Check if we have any extra arguments to throw on the end
1183        XtraTmp="";
1184        if ( ! copyList.at(i).at(5).isEmpty() )
1185          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1186
1187        // If we are working on the last partition, set the size to 0 to use remaining disk
1188        if ( i == (count - 1) ) 
1189                sliceSize = "0";
1190        else
1191                sliceSize=copyList.at(i).at(4);
1192
1193        // Write the user summary
1194        summaryList << "";
1195        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1196        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1197        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1198        summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1199        if ( ! XtraTmp.isEmpty() ) {
1200          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1201        }
1202
1203        // Done with this item, remove it now
1204        copyList.removeAt(i);
1205        i--;
1206        count--;
1207      }
1208    }
1209
1210    // Increment our disk counter
1211    disk++;
1212  }
1213
1214  textConfirmation->setText(summaryList.join("<br>"));
1215}
1216
1217void wizardDisk::slotTerminal()
1218{
1219  system("xterm &");
1220}
1221
1222void wizardDisk::slotUEnc()
1223{
1224  if ( ! treeMounts->currentItem() )
1225    return;
1226
1227  if ( treeMounts->currentItem()->text(3).indexOf(".eli") != -1 )
1228    treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3).replace(".eli", "") );
1229  else {
1230    bool ok;
1231
1232    // If on /swap, we don't need password
1233    if ( treeMounts->currentItem()->text(1) == "SWAP" ) {
1234      treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3) + ".eli" );
1235      return;
1236    }
1237
1238    QString text = QInputDialog::getText(this, tr("Please enter the password for this partition:"),
1239                                         tr("Password:"), QLineEdit::Password,
1240                                         QString(), &ok);
1241    if (!ok || text.isEmpty())
1242      return;
1243
1244    QString text2 = QInputDialog::getText(this, tr("Please confirm the password for this partition:"),
1245                                         tr("Confirm Password:"), QLineEdit::Password,
1246                                         QString(), &ok);
1247    if (!ok || text.isEmpty())
1248      return;
1249
1250    if ( text != text2 ) {
1251      QMessageBox::critical(this, tr("Password Mismatch"),
1252              tr("The passwords entered do not match!"),
1253              QMessageBox::Ok,
1254              QMessageBox::Ok);
1255      return; 
1256    }
1257
1258    // Save the password
1259    treeMounts->currentItem()->setText(3, treeMounts->currentItem()->text(3) + ".eli" );
1260    treeMounts->currentItem()->setText(4, text);
1261  }
1262
1263}
Note: See TracBrowser for help on using the repository browser.