[partition][zfs] Add support for zfs encryption
This commit is contained in:
parent
074941e2bd
commit
6da9bad272
@ -243,7 +243,8 @@ CreatePartitionDialog::getNewlyCreatedPartition()
|
||||
// does so, to set up the partition for create-and-then-set-flags.
|
||||
Partition* partition = nullptr;
|
||||
QString luksPassphrase = m_ui->encryptWidget->passphrase();
|
||||
if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty() )
|
||||
if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty()
|
||||
&& fsType != FileSystem::Zfs )
|
||||
{
|
||||
partition = KPMHelpers::createNewEncryptedPartition(
|
||||
m_parent, *m_device, m_role, fsType, fsLabel, first, last, luksPassphrase, PartitionTable::Flags() );
|
||||
@ -254,6 +255,13 @@ CreatePartitionDialog::getNewlyCreatedPartition()
|
||||
m_parent, *m_device, m_role, fsType, fsLabel, first, last, PartitionTable::Flags() );
|
||||
}
|
||||
|
||||
// For zfs, we let the zfs module handle the encryption but we need to make the passphrase available to that module
|
||||
if( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty()
|
||||
&& fsType == FileSystem::Zfs )
|
||||
{
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "encryptphrase", luksPassphrase );
|
||||
}
|
||||
|
||||
if ( m_device->type() == Device::Type::LVM_Device )
|
||||
{
|
||||
partition->setPartitionPath( m_device->deviceNode() + QStringLiteral( "/" )
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "JobQueue.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
ZfsJob::ZfsJob( QObject* parent )
|
||||
: Calamares::CppJob( parent )
|
||||
{
|
||||
@ -30,6 +32,56 @@ ZfsJob::prettyName() const
|
||||
return tr( "Create ZFS pools and datasets" );
|
||||
}
|
||||
|
||||
ZfsResult
|
||||
ZfsJob::CreateZpool( QString deviceName, QString poolName, QString poolOptions, bool encrypt, QString passphrase ) const
|
||||
{
|
||||
// zfs doesn't wait for the devices so pause for 2 seconds to ensure we give time for the device files to be created
|
||||
QString command;
|
||||
if ( encrypt )
|
||||
{
|
||||
command = "sleep 2 ; echo \"" + passphrase + "\" | zpool create " + poolOptions
|
||||
+ " -O encryption=aes-256-gcm -O keyformat=passphrase " + poolName + " " + deviceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
command = "sleep 2 ; zpool create " + poolOptions + " " + poolName + " " + deviceName;
|
||||
}
|
||||
|
||||
// We use a qProcess instead of runCommand so the password will not end up in the logs
|
||||
QProcess process;
|
||||
|
||||
process.setProcessChannelMode( QProcess::MergedChannels );
|
||||
cDebug() << Logger::SubEntry << "Running zpool create";
|
||||
|
||||
process.start( "sh", QStringList() << "-c" << command );
|
||||
|
||||
if ( !process.waitForStarted() )
|
||||
{
|
||||
return { false, tr( "zpool create process failed to start" ) };
|
||||
}
|
||||
|
||||
if ( !process.waitForFinished( 5000 ) )
|
||||
{
|
||||
return { false, tr( "Process for zpool create timed out" ) };
|
||||
}
|
||||
|
||||
QString output = QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed();
|
||||
|
||||
if ( process.exitStatus() == QProcess::CrashExit )
|
||||
{
|
||||
return { false, tr( "The output from the crash was: " ) + output };
|
||||
}
|
||||
|
||||
auto exitcode = process.exitCode();
|
||||
if ( exitcode != 0 )
|
||||
{
|
||||
cWarning() << "Failed to run zpool create. The output was: " + output;
|
||||
return { false, tr( "Failed to create zpool on " ) + deviceName };
|
||||
}
|
||||
|
||||
return { true, QString() };
|
||||
}
|
||||
|
||||
Calamares::JobResult
|
||||
ZfsJob::exec()
|
||||
{
|
||||
@ -78,15 +130,20 @@ ZfsJob::exec()
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create the zpool
|
||||
// zfs doesn't wait for the devices so pause for 2 seconds to ensure we give time for the device files to be created
|
||||
auto r
|
||||
= system->runCommand( { "sh", "-c", "sleep 2 ; zpool create " + m_poolOptions + " " + m_poolName + " " + deviceName },
|
||||
std::chrono::seconds( 10 ) );
|
||||
if ( r.getExitCode() != 0 )
|
||||
ZfsResult zfsResult;
|
||||
if ( gs->contains( "encryptphrase" ) )
|
||||
{
|
||||
return Calamares::JobResult::error( tr( "zpool failure" ),
|
||||
tr( "Failed to create zpool on " + deviceName.toLocal8Bit() ) );
|
||||
zfsResult
|
||||
= CreateZpool( deviceName, m_poolName, m_poolOptions, true, gs->value( "encryptphrase" ).toString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
zfsResult = CreateZpool( deviceName, m_poolName, m_poolOptions, false );
|
||||
}
|
||||
|
||||
if ( !zfsResult.success )
|
||||
{
|
||||
return Calamares::JobResult::error( tr( "Failed to create zpool" ), zfsResult.failureMessage );
|
||||
}
|
||||
|
||||
// Create the datasets
|
||||
@ -105,12 +162,12 @@ ZfsJob::exec()
|
||||
|
||||
// Create the dataset. We set canmount=no regardless of the setting for now.
|
||||
// It is modified to the correct value in the mount module to ensure mount order is maintained
|
||||
r = system->runCommand( { "sh",
|
||||
"-c",
|
||||
"zfs create " + m_datasetOptions
|
||||
+ " -o canmount=off -o mountpoint=" + datasetMap[ "mountpoint" ].toString()
|
||||
+ " " + m_poolName + "/" + datasetMap[ "dsName" ].toString() },
|
||||
std::chrono::seconds( 10 ) );
|
||||
auto r = system->runCommand( { "sh",
|
||||
"-c",
|
||||
"zfs create " + m_datasetOptions + " -o canmount=off -o mountpoint="
|
||||
+ datasetMap[ "mountpoint" ].toString() + " " + m_poolName + "/"
|
||||
+ datasetMap[ "dsName" ].toString() },
|
||||
std::chrono::seconds( 10 ) );
|
||||
if ( r.getExitCode() != 0 )
|
||||
{
|
||||
cWarning() << "Failed to create dataset" << datasetMap[ "dsName" ].toString();
|
||||
@ -124,7 +181,7 @@ ZfsJob::exec()
|
||||
// If the list isn't empty, add it to global storage
|
||||
if ( !datasetList.isEmpty() )
|
||||
{
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "zfs", datasetList );
|
||||
gs->insert( "zfs", datasetList );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,11 @@
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
struct ZfsResult {
|
||||
bool success;
|
||||
QString failureMessage;
|
||||
};
|
||||
|
||||
/** @brief Create zpools and zfs datasets
|
||||
*
|
||||
*/
|
||||
@ -43,6 +48,20 @@ private:
|
||||
QString m_datasetOptions;
|
||||
|
||||
QList<QVariant> m_datasets;
|
||||
|
||||
/** @brief Creates a zpool based on the provided arguments
|
||||
*
|
||||
* Creates a zpool
|
||||
* @p deviceName is a full path to the device the zpool should be created on
|
||||
* @p poolName is a string containing the name of the pool to create
|
||||
* @p poolOptions are the options to pass to zpool create
|
||||
* @p encrypt is a boolean which determines if the pool should be encrypted
|
||||
* @p passphrase is a string continaing the passphrase
|
||||
*
|
||||
*/
|
||||
ZfsResult CreateZpool(QString deviceName, QString poolName, QString poolOptions, bool encrypt, QString passphrase = QString() ) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( ZfsJobFactory )
|
||||
|
Loading…
Reference in New Issue
Block a user