mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-10-05 18:01:23 +00:00
Implemented detection of device type.
This commit is contained in:
1 parent
6594cddb65
commit
c3a6f0b624
6 files changed
+74
-36
No files matched your search
@@ -72,8 +72,6 @@ hz::ExpectedVoid<SmartctlParserError> SmartctlJsonBasicParser::parse_section_bas
|
||||
{
|
||||
using namespace SmartctlJsonParserHelpers;
|
||||
|
||||
// TODO CD/DVD, RAID
|
||||
|
||||
bool smart_supported = true; // TODO
|
||||
bool smart_enabled = true; // TODO
|
||||
|
||||
@@ -97,6 +95,8 @@ hz::ExpectedVoid<SmartctlParserError> SmartctlJsonBasicParser::parse_section_bas
|
||||
// 2. Present in devices for which we do not have specialized parsers (USB, etc.)
|
||||
static const std::vector<std::tuple<std::string, std::string, PropertyRetrievalFunc>> info_keys = {
|
||||
|
||||
{"device/type", _("Smartctl Device Type"), string_formatter()}, // nvme, sat, etc.
|
||||
|
||||
{"vendor", _("Vendor"), string_formatter()}, // Flash drive
|
||||
{"product", _("Product"), string_formatter()}, // Flash drive
|
||||
|
||||
|
||||
@@ -11,12 +11,17 @@ Copyright:
|
||||
|
||||
#include <locale>
|
||||
#include <cctype> // isspace
|
||||
#include <utility>
|
||||
#include <string_view>
|
||||
|
||||
#include "smartctl_parser.h"
|
||||
#include "ata_storage_property.h"
|
||||
#include "hz/error_container.h"
|
||||
#include "smartctl_text_ata_parser.h"
|
||||
#include "smartctl_json_ata_parser.h"
|
||||
#include "smartctl_json_basic_parser.h"
|
||||
#include "smartctl_text_basic_parser.h"
|
||||
#include "storage_property_repository.h"
|
||||
//#include "ata_storage_property_descr.h"
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ Copyright:
|
||||
|
||||
#include "smartctl_parser_types.h"
|
||||
#include "ata_storage_property_descr.h"
|
||||
#include "storage_device_detected_type.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Copyright:
|
||||
#include "local_glibmm.h"
|
||||
#include <gtkmm.h> // compose()
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
@@ -9,25 +9,36 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#include "build_config.h"
|
||||
#include "storage_detector_linux.h"
|
||||
|
||||
#include "command_executor.h"
|
||||
#include "local_glibmm.h"
|
||||
|
||||
#include <algorithm> // std::find
|
||||
#include <cstdio> // std::fgets(), std::FILE
|
||||
// #include <cerrno> // ENXIO
|
||||
#include <memory>
|
||||
#include <pcrecpp.h>
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#include <utility> // std::pair
|
||||
#include <string>
|
||||
|
||||
#include "build_config.h"
|
||||
#include "command_executor_factory.h"
|
||||
#include "hz/error_container.h"
|
||||
#include "hz/string_algo.h"
|
||||
#include "hz/debug.h"
|
||||
#include "hz/fs.h"
|
||||
#include "hz/string_num.h"
|
||||
#include "rconfig/rconfig.h"
|
||||
#include "app_pcrecpp.h"
|
||||
#include "storage_detector_linux.h"
|
||||
#include "storage_detector.h"
|
||||
#include "storage_detector_helpers.h"
|
||||
#include "storage_device.h"
|
||||
|
||||
|
||||
|
||||
@@ -298,7 +309,7 @@ inline std::string read_proc_scsi_sg_devices_file(std::vector<std::vector<int>>&
|
||||
R"(^([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+))");
|
||||
|
||||
for (std::size_t i = 0; i < lines.size(); ++i) {
|
||||
std::string trimmed = hz::string_trim_copy(lines[i]);
|
||||
const std::string trimmed = hz::string_trim_copy(lines[i]);
|
||||
std::vector<std::string> line(9);
|
||||
if (parse_re.PartialMatch(trimmed, &line[0], &line[1], &line[2], &line[3], &line[4], &line[5], &line[6], &line[7], &line[8])) {
|
||||
std::vector<int> line_num(line.size(), -1);
|
||||
@@ -371,7 +382,7 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_proc_partition
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Detecting drives through partitions file (/proc/partitions by default; set \"system/linux_proc_partitions_path\" config key to override).\n");
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::string error_msg = read_proc_partitions_file(lines);
|
||||
const std::string error_msg = read_proc_partitions_file(lines);
|
||||
if (!error_msg.empty()) {
|
||||
return hz::Unexpected(StorageDetectorError::ProcReadError, error_msg);
|
||||
}
|
||||
@@ -410,7 +421,7 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_proc_partition
|
||||
if (blacked)
|
||||
continue;
|
||||
|
||||
std::string path = "/dev/" + dev; // let's just hope it's really /dev.
|
||||
const std::string path = "/dev/" + dev; // let's just hope it's really /dev.
|
||||
if (std::find(devices.begin(), devices.end(), path) == devices.end()) { // there may be duplicates
|
||||
devices.push_back(path);
|
||||
}
|
||||
@@ -525,7 +536,7 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_3ware(
|
||||
continue; // not a supported controller
|
||||
}
|
||||
|
||||
int host_num = vendor_model.first;
|
||||
const int host_num = vendor_model.first;
|
||||
|
||||
debug_out_dump("app", "Found LSI/AMCC/3ware controller in SCSI file, SCSI host " << host_num << ".\n");
|
||||
|
||||
@@ -557,7 +568,7 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_3ware(
|
||||
// else we default to twl, twa, twe (in this order)
|
||||
}
|
||||
|
||||
// We can't map twaX to scsiY, so lets assume the relative order is the same.
|
||||
// We can't map twaX to scsiY, so let's assume the relative order is the same.
|
||||
std::string dev = std::string("/dev/") + dev_base + hz::number_to_string_nolocale(device_numbers[dev_base]);
|
||||
++device_numbers[dev_base];
|
||||
|
||||
@@ -651,7 +662,7 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_adaptec(
|
||||
if (!app_pcre_match("/Vendor: Adaptec /i", vendors_model.second)) {
|
||||
continue; // not a supported controller
|
||||
}
|
||||
int host_num = vendors_model.first;
|
||||
const int host_num = vendors_model.first;
|
||||
debug_out_dump("app", "Found Adaptec controller in SCSI file, SCSI host " << host_num << ".\n");
|
||||
|
||||
// Skip additional adapters with the same host, since they are the same adapters
|
||||
@@ -673,11 +684,11 @@ inline hz::ExpectedVoid<StorageDetectorError> detect_drives_linux_adaptec(
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string dev = std::string("/dev/sg") + hz::number_to_string_nolocale(sg_num);
|
||||
const std::string dev = std::string("/dev/sg") + hz::number_to_string_nolocale(sg_num);
|
||||
auto drive = std::make_shared<StorageDevice>(dev, std::string("sat"));
|
||||
|
||||
auto fetch_status = drive->fetch_basic_data_and_parse(smartctl_ex);
|
||||
std::string output = drive->get_basic_output();
|
||||
const std::string output = drive->get_basic_output();
|
||||
|
||||
// Note: Not sure about this, have to check with real SAS drives
|
||||
if (app_pcre_match("/Device Read Identity Failed/mi", output)) {
|
||||
|
||||
@@ -34,6 +34,7 @@ Copyright:
|
||||
#include "smartctl_executor.h"
|
||||
#include "smartctl_version_parser.h"
|
||||
#include "ata_storage_property_descr.h"
|
||||
#include "build_config.h"
|
||||
//#include "smartctl_text_parser_helper.h"
|
||||
//#include "ata_storage_property_descr.h"
|
||||
|
||||
@@ -160,7 +161,7 @@ hz::ExpectedVoid<StorageDeviceError> StorageDevice::parse_basic_data()
|
||||
auto basic_parser = SmartctlParser::create(SmartctlParserType::Basic, SmartctlOutputFormat::Json);
|
||||
DBG_ASSERT_RETURN(basic_parser, hz::Unexpected(StorageDeviceError::ParseError, _("Cannot create parser")));
|
||||
|
||||
// This also detects the drive type and adds it to "_custom/parser_detected_drive_type" property.
|
||||
// This also fills the drive type properties.
|
||||
auto parse_status = basic_parser->parse(this->get_basic_output());
|
||||
if (!parse_status) {
|
||||
return hz::Unexpected(StorageDeviceError::ParseError,
|
||||
@@ -168,7 +169,7 @@ hz::ExpectedVoid<StorageDeviceError> StorageDevice::parse_basic_data()
|
||||
}
|
||||
|
||||
// See if we can narrow down the drive type from what was detected
|
||||
// by StorageDetector and "_custom/parser_detected_drive_type" property set by Basic parser.
|
||||
// by StorageDetector and properties set by Basic parser.
|
||||
auto basic_property_repo = basic_parser->get_property_repository();
|
||||
|
||||
// Make detected type more exact.
|
||||
@@ -584,39 +585,58 @@ void StorageDevice::read_common_properties()
|
||||
|
||||
void StorageDevice::detect_drive_type_from_properties(const StoragePropertyRepository& property_repo)
|
||||
{
|
||||
auto drive_type_prop = property_repo.lookup_property("_custom/parser_detected_drive_type");
|
||||
if (!drive_type_prop.empty()) {
|
||||
// This is set by Text parser
|
||||
if (auto drive_type_prop = property_repo.lookup_property("_custom/parser_detected_drive_type"); !drive_type_prop.empty()) {
|
||||
const auto& drive_type_storable_str = drive_type_prop.get_value<std::string>();
|
||||
set_detected_type(StorageDeviceDetectedTypeExt::get_by_storable_name(drive_type_storable_str, StorageDeviceDetectedType::BasicScsi));
|
||||
}
|
||||
|
||||
switch (get_detected_type()) {
|
||||
case StorageDeviceDetectedType::Unknown:
|
||||
set_detected_type(StorageDeviceDetectedType::BasicScsi); // fall back to basic scsi parser
|
||||
break;
|
||||
case StorageDeviceDetectedType::AtaAny:
|
||||
// Find out if it's SSD or HDD
|
||||
{
|
||||
// Find out if it's SSD or HDD
|
||||
if (get_detected_type() == StorageDeviceDetectedType::AtaAny) {
|
||||
auto rpm_prop = property_repo.lookup_property("rotation_rate");
|
||||
if (rpm_prop.empty() || rpm_prop.get_value<std::int64_t>() == 0) {
|
||||
set_detected_type(StorageDeviceDetectedType::AtaSsd);
|
||||
} else {
|
||||
set_detected_type(StorageDeviceDetectedType::AtaHdd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StorageDeviceDetectedType::AtaHdd:
|
||||
case StorageDeviceDetectedType::AtaSsd:
|
||||
case StorageDeviceDetectedType::Nvme:
|
||||
case StorageDeviceDetectedType::BasicScsi:
|
||||
case StorageDeviceDetectedType::CdDvd:
|
||||
case StorageDeviceDetectedType::UnsupportedRaid:
|
||||
// leave as is
|
||||
break;
|
||||
case StorageDeviceDetectedType::NeedsExplicitType:
|
||||
DBG_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// This is set by JSON parser
|
||||
if (auto device_type_prop = property_repo.lookup_property("device/type"); !device_type_prop.empty()) {
|
||||
// Note: USB flash drives in non-scsi mode do not have this property.
|
||||
const auto& smartctl_type = device_type_prop.get_value<std::string>();
|
||||
|
||||
if (smartctl_type == "scsi") { // USB flash in scsi mode, optical, scsi, etc.
|
||||
if (BuildEnv::is_kernel_linux() && get_device_base().starts_with("sr")) {
|
||||
set_detected_type(StorageDeviceDetectedType::CdDvd);
|
||||
} else {
|
||||
set_detected_type(StorageDeviceDetectedType::BasicScsi);
|
||||
}
|
||||
|
||||
} else if (smartctl_type == "sat") { // (S)ATA, including behind supported RAID controllers
|
||||
// Find out if it's SSD or HDD
|
||||
auto rpm_prop = property_repo.lookup_property("rotation_rate");
|
||||
if (rpm_prop.empty() || rpm_prop.get_value<std::int64_t>() == 0) {
|
||||
set_detected_type(StorageDeviceDetectedType::AtaSsd);
|
||||
} else {
|
||||
set_detected_type(StorageDeviceDetectedType::AtaHdd);
|
||||
}
|
||||
|
||||
} else if (smartctl_type == "nvme") { // NVMe SSD
|
||||
set_detected_type(StorageDeviceDetectedType::Nvme);
|
||||
|
||||
} else {
|
||||
// TODO Detect unsupported RAID
|
||||
debug_out_warn("app", "Unsupported type " << smartctl_type << " reported by smartctl for " << get_device_with_type() << "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (get_detected_type() == StorageDeviceDetectedType::Unknown) {
|
||||
set_detected_type(StorageDeviceDetectedType::BasicScsi); // fall back to basic scsi parser
|
||||
}
|
||||
|
||||
debug_out_info("app", "Device " << get_device_with_type() << " detected after parser to be of type "
|
||||
<< StorageDeviceDetectedTypeExt::get_storable_name(get_detected_type()) << "\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user