Skip to content

Repository files navigation

Рекомендации и пояснения

Сервис

  • Для создания mqtt клиента используйте MQTTClient (на базе paho) из библиотеки wb_common. Вы можете использовать функцию клиента start(), которая по умолчанию запускает клиента в отдельном потоке. Также вы можете выключить создание отдельного потока и вручную запускать клиента через start() + loop_forever() в текущем потоке. Использовать функцию loop() для работы не рекомендуется, тк она не делает автоматический реконнект в случае разрыва соединения с брокером.

  • Для перехвата сигналов используйте библиотеку signal: signal.SIGTERM (остановка через systemctl stop) и signal.SIGINT (остановка через Ctrl-C в консоли). В обработчике сигнала нужно вызвать stop(). Если вы используете loop_forever(), то в обработчике не нужно принудительно завершать основной процесс, выполнение после обработки сигнала вернётся в loop_forever(), которая завершится. Больше информации и примеров http://www.steves-internet-guide.com/client-connections-python-mqtt/.

  • Запуск. Как правило, весь основной код оформляется одельным python-пакетом. В пакете создается основной файл (например main.pyили по имени сервиса). В нем создается функция main, которая может быть как импортирована в другой код, так и запущена при обычном запуске файла из консоли. В папке /bin/ создается файл, который будет импортировать и запускать main из пакета.

Пакетирование

Исходная система - где происходит сборка deb-пакета. В терминологии debian - build-система Целевая система - куда устанавливается пакет. В терминологии debian - host-система

Для сборки deb-пакетов в Wiren Board используется кросс-компиляция. Это значит, что сборка будет происходить на машине с архитектурой, отличной от той, на которой всё будет запускаться, и нужно подсказать сборщику, как правильно разрешать зависимости.

  • Собрать пакет вручную и посмотреть что получается можно внутри devcontainer-a командой

    dpkg-buildpackage -rfakeroot -us -uc
    

    Директория debian в проекте (исходная система) будет содержать структуру директорий относительно корня целевой системы. Перед сборкой не забыть установить build-depends.

  • /debian/control для Python

    Для source пакета в Build-Depends нужно использоватьpython3-all вместо python3, потому что это отвязывает процедуру сборки от конкретной реализации Python, и distutils автоматически подтягивается с подходящей версией. Писать python3-all:any в пакетах-библиотеках обычно не имеет смысла, тк используем arch-all.

    Source: wb-my-lib
    ...
    Build-Depends: python3-all, dh-python, ...
    

    Для binary пакетов

    Package: wb-my-lib
    Architecture: all
    Depends: ${python3:Depends}, ${misc:Depends}, ...
    

    Architecture: all (не путать с Architecture: any) нужен для того, чтобы собранный пакет был платформо-независимый. python3 в зависимости не записывается, его заменяет ${python3:Depends}.

  • Кодогенерация при кросс-компиляции

    У нас этот сценарий применяется в wb-mqtt-serial. Кодогенерация там - сборка шаблонов с помощью j2cli. Для того чтобы установить j2cli, совместимый с архитектурой сборщика, используем :native.

    Source: wb-mqtt-serial
    ...
    Build-Depends: ..., j2cli:native
    
  • Резервное копирование конфигов

    Сервис wb-configs-early умеет делать резервное копирование файлов перед началом работы системы и перед выключением. Он перемещает сам файл конфига в раздел, который не сбрасывается при установке обновлений, а сам конфиг в исходном расположении /etc/ заменяет на симлинк. Для этого нужно в папку /etc/wb-configs.d положить скрипт, который вызовет wb_move для всех нужных конфигов (в данном примере это 10wb-python-service-template).

FAQ по сборке и пакетированию для продвинутых

  • Почему all-пакеты не собираются в sbuild с --host=armhf?

    Альтернативная формулировка - почему all-пакеты нельзя было раньше собрать через wbdev cdeb.

    Во-первых, потому что в Debian обычно делят сборку all-пакетов и кросс-компиляцию, вот (пруф).

    Во-вторых, это могло бы заработать, если бы мейнтейнеры Python-библиотек в Debian озадачивались добавлением Multi-Arch: foreign в свои пакеты. На ноябрь 2022 этой пометки нет как минимум в python3-paho-mqtt и python3-jinja2, а эти пакеты мы часто используем.

    В итоге оказалось проще пойти каноничным путём и собирать all и any отдельно.

  • Для чего при сборке cdeb запускаются и --arch-all, и --arch-any?

    Раньше для сборки пакетов отдельно использовались wbdev cdeb (для any) и wbdev ndeb (для all). Это было очень актуально во времена wheezy, когда не было ещё multiarch, и пакеты для Wiren Board приходилось собирать в chroot с qemu. Тогда для экономии времени сборки (qemu медленный) сделали отдельно команду ndeb, которой собирали all-пакеты прямо в Docker-окружении.

    Потом мы перешли на sbuild, и разница между cdeb и ndeb стала размываться, потому что для обеих команд уже использовалось sbuild-окружение, только с разным аргументом --host.

    Так получилось, что при переходе на релизную систему, когда для сборки стало нужно указывать, для какой платформы происходит сборка (wb5/wb6/wb7), добавление наших репозиториев (http://deb.wirenboard.com/wbX/<deb-release>) делалось только в cdeb. Для ndeb появился репозиторий dev-tools, который нужен скорее для сборки пакетов, нужных нам на производстве и для CI.

    Пока наши all-пакеты не зависели друг от друга при сборке, можно было продолжать пользоваться такой системой, выбирая в зависимости от типа пакета cdeb или ndeb. При разработке wb-device-manager нам понадобились all-зависимости из нашего репозитория.

    В этот момент @webconn решил, что пора объединять cdeb и ndeb - так получается меньше пайплайнов для CI и не надо дублировать код в devenv. Также меньше возможностей ошибиться при сборке - скрипты сами сделают всё, что нужно.

    ndeb с этого момента стал deprecated, о чём пишется WARNING.

  • Почему в Python-библиотеках не пишем Multi-Arch в пакетах?

    Как минимум потому что это не делают даже в Debian.

Перед контрибьютом

Перед тем как открывать PR, убедитесь, что:

  1. Код проходит тесты (pytest tests/);
  2. Концы строк во всех файлах остаются LF (это обеспечивает .gitattributes);
  3. Пакет успешно собирается и на выходе получается deb-файл;
  4. Пакет проверен на реальном контроллере:
    • Устанавливается;
    • После установки импортируется namespace-пакет;
    • Сервис запускается сам после установки;
    • Сервис автоматически стартует после перезагрузки контроллера;
    • Пакет удаляется.

Проверка сборки на контроллере

Выполняется на самом Wiren Board (арх all, подойдёт любой). Репозитории WB на контроллере должны быть настроены — из них тянется python3-wb-common.

# 1. Инструменты сборки (один раз на контроллер)
sudo apt update
sudo apt install -y build-essential devscripts equivs git

# 2. Копия из своей ветки
GIT_BRANCH_NAME="feature/branch-name"
git clone -b "${GIT_BRANCH_NAME}" --single-branch \
  https://github.com/wirenboard/wb-python-service-template.git
cd wb-python-service-template

# 3. Build-зависимости из debian/control и сборка пакета
sudo mk-build-deps -ir debian/control
dpkg-buildpackage -us -uc -b

Далее нужно проверить что пакета корректно собран и сервис поднимается сам

# 1. Установка собранного пакета
sudo apt install -y ../wb-python-service-template_*.deb

# 2. Проверка импорта namespace-пакета
python3 -c "import wb.python_service_template.main as m; print('import OK:', m.main)"

# 3. Проверка работы сервиса
systemctl is-enabled wb-python-service-template   # ожидается: enabled
systemctl status wb-python-service-template       # ожидается: active (running)

# 4. Проверка автозапуска после перезагрузки
sudo reboot
# после загрузки снова зайти по SSH и проверить, что сервис поднялся сам:
systemctl status wb-python-service-template       # ожидается: active (running)

# 5. Удаление после проверки
sudo apt purge -y wb-python-service-template

При успешной сборке pytest прогонит tests/ (шаг сборки dh_auto_test), а после установки сервис включится автоматически благодаря секции [Install] в юните.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Contributors

Languages