[zfs] Initial commit for zfs module

This commit is contained in:
dalto 2021-11-06 09:44:27 -05:00
parent 7faf4f30df
commit e24d14c512
5 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# === This file is part of Calamares - <https://calamares.io> ===
#
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: BSD-2-Clause
#
calamares_add_plugin( zfs
TYPE job
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
ZfsJob.cpp
SHARED_LIB
)

118
src/modules/zfs/ZfsJob.cpp Normal file
View File

@ -0,0 +1,118 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Evan James <dalto@fastmail.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "ZfsJob.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "utils/Variant.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "Settings.h"
ZfsJob::ZfsJob( QObject* parent )
: Calamares::CppJob( parent )
{
}
ZfsJob::~ZfsJob() {}
QString
ZfsJob::prettyName() const
{
return tr( "Create ZFS pools and datasets" );
}
Calamares::JobResult
ZfsJob::exec()
{
QList< QVariant > partitions;
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
if ( gs && gs->contains( "partitions" ) && gs->value( "partitions" ).canConvert( QVariant::List ) )
{
partitions = gs->value( "partitions" ).toList();
}
else
{
cWarning() << "No *partitions* defined.";
return Calamares::JobResult::internalError( tr( "Configuration Error" ),
tr( "No partitions are available for Zfs." ),
Calamares::JobResult::InvalidConfiguration );
}
const CalamaresUtils::System* system = CalamaresUtils::System::instance();
for ( auto& partition : qAsConst( partitions ) )
{
QVariantMap pMap;
if ( partition.canConvert( QVariant::Map ) )
pMap = partition.toMap();
// If it isn't a zfs partition, ignore it
if ( pMap[ "fsName" ] != "zfs" )
continue;
// Find the best device identifier, if one isn't available, skip this partition
QString deviceName;
if ( pMap[ "partuuid" ].toString() != "" )
deviceName = "/dev/disk/by-partuuid/" + pMap[ "partuuid" ].toString().toLower();
else if ( pMap[ "device" ].toString() != "" )
deviceName = pMap[ "device" ].toString().toLower();
else
continue;
// Create the zpool
auto r
= system->runCommand( { "sh", "-c", "zpool create " + m_poolOptions + " " + m_poolName + " " + deviceName },
std::chrono::seconds( 10 ) );
if ( r.getExitCode() != 0 )
return Calamares::JobResult::error( "message", "Failed to create zpool on " + deviceName );
// Create the datasets
for ( const auto& dataset : qAsConst( m_datasets ) )
{
QVariantMap dsMap = dataset.toMap();
// Make sure all values are valid
if ( dsMap[ "dsName" ].toString().isEmpty() || dsMap[ "mountpoint" ].toString().isEmpty()
|| dsMap[ "canMount" ].toString().isEmpty() )
{
cWarning() << "Bad dataset entry";
continue;
}
// 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=" + dsMap[ "mountpoint" ].toString() + " "
+ m_poolName + "/" + dsMap[ "dsName" ].toString() },
std::chrono::seconds( 10 ) );
if ( r.getExitCode() != 0 )
cWarning() << "Failed to create dataset" << dsMap[ "dsName" ].toString();
}
}
return Calamares::JobResult::ok();
}
void
ZfsJob::setConfigurationMap( const QVariantMap& map )
{
m_poolName = CalamaresUtils::getString( map, "poolName" );
m_poolOptions = CalamaresUtils::getString( map, "poolOptions" );
m_datasetOptions = CalamaresUtils::getString( map, "datasetOptions" );
m_datasets = CalamaresUtils::getList( map, "datasets" );
}
CALAMARES_PLUGIN_FACTORY_DEFINITION( ZfsJobFactory, registerPlugin< ZfsJob >(); )

50
src/modules/zfs/ZfsJob.h Normal file
View File

@ -0,0 +1,50 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Evan James <dalto@fastmail.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef ZFSJOB_H
#define ZFSJOB_H
#include <QObject>
#include <QStringList>
#include <QVariantMap>
#include "CppJob.h"
#include "utils/PluginFactory.h"
#include "DllMacro.h"
/** @brief Create zpools and zfs datasets
*
*/
class PLUGINDLLEXPORT ZfsJob : public Calamares::CppJob
{
Q_OBJECT
public:
explicit ZfsJob( QObject* parent = nullptr );
~ZfsJob() override;
QString prettyName() const override;
Calamares::JobResult exec() override;
void setConfigurationMap( const QVariantMap& configurationMap ) override;
private:
QString m_poolName;
QString m_poolOptions;
QString m_datasetOptions;
QList<QVariant> m_datasets;
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( ZfsJobFactory )
#endif // ZFSJOB_H

38
src/modules/zfs/zfs.conf Normal file
View File

@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# The zfs module creates the zfs pools and datasets
#
#
#
---
# The name to be used for the zpool
poolName: zpcala
# A list of options that will be passed to zpool create
poolOptions: "-f -o ashift=12 -O mountpoint=none -O acltype=posixacl -O relatime=on"
# A list of options that will be passed to zfs create when creating each dataset
# Do not include "canmount" or "mountpoint" as those are set below in the datasets array
datasetOptions: "-o compression=lz4 -o atime=off -o xattr=sa"
# An array of datasets that will be created on the zpool mounted at /
datasets:
- dsName: ROOT
mountpoint: none
canMount: off
- dsName: ROOT/distro
mountpoint: none
canMount: off
- dsName: ROOT/distro/root
mountpoint: /
canMount: noauto
- dsName: ROOT/distro/home
mountpoint: /home
canMount: on
- dsName: ROOT/distro/varcache
mountpoint: /var/cache
canMount: on
- dsName: ROOT/distro/varlog
mountpoint: /var/log
canMount: on

View File

@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: GPL-3.0-or-later
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/zfs
additionalProperties: false
type: object
properties:
poolName: { type: string }
poolOptions: { type: string }
datasetOptions: { type: string }
datasets:
type: array
items:
type: object
additionalProperties: false
properties:
dsName: { type: string }
mountpoint: { type: string }
canMount: { type: string }
required: [ dsName, mountpoint, canmount ]
required: [ poolName, datasets ]