Compare commits

...

39 Commits

Author SHA1 Message Date
Andrius Štikonas b620b0caaf Merge branch 'master' into raid-support 2020-11-14 01:28:46 +00:00
Andrius Štikonas 83571aa0ef Merge branch 'master' into raid-support 2020-10-12 20:51:16 +01:00
Andrius Štikonas 21c685b528 Merge branch 'master' into raid-support 2020-10-03 15:59:04 +01:00
Andrius Štikonas 2d8a800a6d REUSE: SPDX headers for new files in raid-support branch. 2020-10-02 22:05:40 +01:00
Andrius Štikonas 1d3458fb0a Merge branch 'master' into raid-support 2020-10-02 12:11:29 +01:00
Andrius Štikonas 4a52757009 Merge branch 'master' into raid-support 2020-09-17 01:55:09 +01:00
Andrius Štikonas 0fafc228ed Merge branch 'master' into raid-support 2019-10-06 20:13:06 +01:00
Andrius Štikonas fa7d5a200f Merge branch 'master' into raid-support 2019-09-26 23:52:56 +01:00
Caio Carvalho a4d75750f1 Merge branch 'master' into raid-support 2019-04-03 15:28:30 -06:00
Caio Carvalho 5da3eacdc9 Fixing device scanning process 2019-04-03 15:23:09 -06:00
Caio Carvalho a57bd8846e More error checks in mdadmupdateconf helper 2019-03-18 23:12:46 -06:00
Andrius Štikonas 90ebdb9b42 Merge branch 'master' into raid-support 2019-01-12 00:07:21 +00:00
Andrius Štikonas c2ed6634df Merge branch 'master' into raid-support 2019-01-06 17:17:12 +00:00
Caio Carvalho 355c37097a Including fail and remove PV methods for RAID shrinking 2018-10-13 18:27:52 -03:00
Caio Carvalho 6ab2143158 RAID 4, 5, 6 and 10 asks for confirmation during creation 2018-10-13 18:10:37 -03:00
Caio Carvalho daacc0bfb7 Changing volume group resize to support RAID 2018-10-12 16:59:59 -03:00
Caio Carvalho 6a349f7bc8 Avoiding segfaults on device scanning 2018-10-12 15:07:32 -03:00
Caio Carvalho 3ada811de7 RAID partition table needs to be erased before removing 2018-10-12 12:02:49 -03:00
Caio Carvalho ecc5dc8a4f Including RAID removal 2018-10-11 17:51:25 -03:00
Caio Carvalho f269144474 RAID activation operation support 2018-10-11 15:01:07 -03:00
Caio Carvalho 7429ff7527 Loading physical volumes for RAID 2018-10-11 14:36:08 -03:00
Andrius Štikonas 32eacc4db6 Merge branch 'master' into raid-support 2018-08-27 19:50:07 +01:00
Caio Carvalho b47c52b367 Using std::string instead of char* in mdadm helper. 2018-08-27 08:21:28 -03:00
Caio Carvalho 4353de0f05 Including config parameter in RAID assemble. 2018-08-24 18:54:35 -03:00
Caio Carvalho 8083306d66 Updating mdadm config file through a application helper. 2018-08-24 12:06:35 -03:00
Caio Carvalho aaffe54161 Setting RAID status as inactive after deactivation. 2018-08-24 12:03:24 -03:00
Caio Carvalho d676c8c504 Checking if a SoftwareRAID device is deactivatable 2018-08-16 23:40:27 +02:00
Caio Carvalho 22e857a072 Check if command string is empty in ExternalCommand::start 2018-08-16 23:32:33 +02:00
Caio Carvalho 58a11262f7 Checking if the command is not an empty string. 2018-08-16 18:59:47 +02:00
Caio Carvalho 7863564e35 Setting getDefaultRaidConfigFile method as public. 2018-08-16 14:14:40 +02:00
Caio Carvalho 6ab3f854e7 Initial RAID configuration file setting implementation. 2018-08-16 01:01:03 +02:00
Andrius Štikonas 4ec2d2444b Merge branch 'master' into raid-support 2018-08-15 10:45:06 +00:00
Caio Carvalho 1c714c7854 Setting mount point for linux_raid_member partitions. 2018-08-14 15:07:48 +02:00
Caio Carvalho 213162c1a8 Updating mdadm.conf file information after creation. 2018-08-14 12:18:22 +02:00
Caio Carvalho be89331db0 Initial RAID deactivation support. 2018-08-14 01:51:09 +02:00
Caio Carvalho d7650c51df Job for RAID creation. 2018-08-13 20:08:17 -03:00
Caio Carvalho 6ddb69b661 Avoiding -1B size for inactive RAID. 2018-08-13 09:53:07 -03:00
Caio Carvalho 51d295ca5d Changing eraseDeviceMDSuperblock call in software RAID creation 2018-08-08 16:44:46 -03:00
Caio Carvalho fed87159da Initial Software RAID creation. 2018-07-31 16:21:51 -03:00
34 changed files with 636 additions and 198 deletions

View File

@ -41,7 +41,6 @@ public:
QString m_UUID;
mutable QStringList m_LVPathList;
QVector <const Partition*> m_PVs;
mutable std::unique_ptr<QHash<QString, qint64>> m_LVSizeMap;
};
@ -549,16 +548,6 @@ QString LvmDevice::UUID() const
return d_ptr->m_UUID;
}
QVector <const Partition*>& LvmDevice::physicalVolumes()
{
return d_ptr->m_PVs;
}
const QVector <const Partition*>& LvmDevice::physicalVolumes() const
{
return d_ptr->m_PVs;
}
std::unique_ptr<QHash<QString, qint64>>& LvmDevice::LVSizeMap() const
{
return d_ptr->m_LVSizeMap;

View File

@ -91,8 +91,6 @@ public:
qint64 freePE() const;
void setFreePE(qint64 freePE) const;
QString UUID() const;
QVector <const Partition*>& physicalVolumes();
const QVector <const Partition*>& physicalVolumes() const;
protected:
std::unique_ptr<QHash<QString, qint64>>& LVSizeMap() const;

View File

@ -12,6 +12,7 @@
#include "core/volumemanagerdevice_p.h"
#include "fs/filesystem.h"
#include "fs/filesystemfactory.h"
#include "ops/createpartitiontableoperation.h"
#include "util/externalcommand.h"
#include <utility>
@ -22,6 +23,8 @@
#define d_ptr std::static_pointer_cast<SoftwareRAIDPrivate>(d)
QString SoftwareRAID::s_raidConfigurationFile = QString();
class SoftwareRAIDPrivate : public VolumeManagerDevicePrivate
{
public:
@ -39,8 +42,8 @@ SoftwareRAID::SoftwareRAID(const QString& name, SoftwareRAID::Status status, con
: VolumeManagerDevice(std::make_shared<SoftwareRAIDPrivate>(),
name,
(QStringLiteral("/dev/") + name),
getChunkSize(QStringLiteral("/dev/") + name),
getTotalChunk(QStringLiteral("/dev/") + name),
status == SoftwareRAID::Status::Inactive ? 0 : getChunkSize(QStringLiteral("/dev/") + name),
status == SoftwareRAID::Status::Inactive ? 0 : getTotalChunk(QStringLiteral("/dev/") + name),
iconName,
Device::Type::SoftwareRAID_Device)
{
@ -140,11 +143,6 @@ QString SoftwareRAID::uuid() const
return d_ptr->m_UUID;
}
QStringList SoftwareRAID::devicePathList() const
{
return d_ptr->m_devicePathList;
}
SoftwareRAID::Status SoftwareRAID::status() const
{
return d_ptr->m_status;
@ -159,8 +157,7 @@ void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
{
QStringList availableInConf;
// TODO: Support custom config files.
QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf"));
QString config = getRAIDConfiguration();
if (!config.isEmpty()) {
QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/([\\/\\w-]+)"));
@ -203,6 +200,22 @@ void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
if (getUUID(QStringLiteral("/dev/") + path) == d->uuid())
availableInConf.removeAll(path);
QStringList partitionNodes;
if (d->partitionTable() != nullptr)
for (const Partition *p : d->partitionTable()->children())
partitionNodes << p->partitionPath();
d->setPartitionNodes(partitionNodes);
for (const Device* dev : std::as_const(devices)) {
if (dev->partitionTable()) {
for (const Partition* p : dev->partitionTable()->children())
if (getRaidArrayName(p->deviceNode()) == d->deviceNode())
d->physicalVolumes() << p;
}
}
devices << d;
if (status == QStringLiteral("inactive"))
@ -237,7 +250,7 @@ qint32 SoftwareRAID::getRaidLevel(const QString &path)
QRegularExpression re(QStringLiteral("Raid Level :\\s+\\w+(\\d+)"));
QRegularExpressionMatch reMatch = re.match(output);
if (reMatch.hasMatch())
return reMatch.captured(1).toLongLong();
return reMatch.captured(1).toInt();
}
return -1;
@ -253,10 +266,8 @@ qint64 SoftwareRAID::getChunkSize(const QString &path)
// Look sector size for the first device/partition on the list, as RAID 1 is composed by mirrored devices
ExternalCommand sectorSize(QStringLiteral("blockdev"), { QStringLiteral("--getss"), device });
if (sectorSize.run(-1) && sectorSize.exitCode() == 0) {
int sectors = sectorSize.output().trimmed().toLongLong();
return sectors;
}
if (sectorSize.run(-1) && sectorSize.exitCode() == 0)
return sectorSize.output().trimmed().toLongLong();
}
}
else {
@ -269,7 +280,6 @@ qint64 SoftwareRAID::getChunkSize(const QString &path)
}
}
return -1;
}
qint64 SoftwareRAID::getTotalChunk(const QString &path)
@ -304,8 +314,7 @@ QString SoftwareRAID::getUUID(const QString &path)
// If UUID was not found in detail output, it should be searched in config file
// TODO: Support custom config files.
QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf"));
QString config = getRAIDConfiguration();
if (!config.isEmpty()) {
QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/md([\\/\\w-]+)(.*)"));
@ -361,9 +370,9 @@ QStringList SoftwareRAID::getDevicePathList(const QString &path)
return result;
}
bool SoftwareRAID::isRaidPath(const QString &path)
bool SoftwareRAID::isRaidPath(const QString &devicePath)
{
return !getDetail(path).isEmpty();
return !getDetail(devicePath).isEmpty();
}
bool SoftwareRAID::createSoftwareRAID(Report &report,
@ -372,75 +381,112 @@ bool SoftwareRAID::createSoftwareRAID(Report &report,
const qint32 raidLevel,
const qint32 chunkSize)
{
Q_UNUSED(report)
Q_UNUSED(name)
Q_UNUSED(devicePathList)
Q_UNUSED(raidLevel)
Q_UNUSED(chunkSize)
return false;
QString path = QStringLiteral("/dev/") + name;
QStringList args = { QStringLiteral("--create"), path,
QStringLiteral("--level=") + QString::number(raidLevel),
QStringLiteral("--chunk=") + QString::number(chunkSize),
QStringLiteral("--raid-devices=") + QString::number(devicePathList.size()) };
for (const QString &p : std::as_const(devicePathList)) {
eraseDeviceMDSuperblock(p);
args << p;
}
ExternalCommand cmd(report, QStringLiteral("mdadm"), args);
cmd.write(QByteArrayLiteral("y"));
if (!cmd.run(-1) || cmd.exitCode() != 0)
return false;
if (updateConfigurationFile(path))
qDebug() << QStringLiteral("Updated RAID config: ") + path;
return true;
}
bool SoftwareRAID::deleteSoftwareRAID(Report &report,
SoftwareRAID &raidDevice)
{
Q_UNUSED(report)
Q_UNUSED(raidDevice)
return false;
}
// We need raid activated to erase its partition table
if (assembleSoftwareRAID(raidDevice.deviceNode()))
raidDevice.setStatus(SoftwareRAID::Status::Active); // check this behaviour on mirror devices during resync
bool SoftwareRAID::assembleSoftwareRAID(const QString& deviceNode)
{
if (!isRaidPath(deviceNode))
return false;
if (raidDevice.status() == SoftwareRAID::Status::Active) {
// Erasing device's partition table
if (raidDevice.partitionTable() != nullptr) {
CreatePartitionTableOperation updatePartitionTable(raidDevice, raidDevice.partitionTable()->type());
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--assemble"), QStringLiteral("--scan"), deviceNode });
if (!updatePartitionTable.execute(report))
return false;
}
stopSoftwareRAID(report, raidDevice.deviceNode());
}
for (const QString& path : raidDevice.deviceNodes())
eraseDeviceMDSuperblock(path);
QString config = getRAIDConfiguration();
QStringList lines = config.split(QLatin1Char('\n'));
QString contentUpdated = QStringLiteral("\"");
for (const QString line : lines)
if (!line.isEmpty() && !line.contains(raidDevice.uuid()))
contentUpdated += line + QLatin1Char('\n');
contentUpdated += QLatin1Char('\"');
ExternalCommand cmd(QStringLiteral("/usr/") + QStringLiteral(LIBEXECDIRPATH) + QStringLiteral("/kpmcore_mdadmupdateconf"),
{ QStringLiteral("--write"), contentUpdated, raidConfigurationFilePath() });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::stopSoftwareRAID(const QString& deviceNode)
bool SoftwareRAID::assembleSoftwareRAID(const QString& deviceNode)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--assemble"), QStringLiteral("--scan"), deviceNode,
QStringLiteral("--config=") + raidConfigurationFilePath() });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::stopSoftwareRAID(Report& report, const QString& deviceNode)
{
if (!isRaidPath(deviceNode))
return false;
ExternalCommand cmd(QStringLiteral("mdadm"),
ExternalCommand cmd(report, QStringLiteral("mdadm"),
{ QStringLiteral("--manage"), QStringLiteral("--stop"), deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::reassembleSoftwareRAID(const QString &deviceNode)
bool SoftwareRAID::reassembleSoftwareRAID(Report& report, const QString &deviceNode)
{
return stopSoftwareRAID(deviceNode) && assembleSoftwareRAID(deviceNode);
// TODO: Include report
return stopSoftwareRAID(report, deviceNode) && assembleSoftwareRAID(deviceNode);
}
bool SoftwareRAID::isRaidMember(const QString &path)
QString SoftwareRAID::getRaidArrayName(const QString &partitionPath)
{
QFile mdstat(QStringLiteral("/proc/mdstat"));
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--misc"), QStringLiteral("--query"), partitionPath });
if (!mdstat.open(QIODevice::ReadOnly))
return false;
if (cmd.run(-1) && cmd.exitCode() == 0) {
QRegularExpression ex(QStringLiteral("device active raid\\d+\\s([\\/\\w]+)."));
QRegularExpressionMatch match = ex.match(cmd.output());
QTextStream stream(&mdstat);
QString content = stream.readAll();
mdstat.close();
QRegularExpression re(QStringLiteral("(\\w+)\\[\\d+\\]"));
QRegularExpressionMatchIterator i = re.globalMatch(content);
while (i.hasNext()) {
QRegularExpressionMatch reMatch = i.next();
QString match = QStringLiteral("/dev/") + reMatch.captured(1);
if (match == path)
return true;
if (match.hasMatch())
return match.captured(1);
}
return false;
return QString();
}
void SoftwareRAID::initPartitions()
@ -455,6 +501,22 @@ qint64 SoftwareRAID::mappedSector(const QString &partitionPath, qint64 sector) c
return -1;
}
bool SoftwareRAID::eraseDeviceMDSuperblock(const QString &path)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--misc"), QStringLiteral("--zero-superblock"), path});
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::updateConfigurationFile(const QString &path)
{
ExternalCommand cmd(QStringLiteral("/usr/") + QStringLiteral(LIBEXECDIRPATH) + QStringLiteral("/kpmcore_mdadmupdateconf"),
{ QStringLiteral("--append"), path, raidConfigurationFilePath() });
return cmd.run(-1) && cmd.exitCode() == 0;
}
QString SoftwareRAID::getDetail(const QString &path)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
@ -462,9 +524,9 @@ QString SoftwareRAID::getDetail(const QString &path)
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString();
}
QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath)
QString SoftwareRAID::getRAIDConfiguration()
{
QFile config(configurationPath);
QFile config(raidConfigurationFilePath());
if (!config.open(QIODevice::ReadOnly))
return QString();
@ -477,3 +539,57 @@ QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath)
return result;
}
QString SoftwareRAID::getDeviceInformation(const QString &deviceName)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--misc"), QStringLiteral("--detail"), QStringLiteral("--scan"), deviceName });
// TODO: Get only information about the device line.
// Because if there is any error on config file, it will print more information than needed.
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString();
}
void SoftwareRAID::setRaidConfigurationFilePath(const QString &filePath)
{
s_raidConfigurationFile = filePath;
}
QString SoftwareRAID::raidConfigurationFilePath()
{
if (s_raidConfigurationFile.isEmpty())
s_raidConfigurationFile = getDefaultRaidConfigFile();
return s_raidConfigurationFile;
}
QString SoftwareRAID::getDefaultRaidConfigFile()
{
if (QFile::exists(QStringLiteral("/etc/mdadm.conf")))
return QStringLiteral("/etc/mdadm.conf");
else if (QFile::exists(QStringLiteral("/etc/mdadm/mdadm.conf")))
return QStringLiteral("/etc/mdadm/mdadm.conf");
return QString();
}
bool SoftwareRAID::failPV(Report& report, const QString& devicePath, const QString& physicalVolume)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--manage"), QStringLiteral("--fail"), devicePath, physicalVolume });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::removePV(Report& report, const QString& devicePath, const QString& physicalVolume)
{
failPV(report, devicePath, physicalVolume);
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--manage"), QStringLiteral("--remove"), devicePath, physicalVolume });
return cmd.run(-1) && cmd.exitCode() == 0;
}
void SoftwareRAID::setPartitionNodes(const QStringList& partitionNodes)
{
d_ptr->m_partitionPathList = partitionNodes;
}

View File

@ -46,7 +46,6 @@ public:
qint64 totalChunk() const;
qint64 arraySize() const;
QString uuid() const;
QStringList devicePathList() const;
SoftwareRAID::Status status() const;
void setStatus(SoftwareRAID::Status status);
@ -59,7 +58,7 @@ public:
static QString getUUID(const QString& path);
static QStringList getDevicePathList(const QString& path);
static bool isRaidPath(const QString& path);
static bool isRaidPath(const QString& devicePath);
static bool createSoftwareRAID(Report& report,
const QString& name,
@ -72,11 +71,23 @@ public:
static bool assembleSoftwareRAID(const QString& deviceNode);
static bool stopSoftwareRAID(const QString& deviceNode);
static bool stopSoftwareRAID(Report& report, const QString& deviceNode);
static bool reassembleSoftwareRAID(const QString& deviceNode);
static bool reassembleSoftwareRAID(Report& report, const QString& deviceNode);
static bool isRaidMember(const QString& path);
static QString getRaidArrayName(const QString& partitionPath);
static void setRaidConfigurationFilePath(const QString& filePath);
static QString raidConfigurationFilePath();
static QString getDefaultRaidConfigFile();
static bool failPV(Report& report, const QString& devicePath, const QString& physicalVolume);
//static bool insertPV(Report& report, SoftwareRAID& raid, const QString& deviceNode);
static bool removePV(Report& report, const QString& devicePath, const QString& physicalVolume);
protected:
void initPartitions() override;
@ -84,11 +95,22 @@ protected:
qint64 mappedSector(const QString &partitionPath, qint64 sector) const override;
private:
static bool eraseDeviceMDSuperblock(const QString& path);
static bool updateConfigurationFile(const QString& path);
static void scanSoftwareRAID(QList<Device*>& devices);
static QString getDetail(const QString& path);
static QString getRAIDConfiguration(const QString& configurationPath);
static QString getRAIDConfiguration();
static QString getDeviceInformation(const QString& deviceName);
void setPartitionNodes(const QStringList& partitionNodes);
private:
static QString s_raidConfigurationFile;
};
#endif // SOFTWARERAID_H

View File

@ -9,9 +9,12 @@
#include "core/volumemanagerdevice.h"
#include "core/volumemanagerdevice_p.h"
#include "core/device_p.h"
#include "core/partition.h"
#include "core/lvmdevice.h"
#include "core/raid/softwareraid.h"
#define d_ptr std::static_pointer_cast<VolumeManagerDevicePrivate>(d)
/** Constructs an abstract Volume Manager Device with an empty PartitionTable.
*
* @param name the Device's name
@ -43,5 +46,15 @@ QString VolumeManagerDevice::prettyDeviceNodeList() const
void VolumeManagerDevice::setTotalLogical(qint64 n)
{
Q_ASSERT(n > 0);
d->m_TotalLogical = n;
d_ptr->m_TotalLogical = n;
}
QVector<const Partition*>& VolumeManagerDevice::physicalVolumes()
{
return d_ptr->m_PVs;
}
const QVector<const Partition*>& VolumeManagerDevice::physicalVolumes() const
{
return d_ptr->m_PVs;
}

View File

@ -17,6 +17,7 @@
#include <QObject>
#include <QtGlobal>
class Partition;
class VolumeManagerDevicePrivate;
/** A Volume Manager of physical devices represented as an abstract device.
@ -84,6 +85,10 @@ public:
* @param n Number of sectors.
*/
void setTotalLogical(qint64 n);
QVector<const Partition*>& physicalVolumes();
const QVector<const Partition*>& physicalVolumes() const;
};
#endif

View File

@ -9,8 +9,14 @@
#include "core/device_p.h"
#include <QVector>
class Partition;
class VolumeManagerDevicePrivate : public DevicePrivate
{
public:
QVector<const Partition*> m_PVs;
};
#endif

View File

@ -14,6 +14,7 @@
#include "fs/filesystem.h"
#include "core/fstab.h"
#include "core/raid/softwareraid.h"
#include "fs/lvm2_pv.h"
@ -146,6 +147,8 @@ QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPat
{
if (fs->type() == FileSystem::Type::Lvm2_PV)
return FS::lvm2_pv::getVGName(partitionPath);
else if (fs->type() == FileSystem::Type::LinuxRaidMember)
return SoftwareRAID::getRaidArrayName(partitionPath);
if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed
return QString();

View File

@ -31,6 +31,7 @@ set(JOBS_SRC
jobs/setpartflagsjob.cpp
jobs/copyfilesystemjob.cpp
jobs/movefilesystemjob.cpp
jobs/activateraidjob.cpp
)
set(JOBS_LIB_HDRS

View File

@ -0,0 +1,35 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "core/raid/softwareraid.h"
#include "jobs/activateraidjob.h"
#include "util/report.h"
#include <QDebug>
#include <QString>
#include <KLocalizedString>
ActivateRaidJob::ActivateRaidJob(const QString& path)
: m_path(path)
{
}
bool ActivateRaidJob::run(Report& parent)
{
Report *report = jobStarted(parent);
bool result = SoftwareRAID::assembleSoftwareRAID(m_path);
jobFinished(*report, result);
return result;
}
QString ActivateRaidJob::description() const
{
return xi18nc("@info/plain", "Activate RAID volume: <filename>%1</filename>", m_path);
}

View File

@ -0,0 +1,28 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef KPMCORE_ACTIVATERAIDJOB_H
#define KPMCORE_ACTIVATERAIDJOB_H
#include "jobs/job.h"
class Report;
class QString;
class ActivateRaidJob : public Job
{
public:
ActivateRaidJob(const QString& path);
public:
bool run(Report& parent) override;
QString description() const override;
private:
const QString& m_path;
};
#endif // KPMCORE_ACTIVATERAIDJOB_H

View File

@ -1,6 +1,7 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2017 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -8,6 +9,7 @@
#include "jobs/createvolumegroupjob.h"
#include "core/lvmdevice.h"
#include "core/raid/softwareraid.h"
#include "util/report.h"
@ -18,11 +20,27 @@
* @param pvList List of LVM Physical Volumes used to create Volume Group
* @param peSize LVM Physical Extent size in MiB
*/
CreateVolumeGroupJob::CreateVolumeGroupJob(const QString& vgName, const QVector<const Partition*>& pvList, const qint32 peSize) :
Job(),
m_vgName(vgName),
m_pvList(pvList),
m_PESize(peSize)
CreateVolumeGroupJob::CreateVolumeGroupJob(const QString& vgName, const QVector<const Partition*>& pvList,
const Device::Type type, const qint32 peSize)
: Job()
, m_vgName(vgName)
, m_pvList(pvList)
, m_type(type)
, m_PESize(peSize)
, m_raidLevel(-1)
, m_chunkSize(-1)
{
}
CreateVolumeGroupJob::CreateVolumeGroupJob(const QString& vgName, const QVector<const Partition *>& pvList,
const Device::Type type, const qint32 raidLevel, const qint32 chunkSize)
: Job()
, m_vgName(vgName)
, m_pvList(pvList)
, m_type(type)
, m_PESize(-1)
, m_raidLevel(raidLevel)
, m_chunkSize(chunkSize)
{
}
@ -32,7 +50,16 @@ bool CreateVolumeGroupJob::run(Report& parent)
Report* report = jobStarted(parent);
rval = LvmDevice::createVG(*report, vgName(), pvList(), peSize());
if (type() == Device::Type::LVM_Device)
rval = LvmDevice::createVG(*report, vgName(), pvList(), peSize());
else if (type() == Device::Type::SoftwareRAID_Device) {
QStringList pathList;
for (auto partition : pvList())
pathList << partition->partitionPath();
rval = SoftwareRAID::createSoftwareRAID(*report, vgName(), pathList, raidLevel(), chunkSize());
}
jobFinished(*report, rval);
@ -41,10 +68,12 @@ bool CreateVolumeGroupJob::run(Report& parent)
QString CreateVolumeGroupJob::description() const
{
QString tmp = QString();
for (const auto &p : pvList()) {
QString tmp;
for (const auto &p : pvList())
tmp += p->deviceNode() + QStringLiteral(", ");
}
tmp.chop(2);
return xi18nc("@info/plain", "Create a new Volume Group: <filename>%1</filename> with PV: %2", vgName(), tmp);
}

View File

@ -1,6 +1,7 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2017 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -9,6 +10,7 @@
#define KPMCORE_CREATEVOLUMEGROUPJOB_H
#include "core/partition.h"
#include "core/volumemanagerdevice.h"
#include "jobs/job.h"
#include <QVector>
@ -21,34 +23,48 @@ class QString;
class CreateVolumeGroupJob : public Job
{
public:
CreateVolumeGroupJob(const QString& vgName, const QVector<const Partition*>& pvList, const qint32 peSize);
CreateVolumeGroupJob(const QString& vgName, const QVector<const Partition*>& pvList,
const Device::Type type, const qint32 peSize);
CreateVolumeGroupJob(const QString &vgName, const QVector<const Partition *> &pvList,
const Device::Type type, const qint32 raidLevel, const qint32 chunkSize);
public:
bool run(Report& parent) override;
QString description() const override;
protected:
QString vgName() {
return m_vgName;
}
const QString vgName() const {
return m_vgName;
}
QVector<const Partition*>& pvList() {
return m_pvList;
}
const QVector<const Partition*>& pvList() const {
return m_pvList;
}
qint32 peSize() {
qint32 peSize() const {
return m_PESize;
}
Device::Type type() const {
return m_type;
}
qint32 raidLevel() const {
return m_raidLevel;
}
qint32 chunkSize() const {
return m_chunkSize;
}
private:
QString m_vgName;
QVector<const Partition*> m_pvList;
Device::Type m_type;
qint32 m_PESize;
qint32 m_raidLevel;
qint32 m_chunkSize;
};
#endif

View File

@ -1,6 +1,7 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -9,6 +10,7 @@
#include "core/lvmdevice.h"
#include "core/partition.h"
#include "core/raid/softwareraid.h"
#include "util/report.h"
@ -30,11 +32,19 @@ bool DeactivateVolumeGroupJob::run(Report& parent)
if (device().type() == Device::Type::LVM_Device) {
rval = LvmDevice::deactivateVG(*report, static_cast<LvmDevice&>(device()));
const auto lvmPVs = static_cast<LvmDevice&>(device()).physicalVolumes();
for (auto &p : lvmPVs) {
Partition *partition = const_cast<Partition *>(p);
partition->setMounted(false);
}
}
const auto lvmPVs = static_cast<LvmDevice&>(device()).physicalVolumes();
for (auto &p : lvmPVs) {
Partition *partition = const_cast<Partition *>(p);
partition->setMounted(false);
else if (device().type() == Device::Type::SoftwareRAID_Device) {
rval = SoftwareRAID::stopSoftwareRAID(*report, device().deviceNode());
if (rval) {
SoftwareRAID *raid = static_cast< SoftwareRAID* >(&device());
raid->setStatus(SoftwareRAID::Status::Inactive);
}
}
jobFinished(*report, rval);

View File

@ -8,6 +8,7 @@
#include "jobs/movephysicalvolumejob.h"
#include "core/lvmdevice.h"
#include "core/volumemanagerdevice.h"
#include "util/report.h"
@ -16,7 +17,7 @@
/** Creates a new MovePhysicalVolumeJob
* @param d Device representing LVM Volume Group
*/
MovePhysicalVolumeJob::MovePhysicalVolumeJob(LvmDevice& d, const QList <const Partition*>& partList) :
MovePhysicalVolumeJob::MovePhysicalVolumeJob(VolumeManagerDevice& d, const QList <const Partition*>& partList) :
Job(),
m_Device(d),
m_PartList(partList)

View File

@ -12,7 +12,7 @@
#include "core/partition.h"
#include "jobs/job.h"
class LvmDevice;
class VolumeManagerDevice;
class Report;
class QString;
@ -20,7 +20,7 @@ class QString;
class MovePhysicalVolumeJob : public Job
{
public:
MovePhysicalVolumeJob(LvmDevice& dev, const QList <const Partition*>& partlist);
MovePhysicalVolumeJob(VolumeManagerDevice& dev, const QList <const Partition*>& partlist);
public:
bool run(Report& parent) override;
@ -28,10 +28,10 @@ public:
protected:
LvmDevice& device() {
VolumeManagerDevice& device() {
return m_Device;
}
const LvmDevice& device() const {
const VolumeManagerDevice& device() const {
return m_Device;
}
const QList <const Partition*>& partList() const {
@ -39,7 +39,7 @@ protected:
}
private:
LvmDevice& m_Device;
VolumeManagerDevice& m_Device;
const QList <const Partition*> m_PartList;
};

View File

@ -1,6 +1,7 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -8,6 +9,7 @@
#include "jobs/removevolumegroupjob.h"
#include "core/lvmdevice.h"
#include "core/raid/softwareraid.h"
#include "util/report.h"
@ -27,9 +29,10 @@ bool RemoveVolumeGroupJob::run(Report& parent)
Report* report = jobStarted(parent);
if (device().type() == Device::Type::LVM_Device) {
if (device().type() == Device::Type::LVM_Device)
rval = LvmDevice::removeVG(*report, dynamic_cast<LvmDevice&>(device()));
}
else if (device().type() == Device::Type::SoftwareRAID_Device)
rval = SoftwareRAID::deleteSoftwareRAID(*report, dynamic_cast<SoftwareRAID&>(device()));
jobFinished(*report, rval);
@ -38,5 +41,5 @@ bool RemoveVolumeGroupJob::run(Report& parent)
QString RemoveVolumeGroupJob::description() const
{
return xi18nc("@info/plain", "Remove Volume Group: <filename>%1</filename>", device().name());
return xi18nc("@info/plain", "Remove %1 Volume Group: <filename>%2</filename>", (device().type() == Device::Type::SoftwareRAID_Device ? QStringLiteral("RAID") : QStringLiteral("LVM")), device().name());
}

View File

@ -8,6 +8,7 @@
#include "jobs/resizevolumegroupjob.h"
#include "core/lvmdevice.h"
#include "core/volumemanagerdevice.h"
#include "fs/luks.h"
#include "util/report.h"
@ -16,7 +17,7 @@
/** Creates a new ResizeVolumeGroupJob
*/
ResizeVolumeGroupJob::ResizeVolumeGroupJob(LvmDevice& dev, const QList <const Partition*>& partlist, const Type type) :
ResizeVolumeGroupJob::ResizeVolumeGroupJob(VolumeManagerDevice& dev, const QList <const Partition*>& partlist, const Type type) :
Job(),
m_Device(dev),
m_PartList(partlist),
@ -30,15 +31,18 @@ bool ResizeVolumeGroupJob::run(Report& parent)
Report* report = jobStarted(parent);
for (const auto &p : partList()) {
const QString deviceNode = p->roles().has(PartitionRole::Luks) ? static_cast<const FS::luks*>(&p->fileSystem())->mapperName() : p->partitionPath();
if (type() == ResizeVolumeGroupJob::Type::Grow)
rval = LvmDevice::insertPV(*report, device(), deviceNode);
else if (type() == ResizeVolumeGroupJob::Type::Shrink)
rval = LvmDevice::removePV(*report, device(), deviceNode);
if (device().type() == Device::Type::LVM_Device) {
LvmDevice& lvm = static_cast<LvmDevice&>(device());
for (const auto &p : partList()) {
const QString deviceNode = p->roles().has(PartitionRole::Luks) ? static_cast<const FS::luks*>(&p->fileSystem())->mapperName() : p->partitionPath();
if (type() == ResizeVolumeGroupJob::Type::Grow)
rval = LvmDevice::insertPV(*report, lvm, deviceNode);
else if (type() == ResizeVolumeGroupJob::Type::Shrink)
rval = LvmDevice::removePV(*report, lvm, deviceNode);
if (rval == false)
break;
if (rval == false)
break;
}
}
jobFinished(*report, rval);

View File

@ -11,7 +11,7 @@
#include "core/partition.h"
#include "jobs/job.h"
class LvmDevice;
class VolumeManagerDevice;
class Report;
class QString;
@ -26,17 +26,17 @@ public:
};
public:
ResizeVolumeGroupJob(LvmDevice& dev, const QList <const Partition*>& partlist, const Type type);
ResizeVolumeGroupJob(VolumeManagerDevice& dev, const QList <const Partition*>& partlist, const Type type);
public:
bool run(Report& parent) override;
QString description() const override;
protected:
LvmDevice& device() {
VolumeManagerDevice& device() {
return m_Device;
}
const LvmDevice& device() const {
const VolumeManagerDevice& device() const {
return m_Device;
}
@ -49,7 +49,7 @@ protected:
}
private:
LvmDevice& m_Device;
VolumeManagerDevice& m_Device;
const QList <const Partition*> m_PartList;
ResizeVolumeGroupJob::Type m_Type;
};

View File

@ -21,6 +21,7 @@ set(OPS_SRC
ops/checkoperation.cpp
ops/backupoperation.cpp
ops/copyoperation.cpp
ops/activateraidoperation.cpp
)
set(OPS_LIB_HDRS
@ -40,4 +41,5 @@ set(OPS_LIB_HDRS
ops/restoreoperation.h
ops/setfilesystemlabeloperation.h
ops/setpartflagsoperation.h
ops/activateraidoperation.h
)

View File

@ -0,0 +1,41 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "core/device.h"
#include "core/raid/softwareraid.h"
#include "jobs/activateraidjob.h"
#include "ops/activateraidoperation.h"
#include <KLocalizedString>
ActivateRaidOperation::ActivateRaidOperation(SoftwareRAID* raid)
: Operation()
, m_activateRaidJob(new ActivateRaidJob(raid->deviceNode()))
, m_raid(raid)
{
addJob(activateRaidJob());
}
QString ActivateRaidOperation::description() const
{
return xi18nc("@info/plain", "Activate RAID array \'%1\'.", m_raid->deviceNode());
}
bool ActivateRaidOperation::targets(const Device& device) const
{
return device.type() == Device::Type::SoftwareRAID_Device &&
device.deviceNode() == m_raid->deviceNode();
}
void ActivateRaidOperation::preview()
{
m_raid->setStatus(SoftwareRAID::Status::Active);
}
void ActivateRaidOperation::undo()
{
m_raid->setStatus(SoftwareRAID::Status::Inactive);
}

View File

@ -0,0 +1,49 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef KPMCORE_ACTIVATERAIDOPERATION_H
#define KPMCORE_ACTIVATERAIDOPERATION_H
#include "ops/operation.h"
class ActivateRaidJob;
class Device;
class Partition;
class SoftwareRAID;
class LIBKPMCORE_EXPORT ActivateRaidOperation : public Operation
{
Q_DISABLE_COPY(ActivateRaidOperation)
public:
ActivateRaidOperation(SoftwareRAID* raid);
public:
QString iconName() const override { return QStringLiteral("answer"); }
QString description() const override;
virtual bool targets(const Device& device) const override;
virtual bool targets(const Partition&) const override {
return true;
}
virtual void preview() override;
virtual void undo() override;
protected:
ActivateRaidJob* activateRaidJob() const {
return m_activateRaidJob;
}
private:
ActivateRaidJob* m_activateRaidJob;
SoftwareRAID* m_raid;
};
#endif // KPMCORE_ACTIVATERAIDOPERATION_H

View File

@ -22,18 +22,30 @@
* @param pvList List of LVM Physical Volumes used to create Volume Group
* @param peSize LVM Physical Extent size in MiB
*/
CreateVolumeGroupOperation::CreateVolumeGroupOperation(const QString& vgName, const QVector<const Partition*>& pvList, const qint32 peSize) :
Operation(),
m_CreateVolumeGroupJob(new CreateVolumeGroupJob(vgName, pvList, peSize)),
m_PVList(pvList),
m_vgName(vgName)
CreateVolumeGroupOperation::CreateVolumeGroupOperation(const QString& vgName, const QVector<const Partition*>& pvList,
const Device::Type type, const qint32 peSize)
: Operation()
, m_CreateVolumeGroupJob(new CreateVolumeGroupJob(vgName, pvList, type, peSize))
, m_PVList(pvList)
, m_vgName(vgName)
{
addJob(createVolumeGroupJob());
}
CreateVolumeGroupOperation::CreateVolumeGroupOperation(const QString &vgName, const QVector<const Partition *> &pvList,
const Device::Type type, const qint32 raidLevel,
const qint32 chunkSize)
: Operation()
, m_CreateVolumeGroupJob(new CreateVolumeGroupJob(vgName, pvList, type, raidLevel, chunkSize))
, m_PVList(pvList)
, m_vgName(vgName)
{
addJob(createVolumeGroupJob());
}
QString CreateVolumeGroupOperation::description() const
{
return xi18nc("@info/plain", "Create a new LVM volume group named \'%1\'.", m_vgName);
return xi18nc("@info/plain", "Create a new volume group named \'%1\'.", m_vgName);
}
bool CreateVolumeGroupOperation::targets(const Partition& partition) const
@ -47,15 +59,23 @@ bool CreateVolumeGroupOperation::targets(const Partition& partition) const
void CreateVolumeGroupOperation::preview()
{
LvmDevice::s_DirtyPVs << PVList();
if (type() == Device::Type::LVM_Device)
LvmDevice::s_DirtyPVs << PVList();
else if (type() == Device::Type::SoftwareRAID_Device) {
// TODO: Set it for RAID
}
}
void CreateVolumeGroupOperation::undo()
{
for (const auto &pvPath : PVList()) {
if (LvmDevice::s_DirtyPVs.contains(pvPath)) {
LvmDevice::s_DirtyPVs.removeAll(pvPath);
}
if (type() == Device::Type::LVM_Device) {
for (const auto &pvPath : PVList())
if (LvmDevice::s_DirtyPVs.contains(pvPath))
LvmDevice::s_DirtyPVs.removeAll(pvPath);
}
else if (type() == Device::Type::SoftwareRAID_Device) {
// TODO: Set it for RAID
}
}

View File

@ -14,6 +14,7 @@
#include "ops/operation.h"
#include "core/lvmdevice.h"
#include "core/volumemanagerdevice.h"
#include <QString>
@ -27,7 +28,12 @@ class LIBKPMCORE_EXPORT CreateVolumeGroupOperation : public Operation
friend class OperationStack;
public:
CreateVolumeGroupOperation(const QString& vgName, const QVector<const Partition*>& pvList, const qint32 peSize = 4);
CreateVolumeGroupOperation(const QString& vgName, const QVector<const Partition*>& pvList,
const Device::Type type, const qint32 peSize = 4);
CreateVolumeGroupOperation(const QString& vgName, const QVector<const Partition*>& pvList,
const Device::Type type, const qint32 raidLevel,
const qint32 chunkSize);
public:
QString iconName() const override {
@ -47,18 +53,23 @@ public:
static bool canCreate();
protected:
CreateVolumeGroupJob* createVolumeGroupJob() {
CreateVolumeGroupJob* createVolumeGroupJob() const {
return m_CreateVolumeGroupJob;
}
const QVector<const Partition*>& PVList() {
const QVector<const Partition*>& PVList() const {
return m_PVList;
}
Device::Type type() const {
return m_type;
}
private:
CreateVolumeGroupJob* m_CreateVolumeGroupJob;
const QVector<const Partition*> m_PVList;
QString m_vgName;
Device::Type m_type;
};
#endif

View File

@ -12,6 +12,7 @@
#include "core/volumemanagerdevice.h"
#include "core/partitiontable.h"
#include "core/partition.h"
#include "core/raid/softwareraid.h"
#include <QString>
@ -38,7 +39,10 @@ QString DeactivateVolumeGroupOperation::description() const
void DeactivateVolumeGroupOperation::preview()
{
m_PartitionTable = device().partitionTable();
device().setPartitionTable(new PartitionTable(PartitionTable::vmd, 0, device().totalLogical() - 1));
if (device().type() == Device::Type::LVM_Device)
device().setPartitionTable(new PartitionTable(PartitionTable::vmd, 0, device().totalLogical() - 1));
else if (device().type() == Device::Type::SoftwareRAID_Device && device().partitionTable() != nullptr)
device().setPartitionTable(new PartitionTable(device().partitionTable()->type(), 0, device().totalLogical() - 1));
}
void DeactivateVolumeGroupOperation::undo()
@ -53,14 +57,20 @@ void DeactivateVolumeGroupOperation::undo()
*/
bool DeactivateVolumeGroupOperation::isDeactivatable(const VolumeManagerDevice* dev)
{
if (dev->type() == Device::Type::LVM_Device) {
for (const auto &p : dev->partitionTable()->children()) {
if (p->isMounted()) {
if (dev->type() != Device::Type::SoftwareRAID_Device &&
dev->type() != Device::Type::LVM_Device)
return false;
if (dev->partitionTable()) {
for (const auto &p : dev->partitionTable()->children())
if (p->isMounted())
return false;
}
}
return true;
}
if (dev->type() == Device::Type::SoftwareRAID_Device) {
const SoftwareRAID* raid = static_cast<const SoftwareRAID*>(dev);
return raid->status() == SoftwareRAID::Status::Active;
}
return false;
return true;
}

View File

@ -117,7 +117,7 @@ bool DeleteOperation::canDelete(const Partition* p)
return false;
}
else if (p->fileSystem().type() == FileSystem::Type::LinuxRaidMember) {
if (SoftwareRAID::isRaidMember(p->partitionPath()))
if (!SoftwareRAID::getRaidArrayName(p->partitionPath()).isEmpty())
return false;
}
else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) {
@ -130,7 +130,7 @@ bool DeleteOperation::canDelete(const Partition* p)
return false;
}
else if (fs->type() == FileSystem::Type::LinuxRaidMember) {
if (SoftwareRAID::isRaidMember(p->partitionPath()))
if (!SoftwareRAID::getRaidArrayName(p->partitionPath()).isEmpty())
return false;
}
}

View File

@ -14,6 +14,7 @@
#include "core/partition.h"
#include "core/partitiontable.h"
#include "core/volumemanagerdevice.h"
#include "core/raid/softwareraid.h"
#include <QString>
@ -32,7 +33,7 @@ RemoveVolumeGroupOperation::RemoveVolumeGroupOperation(VolumeManagerDevice& d) :
QString RemoveVolumeGroupOperation::description() const
{
return xi18nc("@info/plain", "Remove a LVM volume group.");
return xi18nc("@info/plain", "Remove a %1 volume group.", (device().type() == Device::Type::SoftwareRAID_Device ? QStringLiteral("RAID") : QStringLiteral("LVM")));
}
void RemoveVolumeGroupOperation::preview()
@ -80,6 +81,10 @@ bool RemoveVolumeGroupOperation::isRemovable(const VolumeManagerDevice* dev)
if (dev->partitionTable()->children().first()->fileSystem().type() == FileSystem::Type::Unknown)
return true;
}
else if (dev->type() == Device::Type::SoftwareRAID_Device) {
const SoftwareRAID* raid = static_cast<const SoftwareRAID*>(dev);
return raid->status() == SoftwareRAID::Status::Inactive;
}
return false;
}

View File

@ -39,6 +39,7 @@ public:
virtual bool targets(const Device&) const override {
return true;
}
virtual bool targets(const Partition&) const override {
return false;
}
@ -49,11 +50,11 @@ public:
static bool isRemovable(const VolumeManagerDevice* dev);
protected:
RemoveVolumeGroupJob* removeVolumeGroupJob() {
RemoveVolumeGroupJob* removeVolumeGroupJob() const {
return m_RemoveVolumeGroupJob;
}
VolumeManagerDevice& device() {
VolumeManagerDevice& device() const {
return m_Device;
}

View File

@ -24,7 +24,7 @@
@param d the Device to create the new PartitionTable on
@param partList list of LVM Physical Volumes that should be in LVM Volume Group
*/
ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& d, const QVector<const Partition*>& partList)
ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(VolumeManagerDevice& d, const QVector<const Partition*>& partList)
: Operation()
, m_Device(d)
, m_TargetList(partList)
@ -50,45 +50,16 @@ ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& d, const QVect
if (!currentList().contains(p))
toInsertList.append(p);
qint64 currentFreePE = 0;
for (const auto &p : currentList()) {
FS::lvm2_pv *lvm2PVFs;
innerFS(p, lvm2PVFs);
currentFreePE += lvm2PVFs->freePE();
}
qint64 removedFreePE = 0;
for (const auto &p : std::as_const(toRemoveList)) {
FS::lvm2_pv *lvm2PVFs;
innerFS(p, lvm2PVFs);
removedFreePE += lvm2PVFs->freePE();
}
qint64 freePE = currentFreePE - removedFreePE;
qint64 movePE = 0;
for (const auto &p : std::as_const(toRemoveList)) {
FS::lvm2_pv *lvm2PVFs;
innerFS(p, lvm2PVFs);
movePE += lvm2PVFs->allocatedPE();
}
qint64 growPE = 0;
for (const auto &p : std::as_const(toInsertList)) {
growPE += p->capacity() / device().peSize();
if (!toInsertList.isEmpty()) {
m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(d, toInsertList, ResizeVolumeGroupJob::Type::Grow);
addJob(growVolumeGroupJob());
}
if ( movePE > (freePE + growPE)) {
// *ABORT* can't move
} else if (partList == currentList()) {
// *DO NOTHING*
} else {
if (!toInsertList.isEmpty()) {
m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(d, toInsertList, ResizeVolumeGroupJob::Type::Grow);
addJob(growVolumeGroupJob());
}
if (!toRemoveList.isEmpty()) {
m_MovePhysicalVolumeJob = new MovePhysicalVolumeJob(d, toRemoveList);
m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(d, toRemoveList, ResizeVolumeGroupJob::Type::Shrink);
addJob(movePhysicalVolumeJob());
addJob(shrinkvolumegroupjob());
}
if (!toRemoveList.isEmpty()) {
m_MovePhysicalVolumeJob = new MovePhysicalVolumeJob(d, toRemoveList);
m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(d, toRemoveList, ResizeVolumeGroupJob::Type::Shrink);
addJob(movePhysicalVolumeJob());
addJob(shrinkvolumegroupjob());
}
}

View File

@ -12,9 +12,10 @@
#include "ops/operation.h"
#include "core/lvmdevice.h"
#include "core/volumemanagerdevice.h"
#include <QString>
#include <QVector>
class ResizeVolumeGroupJob;
class MovePhysicalVolumeJob;
@ -28,7 +29,7 @@ class LIBKPMCORE_EXPORT ResizeVolumeGroupOperation : public Operation
friend class OperationStack;
public:
ResizeVolumeGroupOperation(LvmDevice& dev, const QVector<const Partition*>& partlist);
ResizeVolumeGroupOperation(VolumeManagerDevice& dev, const QVector<const Partition*>& partlist);
public:
QString iconName() const override {
@ -47,10 +48,10 @@ public:
QStringList getToInsertList();
protected:
LvmDevice& device() {
VolumeManagerDevice& device() {
return m_Device;
}
const LvmDevice& device() const {
const VolumeManagerDevice& device() const {
return m_Device;
}
const QVector<const Partition*>& targetList() const {
@ -82,7 +83,7 @@ protected:
}
private:
LvmDevice& m_Device;
VolumeManagerDevice& m_Device;
QVector<const Partition*> m_TargetList;
QVector<const Partition*> m_CurrentList;

View File

@ -281,7 +281,7 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode)
QList<Device *> availableDevices = scanDevices();
for (Device *device : std::as_const(availableDevices))
if (device->deviceNode() == deviceNode)
if (device && device->deviceNode() == deviceNode)
return device;
}
}

View File

@ -49,6 +49,14 @@ add_executable(kpmcore_externalcommand
util/externalcommandhelper.cpp
)
add_executable(kpmcore_mdadmupdateconf
util/mdadmupdateconf.cpp
)
add_definitions(
-DLIBEXECDIRPATH="${LIBEXEC_INSTALL_DIR}"
)
target_link_libraries(kpmcore_externalcommand
Qt5::Core
Qt5::DBus
@ -56,6 +64,7 @@ target_link_libraries(kpmcore_externalcommand
PolkitQt5-1::Core
)
install(TARGETS kpmcore_mdadmupdateconf DESTINATION ${LIBEXEC_INSTALL_DIR})
install(TARGETS kpmcore_externalcommand DESTINATION ${KDE_INSTALL_LIBEXECDIR})
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )

View File

@ -91,7 +91,8 @@ QStringLiteral("xfs_repair"),
QStringLiteral("mkfs.xfs"),
QStringLiteral("xfs_copy"),
QStringLiteral("xfs_growfs"),
QStringLiteral("zpool")
QStringLiteral("zpool"),
QStringLiteral("kpmcore_mdadmupdateconf")
};
#endif

View File

@ -0,0 +1,38 @@
/*
SPDX-FileCopyrightText: 2019 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <cstdlib>
#include <string>
using std::string;
using std::system;
/*
* Use this helper application to append content in the software raid configuration file or to rewrite it.
* Only rewrite if you want to replace *ALL* data.
*
* HOWTO:
* kpmcore_mdadmupdateconf --append [path] [raid configuration file path]
* kpmcore_mdadmupdateconf --write [path] [raid configuration file path]
*
*/
int main(int argc, char *argv[])
{
if (argc != 4)
return 1;
string command = "";
if (string(argv[1]) == "--append")
command = "mdadm --detail --scan " + string(argv[2]) + " >> " + string(argv[3]);
else if (string(argv[1]) == "--write")
command = "echo " + string(argv[2]) + " > " + string(argv[3]);
else
return 1;
return command != "" ? system(command.c_str()) : 1;
}