SONiC Image and Build System
=====
###### tags: `SONiC`
contributed by < Dung-Ru Tsai >
Build the Docker Image/installer image
`git clone --recursive https://github.com/Azure/sonic-buildimage`
[Build p4 Image Jenkins Log:](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all/543/console)
[Build image Getting Started](https://github.com/Azure/sonic-buildimage/blob/master/README.md)
[SONiC Building System Guide](https://github.com/Azure/sonic-buildimage/blob/master/README.buildsystem.md)
# Install the Dependencies:
```bash
sudo apt install python3-pip
sudo apt-get install -y python-pip
sudo pip install --force-reinstall --upgrade jinja2>=2.10
sudo pip install j2cli
```
# Build images
```bash=
# Ensure the 'overlay' module is loaded on your development system
sudo modprobe overlay
# Enter the source directory
cd sonic-buildimage
# (Optional) Checkout a specific branch. By default, it uses master branch. For example, to checkout the branch 201911, use "git checkout 201911"
git checkout [branch_name]
# Execute make init once after cloning the repo, or after fetching remote repo with submodule updates
make init
# Execute make configure once to configure ASIC
make configure PLATFORM=[ASIC_VENDOR]
make configure PLATFORM=vs
# Build SONiC image
make all
ls -al target
-rwxr-xr-x 1 dutsai dutsai 864759062 Mar 4 13:18 sonic-vs.bin
-rw-r--r-- 1 dutsai dutsai 404782 Mar 3 18:13 sonic-vs.bin.log
-rwxr-xr-x 1 dutsai dutsai 877791856 Mar 4 13:20 sonic-vs.img.gz
```
## Backend build
- Contruct the build sonic environment docker.
- The build system will build the Backend first.
- Makefile, slave.mk and sonic-slave-xxx/Dockerfile are the backend of buildimage.
- `sonic-slave-xxx/Dockerfile` describe what builder-docker looks like.
Makefile => Makefile.work => slave.mk
## Front End Build
Build the sonic image content, the design methologies is inheritance the makefile.

### `rules/`: collection of recipes for platform independent targets.
- **Recipes**: Necessary steps and take`rules/swss.mk` as example
- xxx_SRC_PATH: path to sources
- xxx_DEPENDS: build dependencies
- xxx_RDEPENDS: runtime dependencies
- SONIC_DPKG_DEBS: add our target to `SONIC_DPKG_DEBS` target group
- add_derived_package
- **Target groups**: Main target group for building `.deb` packages
- SONIC_DPKG_DEBS (Necessary)
- It will become makefile target
- slave.mk: `$(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) `
- `make target/debs/swss_1.0.0_amd64.deb`
- SONIC_PYTHON_STDEB_DEBS
- SONIC_MAKE_DEBS: just define your own Makefile and add it to buildimage
```clike=
SOME_NEW_DEB = some_new_deb.deb # name of your package
$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources
$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies
$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies
SONIC_MAKE_DEBS += $(SOME_NEW_DEB) # add package to this target group
```
If some packages have to be built locally due to some legal issues or they are already prebuilt and available online, you might find next four target groups useful.
- SONIC_COPY_DEBS
- SONIC_COPY_FILES
- SONIC_ONLINE_DEBS: debian packages that should be fetched from an online source
- SONIC_ONLINE_FILES
- SONIC_SIMPLE_DOCKER_IMAGES
- SONIC_DOCKER_IMAGES
Container makefile `rules/docker-orchagent.mk`:
```bash=
DOCKER_ORCHAGENT_STEM = docker-orchagent #docker image name
$(DOCKER_ORCHAGENT)_CONTAINER_NAME = swss # container name
```
Dabeian package makefile`rules/swss.mk`:
```bash=
SWSS = swss_1.0.0_$(CONFIGURED_ARCH).deb
```
### `rules/config`: configuration file for a build system
- config system default login password
```c
DEFAULT_PASSWORD = YourPaSsWoRd
```
### `dockers/`: place where you can find Dockerfiles for generic docker images.
### `src/`: source code for generic packages goes
### `platform/`: contains all vendor-specific recipes
# Clean the Build
`make reset`
# Only Build your change .deb and docker:
### Docker image
```bash=
make target/docker-orchagent.gz
```
### Debian packages
```bash=
make target/debs/swss_1.0.0_amd64.deb
make target/debs/swss_1.0.0_amd64.deb-clean
make target/debs/stretch/libsairedis_1.0.0_amd64.deb
make target/debs/stretch/libsairedis_1.0.0_amd64.deb-clean
```
# Output Image folder: `sonic-buildimage/target`
```bash=
dutsai@diag-tpe-01:/ws-dutsai/sonic-buildimage/target (master)$ ls
cache docker-dhcp-relay.gz.log docker-orchagent.gz docker-sonic-mgmt-framework.gz python-debs
debs docker-fpm-frr.gz docker-orchagent.gz.log docker-sonic-mgmt-framework.gz.log python-wheels
docker-base-buster.gz docker-fpm-frr.gz.log docker-platform-monitor.gz docker-sonic-telemetry.gz sonic-vs.bin
docker-base-buster.gz-load.log docker-gbsyncd-vs.gz docker-platform-monitor.gz.log docker-sonic-telemetry.gz.log sonic-vs.bin.log
docker-base-buster.gz.log docker-gbsyncd-vs.gz.log docker-ptf.gz.log docker-sonic-vs.gz sonic-vs.img.gz
docker-config-engine-buster.gz docker-lldp.gz docker-router-advertiser.gz docker-sonic-vs.gz.log sonic-vs.img.gz.log
docker-config-engine-buster.gz-load.log docker-lldp.gz.log docker-router-advertiser.gz.log docker-syncd-vs.gz sonic-vs.raw
docker-config-engine-buster.gz.log docker-macsec.gz docker-sflow.gz docker-syncd-vs.gz.log sonic-vs.raw.log
docker-database.gz docker-macsec.gz.log docker-sflow.gz.log docker-teamd.gz versions
docker-database.gz.log docker-nat.gz docker-snmp.gz docker-teamd.gz.log
docker-dhcp-relay.gz docker-nat.gz.log docker-snmp.gz.log files
```
| | make command | Image Type | Testbed | Log |
| ------------- | ------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------- | ---------------------- |
| Run on ONIE | target/sonic-vs.bin | sonic-vs.bin | | sonic-vs.bin.log |
| Run on KVM | target/sonic-vs.img.gz | sonic-vs.img.gz | [KVM Testbed](https://github.com/Azure/sonic-mgmt/blob/master/docs/testbed/README.testbed.VsSetup.md) | sonic-vs.img.gz.log |
| | target/sonic-vs.raw | | | sonic-vs.raw.log |
| Run on docker | target/docker-sonic-vs.gz | docker-sonic-vs.gz | | docker-sonic-vs.gz.log |
# sonic-slave environment update
Enter the slave docker (build environment docker)
`$ make sonic-slave-bash`
Build the environment Docker
`$ make sonic-slave-build`
One can print out all available targets by executing the following command:
`$ make list`
# Debug dockers and debug SONiC installer image
```bash=
INSTALL_DEBUG_TOOLS=y make target/sonic-vs.img.gz
```
Debug images carry a suffix of "-dbg"
e.g. target/docker-orchagent-dbg.gz
Enlarge the memory size for KVM: `scripts/build_kvm_image.sh`:
```bash=
+++ b/scripts/build_kvm_image.sh
@@ -4,7 +4,7 @@
#
# SPDX-License-Identifier: GPL-2.0
-MEM=3072
+MEM=4096
DISK=$1
ONIE_RECOVERY_ISO=$2
```
:::info
$INSTALLER = target/sonic-vs.bin
:::
[GDB Debug with SONiC](https://github.com/Azure/sonic-buildimage/blob/master/README.buildsystem.md#build-debug-dockers-and-debug-sonic-installer-image)
The gdb could be used in each container.
```bash=
tar -zxvf /src/sonic_src.tar.gz -C /debug
docker exec -it bgp bash
gdb -p 48
(gdb) directory /debug/src/sonic-frr/frr/staticd
```
# Target images (Docker Images in SONiC)
- The target directory is `./target`, containing the NOS installer image and docker images.
- **sonic-generic.bin**: SONiC switch installer image (ONIE compatible)
- **sonic-aboot.bin**: SONiC switch installer image (Aboot compatible)
- **docker-base.gz**: base docker image where other docker images are built from, only used in build process (gzip tar archive)
- **docker-database.gz**: docker image for in-memory key-value store, used as inter-process communication (gzip tar archive)
- **docker-fpm.gz**: docker image for quagga with fpm module enabled (gzip tar archive)
- **docker-orchagent.gz**: docker image for SWitch State Service (SWSS) (gzip tar archive)
- **docker-sonic-vs.gz**: docker image for all-in-one for software virtual switch (gzip tar archive)
- **docker-sonic-mgmt.gz**: docker image for [managing, configuring and monitoring SONiC](https://github.com/Azure/sonic-mgmt) (gzip tar archive)
# Extract the denian package to specific folder
```
dpkg -x syncd-vs_1.0.0_amd64.deb your_path
```
# Develope/Push code procedure
Gitflow
```sequence
Note over commiter: Start
Note over commiter: submodule at dev_branch
commiter->submodule_gitlab: push
Note over submodule_gitlab: Merge Request
submodule_gitlab-->jenkins: trigger
Note over jenkins: test dev_branch
Reviewer->submodule_gitlab: Merge and delete dev_branch
submodule_gitlab-->jenkins: trigger
Note over jenkins: test 202012.clounix
Note over commiter: buildimage at dev_branch
Note over commiter: commit submodule id to buildimage
commiter->buildimage_gitlab: push dev_branch to buildimage
Note over buildimage_gitlab: Merge Request
buildimage_gitlab-->jenkins: trigger
Note over jenkins: test dev_branch
Reviewer->buildimage_gitlab: Merge and delete dev_branch
buildimage_gitlab-->jenkins: trigger
Note over jenkins: test 202012.clounix
Note over jenkins: END
```
# Useful MAKE Optional
- SONIC_BUILD_JOBS=4
# Build Fail case
## make target/python-wheels/sonic_config_engine-1.0-py2-none-any.whl
```bash=
Using /sonic/src/sonic-config-engine/.eggs/contextlib2-21.6.0-py2.7.egg
running egg_info
writing requirements to sonic_config_engine.egg-info/requires.txt
writing sonic_config_engine.egg-info/PKG-INFO
writing top-level names to sonic_config_engine.egg-info/top_level.txt
writing dependency_links to sonic_config_engine.egg-info/dependency_links.txt
reading manifest file 'sonic_config_engine.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'sonic_config_engine.egg-info/SOURCES.txt'
running build_ext
test_comprehensive (tests.test_cfggen_pfx_filter.TestPfxFilter) ... Traceback (most recent call last):
File "./sonic-cfggen", line 33, in <module>
import netaddr
File "/sonic/src/sonic-config-engine/.eggs/netaddr-0.8.0-py2.7.egg/netaddr/__init__.py", line 18, in <module>
from netaddr.core import (AddrConversionError, AddrFormatError,
File "/sonic/src/sonic-config-engine/.eggs/netaddr-0.8.0-py2.7.egg/netaddr/core.py", line 11, in <module>
from netaddr.compat import _callable, _iter_dict_keys
File "/sonic/src/sonic-config-engine/.eggs/netaddr-0.8.0-py2.7.egg/netaddr/compat.py", line 93, in <module>
import importlib_resources as _importlib_resources
File "/sonic/src/sonic-config-engine/.eggs/importlib_resources-3.3.1-py2.7.egg/importlib_resources/__init__.py", line 5, in <module>
from ._common import (
File "/sonic/src/sonic-config-engine/.eggs/importlib_resources-3.3.1-py2.7.egg/importlib_resources/_common.py", line 9, in <module>
from ._compat import (
File "/sonic/src/sonic-config-engine/.eggs/importlib_resources-3.3.1-py2.7.egg/importlib_resources/_compat.py", line 15, in <module>
from contextlib2 import suppress # type: ignore
File "/sonic/src/sonic-config-engine/.eggs/contextlib2-21.6.0-py2.7.egg/contextlib2/__init__.py", line 56
async def __aenter__(self):
^
SyntaxError: invalid syntax
ERROR
```
- [Wheel vs Egg](https://packaging.python.org/discussions/wheel-vs-egg/)
- `async` keyword is after 3.7 python,
- Our last build pass is #79 20210626
https://jenkins.clounix.com/job/sonic/job/vs/job/202012.clounix/job/sonic-buildimage/79/
However the contextlib2 has a big change.

src/sonic-config-engine/.eggs/contextlib2-21.6.0-py2.7.egg/contextlib2/__init__.py
Because the module __init__.py using the async keyword.
The .egg and sonic_config_engine.egg-info are create during the sonic build. the package version could setup in `src/sonic-config-engine/setup.py`
The fix version is here.
https://pypi.org/project/contextlib2/0.6.0.post1/
## make target/docker-base-buster.gz
```
08:45:49 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
08:45:49 [ building ] [ target/docker-base-buster.gz ]
08:45:49 Unable to find image 'debian:buster' locally
08:45:51 buster: Pulling from library/debian
08:45:52 0bc3020d05f1: Pulling fs layer
08:45:58 0bc3020d05f1: Verifying Checksum
08:45:58 0bc3020d05f1: Download complete
08:46:00 0bc3020d05f1: Pull complete
08:46:00 Digest: sha256:33a8231b1ec668c044b583971eea94fff37151de3a1d5a3737b08665300c8a0b
08:46:00 Status: Downloaded newer image for debian:buster
08:51:37 [ finished ] [ target/docker-base-buster.gz ]
08:51:37 [ FAIL LOG START ] [ target/docker-base-buster.gz ]
08:51:37 [ REASON ] : target/docker-base-buster.gz does not exist NON-EXISTENT PREREQUISITES: docker-start
```
Don't knwo why, just retest.