diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index cfc5e567e..c166390e8 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -12,6 +12,10 @@ set_package_properties( ) if ( KPMcore_FOUND ) + if ( KPMcore_VERSION VERSION_GREATER "3.3.0") + add_definitions(-DWITH_KPMCOREGT33) # kpmcore greater than 3.3 + endif() + include_directories( ${KPMCORE_INCLUDE_DIR} ) include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) @@ -35,9 +39,11 @@ if ( KPMcore_FOUND ) gui/BootInfoWidget.cpp gui/ChoicePage.cpp gui/CreatePartitionDialog.cpp + gui/CreateVolumeGroupDialog.cpp gui/DeviceInfoWidget.cpp gui/EditExistingPartitionDialog.cpp gui/EncryptWidget.cpp + gui/ListPhysicalVolumeWidgetItem.cpp gui/PartitionPage.cpp gui/PartitionBarsView.cpp gui/PartitionDialogHelpers.cpp @@ -46,17 +52,23 @@ if ( KPMcore_FOUND ) gui/PartitionSplitterWidget.cpp gui/PartitionViewStep.cpp gui/PrettyRadioButton.cpp + gui/ResizeVolumeGroupDialog.cpp gui/ScanningDialog.cpp gui/ReplaceWidget.cpp + gui/VolumeGroupBaseDialog.cpp jobs/ClearMountsJob.cpp jobs/ClearTempMountsJob.cpp jobs/CreatePartitionJob.cpp jobs/CreatePartitionTableJob.cpp + jobs/CreateVolumeGroupJob.cpp + jobs/DeactivateVolumeGroupJob.cpp jobs/DeletePartitionJob.cpp jobs/FillGlobalStorageJob.cpp jobs/FormatPartitionJob.cpp jobs/PartitionJob.cpp + jobs/RemoveVolumeGroupJob.cpp jobs/ResizePartitionJob.cpp + jobs/ResizeVolumeGroupJob.cpp jobs/SetPartitionFlagsJob.cpp UI gui/ChoicePage.ui @@ -66,6 +78,7 @@ if ( KPMcore_FOUND ) gui/EncryptWidget.ui gui/PartitionPage.ui gui/ReplaceWidget.ui + gui/VolumeGroupBaseDialog.ui LINK_PRIVATE_LIBRARIES kpmcore calamaresui diff --git a/src/modules/partition/core/DeviceModel.cpp b/src/modules/partition/core/DeviceModel.cpp index 00058bac4..260315729 100644 --- a/src/modules/partition/core/DeviceModel.cpp +++ b/src/modules/partition/core/DeviceModel.cpp @@ -29,6 +29,7 @@ // KF5 #include +#include #include // STL @@ -77,10 +78,18 @@ DeviceModel::data( const QModelIndex& index, int role ) const if ( device->name().isEmpty() ) return device->deviceNode(); else - return tr( "%1 - %2 (%3)" ) - .arg( device->name() ) - .arg( KFormat().formatByteSize( device->capacity() ) ) - .arg( device->deviceNode() ); + { + if ( device->logicalSize() >= 0 && device->totalLogical() >= 0 ) + return tr( "%1 - %2 (%3)" ) + .arg( device->name() ) + .arg( KFormat().formatByteSize( device->capacity() ) ) + .arg( device->deviceNode() ); + // Newly LVM VGs don't have capacity property yet (i.e. always has 1B capacity), so don't show it for a while + else + return tr( "%1 - (%2)" ) + .arg( device->name() ) + .arg( device->deviceNode() ); + } case Qt::DecorationRole: return CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionDisk, CalamaresUtils::Original, @@ -116,3 +125,31 @@ DeviceModel::swapDevice( Device* oldDevice, Device* newDevice ) emit dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) ); } + +void +DeviceModel::addDevice( Device *device ) +{ + beginResetModel(); + + m_devices << device; + std::sort( m_devices.begin(), m_devices.end(), []( const Device* dev1, const Device* dev2 ) + { + return dev1->deviceNode() < dev2->deviceNode(); + } ); + + endResetModel(); +} + +void +DeviceModel::removeDevice( Device *device ) +{ + beginResetModel(); + + m_devices.removeAll( device ); + std::sort( m_devices.begin(), m_devices.end(), []( const Device* dev1, const Device* dev2 ) + { + return dev1->deviceNode() < dev2->deviceNode(); + } ); + + endResetModel(); +} diff --git a/src/modules/partition/core/DeviceModel.h b/src/modules/partition/core/DeviceModel.h index ccca426bd..2e2f99342 100644 --- a/src/modules/partition/core/DeviceModel.h +++ b/src/modules/partition/core/DeviceModel.h @@ -49,6 +49,10 @@ public: void swapDevice( Device* oldDevice, Device* newDevice ); + void addDevice( Device* device ); + + void removeDevice( Device* device ); + private: QList< Device* > m_devices; }; diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 3cc88d527..147212cbe 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -34,10 +34,14 @@ #include "jobs/ClearTempMountsJob.h" #include "jobs/CreatePartitionJob.h" #include "jobs/CreatePartitionTableJob.h" +#include "jobs/CreateVolumeGroupJob.h" +#include "jobs/DeactivateVolumeGroupJob.h" #include "jobs/DeletePartitionJob.h" #include "jobs/FillGlobalStorageJob.h" #include "jobs/FormatPartitionJob.h" +#include "jobs/RemoveVolumeGroupJob.h" #include "jobs/ResizePartitionJob.h" +#include "jobs/ResizeVolumeGroupJob.h" #include "jobs/SetPartitionFlagsJob.h" #include "Typedefs.h" @@ -45,10 +49,13 @@ // KPMcore #include +#include #include #include #include #include +#include +#include // Qt #include @@ -62,6 +69,7 @@ PartitionCoreModule::DeviceInfo::DeviceInfo( Device* _device ) : device( _device ) , partitionModel( new PartitionModel ) , immutableDevice( new Device( *_device ) ) + , isAvailable( true ) {} PartitionCoreModule::DeviceInfo::~DeviceInfo() @@ -178,6 +186,8 @@ PartitionCoreModule::doInit() m_bootLoaderModel->init( bootLoaderDevices ); + scanForLVMPVs(); + //FIXME: this should be removed in favor of // proper KPM support for EFI if ( PartUtils::isEfiSystem() ) @@ -265,6 +275,77 @@ PartitionCoreModule::createPartition( Device* device, refresh(); } +void +PartitionCoreModule::createVolumeGroup( QString &vgName, + QVector< const Partition* > pvList, + qint32 peSize ) +{ + // Appending '_' character in case of repeated VG name + while ( hasVGwithThisName( vgName ) ) + vgName.append('_'); + + CreateVolumeGroupJob* job = new CreateVolumeGroupJob( vgName, pvList, peSize ); + job->updatePreview(); + + LvmDevice* device = new LvmDevice(vgName); + + for ( const Partition* p : pvList ) + device->physicalVolumes() << p; + + DeviceInfo* deviceInfo = new DeviceInfo( device ); + + deviceInfo->partitionModel->init( device, osproberEntries() ); + + m_deviceModel->addDevice( device ); + + m_deviceInfos << deviceInfo; + deviceInfo->jobs << Calamares::job_ptr( job ); + + refresh(); +} + +void +PartitionCoreModule::resizeVolumeGroup( LvmDevice *device, QVector< const Partition* >& pvList ) +{ + DeviceInfo* deviceInfo = infoForDevice( device ); + Q_ASSERT( deviceInfo ); + + ResizeVolumeGroupJob* job = new ResizeVolumeGroupJob( device, pvList ); + + deviceInfo->jobs << Calamares::job_ptr( job ); + + refresh(); +} + +void +PartitionCoreModule::deactivateVolumeGroup( LvmDevice *device ) +{ + DeviceInfo* deviceInfo = infoForDevice( device ); + Q_ASSERT( deviceInfo ); + + deviceInfo->isAvailable = false; + + DeactivateVolumeGroupJob* job = new DeactivateVolumeGroupJob( device ); + + // DeactivateVolumeGroupJob needs to be immediately called + job->exec(); + + refresh(); +} + +void +PartitionCoreModule::removeVolumeGroup( LvmDevice *device ) +{ + DeviceInfo* deviceInfo = infoForDevice( device ); + Q_ASSERT( deviceInfo ); + + RemoveVolumeGroupJob* job = new RemoveVolumeGroupJob( device ); + + deviceInfo->jobs << Calamares::job_ptr( job ); + + refresh(); +} + void PartitionCoreModule::deletePartition( Device* device, Partition* partition ) { @@ -435,6 +516,37 @@ PartitionCoreModule::efiSystemPartitions() const return m_efiSystemPartitions; } +QVector< const Partition* > +PartitionCoreModule::lvmPVs() const +{ + return m_lvmPVs; +} + +bool +PartitionCoreModule::hasVGwithThisName( const QString& name ) const +{ + for ( DeviceInfo* d : m_deviceInfos ) + if ( dynamic_cast(d->device.data()) && + d->device.data()->name() == name) + return true; + + return false; +} + +bool +PartitionCoreModule::isInVG( const Partition *partition ) const +{ + for ( DeviceInfo* d : m_deviceInfos ) + { + LvmDevice* vg = dynamic_cast( d->device.data() ); + + if ( vg && vg->physicalVolumes().contains( partition )) + return true; + } + + return false; +} + void PartitionCoreModule::dumpQueue() const { @@ -474,6 +586,8 @@ PartitionCoreModule::refresh() updateIsDirty(); m_bootLoaderModel->update(); + scanForLVMPVs(); + //FIXME: this should be removed in favor of // proper KPM support for EFI if ( PartUtils::isEfiSystem() ) @@ -526,6 +640,80 @@ PartitionCoreModule::scanForEfiSystemPartitions() m_efiSystemPartitions = efiSystemPartitions; } +void +PartitionCoreModule::scanForLVMPVs() +{ + m_lvmPVs.clear(); + + QList< Device* > physicalDevices; + QList< LvmDevice* > vgDevices; + + for ( DeviceInfo* deviceInfo : m_deviceInfos ) + { + if ( deviceInfo->device.data()->type() == Device::Type::Disk_Device) + physicalDevices << deviceInfo->device.data(); + else if ( deviceInfo->device.data()->type() == Device::Type::LVM_Device ) + { + LvmDevice* device = dynamic_cast(deviceInfo->device.data()); + + // Restoring physical volume list + device->physicalVolumes().clear(); + + vgDevices << device; + } + } + + // Update LVM::pvList + LvmDevice::scanSystemLVM( physicalDevices ); + + for ( auto p : LVM::pvList ) + { + m_lvmPVs << p.partition().data(); + + for ( LvmDevice* device : vgDevices ) + if ( p.vgName() == device->name() ) + { + // Adding scanned VG to PV list + device->physicalVolumes() << p.partition(); + break; + } + } + + for ( DeviceInfo* d : m_deviceInfos ) + { + for ( auto job : d->jobs ) + { + // Including new LVM PVs + CreatePartitionJob* partJob = dynamic_cast( job.data() ); + if ( partJob ) + { + Partition* p = partJob->partition(); + + if ( p->fileSystem().type() == FileSystem::Type::Lvm2_PV ) + m_lvmPVs << p; + else if ( p->fileSystem().type() == FileSystem::Type::Luks ) + { + // Encrypted LVM PVs + FileSystem* innerFS = static_cast(&p->fileSystem())->innerFS(); + + if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) + m_lvmPVs << p; + } +#ifdef WITH_KPMCOREGT33 + else if ( p->fileSystem().type() == FileSystem::Type::Luks2 ) + { + // Encrypted LVM PVs + FileSystem* innerFS = static_cast(&p->fileSystem())->innerFS(); + + if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) + m_lvmPVs << p; + } +#endif + } + } + } +} + PartitionCoreModule::DeviceInfo* PartitionCoreModule::infoForDevice( const Device* device ) const { @@ -575,8 +763,36 @@ PartitionCoreModule::revert() void PartitionCoreModule::revertAllDevices() { - foreach ( DeviceInfo* devInfo, m_deviceInfos ) - revertDevice( devInfo->device.data() ); + for ( auto it = m_deviceInfos.begin(); it != m_deviceInfos.end(); ) + { + // In new VGs device info, there will be always a CreateVolumeGroupJob as the first job in jobs list + if ( dynamic_cast( ( *it )->device.data() ) ) + { + ( *it )->isAvailable = true; + + if ( !( *it )->jobs.empty() ) + { + CreateVolumeGroupJob* vgJob = dynamic_cast( ( *it )->jobs[0].data() ); + + if ( vgJob ) + { + vgJob->undoPreview(); + + ( *it )->forgetChanges(); + + m_deviceModel->removeDevice( ( *it )->device.data() ); + + it = m_deviceInfos.erase( it ); + + continue; + } + } + } + + revertDevice( ( *it )->device.data() ); + ++it; + } + refresh(); } @@ -586,6 +802,7 @@ PartitionCoreModule::revertDevice( Device* dev ) { QMutexLocker locker( &m_revertMutex ); DeviceInfo* devInfo = infoForDevice( dev ); + if ( !devInfo ) return; devInfo->forgetChanges(); @@ -597,8 +814,13 @@ PartitionCoreModule::revertDevice( Device* dev ) m_deviceModel->swapDevice( dev, newDev ); QList< Device* > devices; - foreach ( auto info, m_deviceInfos ) - devices.append( info->device.data() ); + for ( auto info : m_deviceInfos ) + { + if ( info->device.data()->type() != Device::Type::Disk_Device ) + continue; + else + devices.append( info->device.data() ); + } m_bootLoaderModel->init( devices ); @@ -638,6 +860,16 @@ PartitionCoreModule::isDirty() return m_isDirty; } +bool +PartitionCoreModule::isVGdeactivated( LvmDevice *device ) +{ + for ( DeviceInfo* deviceInfo : m_deviceInfos ) + if ( device == deviceInfo->device.data() && !deviceInfo->isAvailable ) + return true; + + return false; +} + QList< PartitionCoreModule::SummaryInfo > PartitionCoreModule::createSummaryInfo() const { diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 49564dad1..d61311c8a 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -24,6 +24,7 @@ #include "Typedefs.h" // KPMcore +#include #include // Qt @@ -111,6 +112,14 @@ public: void createPartition( Device* device, Partition* partition, PartitionTable::Flags flags = PartitionTable::FlagNone ); + void createVolumeGroup( QString &vgName, QVector< const Partition* > pvList, qint32 peSize ); + + void resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList ); + + void deactivateVolumeGroup( LvmDevice* device ); + + void removeVolumeGroup( LvmDevice* device ); + void deletePartition( Device* device, Partition* partition ); void formatPartition( Device* device, Partition* partition ); @@ -132,6 +141,12 @@ public: QList< Partition* > efiSystemPartitions() const; + QVector< const Partition* > lvmPVs() const; + + bool hasVGwithThisName( const QString& name ) const; + + bool isInVG( const Partition* partition ) const; + /** * @brief findPartitionByMountPoint returns a Partition* for a given mount point. * @param mountPoint the mount point to find a partition for. @@ -151,6 +166,8 @@ public: bool isDirty(); // true if there are pending changes, otherwise false + bool isVGdeactivated( LvmDevice* device ); + /** * To be called when a partition has been altered, but only for changes * which do not affect its size, because changes which affect the partition size @@ -189,11 +206,15 @@ private: const QScopedPointer< Device > immutableDevice; QList< Calamares::job_ptr > jobs; + // To check if LVM VGs are deactivated + bool isAvailable; + void forgetChanges(); bool isDirty() const; }; QList< DeviceInfo* > m_deviceInfos; QList< Partition* > m_efiSystemPartitions; + QVector< const Partition* > m_lvmPVs; DeviceModel* m_deviceModel; BootLoaderModel* m_bootLoaderModel; @@ -205,6 +226,7 @@ private: void updateHasRootMountPoint(); void updateIsDirty(); void scanForEfiSystemPartitions(); + void scanForLVMPVs(); DeviceInfo* infoForDevice( const Device* ) const; diff --git a/src/modules/partition/core/PartitionInfo.cpp b/src/modules/partition/core/PartitionInfo.cpp index 9cc03fc9d..3a2e5bbd3 100644 --- a/src/modules/partition/core/PartitionInfo.cpp +++ b/src/modules/partition/core/PartitionInfo.cpp @@ -20,6 +20,7 @@ #include "core/PartitionInfo.h" // KPMcore +#include #include // Qt @@ -80,6 +81,9 @@ reset( Partition* partition ) bool isDirty( Partition* partition ) { + if ( LvmDevice::s_DirtyPVs.contains( partition ) ) + return true; + return !mountPoint( partition ).isEmpty() || format( partition ) || flags( partition ) != partition->activeFlags(); diff --git a/src/modules/partition/gui/CreateVolumeGroupDialog.cpp b/src/modules/partition/gui/CreateVolumeGroupDialog.cpp new file mode 100644 index 000000000..fe5c40be8 --- /dev/null +++ b/src/modules/partition/gui/CreateVolumeGroupDialog.cpp @@ -0,0 +1,56 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "CreateVolumeGroupDialog.h" + +#include +#include + +#include +#include +#include + +CreateVolumeGroupDialog::CreateVolumeGroupDialog( QString& vgName, + QVector< const Partition* >& selectedPVs, + QVector< const Partition* > pvList, + qint64& pSize, + QWidget* parent ) + : VolumeGroupBaseDialog( vgName, pvList, parent ) + , m_selectedPVs( selectedPVs ) + , m_peSize( pSize ) +{ + setWindowTitle( "Create Volume Group" ); + + peSize()->setValue( pSize ); + + vgType()->setEnabled( false ); +} + +void +CreateVolumeGroupDialog::accept() +{ + QString& name = vgNameValue(); + name = vgName()->text(); + + m_selectedPVs << checkedItems(); + + qint64& pe = m_peSize; + pe = peSize()->value(); + + QDialog::accept(); +} diff --git a/src/modules/partition/gui/CreateVolumeGroupDialog.h b/src/modules/partition/gui/CreateVolumeGroupDialog.h new file mode 100644 index 000000000..b0d5b874c --- /dev/null +++ b/src/modules/partition/gui/CreateVolumeGroupDialog.h @@ -0,0 +1,41 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef CREATEVOLUMEGROUPDIALOG_H +#define CREATEVOLUMEGROUPDIALOG_H + +#include "gui/VolumeGroupBaseDialog.h" + +class CreateVolumeGroupDialog : public VolumeGroupBaseDialog +{ +public: + CreateVolumeGroupDialog( QString& vgName, + QVector< const Partition* >& selectedPVs, + QVector< const Partition* > pvList, + qint64& pSize, + QWidget* parent ); + + void accept() override; + +private: + QVector< const Partition* >& m_selectedPVs; + + qint64& m_peSize; +}; + +#endif // CREATEVOLUMEGROUPDIALOG_H diff --git a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp new file mode 100644 index 000000000..cd480aa55 --- /dev/null +++ b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp @@ -0,0 +1,36 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "ListPhysicalVolumeWidgetItem.h" + +#include + +ListPhysicalVolumeWidgetItem::ListPhysicalVolumeWidgetItem( const Partition* partition, bool checked ) + : QListWidgetItem(QString("%1 | %2").arg( partition->deviceNode(), Capacity::formatByteSize( partition->capacity() ))) + , m_partition(partition) +{ + setToolTip( partition->deviceNode() ); + setSizeHint( QSize(0, 32) ); + setCheckState( checked ? Qt::Checked : Qt::Unchecked ); +} + +const Partition* +ListPhysicalVolumeWidgetItem::partition() const +{ + return m_partition; +} diff --git a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h new file mode 100644 index 000000000..44ba8c3bf --- /dev/null +++ b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h @@ -0,0 +1,37 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef LISTPHYSICALVOLUMEWIDGETITEM_H +#define LISTPHYSICALVOLUMEWIDGETITEM_H + +#include + +#include + +class ListPhysicalVolumeWidgetItem : public QListWidgetItem +{ +public: + ListPhysicalVolumeWidgetItem( const Partition* partition, bool checked ); + + const Partition* partition() const; + +private: + const Partition* m_partition; +}; + +#endif // LISTPHYSICALVOLUMEWIDGETITEM_H diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 09badbf94..994adc3e8 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -30,7 +30,9 @@ #include "core/PartUtils.h" #include "core/KPMHelpers.h" #include "gui/CreatePartitionDialog.h" +#include "gui/CreateVolumeGroupDialog.h" #include "gui/EditExistingPartitionDialog.h" +#include "gui/ResizeVolumeGroupDialog.h" #include "gui/ScanningDialog.h" #include "ui_PartitionPage.h" @@ -45,6 +47,8 @@ // KPMcore #include #include +#include +#include // Qt #include @@ -102,6 +106,10 @@ PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) connect( m_ui->partitionTreeView, &QAbstractItemView::doubleClicked, this, &PartitionPage::onPartitionViewActivated ); connect( m_ui->revertButton, &QAbstractButton::clicked, this, &PartitionPage::onRevertClicked ); + connect( m_ui->newVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onNewVolumeGroupClicked ); + connect( m_ui->resizeVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onResizeVolumeGroupClicked ); + connect( m_ui->deactivateVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onDeactivateVolumeGroupClicked ); + connect( m_ui->removeVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onRemoveVolumeGroupClicked ); connect( m_ui->newPartitionTableButton, &QAbstractButton::clicked, this, &PartitionPage::onNewPartitionTableClicked ); connect( m_ui->createButton, &QAbstractButton::clicked, this, &PartitionPage::onCreateClicked ); connect( m_ui->editButton, &QAbstractButton::clicked, this, &PartitionPage::onEditClicked ); @@ -122,7 +130,8 @@ PartitionPage::~PartitionPage() void PartitionPage::updateButtons() { - bool create = false, createTable = false, edit = false, del = false; + bool create = false, createTable = false, edit = false, del = false, currentDeviceIsVG = false, isDeactivable = false; + bool isRemovable = false, isVGdeactivated = false; QModelIndex index = m_ui->partitionTreeView->currentIndex(); if ( index.isValid() ) @@ -134,6 +143,8 @@ PartitionPage::updateButtons() bool isFree = KPMHelpers::isPartitionFreeSpace( partition ); bool isExtended = partition->roles().has( PartitionRole::Extended ); + bool isInVG = m_core->isInVG( partition ); + create = isFree; // Keep it simple for now: do not support editing extended partitions as // it does not work with our current edit implementation which is @@ -141,8 +152,9 @@ PartitionPage::updateButtons() // because they need to be created *before* creating logical partitions // inside them, so an edit must be applied without altering the job // order. + // TODO: See if LVM PVs can be edited in Calamares edit = !isFree && !isExtended; - del = !isFree; + del = !isFree && !isInVG; } if ( m_ui->deviceComboBox->currentIndex() >= 0 ) @@ -150,12 +162,29 @@ PartitionPage::updateButtons() QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); if ( m_core->deviceModel()->deviceForIndex( deviceIndex )->type() != Device::Type::LVM_Device ) createTable = true; + else + { + currentDeviceIsVG = true; + + LvmDevice* lvmDevice = dynamic_cast(m_core->deviceModel()->deviceForIndex( deviceIndex )); + + isDeactivable = DeactivateVolumeGroupOperation::isDeactivatable( lvmDevice ); + isRemovable = RemoveVolumeGroupOperation::isRemovable( lvmDevice ); + + isVGdeactivated = m_core->isVGdeactivated( lvmDevice ); + + if ( isVGdeactivated ) + m_ui->revertButton->setEnabled( true ); + } } m_ui->createButton->setEnabled( create ); m_ui->editButton->setEnabled( edit ); m_ui->deleteButton->setEnabled( del ); m_ui->newPartitionTableButton->setEnabled( createTable ); + m_ui->resizeVolumeGroupButton->setEnabled( currentDeviceIsVG && !isVGdeactivated ); + m_ui->deactivateVolumeGroupButton->setEnabled( currentDeviceIsVG && isDeactivable && !isVGdeactivated ); + m_ui->removeVolumeGroupButton->setEnabled( currentDeviceIsVG && isRemovable ); } void @@ -204,6 +233,114 @@ PartitionPage::checkCanCreate( Device* device ) return true; // GPT is fine } +void +PartitionPage::onNewVolumeGroupClicked() +{ + QString vgName; + QVector< const Partition* > selectedPVs; + qint64 peSize = 4; + + QVector< const Partition* > availablePVs; + + for ( const Partition* p : m_core->lvmPVs() ) + if ( !m_core->isInVG( p ) ) + availablePVs << p; + + QPointer< CreateVolumeGroupDialog > dlg = new CreateVolumeGroupDialog( vgName, + selectedPVs, + availablePVs, + peSize, + this ); + + if ( dlg->exec() == QDialog::Accepted ) + { + QModelIndex partitionIndex = m_ui->partitionTreeView->currentIndex(); + + if ( partitionIndex.isValid() ) + { + const PartitionModel* model = static_cast< const PartitionModel* >( partitionIndex.model() ); + Q_ASSERT( model ); + Partition* partition = model->partitionForIndex( partitionIndex ); + Q_ASSERT( partition ); + + // Disable delete button if current partition was selected to be in VG + // TODO: Should Calamares edit LVM PVs which are in VGs? + if ( selectedPVs.contains( partition ) ) + m_ui->deleteButton->setEnabled( false ); + } + + QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); + Q_ASSERT( deviceIndex.isValid() ); + + QVariant previousIndexDeviceData = m_core->deviceModel()->data( deviceIndex, Qt::ToolTipRole ); + + // Creating new VG + m_core->createVolumeGroup( vgName, selectedPVs, peSize ); + + // As createVolumeGroup method call resets deviceModel, + // is needed to set the current index in deviceComboBox as the previous one + int previousIndex = m_ui->deviceComboBox->findData( previousIndexDeviceData, Qt::ToolTipRole ); + + m_ui->deviceComboBox->setCurrentIndex( ( previousIndex < 0 ) ? 0 : previousIndex ); + updateFromCurrentDevice(); + } + + delete dlg; +} + +void +PartitionPage::onResizeVolumeGroupClicked() +{ + QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); + LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); + + Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); + + QVector< const Partition* > availablePVs; + QVector< const Partition* > selectedPVs; + + for ( const Partition* p : m_core->lvmPVs() ) + if ( !m_core->isInVG( p ) ) + availablePVs << p; + + QPointer< ResizeVolumeGroupDialog > dlg = new ResizeVolumeGroupDialog( device, + availablePVs, + selectedPVs, + this ); + + if ( dlg->exec() == QDialog::Accepted ) + m_core->resizeVolumeGroup( device, selectedPVs ); + + delete dlg; +} + +void +PartitionPage::onDeactivateVolumeGroupClicked() +{ + QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); + LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); + + Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); + + m_core->deactivateVolumeGroup( device ); + + updateFromCurrentDevice(); + + PartitionModel* model = m_core->partitionModelForDevice( device ); + model->update(); +} + +void +PartitionPage::onRemoveVolumeGroupClicked() +{ + QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); + LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); + + Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); + + m_core->removeVolumeGroup( device ); +} + void PartitionPage::onCreateClicked() { @@ -272,7 +409,7 @@ PartitionPage::onRevertClicked() int oldIndex = m_ui->deviceComboBox->currentIndex(); m_core->revertAllDevices(); - m_ui->deviceComboBox->setCurrentIndex( oldIndex ); + m_ui->deviceComboBox->setCurrentIndex( ( oldIndex < 0 ) ? 0 : oldIndex ); updateFromCurrentDevice(); } ), [ this ]{ diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h index 2ab7f5839..70d8ccdfb 100644 --- a/src/modules/partition/gui/PartitionPage.h +++ b/src/modules/partition/gui/PartitionPage.h @@ -51,6 +51,10 @@ private: PartitionCoreModule* m_core; void updateButtons(); void onNewPartitionTableClicked(); + void onNewVolumeGroupClicked(); + void onResizeVolumeGroupClicked(); + void onDeactivateVolumeGroupClicked(); + void onRemoveVolumeGroupClicked(); void onCreateClicked(); void onEditClicked(); void onDeleteClicked(); diff --git a/src/modules/partition/gui/PartitionPage.ui b/src/modules/partition/gui/PartitionPage.ui index 67ac4fb2d..c028eb513 100644 --- a/src/modules/partition/gui/PartitionPage.ui +++ b/src/modules/partition/gui/PartitionPage.ui @@ -6,7 +6,7 @@ 0 0 - 655 + 684 304 @@ -124,6 +124,38 @@ + + + + + + New Volume Group + + + + + + + Resize Volume Group + + + + + + + Deactivate Volume Group + + + + + + + Remove Volume Group + + + + + @@ -145,7 +177,7 @@ - Install boot &loader on: + I&nstall boot loader on: bootLoaderComboBox diff --git a/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp b/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp new file mode 100644 index 000000000..b3173096d --- /dev/null +++ b/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp @@ -0,0 +1,62 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "ResizeVolumeGroupDialog.h" + +#include "gui/ListPhysicalVolumeWidgetItem.h" + +#include +#include + +#include +#include +#include +#include + +ResizeVolumeGroupDialog::ResizeVolumeGroupDialog( LvmDevice *device, + QVector< const Partition* > availablePVs, + QVector< const Partition* >& selectedPVs, + QWidget* parent ) + : VolumeGroupBaseDialog( device->name(), device->physicalVolumes(), parent ) + , m_selectedPVs( selectedPVs ) +{ + setWindowTitle( "Resize Volume Group" ); + + for ( int i = 0; i < pvList()->count(); i++ ) + pvList()->item(i)->setCheckState( Qt::Checked ); + + for ( const Partition* p : availablePVs ) + pvList()->addItem( new ListPhysicalVolumeWidgetItem( p, false ) ); + + peSize()->setValue( device->peSize() / Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB) ); + + vgName()->setEnabled( false ); + peSize()->setEnabled( false ); + vgType()->setEnabled( false ); + + setUsedSizeValue( device->allocatedPE() * device->peSize() ); + setLVQuantity( device->partitionTable()->children().count() ); +} + +void +ResizeVolumeGroupDialog::accept() +{ + m_selectedPVs << checkedItems(); + + QDialog::accept(); +} diff --git a/src/modules/partition/gui/ResizeVolumeGroupDialog.h b/src/modules/partition/gui/ResizeVolumeGroupDialog.h new file mode 100644 index 000000000..1d6015329 --- /dev/null +++ b/src/modules/partition/gui/ResizeVolumeGroupDialog.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef RESIZEVOLUMEGROUPDIALOG_H +#define RESIZEVOLUMEGROUPDIALOG_H + +#include "gui/VolumeGroupBaseDialog.h" + +class LvmDevice; + +class ResizeVolumeGroupDialog : public VolumeGroupBaseDialog +{ +public: + ResizeVolumeGroupDialog( LvmDevice *device, + QVector< const Partition* > availablePVs, + QVector< const Partition* >& selectedPVs, + QWidget* parent ); + + void accept() override; + +private: + QVector< const Partition* >& m_selectedPVs; +}; + +#endif // RESIZEVOLUMEGROUPDIALOG_H diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.cpp b/src/modules/partition/gui/VolumeGroupBaseDialog.cpp new file mode 100644 index 000000000..a727fe42a --- /dev/null +++ b/src/modules/partition/gui/VolumeGroupBaseDialog.cpp @@ -0,0 +1,184 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "VolumeGroupBaseDialog.h" +#include "ui_VolumeGroupBaseDialog.h" + +#include "gui/ListPhysicalVolumeWidgetItem.h" + +#include + +#include +#include +#include +#include +#include +#include + +VolumeGroupBaseDialog::VolumeGroupBaseDialog( QString& vgName, + QVector< const Partition* > pvList, + QWidget *parent ) + : QDialog(parent) + , ui(new Ui::VolumeGroupBaseDialog) + , m_vgNameValue(vgName) + , m_totalSizeValue(0) + , m_usedSizeValue(0) +{ + ui->setupUi(this); + + for ( const Partition* p : pvList ) + ui->pvList->addItem( new ListPhysicalVolumeWidgetItem( p, false ) ); + + ui->vgType->addItems( QStringList() << "LVM" << "RAID" ); + ui->vgType->setCurrentIndex(0); + + QRegularExpression re(R"(^(?!_|\.)[\w\-.+]+)"); + ui->vgName->setValidator( new QRegularExpressionValidator( re, this ) ); + ui->vgName->setText( m_vgNameValue ); + + updateOkButton(); + updateTotalSize(); + + connect( ui->pvList, &QListWidget::itemChanged, this, + [&](QListWidgetItem*) { + updateTotalSize(); + updateOkButton(); + } ); + + connect( ui->peSize, qOverload(&QSpinBox::valueChanged), this, + [&](int) { + updateTotalSectors(); + updateOkButton(); + }); + + connect( ui->vgName, &QLineEdit::textChanged, this, + [&](const QString&) { + updateOkButton(); + }); +} + +VolumeGroupBaseDialog::~VolumeGroupBaseDialog() +{ + delete ui; +} + +QVector< const Partition* > +VolumeGroupBaseDialog::checkedItems() const +{ + QVector< const Partition* > items; + + for ( int i = 0; i < ui->pvList->count(); i++) { + ListPhysicalVolumeWidgetItem* item = dynamic_cast< ListPhysicalVolumeWidgetItem* >( ui->pvList->item(i) ); + + if ( item && item->checkState() == Qt::Checked ) + items << item->partition(); + } + + return items; +} + +bool +VolumeGroupBaseDialog::isSizeValid() const +{ + return m_totalSizeValue >= m_usedSizeValue; +} + +void +VolumeGroupBaseDialog::updateOkButton() +{ + okButton()->setEnabled(isSizeValid() && + !checkedItems().empty() && + !ui->vgName->text().isEmpty() && + ui->peSize->value() > 0); +} + +void +VolumeGroupBaseDialog::setUsedSizeValue( qint64 usedSize ) +{ + m_usedSizeValue = usedSize; + + ui->usedSize->setText( Capacity::formatByteSize(m_usedSizeValue) ); +} + +void +VolumeGroupBaseDialog::setLVQuantity( qint32 lvQuantity ) +{ + ui->lvQuantity->setText( QString::number( lvQuantity ) ); +} + +void +VolumeGroupBaseDialog::updateTotalSize() +{ + m_totalSizeValue = 0; + + for ( const Partition *p : checkedItems()) + m_totalSizeValue += p->capacity() - p->capacity() % (ui->peSize->value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB)); + + ui->totalSize->setText(Capacity::formatByteSize(m_totalSizeValue)); + + updateTotalSectors(); +} + +void +VolumeGroupBaseDialog::updateTotalSectors() +{ + qint32 totalSectors = 0; + + qint32 extentSize = ui->peSize->value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); + + if ( extentSize > 0 ) + totalSectors = m_totalSizeValue / extentSize; + + ui->totalSectors->setText( QString::number( totalSectors ) ); +} + +QString& +VolumeGroupBaseDialog::vgNameValue() const +{ + return m_vgNameValue; +} + +QLineEdit* +VolumeGroupBaseDialog::vgName() const +{ + return ui->vgName; +} + +QComboBox* +VolumeGroupBaseDialog::vgType() const +{ + return ui->vgType; +} + +QSpinBox* +VolumeGroupBaseDialog::peSize() const +{ + return ui->peSize; +} + +QListWidget* +VolumeGroupBaseDialog::pvList() const +{ + return ui->pvList; +} + +QPushButton* +VolumeGroupBaseDialog::okButton() const +{ + return ui->buttonBox->button( QDialogButtonBox::StandardButton::Ok ); +} diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.h b/src/modules/partition/gui/VolumeGroupBaseDialog.h new file mode 100644 index 000000000..e6011ce62 --- /dev/null +++ b/src/modules/partition/gui/VolumeGroupBaseDialog.h @@ -0,0 +1,81 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef VOLUMEGROUPBASEDIALOG_H +#define VOLUMEGROUPBASEDIALOG_H + +#include + +#include + +namespace Ui { +class VolumeGroupBaseDialog; +} + +class QComboBox; +class QLineEdit; +class QListWidget; +class QSpinBox; + +class VolumeGroupBaseDialog : public QDialog +{ + Q_OBJECT + +public: + explicit VolumeGroupBaseDialog( QString& vgName, + QVector< const Partition* > pvList, + QWidget* parent = nullptr ); + ~VolumeGroupBaseDialog(); + +protected: + virtual void updateOkButton(); + + void setUsedSizeValue( qint64 usedSize ); + + void setLVQuantity( qint32 lvQuantity ); + + void updateTotalSize(); + + void updateTotalSectors(); + + QVector< const Partition* > checkedItems() const; + + bool isSizeValid() const; + + QString& vgNameValue() const; + + QLineEdit* vgName() const; + + QComboBox* vgType() const; + + QSpinBox* peSize() const; + + QListWidget* pvList() const; + + QPushButton* okButton() const; + +private: + Ui::VolumeGroupBaseDialog* ui; + + QString& m_vgNameValue; + + qint64 m_totalSizeValue; + qint64 m_usedSizeValue; +}; + +#endif // VOLUMEGROUPBASEDIALOG_H diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.ui b/src/modules/partition/gui/VolumeGroupBaseDialog.ui new file mode 100644 index 000000000..b45d204e2 --- /dev/null +++ b/src/modules/partition/gui/VolumeGroupBaseDialog.ui @@ -0,0 +1,206 @@ + + + VolumeGroupBaseDialog + + + + 0 + 0 + 611 + 367 + + + + VolumeGroupDialog + + + + + + List of Physical Volumes + + + + + + + + + + Volume Group Name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Volume Group Type: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Physical Extent Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + MiB + + + 1 + + + 999 + + + 4 + + + + + + + Total Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + --- + + + Qt::AlignCenter + + + + + + + Used Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + --- + + + Qt::AlignCenter + + + + + + + Total Sectors: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + --- + + + Qt::AlignCenter + + + + + + + Quantity of LVs: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + --- + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + VolumeGroupBaseDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + VolumeGroupBaseDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.cpp b/src/modules/partition/jobs/CreateVolumeGroupJob.cpp new file mode 100644 index 000000000..7debd9475 --- /dev/null +++ b/src/modules/partition/jobs/CreateVolumeGroupJob.cpp @@ -0,0 +1,84 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "CreateVolumeGroupJob.h" + +// KPMcore +#include +#include +#include +#include + +CreateVolumeGroupJob::CreateVolumeGroupJob( QString& vgName, QVector< const Partition* > pvList, const qint32 peSize ) + : m_vgName(vgName) + , m_pvList(pvList) + , m_peSize(peSize) +{ + +} + +QString +CreateVolumeGroupJob::prettyName() const +{ + return tr( "Create new volume group named %1." ) + .arg( m_vgName ); +} + +QString +CreateVolumeGroupJob::prettyDescription() const +{ + return tr( "Create new volume group named %1." ) + .arg( m_vgName ); +} + +QString +CreateVolumeGroupJob::prettyStatusMessage() const +{ + return tr( "Creating new volume group named %1." ) + .arg( m_vgName ); +} + +Calamares::JobResult +CreateVolumeGroupJob::exec() +{ + Report report( nullptr ); + + CreateVolumeGroupOperation op( m_vgName, m_pvList, m_peSize ); + + op.setStatus( Operation::StatusRunning ); + + QString message = tr( "The installer failed to create a volume group named '%1'.").arg( m_vgName ); + if (op.execute(report)) + return Calamares::JobResult::ok(); + + return Calamares::JobResult::error(message, report.toText()); +} + +void +CreateVolumeGroupJob::updatePreview() +{ + LvmDevice::s_DirtyPVs << m_pvList; +} + +void +CreateVolumeGroupJob::undoPreview() +{ + for ( const auto& pv : m_pvList ) + if ( LvmDevice::s_DirtyPVs.contains( pv )) + LvmDevice::s_DirtyPVs.removeAll( pv ); +} diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.h b/src/modules/partition/jobs/CreateVolumeGroupJob.h new file mode 100644 index 000000000..9e84fba73 --- /dev/null +++ b/src/modules/partition/jobs/CreateVolumeGroupJob.h @@ -0,0 +1,47 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef CREATEVOLUMEGROUPJOB_H +#define CREATEVOLUMEGROUPJOB_H + +#include + +#include + +#include + +class CreateVolumeGroupJob : public Calamares::Job +{ +public: + CreateVolumeGroupJob( QString& vgName, QVector< const Partition* > pvList, const qint32 peSize ); + + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + Calamares::JobResult exec() override; + + void updatePreview(); + void undoPreview(); + +private: + QString m_vgName; + QVector< const Partition* > m_pvList; + qint32 m_peSize; +}; + +#endif // CREATEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp b/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp new file mode 100644 index 000000000..f772b3e5a --- /dev/null +++ b/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp @@ -0,0 +1,69 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "DeactivateVolumeGroupJob.h" + +#include +#include +#include + +DeactivateVolumeGroupJob::DeactivateVolumeGroupJob( LvmDevice* device ) + : m_device( device ) +{ + +} + +QString +DeactivateVolumeGroupJob::prettyName() const +{ + return tr( "Deactivate volume group named %1." ) + .arg( m_device->name() ); +} + +QString +DeactivateVolumeGroupJob::prettyDescription() const +{ + return tr( "Deactivate volume group named %1." ) + .arg( m_device->name() ); +} + +QString +DeactivateVolumeGroupJob::prettyStatusMessage() const +{ + return tr( "Deactivate volume group named %1." ) + .arg( m_device->name() ); +} + +Calamares::JobResult +DeactivateVolumeGroupJob::exec() +{ + Report report( nullptr ); + + DeactivateVolumeGroupOperation op( *m_device ); + + op.setStatus( Operation::OperationStatus::StatusRunning ); + + QString message = tr( "The installer failed to deactivate a volume group named %1." ).arg( m_device->name() ); + if ( op.execute( report ) ) + { + op.preview(); + return Calamares::JobResult::ok(); + } + + return Calamares::JobResult::error(message, report.toText()); +} diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h new file mode 100644 index 000000000..5b59c2c4f --- /dev/null +++ b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef DEACTIVATEVOLUMEGROUPJOB_H +#define DEACTIVATEVOLUMEGROUPJOB_H + +#include "Job.h" + +class LvmDevice; + +class DeactivateVolumeGroupJob : public Calamares::Job +{ +public: + DeactivateVolumeGroupJob( LvmDevice* device ); + + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + Calamares::JobResult exec() override; + +private: + LvmDevice* m_device; +}; + +#endif // DEACTIVATEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp b/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp new file mode 100644 index 000000000..69b510754 --- /dev/null +++ b/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp @@ -0,0 +1,66 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "RemoveVolumeGroupJob.h" + +#include +#include +#include + +RemoveVolumeGroupJob::RemoveVolumeGroupJob( LvmDevice* device ) + : m_device( device ) +{ + +} + +QString +RemoveVolumeGroupJob::prettyName() const +{ + return tr( "Remove Volume Group named %1." ) + .arg( m_device->name() ); +} + +QString +RemoveVolumeGroupJob::prettyDescription() const +{ + return tr( "Remove Volume Group named %1.") + .arg( m_device->name() ); +} + +QString +RemoveVolumeGroupJob::prettyStatusMessage() const +{ + return tr( "Remove Volume Group named %1." ) + .arg( m_device->name() ); +} + +Calamares::JobResult +RemoveVolumeGroupJob::exec() +{ + Report report( nullptr ); + + RemoveVolumeGroupOperation op( *m_device ); + + op.setStatus( Operation::OperationStatus::StatusRunning ); + + QString message = tr( "The installer failed to remove a volume group named '%1'." ).arg( m_device->name() ); + if ( op.execute( report ) ) + return Calamares::JobResult::ok(); + + return Calamares::JobResult::error(message, report.toText()); +} diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.h b/src/modules/partition/jobs/RemoveVolumeGroupJob.h new file mode 100644 index 000000000..426dde7fb --- /dev/null +++ b/src/modules/partition/jobs/RemoveVolumeGroupJob.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef REMOVEVOLUMEGROUPJOB_H +#define REMOVEVOLUMEGROUPJOB_H + +#include + +class LvmDevice; + +class RemoveVolumeGroupJob : public Calamares::Job +{ +public: + RemoveVolumeGroupJob( LvmDevice* device ); + + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + Calamares::JobResult exec() override; + +private: + LvmDevice* m_device; +}; + +#endif // REMOVEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp b/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp new file mode 100644 index 000000000..bc7ef264d --- /dev/null +++ b/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp @@ -0,0 +1,101 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "ResizeVolumeGroupJob.h" + +// KPMcore +#include +#include +#include +#include + +ResizeVolumeGroupJob::ResizeVolumeGroupJob( LvmDevice* device, QVector< const Partition* >& partitionList ) + : m_device( device ) + , m_partitionList( partitionList ) +{ + +} + +QString +ResizeVolumeGroupJob::prettyName() const +{ + return tr( "Resize volume group named %1 from %2 to %3." ) + .arg( m_device->name() ) + .arg( currentPartitions() ) + .arg( targetPartitions() ); +} + +QString +ResizeVolumeGroupJob::prettyDescription() const +{ + return tr( "Resize volume group named %1 from %2 to %3." ) + .arg( m_device->name() ) + .arg( currentPartitions() ) + .arg( targetPartitions() ); +} + +QString +ResizeVolumeGroupJob::prettyStatusMessage() const +{ + return tr( "Resize volume group named %1 from %2 to %3." ) + .arg( m_device->name() ) + .arg( currentPartitions() ) + .arg( targetPartitions() ); +} + +Calamares::JobResult +ResizeVolumeGroupJob::exec() +{ + Report report( nullptr ); + + ResizeVolumeGroupOperation op( *m_device, m_partitionList ); + + op.setStatus( Operation::OperationStatus::StatusRunning ); + + QString message = tr( "The installer failed to resize a volume group named '%1'." ).arg( m_device->name() ); + if ( op.execute( report ) ) + return Calamares::JobResult::ok(); + + return Calamares::JobResult::error( message, report.toText() ); +} + +QString +ResizeVolumeGroupJob::currentPartitions() const +{ + QString result; + + for ( const Partition *p : m_device->physicalVolumes() ) + result += p->deviceNode() + ", "; + + result.chop(2); + + return result; +} + +QString +ResizeVolumeGroupJob::targetPartitions() const +{ + QString result; + + for ( const Partition *p : m_partitionList ) + result += p->deviceNode() + ", "; + + result.chop(2); + + return result; +} diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.h b/src/modules/partition/jobs/ResizeVolumeGroupJob.h new file mode 100644 index 000000000..380bee416 --- /dev/null +++ b/src/modules/partition/jobs/ResizeVolumeGroupJob.h @@ -0,0 +1,48 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Caio Jordão Carvalho + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef RESIZEVOLUMEGROUPJOB_H +#define RESIZEVOLUMEGROUPJOB_H + +#include + +#include + +class LvmDevice; +class Partition; + +class ResizeVolumeGroupJob : public Calamares::Job +{ +public: + ResizeVolumeGroupJob( LvmDevice* device, QVector< const Partition* >& partitionList ); + + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + Calamares::JobResult exec() override; + +private: + QString currentPartitions() const; + QString targetPartitions() const; + +private: + LvmDevice* m_device; + QVector< const Partition* > m_partitionList; +}; + +#endif // RESIZEVOLUMEGROUPJOB_H