Pull to refresh

Бюджетное SAN-хранилище на LSI Syncro, часть 1

Configuring Linux*nixVirtualizationData storageData storages
Tutorial

Вторая часть

Итак, продолжу свои редкие статьи на тему «как не платить HP/EMC/IBM многие кило-(или даже мега-) доллары и собрать своё хранилище не хуже». Прошлый цикл я до победного конца не довёл, но 90% мыслей всё же оформил в текст.

Нашей сегодняшней целью будет отказоустойчивое «All-Flash» (то есть — только из SSD, без жестких дисков, хотя это и не принципиально) хранилище для нужд кластера vSphere, в несколько раз дешевле брендовых аналогов и с очень неплохой производительностью. Подключаться к нему мы будем по Fibre Channel, но никто не мешает сделать iSCSI, FCoE или даже, о ужас, Infiniband.

Syncro


Как ясно из названия, основой всей этой богодельни станет достаточно уникальный на рынке продукт под названием Syncro CS от компании LSI (ныне Avago).

Что же оно такое есть и чем примечательно?

По сути, это комплект из двух обычных контроллеров LSI 9286-8e (либо 9271-8i, если нужны внутренние порты) и двух суперконденсаторов для сохранения кеш-памяти на флешку контроллера в случае потери питания. Стоимость комплекта при этом в несколько раз выше цены аналогичного комплекта без HA-функционала. Но, если сравнивать с решениями на базе DRBD, то эта разница с лихвой компенсируется отсутствием необходимости иметь двойной набор накопителей.

Но самое интересное кроется в прошивке. Благодаря ей, эти контроллеры, будучи подключенными к одной SAS-сети (например, дисковой корзине с экспандерами) устанавливают через неё связь друг с другом и работают в режиме отказоустойчивого кластера.

Для нас это интересно вот чем:
  • Возможность создавать RAID-массивы, доступные сразу на двух серверах
  • Отказоустойчивость на уровне контроллеров: при смерти одного из них (или целиком сервера) второй продолжит работать и обслуживать I/O

Через SAS-сеть эти контроллеры синхронизируют свои кеши записи (т.н. cache coherency), обмениваются Heartbeat-ами, сообщая друг другу что живы-здоровы, и так далее.

У них есть некоторые важные особенности, выясненные как потом и кровью опытным путём, так и вдумчивым чтением документации:
  • По причине отказоустойчивой натуры решения, LSI Syncro поддерживает только двухпортовые SAS диски. Так что никаких SATA SSD, к сожалению, что довольно сильно увеличивает стоимость хранилища.

  • Как я понял, контроллеры поддерживают не более 96 SAS-накопителей. В документации ещё фигурирует фраза Maximum of 120 dual-ported SAS devices in the HA storage domain, которая противоречит Up to 96 ea 6G SAS and/or NearLine-SAS dual-ported HDDs and SSDs двумя строчками выше там же. Так что будем считать по-минимуму.

  • При создании массива на одном из контроллеров этот контроллер становится его хозяином до тех пор пока не будет, к примеру, перезагружен сервер где он установлен. После этого роль хозяина переходит ко второму контроллеру.

  • После возвращения в строй первого контроллера роль хозяина массива ему не возвращается, а остаётся у второго.

  • Контроллеры используют механизм I/O Shipping: при приходе I/O-запроса на контроллер, который в данный момент не является хозяином массива, он переправляет этот запрос контроллеру-хозяину по SAS-шине, тот его исполняет и отправляет обратно.

  • В результате вышесказанного скорость работы подчиненного контроллера с массивом в несколько раз ниже (по линейной скорости — в 2 раза, по IOPSам — в 7(!) раз) чем скорость работы контроллера-хозяина массива.

  • На данный момент не существует способа заставить контроллер-хозяин добровольно передать владение массивом второму контроллеру, что очень странно. Особенно учитывая то, что при мягкой перезагрузке (Controlled failover) основного контроллера, в логах второго контроллера видны сообщения о том, что основной предупреждает о своём ребуте и просит забрать массивы. LSI что-то такое обещала добавить в свои утилиты, а пока… только перезагрузка, только хардкор.

  • ОС сервера, куда вставлен подчинённый (на данный момент времени) контроллер видит массивы контроллера-хозяина, но утилиты управления контроллером (StorCLI, MegaCLI, ...) массивов (и дисков, состоящих в этих массивах) показывать не будут. Как только владение массивами перейдёт этому контроллеру, то массивы и диски сразу появятся в выводе утилит и можно будет ими управлять

ALUA


Так как скорость работы с массивом у хозяина и подчинённого контроллеров разная, то нам придётся строить хранилище с парадигмой ALUA, которая как раз для таких случаев и была придумана. Там много всяких особенностей, но для нас смысл её в том, что можно часть портов на хранилищах пометить как Optimized (т.е. рекомендованные к использованию), а другие как Unoptimized (соответственно, не рекомендованные). Все эти порты могут обслуживать ввод-вывод в любой момент времени, но при наличии живых путей до Optimized портов инициатор будет использовать их, а остальные держать в запасе. Если же все Optimized порты откажут, то инициатор (ESXi в нашем случае), немного подумав, пустит I/O по Unoptimized портам.

С точки зрения VMWare ESXi это выглядит так:


Первая тройка путей ведёт нас к подчинённому хранилищу, а вторая тройка — к главному, которое может обслуживать I/O на полной скорости.

Если бы мы не использовали ALUA, то I/O запросы (в режиме Round-Robin) шли бы на оба хранилища, что привело бы к неравномерности задержек и скорости, по сути упираясь в производительность подчинённого хранилища.

Achtung!
Многие программы, работающие с SAN (например — Microsoft Cluster Services), опираются на SCSI Persistent Reservations, позволяющие блокировать LUN и производить с ним эксклюзивно всякие непотребства. Так вот, эти самые SCSI PR не будут реплицироваться на другой сервер.

То есть, если инициатор поставит блокировку на LUN через путь, ведущий на первый сервер, то через путь, ведущий на второй сервер, эта блокировка видна не будет. Для работы в режиме Round Robin это особенно важно, так как пути меняются постоянно и через какой путь будет установлена блокировка заранее неизвестно. В случае с VMWare ESXi это, в принципе, не проблема так как с версии VMFS5 не используются SCSI PR, а вместо них идёт в ход инструкция Atomic-Test-and-Set (которая, впрочем, тоже не реплицируется, но зато блокирует только нужную область на LUNе и на короткое время, а не весь LUN целиком), да и ALUA должен дать знать ESXi чтобы тот не использовал пути на второй сервер пока жив основной.

Есть какие-то коммерческие решения на базе SCST, реализующие синхронизацию SCSI PR, но я их не пробовал. И, по слухам, какое-то подобное решение будет, возможно, скоро открыто для публики.

Ладно, с теорией закончили, приступим к практике.

Hard & Soft


Железо


Серверы-контроллеры:
  • Комплект LSI Syncro CS 9286-8e x 1
    Нынче уже доступны Syncro со скоростью 12Gb/s, но я их не щупал. Плюс, там ещё больше порезаны фичи MegaRAID (убран Cachecade совсем, а в предыдущей версии был, хоть и только в режиме кеширования чтения).

  • Корпуса Supermicro SC216 2U x 2
    Можно было, конечно, использовать 1U, но у них очень туго со слотами расширения, да и место в стойке экономить особо не надо было.

  • МП Supermicro X10SRL-F x 2
    Выбрана за большое количество слотов PCI-E.

  • Процессор Intel Xeon E5-1650 v3 x 2
    Выбран за большую частоту.

  • Память DDR4-2133 16GB ECC Registered x 8
    Память нашим железкам почти не понадобится (хотя, если добавить корзину с жесткими дисками, то как кеш чтения вполне пригодится), поэтому можно брать поменьше, но с учетом 4-х канального контроллера памяти и возможности зеркалировать модули.

  • Двухпортовые Fibre Channel контроллеры QLogic 2562 x 4
    На эту номинацию проходили кастинг и 16Гбитные QLogic 2672, но там вылезли проблемы совместимости с драйвером, да и 16Гбит свичей у меня нет. Поэтому была применена волшебная палочка и они, до поры до времени, превратились в двухпортовые 10Гбит сетевые карты с космической стоимостью… :)

  • Intel DC S3500 80Gb x 4
    По паре в каждый сервер (RAID1) под ОС (да, можно было бы поставить на USB флешки или SATA DOM, но у первых плохая надежность (иногда отваливаются), а у вторых нет возможности Hot Swap).

Дисковая полка:
  • Корпус на 72 2.5" диска Supermicro SC417E26 x 1
    Внутри имеет три идентичных бэкплейна на 24 диска со двойными экспандерами для отказоустойчивости. У них есть ещё более монструозное решение — SC417E16-RJBOD1 — на 88 дисков, но там лишь одинарные экспандеры, что плохо скажется на надёжности, да и слотов расширения мало. А нам нужно, по хорошему, минимум три (для установки планок с внешними SAS портами — две для подключения к серверам и одна для каскадирования корзин).

  • Твердотельные SAS диски на 400Гбайт Hitachi S842E400M2 x 48
    На момент закупки это были одни из самых надёжных и недорогих на рынке (из списка совместимости Syncro). Производитель обещает износостойкость 30 Петабайт на запись или 40 полных перезаписей в день в течении 5 лет. Что ж, время покажет…

  • Всякая прочая мелочь вроде платы питания Supermicro CSE-PTJBOD-CB2 (чтобы корпус включался без М/П + мониторинг БП корпуса через I2C/SAS), провода SAS внутренние и внешние (для коммутации бэкплейнов между собой и подключения серверов к полке) и т.п.

FC-коммутаторы:
  • Cisco MDS9148 x 2
    Относительно недорогие и качественные девайсы (я брал с 16 активированными портами).
    Сейчас вроде уже end-of-sale, вместо них 9148S на 16Гбит.

Cost & Performance


Всё это счастье (вместе со свичами) на момент закупки (ноябрь 2014) стоило около 4 млн. рублей, что при «сырой емкости» в 19.2Тб флеша очень и очень недорого. Для сравнения: за low-end двухконтроллерную железяку MSA 2040 с 24 х 800GB SSD на борту компания HP сейчас хочет что-то около 18 млн (да, я знаю про всякие скидки, да и доллар подрос, но всё же порядок цен, думаю, примерно такой).

По скорости они обещают не более 85k IOPS, у нас же будет чуть побольше: с одной ноды я снимал 720k IOPS с 75% загрузкой CPU с бэкендом vdisk_nullio (при чтении выдаёт нули, записи же отбрасывает, эдакий аналог /dev/null).

Причём загрузка CPU, почему-то, скачкообразно нарастает при увеличении IOPS с 600k до 720k — с 40% до 75%, до этого же растёт равномерно. Линейная скорость ожидаемо упирается в FC интерфейсы — около 3Гбайт/c (4 порта по 800Мб/c в теории, учитывая 8b/10b кодирование у 8Gbit FC).

Из Syncro я смог выжать 420k IOPS, что близко к теоретическому пределу в 450k IOPS, которые обещает LSI. При работе с SSD очень важно отключать кеш записи на массиве (режим write-through) и включать Direct I/O, в противном случае производительность упирается в 150k IOPS даже при чтении. Это особенности технологии FastPath у LSI, она активируется только при соблюдении этих двух условий.
Линейная скорость чтения с массива достигает 3.8Гбайт/c. Тут, скорее всего, упираемся в производительность самого контроллера (шина PCI-E 3.0 x8 может прокачать 8Гбайт/c).

Более подробные бенчмарки, думаю, будут во второй части.

Сборка серверов


Тут особо рассказывать нечего.
В каждый сервер устанавливаем материнскую плату, процессор, память, два FC контроллера и один Syncro.
Я ещё установил в заднюю часть корпуса небольшую корзину (Supermicro MCP-220-82609-0N) на два диска и туда вставил SSD под ОСь. Основная корзина корпуса пока осталась незадействованной, но в будущем её можно будет тоже подключить к Syncro, хотя это и разрушит отказоустойчивую натуру решения (выключил одну ноду — заодно вырубил и бэкплейн).

Важный совет по надежности — выставить в биосе зеркалирование памяти, это эдакий RAID1 для DDR.
Мозгов станет вдвое меньше, зато надёжность резко повысится. Ну и погонять memtest-ом недельку, для верности. В логах биоса читать про ошибки ECC, если они есть — менять сбойный модуль и гонять заново. Ибо если пока это корректируемые ошибки, то потом могут стать фатальными, такие случаи были.

Схема подключения


SAS


Следующая схема нагло стырена из документации к Syncro:


Глубинный смысл такого подключения в том, что при отказе одной из дисковых полок
вторая продолжит работать. Если же подключать полки одну за другой (daisy chain),
то при отказе первой полки в цепочке связь со всеми остальными тоже будет потеряна.
А тут мы имеем что-то вроде топологии «кольцо», когда дополнительные полки подключаются
между этими двумя.

В нашем же случае полка одна (хоть в ней и три бэкплейна), так что подключать мы её будем
по-обычному, примерно так:

Внутри полки бэкплейны соединяем последовательно.

FC


Сервера подключаем к FC-коммутаторам так:

Таким образом, при отказе любой из HBA-карт и/или одного коммутатора у нас будет связность.

Вминание! Коммутаторы не следует соединять между собой транками и прочими ISL!
Это должны быть две независимые фабрики.
Ибо, если мы сделаем ошибку в настройке одного из них (или будет сбоить софт) — это не скажется на втором (в FC зонирование и прочие настройки распространяются по всем свичам фабрики).

Зонировал я по принципу «один порт инициатора и один порт хранилища».
При наличии большого количества инициаторов это трудоёмко, так как количество зон будет равно [кол-во портов инициаторов] X [кол-во портов хранилищ]. Но, имея список портов хранилищ и инициаторов зоны легко можно сгенерировать скриптом :) Лень — двигатель прогресса.

Программная часть


  • Debian Linux 7 x86-64
  • Kernel 3.14.xx LTS
    Если требуется крайне высокая производительность, то стоит обратить свой светлый взор на ядра 3.18+ так как в них была интегрирована поддержка SCSI-MQ, которая позволяет добиться 1млн+ IOPS на одном LUN.

    Но, в нашем случае, когда много инициаторов подключаются к нескольким LUN-ам, это даже вредно, ибо по бенчмарками в данном случае SCSI-MQ работает несколько медленнее обычного стека. Ещё один минус — SCSI-MQ не имеет планировщиков I/O (deadline, cfq), что, в общем-то логично — SSD планировщик не нужен, а для жёстких дисков толку от SCSI-MQ никакого, там IOPSам далеко до программных пределов. А вот в смешанных конфигурациях (SSD+HDD) это, скорее всего, негативно скажется на скорости работы массивов с HDD.
  • SCST Target Framework 3.0.1

Тут всё более или менее стандартно, ставим ОС на софтовый линуксовый рейд (mdraid) так как железного рейда в этих материнских платах не предусмотрено.

Далее настраиваем и собираем ядро.
Мой конфиг, может кому пригодится
CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_MMU=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_CPU_AUTOPROBE=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ZONE_DMA32=y
CONFIG_AUDIT_ARCH=y
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_X86_64_SMP=y
CONFIG_X86_HT=y
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_EXTABLE_SORT=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE=""
CONFIG_LOCALVERSION=""
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_KERNEL_XZ=y
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_FHANDLE=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_TREE_RCU=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_FANOUT=64
CONFIG_RCU_FANOUT_LEAF=16
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
CONFIG_ARCH_SUPPORTS_INT128=y
CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y
CONFIG_ARCH_USES_NUMA_PROT_NONE=y
CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_NUMA_BALANCING=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_CGROUP=y
CONFIG_NAMESPACES=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_HAVE_UID16=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_HAVE_PCSPKR_PLATFORM=y
CONFIG_UID16=y
CONFIG_KALLSYMS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_PCI_QUIRKS=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
CONFIG_JUMP_LABEL=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_CC_STACKPROTECTOR_NONE=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_HAVE_ARCH_SOFT_DIRTY=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_COMPAT_OLD_SIGACTION=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_BSG=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MSDOS_PARTITION=y
CONFIG_EFI_PARTITION=y
CONFIG_BLOCK_COMPAT=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CFQ_GROUP_IOSCHED=y
CONFIG_DEFAULT_DEADLINE=y
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_PADATA=y
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y
CONFIG_INLINE_WRITE_UNLOCK=y
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_ZONE_DMA=y
CONFIG_SMP=y
CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_NO_BOOTMEM=y
CONFIG_MCORE2=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_P6_NOP=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y
CONFIG_NR_CPUS=32
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
CONFIG_PREEMPT_NONE=y
CONFIG_X86_UP_APIC_MSI=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
CONFIG_X86_MCE=y
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_THRESHOLD=y
CONFIG_X86_THERMAL_VECTOR=y
CONFIG_X86_16BIT=y
CONFIG_X86_ESPFIX64=y
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_DIRECT_GBPAGES=y
CONFIG_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NODES_SPAN_OTHER_NODES=y
CONFIG_NODES_SHIFT=2
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
CONFIG_COMPACTION=y
CONFIG_MIGRATION=y
CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_X86_RESERVE_LOW=64
CONFIG_MTRR=y
CONFIG_MTRR_SANITIZER=y
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1
CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
CONFIG_X86_PAT=y
CONFIG_ARCH_USES_PG_UNCACHED=y
CONFIG_ARCH_RANDOM=y
CONFIG_X86_SMAP=y
CONFIG_SECCOMP=y
CONFIG_HZ_100=y
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
CONFIG_PHYSICAL_START=0x1000000
CONFIG_PHYSICAL_ALIGN=0x1000000
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_USE_PERCPU_NUMA_NODE_ID=y
CONFIG_ACPI=y
CONFIG_ACPI_FAN=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_NUMA=y
CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_HED=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_EXTLOG=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_COMMON=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_INTEL_IDLE=y
CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
CONFIG_PCIEASPM=y
CONFIG_PCIEASPM_PERFORMANCE=y
CONFIG_PCI_MSI=y
CONFIG_PCI_LABEL=y
CONFIG_ISA_DMA_API=y
CONFIG_AMD_NB=y
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_COREDUMP=y
CONFIG_IA32_EMULATION=y
CONFIG_X86_X32=y
CONFIG_COMPAT=y
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_X86_DEV_DMA_OPS=y
CONFIG_IOSF_MBI=m
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y
CONFIG_IP_MULTICAST=y
CONFIG_NET_IPIP=y
CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IP_TUNNEL=y
CONFIG_NET_IPGRE=y
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_INET_TUNNEL=y
CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_INET_UDP_DIAG=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_HTCP=y
CONFIG_DEFAULT_HTCP=y
CONFIG_DEFAULT_TCP_CONG="htcp"
CONFIG_STP=y
CONFIG_BRIDGE=y
CONFIG_HAVE_NET_DSA=y
CONFIG_VLAN_8021Q=y
CONFIG_LLC=y
CONFIG_NETLINK_MMAP=y
CONFIG_NETLINK_DIAG=y
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_BQL=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_HAVE_BPF_JIT=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_PNP=y
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
CONFIG_HAVE_IDE=y
CONFIG_SCSI_MOD=y
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
CONFIG_SCSI_NETLINK=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_SAS_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_MEGARAID_SAS=y
CONFIG_ATA=y
CONFIG_ATA_VERBOSE_ERROR=y
CONFIG_ATA_ACPI=y
CONFIG_SATA_PMP=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_AUTODETECT=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=y
CONFIG_MD_RAID456=y
CONFIG_BLK_DEV_DM_BUILTIN=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_ZERO=y
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
CONFIG_BONDING=y
CONFIG_NET_FC=y
CONFIG_NETCONSOLE=y
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETPOLL=y
CONFIG_NETPOLL_TRAP=y
CONFIG_NET_POLL_CONTROLLER=y
CONFIG_TUN=y
CONFIG_ETHERNET=y
CONFIG_MDIO=y
CONFIG_NET_VENDOR_INTEL=y
CONFIG_E1000E=y
CONFIG_IGB=y
CONFIG_IGB_HWMON=y
CONFIG_IGB_DCA=y
CONFIG_IXGBE=y
CONFIG_IXGBE_HWMON=y
CONFIG_IXGBE_DCA=y
CONFIG_PPP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_SLHC=y
CONFIG_INPUT=y
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
CONFIG_SERIO=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
CONFIG_SERIO_LIBPS2=y
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_SERIAL_8250_DMA=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
CONFIG_HPET_MMAP_DEFAULT=y
CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_I801=y
CONFIG_I2C_SCMI=y
CONFIG_PPS=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_HWMON=y
CONFIG_HWMON_VID=y
CONFIG_SENSORS_CORETEMP=y
CONFIG_SENSORS_JC42=y
CONFIG_SENSORS_W83627EHF=y
CONFIG_SENSORS_ACPI_POWER=y
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_SSB_POSSIBLE=y
CONFIG_BCMA_POSSIBLE=y
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_VGA_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_HID=y
CONFIG_HIDRAW=y
CONFIG_HID_GENERIC=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_EZKEY=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_USB_HID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_COMMON=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB=y
CONFIG_USB_DEFAULT_PERSIST=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_EHCI_PCI=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_ACM=y
CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_FTDI_SIO=y
CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_WWAN=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_GHES=y
CONFIG_EDAC_I7CORE=y
CONFIG_EDAC_SBRIDGE=y
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_DMADEVICES=y
CONFIG_INTEL_IOATDMA=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_ACPI=y
CONFIG_ASYNC_TX_DMA=y
CONFIG_DMA_ENGINE_RAID=y
CONFIG_DCA=y
CONFIG_CLKEVT_I8253=y
CONFIG_I8253_LOCK=y
CONFIG_CLKBLD_I8253=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
CONFIG_UEFI_CPER=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_USE_FOR_EXT23=y
CONFIG_JBD2=y
CONFIG_FS_MBCACHE=y
CONFIG_EXPORTFS=y
CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_FANOTIFY=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=y
CONFIG_UDF_NLS=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_CONFIGFS_FS=y
CONFIG_MISC_FILESYSTEMS=y
CONFIG_PSTORE=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_855=y
CONFIG_NLS_CODEPAGE_866=y
CONFIG_NLS_CODEPAGE_1251=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_5=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_KOI8_R=y
CONFIG_NLS_UTF8=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_FRAME_WARN=1024
CONFIG_STRIP_ASM_SYMS=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_ARCH_KMEMCHECK=y
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_FENTRY=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_STRICT_DEVMEM=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
CONFIG_DOUBLEFAULT=y
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_0X80=y
CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_OPTIMIZE_INLINING=y
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_XOR_BLOCKS=y
CONFIG_ASYNC_CORE=y
CONFIG_ASYNC_MEMCPY=y
CONFIG_ASYNC_XOR=y
CONFIG_ASYNC_PQ=y
CONFIG_ASYNC_RAID6_RECOV=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_GF128MUL=y
CONFIG_CRYPTO_PCRYPT=y
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_ABLK_HELPER=y
CONFIG_CRYPTO_GLUE_HELPER_X86=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_VMAC=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CRC32C_INTEL=y
CONFIG_CRYPTO_CRC32=y
CONFIG_CRYPTO_CRC32_PCLMUL=y
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_CRCT10DIF_PCLMUL=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA1_SSSE3=y
CONFIG_CRYPTO_SHA256_SSSE3=y
CONFIG_CRYPTO_SHA512_SSSE3=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_X86_64=y
CONFIG_CRYPTO_AES_NI_INTEL=y
CONFIG_HAVE_KVM=y
CONFIG_RAID6_PQ=y
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IO=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC32=y
CONFIG_CRC32_SLICEBY8=y
CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_CHECK_SIGNATURE=y
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_DDR=y


Запускаем компиляцию и сборку в deb-пакет:
# cd /usr/src/linux-3.14.xx
# fakeroot make-kpkg clean
# CONCURRENCY_LEVEL=12 fakeroot make-kpkg --us --uc --jobs 12 --stem=kernel-scst --revision=1 kernel_image

Затем выкачиваем SCST, собираем и устанавливаем (указываем путь к исходникам ядра):
# svn checkout svn://svn.code.sf.net/p/scst/svn/branches/3.0.x scst-svn
# cd scst-svn
# BUILD_2X_MODULE=y CONFIG_SCSI_QLA_FC=y CONFIG_SCSI_QLA2XXX_TARGET=y KDIR="/usr/src/linux-3.14.xx" make all install

Более развёрнутую инструкцию по установке SCST с драйвером под QLogic можно найти на сайте проекта (но там собирается драйвер QLogic из их GIT дерева, который мне не показался особо стабильным. Мы же возьмём драйвер из комплекта SCST).

В результате мы получили пакет с ядром + директорию /lib/modules/3.14.xx/extra с модулями SCST, которые нужно будет скопировать вручную на сервера. Можно, конечно, придумать способ интеграции их прямо в .deb пакет, но мне было лень.

Для работы FC карт также нужна прошивка, которую можно как залить в адаптер (точнее — обновить, ибо какая-то там уже есть), так и просто положить в /lib/firmware и драйвер при загрузке её оттуда подтянет. Я, для верности, да и производитель рекомендует, сделал и то и то. Прошить можно либо через линуксовую утилиту от QLogic — qaucli, либо из под FreeDOS (или EFI) их же софтом с сайта.

Качаем прошивку (в нашем случае это ql2500_fw.bin) и кладём на место:
# mkdir -p /lib/firmware
# cd /lib/firmware
# wget http://ldriver.qlogic.com/firmware/ql2500_fw.bin

Далее нам понадобится утилита управления SCST под ёмким названием scstadmin и библиотеки, ей используемые. Саму утилиту берём в дереве исходников SCST: scstadmin/scstadmin.sysfs/scstadmin и кладём её на наши сервера куда-нибудь в /usr/bin, чтобы всем видно было. Затем берём директорию scstadmin/scstadmin.sysfs/scst-0.9.10/lib/SCST и кладём её в /usr/lib/perl/<версия Perl>.

Затем устанавливаем Pacemaker чтобы рулить нашим кластером и генерируем ключ авторизации.
Pacemaker будет переключать режимы ALUA в зависимости от состояния нод.

# apt-get -t wheezy-backports install pacemaker
# corosync-keygen

Файл-ключ /etc/corosync/authkey переносим на второй сервер в то же место.

Для управления SCST через Pacemaker нам понадобится «ресурс», который я утащил из проекта ESOS и подкрутил под себя.
Ресурс
#! /bin/sh
#
# $Id$

#
#   Resource Agent for managing the Generic SCSI Target Subsystem
#   for Linux (SCST) and related daemons.
#
#   License: GNU General Public License (GPL)
#   (c) 2012-2014 Marc A. Smith
#

# Initialization
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
MODULES="scst scst_vdisk qla2x00tgt"
SCST_CFG="/etc/scst.conf"
PRE_SCST_CONF="/etc/pre-scst_xtra_conf"
POST_SCST_CONF="/etc/post-scst_xtra_conf"
SCST_SYSFS="/sys/kernel/scst_tgt"
ALUA_STATES="active nonoptimized standby unavailable offline transitioning"
NO_CLOBBER="/tmp/scst_ra-no_clobber"

# For optional SCST modules
if [ -f "/lib/modules/$(uname -r)/extra/ocs_fc_scst.ko" ]; then
    MODULES="${MODULES} ocs_fc_scst"
fi
if [ -f "/lib/modules/$(uname -r)/extra/chfcoe.ko" ]; then
    MODULES="${MODULES} chfcoe"
fi


scst_start() {
    # Exit immediately if configuration is not valid
    scst_validate_all || exit ${?}

    # If resource is already running, bail out early
    if scst_monitor; then
        ocf_log info "Resource is already running."
        return ${OCF_SUCCESS}
    fi

    # If our pre-SCST file exists, run it
    if [ -f "${PRE_SCST_CONF}" ]; then
        ocf_log info "Pre-SCST user config. file found; running..."
        ocf_run -warn sh "${PRE_SCST_CONF}"
    fi

    # Load all modules
    ocf_log info "Loading kernel modules..."
    for i in ${MODULES}; do
        ocf_log debug "scst_start() -> Module: ${i}"
        if [ -d /sys/module/${i} ]; then
            ocf_log warn "The ${i} module is already loaded!"
        else
            ocf_run modprobe ${i} || exit ${OCF_ERR_GENERIC}
        fi
    done

    # Configure SCST
    if [ -f "${SCST_CFG}" ]; then
        ocf_log info "Applying SCST configuration..."
        ocf_run scstadmin -config "${SCST_CFG}"
        # Prevent scst_stop() from clobbering the configuration file
        if [ ${?} -ne 0 ]; then
            ocf_log err "Something is wrong with the SCST configuration!"
            ocf_run touch "${NO_CLOBBER}"
            exit ${OCF_ERR_GENERIC}
        else
            if [ -f "${NO_CLOBBER}" ]; then
                ocf_run rm -f "${NO_CLOBBER}"
            fi
        fi
    fi

    # If our post-SCST file exists, run it
    if [ -f "${POST_SCST_CONF}" ]; then
        ocf_log info "Post-SCST user config. file found; running..."
        ocf_run -warn sh "${POST_SCST_CONF}"
    fi

    # If we are using ALUA, be sure we are using the "Slave" state initially
    if ocf_is_true ${OCF_RESKEY_alua}; then
        check_alua
        # Set the local target group ALUA state
        ocf_log debug "scst_start() -> Setting target group" \
            "'${OCF_RESKEY_local_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_s_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_local_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_s_alua_state} || exit ${OCF_ERR_GENERIC}
        # For now, we simply assume the other node is the Master
        ocf_log debug "scst_start() -> Setting target group" \
            "'${OCF_RESKEY_remote_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_m_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_remote_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_m_alua_state} || exit ${OCF_ERR_GENERIC}
    fi

    # Make sure the resource started correctly
    while ! scst_monitor; do
        ocf_log debug "scst_start() -> Resource has not started yet, waiting..."
        sleep 1
    done

    # Only return $OCF_SUCCESS if _everything_ succeeded as expected
    return ${OCF_SUCCESS}
}


scst_stop() {
    # Exit immediately if configuration is not valid
    scst_validate_all || exit ${?}

    # Check the current resource state
    scst_monitor
    local rc=${?}
    case "${rc}" in
    "${OCF_SUCCESS}")
        # Currently running; normal, expected behavior
        ocf_log info "Resource is currently running."
        ;;
    "${OCF_RUNNING_MASTER}")
        # Running as a Master; need to demote before stopping
        ocf_log info "Resource is currently running as Master."
        scst_demote || ocf_log warn "Demote failed, trying to stop anyway..."
        ;;
    "${OCF_NOT_RUNNING}")
        # Currently not running; nothing to do
        ocf_log info "Resource is already stopped."
        return ${OCF_SUCCESS}
        ;;
    esac

    # Unload the modules (in reverse)
    ocf_log info "Unloading kernel modules..."
    for i in $(echo ${MODULES} | tr ' ' '\n' | tac | tr '\n' ' '); do
        ocf_log debug "scst_stop() -> Module: ${i}"
        if [ -d /sys/module/${i} ]; then
            ocf_run rmmod -w ${i} || exit ${OCF_ERR_GENERIC}
        else
            ocf_log warn "The ${i} module is not loaded!"
        fi
    done

    # Make sure the resource stopped correctly
    while scst_monitor; do
        ocf_log info "scst_stop() -> Resource has not stopped yet, waiting..."
        sleep 1
    done

    # Only return $OCF_SUCCESS if _everything_ succeeded as expected
    return ${OCF_SUCCESS}
}


scst_monitor() {
    # Exit immediately if configuration is not valid
    scst_validate_all || exit ${?}

    # Check if SCST is loaded
    local rc
    if [ -e "${SCST_SYSFS}/version" ]; then
        ocf_log debug "scst_monitor() -> SCST version:" \
            "$(cat ${SCST_SYSFS}/version)"
        ocf_log debug "scst_monitor() -> Resource is running."
        crm_master -l reboot -v 100
        rc=${OCF_SUCCESS}
    else
        ocf_log debug "scst_monitor() -> Resource is not running."
        crm_master -l reboot -D
        rc=${OCF_NOT_RUNNING}
        return ${rc}
    fi

    # If we are using ALUA, then we can test if we are Master or not
    if ocf_is_true ${OCF_RESKEY_alua}; then
        dev_grp_path="${SCST_SYSFS}/device_groups/${OCF_RESKEY_device_group}"
        tgt_grp_path="${dev_grp_path}/target_groups/${OCF_RESKEY_local_tgt_grp}"
        tgt_grp_state="$(head -1 ${tgt_grp_path}/state)"
        ocf_log debug "scst_monitor() -> SCST local target" \
            "group state: ${tgt_grp_state}"
        if [ "x${tgt_grp_state}" = "x${OCF_RESKEY_m_alua_state}" ]; then
            rc=${OCF_RUNNING_MASTER}
        fi
    fi

    return ${rc}
}


scst_validate_all() {
    # Test for required binaries
    check_binary scstadmin

    # There can only be one instance of SCST running per node
    if [ ! -z "${OCF_RESKEY_CRM_meta_clone_node_max}" ] &&
        [ "${OCF_RESKEY_CRM_meta_clone_node_max}" -ne 1 ]; then
        ocf_log err "The 'clone-node-max' parameter must equal '1'."
        exit ${OCF_ERR_CONFIGURED}
    fi

    # If ALUA support is enabled, we need to check the parameters
    if ocf_is_true ${OCF_RESKEY_alua}; then
        # Make sure they are set to something
        if [ -z "${OCF_RESKEY_device_group}" ]; then
            ocf_log err "The 'device_group' parameter is not set!"
            exit ${OCF_ERR_CONFIGURED}
        fi
        if [ -z "${OCF_RESKEY_local_tgt_grp}" ]; then
            ocf_log err "The 'local_tgt_grp' parameter is not set!"
            exit ${OCF_ERR_CONFIGURED}
        fi
        if [ -z "${OCF_RESKEY_remote_tgt_grp}" ]; then
            ocf_log err "The 'remote_tgt_grp' parameter is not set!"
            exit ${OCF_ERR_CONFIGURED}
        fi
        if [ -z "${OCF_RESKEY_m_alua_state}" ]; then
            ocf_log err "The 'm_alua_state' parameter is not set!"
            exit ${OCF_ERR_CONFIGURED}
        fi
        if [ -z "${OCF_RESKEY_s_alua_state}" ]; then
            ocf_log err "The 's_alua_state' parameter is not set!"
            exit ${OCF_ERR_CONFIGURED}
        fi
        #  Currently, we only support using one Master with this RA
        if [ ! -z "${OCF_RESKEY_CRM_meta_master_max}" ] &&
            [ "${OCF_RESKEY_CRM_meta_master_max}" -ne 1 ]; then
            ocf_log err "The 'master-max' parameter must equal '1'."
            exit ${OCF_ERR_CONFIGURED}
        fi
        if [ ! -z "${OCF_RESKEY_CRM_meta_master_node_max}" ] &&
            [ "${OCF_RESKEY_CRM_meta_master_node_max}" -ne 1 ]; then
            ocf_log err "The 'master-node-max' parameter must equal '1'."
            exit ${OCF_ERR_CONFIGURED}
        fi
    fi

    return ${OCF_SUCCESS}
}


scst_meta_data() {
	cat <<-EOF
	<?xml version="1.0"?>
	<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
	<resource-agent name="scst" version="0.1">
	  <version>0.1</version>
	  <longdesc lang="en">The SCST OCF resource agent for ESOS; includes SCST ALUA support.</longdesc>
	  <shortdesc lang="en">SCST OCF RA script for ESOS.</shortdesc>
	  <parameters>
	    <parameter name="alua" unique="0" required="0">
	      <longdesc lang="en">Use to enable/disable updating ALUA status in SCST.</longdesc>
	      <shortdesc lang="en">The 'alua' parameter.</shortdesc>
	      <content type="boolean" default="false" />
	    </parameter>
	    <parameter name="device_group" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST device group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'device_group' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="local_tgt_grp" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST local target group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'local_tgt_grp' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="remote_tgt_grp" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST remote target group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'remote_tgt_grp' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="m_alua_state" unique="0" required="0">
	      <longdesc lang="en">The ALUA state (eg, active) for a Master node (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'm_alua_state' parameter.</shortdesc>
	      <content type="string" default="active" />
	    </parameter>
	    <parameter name="s_alua_state" unique="0" required="0">
	      <longdesc lang="en">The ALUA state (eg, nonoptimized) for a Slave node (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 's_alua_state' parameter.</shortdesc>
	      <content type="string" default="nonoptimized" />
	    </parameter>
	  </parameters>
	  <actions>
	    <action name="meta-data" timeout="5" />
	    <action name="start" timeout="120" />
	    <action name="stop" timeout="60" />
	    <action name="monitor" timeout="20" depth="0" interval="10" role="Master" />
	    <action name="monitor" timeout="20" depth="0" interval="20" role="Slave" />
	    <action name="notify" timeout="20" />
	    <action name="promote" timeout="20" />
	    <action name="demote" timeout="20" />
	    <action name="reload" timeout="20" />
	    <action name="validate-all" timeout="20" />
	  </actions>
	</resource-agent>
	EOF
}


scst_usage() {
    echo "usage: ${0} {start|stop|monitor|validate-all|promote|demote|reload|notify|meta-data}"
    echo ""
    echo "Expects to have a fully populated OCF RA-compliant environment set."
}


scst_promote() {
    # Exit immediately if configuration is not valid
    scst_validate_all || exit ${?}

    # Test the resource's current state
    scst_monitor
    local rc=${?}
    case "${rc}" in
    "${OCF_SUCCESS}")
        # Running as Slave; normal, expected behavior
        ocf_log debug "scst_promote() -> Resource is" \
            "currently running as Slave."
        ;;
    "${OCF_RUNNING_MASTER}")
        # Already a Master; unexpected, but not a problem
        ocf_log info "Resource is already running as Master."
        return ${OCF_SUCCESS}
        ;;
    "${OCF_NOT_RUNNING}")
        # Currently not running; need to start before promoting
        ocf_log info "Resource is currently not running."
        scst_start
        ;;
    *)
        # Failed resource; let the cluster manager recover
        ocf_log err "Unexpected error, cannot promote."
        exit ${rc}
        ;;
    esac

    # Promote only makes sense if we are using ALUA
    if ocf_is_true ${OCF_RESKEY_alua}; then
        check_alua
        # Set the local target group to the "Master" ALUA state
        ocf_log debug "scst_promote() -> Setting target group" \
            "'${OCF_RESKEY_local_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_m_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_local_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_m_alua_state} || exit ${OCF_ERR_GENERIC}
        # Since there can only be one Master, set the remote target group
        ocf_log debug "scst_promote() -> Setting target group" \
            "'${OCF_RESKEY_remote_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_s_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_remote_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_s_alua_state} || exit ${OCF_ERR_GENERIC}
    else
        ocf_log err "The ALUA parameters need to be configured before using MS."
        exit ${OCF_ERR_CONFIGURED}
    fi

    # After the resource has been promoted, check whether the promotion worked
    while true; do
        scst_monitor
        if [ ${?} -eq ${OCF_RUNNING_MASTER} ]; then
            ocf_log info "Resource was promoted successfully."
            break
        else
            ocf_log debug "scst_promote() -> Resource still" \
                "awaiting promotion."
            sleep 1
        fi
    done

    # Only return $OCF_SUCCESS if _everything_ succeeded as expected
    return ${OCF_SUCCESS}
}


scst_demote() {
    # Exit immediately if configuration is not valid
    scst_validate_all || exit ${?}

    # Test the resource's current state
    scst_monitor
    local rc=${?}
    case "${rc}" in
    "${OCF_RUNNING_MASTER}")
        # Running as Master; normal, expected behavior
        ocf_log debug "scst_demote() -> Resource is" \
            "currently running as Master."
        ;;
    "${OCF_SUCCESS}")
        # Already running as Slave; nothing to do
        ocf_log debug "scst_demote() -> Resource is" \
            "currently running as Slave."
        return ${OCF_SUCCESS}
        ;;
    "${OCF_NOT_RUNNING}")
        # Not running; getting a demote action in this state is unexpected
        ocf_log err "Resource is currently not running."
        exit ${OCF_ERR_GENERIC}
        ;;
    *)
        # Failed resource; let the cluster manager recover
        ocf_log err "Unexpected error, cannot demote."
        exit ${rc}
        ;;
    esac

    # Demote only makes sense if we are using ALUA
    if ocf_is_true ${OCF_RESKEY_alua}; then
        check_alua
        # Set the local target group to the "Slave" ALUA state
        ocf_log debug "scst_demote() -> Setting target group" \
            "'${OCF_RESKEY_local_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_s_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_local_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_s_alua_state} || exit ${OCF_ERR_GENERIC}
        # If we're a Slave, we assume the remote side is the Master
        ocf_log debug "scst_demote() -> Setting target group" \
            "'${OCF_RESKEY_remote_tgt_grp}' ALUA state to" \
            "'${OCF_RESKEY_m_alua_state}'..."
        ocf_run scstadmin -noprompt -set_tgrp_attr \
            ${OCF_RESKEY_remote_tgt_grp} -dev_group \
            ${OCF_RESKEY_device_group} -attributes \
            state\=${OCF_RESKEY_m_alua_state} || exit ${OCF_ERR_GENERIC}
    else
        ocf_log err "The ALUA parameters need to be configured before using MS."
        exit ${OCF_ERR_CONFIGURED}
    fi

    # After the resource has been demoted, check whether the demotion worked
    while true; do
        scst_monitor
        if [ ${?} -eq ${OCF_RUNNING_MASTER} ]; then
            ocf_log debug "scst_demote() -> Resource still" \
                "awaiting demotion."
            sleep 1
        else
            ocf_log info "Resource was demoted successfully."
            break
        fi
    done

    # Only return $OCF_SUCCESS if _everything_ succeeded as expected
    return ${OCF_SUCCESS}
}


scst_notify() {
    # We're currently not using this
    ocf_log debug "scst_notify() -> Received a" \
        "'${OCF_RESKEY_CRM_meta_notify_type}' /" \
        "'${OCF_RESKEY_CRM_meta_notify_operation}' notification."

    return ${OCF_SUCCESS}
}


check_alua() {
    # Make sure the directories exist in the SCST sysfs structure
    if [ ! -d "${SCST_SYSFS}/device_groups/${OCF_RESKEY_device_group}" ]; then
        ocf_log err "The '${OCF_RESKEY_device_group}' device group does not exist!"
        exit ${OCF_ERR_INSTALLED}
    fi
    target_groups="${SCST_SYSFS}/device_groups/${OCF_RESKEY_device_group}/target_groups"
    if [ ! -d "${target_groups}/${OCF_RESKEY_local_tgt_grp}" ]; then
        ocf_log err "The '${OCF_RESKEY_local_tgt_grp}' target group does not exist!"
        exit ${OCF_ERR_INSTALLED}
    fi
    if [ ! -d "${target_groups}/${OCF_RESKEY_remote_tgt_grp}" ]; then
        ocf_log err "The '${OCF_RESKEY_remote_tgt_grp}' target group does not exist!"
        exit ${OCF_ERR_INSTALLED}
    fi

    # Check that the given ALUA states are valid
    local valid_m_alua_state=0
    local valid_s_alua_state=0
    for i in ${ALUA_STATES}; do
        if [ "x${OCF_RESKEY_m_alua_state}" = "x${i}" ]; then
            valid_m_alua_state=1
        fi
        if [ "x${OCF_RESKEY_s_alua_state}" = "x${i}" ]; then
            valid_s_alua_state=1
        fi
    done
    if [ ${valid_m_alua_state} -eq 0 ]; then
        ocf_log err "The 'm_alua_state' value is not valid: ${OCF_RESKEY_m_alua_state}"
        exit ${OCF_ERR_INSTALLED}
    fi
    if [ ${valid_s_alua_state} -eq 0 ]; then
        ocf_log err "The 's_alua_state' value is not valid: ${OCF_RESKEY_s_alua_state}"
        exit ${OCF_ERR_INSTALLED}
    fi
}


# Make sure meta-data and usage always succeed
case ${__OCF_ACTION} in
meta-data)
    scst_meta_data
    exit ${OCF_SUCCESS}
    ;;
usage|help)
    scst_usage
    exit ${OCF_SUCCESS}
    ;;
esac

# Anything other than meta-data and usage must pass validation
scst_validate_all || exit ${?}

# Translate each action into the appropriate function call
case ${__OCF_ACTION} in
start)
    scst_start
    ;;
stop)
    scst_stop
    ;;
status|monitor)
    scst_monitor
    ;;
notify)
    scst_notify
    ;;
promote)
    scst_promote
    ;;
demote)
    scst_demote
    ;;
reload)
    ocf_log info "Reloading..."
    scst_start
    ;;
validate-all)
    ;;
migrate_to|migrate_from)
    scst_usage
    exit ${OCF_ERR_UNIMPLEMENTED}
    ;;
*)
    scst_usage
    exit ${OCF_ERR_UNIMPLEMENTED}
    ;;
esac

# Log a debug message and exit
rc=${?}
ocf_log debug "${OCF_RESOURCE_INSTANCE} ${__OCF_ACTION} returned: ${rc}"
exit ${rc}


Сей файл нужно положить под именем /usr/lib/ocf/resource.d/esos/scst и сделать исполняемым.

Так как для устойчивости кластера двух нод мало (будет Split-Brain если связность нарушится), то у нас будет ещё третья нода, которая будет создавать кворум, но никаких ресурсов исполнять не будет. Тут вступает в игру такая особенность Pacemaker, что «здоровье» ресурсов проверяется на всех нодах кластера вне зависимости от того может ли там исполняться этот ресурс вообще или нет (в новых версиях вроде добавили какой-то признак, отключающий эту фичу, но в версии из репозитория Debian такого счастья еще вроде нет). Поэтому для кворум-ноды нам понадобится фейковый ресурс который будет просто говорить «в Багдаде всё спокойно».
Фейковый ресурс
#! /bin/sh
#
# $Id$

#
#   Resource Agent for managing the Generic SCSI Target Subsystem
#   for Linux (SCST) and related daemons.
#
#   License: GNU General Public License (GPL)
#   (c) 2012-2014 Marc A. Smith
#

# Initialization
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
MODULES="scst scst_vdisk qla2x00tgt"
SCST_CFG="/etc/scst.conf"
PRE_SCST_CONF="/etc/pre-scst_xtra_conf"
POST_SCST_CONF="/etc/post-scst_xtra_conf"
SCST_SYSFS="/sys/kernel/scst_tgt"
ALUA_STATES="active nonoptimized standby unavailable offline transitioning"
NO_CLOBBER="/tmp/scst_ra-no_clobber"

scst_monitor() {
    return ${OCF_NOT_RUNNING}
}

scst_meta_data() {
	cat <<-EOF
	<?xml version="1.0"?>
	<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
	<resource-agent name="scst" version="0.1">
	  <version>0.1</version>
	  <longdesc lang="en">The SCST OCF resource agent for ESOS; includes SCST ALUA support.</longdesc>
	  <shortdesc lang="en">SCST OCF RA script for ESOS.</shortdesc>
	  <parameters>
	    <parameter name="alua" unique="0" required="0">
	      <longdesc lang="en">Use to enable/disable updating ALUA status in SCST.</longdesc>
	      <shortdesc lang="en">The 'alua' parameter.</shortdesc>
	      <content type="boolean" default="false" />
	    </parameter>
	    <parameter name="device_group" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST device group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'device_group' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="local_tgt_grp" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST local target group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'local_tgt_grp' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="remote_tgt_grp" unique="0" required="0">
	      <longdesc lang="en">The name of the SCST remote target group (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'remote_tgt_grp' parameter.</shortdesc>
	      <content type="string" default="" />
	    </parameter>
	    <parameter name="m_alua_state" unique="0" required="0">
	      <longdesc lang="en">The ALUA state (eg, active) for a Master node (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 'm_alua_state' parameter.</shortdesc>
	      <content type="string" default="active" />
	    </parameter>
	    <parameter name="s_alua_state" unique="0" required="0">
	      <longdesc lang="en">The ALUA state (eg, nonoptimized) for a Slave node (used with ALUA support).</longdesc>
	      <shortdesc lang="en">The 's_alua_state' parameter.</shortdesc>
	      <content type="string" default="nonoptimized" />
	    </parameter>
	  </parameters>
	  <actions>
	    <action name="meta-data" timeout="5" />
	    <action name="start" timeout="120" />
	    <action name="stop" timeout="60" />
	    <action name="monitor" timeout="20" depth="0" interval="10" role="Master" />
	    <action name="monitor" timeout="20" depth="0" interval="20" role="Slave" />
	    <action name="notify" timeout="20" />
	    <action name="promote" timeout="20" />
	    <action name="demote" timeout="20" />
	    <action name="reload" timeout="20" />
	    <action name="validate-all" timeout="20" />
	  </actions>
	</resource-agent>
	EOF
}

scst_usage() {
    echo "usage: ${0} {start|stop|monitor|validate-all|promote|demote|reload|notify|meta-data}"
    echo ""
    echo "Expects to have a fully populated OCF RA-compliant environment set."
}

# Make sure meta-data and usage always succeed
case ${__OCF_ACTION} in
meta-data)
    scst_meta_data
    exit ${OCF_SUCCESS}
    ;;
usage|help)
    scst_usage
    exit ${OCF_SUCCESS}
    ;;
esac

# Translate each action into the appropriate function call
case ${__OCF_ACTION} in
start)
    ;;
stop)
    ;;
status|monitor)
    scst_monitor
    ;;
notify)
    ;;
promote)
    ;;
demote)
    ;;
reload)
    ocf_log info "Reloading..."
    ;;
validate-all)
    ;;
migrate_to|migrate_from)
    scst_usage
    exit ${OCF_ERR_UNIMPLEMENTED}
    ;;
*)
    scst_usage
    exit ${OCF_ERR_UNIMPLEMENTED}
    ;;
esac

# Log a debug message and exit
rc=${?}
ocf_log debug "${OCF_RESOURCE_INSTANCE} ${__OCF_ACTION} returned: ${rc}"
exit ${rc}



Его положить на кворум-ноду аналогично основным нодам.

Так, напоследок создадим массивы и настроим конфигурацию SCST.
Для первой части, наверное, хватит.

Поглядим какие девайсы у нас есть:
storcli64 /c0/eall/sall show
Controller = 0
Status = Success
Description = Show Drive Information Succeeded.


Drive Information :
=================

-------------------------------------------------------------------------
EID:Slt DID State DG       Size Intf Med SED PI SeSz Model            Sp 
-------------------------------------------------------------------------
37:0     61 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:1     62 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:2     63 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:3     64 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:4     65 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:5     66 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:6     67 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:7     68 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:8     69 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:9     70 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:10    71 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:11    72 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:12    73 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:13    74 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:14    75 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:15    76 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:16    77 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:17    78 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:18    15 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:19    19 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:20    79 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:21    80 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:22    81 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
37:23    82 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:0      8 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:1      9 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:2     10 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:3     11 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:4     12 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:5     14 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:6     21 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:7     22 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:8     23 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:9     24 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:10    18 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:11    17 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:12    25 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:13    26 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:14    16 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:15    27 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:16    28 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:17    29 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:18    30 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:19    31 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:20    32 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:21    33 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:22    34 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
59:23    35 UGood   - 372.093 GB SAS  SSD N   N  512B S842E400M2       U  
-------------------------------------------------------------------------


Понятно, значит будем созавать два RAID6 массива (23 + 1 Hot Spare), по одному на каждом бэкплейне:
# storcli /c0 add vd r6 name=SSD-RAID6-1 drives=37:0-22 WT nora direct Strip=64
# storcli /c0 add vd r6 name=SSD-RAID6-2 drives=59:0-22 WT nora direct Strip=64

Это рекомендованные параметры LSI для SSD. Судя по моим тестам размер страйпа от 8Кб до 128Кб почти никак не влияет на скорость работы.

Конфигурация SCST: /etc/scst.conf
Сервер-1 (с комментариями)
# Перечисляем устройства
## Режим blockio работает с устройствами минуя ядерный Page Cache, для SSD самое то
HANDLER vdisk_blockio {
        ## Нужно иметь в виду, что исходя из имени устройства SCST генерирует поля t10_dev_id и usn
        ## по которым ESXi идентифицирует LUN.
        DEVICE SSD-RAID6-1 {
                ## Уникальный путь к устройству (отвязываемся от именования /dev/sdX)
                filename /dev/disk/by-id/scsi-3600605b008b4be401c91ac4abce21c9b
                ## Отключаем кеш записи
                write_through 1
                ## Говорим что это SSD
                rotational 0
        }

        DEVICE SSD-RAID6-2 {
                filename /dev/disk/by-id/scsi-3600605b008b4be401c91ac53bd668eda
                write_through 1
                rotational 0
        }
}

# Настройка таргетов
TARGET_DRIVER qla2x00t {
        ## WWN порта, свои смотреть в /sys/kernel/scst_tgt/targets/qla2x00t
        TARGET 21:00:00:24:ff:54:09:32 {
                HW_TARGET

                enabled 1
                # Порядковый номер в ALUA группе (1-4 у первого сервера и 5-8 у второго)
                rel_tgt_id 1
                
                ## Добавляем в него наши девайсы
                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:54:09:33 {
                HW_TARGET

                enabled 1
                rel_tgt_id 2

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:54:09:80 {
                HW_TARGET

                enabled 1
                rel_tgt_id 3

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:54:09:81 {
                HW_TARGET

                enabled 1
                rel_tgt_id 4

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }
}


# Группа ALUA, имя произвольное
DEVICE_GROUP default {
        ## Добавляем устройства в группу
        DEVICE SSD-RAID6-1
        DEVICE SSD-RAID6-2
        
        ## Группа портов в Сервере-1, имя произвольное
        TARGET_GROUP local {
                ## ID группы, произвольное
                group_id 256

                ## ALUA статус
                state active

                ## Порты Сервера-1
                TARGET 21:00:00:24:ff:54:09:32
                TARGET 21:00:00:24:ff:54:09:33
                TARGET 21:00:00:24:ff:54:09:80
                TARGET 21:00:00:24:ff:54:09:81
        }

        ## Группа портов Сервера-2
        TARGET_GROUP remote {
                group_id 257

                ## ALUA статус
                state nonoptimized
                
                ## Порты Сервера-2 и их порядковые номера
                TARGET 21:00:00:24:ff:4a:af:b2 {
                        rel_tgt_id 5
                }
                TARGET 21:00:00:24:ff:4a:af:b3 {
                        rel_tgt_id 6
                }
                TARGET 21:00:00:24:ff:54:09:06 {
                        rel_tgt_id 7
                }
                TARGET 21:00:00:24:ff:54:09:07 {
                        rel_tgt_id 8
                }
        }
}


Сервер-2 (симметрично)
HANDLER vdisk_blockio {
        DEVICE SSD-RAID6-1 {
                filename /dev/disk/by-id/scsi-3600605b008b4be401c91ac4abce21c9b
                write_through 1
                rotational 0
        }

        DEVICE SSD-RAID6-2 {
                filename /dev/disk/by-id/scsi-3600605b008b4be401c91ac53bd668eda
                write_through 1
                rotational 0
        }
}

TARGET_DRIVER qla2x00t {
        TARGET 21:00:00:24:ff:4a:af:b2 {
                HW_TARGET

                enabled 1
                rel_tgt_id 5

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:4a:af:b3 {
                HW_TARGET

                enabled 1
                rel_tgt_id 6

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:54:09:06 {
                HW_TARGET

                enabled 1
                rel_tgt_id 7

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }

        TARGET 21:00:00:24:ff:54:09:07 {
                HW_TARGET

                enabled 1
                rel_tgt_id 8

                LUN 0 SSD-RAID6-1
                LUN 1 SSD-RAID6-2
        }
}

DEVICE_GROUP default {
        DEVICE SSD-RAID6-1
        DEVICE SSD-RAID6-2

        TARGET_GROUP local {
                group_id 257
                state nonoptimized

                TARGET 21:00:00:24:ff:4a:af:b2
                TARGET 21:00:00:24:ff:4a:af:b3
                TARGET 21:00:00:24:ff:54:09:06
                TARGET 21:00:00:24:ff:54:09:07
        }

        TARGET_GROUP remote {
                group_id 256
                state active

                TARGET 21:00:00:24:ff:54:09:32 {
                        rel_tgt_id 1
                }
                TARGET 21:00:00:24:ff:54:09:33 {
                        rel_tgt_id 2
                }
                TARGET 21:00:00:24:ff:54:09:80 {
                        rel_tgt_id 3
                }
                TARGET 21:00:00:24:ff:54:09:81 {
                        rel_tgt_id 4
                }
        }
}



Всё, для первой части, думаю, достаточно. Надеюсь, что скоро осилю вторую :)
Tags:lsisyncrolinuxscsttargetfibrechannelнищеброды
Hubs: Configuring Linux *nix Virtualization Data storage Data storages
Total votes 9: ↑8 and ↓1+7
Views23K

Popular right now

Top of the last 24 hours