SONiC Application Extension Guide

Rev 0.1

Table of Content

  • Revision

  • Scope

  • Porting an existing SONiC Docker image to be an Application Extension

  • Developing a new SONiC Application Extension

  • Adding 3rd party application to SONiC package database

  • Building SONiC image with 3rd party application

  • Manifest Reference

Revision

RevDateAuthorChange Description
0.102/2021Stepan BlyshchakInitial Proposal

Scope

This document gives developers a quick guide through developing new application extensions or porting existing SONiC docker images into application extension compatible ones.

It is recommended to get acquainted with HLD document before reading this document.

Porting an existing SONiC Docker image to be an Application Extension

It is possible to port existing SONiC docker image and make it an Application Extension.

An example of porting DHCP relay - https://github.com/sonic-net/sonic-buildimage/commit/b3b6938fda9244607fb00bfd36a74bccab0c38a9.

  1. Add a new build time flag to SONiC build system to control whether to include new Docker Image XXX:

Makefile.work

INCLUDE_XXX=$(INCLUDE_XXX)
  1. Register this Docker image in SONIC_PACKAGES_LOCAL target group and remove from SONIC_INSTALL_DOCKER_IMAGES:

rules/docker-XXX.mk

ifeq ($(INCLUDE_XXX), y)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
SONIC_PACKAGES_LOCAL += $(DOCKER_XXX_DBG)
else
SONIC_PACKAGES_LOCAL += $(DOCKER_XXX)
endif
endif
  1. Remove $(DOCKER_XXX)_RUN_OPT and replace with variables used to generate manifest for the docker:

rules/docker-XXX.mk

$(DOCKER_XXX)_CONTAINER_PRIVILEGED = true
$(DOCKER_XXX)_CONTAINER_VOLUMES += /etc/sonic:/etc/sonic:ro
$(DOCKER_XXX)_CONTAINER_VOLUMES += /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro
$(DOCKER_XXX)_CONTAINER_TMPFS += /tmp/

These variables are used to generate manifest for docker at build time (see generate_manifest function in https://github.com/sonic-net/sonic-buildimage/blob/master/rules/functions):

  1. For extensions that provide CLI commands a CLI plugin is needed.

4.1. Remove extension CLI commands from sonic-utilities code.

4.2. Move the implementation as a separate file into sonic-buildimage under dockers/docker-xxx/cli folder.

This plugin has to implement register function needed to be loaded by sonic-utilities core:

dockers/docker-xxx/cli/show.py

import click

@click.command()
def example()
    pass

def register(cli):
    cli.add_command(example)

register may throw an exception, in this case main CLI will still work but a warning will be printed to the user.

4.3 UT for CLI:

In case CLI has unit tests, they need to be moved from sonic-utilities into sonic-buildimage repository and placed under dockers/docker-xxx/cli-plugins-tests/.

In case this folder exists tests are executed at docker image build time and test log is recorder in target/docker-xxx.gz.log.

The command line to execute tests is:

pytest-3 -v

Developing a new SONiC Application Extension

To develop a new SONiC Application Extension use the following example extension as a template: https://github.com/stepanblyschak/sonic-example-extension.

Prerequisites, build instructions and installation instructions are present in repository README.md file.

Adding 3rd party application to SONiC package database

Modify files/build_templates/packages.json.j2 to include new package. Example for the previous sonic-example-extension - cpu-report:

{
    "cpu-report": {
        "repository": "stepanblyschak/cpu-report",
        "description": "CPU report example",
        "default-reference": "1.0.0"
    }
}

Building SONiC image with 3rd party application

To build SONiC image with 3rd party application pre-installed use SONIC_PACKAGES target group. See https://github.com/sonic-net/sonic-buildimage/blob/master/rules/sonic-packages.mk.

Create a file under rules/ called rules/cpu-report.mk with the following content:

CPU_REPORT = cpu-report
$(CPU_REPORT)_REPOSITORY = stepanblyschak/cpu-report
$(CPU_REPORT)_VERSION = 1.0.0
SONIC_PACKAGES += $(CPU_REPORT)

Additional options:

$(CPU_REPORT)_DEFAULT_FEATURE_STATE_ENABLED # "y" or "n" - whether feature is enabled by default at system start. Sets enabled in the FEATURE table. Disabled by default.
$(CPU_REPORT)_DEFAULT_FEATURE_OWNER # "local" or "kube". Default is "local".

Manifest Reference

Label name the manifest content should be written to:

com.azure.sonic.manifest

The value should contain a JSON serialized as a string.

PathTypeMandatoryDescription
/versionstringnoVersion of manifest schema definition. Defaults to 1.0.0.
/packageobjectnoPackage related metadata information.
/package/versionstringyesVersion of the package.
/package/namestringyesName of the package.
/package/descriptionstringnoDescription of the package.
/package/dependslistnoList of SONiC packages the service depends on. Defaults to []
/package/depends[index]/namestringyesName of SONiC Package
/package/depends[index]/versionstringnoVersion constraint expression string
/package/depends/[index]/componentsobjectnoPer component version
/package/breakslistnoList of SONiC package the service breaks with. Defaults to []
/package/breaks[index]/namestringyesName of SONiC Package
/package/breaks[index]/versionstringnoVersion constraint expression string
/package/breaks/[index]/componentsobjectnoPer component version
/package/base-os/objectnoBase OS versions constraints
/package/base-os/[index]/namestrnigyesBase OS component name
/package/base-os/[index]/versionstringyesBase OS component version
/package/changelogdictnoChangelog dictionary.
/package/changelog/<version>dictyesPackage version.
/package/changelog/<version>/changeslist of stringsyesChangelog messages for a given version.
/package/changelog/<version>/authorstringyesAuthor name.
/package/changelog/<version>/emailstringyesAuthor's email address.
/package/changelog/<version>/datestringyesDate and time in RFC 2822 format.
/package/init-cfgdictnoDefault package configuration in CONFIG DB format. Defaults to {}
/package/debug-dumpstringNoA command to be executed during system dump
/serviceobjectyesService management related properties.
/service/namestringyesName of the service. There could be two packages e.g: fpm-quagga, fpm-frr but the service name is the same "bgp". For such cases each one have to declare the other service in "conflicts".
/service/requireslist of stringsnoList of SONiC services the application requires.The option maps to systemd's unit "Requires=".
/service/requisitelist of stringsnoList of SONiC services that are requisite for this package.The option maps to systemd's unit "Requisite=".
/service/wanted-bylist of stringsnoList of SONiC services that wants for this package.The option maps to systemd's unit "WantedBy=".
/service/afterlist of stringsnoBoot order dependency. List of SONiC services the application is set to start after on system boot.
/service/beforelist of stringsnoBoot order dependency. List of SONiC services the application is set to start before on system boot.
/service/delayedbooleannoWether to generate a timer to delay the service on boot. Defaults to false.
/service/dependent-oflits of strnigsnoList of SONiC services this application is dependent of.Specifying in this option a service X, will regenerate the /usr/local/bin/X.sh script and upgrade the "DEPENDENT" list with this package service.This option is warm-restart related, a warm-restart of service X will not trigger this package service restart.On the other hand, this service package will be started, stopped, restarted togather with service X.Example:For "dhcp-relay", "radv", "teamd" this field will have "swss" service in the list.
/service/post-start-actionstringnoPath to an executable inside Docker image filesystem to be executed after container start.A package may use this field in case a systemd service should not reach started state before some condition. E.g.: A database service should not reach started state before redis process is not ready. Since, there is no control, when the redis process will start a "post-start-action" script may execute "redis-cli ping" till the ping is succeessful.
/service/pre-shutdown-actionstringnoPath to an executable inside Docker image filesystem to be executed before container stops.A uses case is to execute a warm-shutdown preparation script.A script that sends SIGUSR1 to teamd to initiate warm shutdown is one of such examples.
/service/host-servicebooleannoMulti-ASIC field. Wether a service should run in host namespace. Default is True.
/service/asic-servicebooleannoMulti-ASIC field. Wether a service should run per ASIC namespace. Default is False.
/service/warm-shutdown/objectnoWarm reboot related properties. Used to generate the warm-reboot script.
/service/warm-shutdown/afterlits of stringsnoWarm shutdown order dependency. List of SONiC services the application is set to stop after on warm shutdown.Example: a "bgp" may specify "radv" in this field in order to avoid radv to announce departure and cause hosts to lose default gateway.NOTE: Putting "radv" here, does not mean the "radv" should be installed as there is no such dependency for the "bgp" package.
/service/warm-shutdown/beforelits of stringsnoWarm shutdown order dependency. List of SONiC services the application is set to stop before on warm shutdown.Example: a "teamd" service has to stop before "syncd", but after "swss" to be able to send the last LACP PDU though CPU port right before CPU port becomes unavailable.
/service/fast-shutdown/objectnoFast reboot related properties. Used to generate the fast-reboot script.
/service/fast-shutdown/afterlits of stringsnoSame as for warm-shutdown.
/service/fast-shutdown/beforelits of stringsnoSame as for warm-shutdown.
/processesobjectnoProcesses infromation
/processes/[name]/reconcilesbooleannoWether process performs warm-boot reconciliation, the warmboot-finalizer service has to wait for. Defaults to False.
/containerobjectnoContainer related properties.
/container/privilegedstringnoStart the container in privileged mode. Later versions of manifest might extend container properties to include docker capabilities instead of privileged mode. Defaults to False.
/container/volumeslist of stringsnoList of mounts for a container. The same syntax used for '-v' parameter for "docker run".Example: "<src>:<dest>:<options>". Defaults to [].
/container/mountslist of objectsnoList of mounts for a container. Defaults to [].
/container/mounts/[id]/sourcestringyesSource for mount
/container/mounts/[id]/targetstringyesTarget for mount
/container/mounts/[id]/typestringyesType for mount. See docker mount types.
/container/tmpfslist of stringsnoTmpfs mounts. Defaults to []
/container/environmentdictnoEnvironment variables for Docker container (key=value). Defaults to {}.
/processeslistnoA list defining processes running inside the container.
/cliobjectnoCLI plugin information. NOTE: Later will deprecated and replaced with a YANG module file path.
/cli/mandatorybooleannoWether CLI is a mandatory functionality for the package. Default: False.
/cli/show-cli-pluginlist of stringsnoList of paths to plugins for sonic-utilities show CLI command.
/cli/config-cli-pluginlist of stringsnoList of paths to plugins for sonic-utilities config CLI command.
/cli/clear-cli-pluginlist of stringsnoList of paths to plugins for sonic-utilities sonic-clear CLI command.
/cli/auto-generate-configbooleanyesON/OFF triger for auto-generation of CLI command config. Default: false
/cli/auto-generate-showbooleanyesON/OFF triger for auto-generation of CLI command show. Default: false
/cli/auto-generate-config-source-yang-moduleslist of stringsnoIf set, config CLI auto-generation will only apply to specified YANG modules. The YANG module is referenced by the name recorded in labels (which should match the name of the module)
/cli/auto-generate-show-source-yang-moduleslist of stringsnoIf set, config CLI auto-generation will only apply to specified YANG modules. The YANG module is referenced by the name recorded in labels (which should match the name of the module)