[luksopenswaphookcfg] Port to C++
Merge pull request #1845 from calamares/issue-1659 FIXES #1659 FIXES #1644
This commit is contained in:
commit
7fc2859f23
22
src/modules/luksopenswaphookcfg/CMakeLists.txt
Normal file
22
src/modules/luksopenswaphookcfg/CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
||||
# === This file is part of Calamares - <https://calamares.io> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
# Because LUKS Open Swap Hook (Job) is such a mouthful, we'll
|
||||
# use LOSH all over the place as a shorthand.
|
||||
calamares_add_plugin( luksopenswaphook
|
||||
TYPE job
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
LOSHJob.cpp
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
calamares_add_test(
|
||||
luksopenswaphooktest
|
||||
SOURCES
|
||||
LOSHJob.cpp
|
||||
Tests.cpp
|
||||
)
|
66
src/modules/luksopenswaphookcfg/LOSHInfo.h
Normal file
66
src/modules/luksopenswaphookcfg/LOSHInfo.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
#ifndef LUKSOPENSWAPHOOKCFG_LOSHINFO_H
|
||||
#define LUKSOPENSWAPHOOKCFG_LOSHINFO_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/** @brief Information needed to create a suitable config file
|
||||
*
|
||||
* The LUKS swap configuration has a handful of keys that need to
|
||||
* be written to the config file. This struct holds those keys
|
||||
* and can find the key values from Global Storage (where the
|
||||
* *partition* module sets them).
|
||||
*/
|
||||
struct LOSHInfo
|
||||
{
|
||||
// Member names copied from Python code
|
||||
QString swap_outer_uuid;
|
||||
QString swap_mapper_name;
|
||||
QString mountable_keyfile_device;
|
||||
QString swap_device_path;
|
||||
QString keyfile_device_mount_options;
|
||||
|
||||
bool isValid() const { return !swap_device_path.isEmpty(); }
|
||||
|
||||
/** @brief Helper method for doing key-value replacements
|
||||
*
|
||||
* Given a named @p key (e.g. "duck", or "swap_device"), returns the
|
||||
* value set for that key. Invalid keys (e.g. "duck") return an empty string.
|
||||
*/
|
||||
QString replacementFor( const QString& key ) const
|
||||
{
|
||||
if ( key == QStringLiteral( "swap_device" ) )
|
||||
{
|
||||
return swap_device_path;
|
||||
}
|
||||
if ( key == QStringLiteral( "crypt_swap_name" ) )
|
||||
{
|
||||
return swap_mapper_name;
|
||||
}
|
||||
if ( key == QStringLiteral( "keyfile_device" ) )
|
||||
{
|
||||
return mountable_keyfile_device;
|
||||
}
|
||||
if ( key == QStringLiteral( "keyfile_filename" ) )
|
||||
{
|
||||
return QStringLiteral( "crypto_keyfile.bin" );
|
||||
}
|
||||
if ( key == QStringLiteral( "keyfile_device_mount_options" ) )
|
||||
{
|
||||
return keyfile_device_mount_options;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
/** @brief Creates a struct from information already set in GS
|
||||
*
|
||||
*/
|
||||
static LOSHInfo fromGlobalStorage();
|
||||
};
|
||||
|
||||
#endif
|
180
src/modules/luksopenswaphookcfg/LOSHJob.cpp
Normal file
180
src/modules/luksopenswaphookcfg/LOSHJob.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
#include "LOSHJob.h"
|
||||
|
||||
#include "LOSHInfo.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Permissions.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
#include "utils/String.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
LOSHJob::LOSHJob( QObject* parent )
|
||||
: Calamares::CppJob( parent )
|
||||
{
|
||||
}
|
||||
|
||||
LOSHJob::~LOSHJob() {}
|
||||
|
||||
|
||||
QString
|
||||
LOSHJob::prettyName() const
|
||||
{
|
||||
return tr( "Configuring encrypted swap." );
|
||||
}
|
||||
|
||||
STATICTEST QString
|
||||
get_assignment_part( const QString& line )
|
||||
{
|
||||
static QRegularExpression re( "^[# \\t]*([A-Za-z_]+)[ \\t]*=" );
|
||||
auto m = re.match( line );
|
||||
if ( m.hasMatch() )
|
||||
{
|
||||
return m.captured( 1 );
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
/** Writes the config file at @p path
|
||||
*
|
||||
* NOTE: @p path is relative to the target system, not an absolute path.
|
||||
*/
|
||||
STATICTEST void
|
||||
write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info )
|
||||
{
|
||||
if ( info.isValid() )
|
||||
{
|
||||
for ( auto& line : contents )
|
||||
{
|
||||
const QString key = get_assignment_part( line );
|
||||
QString replacement = info.replacementFor( key );
|
||||
if ( !replacement.isEmpty() )
|
||||
{
|
||||
line.clear();
|
||||
line.append( QStringLiteral( "%1=%2" ).arg( key, replacement ) );
|
||||
}
|
||||
}
|
||||
cDebug() << "Writing" << contents.length() << "line configuration to" << path;
|
||||
// \n between each two lines, and a \n at the end
|
||||
CalamaresUtils::System::instance()->createTargetFile(
|
||||
path, contents.join( '\n' ).append( '\n' ).toUtf8(), CalamaresUtils::System::WriteMode::Overwrite );
|
||||
}
|
||||
else
|
||||
{
|
||||
cDebug() << "Will not write an invalid configuration to" << path;
|
||||
}
|
||||
}
|
||||
|
||||
Calamares::JobResult
|
||||
LOSHJob::exec()
|
||||
{
|
||||
const auto* sys = CalamaresUtils::System::instance();
|
||||
if ( !sys )
|
||||
{
|
||||
return Calamares::JobResult::internalError(
|
||||
"LuksOpenSwapHook", tr( "No target system available." ), Calamares::JobResult::InvalidConfiguration );
|
||||
}
|
||||
|
||||
Calamares::GlobalStorage* gs
|
||||
= Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
|
||||
if ( !gs || gs->value( "rootMountPoint" ).toString().isEmpty() )
|
||||
{
|
||||
return Calamares::JobResult::internalError(
|
||||
"LuksOpenSwapHook", tr( "No rootMountPoint is set." ), Calamares::JobResult::InvalidConfiguration );
|
||||
}
|
||||
if ( m_configFilePath.isEmpty() )
|
||||
{
|
||||
return Calamares::JobResult::internalError(
|
||||
"LuksOpenSwapHook", tr( "No configFilePath is set." ), Calamares::JobResult::InvalidConfiguration );
|
||||
}
|
||||
|
||||
QStringList contents = sys->readTargetFile( m_configFilePath );
|
||||
if ( contents.isEmpty() )
|
||||
{
|
||||
contents << QStringLiteral( "# swap_device=" ) << QStringLiteral( "# crypt_swap_name=" )
|
||||
<< QStringLiteral( "# keyfile_device=" ) << QStringLiteral( "# keyfile_filename=" )
|
||||
<< QStringLiteral( "# keyfile_device_mount_options" );
|
||||
}
|
||||
|
||||
write_openswap_conf( m_configFilePath, contents, LOSHInfo::fromGlobalStorage() );
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
||||
void
|
||||
LOSHJob::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
m_configFilePath = CalamaresUtils::getString(
|
||||
configurationMap, QStringLiteral( "configFilePath" ), QStringLiteral( "/etc/openswap.conf" ) );
|
||||
}
|
||||
|
||||
STATICTEST void
|
||||
globalStoragePartitionInfo( Calamares::GlobalStorage* gs, LOSHInfo& info )
|
||||
{
|
||||
if ( !gs )
|
||||
{
|
||||
return;
|
||||
}
|
||||
QVariantList l = gs->value( "partitions" ).toList();
|
||||
if ( l.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( const auto& pv : l )
|
||||
{
|
||||
const QVariantMap partition = pv.toMap();
|
||||
if ( !partition.isEmpty() )
|
||||
{
|
||||
QString mountPoint = partition.value( "mountPoint" ).toString();
|
||||
QString fileSystem = partition.value( "fs" ).toString();
|
||||
QString luksMapperName = partition.value( "luksMapperName" ).toString();
|
||||
// if partition["fs"] == "linuxswap" and "luksMapperName" in partition:
|
||||
if ( fileSystem == QStringLiteral( "linuxswap" ) && !luksMapperName.isEmpty() )
|
||||
{
|
||||
info.swap_outer_uuid = partition.value( "luksUuid" ).toString();
|
||||
info.swap_mapper_name = luksMapperName;
|
||||
}
|
||||
else if ( mountPoint == QStringLiteral( "/" ) && !luksMapperName.isEmpty() )
|
||||
{
|
||||
|
||||
info.mountable_keyfile_device = QStringLiteral( "/dev/mapper/" ) + luksMapperName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !info.mountable_keyfile_device.isEmpty() && !info.swap_outer_uuid.isEmpty() )
|
||||
{
|
||||
info.swap_device_path = QStringLiteral( "/dev/disk/by-uuid/" ) + info.swap_outer_uuid;
|
||||
}
|
||||
|
||||
QString btrfsRootSubvolume = gs->value( "btrfsRootSubvolume" ).toString();
|
||||
if ( !btrfsRootSubvolume.isEmpty() )
|
||||
{
|
||||
CalamaresUtils::removeLeading( btrfsRootSubvolume, '/' );
|
||||
info.keyfile_device_mount_options
|
||||
= QStringLiteral( "keyfile_device_mount_options=--options=subvol=" ) + btrfsRootSubvolume;
|
||||
}
|
||||
}
|
||||
|
||||
LOSHInfo
|
||||
LOSHInfo::fromGlobalStorage()
|
||||
{
|
||||
LOSHInfo i {};
|
||||
globalStoragePartitionInfo(
|
||||
Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr, i );
|
||||
return i;
|
||||
}
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( LOSHJobFactory, registerPlugin< LOSHJob >(); )
|
37
src/modules/luksopenswaphookcfg/LOSHJob.h
Normal file
37
src/modules/luksopenswaphookcfg/LOSHJob.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
#ifndef LUKSOPENSWAPHOOKCFG_LOSHJOB_H
|
||||
#define LUKSOPENSWAPHOOKCFG_LOSHJOB_H
|
||||
|
||||
#include "CppJob.h"
|
||||
#include "DllMacro.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
class PLUGINDLLEXPORT LOSHJob : public Calamares::CppJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LOSHJob( QObject* parent = nullptr );
|
||||
~LOSHJob() override;
|
||||
|
||||
QString prettyName() const override;
|
||||
|
||||
Calamares::JobResult exec() override;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||
|
||||
private:
|
||||
QString m_configFilePath;
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( LOSHJobFactory )
|
||||
|
||||
#endif
|
253
src/modules/luksopenswaphookcfg/Tests.cpp
Normal file
253
src/modules/luksopenswaphookcfg/Tests.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LOSHInfo.h"
|
||||
#include "LOSHJob.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
// LOSH = LUKS Open Swap Hook (Job)
|
||||
|
||||
// Implementation details
|
||||
extern QString get_assignment_part( const QString& line );
|
||||
extern void write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info );
|
||||
|
||||
class LOSHTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LOSHTests();
|
||||
~LOSHTests() override {}
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testAssignmentExtraction_data();
|
||||
void testAssignmentExtraction();
|
||||
|
||||
void testLOSHInfo();
|
||||
void testConfigWriting();
|
||||
void testJob();
|
||||
};
|
||||
|
||||
LOSHTests::LOSHTests() {}
|
||||
|
||||
void
|
||||
LOSHTests::initTestCase()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
cDebug() << "LOSH test started.";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LOSHTests::testAssignmentExtraction_data()
|
||||
{
|
||||
QTest::addColumn< QString >( "line" );
|
||||
QTest::addColumn< QString >( "match" );
|
||||
|
||||
QTest::newRow( "empty" ) << QString() << QString();
|
||||
QTest::newRow( "comment-only1" ) << QStringLiteral( "# " ) << QString();
|
||||
QTest::newRow( "comment-only2" ) << QStringLiteral( "###" ) << QString();
|
||||
QTest::newRow( "comment-only3" ) << QStringLiteral( "# # #" ) << QString();
|
||||
|
||||
QTest::newRow( "comment-text" ) << QStringLiteral( "# NOTE:" ) << QString();
|
||||
QTest::newRow( "comment-story" ) << QStringLiteral( "# This is a shell comment" ) << QString();
|
||||
// We look for assignments, but only for single-words
|
||||
QTest::newRow( "comment-space-eq" ) << QStringLiteral( "# Check that a = b" ) << QString();
|
||||
|
||||
|
||||
QTest::newRow( "assignment1" ) << QStringLiteral( "a=1" ) << QStringLiteral( "a" );
|
||||
QTest::newRow( "assignment2" ) << QStringLiteral( "a = 1" ) << QStringLiteral( "a" );
|
||||
QTest::newRow( "assignment3" ) << QStringLiteral( "# a=1" ) << QStringLiteral( "a" );
|
||||
QTest::newRow( "assignment4" ) << QStringLiteral( "cows = 12" ) << QStringLiteral( "cows" );
|
||||
QTest::newRow( "assignment5" ) << QStringLiteral( "# # cows=1" ) << QStringLiteral( "cows" );
|
||||
QTest::newRow( "assignment6" ) << QStringLiteral( "# moose='cool' # not cows" ) << QStringLiteral( "moose" );
|
||||
QTest::newRow( "assignment7" ) << QStringLiteral( " moose=cows=42" ) << QStringLiteral( "moose" );
|
||||
QTest::newRow( "assignment8" ) << QStringLiteral( "#swap_device=/dev/something" )
|
||||
<< QStringLiteral( "swap_device" );
|
||||
QTest::newRow( "assignment9" ) << QStringLiteral( "# swap_device=/dev/something" )
|
||||
<< QStringLiteral( "swap_device" );
|
||||
QTest::newRow( "assignment10" ) << QStringLiteral( "swap_device=/dev/something" )
|
||||
<< QStringLiteral( "swap_device" );
|
||||
}
|
||||
|
||||
void
|
||||
LOSHTests::testAssignmentExtraction()
|
||||
{
|
||||
QFETCH( QString, line );
|
||||
QFETCH( QString, match );
|
||||
|
||||
QCOMPARE( get_assignment_part( line ), match );
|
||||
}
|
||||
|
||||
static CalamaresUtils::System*
|
||||
file_setup( const QTemporaryDir& tempRoot )
|
||||
{
|
||||
CalamaresUtils::System* ss = CalamaresUtils::System::instance();
|
||||
if ( !ss )
|
||||
{
|
||||
ss = new CalamaresUtils::System( true );
|
||||
}
|
||||
|
||||
Calamares::GlobalStorage* gs
|
||||
= Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
|
||||
if ( !gs )
|
||||
{
|
||||
cDebug() << "Creating new JobQueue";
|
||||
(void)new Calamares::JobQueue();
|
||||
gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
|
||||
}
|
||||
if ( gs )
|
||||
{
|
||||
// Working with a rootMountPoint set
|
||||
gs->insert( "rootMountPoint", tempRoot.path() );
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
static void
|
||||
make_valid_loshinfo( LOSHInfo& i )
|
||||
{
|
||||
i.swap_outer_uuid = QStringLiteral( "UUID-0000" );
|
||||
i.swap_mapper_name = QStringLiteral( "/dev/mapper/0000" );
|
||||
i.swap_device_path = QStringLiteral( "/dev/sda0" );
|
||||
i.mountable_keyfile_device = QStringLiteral( "/dev/ada0p0s0" );
|
||||
}
|
||||
|
||||
void
|
||||
LOSHTests::testLOSHInfo()
|
||||
{
|
||||
LOSHInfo i {};
|
||||
QVERIFY( !i.isValid() );
|
||||
|
||||
make_valid_loshinfo( i );
|
||||
QVERIFY( i.isValid() );
|
||||
QCOMPARE( i.replacementFor( QStringLiteral( "swap_device" ) ), QStringLiteral( "/dev/sda0" ) );
|
||||
QCOMPARE( i.replacementFor( QStringLiteral( "duck" ) ), QString() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LOSHTests::testConfigWriting()
|
||||
{
|
||||
QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) );
|
||||
QVERIFY( tempRoot.isValid() );
|
||||
auto* ss = file_setup( tempRoot );
|
||||
QVERIFY( ss );
|
||||
QVERIFY( Calamares::JobQueue::instance()->globalStorage() );
|
||||
QVERIFY( QFile::exists( tempRoot.path() ) );
|
||||
QVERIFY( QFileInfo( tempRoot.path() ).isDir() );
|
||||
|
||||
const QString targetFilePath = QStringLiteral( "losh.conf" );
|
||||
const QString filePath = tempRoot.filePath( targetFilePath );
|
||||
QStringList contents { QStringLiteral( "# Calamares demo" ),
|
||||
QStringLiteral( "# swap_device=a thing" ),
|
||||
QStringLiteral( "# duck duck swap_device=another" ) };
|
||||
|
||||
// When the information is invalid, file contents are unchanged,
|
||||
// and no file is written either.
|
||||
LOSHInfo i {};
|
||||
QVERIFY( !i.isValid() );
|
||||
QVERIFY( !QFile::exists( filePath ) );
|
||||
write_openswap_conf( targetFilePath, contents, i ); // Invalid i
|
||||
QVERIFY( !QFile::exists( filePath ) );
|
||||
QCOMPARE( contents.length(), 3 );
|
||||
QCOMPARE( contents.at( 1 ).left( 4 ), QStringLiteral( "# s" ) );
|
||||
|
||||
// Can we write there at all?
|
||||
QFile derp( filePath );
|
||||
QVERIFY( derp.open( QIODevice::WriteOnly ) );
|
||||
QVERIFY( derp.write( "xx", 2 ) );
|
||||
derp.close();
|
||||
QVERIFY( QFile::exists( filePath ) );
|
||||
QVERIFY( QFile::remove( filePath ) );
|
||||
|
||||
// Once the information is valid, though, the file is written
|
||||
make_valid_loshinfo( i );
|
||||
QVERIFY( i.isValid() );
|
||||
QVERIFY( !QFile::exists( filePath ) );
|
||||
write_openswap_conf( targetFilePath, contents, i ); // Now it is valid
|
||||
QVERIFY( QFile::exists( filePath ) );
|
||||
QCOMPARE( contents.length(), 3 );
|
||||
QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/sda0" ) ); // expected key value
|
||||
QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/sda0" ) ); // expected line
|
||||
|
||||
// readLine() returns with newlines-added
|
||||
QFile f( filePath );
|
||||
QVERIFY( f.open( QIODevice::ReadOnly ) );
|
||||
QCOMPARE( f.readLine(), QStringLiteral( "# Calamares demo\n" ) );
|
||||
QCOMPARE( f.readLine(), QStringLiteral( "swap_device=/dev/sda0\n" ) );
|
||||
QCOMPARE( f.readLine(), QStringLiteral( "# duck duck swap_device=another\n" ) );
|
||||
QCOMPARE( f.readLine(), QString() );
|
||||
QVERIFY( f.atEnd() );
|
||||
|
||||
// Note how the contents is updated on every write_openswap_conf()
|
||||
i.swap_device_path = QStringLiteral( "/dev/zram/0.zram" );
|
||||
write_openswap_conf( targetFilePath, contents, i ); // Still valid
|
||||
QCOMPARE( contents.length(), 3 );
|
||||
QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/zram/0.zram" ) ); // expected key value
|
||||
QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/zram/0.zram" ) ); // expected line
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LOSHTests::testJob()
|
||||
{
|
||||
QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) );
|
||||
QVERIFY( tempRoot.isValid() );
|
||||
auto* ss = file_setup( tempRoot );
|
||||
QVERIFY( ss );
|
||||
Calamares::GlobalStorage* gs
|
||||
= Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
|
||||
QVERIFY( gs );
|
||||
|
||||
{
|
||||
QDir d( tempRoot.path() );
|
||||
d.mkdir( "etc" );
|
||||
}
|
||||
|
||||
QVERIFY( !LOSHInfo::fromGlobalStorage().isValid() );
|
||||
QVariantList outerPartition;
|
||||
QVariantMap innerPartition;
|
||||
innerPartition.insert( "mountPoint", "/" );
|
||||
innerPartition.insert( "fs", "ext4" );
|
||||
innerPartition.insert( "luksMapperName", "root" );
|
||||
innerPartition.insert( "luksUUID", "0000" );
|
||||
outerPartition.append( innerPartition );
|
||||
innerPartition.remove( "mountPoint" );
|
||||
innerPartition.insert( "fs", "linuxswap" );
|
||||
innerPartition.insert( "luksMapperName", "swap" );
|
||||
innerPartition.insert( "luksUuid", "0001" );
|
||||
outerPartition.append( innerPartition );
|
||||
gs->insert( "partitions", outerPartition );
|
||||
QVERIFY( LOSHInfo::fromGlobalStorage().isValid() );
|
||||
|
||||
LOSHJob j;
|
||||
j.setConfigurationMap( QVariantMap() );
|
||||
auto jobresult = j.exec();
|
||||
QVERIFY( jobresult );
|
||||
|
||||
{
|
||||
QFile f( tempRoot.filePath( "etc/openswap.conf" ) );
|
||||
QVERIFY( f.exists() );
|
||||
QVERIFY( f.open( QIODevice::ReadOnly ) );
|
||||
cDebug() << f.readAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN( LOSHTests )
|
||||
|
||||
#include "utils/moc-warnings.h"
|
||||
|
||||
#include "Tests.moc"
|
@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# === This file is part of Calamares - <https://calamares.io> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2016 Teo Mrnjavac <teo@kde.org>
|
||||
# SPDX-FileCopyrightText: 2017 Alf Gaida <agaida@siduction.org>
|
||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Calamares is Free Software: see the License-Identifier above.
|
||||
#
|
||||
|
||||
import libcalamares
|
||||
import os.path
|
||||
|
||||
|
||||
import gettext
|
||||
_ = gettext.translation("calamares-python",
|
||||
localedir=libcalamares.utils.gettext_path(),
|
||||
languages=libcalamares.utils.gettext_languages(),
|
||||
fallback=True).gettext
|
||||
|
||||
|
||||
def pretty_name():
|
||||
return _("Configuring encrypted swap.")
|
||||
|
||||
|
||||
def write_openswap_conf(partitions, root_mount_point, openswap_conf_path):
|
||||
swap_outer_uuid = ""
|
||||
swap_mapper_name = ""
|
||||
mountable_keyfile_device = ""
|
||||
|
||||
for partition in partitions:
|
||||
if partition["fs"] == "linuxswap" and "luksMapperName" in partition:
|
||||
swap_outer_uuid = partition["luksUuid"]
|
||||
swap_mapper_name = partition["luksMapperName"]
|
||||
|
||||
elif partition["mountPoint"] == "/" and "luksMapperName" in partition:
|
||||
mountable_keyfile_device = (
|
||||
"/dev/mapper/{!s}".format(partition["luksMapperName"])
|
||||
)
|
||||
|
||||
if not mountable_keyfile_device or not swap_outer_uuid:
|
||||
return None
|
||||
|
||||
swap_device_path = "/dev/disk/by-uuid/{!s}".format(swap_outer_uuid)
|
||||
|
||||
lines = []
|
||||
with open(os.path.join(root_mount_point,
|
||||
openswap_conf_path), 'r') as openswap_file:
|
||||
lines = [x.strip() for x in openswap_file.readlines()]
|
||||
|
||||
for i in range(len(lines)):
|
||||
if lines[i].startswith("swap_device"):
|
||||
lines[i] = "swap_device={!s}".format(swap_device_path)
|
||||
|
||||
elif lines[i].startswith("crypt_swap_name"):
|
||||
lines[i] = "crypt_swap_name={!s}".format(swap_mapper_name)
|
||||
|
||||
elif lines[i].startswith("keyfile_device"):
|
||||
lines[i] = "keyfile_device={!s}".format(mountable_keyfile_device)
|
||||
|
||||
elif lines[i].startswith("keyfile_filename"):
|
||||
lines[i] = "keyfile_filename=crypto_keyfile.bin"
|
||||
|
||||
elif lines[i].startswith("#keyfile_device_mount_options"):
|
||||
if libcalamares.globalstorage.contains("btrfsRootSubvolume"):
|
||||
btrfs_root_subvolume = libcalamares.globalstorage.value("btrfsRootSubvolume")
|
||||
lines[i] = "keyfile_device_mount_options=--options=subvol=" + btrfs_root_subvolume.lstrip("/")
|
||||
|
||||
with open(os.path.join(root_mount_point,
|
||||
openswap_conf_path), 'w') as openswap_file:
|
||||
openswap_file.write("\n".join(lines) + "\n")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
This module sets up the openswap hook for a resumable encrypted swap.
|
||||
:return:
|
||||
"""
|
||||
|
||||
root_mount_point = libcalamares.globalstorage.value("rootMountPoint")
|
||||
openswap_conf_path = libcalamares.job.configuration["configFilePath"]
|
||||
partitions = libcalamares.globalstorage.value("partitions")
|
||||
|
||||
if not partitions:
|
||||
libcalamares.utils.warning("partitions is empty, {!s}".format(partitions))
|
||||
return (_("Configuration Error"),
|
||||
_("No partitions are defined for <pre>{!s}</pre> to use.").format("luksopenswaphookcfg"))
|
||||
if not root_mount_point:
|
||||
libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point))
|
||||
return (_("Configuration Error"),
|
||||
_("No root mount point is given for <pre>{!s}</pre> to use.").format("luksopenswaphookcfg"))
|
||||
|
||||
openswap_conf_path = openswap_conf_path.lstrip('/')
|
||||
|
||||
return write_openswap_conf(partitions, root_mount_point, openswap_conf_path)
|
@ -1,7 +0,0 @@
|
||||
# SPDX-FileCopyrightText: no
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
---
|
||||
type: "job"
|
||||
name: "luksopenswaphookcfg"
|
||||
interface: "python"
|
||||
script: "main.py"
|
Loading…
Reference in New Issue
Block a user