Skip to content

Commit

Permalink
tests: Add nvme SMART/health and sanitize tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tbzatek committed May 17, 2022
1 parent 4f6ebde commit c7b2541
Showing 1 changed file with 100 additions and 0 deletions.
100 changes: 100 additions & 0 deletions src/tests/dbus-tests/test_nvme.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import stat
import re
import six
import tempfile
import time
import sys
Expand Down Expand Up @@ -342,3 +343,102 @@ def test_namespace_info(self):
self.assertEqual(ncap, self.NS_SIZE / lbaf_curr[0])
nutl = self.get_property_raw(ns, '.NVMe.Namespace', 'NamespaceUtilization')
self.assertEqual(nutl, self.NS_SIZE / lbaf_curr[0])


def test_health_info(self):
self._nvme_connect()
self.addCleanup(self._nvme_disconnect, self.SUBNQN, ignore_errors=True)
time.sleep(1)

ctrl_devs = find_nvme_ctrl_devs_for_subnqn(self.SUBNQN)
self.assertEqual(len(ctrl_devs), 1)
ns_devs = find_nvme_ns_devs_for_subnqn(self.SUBNQN)
self.assertEqual(len(ns_devs), self.NUM_NS)

# find drive object through one of the namespace block objects
ns = self.get_object('/block_devices/' + os.path.basename(ns_devs[0]))
self.assertHasIface(ns, 'org.freedesktop.UDisks2.NVMe.Namespace')
drive_obj_path = self.get_property_raw(ns, '.Block', 'Drive')
drive_obj = self.get_object(drive_obj_path)
self.assertHasIface(drive_obj, 'org.freedesktop.UDisks2.NVMe.Controller')
state = self.get_property(drive_obj, '.NVMe.Controller', 'State')
state.assertEqual('live', timeout=10)

smart_updated = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartUpdated')
self.assertGreater(smart_updated, 0)
smart_warnings = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartCriticalWarning')
self.assertEqual(len(smart_warnings), 0)
smart_poh = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartPowerOnHours')
self.assertEqual(smart_poh, 0)
smart_temp = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartTemperature')
self.assertEqual(smart_temp, 0)
smart_selftest_status = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartSelftestStatus')
self.assertEqual(smart_selftest_status, '')
smart_selftest_remaining = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartSelftestPercentRemaining')
self.assertEqual(smart_selftest_remaining, -1)

drive_obj.SmartUpdate(self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
smart_updated2 = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SmartUpdated')
self.assertGreaterEqual(smart_updated2, smart_updated)

attrs = drive_obj.SmartGetAttributes(self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
self.assertGreater(len(attrs), 10)
self.assertEqual(attrs['avail_spare'], 0);
self.assertEqual(attrs['spare_thresh'], 0);
self.assertEqual(attrs['percent_used'], 0);
self.assertEqual(attrs['ctrl_busy_time'], 0);
self.assertEqual(attrs['power_cycles'], 0);
self.assertEqual(attrs['unsafe_shutdowns'], 0);
self.assertEqual(attrs['media_errors'], 0);
self.assertIn('num_err_log_entries', attrs);
self.assertEqual(attrs['temp_sensors'], [0, 0, 0, 0, 0, 0, 0, 0]);
self.assertEqual(attrs['warning_temp_time'], 0);
self.assertEqual(attrs['critical_temp_time'], 0);

# Try trigerring a self-test operation
msg = 'Unknown self-test type xxx'
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SmartSelftestStart('xxx', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
msg = 'NVMe Get Log Page - Device Self-test Log command error: Invalid Field in Command'
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SmartSelftestStart('short', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
msg = 'NVMe Device Self-test command error: Invalid Command Opcode'
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SmartSelftestAbort(self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')


def test_sanitize(self):
self._nvme_connect()
self.addCleanup(self._nvme_disconnect, self.SUBNQN, ignore_errors=True)
time.sleep(1)

ctrl_devs = find_nvme_ctrl_devs_for_subnqn(self.SUBNQN)
self.assertEqual(len(ctrl_devs), 1)
ns_devs = find_nvme_ns_devs_for_subnqn(self.SUBNQN)
self.assertEqual(len(ns_devs), self.NUM_NS)

# find drive object through one of the namespace block objects
ns = self.get_object('/block_devices/' + os.path.basename(ns_devs[0]))
self.assertHasIface(ns, 'org.freedesktop.UDisks2.NVMe.Namespace')
drive_obj_path = self.get_property_raw(ns, '.Block', 'Drive')
drive_obj = self.get_object(drive_obj_path)
self.assertHasIface(drive_obj, 'org.freedesktop.UDisks2.NVMe.Controller')
state = self.get_property(drive_obj, '.NVMe.Controller', 'State')
state.assertEqual('live', timeout=10)

sanitize_status = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SanitizeStatus')
self.assertEqual(sanitize_status, '')
sanitize_percent_remaining = self.get_property_raw(drive_obj, '.NVMe.Controller', 'SanitizePercentRemaining')
self.assertEqual(sanitize_percent_remaining, -1)

# Try trigerring a sanitize operation
msg = 'Unknown sanitize action xxx'
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SanitizeStart('xxx', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
msg = 'NVMe Get Log Page - Sanitize Status Log command error: Invalid Field in Command'
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SanitizeStart('block-erase', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SanitizeStart('crypto-erase', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')
with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
drive_obj.SanitizeStart('overwrite', self.no_options, dbus_interface=self.iface_prefix + '.NVMe.Controller')

0 comments on commit c7b2541

Please sign in to comment.