|
|
|
@ -41,6 +41,7 @@
|
|
|
|
|
#include "partition/PartitionIterator.h"
|
|
|
|
|
#include "partition/PartitionQuery.h"
|
|
|
|
|
#include "utils/Logger.h"
|
|
|
|
|
#include "utils/Traits.h"
|
|
|
|
|
#include "utils/Variant.h"
|
|
|
|
|
|
|
|
|
|
// KPMcore
|
|
|
|
@ -97,6 +98,89 @@ private:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//- DeviceInfo ---------------------------------------------
|
|
|
|
|
// Some jobs have an updatePreview some don't
|
|
|
|
|
DECLARE_HAS_METHOD( updatePreview )
|
|
|
|
|
|
|
|
|
|
template < typename Job >
|
|
|
|
|
void
|
|
|
|
|
updatePreview( Job* job, const std::true_type& )
|
|
|
|
|
{
|
|
|
|
|
job->updatePreview();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < typename Job >
|
|
|
|
|
void
|
|
|
|
|
updatePreview( Job* job, const std::false_type& )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < typename Job >
|
|
|
|
|
void
|
|
|
|
|
updatePreview( Job* job )
|
|
|
|
|
{
|
|
|
|
|
updatePreview( job, has_updatePreview< Job > {} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Owns the Device, PartitionModel and the jobs
|
|
|
|
|
*/
|
|
|
|
|
struct PartitionCoreModule::DeviceInfo
|
|
|
|
|
{
|
|
|
|
|
DeviceInfo( Device* );
|
|
|
|
|
~DeviceInfo();
|
|
|
|
|
QScopedPointer< Device > device;
|
|
|
|
|
QScopedPointer< PartitionModel > partitionModel;
|
|
|
|
|
const QScopedPointer< Device > immutableDevice;
|
|
|
|
|
|
|
|
|
|
// To check if LVM VGs are deactivated
|
|
|
|
|
bool isAvailable;
|
|
|
|
|
|
|
|
|
|
void forgetChanges();
|
|
|
|
|
bool isDirty() const;
|
|
|
|
|
|
|
|
|
|
const Calamares::JobList& jobs() const { return m_jobs; }
|
|
|
|
|
|
|
|
|
|
/** @brief Take the jobs of the given type that apply to @p partition
|
|
|
|
|
*
|
|
|
|
|
* Returns a job pointer to the job that has just been removed.
|
|
|
|
|
*/
|
|
|
|
|
template < typename Job >
|
|
|
|
|
Calamares::job_ptr takeJob( Partition* partition )
|
|
|
|
|
{
|
|
|
|
|
for ( auto it = m_jobs.begin(); it != m_jobs.end(); )
|
|
|
|
|
{
|
|
|
|
|
Job* job = qobject_cast< Job* >( it->data() );
|
|
|
|
|
if ( job && job->partition() == partition )
|
|
|
|
|
{
|
|
|
|
|
Calamares::job_ptr p = *it;
|
|
|
|
|
it = m_jobs.erase( it );
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Calamares::job_ptr( nullptr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Add a job of given type to the job list
|
|
|
|
|
*/
|
|
|
|
|
template < typename Job, typename... Args >
|
|
|
|
|
Calamares::Job* makeJob( Args... a )
|
|
|
|
|
{
|
|
|
|
|
auto* job = new Job( device.get(), a... );
|
|
|
|
|
updatePreview( job );
|
|
|
|
|
m_jobs << Calamares::job_ptr( job );
|
|
|
|
|
return job;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Calamares::JobList m_jobs;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PartitionCoreModule::DeviceInfo::DeviceInfo( Device* _device )
|
|
|
|
|
: device( _device )
|
|
|
|
|
, partitionModel( new PartitionModel )
|
|
|
|
@ -111,7 +195,7 @@ PartitionCoreModule::DeviceInfo::~DeviceInfo() {}
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::DeviceInfo::forgetChanges()
|
|
|
|
|
{
|
|
|
|
|
jobs.clear();
|
|
|
|
|
m_jobs.clear();
|
|
|
|
|
for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it )
|
|
|
|
|
{
|
|
|
|
|
PartitionInfo::reset( *it );
|
|
|
|
@ -123,16 +207,18 @@ PartitionCoreModule::DeviceInfo::forgetChanges()
|
|
|
|
|
bool
|
|
|
|
|
PartitionCoreModule::DeviceInfo::isDirty() const
|
|
|
|
|
{
|
|
|
|
|
if ( !jobs.isEmpty() )
|
|
|
|
|
if ( !m_jobs.isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it )
|
|
|
|
|
{
|
|
|
|
|
if ( PartitionInfo::isDirty( *it ) )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -284,36 +370,30 @@ PartitionCoreModule::immutableDeviceCopy( const Device* device )
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::createPartitionTable( Device* device, PartitionTable::TableType type )
|
|
|
|
|
{
|
|
|
|
|
DeviceInfo* info = infoForDevice( device );
|
|
|
|
|
if ( info )
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
if ( deviceInfo )
|
|
|
|
|
{
|
|
|
|
|
// Creating a partition table wipes all the disk, so there is no need to
|
|
|
|
|
// keep previous changes
|
|
|
|
|
info->forgetChanges();
|
|
|
|
|
deviceInfo->forgetChanges();
|
|
|
|
|
|
|
|
|
|
OperationHelper helper( partitionModelForDevice( device ), this );
|
|
|
|
|
CreatePartitionTableJob* job = new CreatePartitionTableJob( device, type );
|
|
|
|
|
job->updatePreview();
|
|
|
|
|
info->jobs << Calamares::job_ptr( job );
|
|
|
|
|
deviceInfo->makeJob< CreatePartitionTableJob >( type );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::createPartition( Device* device, Partition* partition, PartitionTable::Flags flags )
|
|
|
|
|
{
|
|
|
|
|
auto deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
|
|
|
|
|
OperationHelper helper( partitionModelForDevice( device ), this );
|
|
|
|
|
CreatePartitionJob* job = new CreatePartitionJob( device, partition );
|
|
|
|
|
job->updatePreview();
|
|
|
|
|
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
deviceInfo->makeJob< CreatePartitionJob >( partition );
|
|
|
|
|
|
|
|
|
|
if ( flags != KPM_PARTITION_FLAG( None ) )
|
|
|
|
|
{
|
|
|
|
|
SetPartFlagsJob* fJob = new SetPartFlagsJob( device, partition, flags );
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( fJob );
|
|
|
|
|
deviceInfo->makeJob< SetPartFlagsJob >( partition, flags );
|
|
|
|
|
PartitionInfo::setFlags( partition, flags );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -327,49 +407,39 @@ PartitionCoreModule::createVolumeGroup( QString& vgName, QVector< const Partitio
|
|
|
|
|
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 );
|
|
|
|
|
|
|
|
|
|
deviceInfo->makeJob< CreateVolumeGroupJob >( vgName, pvList, peSize );
|
|
|
|
|
refreshAfterModelChange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList )
|
|
|
|
|
{
|
|
|
|
|
DeviceInfo* deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
|
|
|
|
|
ResizeVolumeGroupJob* job = new ResizeVolumeGroupJob( device, pvList );
|
|
|
|
|
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
|
|
|
|
|
deviceInfo->makeJob< ResizeVolumeGroupJob >( device, pvList );
|
|
|
|
|
refreshAfterModelChange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::deactivateVolumeGroup( LvmDevice* device )
|
|
|
|
|
{
|
|
|
|
|
DeviceInfo* deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
|
|
|
|
|
deviceInfo->isAvailable = false;
|
|
|
|
|
|
|
|
|
|
// TODO: this leaks
|
|
|
|
|
DeactivateVolumeGroupJob* job = new DeactivateVolumeGroupJob( device );
|
|
|
|
|
|
|
|
|
|
// DeactivateVolumeGroupJob needs to be immediately called
|
|
|
|
@ -381,20 +451,16 @@ PartitionCoreModule::deactivateVolumeGroup( LvmDevice* device )
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::removeVolumeGroup( LvmDevice* device )
|
|
|
|
|
{
|
|
|
|
|
DeviceInfo* deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
|
|
|
|
|
RemoveVolumeGroupJob* job = new RemoveVolumeGroupJob( device );
|
|
|
|
|
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
|
|
|
|
|
deviceInfo->makeJob< RemoveVolumeGroupJob >( device );
|
|
|
|
|
refreshAfterModelChange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::deletePartition( Device* device, Partition* partition )
|
|
|
|
|
{
|
|
|
|
|
auto deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
|
|
|
|
|
OperationHelper helper( partitionModelForDevice( device ), this );
|
|
|
|
@ -417,29 +483,23 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition )
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Calamares::JobList& jobs = deviceInfo->jobs;
|
|
|
|
|
const Calamares::JobList& jobs = deviceInfo->jobs();
|
|
|
|
|
if ( partition->state() == KPM_PARTITION_STATE( New ) )
|
|
|
|
|
{
|
|
|
|
|
// First remove matching SetPartFlagsJobs
|
|
|
|
|
for ( auto it = jobs.begin(); it != jobs.end(); )
|
|
|
|
|
{
|
|
|
|
|
SetPartFlagsJob* job = qobject_cast< SetPartFlagsJob* >( it->data() );
|
|
|
|
|
if ( job && job->partition() == partition )
|
|
|
|
|
// Take all the SetPartFlagsJob from the list and delete them
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
it = jobs.erase( it );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
auto job_ptr = deviceInfo->takeJob< SetPartFlagsJob >( partition );
|
|
|
|
|
if ( job_ptr.data() )
|
|
|
|
|
{
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} while ( false );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find matching CreatePartitionJob
|
|
|
|
|
auto it = std::find_if( jobs.begin(), jobs.end(), [partition]( Calamares::job_ptr job ) {
|
|
|
|
|
CreatePartitionJob* createJob = qobject_cast< CreatePartitionJob* >( job.data() );
|
|
|
|
|
return createJob && createJob->partition() == partition;
|
|
|
|
|
} );
|
|
|
|
|
if ( it == jobs.end() )
|
|
|
|
|
auto job_ptr = deviceInfo->takeJob< CreatePartitionJob >( partition );
|
|
|
|
|
if ( !job_ptr.data() )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << "Failed to find a CreatePartitionJob matching the partition to remove";
|
|
|
|
|
return;
|
|
|
|
@ -452,7 +512,6 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
device->partitionTable()->updateUnallocated( *device );
|
|
|
|
|
jobs.erase( it );
|
|
|
|
|
// The partition is no longer referenced by either a job or the device
|
|
|
|
|
// partition list, so we have to delete it
|
|
|
|
|
delete partition;
|
|
|
|
@ -460,61 +519,49 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition )
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Remove any PartitionJob on this partition
|
|
|
|
|
for ( auto it = jobs.begin(); it != jobs.end(); )
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
PartitionJob* job = qobject_cast< PartitionJob* >( it->data() );
|
|
|
|
|
if ( job && job->partition() == partition )
|
|
|
|
|
auto job_ptr = deviceInfo->takeJob< PartitionJob >( partition );
|
|
|
|
|
if ( job_ptr.data() )
|
|
|
|
|
{
|
|
|
|
|
it = jobs.erase( it );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
DeletePartitionJob* job = new DeletePartitionJob( device, partition );
|
|
|
|
|
job->updatePreview();
|
|
|
|
|
jobs << Calamares::job_ptr( job );
|
|
|
|
|
} while ( false );
|
|
|
|
|
|
|
|
|
|
deviceInfo->makeJob< DeletePartitionJob >( partition );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::formatPartition( Device* device, Partition* partition )
|
|
|
|
|
{
|
|
|
|
|
auto deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
OperationHelper helper( partitionModelForDevice( device ), this );
|
|
|
|
|
|
|
|
|
|
FormatPartitionJob* job = new FormatPartitionJob( device, partition );
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
deviceInfo->makeJob< FormatPartitionJob >( partition );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::resizePartition( Device* device, Partition* partition, qint64 first, qint64 last )
|
|
|
|
|
{
|
|
|
|
|
auto deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
OperationHelper helper( partitionModelForDevice( device ), this );
|
|
|
|
|
|
|
|
|
|
ResizePartitionJob* job = new ResizePartitionJob( device, partition, first, last );
|
|
|
|
|
job->updatePreview();
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
deviceInfo->makeJob< ResizePartitionJob >( partition, first, last );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PartitionCoreModule::setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags )
|
|
|
|
|
{
|
|
|
|
|
auto deviceInfo = infoForDevice( device );
|
|
|
|
|
auto* deviceInfo = infoForDevice( device );
|
|
|
|
|
Q_ASSERT( deviceInfo );
|
|
|
|
|
OperationHelper( partitionModelForDevice( device ), this );
|
|
|
|
|
|
|
|
|
|
SetPartFlagsJob* job = new SetPartFlagsJob( device, partition, flags );
|
|
|
|
|
deviceInfo->jobs << Calamares::job_ptr( job );
|
|
|
|
|
deviceInfo->makeJob< SetPartFlagsJob >( partition, flags );
|
|
|
|
|
PartitionInfo::setFlags( partition, flags );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Calamares::JobList
|
|
|
|
|
PartitionCoreModule::jobs() const
|
|
|
|
|
PartitionCoreModule::jobs( const Config* config ) const
|
|
|
|
|
{
|
|
|
|
|
Calamares::JobList lst;
|
|
|
|
|
QList< Device* > devices;
|
|
|
|
@ -542,10 +589,10 @@ PartitionCoreModule::jobs() const
|
|
|
|
|
|
|
|
|
|
for ( auto info : m_deviceInfos )
|
|
|
|
|
{
|
|
|
|
|
lst << info->jobs;
|
|
|
|
|
lst << info->jobs();
|
|
|
|
|
devices << info->device.data();
|
|
|
|
|
}
|
|
|
|
|
lst << Calamares::job_ptr( new FillGlobalStorageJob( devices, m_bootLoaderInstallPath ) );
|
|
|
|
|
lst << Calamares::job_ptr( new FillGlobalStorageJob( config, devices, m_bootLoaderInstallPath ) );
|
|
|
|
|
|
|
|
|
|
return lst;
|
|
|
|
|
}
|
|
|
|
@ -596,7 +643,7 @@ PartitionCoreModule::dumpQueue() const
|
|
|
|
|
for ( auto info : m_deviceInfos )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << "## Device:" << info->device->name();
|
|
|
|
|
for ( auto job : info->jobs )
|
|
|
|
|
for ( const auto& job : info->jobs() )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << "-" << job->prettyName();
|
|
|
|
|
}
|
|
|
|
@ -736,7 +783,7 @@ PartitionCoreModule::scanForLVMPVs()
|
|
|
|
|
|
|
|
|
|
for ( DeviceInfo* d : m_deviceInfos )
|
|
|
|
|
{
|
|
|
|
|
for ( auto job : d->jobs )
|
|
|
|
|
for ( const auto& job : d->jobs() )
|
|
|
|
|
{
|
|
|
|
|
// Including new LVM PVs
|
|
|
|
|
CreatePartitionJob* partJob = dynamic_cast< CreatePartitionJob* >( job.data() );
|
|
|
|
@ -963,9 +1010,9 @@ PartitionCoreModule::revertAllDevices()
|
|
|
|
|
{
|
|
|
|
|
( *it )->isAvailable = true;
|
|
|
|
|
|
|
|
|
|
if ( !( *it )->jobs.empty() )
|
|
|
|
|
if ( !( *it )->jobs().empty() )
|
|
|
|
|
{
|
|
|
|
|
CreateVolumeGroupJob* vgJob = dynamic_cast< CreateVolumeGroupJob* >( ( *it )->jobs[ 0 ].data() );
|
|
|
|
|
CreateVolumeGroupJob* vgJob = dynamic_cast< CreateVolumeGroupJob* >( ( *it )->jobs().first().data() );
|
|
|
|
|
|
|
|
|
|
if ( vgJob )
|
|
|
|
|
{
|
|
|
|
|