|
Bogdan Timofte
authored
3 months ago
|
1
|
#!/usr/bin/perl
|
|
|
2
|
|
|
|
3
|
=head1 NAME
|
|
|
4
|
|
|
|
5
|
simple-smart-test.pl - Very simple SMART data test
|
|
|
6
|
|
|
|
7
|
=head1 DESCRIPTION
|
|
|
8
|
|
|
|
9
|
Direct SMART data collection and database storage test.
|
|
|
10
|
|
|
|
11
|
=cut
|
|
|
12
|
|
|
|
13
|
use strict;
|
|
|
14
|
use warnings;
|
|
|
15
|
use DBI;
|
|
|
16
|
use JSON::XS;
|
|
|
17
|
|
|
|
18
|
print "=== Simple SMART Test ===\n\n";
|
|
|
19
|
|
|
|
20
|
# Database connection
|
|
|
21
|
my $dsn = "DBI:Pg:dbname=autosmart;host=192.168.2.102;port=5432";
|
|
|
22
|
my $dbh = DBI->connect($dsn, "autosmart", "autoSMART2025!", {
|
|
|
23
|
RaiseError => 1,
|
|
|
24
|
AutoCommit => 1,
|
|
|
25
|
PrintError => 0
|
|
|
26
|
}) or die "Failed to connect to database: $DBI::errstr\n";
|
|
|
27
|
|
|
|
28
|
print "✓ Database connected\n";
|
|
|
29
|
|
|
|
30
|
# Test SMART data collection manually
|
|
|
31
|
my @devices = glob('/dev/sd[a-z]');
|
|
|
32
|
|
|
|
33
|
for my $device (@devices) {
|
|
|
34
|
print "\nTesting device: $device\n";
|
|
|
35
|
|
|
|
36
|
# Get basic device info
|
|
|
37
|
my $smartctl_output = `smartctl -i $device 2>/dev/null`;
|
|
|
38
|
if ($? != 0) {
|
|
|
39
|
print " ✗ SMART not available\n";
|
|
|
40
|
next;
|
|
|
41
|
}
|
|
|
42
|
|
|
|
43
|
# Parse basic info
|
|
|
44
|
my ($model) = $smartctl_output =~ /Device Model:\s+(.+)/;
|
|
|
45
|
my ($serial) = $smartctl_output =~ /Serial Number:\s+(.+)/;
|
|
|
46
|
|
|
|
47
|
if (!$model || !$serial) {
|
|
|
48
|
print " ✗ Could not parse model/serial\n";
|
|
|
49
|
next;
|
|
|
50
|
}
|
|
|
51
|
|
|
|
52
|
print " Model: $model\n";
|
|
|
53
|
print " Serial: $serial\n";
|
|
|
54
|
|
|
|
55
|
# Get SMART attributes
|
|
|
56
|
my $smart_output = `smartctl -A $device 2>/dev/null`;
|
|
|
57
|
my %parameters;
|
|
|
58
|
|
|
|
59
|
# Parse SMART attributes
|
|
|
60
|
for my $line (split /\n/, $smart_output) {
|
|
|
61
|
if ($line =~ /^\s*(\d+)\s+(\w+)\s+0x[\da-f]+\s+(\d+)\s+(\d+)\s+(\d+)\s+\S+\s+\S+\s+\S+\s+(\d+)/) {
|
|
|
62
|
my ($id, $name, $current, $worst, $threshold, $raw) = ($1, $2, $3, $4, $5, $6);
|
|
|
63
|
$parameters{$name} = $raw;
|
|
|
64
|
}
|
|
|
65
|
}
|
|
|
66
|
|
|
|
67
|
# Get temperature
|
|
|
68
|
my $temp = $parameters{'Temperature_Celsius'} || 0;
|
|
|
69
|
print " Temperature: ${temp}°C\n";
|
|
|
70
|
print " Parameters: " . scalar(keys %parameters) . "\n";
|
|
|
71
|
|
|
|
72
|
# Check if HDD exists in inventory
|
|
|
73
|
my $sth = $dbh->prepare("SELECT id FROM hdd_inventory WHERE serial_number = ? AND model_name = ?");
|
|
|
74
|
$sth->execute($serial, $model);
|
|
|
75
|
my ($hdd_id) = $sth->fetchrow_array();
|
|
|
76
|
|
|
|
77
|
if (!$hdd_id) {
|
|
|
78
|
# Create new HDD
|
|
|
79
|
print " Creating new HDD entry...\n";
|
|
|
80
|
$sth = $dbh->prepare(q{
|
|
|
81
|
INSERT INTO hdd_inventory
|
|
|
82
|
(serial_number, model_name, current_device_path, current_node_id, status)
|
|
|
83
|
VALUES (?, ?, ?, 'ebony', 'active')
|
|
|
84
|
RETURNING id
|
|
|
85
|
});
|
|
|
86
|
$sth->execute($serial, $model, $device);
|
|
|
87
|
($hdd_id) = $sth->fetchrow_array();
|
|
|
88
|
print " ✓ HDD created with ID: $hdd_id\n";
|
|
|
89
|
} else {
|
|
|
90
|
print " ✓ HDD exists with ID: $hdd_id\n";
|
|
|
91
|
# Update location
|
|
|
92
|
$sth = $dbh->prepare("UPDATE hdd_inventory SET current_device_path = ?, last_seen = NOW() WHERE id = ?");
|
|
|
93
|
$sth->execute($device, $hdd_id);
|
|
|
94
|
}
|
|
|
95
|
|
|
|
96
|
# Store SMART reading
|
|
|
97
|
print " Storing SMART reading...\n";
|
|
|
98
|
my $parameters_json = encode_json(\%parameters);
|
|
|
99
|
|
|
|
100
|
$sth = $dbh->prepare(q{
|
|
|
101
|
INSERT INTO smart_readings
|
|
|
102
|
(hdd_id, serial_number, device_path, node_id, timestamp,
|
|
|
103
|
collection_ok, temperature, parameters_json, reading_type)
|
|
|
104
|
VALUES (?, ?, ?, 'ebony', NOW(), true, ?, ?, 'full')
|
|
|
105
|
});
|
|
|
106
|
|
|
|
107
|
$sth->execute($hdd_id, $serial, $device, $temp, $parameters_json);
|
|
|
108
|
print " ✓ SMART reading stored\n";
|
|
|
109
|
}
|
|
|
110
|
|
|
|
111
|
# Show results
|
|
|
112
|
print "\n=== Database Summary ===\n";
|
|
|
113
|
|
|
|
114
|
my $sth = $dbh->prepare("SELECT COUNT(*) FROM hdd_inventory");
|
|
|
115
|
$sth->execute();
|
|
|
116
|
my ($hdd_count) = $sth->fetchrow_array();
|
|
|
117
|
print "HDD Inventory: $hdd_count drives\n";
|
|
|
118
|
|
|
|
119
|
$sth = $dbh->prepare("SELECT COUNT(*) FROM smart_readings");
|
|
|
120
|
$sth->execute();
|
|
|
121
|
my ($reading_count) = $sth->fetchrow_array();
|
|
|
122
|
print "SMART Readings: $reading_count readings\n";
|
|
|
123
|
|
|
|
124
|
# Show latest readings
|
|
|
125
|
$sth = $dbh->prepare(q{
|
|
|
126
|
SELECT hi.serial_number, hi.model_name, sr.timestamp, sr.temperature
|
|
|
127
|
FROM smart_readings sr
|
|
|
128
|
JOIN hdd_inventory hi ON sr.hdd_id = hi.id
|
|
|
129
|
ORDER BY sr.timestamp DESC
|
|
|
130
|
LIMIT 5
|
|
|
131
|
});
|
|
|
132
|
$sth->execute();
|
|
|
133
|
|
|
|
134
|
print "\nLatest readings:\n";
|
|
|
135
|
while (my $row = $sth->fetchrow_hashref()) {
|
|
|
136
|
printf " %s (%s) - %s - %d°C\n",
|
|
|
137
|
substr($row->{serial_number}, 0, 12),
|
|
|
138
|
substr($row->{model_name}, 0, 20),
|
|
|
139
|
$row->{timestamp},
|
|
|
140
|
$row->{temperature} || 0;
|
|
|
141
|
}
|
|
|
142
|
|
|
|
143
|
$dbh->disconnect();
|
|
|
144
|
print "\n=== Test Complete ===\n";
|