Skip to main content

HP D2700: схема дисковых массивов и назначение хранилищ

HP D2700: схема дисковых массивов и назначение хранилищ

Версия 1.1
Дата 28.10.2026
Статус P411 с 512 MB FBWC и firmware 6.64 работает в PCIe Slot 1 как PCIe Gen2 x8. D2700 firmware 0150, все 25 дисков исправны, production RAID-массивы созданы. MAIN-DATA передан в VM 103, production Btrfs смонтирован в /srv/main-data. Созданы 8 функциональных Btrfs subvolume, Snapper, группы и POSIX ACL. Samba введена в эксплуатацию: опубликованы 8 SMB shares, проверена матрица доступа, исправлена модель создания файлов/ACL, настроена Samba-корзина на 7 рабочих ресурсах. Windows Previous Versions через vfs_snapper проверен на реальном Windows-клиенте, включено скрытие служебных каталогов, автоматическая очистка .recycle и защита smbd от запуска без смонтированного /srv/main-data.
Проект Расширение памяти сервера

1. Назначение документа

Документ фиксирует production-архитектуру хранения HP ProLiant DL380 G7 с внешней дисковой полкой HP StorageWorks D2700, контроллером Smart Array P411, аппаратными RAID, виртуальной машиной Ubuntu Server, Btrfs, Snapper, POSIX ACL и Samba.

Здесь рассматриваются основной файловый массив MAIN-DATA, локальный массив CRITICAL-BACKUP, служебный RECOVERY, общий горячий резерв, передача MAIN-DATA в VM 103 и публикация функциональных ресурсов по SMB. TFTP/PXE/Cisco recovery для массива RECOVERY должен оформляться отдельной статьёй.

2. Состав оборудования

Сервер HP ProLiant DL380 G7
Гипервизор Proxmox VE 9.1.9
Внутренний RAID HP Smart Array P410i, firmware 6.64, 512 MB cache
Внешний RAID HP Smart Array P411, PCIe Slot 1, firmware 6.64, 512 MB FBWC
Полка HP StorageWorks D2700, 25 × 2.5" SFF SAS
Firmware D2700 0150
Подключение P411 port 1E → SFF-8088 → D2700 I/O Module A, P1
Режим Single Domain

3. Физическая раскладка дисков D2700

Отсеки Диски Роль Имя
1–12 12 × 600 GB SAS 10K Основной RAID50 MAIN-DATA
13–14 2 × 146 GB SAS 15K RAID1 RECOVERY
15 1 × 600 GB SAS 10K Shared online spare GLOBAL-SPARE
16–25 10 × 500 GB SAS 7.2K Резервный RAID50 CRITICAL-BACKUP
HP D2700 — bays 01–25

01–12  600 GB  MAIN-DATA
13–14  146 GB  RECOVERY
15     600 GB  GLOBAL-SPARE
16–25  500 GB  CRITICAL-BACKUP

4. Production RAID-массивы

4.1. MAIN-DATA

RAID RAID50
Состав 12 × 600 GB SAS 10K
Parity groups 2 группы: bays 1–6 и 7–12
Strip size 256 KiB
Полезная ёмкость 5.46 TiB / 6.00 TB
Назначение рабочие данные, SMB/NFS, Clonezilla

4.2. RECOVERY

RAID1 из bays 13–14, около 136 GiB. Зарезервирован под отдельный TFTP/PXE/Cisco recovery-проект.

4.3. GLOBAL-SPARE

Bay 15, 600 GB SAS 10K. P411 отображает диск как shared spare. При отказе активного диска контроллер автоматически использует spare для rebuild. После установки замены в штатный bay контроллер может выполнить copy-back, после чего bay 15 снова становится свободным spare.

4.4. CRITICAL-BACKUP

RAID50 из 10 × 500 GB SAS 7.2K, две parity group по пять дисков, полезная ёмкость около 3.64 TiB. Используется для локальных копий выбранных критичных данных и не публикуется как обычная пользовательская шара.

CRITICAL-BACKUP не является независимым backup: MAIN-DATA и CRITICAL-BACKUP находятся в одной D2700 и зависят от одного P411, сервера и общей инфраструктуры питания.

5. Логика использования хранилищ

MAIN-DATA
├── рабочие документы
├── SMB shares
├── NFS при необходимости
└── Clonezilla
        │
        └── выбранные критичные копии
                ↓
        CRITICAL-BACKUP

RECOVERY
└── отдельный TFTP/PXE/Cisco recovery проект

6. Имена объектов

Объект Имя Статус
Основной RAID50 MAIN-DATA Создан
Служебный RAID1 RECOVERY Создан
Общий spare GLOBAL-SPARE Назначен
Резервный RAID50 CRITICAL-BACKUP Создан

7. Ввод P411 и D2700 в эксплуатацию

Первоначальный 256 MB cache-модуль P411 оказался неисправным и приводил к ошибке self-test. После установки исправного 512 MB FBWC и обновления firmware до 6.64 P411 корректно заработал с SAS-expander D2700. D2700 и оба I/O-модуля работают на firmware 0150.

7.1. Диагностика PCIe/IOCK

При размещении P411 в прежнем PCIe Slot 5 воспроизводились IOCK, reset и controller lockup. Перевод драйвера hpsa в simple mode не устранил проблему. После переноса P411 в PCIe Slot 1 контроллер согласовал PCIe Gen2 5 GT/s ×8; повторных IOCK/lockup в контрольном периоде не зафиксировано.

7.2. Контроль через ssacli

ssacli ctrl all show status
ssacli ctrl slot=1 show detail
ssacli ctrl slot=1 show config
ssacli ctrl slot=1 ld all show detail
ssacli ctrl slot=1 pd all show status

Production checkpoint P411: Controller/Cache/Capacitor Status = OK; firmware 6.64; cache ratio 25% read / 75% write.

7.3. Parity initialization

MAIN-DATA и CRITICAL-BACKUP сохраняют Parity Initialization Status: Queued, при этом logical drive имеют Status: OK. Это не блокирует эксплуатацию, но статус продолжает контролироваться.

8. Виртуальная машина файлового сервера

VM ID 103
Имя SMR-SRV-OT-SHARE
Hostname smr-srv-ot-share
ОС Ubuntu Server 24.04.4 LTS
CPU 4 vCPU, type host
RAM 8 GiB
Системный диск 100 GiB, ext4/LVM
Production data MAIN-DATA через отдельный SCSI device

9. Системный диск VM

Системный диск 100 GiB размещён на внутреннем хранилище Proxmox/P410i. Корневая файловая система Ubuntu — ext4 поверх LVM; production-данные на системном диске не хранятся.

10. Сетевые интерфейсы VM

Ubuntu Сегмент Адрес
ens18 временная сеть настройки 192.168.1.229/24
ens19 Prod management VLAN2100 10.44.100.229/24
ens20 Rozliv VLAN2002 172.16.68.229/23
ens21 Pivoproduction VLAN2030 целевой 172.16.66.229/23
ens22 Utilities VLAN2040 172.16.70.229/23
ens23 Legacy VLAN1 10.255.0.229/16 + переходный 172.16.66.229/23
enp2s1 АСТУЭ VLAN2006 172.17.14.229/24

Адрес 172.16.66.229 не должен одновременно находиться на legacy-интерфейсе и VLAN2030. После миграции он переносится на целевой интерфейс VLAN2030.

11. Ubuntu Server

Ubuntu Server 24.04.4 LTS установлен с OpenSSH. Hostname: smr-srv-ot-share. Временная сеть установки — 192.168.1.229/24.

12. Базовые пакеты

sudo apt install -y   ca-certificates curl nano openssl iputils-ping tcpdump arping   bash-completion lsof qemu-guest-agent systemd-timesyncd ufw   ethtool rsync acl attr btrfs-progs snapper

13. QEMU Guest Agent

sudo systemctl enable --now qemu-guest-agent
systemctl status qemu-guest-agent --no-pager

Сервис подтверждён как active (running).

14. Время

sudo timedatectl set-timezone Europe/Samara
sudo timedatectl set-local-rtc 0
sudo timedatectl set-ntp true

15. Запрет маршрутизации между OT-сегментами

net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

VM является многосетевым файловым сервером, но не маршрутизатором. Для reverse path filtering используется loose mode rp_filter=2.

16. Production MAIN-DATA в VM 103

Logical drive MAIN-DATA передан в VM по стабильному идентификатору /dev/disk/by-id/scsi-3600508b1001c2abf1f734aef851f07c9. Имена /dev/sdX не считаются постоянными.

qm set 103   -scsi2 /dev/disk/by-id/scsi-3600508b1001c2abf1f734aef851f07c9,cache=none,iothread=1,backup=0

16.1. Production Btrfs

Label MAIN-DATA
UUID 98e5188a-407c-4d4a-adc1-24d8c90afb32
Размер 5.46 TiB
Data single
Metadata/System DUP
Mount /srv/main-data
UUID=98e5188a-407c-4d4a-adc1-24d8c90afb32 /srv/main-data btrfs defaults,nofail,x-systemd.device-timeout=10s 0 0

17. Логическая структура MAIN-DATA

/srv/main-data
└── baltikashare
    ├── clonezilla
    ├── exchange
    ├── pivoproduction
    ├── rozliv
    ├── utilities
    ├── software
    ├── documentation
    └── ot-admin
Ресурс Назначение
clonezilla образы рабочих станций и технологических ПК
exchange общий обмен инженеров
pivoproduction рабочие данные пивопроизводства
rozliv рабочие данные розлива
utilities инженерные и энергетические системы
software дистрибутивы, драйверы, firmware, утилиты
documentation инструкции, схемы, ТЗ и паспорта
ot-admin административные OT-материалы

18. Snapper

Для каждого из 8 функциональных Btrfs subvolume создана отдельная Snapper-конфигурация: clonezilla, exchange, pivoproduction, rozliv, utilities, software, documentation, ot-admin.

BACKGROUND_COMPARISON=no
TIMELINE_CREATE=yes
TIMELINE_CLEANUP=yes
TIMELINE_MIN_AGE=1800
Ресурс Hourly Daily Weekly Monthly Yearly
clonezilla 24 30 12 12 1
exchange 24 7 2 0 0
pivoproduction 72 30 12 12 0
rozliv 72 30 12 12 0
utilities 72 30 12 12 0
software 0 14 8 6 0
documentation 72 60 26 24 3
ot-admin 72 90 26 24 5
systemctl is-active snapper-timeline.timer snapper-cleanup.timer

Оба таймера подтверждены как active.

19. Модель доступа: группы и POSIX ACL

19.1. Группы

Группа Назначение
admins полный доступ ко всем ресурсам
engineers exchange RW; software/documentation RO
clonezilla-rw RW clonezilla
pivoproduction-rw RW pivoproduction
rozliv-rw RW rozliv
utilities-rw RW utilities
software-rw RW software
documentation-rw RW documentation

19.2. Матрица доступа

Ресурс admins engineers Профильная группа
clonezilla RW DENY clonezilla-rw → RW
exchange RW RW —
pivoproduction RW DENY pivoproduction-rw → RW
rozliv RW DENY rozliv-rw → RW
utilities RW DENY utilities-rw → RW
software RW RO software-rw → RW
documentation RW RO documentation-rw → RW
ot-admin RW DENY только admins

19.3. Универсальные учётные записи

Учётная запись Группа доступа
baltikashare admins
engineer engineers
clonezilla clonezilla-rw
pivo pivoproduction-rw
rozliv rozliv-rw
utilities utilities-rw
software software-rw
documents documentation-rw

19.4. POSIX ACL

Для профильного RW-ресурса используется следующая базовая модель:

user::rwx
group::rwx
group:admins:rwx
mask::rwx
other::---

default:user::rwx
default:group::rwx
default:group:admins:rwx
default:mask::rwx
default:other::---

Для software и documentation дополнительно задан RO для engineers:

group:engineers:r-x
default:group:engineers:r-x

20. Samba — production-конфигурация

20.1. Состояние

Версия Samba 4.19.5-Ubuntu
Роль standalone server
NetBIOS name SMR-OT-SHARE
Security user
Минимальный протокол SMB2_02; SMB1 отключён
Конфигурация /etc/samba/smb.conf
Сервис smbd.service — active

Проверка конфигурации:

sudo testparm
sudo systemctl restart smbd
sudo systemctl is-active smbd
sudo smbstatus

20.2. Опубликованные shares

\\SMR-OT-SHARE\exchange
\\SMR-OT-SHARE\clonezilla
\\SMR-OT-SHARE\pivoproduction
\\SMR-OT-SHARE\rozliv
\\SMR-OT-SHARE\utilities
\\SMR-OT-SHARE\software
\\SMR-OT-SHARE\documentation
\\SMR-OT-SHARE\ot-admin

20.3. Исправление ACL-маски при создании файлов через SMB

Первоначальная комбинация inherit acls = yes + inherit permissions = yes привела к тому, что новый файл через SMB получил эффективную маску mask::r--. Именованная ACL для admins присутствовала, но фактическая запись была запрещена.

-rwxr-----+
user::rwx
group::rwx                      #effective:r--
group:admins:rwx                #effective:r--
mask::r--
other::---

Production-схема изменена: default ACL наследуются Linux/Btrfs, а Samba создаёт файлы и каталоги с фиксированной базовой маской:

create mask = 0660
force create mode = 0660
directory mask = 0770
force directory mode = 0770

inherit acls = no
inherit permissions = no

После исправления новый файл через SMB:

-rw-rw----+
user::rw-
group::rwx                      #effective:rw-
group:admins:rwx                #effective:rw-
mask::rw-
other::---

Контрольная запись от пользователя baltikashare через ACL группы admins выполнена успешно.

20.4. DOS/Windows attributes

Чтобы DOS Archive/Hidden/System не превращались в UNIX execute-биты, Windows-атрибуты хранятся в xattr:

store dos attributes = yes
map archive = no
map hidden = no
map system = no

20.5. Актуальный smb.conf

# ============================================================
# Samba configuration
# Server: SMR-SRV-OT-SHARE
# Role: standalone OT file server
# Data root: /srv/main-data/baltikashare
# ============================================================

[global]

   # Рабочая группа Windows.
   # Используется для standalone Samba без Active Directory.
   workgroup = WORKGROUP

   # Сервер работает автономно и не является контроллером домена.
   server role = standalone server

   # Аутентификация пользователей по логину и паролю.
   security = user

   # Локальная база Samba-пользователей.
   # В неё пользователи добавляются командой smbpasswd -a.
   passdb backend = tdbsam

   # Короткое NetBIOS-имя Samba-сервера.
   # Ограничение NetBIOS — максимум 15 символов.
   # Linux hostname при этом остаётся smr-srv-ot-share.
   netbios name = SMR-OT-SHARE

   # Описание сервера, которое могут видеть SMB-клиенты.
   server string = SMR OT File Server

   # Никогда не преобразовывать неизвестного пользователя в guest.
   map to guest = never

   # Запрещаем usershare и guest usershare.
   usershare max shares = 0
   usershare allow guests = no

   # Samba не используется как print server.
   load printers = no
   disable spoolss = yes
   printcap name = /dev/null

   # Минимально разрешённая версия SMB — SMB2.
   # SMB1/CIFS не разрешаем.
   server min protocol = SMB2_02

   # Логирование.
   log file = /var/log/samba/log.%m
   logging = file
   max log size = 1000

   # PAM.
   obey pam restrictions = yes
   unix password sync = no
   pam password change = no

   # =========================================================
   # Права создаваемых файлов и каталогов
   # =========================================================

   # Обычные файлы:
   # владелец = RW, группа = RW, остальные = NO ACCESS.
   create mask = 0660
   force create mode = 0660

   # Каталоги:
   # владелец = RWX, группа = RWX, остальные = NO ACCESS.
   directory mask = 0770
   force directory mode = 0770

   # Специальное наследование Samba не используем.
   # Default POSIX ACL наследуются файловой системой Linux.
   #
   # inherit permissions = yes переопределяет create/directory mask
   # и в данной схеме использоваться не должен.
   inherit acls = no
   inherit permissions = no

   # =========================================================
   # DOS / Windows attributes
   # =========================================================

   # DOS/Windows-атрибуты храним в extended attributes,
   # а не кодируем UNIX execute-битами.
   store dos attributes = yes
   map archive = no
   map hidden = no
   map system = no


# ============================================================
# EXCHANGE
# admins = RW
# engineers = RW
# ============================================================

[exchange]

   path = /srv/main-data/baltikashare/exchange
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @engineers

   # =========================================================
   # Служебные каталоги
   # =========================================================

   # Каталог Snapper полностью скрываем от обычного SMB-доступа.
   # Пользователь работает со snapshots через Windows
   # «Свойства» -> «Предыдущие версии».
   veto files = /.snapshots/

   # Сетевую корзину скрываем из обычного списка файлов,
   # но оставляем доступной по прямому SMB-пути.
   hide files = /.recycle/

   # Snapper = Windows Previous Versions.
   # Recycle = сетевая корзина Samba.
   vfs objects = snapper recycle

   # Для каждого SMB-пользователя создаётся отдельная корзина.
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# CLONEZILLA
# admins = RW
# clonezilla-rw = RW
# ============================================================

[clonezilla]

   path = /srv/main-data/baltikashare/clonezilla
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @clonezilla-rw

   # =========================================================
   # Служебные каталоги
   # =========================================================

   # Каталог Snapper полностью скрываем от обычного SMB-доступа.
   # Previous Versions продолжает работать через vfs_snapper.
   veto files = /.snapshots/

   # Только Snapper.
   # vfs_recycle намеренно не включён: большие образы могут
   # одновременно удерживаться корзиной и Btrfs snapshots.
   vfs objects = snapper


# ============================================================
# PIVOPRODUCTION
# admins = RW
# pivoproduction-rw = RW
# ============================================================

[pivoproduction]

   path = /srv/main-data/baltikashare/pivoproduction
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @pivoproduction-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# ROZLIV
# admins = RW
# rozliv-rw = RW
# ============================================================

[rozliv]

   path = /srv/main-data/baltikashare/rozliv
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @rozliv-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# UTILITIES
# admins = RW
# utilities-rw = RW
# ============================================================

[utilities]

   path = /srv/main-data/baltikashare/utilities
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @utilities-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# SOFTWARE
# admins = RW
# software-rw = RW
# engineers = RO
# ============================================================

[software]

   path = /srv/main-data/baltikashare/software
   browseable = yes
   guest ok = no

   # По умолчанию только чтение.
   read only = yes
   valid users = @admins @engineers @software-rw

   # Запись только для admins и software-rw.
   write list = @admins @software-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# DOCUMENTATION
# admins = RW
# documentation-rw = RW
# engineers = RO
# ============================================================

[documentation]

   path = /srv/main-data/baltikashare/documentation
   browseable = yes
   guest ok = no

   # По умолчанию только чтение.
   read only = yes
   valid users = @admins @engineers @documentation-rw

   # Запись только для admins и documentation-rw.
   write list = @admins @documentation-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle


# ============================================================
# OT-ADMIN
# admins = RW
# Все остальные = NO ACCESS
# ============================================================

[ot-admin]

   path = /srv/main-data/baltikashare/ot-admin
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0700
   recycle:subdir_mode = 0700
   recycle:exclude_dir = .recycle

20.6. Проверка матрицы доступа через smbclient

Пользователь engineer проверен фактическими SMB-операциями:

Share Ожидаемо Факт
exchange RW OK: put/del
software RO OK: ls; put → ACCESS_DENIED
documentation RO OK: ls; put → ACCESS_DENIED
clonezilla DENY ACCESS_DENIED
pivoproduction DENY ACCESS_DENIED
rozliv DENY ACCESS_DENIED
utilities DENY ACCESS_DENIED
ot-admin DENY ACCESS_DENIED

Профильные учётные записи подтвердили RW только на своих shares:

Учётка Share Результат
clonezilla clonezilla RW OK
pivo pivoproduction RW OK
rozliv rozliv RW OK
utilities utilities RW OK
software software RW OK
documents documentation RW OK

Контрольные попытки профильных пользователей подключиться к чужим ресурсам вернули tree connect failed: NT_STATUS_ACCESS_DENIED.

Администратор baltikashare успешно выполнил создание и удаление файла во всех восьми shares, включая software и documentation, где запись разрешена через write list.

20.7. Samba recycle

vfs_recycle включён на: exchange, pivoproduction, rozliv, utilities, software, documentation, ot-admin.

Для clonezilla recycle намеренно отключён: крупные образы могут одновременно удерживаться корзиной и Btrfs snapshots, что создаёт риск чрезмерного расхода MAIN-DATA. Clonezilla защищается Snapper; критичные образы дополнительно должны копироваться на CRITICAL-BACKUP.

20.7.1. Структура корзины

.recycle/%U

Пример для Pivoproduction:

/srv/main-data/baltikashare/pivoproduction/.recycle/pivo/recycle-test-dir/recycle-test.txt

Проверенный файл в корзине сохранил корректные ACL:

-rw-rw----+  pivo pivoproduction-rw

user::rw-
group::rwx                      #effective:rw-
group:admins:rwx                #effective:rw-
mask::rw-
other::---

20.7.2. Сохранение структуры

recycle:keeptree = yes проверен удалением файла из вложенного каталога: исходная структура каталога появилась внутри персональной корзины.

20.7.3. Несколько версий

recycle:versions = yes проверен двойным удалением файла с одинаковым именем. В корзине появились:

version-test.txt
Copy #1 of version-test.txt

20.7.4. Удаление из самой корзины

recycle:exclude_dir = .recycle проверен удалением файла непосредственно из .recycle через SMB. Файл исчез окончательно и не был повторно перемещён во вложенную корзину.

20.7.5. Скрытие служебных каталогов

Для рабочих shares каталог Snapper полностью исключён из обычного SMB-просмотра, а Samba-корзина помечена как скрытая:

veto files = /.snapshots/
hide files = /.recycle/

veto files делает .snapshots недоступным по обычному SMB-пути, но не мешает vfs_snapper публиковать snapshots через Windows «Предыдущие версии». hide files присваивает .recycle атрибут Hidden; при необходимости корзину можно открыть напрямую, например \\SMR-OT-SHARE\exchange\.recycle.

На clonezilla используется только veto files = /.snapshots/, так как vfs_recycle для этого ресурса отключён.

20.8. Snapper и Windows «Предыдущие версии»

Цепочка Btrfs snapshot → Snapper → vfs_snapper → Samba → Windows Previous Versions проверена на реальном Windows-клиенте.

20.8.1. Контрольный тест

Для exchange были созданы две ручные точки Snapper с разными версиями одного файла, после чего текущая версия файла была изменена ещё раз. Windows отобразил обе сохранённые версии в свойствах файла и позволил восстановить более раннюю версию. После восстановления содержимое файла фактически вернулось к исходному варианту.

Отдельный тест выполнен на documentation: snapshot появился в «Свойства → Предыдущие версии», его содержимое успешно открывалось из Windows. Это подтвердило работу настройки не только на exchange, но и после её распространения на остальные shares.

20.8.2. Проверка автоматических timeline snapshots

Snapper создаёт timeline snapshots ежечасно. Контрольный вывод для exchange 28.10.2026 показывал последовательные snapshots с 05:00 до 14:00. Если Windows Explorer не сразу показывает последние точки, достаточно повторно открыть каталог или окно свойств: серверные snapshots при этом продолжают создаваться корректно.

20.9. Автоматическая очистка Samba recycle

Так как одновременно используется Snapper, корзина Samba предназначена для быстрого возврата случайно удалённых файлов и не должна хранить данные месяцами без ограничения. Для каждого ресурса задан отдельный срок хранения.

Ресурс Срок хранения .recycle
exchange 7 дней
pivoproduction 14 дней
rozliv 14 дней
utilities 14 дней
software 14 дней
documentation 30 дней
ot-admin 30 дней
clonezilla recycle отключён

В smb.conf используется recycle:touch_mtime = yes, поэтому при перемещении файла в корзину обновляется его mtime, и очистка может ориентироваться на время удаления через Samba.

20.9.1. Скрипт /usr/local/sbin/samba-recycle-cleanup

#!/usr/bin/env bash

# ============================================================
# Samba recycle cleanup
# Server: SMR-SRV-OT-SHARE
#
# Автоматическая очистка файлов из Samba .recycle
# по времени их нахождения в корзине.
#
# Режимы:
#   --dry-run  только показать, что было бы удалено
#   --delete   реально удалить просроченные файлы
# ============================================================

set -u
set -o pipefail

BASE="/srv/main-data/baltikashare"
MODE="${1:---dry-run}"

case "$MODE" in
    --dry-run)
        DELETE=false
        ;;
    --delete)
        DELETE=true
        ;;
    *)
        echo "Usage: $0 [--dry-run|--delete]"
        exit 2
        ;;
esac

# Не допускаем работу по каталогу на root FS,
# если production MAIN-DATA не смонтирован.
if ! mountpoint -q /srv/main-data; then
    echo "ERROR: /srv/main-data is not mounted."
    echo "Cleanup aborted."
    exit 1
fi

FS_TYPE="$(findmnt -n -o FSTYPE /srv/main-data 2>/dev/null || true)"
if [[ "$FS_TYPE" != "btrfs" ]]; then
    echo "ERROR: /srv/main-data filesystem is '$FS_TYPE', expected 'btrfs'."
    echo "Cleanup aborted."
    exit 1
fi

POLICY=(
    "exchange:7"
    "pivoproduction:14"
    "rozliv:14"
    "utilities:14"
    "software:14"
    "documentation:30"
    "ot-admin:30"
)

echo "============================================================"
echo "Samba recycle cleanup"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S %z')"
echo "Mode: $MODE"
echo "============================================================"

TOTAL_FILES=0
TOTAL_BYTES=0

for ITEM in "${POLICY[@]}"; do
    SHARE="${ITEM%%:*}"
    DAYS="${ITEM##*:}"
    RECYCLE="${BASE}/${SHARE}/.recycle"

    echo
    echo "------------------------------------------------------------"
    echo "Share:     $SHARE"
    echo "Recycle:   $RECYCLE"
    echo "Retention: $DAYS days"
    echo "------------------------------------------------------------"

    if [[ ! -d "$RECYCLE" ]]; then
        echo "INFO: recycle directory does not exist, skipping."
        continue
    fi

    AGE_MINUTES=$((DAYS * 24 * 60))

    while IFS= read -r -d '' FILE; do
        SIZE="$(stat -c '%s' "$FILE" 2>/dev/null || echo 0)"
        TOTAL_FILES=$((TOTAL_FILES + 1))
        TOTAL_BYTES=$((TOTAL_BYTES + SIZE))

        if [[ "$DELETE" == true ]]; then
            echo "DELETE: $FILE"
            rm -f -- "$FILE"
        else
            echo "WOULD DELETE: $FILE"
        fi
    done < <(
        find "$RECYCLE" \
            -xdev \
            -type f \
            -mmin "+${AGE_MINUTES}" \
            -print0
    )

    if [[ "$DELETE" == true ]]; then
        find "$RECYCLE" \
            -xdev \
            -depth \
            -mindepth 1 \
            -type d \
            -empty \
            -delete
    fi
done

echo
echo "============================================================"
echo "Summary"
echo "============================================================"
echo "Matched files: $TOTAL_FILES"
echo "Matched bytes: $TOTAL_BYTES"

if command -v numfmt >/dev/null 2>&1; then
    echo "Matched size:  $(numfmt --to=iec-i --suffix=B "$TOTAL_BYTES")"
fi

if [[ "$DELETE" == true ]]; then
    echo "Result: expired files deleted."
else
    echo "Result: DRY-RUN only. Nothing was deleted."
fi

echo "Finished: $(date '+%Y-%m-%d %H:%M:%S %z')"

Права и контроль синтаксиса:

sudo chmod 0755 /usr/local/sbin/samba-recycle-cleanup
sudo bash -n /usr/local/sbin/samba-recycle-cleanup

20.9.2. Проверка dry-run и удаления

Сначала скрипт был запущен с --dry-run: при отсутствии просроченных файлов он вернул Matched files: 0. Затем в корзине exchange был создан искусственно состаренный на 8 дней файл. Dry-run обнаружил его как WOULD DELETE, но не удалил. Запуск с --delete удалил только этот файл и вернул успешный результат.

20.9.3. systemd service

/etc/systemd/system/samba-recycle-cleanup.service:

[Unit]
Description=Cleanup expired Samba recycle files
Documentation=man:find(1)
RequiresMountsFor=/srv/main-data

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/samba-recycle-cleanup --delete
PrivateTmp=yes
NoNewPrivileges=yes
StandardOutput=journal
StandardError=journal

20.9.4. systemd timer

/etc/systemd/system/samba-recycle-cleanup.timer:

[Unit]
Description=Daily Samba recycle cleanup

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=10m
Unit=samba-recycle-cleanup.service

[Install]
WantedBy=timers.target

Активация:

sudo systemctl daemon-reload
sudo systemctl enable --now samba-recycle-cleanup.timer

systemctl status samba-recycle-cleanup.timer --no-pager
systemctl list-timers samba-recycle-cleanup.timer --all

sudo journalctl \
  -u samba-recycle-cleanup.service \
  -n 100 \
  --no-pager

Контрольный статус: timer active (waiting). После включения 28.10.2026 следующий запуск был назначен на 29.10.2026 03:36:04 +04, что соответствует 03:30 плюс RandomizedDelaySec=10m.

20.10. Защита smbd от запуска без MAIN-DATA

Если D2700 или MAIN-DATA недоступны, каталог /srv/main-data всё равно может существовать на системном root filesystem. Без дополнительной защиты Samba могла бы запуститься и начать принимать данные в этот обычный каталог, заполняя системный диск.

Для smbd.service создан systemd drop-in: /etc/systemd/system/smbd.service.d/main-data.conf.

# ============================================================
# SMR-SRV-OT-SHARE
# Защита Samba от запуска без MAIN-DATA
#
# Не позволять smbd стартовать, если production-хранилище
# /srv/main-data не смонтировано.
# ============================================================

[Unit]

# systemd должен поднять все mount units, необходимые
# для доступа к /srv/main-data, до запуска smbd.
RequiresMountsFor=/srv/main-data


[Service]

# /srv/main-data должен быть именно mountpoint.
# Если MAIN-DATA не смонтирован, ExecStartPre завершится
# неуспешно и smbd не запустится.
ExecStartPre=/usr/bin/mountpoint -q /srv/main-data

Применение и проверка:

sudo systemctl daemon-reload
sudo systemctl cat smbd

mountpoint /srv/main-data
findmnt /srv/main-data

sudo systemctl restart smbd
sudo systemctl status smbd --no-pager

Фактически подтверждено:

/srv/main-data is a mountpoint

TARGET         SOURCE    FSTYPE OPTIONS
/srv/main-data /dev/sdb1 btrfs  rw,relatime,space_cache=v2,subvolid=5,subvol=/

ExecStartPre=/usr/bin/mountpoint -q /srv/main-data
(code=exited, status=0/SUCCESS)

Status: "smbd: ready to serve connections..."

Проверка UUID в ExecStartPre намеренно не добавлялась: для текущей схемы принято оставить защиту простой — systemd dependency плюс проверка факта монтирования.

20.11. NFS

NFS не публикуется автоматически для всех ресурсов. Первым NFS-потребителем должен стать Clonezilla. Для NFS необходимо отдельно зафиксировать разрешённые сети/клиенты и UID/GID-модель; предпочтительна выделенная сервисная учётная запись clonezilla и root squashing.

20.12. Access Based Enumeration

Access Based Enumeration намеренно не включается. Недоступные SMB shares могут отображаться в списке ресурсов сервера, но попытка подключения к ним блокируется через valid users и файловые ACL. Для текущей эксплуатации такое поведение принято как штатное.

21. Текущая контрольная точка

Этап Состояние
P411 Slot 1, firmware 6.64, 512 MB FBWC, PCIe Gen2 x8, Status OK
D2700 firmware 0150, 25/25 дисков OK
MAIN-DATA RAID50, 5.46 TiB, production Btrfs, VM 103
RECOVERY RAID1, около 136 GiB
CRITICAL-BACKUP RAID50, около 3.64 TiB
GLOBAL-SPARE bay 15, shared spare, OK
Parity RAID50 Queued; эксплуатацию не блокирует, контролируется
Production Btrfs LABEL MAIN-DATA, mount /srv/main-data
Subvolume 8 functional Btrfs subvolume
Snapper 8 configs; timeline/cleanup timers active
POSIX ACL SGID/default ACL настроены; SMB create-mask исправлен
Samba введена в эксплуатацию; 8 shares; матрица доступа проверена
vfs_recycle 7 shares; clonezilla исключён намеренно
Очистка .recycle production-скрипт + systemd timer; dry-run/delete проверены
vfs_snapper Windows Previous Versions: просмотр и восстановление проверены
Служебные каталоги .snapshots veto; .recycle hidden
Защита smbd RequiresMountsFor + mountpoint ExecStartPre работают
ABE не используется по принятому решению
NFS следующий отдельный этап; первым будет clonezilla

21.1. Следующие этапы

  1. Настроить NFS для clonezilla с ограничением разрешённых клиентов/сетей.
  2. После настройки файловых сервисов настроить UFW.
  3. Настроить копирование выбранных критичных данных на CRITICAL-BACKUP.
  4. Добавить мониторинг P410i/P411, D2700, physical disks, Btrfs usage, Snapper, mount и файловых сервисов.
  5. Отдельно решить вопрос постоянного использования hpsa_simple_mode=1.
  6. Отдельно оценить необходимость Dual Domain через второй порт P411 и I/O Module B.

22. Порядок включения и выключения D2700

22.1. Включение

  1. Подать питание на оба БП D2700.
  2. Включить полку и дождаться инициализации.
  3. Включить DL380 G7.
  4. Проверить POST P411 и доступность logical drive.

22.2. Выключение

  1. Корректно остановить VM.
  2. Корректно остановить Proxmox/DL380.
  3. Дождаться полного выключения сервера.
  4. Перевести D2700 в Standby.
  5. При необходимости снять AC с БП полки.

22.3. Восстановление питания

Желаемая последовательность: сначала D2700 и её инициализация, затем запуск DL380 G7 с задержкой. Поведение после полного снятия и возврата AC требуется отдельно проверить в production-конфигурации.

23. Справочные материалы

  • Btrfs documentation
  • Snapper documentation
  • Samba vfs_snapper / vfs_recycle
  • HPE Smart Array / D2700 documentation

Обновление 1.0: фактическая конфигурация Samba и результаты тестов добавлены 28.10.2026.
Обновление 1.1: проверены Windows Previous Versions, скрытие служебных каталогов, автоматическая очистка Samba recycle и защита smbd от запуска без MAIN-DATA; ABE оставлен отключённым.