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. Скрытие служебных каталогов
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. Следующие этапы
- Настроить NFS для
clonezillaс ограничением разрешённых клиентов/сетей. - После настройки файловых сервисов настроить UFW.
- Настроить копирование выбранных критичных данных на
CRITICAL-BACKUP. - Добавить мониторинг P410i/P411, D2700, physical disks, Btrfs usage, Snapper, mount и файловых сервисов.
- Отдельно решить вопрос постоянного использования
hpsa_simple_mode=1. - Отдельно оценить необходимость Dual Domain через второй порт P411 и I/O Module B.
22. Порядок включения и выключения D2700
22.1. Включение
- Подать питание на оба БП D2700.
- Включить полку и дождаться инициализации.
- Включить DL380 G7.
- Проверить POST P411 и доступность logical drive.
22.2. Выключение
- Корректно остановить VM.
- Корректно остановить Proxmox/DL380.
- Дождаться полного выключения сервера.
- Перевести D2700 в Standby.
- При необходимости снять 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 оставлен отключённым.