Support inactive RAID devices.
This commit is contained in:
parent
5828e9daac
commit
a0b9a93b6b
|
@ -39,9 +39,10 @@ public:
|
||||||
qint64 m_arraySize;
|
qint64 m_arraySize;
|
||||||
QString m_UUID;
|
QString m_UUID;
|
||||||
QStringList m_devicePathList;
|
QStringList m_devicePathList;
|
||||||
|
bool m_active;
|
||||||
};
|
};
|
||||||
|
|
||||||
SoftwareRAID::SoftwareRAID(const QString& name, const QString& iconName)
|
SoftwareRAID::SoftwareRAID(const QString& name, bool active, const QString& iconName)
|
||||||
: VolumeManagerDevice(std::make_shared<SoftwareRAIDPrivate>(),
|
: VolumeManagerDevice(std::make_shared<SoftwareRAIDPrivate>(),
|
||||||
name,
|
name,
|
||||||
(QStringLiteral("/dev/") + name),
|
(QStringLiteral("/dev/") + name),
|
||||||
|
@ -56,6 +57,7 @@ SoftwareRAID::SoftwareRAID(const QString& name, const QString& iconName)
|
||||||
d_ptr->m_arraySize = getArraySize(deviceNode());
|
d_ptr->m_arraySize = getArraySize(deviceNode());
|
||||||
d_ptr->m_UUID = getUUID(deviceNode());
|
d_ptr->m_UUID = getUUID(deviceNode());
|
||||||
d_ptr->m_devicePathList = getDevicePathList(deviceNode());
|
d_ptr->m_devicePathList = getDevicePathList(deviceNode());
|
||||||
|
d_ptr->m_active = active;
|
||||||
|
|
||||||
initPartitions();
|
initPartitions();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +94,23 @@ bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices)
|
||||||
|
|
||||||
QString SoftwareRAID::prettyName() const
|
QString SoftwareRAID::prettyName() const
|
||||||
{
|
{
|
||||||
return VolumeManagerDevice::prettyName() + xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel());
|
return VolumeManagerDevice::prettyName() +
|
||||||
|
(isActive() ? xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()) :
|
||||||
|
QStringLiteral(" [RAID]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SoftwareRAID::operator ==(const Device& other) const
|
||||||
|
{
|
||||||
|
bool equalDeviceNode = Device::operator ==(other);
|
||||||
|
|
||||||
|
if (other.type() == Device::Type::SoftwareRAID_Device) {
|
||||||
|
const SoftwareRAID& raid = static_cast<const SoftwareRAID&>(other);
|
||||||
|
|
||||||
|
if (!equalDeviceNode)
|
||||||
|
return raid.uuid() == uuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
return equalDeviceNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint32 SoftwareRAID::raidLevel() const
|
qint32 SoftwareRAID::raidLevel() const
|
||||||
|
@ -125,9 +143,37 @@ QStringList SoftwareRAID::devicePathList() const
|
||||||
return d_ptr->m_devicePathList;
|
return d_ptr->m_devicePathList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SoftwareRAID::isActive() const
|
||||||
|
{
|
||||||
|
return d_ptr->m_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftwareRAID::setActive(bool active)
|
||||||
|
{
|
||||||
|
d_ptr->m_active = active;
|
||||||
|
}
|
||||||
|
|
||||||
void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
|
void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
|
||||||
{
|
{
|
||||||
// TODO: Check configuration file and load all the devices that aren't in /proc/mdstat as innactive
|
QList<Device *> scannedRaid;
|
||||||
|
|
||||||
|
// TODO: Support custom config files.
|
||||||
|
QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf"));
|
||||||
|
|
||||||
|
if (!config.isEmpty()) {
|
||||||
|
QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/([\\/\\w-]+)"));
|
||||||
|
QRegularExpressionMatchIterator i = re.globalMatch(config);
|
||||||
|
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QRegularExpressionMatch reMatch = i.next();
|
||||||
|
QString deviceName = reMatch.captured(1).trimmed();
|
||||||
|
|
||||||
|
SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, false);
|
||||||
|
|
||||||
|
scannedRaid << raidDevice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") });
|
ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") });
|
||||||
|
|
||||||
if (scanRaid.run(-1) && scanRaid.exitCode() == 0) {
|
if (scanRaid.run(-1) && scanRaid.exitCode() == 0) {
|
||||||
|
@ -136,14 +182,18 @@ void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
QRegularExpressionMatch reMatch = i.next();
|
QRegularExpressionMatch reMatch = i.next();
|
||||||
|
|
||||||
QString deviceNode = QStringLiteral("/dev/") + QStringLiteral("md") + reMatch.captured(1).trimmed();
|
QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed();
|
||||||
|
|
||||||
Device* d = CoreBackendManager::self()->backend()->scanDevice(deviceNode);
|
SoftwareRAID* d = static_cast<SoftwareRAID *>(CoreBackendManager::self()->backend()->scanDevice(deviceNode));
|
||||||
|
|
||||||
if ( d )
|
if (scannedRaid.contains(d))
|
||||||
devices << d;
|
d->setActive(true);
|
||||||
|
else
|
||||||
|
scannedRaid << d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devices << scannedRaid;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint32 SoftwareRAID::getRaidLevel(const QString &path)
|
qint32 SoftwareRAID::getRaidLevel(const QString &path)
|
||||||
|
@ -193,8 +243,51 @@ qint64 SoftwareRAID::getArraySize(const QString &path)
|
||||||
|
|
||||||
QString SoftwareRAID::getUUID(const QString &path)
|
QString SoftwareRAID::getUUID(const QString &path)
|
||||||
{
|
{
|
||||||
Q_UNUSED(path)
|
QString output = getDetail(path);
|
||||||
return QStringLiteral();
|
|
||||||
|
if (!output.isEmpty()) {
|
||||||
|
QRegularExpression re(QStringLiteral("UUID :\\s+([\\w:]+)"));
|
||||||
|
QRegularExpressionMatch reMatch = re.match(output);
|
||||||
|
|
||||||
|
if (reMatch.hasMatch())
|
||||||
|
return reMatch.captured(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"));
|
||||||
|
|
||||||
|
if (!config.isEmpty()) {
|
||||||
|
QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/md([\\/\\w-]+)(.*)"));
|
||||||
|
QRegularExpressionMatchIterator i = re.globalMatch(config);
|
||||||
|
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QRegularExpressionMatch reMatch = i.next();
|
||||||
|
QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed();
|
||||||
|
QString otherInfo = reMatch.captured(2).trimmed();
|
||||||
|
|
||||||
|
// Consider device node as name=host:deviceNode when the captured device node string has '-' character
|
||||||
|
// It happens when user have included the device to config file using 'mdadm --examine --scan'
|
||||||
|
if (deviceNode.contains(QLatin1Char('-'))) {
|
||||||
|
QRegularExpression reName(QStringLiteral("name=[\\w:]+\\/dev\\/md\\/([\\/\\w]+)"));
|
||||||
|
QRegularExpressionMatch nameMatch = reName.match(otherInfo);
|
||||||
|
|
||||||
|
if (nameMatch.hasMatch())
|
||||||
|
deviceNode = nameMatch.captured(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceNode == path) {
|
||||||
|
QRegularExpression reUUID(QStringLiteral("(UUID=|uuid=)([\\w:]+)"));
|
||||||
|
QRegularExpressionMatch uuidMatch = reUUID.match(otherInfo);
|
||||||
|
|
||||||
|
if (uuidMatch.hasMatch())
|
||||||
|
return uuidMatch.captured(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList SoftwareRAID::getDevicePathList(const QString &path)
|
QStringList SoftwareRAID::getDevicePathList(const QString &path)
|
||||||
|
@ -266,5 +359,12 @@ QString SoftwareRAID::getDetail(const QString &path)
|
||||||
{
|
{
|
||||||
ExternalCommand cmd(QStringLiteral("mdadm"),
|
ExternalCommand cmd(QStringLiteral("mdadm"),
|
||||||
{ QStringLiteral("--misc"), QStringLiteral("--detail"), path });
|
{ QStringLiteral("--misc"), QStringLiteral("--detail"), path });
|
||||||
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QStringLiteral();
|
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath)
|
||||||
|
{
|
||||||
|
ExternalCommand cmd(QStringLiteral("cat"), { configurationPath });
|
||||||
|
|
||||||
|
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class LIBKPMCORE_EXPORT SoftwareRAID : public VolumeManagerDevice
|
||||||
Q_DISABLE_COPY(SoftwareRAID)
|
Q_DISABLE_COPY(SoftwareRAID)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoftwareRAID(const QString& name, const QString& iconName = QString());
|
SoftwareRAID(const QString& name, bool active = true, const QString& iconName = QString());
|
||||||
|
|
||||||
const QStringList deviceNodes() const override;
|
const QStringList deviceNodes() const override;
|
||||||
const QStringList& partitionNodes() const override;
|
const QStringList& partitionNodes() const override;
|
||||||
|
@ -39,12 +39,17 @@ public:
|
||||||
|
|
||||||
virtual QString prettyName() const override;
|
virtual QString prettyName() const override;
|
||||||
|
|
||||||
|
virtual bool operator==(const Device& other) const override;
|
||||||
|
|
||||||
qint32 raidLevel() const;
|
qint32 raidLevel() const;
|
||||||
qint64 chunkSize() const;
|
qint64 chunkSize() const;
|
||||||
qint64 totalChunk() const;
|
qint64 totalChunk() const;
|
||||||
qint64 arraySize() const;
|
qint64 arraySize() const;
|
||||||
QString uuid() const;
|
QString uuid() const;
|
||||||
QStringList devicePathList() const;
|
QStringList devicePathList() const;
|
||||||
|
bool isActive() const;
|
||||||
|
|
||||||
|
void setActive(bool active);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void scanSoftwareRAID(QList<Device*>& devices);
|
static void scanSoftwareRAID(QList<Device*>& devices);
|
||||||
|
@ -80,6 +85,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QString getDetail(const QString& path);
|
static QString getDetail(const QString& path);
|
||||||
|
|
||||||
|
static QString getRAIDConfiguration(const QString& configurationPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SOFTWARERAID_H
|
#endif // SOFTWARERAID_H
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
#include "core/partitiontable.h"
|
#include "core/partitiontable.h"
|
||||||
#include "core/partition.h"
|
#include "core/partition.h"
|
||||||
|
#include "core/raid/softwareraid.h"
|
||||||
|
|
||||||
#include "jobs/createpartitiontablejob.h"
|
#include "jobs/createpartitiontablejob.h"
|
||||||
|
|
||||||
|
@ -93,7 +94,18 @@ bool CreatePartitionTableOperation::execute(Report& parent)
|
||||||
*/
|
*/
|
||||||
bool CreatePartitionTableOperation::canCreate(const Device* device)
|
bool CreatePartitionTableOperation::canCreate(const Device* device)
|
||||||
{
|
{
|
||||||
return (device != nullptr) && (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted()) && (device->type() != Device::Type::LVM_Device);
|
if (device == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (device->type() == Device::Type::SoftwareRAID_Device) {
|
||||||
|
const SoftwareRAID* raid = static_cast<const SoftwareRAID *>(device);
|
||||||
|
|
||||||
|
if (!raid->isActive())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted())
|
||||||
|
&& (device->type() != Device::Type::LVM_Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CreatePartitionTableOperation::description() const
|
QString CreatePartitionTableOperation::description() const
|
||||||
|
|
Loading…
Reference in New Issue