Добрый день, коллеги. Со времени написания первой статьи прошло достаточно много времени. За это время моя библиотечка для доступа к диску научилась работать со встроенными SMART-тестами и их логами а также механизмами безопасности современных накопителей.
На этот раз я расскажу о создании приложения для тестирования жестких дисков на базе этой библиотеки.
Мне нужно было приложение, которое можно запустить на сервере с hot-swap корзиной и тестировать на нем диски, заменяя их по мере прохождения тестов. Лучшим решением для этого мне показалось запускать процесс тестирования каждого диска в отдельном потоке. Поскольку опыта многопоточного программирование в python у меня не было, я начал изучать вопрос. Для создания многопоточных приложений в питоне есть модуль threading. Поскольку потоки создаются в пределах одного процесса, нет никакой проблемы с доступом к общим данным. Все выглядит очень просто. К сожалению меня поджидала проблема. Моя библиотека отказалась работать в режиме многопоточности. Значит путь мой лежал к написанию приложения с несколькими процессами и всеми прелестями межпроцессного взаимодействия. В питоне для этого есть модуль multiprocessing.
Архитектура приложения мне виделась следующим образом: Основной поток занимается взаимодействием с пользователем. Выводит список дисков, принимает команды и отображает прогресс тестов. Каждая команда диску запускается в отдельном процессе. Чтобы быть уверенным, что тест выполнится именно на том диске, на который отдавалась команда в меню, (диски например можно случайно переставить местами и забыть перечитать в программе) ключом для выполнения команды сделан серийный номер диска. Перед выполнением команды проверяется соответствие серийного номера переданного команде при запуске, серийному номеру подключенного диска. При несовпадении номеров команда отклоняется со звуковым сигналом. Полезная функция, чтобы случайно не запустить деструктивный тест на диске, подключенном чтобы посмотреть SMART.
Для обмена данными между основным процессом и процессами тестирования было создано несколько словарей. Ключами словарей являются серийные номера дисков. Мне не очень нравится решение в виде пачки словарей, но лучшего я пока не придумал.
Вот, как выглядит главное окно программы.
Каждый диск в программе имеет режим, в котором он находится. По умолчанию это режим простоя «idle». При запуске теста этот режим изменяется на название выполняемого теста. Процесс теста регулярно проверяет соответствие режима своему названию а при несовпадении прерывает тест. Таким образом основной процесс может прервать выполнение теста поменяв диску режим на idle. Программа может запускать на дисках встроенные SMART-тесты (Short и Extended), проверять диски последовательным чтением и записью. При этом тест записи сделан цикличным, прописывающим диск снова и снова, отмечая сколько циклов было сделано. Непрерывная циклическая запись позволяет «добить» диски у которых «сыпется» поверхность, но которые еще не набрали нужное количество ошибок для возврата поставщику. За несколько дней в таком режиме они обычно доходят до состояния SMART status bad, что является основанием для замены. На экране, при тестировании показывается скорость прохождения теста (где это возможно), количество ошибок диска и количество «медленных» секторов. Время, после которого сектор считается «медленным» задается константой в программе. Программа также умеет показывать основную информацию по диску, SMART и логи SMART-тестов.
Тест записи может прописывать диск как нулевыми значениями так и уникальным паттерном, по которому можно будет определить, что диск уже тестировался этой программой. Метод записи переключается тоже константой. Поскольку программа рассчитывалась на загрузку тестовой среды по сети, в ней есть возможность отключить в меню пункт выхода из программы.
Вот такая получилась утилитка, может кому нибудь пригодится. Код утилиты и библиотеки, на которой она построена доступен на github.
Комментарии (20)
dark_snow
13.01.2017 09:33+1Меня сейчас заминусуют, но во фразе «как нулевыми значениями так и уникальным партерном» я так понимаю имелось в виду «паТТерном»?
kazenniy
13.01.2017 09:34+1Поправил.
Про орфографию лучше писать в личку, а то ведь действительно заминусуют.AIxray
14.01.2017 12:29Спасибо вам!) Какие аналоги(.exe) есть для винды?
dark_snow
15.01.2017 01:46Так змей кроссплатформенный, кто мешает поставить в окнах интерпретатор и запускать?
kazenniy
15.01.2017 09:11В данном случаем так сделать не получится. Билиотека использует линуксовый механизм ATA Pass-Through. В windows добираться до диска придется другими методами.
dark_snow
15.01.2017 09:32Тогда прошу прощения, упустил этот момент — почему-то показалось что раз питон, то везде взлетит. Встречный вопрос — а на ноут(нет)буке с андроидом взлетит либо через питон-интерпретатор, либо например под Debian в chroot?
Vcoderlab
16.01.2017 16:39+1Прочитав заголовок, открыл статью, рассчитывая увидеть описание способов прямого доступа к диску и используемых для этого библиотек с примерами кода и объяснением, что зачем и почему в этом коде делается. Вместо этого вижу описание некоей программы, код которой доступен на гитхабе, и ничего из ожидаемого…
amarao
Когда я разрабатывал in-house программу для замены дисков (с пересозданием файловых систем и т.д.) для swift-storage, одна из проблем, с которой я столкнулся, были «умирающие IO». Это когда дисковый запрос уходит, а ответа не приходит. Приложение в D+, убить нельзя, ничего сделать нельзя.
В рамках попыток сделать жизнь людей лучше (вылечить эту проблему нельзя) я реализовал декоратор, который позволяет запускать код в отдельном треде, ждёт завершения или таймаута и сообщает о таймауте. Залипший тред остаётся висеть в ОС навсегда, но, хотя бы, пользователю об этом сообщают.
https://github.com/amarao/thread_timeout
kazenniy
Тут подобной проблемы не будет. У sgio запроса есть таймаут, задаваемый при вызове. Если диск не ответил вовремя, то команда отвалится по таймауту. Я на это напоролся, когда делал поддержку безопасности дисков. Команда снятия пароля с диска со стиранием содержимого не возвращает управление до конца стирания. На больших дисках это много часов. Приходится сдвигать таймаут на предпологаемый срок завершения.
amarao
Эти таймауты работают, если на шине всё хорошо. Просто поверьте мне, когда SCSI контроллеру или enclosure плохо, то ни какой из таймаутов не срабатывает. На совсем. Я пробовал — висит более недели (дальше у меня терпение закончилось). По коду ядра видно, что таймаут есть, но почему-то он не срабатывает. Дальше моего Си-конфу не хватило понять почему, но это стабильное поведение на LSI как минимум с 2.6.18, и по 4.4+.
kazenniy
Надо будет погонять на полумертвых дисках, посмотреть результат. Может проявится.
amarao
Если есть SAS-enclosure с sata-дисками, есть довольно простой трюк: https://github.com/amarao/lsi-sata-fuckup
kazenniy
Команда security-erase можно сказать имитирует зависание диска. Она поднимает флаг занятости диска на очень долгое время. А следующая команда попадая в очередь блокирует ее на весь sas порт? Тогда это програмный косяк в драйверах. И все развиснет, как только закончится security-erase.
Это работает только на корзинах с экспандером или на прямом подключении тоже?
amarao
Только на экспандерах. Если диски подключены к разным хостам («хостам» в терминах SAS, т.е. к разным портам), то проблемы нет.
kazenniy
Заинтересовали вы меня этой проблемой. Дорвусь до разных корзин обязательно потестирую.
amarao
Отпишитесь, если сделаете, пожалуйста. Я с этой проблемой половину своей карьеры сталкиваюсь.
Если что, поведение можно поменять изменив queue depth для устройств. Если queue depth =1, то проблема не возникает.
На самом деле всем пофигу на secure-erase баги, это просто метод воспроизвести проблему на рабочем железе. На нерабочем железе это выглядит так: плохо умирает диск, на него уходит запрос (запросы?) и всё — ответа назад не приходит. Иногда со всех устройств бэкплейна (это уже совсем катастрофа), иногда только с одного.