diff --git a/src/core/device.cpp b/src/core/device.cpp index f6acae1..d6f576c 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -1,179 +1,156 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "core/device.h" #include "core/device_p.h" #include "core/partitiontable.h" #include "core/smartstatus.h" #include "util/capacity.h" #include -/** Constructs a Device with an empty PartitionTable. - @param name the Device's name, usually some string defined by the manufacturer - @param deviceNode the Device's node, for example "/dev/sda" -*/ -Device::Device(const QString& name, - const QString& deviceNode, - const qint64 logicalSectorSize, - const qint64 totalLogicalSectors, - const QString& iconName, - Device::Type type) - : QObject() - , d(std::make_shared()) -{ - d->m_Name = name.length() > 0 ? name : i18n("Unknown Device"); - d->m_DeviceNode = deviceNode; - d->m_LogicalSectorSize = logicalSectorSize; - d->m_TotalLogical = totalLogicalSectors; - d->m_PartitionTable = nullptr; - d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; - d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; - d->m_Type = type; -} - /** Constructs a Device with an empty PartitionTable. @param name the Device's name, usually some string defined by the manufacturer @param deviceNode the Device's node, for example "/dev/sda" */ Device::Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName, Device::Type type) : QObject() , d(d_ptr) { d->m_Name = name.length() > 0 ? name : i18n("Unknown Device"); d->m_DeviceNode = deviceNode; d->m_LogicalSectorSize = logicalSectorSize; d->m_TotalLogical = totalLogicalSectors; d->m_PartitionTable = nullptr; d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; d->m_Type = type; } /** Copy constructor for Device. * @param other the other Device. */ Device::Device(const Device& other) : QObject() { d->m_Name = other.d->m_Name; d->m_DeviceNode = other.d->m_DeviceNode; d->m_LogicalSectorSize = other.d->m_LogicalSectorSize; d->m_TotalLogical = other.d->m_TotalLogical; d->m_PartitionTable = nullptr; d->m_IconName = other.d->m_IconName; d->m_SmartStatus = nullptr; d->m_Type = other.d->m_Type; d->m_SmartStatus = other.d->m_SmartStatus; if (other.d->m_PartitionTable) d->m_PartitionTable = new PartitionTable(*other.d->m_PartitionTable); } /** Destructs a Device. */ Device::~Device() { delete d->m_PartitionTable; } bool Device::operator==(const Device& other) const { return d->m_DeviceNode == other.d->m_DeviceNode; } bool Device::operator!=(const Device& other) const { return !(other == *this); } QString Device::prettyName() const { return xi18nc("@item:inlistbox Device name – Capacity (device node)", "%1 – %2 (%3)", name(), Capacity::formatByteSize(capacity()), deviceNode()); } QString& Device::name() { return d->m_Name; } const QString& Device::name() const { return d->m_Name; } const QString& Device::deviceNode() const { return d->m_DeviceNode; } qint64 Device::logicalSize() const { return d->m_LogicalSectorSize; } qint64 Device::totalLogical() const { return d->m_TotalLogical; } PartitionTable* Device::partitionTable() { return d->m_PartitionTable; } const PartitionTable* Device::partitionTable() const { return d->m_PartitionTable; } void Device::setPartitionTable(PartitionTable* ptable) { d->m_PartitionTable = ptable; } const QString& Device::iconName() const { return d->m_IconName; } void Device::setIconName(const QString& name) { d->m_IconName = name; } SmartStatus& Device::smartStatus() { return *(d->m_SmartStatus); } const SmartStatus& Device::smartStatus() const { return *(d->m_SmartStatus); } Device::Type Device::type() const { return d->m_Type; } diff --git a/src/core/device.h b/src/core/device.h index 393723a..f99e642 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -1,117 +1,115 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #ifndef KPMCORE_DEVICE_H #define KPMCORE_DEVICE_H #include "util/libpartitionmanagerexport.h" #include #include #include class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; class DevicePrivate; /** A device description. Represents a device like /dev/sda. Contains information about the device (name, status, size ..) but does not operate on the device itself. @see CoreBackendDevice Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. @see PartitionTable, Partition @author Volker Lanz */ class LIBKPMCORE_EXPORT Device : public QObject { Device &operator=(const Device &) = delete; friend class CreatePartitionTableOperation; friend class CoreBackend; public: enum Type { Disk_Device = 0, LVM_Device = 1, /* VG */ RAID_Device = 2, /* software RAID device */ Unknown_Device = 4 }; protected: - explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); - explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); public: explicit Device(const Device& other); virtual ~Device(); virtual bool operator==(const Device& other) const; virtual bool operator!=(const Device& other) const; /**< @return the Device's name, usually some manufacturer string */ virtual QString& name(); virtual const QString& name() const; /**< @return the Device's node, for example "/dev/sda" */ virtual const QString& deviceNode() const; /**< @return the logical sector size the Device uses (would be extent size for e.g. LVM devices) */ virtual qint64 logicalSize() const; /**< @return the total number of logical sectors on the device */ virtual qint64 totalLogical() const; /**< @return the Device's PartitionTable */ virtual PartitionTable* partitionTable(); virtual const PartitionTable* partitionTable() const; /** * Change the description of the partition table for different one. * The device itself is not changed; use CreatePartitionTableOperation * for that. The Device instance becomes the owner of @p ptable . */ virtual void setPartitionTable(PartitionTable* ptable); virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */ return logicalSize() * totalLogical(); } /**< @return suggested icon name for this Device */ virtual const QString& iconName() const; /**< @param name set the new Icon for this Device */ virtual void setIconName(const QString& name); virtual SmartStatus& smartStatus(); virtual const SmartStatus& smartStatus() const; virtual Device::Type type() const; virtual QString prettyName() const; protected: std::shared_ptr d; }; #endif diff --git a/src/core/device_p.h b/src/core/device_p.h index 688f3c5..97d152c 100644 --- a/src/core/device_p.h +++ b/src/core/device_p.h @@ -1,38 +1,43 @@ /************************************************************************* * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ +#ifndef KPMCORE_DEVICE_P_H +#define KPMCORE_DEVICE_P_H + #include "core/device.h" #include #include class PartitionTable; class SmartStatus; class DevicePrivate { public: QString m_Name; QString m_DeviceNode; qint64 m_LogicalSectorSize; qint64 m_TotalLogical; PartitionTable* m_PartitionTable; QString m_IconName; std::shared_ptr m_SmartStatus; Device::Type m_Type; }; + +#endif diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 0799c54..917410c 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -1,494 +1,557 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "core/lvmdevice.h" #include "core/partition.h" +#include "core/volumemanagerdevice_p.h" #include "fs/filesystem.h" #include "fs/lvm2_pv.h" #include "fs/luks.h" #include "fs/filesystemfactory.h" #include "core/partitiontable.h" #include "util/externalcommand.h" #include "util/helpers.h" #include "util/report.h" #include #include #include #include +#define d_ptr std::static_pointer_cast(d) + +class LvmDevicePrivate : public VolumeManagerDevicePrivate +{ +public: + qint64 m_peSize; + qint64 m_totalPE; + qint64 m_allocPE; + qint64 m_freePE; + QString m_UUID; + + mutable QStringList* m_LVPathList; + QVector m_PVs; + mutable QHash* m_LVSizeMap; +}; + /** Constructs a representation of LVM device with initialized LV as Partitions * * @param vgName Volume Group name * @param iconName Icon representing LVM Volume group */ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName) - : VolumeManagerDevice(vgName, + : VolumeManagerDevice(std::make_shared(), + vgName, (QStringLiteral("/dev/") + vgName), getPeSize(vgName), getTotalPE(vgName), iconName, Device::LVM_Device) { - m_peSize = logicalSize(); - m_totalPE = totalLogical(); - m_freePE = getFreePE(vgName); - m_allocPE = m_totalPE - m_freePE; - m_UUID = getUUID(vgName); - m_LVPathList = new QStringList(getLVs(vgName)); - m_LVSizeMap = new QHash(); + d_ptr->m_peSize = logicalSize(); + d_ptr->m_totalPE = totalLogical(); + d_ptr->m_freePE = getFreePE(vgName); + d_ptr->m_allocPE = d_ptr->m_totalPE - d_ptr->m_freePE; + d_ptr->m_UUID = getUUID(vgName); + d_ptr->m_LVPathList = new QStringList(getLVs(vgName)); + d_ptr->m_LVSizeMap = new QHash(); initPartitions(); } /** * shared list of PV's paths that will be added to any VGs. * (have been added to an operation, but not yet applied) */ QVector LvmDevice::s_DirtyPVs; LvmDevice::~LvmDevice() { - delete m_LVPathList; - delete m_LVSizeMap; + delete d_ptr->m_LVPathList; + delete d_ptr->m_LVSizeMap; } void LvmDevice::initPartitions() { qint64 firstUsable = 0; qint64 lastusable = totalPE() - 1; PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable); for (const auto &p : scanPartitions(pTable)) { LVSizeMap()->insert(p->partitionPath(), p->length()); pTable->append(p); } pTable->updateUnallocated(*this); setPartitionTable(pTable); } /** * @return an initialized Partition(LV) list */ const QList LvmDevice::scanPartitions(PartitionTable* pTable) const { QList pList; for (const auto &lvPath : partitionNodes()) { pList.append(scanPartition(lvPath, pTable)); } return pList; } /** scan and construct a partition(LV) at a given path * * NOTE: * LVM partition has 2 different start and end sector values * 1. representing the actual LV start from 0 -> size of LV - 1 * 2. representing abstract LV's sector inside a VG partitionTable * start from last sector + 1 of last Partitions -> size of LV - 1 * Reason for this is for the LV Partition to work nicely with other parts of the codebase * without too many special cases. * * @param lvPath LVM Logical Volume path * @param pTable Abstract partition table representing partitions of LVM Volume Group * @return initialized Partition(LV) */ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTable) const { activateLV(lvPath); qint64 lvSize = getTotalLE(lvPath); qint64 startSector = mappedSector(lvPath, 0); qint64 endSector = startSector + lvSize - 1; FileSystem::Type type = FileSystem::detectFileSystem(lvPath); FileSystem* fs = FileSystemFactory::create(type, 0, lvSize - 1, logicalSize()); fs->scan(lvPath); PartitionRole::Roles r = PartitionRole::Lvm_Lv; QString mountPoint; bool mounted; // Handle LUKS partition if (fs->type() == FileSystem::Type::Luks) { r |= PartitionRole::Luks; FS::luks* luksFs = static_cast(fs); luksFs->initLUKS(); QString mapperNode = luksFs->mapperName(); mountPoint = FileSystem::detectMountPoint(fs, mapperNode); mounted = FileSystem::detectMountStatus(fs, mapperNode); } else { mountPoint = FileSystem::detectMountPoint(fs, lvPath); mounted = FileSystem::detectMountStatus(fs, lvPath); if (mountPoint != QString() && fs->type() != FileSystem::Type::LinuxSwap) { const QStorageInfo storage = QStorageInfo(mountPoint); if (logicalSize() > 0 && fs->type() != FileSystem::Type::Luks && mounted && storage.isValid()) fs->setSectorsUsed( (storage.bytesTotal() - storage.bytesFree()) / logicalSize() ); } else if (fs->supportGetUsed() == FileSystem::cmdSupportFileSystem) fs->setSectorsUsed(qCeil(fs->readUsedCapacity(lvPath) / static_cast(logicalSize()))); } if (fs->supportGetLabel() != FileSystem::cmdSupportNone) { fs->setLabel(fs->readLabel(lvPath)); } if (fs->supportGetUUID() != FileSystem::cmdSupportNone) fs->setUUID(fs->readUUID(lvPath)); Partition* part = new Partition(pTable, *this, PartitionRole(r), fs, startSector, endSector, lvPath, PartitionTable::Flag::FlagNone, mountPoint, mounted); return part; } /** scan and construct list of initialized LvmDevice objects. * * @param devices list of initialized Devices */ void LvmDevice::scanSystemLVM(QList& devices) { QList lvmList; for (const auto &vgName : getVGs()) { lvmList.append(new LvmDevice(vgName)); } // Some LVM operations require additional information about LVM physical volumes which we store in LVM::pvList LVM::pvList = FS::lvm2_pv::getPVs(devices); // Look for LVM physical volumes in LVM VGs for (const auto &d : lvmList) { devices.append(d); LVM::pvList.append(FS::lvm2_pv::getPVinNode(d->partitionTable())); } // Inform LvmDevice about which physical volumes form that particular LvmDevice for (const auto &d : lvmList) for (const auto &p : qAsConst(LVM::pvList)) if (p.vgName() == d->name()) d->physicalVolumes().append(p.partition()); } qint64 LvmDevice::mappedSector(const QString& lvPath, qint64 sector) const { qint64 mSector = 0; QStringList lvpathList = partitionNodes(); qint32 devIndex = lvpathList.indexOf(lvPath); if (devIndex) { for (int i = 0; i < devIndex; i++) { mSector += LVSizeMap()->value(lvpathList[i]); } mSector += sector; } return mSector; } const QStringList LvmDevice::deviceNodes() const { QStringList pvList; for (const auto &p : physicalVolumes()) { if (p->roles().has(PartitionRole::Luks)) pvList << static_cast(&p->fileSystem())->mapperName(); else pvList << p->partitionPath(); } return pvList; } const QStringList LvmDevice::partitionNodes() const { return *LVPathList(); } qint64 LvmDevice::partitionSize(QString& partitionPath) const { return LVSizeMap()->value(partitionPath); } const QStringList LvmDevice::getVGs() { QStringList vgList; QString output = getField(QStringLiteral("vg_name")); if (!output.isEmpty()) { const QStringList vgNameList = output.split(QStringLiteral("\n"), QString::SkipEmptyParts); for (const auto &vgName : vgNameList) { vgList.append(vgName.trimmed()); } } return vgList; } const QStringList LvmDevice::getLVs(const QString& vgName) { QStringList lvPathList; QString cmdOutput = getField(QStringLiteral("lv_path"), vgName); if (cmdOutput.size()) { const QStringList tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts); for (const auto &lvPath : tempPathList) { lvPathList.append(lvPath.trimmed()); } } return lvPathList; } qint64 LvmDevice::getPeSize(const QString& vgName) { QString val = getField(QStringLiteral("vg_extent_size"), vgName); return val.isEmpty() ? -1 : val.toLongLong(); } qint64 LvmDevice::getTotalPE(const QString& vgName) { QString val = getField(QStringLiteral("vg_extent_count"), vgName); return val.isEmpty() ? -1 : val.toInt(); } qint64 LvmDevice::getAllocatedPE(const QString& vgName) { return getTotalPE(vgName) - getFreePE(vgName); } qint64 LvmDevice::getFreePE(const QString& vgName) { QString val = getField(QStringLiteral("vg_free_count"), vgName); return val.isEmpty() ? -1 : val.toInt(); } QString LvmDevice::getUUID(const QString& vgName) { QString val = getField(QStringLiteral("vg_uuid"), vgName); return val.isEmpty() ? QStringLiteral("---") : val; } /** Get LVM vgs command output with field name * * @param fieldName LVM field name * @param vgName the name of LVM Volume Group * @return raw output of command output, usually with many spaces within the returned string * */ QString LvmDevice::getField(const QString& fieldName, const QString& vgName) { QStringList args = { QStringLiteral("vgs"), QStringLiteral("--foreign"), QStringLiteral("--readonly"), QStringLiteral("--noheadings"), QStringLiteral("--units"), QStringLiteral("B"), QStringLiteral("--nosuffix"), QStringLiteral("--options"), fieldName }; if (!vgName.isEmpty()) { args << vgName; } ExternalCommand cmd(QStringLiteral("lvm"), args, QProcess::ProcessChannelMode::SeparateChannels); if (cmd.run(-1) && cmd.exitCode() == 0) { return cmd.output().trimmed(); } return QString(); } qint64 LvmDevice::getTotalLE(const QString& lvPath) { ExternalCommand cmd(QStringLiteral("lvm"), { QStringLiteral("lvdisplay"), lvPath}); if (cmd.run(-1) && cmd.exitCode() == 0) { QRegularExpression re(QStringLiteral("Current LE\\h+(\\d+)")); QRegularExpressionMatch match = re.match(cmd.output()); if (match.hasMatch()) { return match.captured(1).toInt(); } } return -1; } bool LvmDevice::removeLV(Report& report, LvmDevice& d, Partition& p) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvremove"), QStringLiteral("--yes"), p.partitionPath()}); if (cmd.run(-1) && cmd.exitCode() == 0) { d.partitionTable()->remove(&p); return true; } return false; } bool LvmDevice::createLV(Report& report, LvmDevice& d, Partition& p, const QString& lvName) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvcreate"), QStringLiteral("--yes"), QStringLiteral("--extents"), QString::number(p.length()), QStringLiteral("--name"), lvName, d.name()}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::createLVSnapshot(Report& report, Partition& p, const QString& name, const qint64 extents) { QString numExtents = (extents > 0) ? QString::number(extents) : QString::number(p.length()); ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvcreate"), QStringLiteral("--yes"), QStringLiteral("--extents"), numExtents, QStringLiteral("--snapshot"), QStringLiteral("--name"), name, p.partitionPath() }); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::resizeLV(Report& report, Partition& p) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvresize"), QStringLiteral("--force"), QStringLiteral("--yes"), QStringLiteral("--extents"), QString::number(p.length()), p.partitionPath()}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::removePV(Report& report, LvmDevice& d, const QString& pvPath) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgreduce"), d.name(), pvPath}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::insertPV(Report& report, LvmDevice& d, const QString& pvPath) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgextend"), QStringLiteral("--yes"), d.name(), pvPath}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList& destinations) { if (FS::lvm2_pv::getAllocatedPE(pvPath) <= 0) return true; QStringList args = QStringList(); args << QStringLiteral("pvmove"); args << pvPath; if (!destinations.isEmpty()) for (const auto &destPath : destinations) args << destPath.trimmed(); ExternalCommand cmd(report, QStringLiteral("lvm"), args); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::createVG(Report& report, const QString vgName, const QVector& pvList, const qint32 peSize) { QStringList args = QStringList(); args << QStringLiteral("vgcreate") << QStringLiteral("--physicalextentsize") << QString::number(peSize); args << vgName; for (const auto &p : pvList) { if (p->roles().has(PartitionRole::Luks)) args << static_cast(&p->fileSystem())->mapperName(); else args << p->partitionPath(); } ExternalCommand cmd(report, QStringLiteral("lvm"), args); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::removeVG(Report& report, LvmDevice& d) { bool deactivated = deactivateVG(report, d); ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgremove"), QStringLiteral("--force"), d.name() }); return (deactivated && cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::deactivateVG(Report& report, const LvmDevice& d) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("vgchange"), QStringLiteral("--activate"), QStringLiteral("n"), d.name() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::deactivateLV(Report& report, const Partition& p) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("lvchange"), QStringLiteral("--activate"), QStringLiteral("n"), p.partitionPath() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::activateVG(Report& report, const LvmDevice& d) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("vgchange"), QStringLiteral("--activate"), QStringLiteral("y"), d.name() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::activateLV(const QString& lvPath) { ExternalCommand deactivate(QStringLiteral("lvm"), { QStringLiteral("lvchange"), QStringLiteral("--activate"), QStringLiteral("y"), lvPath }); return deactivate.run(-1) && deactivate.exitCode() == 0; } + +qint64 LvmDevice::peSize() const +{ + return d_ptr->m_peSize; +} + +qint64 LvmDevice::totalPE() const +{ + return d_ptr->m_totalPE; +} + +qint64 LvmDevice::allocatedPE() const +{ + return d_ptr->m_allocPE; +} + +qint64 LvmDevice::freePE() const +{ + return d_ptr->m_freePE; +} + +QString LvmDevice::UUID() const +{ + return d_ptr->m_UUID; +} + +QStringList* LvmDevice::LVPathList() const +{ + return d_ptr->m_LVPathList; +} + +QVector & LvmDevice::physicalVolumes() +{ + return d_ptr->m_PVs; +} + +const QVector & LvmDevice::physicalVolumes() const +{ + return d_ptr->m_PVs; +} + +QHash* LvmDevice::LVSizeMap() const +{ + return d_ptr->m_LVSizeMap; +} diff --git a/src/core/lvmdevice.h b/src/core/lvmdevice.h index 8a49263..08b768e 100644 --- a/src/core/lvmdevice.h +++ b/src/core/lvmdevice.h @@ -1,142 +1,109 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_LVMDEVICE_H) - +#ifndef KPMCORE_LVMDEVICE_H #define KPMCORE_LVMDEVICE_H #include "core/device.h" #include "core/volumemanagerdevice.h" #include "util/libpartitionmanagerexport.h" #include #include #include #include #include #include class PartitionTable; class Report; class Partition; class SmartStatus; /** Representation of LVM Volume Group(VG). Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. @see Device, VolumeManagerDevice, PartitionTable, Partition */ class LIBKPMCORE_EXPORT LvmDevice : public VolumeManagerDevice { Q_DISABLE_COPY(LvmDevice) public: LvmDevice(const QString& name, const QString& iconName = QString()); ~LvmDevice(); public: const QStringList deviceNodes() const override; const QStringList partitionNodes() const override; qint64 partitionSize(QString& partitionPath) const override; static QVector s_DirtyPVs; -public: static void scanSystemLVM(QList& devices); static const QStringList getVGs(); static const QStringList getLVs(const QString& vgName); static qint64 getPeSize(const QString& vgName); static qint64 getTotalPE(const QString& vgName); static qint64 getAllocatedPE(const QString& vgName); static qint64 getFreePE(const QString& vgName); static QString getUUID(const QString& vgName); static QString getField(const QString& fieldName, const QString& vgName = QString()); static qint64 getTotalLE(const QString& lvPath); static bool removeLV(Report& report, LvmDevice& d, Partition& p); static bool createLV(Report& report, LvmDevice& d, Partition& p, const QString& lvName); static bool createLVSnapshot(Report& report, Partition& p, const QString& name, const qint64 extents = 0); static bool resizeLV(Report& report, Partition& p); static bool deactivateLV(Report& report, const Partition& p); static bool activateLV(const QString& deviceNode); static bool removePV(Report& report, LvmDevice& d, const QString& pvPath); static bool insertPV(Report& report, LvmDevice& d, const QString& pvPath); static bool movePV(Report& report, const QString& pvPath, const QStringList& destinations = QStringList()); static bool removeVG(Report& report, LvmDevice& d); static bool createVG(Report& report, const QString vgName, const QVector& pvList, const qint32 peSize = 4); // peSize in megabytes static bool deactivateVG(Report& report, const LvmDevice& d); static bool activateVG(Report& report, const LvmDevice& d); protected: - void initPartitions() override; const QList scanPartitions(PartitionTable* pTable) const; Partition* scanPartition(const QString& lvPath, PartitionTable* pTable) const; qint64 mappedSector(const QString& lvPath, qint64 sector) const override; public: - qint64 peSize() const { - return m_peSize; - } - qint64 totalPE() const { - return m_totalPE; - } - qint64 allocatedPE() const { - return m_allocPE; - } - qint64 freePE() const { - return m_freePE; - } - QString UUID() const { - return m_UUID; - } - QStringList* LVPathList() const { - return m_LVPathList; - } - QVector & physicalVolumes() { - return m_PVs; - } - const QVector & physicalVolumes() const { - return m_PVs; - } + qint64 peSize() const; + qint64 totalPE() const; + qint64 allocatedPE() const; + qint64 freePE() const; + QString UUID() const; + QStringList* LVPathList() const; + QVector & physicalVolumes(); + const QVector & physicalVolumes() const; protected: - QHash* LVSizeMap() const { - return m_LVSizeMap; - } - -private: - qint64 m_peSize; - qint64 m_totalPE; - qint64 m_allocPE; - qint64 m_freePE; - QString m_UUID; - - mutable QStringList* m_LVPathList; - QVector m_PVs; - mutable QHash* m_LVSizeMap; - + QHash* LVSizeMap() const; }; #endif diff --git a/src/core/volumemanagerdevice.cpp b/src/core/volumemanagerdevice.cpp index 8dc9659..7c339af 100644 --- a/src/core/volumemanagerdevice.cpp +++ b/src/core/volumemanagerdevice.cpp @@ -1,44 +1,49 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "core/device_p.h" #include "core/volumemanagerdevice.h" +#include "core/volumemanagerdevice_p.h" /** Constructs an abstract Volume Manager Device with an empty PartitionTable. * + * @param name the Device's name + * @param deviceNode the Device's node + * @param logicalExtentSize the logical extent size that device uses */ -VolumeManagerDevice::VolumeManagerDevice(const QString& name, +VolumeManagerDevice::VolumeManagerDevice(std::shared_ptr d, + const QString& name, const QString& deviceNode, - const qint64 logicalSize, + const qint64 logicalExtentSize, const qint64 totalLogical, const QString& iconName, Device::Type type) - : Device(name, deviceNode, logicalSize, totalLogical, iconName, type) + : Device(std::static_pointer_cast(d), name, deviceNode, logicalExtentSize, totalLogical, iconName, type) { } QString VolumeManagerDevice::prettyDeviceNodeList() const { return deviceNodes().join(QStringLiteral(", ")); } void VolumeManagerDevice::setTotalLogical(qint64 n) { Q_ASSERT(n > 0); d->m_TotalLogical = n; } diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index be59eb5..60dd4d3 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -1,95 +1,96 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #ifndef KPMCORE_VOLUMEMANAGERDEVICE_H #define KPMCORE_VOLUMEMANAGERDEVICE_H #include "util/libpartitionmanagerexport.h" #include "core/device.h" #include #include #include #include +class VolumeManagerDevicePrivate; + /** A Volume Manager of physical devices represented as an abstract device. * * VolumeManagerDevice is an abstract device class for volume manager. e.g: LVM, SoftRAID. * example of physical device: /dev/sda, /dev/sdb1. * * Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. * * @see Device, PartitionTable, Partition */ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device { Q_DISABLE_COPY(VolumeManagerDevice) public: - - VolumeManagerDevice(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device); + VolumeManagerDevice(std::shared_ptr d, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device); /** * @return list of physical device's path that makes up volumeManagerDevice.(e.g: /dev/sda, /dev/sdb1) */ virtual const QStringList deviceNodes() const = 0; /** * @return list of logical partition's path. */ virtual const QStringList partitionNodes() const = 0; /** * @return size of logical partition at the given path in bytes. */ virtual qint64 partitionSize(QString& partitionPath) const = 0; protected: /** Initialize device's partition table and partitions. * */ virtual void initPartitions() = 0; /** absolute sector as represented inside the device's partitionTable * * For VolumeMangerDevice to works with the rest of the codebase, partitions are stringed * one after another to create a representation of PartitionTable and partition just like * real disk device. * * @param partitionPath logical partition path * @sector sector value to be mapped (if 0, will return start sector of the partition) * @return absolute sector value as represented inside device's partitionTable */ virtual qint64 mappedSector(const QString& partitionPath, qint64 sector) const = 0; public: /** join deviceNodes together into comma-separated list * * @return comma-separated list of deviceNodes */ virtual QString prettyDeviceNodeList() const; /** Resize device total number of logical sectors. * * @param n Number of sectors. */ void setTotalLogical(qint64 n); }; #endif diff --git a/src/core/device_p.h b/src/core/volumemanagerdevice_p.h similarity index 76% copy from src/core/device_p.h copy to src/core/volumemanagerdevice_p.h index 688f3c5..6061c26 100644 --- a/src/core/device_p.h +++ b/src/core/volumemanagerdevice_p.h @@ -1,38 +1,27 @@ /************************************************************************* * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ -#include "core/device.h" +#ifndef KPMCORE_VOLUMEMANAGERDEVICE_P_H +#define KPMCORE_VOLUMEMANAGERDEVICE_P_H -#include +#include "core/device_p.h" -#include - -class PartitionTable; -class SmartStatus; - -class DevicePrivate +class VolumeManagerDevicePrivate : public DevicePrivate { -public: - QString m_Name; - QString m_DeviceNode; - qint64 m_LogicalSectorSize; - qint64 m_TotalLogical; - PartitionTable* m_PartitionTable; - QString m_IconName; - std::shared_ptr m_SmartStatus; - Device::Type m_Type; }; + +#endif