Compare commits
39 Commits
master
...
raid-suppo
Author | SHA1 | Date |
---|---|---|
Andrius Štikonas | b620b0caaf | |
Andrius Štikonas | 83571aa0ef | |
Andrius Štikonas | 21c685b528 | |
Andrius Štikonas | 2d8a800a6d | |
Andrius Štikonas | 1d3458fb0a | |
Andrius Štikonas | 4a52757009 | |
Andrius Štikonas | 0fafc228ed | |
Andrius Štikonas | fa7d5a200f | |
Caio Carvalho | a4d75750f1 | |
Caio Carvalho | 5da3eacdc9 | |
Caio Carvalho | a57bd8846e | |
Andrius Štikonas | 90ebdb9b42 | |
Andrius Štikonas | c2ed6634df | |
Caio Carvalho | 355c37097a | |
Caio Carvalho | 6ab2143158 | |
Caio Carvalho | daacc0bfb7 | |
Caio Carvalho | 6a349f7bc8 | |
Caio Carvalho | 3ada811de7 | |
Caio Carvalho | ecc5dc8a4f | |
Caio Carvalho | f269144474 | |
Caio Carvalho | 7429ff7527 | |
Andrius Štikonas | 32eacc4db6 | |
Caio Carvalho | b47c52b367 | |
Caio Carvalho | 4353de0f05 | |
Caio Carvalho | 8083306d66 | |
Caio Carvalho | aaffe54161 | |
Caio Carvalho | d676c8c504 | |
Caio Carvalho | 22e857a072 | |
Caio Carvalho | 58a11262f7 | |
Caio Carvalho | 7863564e35 | |
Caio Carvalho | 6ab3f854e7 | |
Andrius Štikonas | 4ec2d2444b | |
Caio Carvalho | 1c714c7854 | |
Caio Carvalho | 213162c1a8 | |
Caio Carvalho | be89331db0 | |
Caio Carvalho | d7650c51df | |
Caio Carvalho | 6ddb69b661 | |
Caio Carvalho | 51d295ca5d | |
Caio Carvalho | fed87159da |
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,8 +9,14 @@
|
|||
|
||||
#include "core/device_p.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
class Partition;
|
||||
|
||||
class VolumeManagerDevicePrivate : public DevicePrivate
|
||||
{
|
||||
public:
|
||||
QVector<const Partition*> m_PVs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -31,6 +31,7 @@ set(JOBS_SRC
|
|||
jobs/setpartflagsjob.cpp
|
||||
jobs/copyfilesystemjob.cpp
|
||||
jobs/movefilesystemjob.cpp
|
||||
jobs/activateraidjob.cpp
|
||||
)
|
||||
|
||||
set(JOBS_LIB_HDRS
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ QStringLiteral("xfs_repair"),
|
|||
QStringLiteral("mkfs.xfs"),
|
||||
QStringLiteral("xfs_copy"),
|
||||
QStringLiteral("xfs_growfs"),
|
||||
QStringLiteral("zpool")
|
||||
QStringLiteral("zpool"),
|
||||
QStringLiteral("kpmcore_mdadmupdateconf")
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue