Всем привет.
Недавние статьи на Хабре Импортозамещение на практике. Часть 1. Варианты и Не долго музыка играла… или как ОС Эльбрус так и не стала свободной не оставили меня равнодушным. Я решил поизучать этот вопрос в ключе задачи резервного копирования. Тем более, что в этой статье продукты Veeam Software упоминаются, а значит, вопрос может быть актуальным именно в ключе импортозамещения.
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/782/a91/e82/782a91e824b3206aa6c8f299bae8a311.jpg)
первоисточник изображения
Первым делом я решил скачать ОС «Эльбрус», а точнее — только доступный дистрибутив для архитектуры x86_64, посмотреть, как он устроен, и попробовать поставить на него Veeam Agent for Linux. Желающих узнать, что из этого получилось, прошу под кат.
Итак, маленькое отступление, а то вдруг кто-то не знает. «Эльбрус» — это такой процессор с довольно специфичной системой команд. Помимо него, есть программное обеспечение ОС «Эльбрус». И — вопреки распространенному заблуждению — для работы ОС «Эльбрус» не обязательно иметь аппаратный комплекс на базе процессора Эльбрус. Есть «PDK «Эльбрус» для x86» — собственно, он и появился в открытом доступе в виде установочного диска. Кстати, там есть сноска «PDK — platform development kit, набор разработчика» — отлично, значит, там есть как минимум компилятор.
Ещё одно маленькое вынужденное отступление. Дело в том, что я когда-то имел дело и с отечественным ПО, таким как «МСВС» и ОСРВ «Багет». Был опыт по работе и с отечественной элементной базой, в том числе и с процессором от МЦСТ. Поэтому со всей ответственностью могу сказать, что есть в этой области определённая специфика и, как раз её я постараюсь в статье не касаться. Когда ну прям очень захочется — буду ставить тэг [TBD]. Так что постараемся обойтись без откровенного троллинга и банальных стонов. В конце концов российскую оборонку и госструктуры нужно понять. Страна большая — бюджетмал.. [TBD].
Нулевой этап — качаем. Примечательно, что новость о том, что ОС «Эльбрус» стал доступной, вызвала резонанс, да такой, что сервер раздачи лёг. [TBD] Спасибо Yandex и тому инженеру, который догадался переложить его туда. Так что скорость закачки радует.
Первый этап — установка. Ставил я на первый попавшийся свободный для бесплатного использования гипервизор. Выделил два ядра, пару гигов ОЗУ, 32 Мб на видео (там ведь будет графический интерфейс, подумал я). Дисочек как обычно — 32 Гб.
Запустил инсталляцию. Инструкцией по установке я не пользовался, так что прокомментировать её не смогу. Интерфейс установки TUI — сурово-минималистический.
![](https://habrastorage.org/r/w1560/webt/h1/en/li/h1enlitw7iqvief-xs65x1y2f24.png)
Ну и отлично, без мышки, значит, обойдёмся.
Со следующим окном я справился со второй попытки. Почему бы при инсталляции с диска не выбрать по умолчанию устройство sr0 [TBD]?
Выбираем источник CD-ROM, едем дальше.
![](https://habrastorage.org/r/w1560/webt/vc/ha/fs/vchafs6xvohij8pkvwinexk9nzg.png)
Выбирая часовой пояс, я неожиданно понял, что система использует процесс загрузки init, и работаю я из TTY0.
![](https://habrastorage.org/r/w1560/webt/fp/rl/xs/fprlxsxgk-t4nlxnahabu76fshc.png)
ОК, значит отнесём «Эльбрус» к сообществу староверов[TBD]. В принципе, это хорошо: не нужно просить исходники, чтобы посмотреть, как отрабатывает процесс загрузки, так как всё на скриптах.
Остальное почти неважно: ставим всё и соглашаемся. Попутно узнаём, что ядро используется 3.14.79-13.84. Хм, а в Debian 7 было 3.2 [TBD].
Далее выбираем разбиение диска на разделы по умолчанию и… Видим предупреждение:
![](https://habrastorage.org/r/w1560/webt/ux/ps/fk/uxpsfksjojli1aqyoiixicsbp20.png)
Мда, как-то плохо автоматическая разметка справилась с диском в 32 гига. Диск менять я не стал, прошёл квест с ручной разметкой диска в стиле «всё в одном». Пришлось ставить ext3, так как /boot не мог быть в ext4.
Система встала без происшествий.
Второй этап — поиск альтернатив.
Покопавшись с содержимым второго диска, я понял, что это репозитарий с доп. пакетами. А глянув в /etc/apt/sources.list, сообразил, что монтировать его нужно в /mnt/cdrom. Зато /etc/os-release я не нашёл. Но есть /etc/mcst-version с содержимым 3.0-rc36. 3.0 — это, наверное, версия — вроде сходится, а вот rc36? В общем, распознать этот дистрибутив классическим путём стороннему ПО скорее всего не удастся.
В рутовом разделе в глаза бросается директория /mcst, а там с замиранием сердца я обнаружил /mcst/backup. То есть средство для резервного копирования есть, причём встроенное в систему! «Отлично», — подумал я, — «Посмотрим как это работает!»
Оказалось, что есть bash-скрипт /mcst/bin/backup размером в 4Kб, который обеспечивает копирование файлов. По умолчанию — в директорию /mcst/backup. В исходнике я ожидал увидеть команду rsync, но в дефолтной конфигурации его нет. Скрипт выполняет просто копирование файлов. Команда выглядит как-то так:
Хотя, может я чего не понял? Может, кто в комментах сможет пояснить: как этот скрипт обеспечивает безопасное и надёжное резервирование данных? [TBD]
rsync, кстати, есть в доп. репозитарии. Версия 3.1.3. Я думаю, использование rsync — это всё-же лучшая альтернатива приложению /mcst/bin/backup.
Далее я решил поставить свеженький Veeam Agent for Linux. Кто-то спросит: «А при чём тут Veeam и импортозамещение?» Да, в реестре его нет, но он сертифицирован ФСТЭК, а значит, при отсутствии альтернатив его можно использовать. Уделив минут пятнадцать на альтернативы из реестра, мне удалось найти 3 ссылки по слову «backup» (ни одной, относящейся к моему вопросу, на слово «резерв»). Глубоким анализом этих программ я не занимался — потому не буду пытаться судить, насколько они подходят для резервного копирования машин под ОС Linux. Кому надо — сам сделает вывод и поделится им в комментах.
Этап третий — установка Veeam Agent for Linux.
Итак, Veeam Agent for Linux состоит из двух пакетов: модуля ядра veeamsnap (кстати, исходник тут) и проприетарного user-space кода в виде пакета veeam.
С установкой модуля ядра возникла одна маленькая проблема — отсутствие пакета dkms. Это такой сервис, который позволяет собирать модули ядра из исходников. Как правило, он есть на всех deb дистрибутивах. Пришлось его скачать из стороннего deb репозитария. Одно порадовало — пакет не зависит от архитектуры, так что встал как родной. Почему его не внесли в список доступных пакетов, точнее, не разработали [TBD]? Возможно, предполагается, что никто не должен собирать и запускать всякие не МЦСТ модули ядра. Тут правда есть неувязочка — так как linux-headers есть. То есть, модуль, при желании, можно собрать руками и запускать при старте машины скриптом. Я думаю частых обновлений от МЦСТ ждать не стоит [TBD].
«OK, модуль встал — самое сложное позади», — подумал я… Пакет veeam для deb репозитария есть для платформы amd64, а у ОС «Эльбрус» платформа x86_64 [TBD]. Разница, конечно, только в названии, но эта разница делает практически все пакеты из сторонних deb репозитариев несовместимыми с ОС «Эльбрус». Устраняется это досадное недоразумение элементарно: достаточно разобрать пакет, поправить информацию об архитектуре и собрать обратно. Как это сделать нагуглилось моментально.
Другая проблема — зависимости. Нужные файлы вроде есть, а вот пакетов нет. Сложилось впечатление, что имена пакетов отличаются он «импортных аналогов». Возможно, библиотеки по-другому объединены в пакеты. Я не стал глубоко вдаваться в подробности, убрал почти все зависимости, и установка пошла.
Следом всплыли проблемы с кодом старта сервиса. Не оказалось скрипта /lib/init/vars.sh. Почему-то «Эльбрус» обходится без него, так что уберём и мы. Далее пришлось заменить функцию вывода сообщений: не оказалось функций log_daemon_msg и log_end_msg. Покопавшись в файле /lib/lsb/init-functions, я нашёл функцию log_success_msg — нам сгодится для экспериментов. Кстати, в файле /lib/lsb/init-functions строка "# Source SuSE`s rc functions" в начале файла [TBD].
После такой вот грубой обработки пакета напильником бэкап entire-machine на NFS-шару успешно запустился. Маунт бэкапа тоже прошёл успешно. Так что, я полагаю, для резервного копирования машины с PDK «Эльбрус», скачанной за «просто так» без всяких обязательств, Veeam Agent for Linux точно подойдёт. Даже после всех доработок напильником.
Конечно, формально дистрибутив ОС «Эльбрус» не поддерживается, так как не входит в перечень поддерживаемых. Кроме того, Veeam Agent for Linux на нём не тестировался отделом QA, так что тех. поддержки нет (по крайней мере на момент публикации статьи).
Надеюсь, статья будет полезной тем, кто пытается реализовать приказ №334 от 29.06.2017. Мои вам… [TBD].
Недавние статьи на Хабре Импортозамещение на практике. Часть 1. Варианты и Не долго музыка играла… или как ОС Эльбрус так и не стала свободной не оставили меня равнодушным. Я решил поизучать этот вопрос в ключе задачи резервного копирования. Тем более, что в этой статье продукты Veeam Software упоминаются, а значит, вопрос может быть актуальным именно в ключе импортозамещения.
![image](https://habrastorage.org/getpro/habr/post_images/782/a91/e82/782a91e824b3206aa6c8f299bae8a311.jpg)
первоисточник изображения
Первым делом я решил скачать ОС «Эльбрус», а точнее — только доступный дистрибутив для архитектуры x86_64, посмотреть, как он устроен, и попробовать поставить на него Veeam Agent for Linux. Желающих узнать, что из этого получилось, прошу под кат.
Итак, маленькое отступление, а то вдруг кто-то не знает. «Эльбрус» — это такой процессор с довольно специфичной системой команд. Помимо него, есть программное обеспечение ОС «Эльбрус». И — вопреки распространенному заблуждению — для работы ОС «Эльбрус» не обязательно иметь аппаратный комплекс на базе процессора Эльбрус. Есть «PDK «Эльбрус» для x86» — собственно, он и появился в открытом доступе в виде установочного диска. Кстати, там есть сноска «PDK — platform development kit, набор разработчика» — отлично, значит, там есть как минимум компилятор.
Ещё одно маленькое вынужденное отступление. Дело в том, что я когда-то имел дело и с отечественным ПО, таким как «МСВС» и ОСРВ «Багет». Был опыт по работе и с отечественной элементной базой, в том числе и с процессором от МЦСТ. Поэтому со всей ответственностью могу сказать, что есть в этой области определённая специфика и, как раз её я постараюсь в статье не касаться. Когда ну прям очень захочется — буду ставить тэг [TBD]. Так что постараемся обойтись без откровенного троллинга и банальных стонов. В конце концов российскую оборонку и госструктуры нужно понять. Страна большая — бюджет
Нулевой этап — качаем. Примечательно, что новость о том, что ОС «Эльбрус» стал доступной, вызвала резонанс, да такой, что сервер раздачи лёг. [TBD] Спасибо Yandex и тому инженеру, который догадался переложить его туда. Так что скорость закачки радует.
Первый этап — установка. Ставил я на первый попавшийся свободный для бесплатного использования гипервизор. Выделил два ядра, пару гигов ОЗУ, 32 Мб на видео (там ведь будет графический интерфейс, подумал я). Дисочек как обычно — 32 Гб.
Запустил инсталляцию. Инструкцией по установке я не пользовался, так что прокомментировать её не смогу. Интерфейс установки TUI — сурово-минималистический.
![](https://habrastorage.org/webt/h1/en/li/h1enlitw7iqvief-xs65x1y2f24.png)
Ну и отлично, без мышки, значит, обойдёмся.
Со следующим окном я справился со второй попытки. Почему бы при инсталляции с диска не выбрать по умолчанию устройство sr0 [TBD]?
Выбираем источник CD-ROM, едем дальше.
![](https://habrastorage.org/webt/vc/ha/fs/vchafs6xvohij8pkvwinexk9nzg.png)
Выбирая часовой пояс, я неожиданно понял, что система использует процесс загрузки init, и работаю я из TTY0.
![](https://habrastorage.org/webt/fp/rl/xs/fprlxsxgk-t4nlxnahabu76fshc.png)
ОК, значит отнесём «Эльбрус» к сообществу староверов[TBD]. В принципе, это хорошо: не нужно просить исходники, чтобы посмотреть, как отрабатывает процесс загрузки, так как всё на скриптах.
Остальное почти неважно: ставим всё и соглашаемся. Попутно узнаём, что ядро используется 3.14.79-13.84. Хм, а в Debian 7 было 3.2 [TBD].
Далее выбираем разбиение диска на разделы по умолчанию и… Видим предупреждение:
![](https://habrastorage.org/webt/ux/ps/fk/uxpsfksjojli1aqyoiixicsbp20.png)
Мда, как-то плохо автоматическая разметка справилась с диском в 32 гига. Диск менять я не стал, прошёл квест с ручной разметкой диска в стиле «всё в одном». Пришлось ставить ext3, так как /boot не мог быть в ext4.
Система встала без происшествий.
Второй этап — поиск альтернатив.
Покопавшись с содержимым второго диска, я понял, что это репозитарий с доп. пакетами. А глянув в /etc/apt/sources.list, сообразил, что монтировать его нужно в /mnt/cdrom. Зато /etc/os-release я не нашёл. Но есть /etc/mcst-version с содержимым 3.0-rc36. 3.0 — это, наверное, версия — вроде сходится, а вот rc36? В общем, распознать этот дистрибутив классическим путём стороннему ПО скорее всего не удастся.
В рутовом разделе в глаза бросается директория /mcst, а там с замиранием сердца я обнаружил /mcst/backup. То есть средство для резервного копирования есть, причём встроенное в систему! «Отлично», — подумал я, — «Посмотрим как это работает!»
Оказалось, что есть bash-скрипт /mcst/bin/backup размером в 4Kб, который обеспечивает копирование файлов. По умолчанию — в директорию /mcst/backup. В исходнике я ожидал увидеть команду rsync, но в дефолтной конфигурации его нет. Скрипт выполняет просто копирование файлов. Команда выглядит как-то так:
cp -rpdx <file backup> <file>
Целиком файл /mcst/bin/backup тут
Сразу предупреждаю, что для полного понимания одного этого скрипта недостаточно. Он тянет функции из /mcst/bin/source, который представляет собой что-то типа библиотеки функций. Его я приводить не стал (44KB).
#!/bin/bash
unalias -a
set +vx
source $(dirname $0)/source
[[ $? != 0 ]] && exit 1
OPTIONS="hvcdrRil:L:"
usage()
{
echo "Usage: $PROG_NAME [-$OPTIONS] [backup]"
echo " h - this help"
echo " v vv vvv - verbose, very verbose, extremly verbose"
echo " c - create backup"
echo " d - diffs backup and system"
echo " r - recovery system"
echo " R - remove backup"
echo " i - prompt before backup removing"
echo " l list - additional backup files list"
echo " L list - global backup files list"
echo " backup - backup directory, default /mcst/backup/backup"
}
init_prog()
{
typeset flg=0
while getopts $OPTIONS opt
do
case $opt in
h ) usage; exit 0;;
v ) (( verbose = verbose + 1 )); set_verbose;;
c ) flg=1; c_flg=1;;
d ) flg=1; d_flg=1;;
r ) flg=1; r_flg=1;;
R ) flg=1; R_flg=1;;
i ) i_flg=1;;
l ) l_flg=1; list_arg="$list_arg $OPTARG";;
L ) L_flg=1; LIST_arg="$LIST_arg $OPTARG";;
* ) usage "Invalid option"; exit 1;;
esac
done
set_verbose
check_su
init_variables
shift $((OPTIND-1))
if (( $# > 1 ))
then
echo_fatal "invalid arguments number, exp 0|1, act $#"
exit 1
fi
[[ $# = 1 ]] && BACKUP=$1
echo "Backup directory is $BACKUP"
if [[ $L_flg = 1 ]]
then
backup_list="$LIST_arg"
elif [[ $c_flg != 1 && $R_flg != 1 ]]
then
get_output_cmd "cat $BACKUP/$BACKUP_LIST_NAME"
backup_list="$output_cmd"
else
get_output_cmd "get_backup_list"
backup_list="$output_cmd"
fi
if [[ $l_flg = 1 ]]
then
backup_list="$backup_list $list_arg"
fi
if [[ $flg = 0 ]]
then
if [[ -d $BACKUP ]]
then
ls -laR $BACKUP
else
echo_info "Cannot access $BACKUP"
fi
echo "backup_list=$backup_list"
exit 0
fi
### echo "Backup list: $backup_list"
}
create_file()
{
typeset f=$1 fr=$2
typeset fb
[[ -z $fr ]] && fr=$f
fb=${f#/}
fb=$BACKUP/$fb
xcmd="rm -rf $fb"
set_cmd "$xcmd"
run_cmd
xcmd="mkdir -p $fb"
set_cmd "$xcmd"
run_cmd
if [[ -a $fr ]]
then
xcmd="cp -rpdx $fr $fb/file"
set_cmd "$xcmd"
run_cmd
xcmd="touch $fb/create"
set_cmd "$xcmd"
run_cmd
else
xcmd="touch $fb/delete"
set_cmd "$xcmd"
run_cmd
fi
}
diff_file()
{
typeset f=$1
typeset fb
fb=${f#/}
fb=$BACKUP/$fb
if [[ -f $fb/delete ]]
then
echo_info "$f absent"
elif [[ -f $fb/create ]]
then
# echo "state: create $f"
if [[ ! -a $f ]]
then
echo_info "cannot access $f"
else
xcmd="diff -r $f $fb/file"
echo "$xcmd"
set_cmd "$xcmd" "" "0 1 2"
run_cmd
fi
else
echo_fatal "wrong $f backup"
exit 1
fi
}
recovery_file()
{
typeset f=$1
typeset fb
fb=${f#/}
fb=$BACKUP/$fb
if [[ ! -a $fb ]]
then
echo_fatal "cannot access $fb"
exit 1
fi
xcmd="rm -rf $f"
set_cmd "$xcmd"
run_cmd
if [[ -f $fb/delete ]]
then
:
elif [[ -f $fb/create ]]
then
xcmd="cp -rpdx $fb/file $f"
set_cmd "$xcmd"
run_cmd
else
echo_fatal "wrong $fb backup"
exit 1
fi
}
remove_backup()
{
echo "Remove backup"
if [[ ! -d $BACKUP ]]
then
echo_info "Cannot access $BACKUP"
return
fi
if [[ ! -f $BACKUP/$BACKUP_LIST_NAME ]]
then
echo_fatal "$BACKUP_LIST_NAME absent, remove backup manually"
exit 0
fi
answer=
if [[ $i_flg = 1 ]]
then
echo -n "Remove $BACKUP directory (yes/...)?"
read answer
else
answer=yes
fi
if [[ $answer = yes ]]
then
xcmd="rm -rf $BACKUP"
set_cmd "$xcmd"
run_cmd
fi
}
recovery_backup()
{
echo "Recovery system from $BACKUP"
for f in $backup_list
do
get_output_cmd "get_mount_point $f"
mnt=$output_cmd
get_output_cmd "is_ro_mounted $mnt"
mnt=$output_cmd
if [[ ! -z $mnt ]]
then
remount_rw_fs $mnt
fi
recovery_file $f
if [[ ! -z $mnt ]]
then
remount_ro_fs $mnt
fi
done
echo "The system is ready, reboot the system manually"
}
create_backup()
{
echo "Create backup"
xcmd="mkdir -pm0777 $BACKUP"
set_cmd "$xcmd"
run_cmd
for v in $backup_list
do
f=${v%%:*}
backup_list2="$backup_list2 $f"
fr=${v#*:}
create_file $f $fr
done
echo "$backup_list2" >$BACKUP/$BACKUP_LIST_NAME
}
diff_backup()
{
echo "Diffs system and backup"
if [[ ! -d $BACKUP ]]
then
echo_fatal "cannot access $BACKUP"
exit 1
fi
for f in $backup_list
do
diff_file $f
done
}
main()
{
typeset f mnt mnt_list answer
if [[ $R_flg = 1 ]]
then
remove_backup
fi
if [[ $r_flg = 1 ]]
then
recovery_backup
fi
if [[ $c_flg = 1 ]]
then
create_backup
fi
if [[ $d_flg = 1 ]]
then
diff_backup
fi
}
init_prog "$@"
main
exit 0
Хотя, может я чего не понял? Может, кто в комментах сможет пояснить: как этот скрипт обеспечивает безопасное и надёжное резервирование данных? [TBD]
rsync, кстати, есть в доп. репозитарии. Версия 3.1.3. Я думаю, использование rsync — это всё-же лучшая альтернатива приложению /mcst/bin/backup.
Далее я решил поставить свеженький Veeam Agent for Linux. Кто-то спросит: «А при чём тут Veeam и импортозамещение?» Да, в реестре его нет, но он сертифицирован ФСТЭК, а значит, при отсутствии альтернатив его можно использовать. Уделив минут пятнадцать на альтернативы из реестра, мне удалось найти 3 ссылки по слову «backup» (ни одной, относящейся к моему вопросу, на слово «резерв»). Глубоким анализом этих программ я не занимался — потому не буду пытаться судить, насколько они подходят для резервного копирования машин под ОС Linux. Кому надо — сам сделает вывод и поделится им в комментах.
Этап третий — установка Veeam Agent for Linux.
Итак, Veeam Agent for Linux состоит из двух пакетов: модуля ядра veeamsnap (кстати, исходник тут) и проприетарного user-space кода в виде пакета veeam.
С установкой модуля ядра возникла одна маленькая проблема — отсутствие пакета dkms. Это такой сервис, который позволяет собирать модули ядра из исходников. Как правило, он есть на всех deb дистрибутивах. Пришлось его скачать из стороннего deb репозитария. Одно порадовало — пакет не зависит от архитектуры, так что встал как родной. Почему его не внесли в список доступных пакетов, точнее, не разработали [TBD]? Возможно, предполагается, что никто не должен собирать и запускать всякие не МЦСТ модули ядра. Тут правда есть неувязочка — так как linux-headers есть. То есть, модуль, при желании, можно собрать руками и запускать при старте машины скриптом. Я думаю частых обновлений от МЦСТ ждать не стоит [TBD].
«OK, модуль встал — самое сложное позади», — подумал я… Пакет veeam для deb репозитария есть для платформы amd64, а у ОС «Эльбрус» платформа x86_64 [TBD]. Разница, конечно, только в названии, но эта разница делает практически все пакеты из сторонних deb репозитариев несовместимыми с ОС «Эльбрус». Устраняется это досадное недоразумение элементарно: достаточно разобрать пакет, поправить информацию об архитектуре и собрать обратно. Как это сделать нагуглилось моментально.
mkdir tmp
dpkg-deb -R original.deb tmp
# edit DEBIAN/postinst
dpkg-deb -b tmp fixed.deb
Другая проблема — зависимости. Нужные файлы вроде есть, а вот пакетов нет. Сложилось впечатление, что имена пакетов отличаются он «импортных аналогов». Возможно, библиотеки по-другому объединены в пакеты. Я не стал глубоко вдаваться в подробности, убрал почти все зависимости, и установка пошла.
Следом всплыли проблемы с кодом старта сервиса. Не оказалось скрипта /lib/init/vars.sh. Почему-то «Эльбрус» обходится без него, так что уберём и мы. Далее пришлось заменить функцию вывода сообщений: не оказалось функций log_daemon_msg и log_end_msg. Покопавшись в файле /lib/lsb/init-functions, я нашёл функцию log_success_msg — нам сгодится для экспериментов. Кстати, в файле /lib/lsb/init-functions строка "# Source SuSE`s rc functions" в начале файла [TBD].
После такой вот грубой обработки пакета напильником бэкап entire-machine на NFS-шару успешно запустился. Маунт бэкапа тоже прошёл успешно. Так что, я полагаю, для резервного копирования машины с PDK «Эльбрус», скачанной за «просто так» без всяких обязательств, Veeam Agent for Linux точно подойдёт. Даже после всех доработок напильником.
Конечно, формально дистрибутив ОС «Эльбрус» не поддерживается, так как не входит в перечень поддерживаемых. Кроме того, Veeam Agent for Linux на нём не тестировался отделом QA, так что тех. поддержки нет (по крайней мере на момент публикации статьи).
Надеюсь, статья будет полезной тем, кто пытается реализовать приказ №334 от 29.06.2017. Мои вам… [TBD].