From 616e3a82a8d01f248f96b68db7a75406a617beed Mon Sep 17 00:00:00 2001 From: Jackie Huang Date: Fri, 6 Dec 2024 16:32:25 +0800 Subject: [PATCH] patches-arm: add patches based on stx.9.0 for cgcs-root Add patches based on stx.9.0 for cgcs-root repo: https://opendev.org/starlingx/root.git Issue-ID: INF-481 Signed-off-by: Jackie Huang Change-Id: I3f48a1de8ff3582255dc287426470155308e9ffc --- ...debrepack-add-arm64-support-for-meta-data.patch | 305 +++++++++++++++ .../0002-downloader-add-support-for-arm64.patch | 165 ++++++++ .../0003-build-tools-add-supoort-for-arm64.patch | 430 +++++++++++++++++++++ .../0004-Add-debian-image_arm64.inc.patch | 365 +++++++++++++++++ 4 files changed, 1265 insertions(+) create mode 100644 scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0001-debrepack-add-arm64-support-for-meta-data.patch create mode 100644 scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0002-downloader-add-support-for-arm64.patch create mode 100644 scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0003-build-tools-add-supoort-for-arm64.patch create mode 100644 scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0004-Add-debian-image_arm64.inc.patch diff --git a/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0001-debrepack-add-arm64-support-for-meta-data.patch b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0001-debrepack-add-arm64-support-for-meta-data.patch new file mode 100644 index 00000000..3526ba12 --- /dev/null +++ b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0001-debrepack-add-arm64-support-for-meta-data.patch @@ -0,0 +1,305 @@ +From 7518b647ea0085c231a903c7a3e4351b2b2966c4 Mon Sep 17 00:00:00 2001 +From: Jackie Huang +Date: Wed, 26 Jul 2023 17:23:55 +0800 +Subject: [PATCH 1/4] debrepack: add arm64 support for meta data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add set_build_arch (similar to set_build_type) so +@BUILD_ARCH@ can be used as placeholder in meta data +files to avoid hardcoded arch names. + +The items in dl_path/dl_files in meta_data.yaml may +have different values and the patches in the patches +or deb_patches directory may be different for arm64 +arch, this change will allow multiple dl_path/dl_files +items exist in meta_data.yaml, and multiple series files +in patches or deb_patches directories exist, and the +arch specific ones will be used as first priority if +it exists. + +The arch specific ones will have sufix like _arm64, +e.g. in meta_data.yaml + +dl_files: + pkg-file-amd64.tar.gz: + topdir: pkg-amd64 + url: https://path/to/pkg-file-amd64.tar.gz + sha256sum: +dl_files_arm64: + pkg-file-arm64.tar.gz: + topdir: pkg-arm64 + url: https://path/to/pkg-file-arm64.tar.gz + sha256sum: + +dl_path: + name: pkg-name-amd64.tar.gz + url: https://path/to/pkg-name-amd64.tar.gz + sha256sum: +dl_path_arm64: + name: pkg-name-arm64.tar.gz + url: https://path/to/pkg-name-arm64.tar.gz + sha256sum: + +e.g. for patches/deb_patches + +deb_patches +├── 0001-deb-patch1.patch +├── 0002-deb-patch2.patch +├── 0003-arm64-deb-patch1.patch +├── series +└── series_arm64 + +patches +├── 0001-patch1.patch +├── 0002-patch2.patch +├── 0002-arm64-patch1.patch +├── series +└── series_arm64 + +Test Plan: +PASS: update meta data for packages in repos: + - starlingx/integ + - starlingx/kernel +PASS: downloader -s on x86-64 host +PASS: downloader -s on arm64 host +PASS: build-pkgs -p on x86-64 host +PASS: build-pkgs -p on arm64 host +PASS: build-pkgs on x86-64 host +PASS: build-image on x86-64 host +PASS: build-pkgs on arm64 host +PASS: build-image on arm64 host +PASS: Deploy AIO-SX on x86-64 target +PASS: Deploy AIO-SX on arm64 target + +Story: 2010739 +Task: 48013 + +Change-Id: I42063364c416e40794d85af41e7a22366a84faa1 +Signed-off-by: Jackie Huang +--- + build-tools/stx/debrepack.py | 114 ++++++++++++++++++++++++++++------- + 1 file changed, 93 insertions(+), 21 deletions(-) + +diff --git a/build-tools/stx/debrepack.py b/build-tools/stx/debrepack.py +index 524b38d..85f593b 100755 +--- a/build-tools/stx/debrepack.py ++++ b/build-tools/stx/debrepack.py +@@ -28,6 +28,7 @@ import sys + import utils + from utils import run_shell_cmd, get_download_url + import yaml ++import platform + + + RELEASENOTES = " ".join([os.environ.get('PROJECT'), os.environ.get('MY_RELEASE'), "distribution"]) +@@ -58,7 +59,21 @@ if STX_MIRROR_STRATEGY is None: + STX_MIRROR_STRATEGY = "stx_mirror_first" + + BTYPE = "@KERNEL_TYPE@" ++BARCH = "@BUILD_ARCH@" + ++STX_ARCH = "amd64" ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" ++ ++DL_FILES_DEFAULT = "dl_files" ++DL_FILES_ARCH = DL_FILES_DEFAULT + "_" + STX_ARCH ++ ++DL_PATH_DEFAULT = "dl_path" ++DL_PATH_ARCH = DL_PATH_DEFAULT + "_" + STX_ARCH ++ ++SERIES_DEFAULT = "series" ++SERIES_ARCH = SERIES_DEFAULT + "_" + STX_ARCH + + class DownloadProgress(): + def __init__(self): +@@ -296,6 +311,16 @@ class Parser(): + + self.pkginfo["debfolder"] = os.path.join(local_debian) + ++ def set_build_arch(self): ++ ++ local_debian = os.path.join(self.pkginfo["packdir"], "local_debian") ++ ++ # clean @BUILD_ARCH@ ++ sed_cmd = 'sed -i s#%s#%s#g %s' ++ for root, _, files in os.walk(local_debian): ++ for name in files: ++ run_shell_cmd(sed_cmd % (BARCH, STX_ARCH, os.path.join(root, name)), self.logger) ++ + def get_gitrevcount_srcdir(self, gitrevcount_obj): + src_dir = str(gitrevcount_obj.get("SRC_DIR", "")) + if src_dir: +@@ -463,8 +488,14 @@ class Parser(): + self.logger.info("Overwrite the debian folder by %s", metadata) + run_shell_cmd('cp -r %s/* %s' % (metadata, deb_folder), self.logger) + +- series = os.path.join(metadata, "patches/series") +- if not os.path.isfile(series): ++ series_default = os.path.join(metadata, "patches", SERIES_DEFAULT) ++ series_arch = os.path.join(metadata, "patches", SERIES_ARCH) ++ ++ if os.path.isfile(series_arch): ++ series = series_arch ++ elif os.path.isfile(series_default): ++ series = series_default ++ else: + return True + + format_ver, format_type = self.set_deb_format() +@@ -497,11 +528,16 @@ class Parser(): + run_shell_cmd('cp -rL %s %s' % (src_file, self.pkginfo["srcdir"]), + self.logger) + +- if "dl_files" in self.meta_data: ++ dl_files = DL_FILES_DEFAULT ++ # Arch specific dl_files have higher priority ++ if DL_FILES_ARCH in self.meta_data: ++ dl_files = DL_FILES_ARCH ++ ++ if dl_files in self.meta_data: + pwd = os.getcwd() + os.chdir(self.pkginfo["packdir"]) +- for dl_file in self.meta_data['dl_files']: +- dir_name = self.meta_data['dl_files'][dl_file]['topdir'] ++ for dl_file in self.meta_data[dl_files]: ++ dir_name = self.meta_data[dl_files][dl_file]['topdir'] + dl_path = os.path.join(self.pkginfo["packdir"], dl_file) + if not os.path.exists(dl_path): + self.logger.error("No such file %s in local mirror", dl_file) +@@ -537,8 +573,15 @@ class Parser(): + def apply_src_patches(self): + + format_ver, format_type = self.set_deb_format() +- series = os.path.join(self.pkginfo["debfolder"], "patches/series") +- if not os.path.isfile(series): ++ ++ series_default = os.path.join(self.pkginfo["debfolder"], "patches", SERIES_DEFAULT) ++ series_arch = os.path.join(self.pkginfo["debfolder"], "patches", SERIES_ARCH) ++ ++ if os.path.isfile(series_arch): ++ series = series_arch ++ elif os.path.isfile(series_default): ++ series = series_default ++ else: + return True + + f = open(series) +@@ -547,7 +590,13 @@ class Parser(): + f.close() + + patches_folder = os.path.join(self.pkginfo["srcdir"], "debian/patches") +- series_file = os.path.join(self.pkginfo["srcdir"], "debian/patches/series") ++ series_file_default = os.path.join(patches_folder, SERIES_DEFAULT) ++ series_file_arch = os.path.join(patches_folder, SERIES_ARCH) ++ ++ series_file = series_file_default ++ if os.path.isfile(series_file_arch): ++ series_file = series_file_arch ++ + if not os.path.isdir(patches_folder): + os.mkdir(patches_folder) + os.mknod(series_file) +@@ -587,9 +636,16 @@ class Parser(): + + def apply_deb_patches(self): + +- series = os.path.join(self.pkginfo["debfolder"], "deb_patches/series") +- if not os.path.isfile(series): ++ series_default = os.path.join(self.pkginfo["debfolder"], "deb_patches", SERIES_DEFAULT) ++ series_arch = os.path.join(self.pkginfo["debfolder"], "deb_patches", SERIES_ARCH) ++ ++ if os.path.isfile(series_arch): ++ series = series_arch ++ elif os.path.isfile(series_default): ++ series = series_default ++ else: + return True ++ + f = open(series) + patches = f.readlines() + patches_src = os.path.dirname(series) +@@ -609,8 +665,12 @@ class Parser(): + return True + + def extract_tarball(self): ++ # Arch specific dl_path have higher priority ++ dl_path = DL_PATH_DEFAULT ++ if DL_PATH_ARCH in self.meta_data: ++ dl_path = DL_PATH_ARCH + +- tarball_name = self.meta_data["dl_path"]["name"] ++ tarball_name = self.meta_data[dl_path]["name"] + tarball_file = os.path.join(self.pkginfo["packdir"], tarball_name) + + cmd, _, _ = tar_cmd(tarball_name, self.logger) +@@ -715,9 +775,15 @@ class Parser(): + + pwd = os.getcwd() + os.chdir(saveto) +- if "dl_files" in self.meta_data: +- for dl_file in self.meta_data['dl_files']: +- dl_file_info = self.meta_data['dl_files'][dl_file] ++ ++ dl_files = DL_FILES_DEFAULT ++ # Arch specific dl_files have higher priority ++ if DL_FILES_ARCH in self.meta_data: ++ dl_files = DL_FILES_ARCH ++ ++ if dl_files in self.meta_data: ++ for dl_file in self.meta_data[dl_files]: ++ dl_file_info = self.meta_data[dl_files][dl_file] + url = dl_file_info['url'] + if "sha256sum" in dl_file_info: + check_cmd = "sha256sum" +@@ -739,16 +805,21 @@ class Parser(): + if not checksum(dl_file, check_sum, check_cmd, self.logger): + raise Exception(f'Fail to download {dl_file}') + +- if "dl_path" in self.meta_data: +- dl_file = self.meta_data["dl_path"]["name"] +- url = self.meta_data["dl_path"]["url"] +- if "sha256sum" in self.meta_data["dl_path"]: ++ dl_path = DL_PATH_DEFAULT ++ # Arch specific dl_path have higher priority ++ if DL_PATH_ARCH in self.meta_data: ++ dl_path = DL_PATH_ARCH ++ ++ if dl_path in self.meta_data: ++ dl_file = self.meta_data[dl_path]["name"] ++ url = self.meta_data[dl_path]["url"] ++ if "sha256sum" in self.meta_data[dl_path]: + check_cmd = "sha256sum" +- check_sum = self.meta_data["dl_path"]['sha256sum'] ++ check_sum = self.meta_data[dl_path]['sha256sum'] + else: + self.logger.warning(f"{dl_file} missing sha256sum") + check_cmd = "md5sum" +- check_sum = self.meta_data["dl_path"]['md5sum'] ++ check_sum = self.meta_data[dl_path]['md5sum'] + if not checksum(dl_file, check_sum, check_cmd, self.logger): + (dl_url, alt_dl_url) = get_download_url(url, self.strategy) + if alt_dl_url: +@@ -813,6 +884,7 @@ class Parser(): + os.mkdir(self.pkginfo["packdir"]) + + self.set_build_type() ++ self.set_build_arch() + + logfile = os.path.join(self.pkginfo["packdir"], self.pkginfo["pkgname"] + ".log") + if os.path.exists(logfile): +@@ -832,7 +904,7 @@ class Parser(): + + if "dl_hook" in self.meta_data: + self.run_dl_hook() +- elif "dl_path" in self.meta_data: ++ elif (DL_PATH_DEFAULT or DL_PATH_ARCH) in self.meta_data: + self.extract_tarball() + elif "src_path" in self.meta_data: + self.create_src_package() +-- +2.30.2 + diff --git a/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0002-downloader-add-support-for-arm64.patch b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0002-downloader-add-support-for-arm64.patch new file mode 100644 index 00000000..2b63afb2 --- /dev/null +++ b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0002-downloader-add-support-for-arm64.patch @@ -0,0 +1,165 @@ +From c3a2332443a87b1a5c9477838cae5314413eebe6 Mon Sep 17 00:00:00 2001 +From: Jackie Huang +Date: Wed, 26 Jul 2023 13:06:48 +0800 +Subject: [PATCH 2/4] downloader: add support for arm64 + +* Check the host arch. +* Dwnload arch specific binaries for arm64. +* Support arch specific pkg list files, and the + arch specific one (with suffix _arm64) will be used + if it exists. +e.g. +debian_pkg_dirs +debian_pkg_dirs_arm64 +debian_pkg_dirs_rt +debian_pkg_dirs_rt_arm64 +debian_pkg_dirs_installer +debian_pkg_dirs_installer_arm64 + +base-bullseye.lst +base-bullseye_arm64.lst + +os-std.lst +os-std_arm64.lst + +Test Plan: +PASS: update packages list for arm64 in repos: + - starlingx/tools + - starlingx/kernel + - starlingx/integ + - starlingx/virt + - starlingx/utilities +PASS: downloader -s -b on x86-64 host +PASS: downloader -s -b on arm64 host +PASS: build-pkgs on x86-64 host +PASS: build-image on x86-64 host +PASS: build-pkgs on arm64 host +PASS: build-image on arm64 host +PASS: Deploy AIO-SX on x86-64 target +PASS: Deploy AIO-SX on arm64 target + +Story: 2010739 +Task: 48013 + +Change-Id: I5fadf737ee75fc631d57d6bf689d54638548bffe +Signed-off-by: Jackie Huang +--- + build-tools/stx/debdownloader | 5 +++++ + build-tools/stx/downloader | 37 +++++++++++++++++++++++++++-------- + 2 files changed, 34 insertions(+), 8 deletions(-) + +diff --git a/build-tools/stx/debdownloader b/build-tools/stx/debdownloader +index 6988cc7..a1ca92e 100755 +--- a/build-tools/stx/debdownloader ++++ b/build-tools/stx/debdownloader +@@ -109,6 +109,7 @@ if __name__ == "__main__": + # strip epoch + major_ver = version.split(":")[-1] + pname_x86 = ''.join([name, '_', major_ver, '_amd64.deb']) ++ pname_arm64 = ''.join([name, '_', major_ver, '_arm64.deb']) + pname_all = ''.join([name, '_', major_ver, '_all.deb']) + if repomgr.search_pkg(REPO_BIN, name, version): + logger.info(''.join([name, '-', version, +@@ -118,6 +119,10 @@ if __name__ == "__main__": + logger.info(''.join([name, '-', version, + ' already downloaded, skip download'])) + debs_need_upload.append(pname_x86) ++ elif debs_downloaded and pname_arm64 in debs_downloaded: ++ logger.info(''.join([name, '-', version, ++ ' already downloaded, skip download'])) ++ debs_need_upload.append(pname_arm64) + else: + if debs_downloaded and pname_all in debs_downloaded: + logger.info(''.join([name, '-', version, +diff --git a/build-tools/stx/downloader b/build-tools/stx/downloader +index 14d97f7..2d98707 100755 +--- a/build-tools/stx/downloader ++++ b/build-tools/stx/downloader +@@ -27,8 +27,14 @@ import shutil + import signal + import sys + import utils ++import platform + +-DEFAULT_ARCH = 'amd64' ++STX_ARCH = 'amd64' ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" ++ ++DEB_DISTRO = 'bullseye' + REPO_BIN = 'deb-local-binary' + mirror_root = os.environ.get('STX_MIRROR') + stx_src_mirror = os.path.join(mirror_root, 'sources') +@@ -115,7 +121,11 @@ def get_all_stx_pkgs(): + for r in files: + # Find all types of package dirs? + if r in types_pkg_dirs: +- pkgs_file = os.path.join(root, r) ++ r_arch = r + "_" + STX_ARCH ++ if os.path.isfile(r_arch): ++ pkgs_file = os.path.join(root, r_arch) ++ else: ++ pkgs_file = os.path.join(root, r) + pkgs.update(get_pkgs_from_list(root, pkgs_file)) + return pkgs + +@@ -153,24 +163,34 @@ def get_all_binary_list(distro=STX_DEFAULT_DISTRO, layers=None, build_types=None + logger.warning(' '.join([build_type, 'is not a valid build_type for distro', distro, 'of layer', layer])) + continue + +- pattern=''.join(['os-',build_type,'.lst']) ++ pattern = ''.join(['os-', build_type, '.lst']) ++ pattern_arch = ''.join(['os-', build_type, '_', STX_ARCH, '.lst']) + for root, dirs, files in os.walk(search_dir): + for f in fnmatch.filter(files, pattern): +- layer_binaries[layer].append(os.path.join(root, f)) ++ f_arch = os.path.join(root, pattern_arch) ++ if os.path.isfile(f_arch): ++ layer_binaries[layer].append(os.path.join(root, f_arch)) ++ else: ++ layer_binaries[layer].append(os.path.join(root, f)) + logger.info( + f"Binary lists for layer `{layer}`: " + f"{layer_binaries[layer]}" + ) + + search_dir = os.path.join(stx_config, 'common') +- pattern='base-*.lst' ++ pattern = ''.join(['base-', DEB_DISTRO, '.lst']) ++ pattern_arch = ''.join(['base-', DEB_DISTRO, '_', STX_ARCH, '.lst']) + + if "common" not in layer_binaries: + layer_binaries["common"] = [] + + for root, dirs, files in os.walk(search_dir): + for f in fnmatch.filter(files, pattern): +- layer_binaries["common"].append(os.path.join(root, f)) ++ f_arch = os.path.join(root, pattern_arch) ++ if os.path.isfile(f_arch): ++ layer_binaries["common"].append(os.path.join(root, f_arch)) ++ else: ++ layer_binaries["common"].append(os.path.join(root, f)) + + logger.info( + f"Binary lists for layer `common`: " +@@ -727,13 +747,14 @@ if __name__ == "__main__": + args.download_source = True + + if args.download_binary: ++ + all_binary_lists = get_all_binary_list(distro=distro, layers=layers, build_types=build_types) +- binary_dl = DebDownloader(DEFAULT_ARCH, stx_bin_mirror, clean_mirror, all_binary_lists) ++ binary_dl = DebDownloader(STX_ARCH, stx_bin_mirror, clean_mirror, all_binary_lists) + if not binary_dl.create_binary_repo(): + sys.exit(1) + + if args.download_source: +- source_dl = SrcDownloader(DEFAULT_ARCH, stx_src_mirror, clean_mirror) ++ source_dl = SrcDownloader(STX_ARCH, stx_src_mirror, clean_mirror) + + dl_register_signal_handler() + if binary_dl: +-- +2.30.2 + diff --git a/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0003-build-tools-add-supoort-for-arm64.patch b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0003-build-tools-add-supoort-for-arm64.patch new file mode 100644 index 00000000..3a417f76 --- /dev/null +++ b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0003-build-tools-add-supoort-for-arm64.patch @@ -0,0 +1,430 @@ +From 516085675edd2a3330b4ddba10c4b613ee91955b Mon Sep 17 00:00:00 2001 +From: Jackie Huang +Date: Wed, 26 Jul 2023 14:55:29 +0800 +Subject: [PATCH 3/4] build-tools: add supoort for arm64 + +* Check the host arch. +* use ARCH to replace the hardcoded arch names. +* Support arch specific pkg list files and yaml files, + and the arch specific one (with suffix _arm64) will + be used if it exists. + +e.g. +debian-image.inc +debian-image_arm64.inc + +debian_iso_image.inc +debian_iso_image_arm64.inc + +debian_pkg_dirs +debian_pkg_dirs_arm64 + +base-bullseye.yaml +base-bullseye_arm64.yaml + +base-initramfs-bullseye.yaml +base-initramfs-bullseye_arm64.yaml + +os-std.lst +os-std_arm64.lst + +Test Plan: +PASS: update packages list for arm64 in repos: + - starlingx/tools + - starlingx/kernel + - starlingx/integ + - starlingx/virt + - starlingx/utilities +PASS: downloader -s -b on x86-64 host +PASS: downloader -s -b on arm64 host +PASS: build-pkgs on x86-64 host +PASS: build-image on x86-64 host +PASS: build-pkgs on arm64 host +PASS: build-image on arm64 host +PASS: Deploy AIO-SX on x86-64 target +PASS: Deploy AIO-SX on arm64 target + +Story: 2010739 +Task: 48013 + +Change-Id: I9e381f3f04f6747c68d40011c9eda419219c2311 +Signed-off-by: Jackie Huang +--- + build-tools/stx/aptly_deb_usage.py | 12 ++++-- + build-tools/stx/build-image | 65 ++++++++++++++++++++++++------ + build-tools/stx/build-pkgs | 8 +++- + build-tools/stx/discovery.py | 42 ++++++++++++++++--- + build-tools/stx/downloader | 2 +- + build-tools/stx/repo_manage.py | 9 ++++- + 6 files changed, 111 insertions(+), 27 deletions(-) + +diff --git a/build-tools/stx/aptly_deb_usage.py b/build-tools/stx/aptly_deb_usage.py +index f1d91c2..d10e6a2 100755 +--- a/build-tools/stx/aptly_deb_usage.py ++++ b/build-tools/stx/aptly_deb_usage.py +@@ -25,6 +25,7 @@ from debian import debian_support + import os + import time + from typing import Optional ++import platform + + PREFIX_LOCAL = 'deb-local-' + PREFIX_REMOTE = 'deb-remote-' +@@ -34,6 +35,11 @@ SIGN_PASSWD = 'starlingx' + DEFAULT_TIMEOUT_COUNT = 1 + STX_DIST = os.environ.get('STX_DIST') + ++STX_ARCH = 'amd64' ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" ++ + # Class used to manage aptly data base, it can: + # create_remote: Create a repository link to a remote mirror + # deploy_remote: Sync and deploy a remote mirror +@@ -326,7 +332,7 @@ class Deb_aptly(): + self.logger.warning('Drop failed publication %s : %s', publish_name, task_state) + return None + task = self.aptly.publish.publish(source_kind='local', sources=[{'Name': repo_name}], +- architectures=['amd64', 'source'], prefix=publish_name, ++ architectures=[STX_ARCH, 'source'], prefix=publish_name, + distribution=None, sign_skip=True) + task_state = self.__wait_for_task(task, 10) + if task_state != 'SUCCEEDED': +@@ -366,8 +372,8 @@ class Deb_aptly(): + extra_param['distribution'] = mirror.distribution + extra_param['origin'] = None + else: +- # Only support binary_amd64 and source packages +- extra_param['architectures'] = ['amd64', 'source'] ++ # Only support binary_amd64/arm64 and source packages ++ extra_param['architectures'] = [STX_ARCH, 'source'] + extra_param['distribution'] = None + extra_param['origin'] = self.origin + +diff --git a/build-tools/stx/build-image b/build-tools/stx/build-image +index 8536c32..ea04fa2 100755 +--- a/build-tools/stx/build-image ++++ b/build-tools/stx/build-image +@@ -28,11 +28,17 @@ import sys + import time + import utils + import yaml ++import platform + + STX_DEFAULT_DISTRO = discovery.STX_DEFAULT_DISTRO + ALL_LAYERS = discovery.get_all_layers(distro=STX_DEFAULT_DISTRO) + ALL_BUILD_TYPES = discovery.get_all_build_types(distro=STX_DEFAULT_DISTRO) + ++STX_ARCH = 'amd64' ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" ++ + LAT_ROOT = '/localdisk' + REPO_ALL = 'deb-merge-all' + REPO_BINARY = 'deb-local-binary' +@@ -48,8 +54,8 @@ IMAGE_LAYERS_PATH = os.path.join( + ) + img_pkgs = [] + kernel_type = 'std' +-stx_std_kernel = 'linux-image-5.10.0-6-amd64-unsigned' +-stx_rt_kernel = 'linux-rt-image-5.10.0-6-rt-amd64-unsigned' ++stx_std_kernel = 'linux-image-5.10.0-6-%s-unsigned' % STX_ARCH ++stx_rt_kernel = 'linux-rt-image-5.10.0-6-rt-%s-unsigned' % STX_ARCH + WAIT_TIME_BEFORE_CHECKING_LOG = 2 + # The max timeout value to wait LAT to output the build log + MAX_WAIT_LAT_TIME = 300 +@@ -242,7 +248,7 @@ def update_rt_kernel_in_initramfs_yaml(initramfs_yaml): + + # Updated the name of kernel module + for layer in ALL_LAYERS: +- pkg_dirs = discovery.package_dir_list(distro=STX_DEFAULT_DISTRO, layer=layer, build_type='rt') ++ pkg_dirs = discovery.package_dir_list(distro=STX_DEFAULT_DISTRO, layer=layer, build_type='rt', arch=STX_ARCH) + if not pkg_dirs: + continue + for pkg_dir in pkg_dirs: +@@ -305,7 +311,7 @@ def add_lat_packages(img_yaml, packages): + yaml_doc['packages'].extend(packages) + + for build_type in ALL_BUILD_TYPES: +- pkgs = discovery.package_iso_list(distro=STX_DEFAULT_DISTRO, layer="all", build_type=build_type) ++ pkgs = discovery.package_iso_list(distro=STX_DEFAULT_DISTRO, layer="all", build_type=build_type, arch=STX_ARCH) + yaml_doc['packages'].extend(pkgs) + + yaml_doc['packages'] = list(set(yaml_doc['packages'])) +@@ -319,8 +325,16 @@ def add_lat_packages(img_yaml, packages): + + + def check_base_os_binaries(repomgr): +- base_bins_list = os.path.join(os.environ.get('MY_REPO_ROOT_DIR'), ++ base_bins_list_default = os.path.join(os.environ.get('MY_REPO_ROOT_DIR'), + 'cgcs-root/build-tools/stx/debian-image.inc') ++ base_bins_list_arch = os.path.join(os.environ.get('MY_REPO_ROOT_DIR'), ++ 'cgcs-root/build-tools/stx', ++ 'debian-image_%s.inc' % STX_ARCH) ++ if os.path.exists(base_bins_list_arch): ++ base_bins_list = base_bins_list_arch ++ else: ++ base_bins_list = base_bins_list_default ++ + if not os.path.exists(base_bins_list): + logger.error(' '.join(['Base OS packages list', base_bins_list, + 'does not exist'])) +@@ -338,8 +352,15 @@ def check_base_os_binaries(repomgr): + + + def check_stx_binaries(repomgr, btype='std'): +- stx_bins_list = ''.join([PKG_LIST_DIR, '/debian/distro/os-', btype, +- '.lst']) ++ stx_bins_list_default = ''.join([PKG_LIST_DIR, '/debian/distro/os-', ++ btype, '.lst']) ++ stx_bins_list_arch = ''.join([PKG_LIST_DIR, '/debian/distro/os-', ++ btype, '_', STX_ARCH, '.lst']) ++ if os.path.exists(stx_bins_list_arch): ++ stx_bins_list = stx_bins_list_arch ++ else: ++ stx_bins_list = stx_bins_list_default ++ + if not os.path.exists(stx_bins_list): + logger.warning(' '.join(['STX binary packages list', stx_bins_list, + 'does not exist'])) +@@ -660,16 +681,30 @@ if __name__ == "__main__": + logger.error("Fail to get prepared to build image") + sys.exit(1) + +- base_yaml = os.path.join(PKG_LIST_DIR, 'debian/common/base-bullseye.yaml') +- base_initramfs_yaml = os.path.join(PKG_LIST_DIR, 'debian/common/base-initramfs-bullseye.yaml') ++ base_yaml_default = os.path.join(PKG_LIST_DIR, 'debian/common/base-bullseye.yaml') ++ base_yaml_arch = os.path.join(PKG_LIST_DIR, 'debian/common/base-bullseye_%s.yaml' % STX_ARCH) ++ base_initramfs_yaml_default = os.path.join(PKG_LIST_DIR, 'debian/common/base-initramfs-bullseye.yaml') ++ base_initramfs_yaml_arch = os.path.join(PKG_LIST_DIR, 'debian/common/base-initramfs-bullseye_%s.yaml' % STX_ARCH) ++ + os.environ["WORKSPACE_DIR"] = LAT_ROOT + lat_yaml = os.path.join(LAT_ROOT, "lat.yaml") + lat_initramfs_yaml = os.path.join(LAT_ROOT, "lat-initramfs.yaml") + +- for yaml_file in (base_yaml, base_initramfs_yaml): +- if not os.path.exists(yaml_file): +- logger.error(' '.join(['Base yaml file', yaml_file, 'does not exist'])) +- sys.exit(1) ++ if os.path.exists(base_yaml_arch): ++ base_yaml = base_yaml_arch ++ elif os.path.exists(base_yaml_default): ++ base_yaml = base_yaml_default ++ else: ++ logger.error(' '.join(['Base yaml file', base_yaml_default, 'does not exist'])) ++ sys.exit(1) ++ ++ if os.path.exists(base_initramfs_yaml_arch): ++ base_initramfs_yaml = base_initramfs_yaml_arch ++ elif os.path.exists(base_initramfs_yaml_default): ++ base_initramfs_yaml = base_initramfs_yaml_default ++ else: ++ logger.error(' '.join(['Base yaml file', base_initramfs_yaml_default, 'does not exist'])) ++ sys.exit(1) + + if not os.path.exists(LAT_ROOT): + os.makedirs(LAT_ROOT) +@@ -758,6 +793,10 @@ if __name__ == "__main__": + logger.info("build-image successfully done, check the output in %s", LAT_ROOT) + ret = 0 + break ++ if STX_ARCH == "arm64" and "INFO: Create ISO Image: Succeeded" in line: ++ logger.info("build-image successfully done, check the output in %s", LAT_ROOT) ++ ret = 0 ++ break + # stop latd + stop_latd() + +diff --git a/build-tools/stx/build-pkgs b/build-tools/stx/build-pkgs +index a8feaa9..9dacef3 100755 +--- a/build-tools/stx/build-pkgs ++++ b/build-tools/stx/build-pkgs +@@ -37,7 +37,7 @@ import tempfile + import time + import utils + import yaml +- ++import platform + + BUILDER_URL = os.environ.get('BUILDER_URL') + REPOMGR_URL = os.environ.get('REPOMGR_URL') +@@ -49,6 +49,10 @@ USER = os.environ.get('MYUNAME') + PROJECT = os.environ.get('PROJECT') + DISTRIBUTION = os.environ.get('DEBIAN_DISTRIBUTION') + STX_ARCH = 'amd64' ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" ++ + STX_META_NAME = 'stx-meta' + STX_META_PKG = 'stx-meta_1.0.orig.tar.gz' + # Different reasons can lead to package build failure +@@ -1658,7 +1662,7 @@ class BuildController(): + logger.error('Failed to specify build_type') + return + +- pkg_dirs = discovery.package_dir_list(distro=self.attrs['distro'], layer=layer, build_type=build_type) ++ pkg_dirs = discovery.package_dir_list(distro=self.attrs['distro'], layer=layer, build_type=build_type, arch=STX_ARCH) + layer_pkg_dirs = pkg_dirs + word = "all" + if packages: +diff --git a/build-tools/stx/discovery.py b/build-tools/stx/discovery.py +index 3de7d48..d16e520 100644 +--- a/build-tools/stx/discovery.py ++++ b/build-tools/stx/discovery.py +@@ -17,6 +17,7 @@ import os + import re + import glob + import yaml ++import platform + + from git_utils import git_list + from repo_utils import repo_root +@@ -30,6 +31,11 @@ STX_DEFAULT_DISTRO_LIST = [ "debian", "centos" ] + STX_DEFAULT_BUILD_TYPE = "std" + STX_DEFAULT_BUILD_TYPE_LIST = [STX_DEFAULT_BUILD_TYPE] + ++STX_ARCH = "amd64" ++STX_SUPPORTED_ARCH = ["amd64", "arm64"] ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" + + def get_all_distros(): + distro_lst = STX_DEFAULT_DISTRO_LIST +@@ -126,6 +132,14 @@ def get_layer_build_types (layer, distro="debian", skip_non_buildable=True): + for proj_dir in project_dir_list_all: + for pkg_dir_file in glob.glob("%s/%s%s" % (proj_dir, distro, "_pkg_dirs_*")): + bt = os.path.basename(pkg_dir_file).split("_pkg_dirs_")[1] ++ # cleanup arch specific suffix ++ if bt in STX_SUPPORTED_ARCH: ++ continue ++ else: ++ for arch in STX_SUPPORTED_ARCH: ++ arch_suffix = "_" + arch ++ if bt.endswith(arch_suffix): ++ bt = bt.replace(arch_suffix, "") + if not bt in bt_lst: + bt_lst.append(bt) + return sort_build_type_list(bt_lst, layer) +@@ -137,6 +151,14 @@ def get_all_build_types (distro="debian", skip_non_buildable=True): + for proj_dir in project_dir_list_all: + for pkg_dir_file in glob.glob("%s/%s%s" % (proj_dir, distro, "_pkg_dirs_*")): + bt = os.path.basename(pkg_dir_file).split("_pkg_dirs_")[1] ++ # cleanup arch specific suffix ++ if bt in STX_SUPPORTED_ARCH: ++ continue ++ else: ++ for arch in STX_SUPPORTED_ARCH: ++ arch_suffix = "_" + arch ++ if bt.endswith(arch_suffix): ++ bt = bt.replace(arch_suffix, "") + if not bt in bt_lst: + bt_lst.append(bt) + return sorted(bt_lst) +@@ -186,32 +208,40 @@ def package_dir_list_handler(entry, proj_dir): + return [ path ] + + +-def package_iso_list (distro="debian", layer="all", build_type="std", skip_non_buildable=True): ++def package_iso_list (distro="debian", layer="all", build_type="std", arch=STX_ARCH, skip_non_buildable=True): + pkg_iso_list = [] + if layer is None: + layer = "all" + for proj_dir in project_dir_list(distro=distro, layer=layer, skip_non_buildable=skip_non_buildable): +- iso_file = os.path.join(proj_dir, "%s%s%s%s" % (distro, "_iso_image_", build_type, ".inc")) ++ iso_file = os.path.join(proj_dir, "%s_%s_%s_%s%s" % (distro, "iso_image", build_type, arch, ".inc")) ++ if not os.path.isfile(iso_file): ++ iso_file = os.path.join(proj_dir, "%s_%s_%s%s" % (distro, "iso_image", build_type, ".inc")) + if not os.path.isfile(iso_file): + if build_type == "std": + # It's permitted to omit the "_std" suffix from the file name +- iso_file = os.path.join(proj_dir, "%s%s" % (distro, "_iso_image.inc")) ++ iso_file = os.path.join(proj_dir, "%s_%s_%s%s" % (distro, "iso_image", arch, ".inc")) ++ if not os.path.isfile(iso_file): ++ iso_file = os.path.join(proj_dir, "%s_%s" % (distro, "iso_image.inc")) + if not os.path.isfile(iso_file): + continue + pkg_iso_list.extend(bc_safe_fetch(iso_file)) + return pkg_iso_list + + +-def package_dir_list (distro="debian", layer="all", build_type="std", skip_non_buildable=True): ++def package_dir_list (distro="debian", layer="all", build_type="std", arch=STX_ARCH, skip_non_buildable=True): + pkg_dir_list = [] + if layer is None: + layer = "all" + for proj_dir in project_dir_list(distro=distro, layer=layer, skip_non_buildable=skip_non_buildable): +- pkg_file = os.path.join(proj_dir, "%s%s%s" % (distro, "_pkg_dirs_", build_type)) ++ pkg_file = os.path.join(proj_dir, "%s_%s_%s_%s" % (distro, "pkg_dirs", build_type, arch)) ++ if not os.path.isfile(pkg_file): ++ pkg_file = os.path.join(proj_dir, "%s_%s_%s" % (distro, "pkg_dirs", build_type)) + if not os.path.isfile(pkg_file): + if build_type == "std": + # It's permitted to omit the "_std" suffix from the file name +- pkg_file = os.path.join(proj_dir, "%s%s" % (distro, "_pkg_dirs")) ++ pkg_file = os.path.join(proj_dir, "%s_%s_%s" % (distro, "pkg_dirs", arch)) ++ if not os.path.isfile(pkg_file): ++ pkg_file = os.path.join(proj_dir, "%s_%s" % (distro, "pkg_dirs")) + if not os.path.isfile(pkg_file): + continue + pkg_dir_list.extend(bc_safe_fetch(pkg_file, package_dir_list_handler, proj_dir)) +diff --git a/build-tools/stx/downloader b/build-tools/stx/downloader +index 2d98707..47093ea 100755 +--- a/build-tools/stx/downloader ++++ b/build-tools/stx/downloader +@@ -635,7 +635,7 @@ class SrcDownloader(BaseDownloader): + logger.warning(' '.join([build_type, 'is not a valid build_type for distro', distro, 'of layer', layer])) + continue + +- pkg_dirs.extend(discovery.package_dir_list(distro=distro, layer=layer, build_type=build_type)) ++ pkg_dirs.extend(discovery.package_dir_list(distro=distro, layer=layer, build_type=build_type, arch=STX_ARCH)) + + if not len(pkg_dirs): + logger.info("No source packages found") +diff --git a/build-tools/stx/repo_manage.py b/build-tools/stx/repo_manage.py +index dbe0cc3..bf68b70 100755 +--- a/build-tools/stx/repo_manage.py ++++ b/build-tools/stx/repo_manage.py +@@ -31,6 +31,7 @@ import shutil + from threading import Lock + import urllib.request + import utils ++import platform + + REPOMGR_URL = os.environ.get('REPOMGR_URL') + REPOMGR_ORIGIN = os.environ.get('REPOMGR_ORIGIN') +@@ -38,6 +39,10 @@ REPOMGR_DEPLOY_URL = os.environ.get('REPOMGR_DEPLOY_URL') + + APTFETCH_JOBS = 20 + ++STX_ARCH = 'amd64' ++host_arch = platform.machine() ++if host_arch == 'aarch64': ++ STX_ARCH = "arm64" + + class AptFetch(): + ''' +@@ -497,7 +502,7 @@ class RepoMgr(): + # kwargs:url: URL of the upstream repo (http://deb.debian.org/debian) + # kwargs:distribution: the distribution of the repo (bullseye) + # kwargs:component: component of the repo (main) +- # kwargs:architecture: architecture of the repo, "all" is always enabled. (amd64) ++ # kwargs:architecture: architecture of the repo, "all" is always enabled. (amd64 or arm64) + # kwargs:with_sources: include source packages, default is False. + # Output: None + def mirror(self, repo_name, **kwargs): +@@ -923,7 +928,7 @@ def subcmd_mirror(subparsers): + mirror_parser.add_argument('--component', '-c', help='component name', required=False, + default='nginx') + mirror_parser.add_argument('--architectures', '-a', help='architectures', required=False, +- default='amd64') ++ default=STX_ARCH) + mirror_parser.add_argument('--with-sources', '-s', help='include source packages', + action='store_true') + mirror_parser.set_defaults(handle=_handleMirror) +-- +2.30.2 + diff --git a/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0004-Add-debian-image_arm64.inc.patch b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0004-Add-debian-image_arm64.inc.patch new file mode 100644 index 00000000..c73a93ad --- /dev/null +++ b/scripts/build_inf_debian/meta-patches-arm/stx90/cgcs-root/0004-Add-debian-image_arm64.inc.patch @@ -0,0 +1,365 @@ +From c0f2e1c04e0a3ceb7a9aff4651186dfb68dc3f16 Mon Sep 17 00:00:00 2001 +From: Jackie Huang +Date: Thu, 27 Jul 2023 23:46:36 +0800 +Subject: [PATCH 4/4] Add debian-image_arm64.inc + +syslinux-utils doesn't support arm64, so add +debian-image_arm64.inc and remove syslinux-utils +from the list. + +diff debian-image.inc debian-image_arm64.inc +298d297 +< syslinux-utils + +Test Plan: +PASS: downloader -s -b on x86-64 host +PASS: downloader -s -b on arm64 host +PASS: build-pkgs on x86-64 host +PASS: build-image on x86-64 host +PASS: build-pkgs on arm64 host +PASS: build-image on arm64 host +PASS: Deploy AIO-SX on x86-64 target +PASS: Deploy AIO-SX on arm64 target + +Story: 2010739 +Task: 48013 + +Depends-On: https://review.opendev.org/c/starlingx/root/+/889682 + +Change-Id: Id655994ee41bd7dfe20399b7acc4a44544d504cb +Signed-off-by: Jackie Huang +--- + build-tools/stx/debian-image_arm64.inc | 321 +++++++++++++++++++++++++ + 1 file changed, 321 insertions(+) + create mode 100644 build-tools/stx/debian-image_arm64.inc + +diff --git a/build-tools/stx/debian-image_arm64.inc b/build-tools/stx/debian-image_arm64.inc +new file mode 100644 +index 0000000..432fabb +--- /dev/null ++++ b/build-tools/stx/debian-image_arm64.inc +@@ -0,0 +1,321 @@ ++acl ++acpi-support-base ++ansible ++apache2 ++apparmor-utils ++apt-utils ++auditd ++bash-completion ++bc ++bind9-dnsutils ++bind9-host ++bsdextrautils ++bsdutils ++busybox ++cdebconf ++cloud-init ++cluster-glue ++collectd ++conntrack ++conntrackd ++cracklib-runtime ++cron ++cryptsetup-bin ++curl ++dash ++dbconfig-common ++dbus-user-session ++dconf-gsettings-backend ++debconf-i18n ++diffutils ++dnf ++docker.io ++dosfstools ++e2fsprogs ++efibootmgr ++eject ++elfutils ++erlang-base ++erlang-eldap ++erlang-inets ++erlang-os-mon ++erlang-parsetools ++erlang-syntax-tools ++erlang-tools ++erlang-xmerl ++expect ++fdisk ++findutils ++firmware-ath9k-htc ++firmware-atheros ++firmware-bnx2 ++firmware-bnx2x ++firmware-brcm80211 ++firmware-cavium ++firmware-intel-sound ++firmware-iwlwifi ++firmware-libertas ++firmware-linux ++firmware-myricom ++firmware-netronome ++firmware-netxen ++firmware-qcom-soc ++firmware-qlogic ++firmware-realtek ++firmware-samsung ++firmware-siano ++flake8 ++fonts-dejavu-core ++gcc-10 ++genisoimage ++gettext-base ++gnupg ++grep ++gunicorn ++gzip ++hdparm ++hostname ++ifenslave ++init ++initramfs-tools ++inotify-tools ++install-info ++iperf3 ++ipmitool ++iptables-persistent ++ipxe-qemu ++iscsiuio ++iotop ++isomd5sum ++kbd ++less ++libapache2-mod-wsgi-py3 ++libaprutil1-dbd-sqlite3 ++libavahi-glib1 ++libbabeltrace1 ++libblas3 ++libbluetooth3 ++libboost-context1.74.0 ++libboost-iostreams1.74.0 ++libboost-python1.74.0 ++libboost-regex1.74.0 ++libc6 ++libc6-dev ++libcacard0 ++libcapstone4 ++libcrypt1 ++libdebconfclient0 ++libdns-export1110 ++libeinfo1 ++libfam0 ++libfuse2 ++libgcc-s1 ++libgeoip1 ++libgfapi0 ++libgoogle-perftools4 ++libinotifytools0 ++libiscsi7 ++libjs-jquery-cookie ++liblapack3 ++libleveldb1d ++liblognorm5 ++libmm-glib0 ++libndctl6 ++libndp0 ++libnetcf1 ++libnet-ntp-perl ++libnfs13 ++libnm0 ++libnss-cache ++libnss-mdns ++libnss-sss ++liboath0 ++libodbc1 ++libopendbx1 ++libpam-sss ++libpciaccess0 ++librabbitmq4 ++librte-vhost21 ++libsanlock-client1 ++libsecret-1-0 ++libslirp0 ++libsoup2.4-1 ++libspice-server1 ++libssh-4 ++libsss-sudo ++libteam-utils ++libunbound8 ++liburing1 ++libusb-1.0-0 ++libusbredirparser1 ++libvdeplug2 ++libvirglrenderer1 ++libyajl2 ++linux-cpupower ++locales-all ++logrotate ++lsb-base ++lsof ++man-db ++mawk ++mdadm ++memcached ++mokutil ++multipath-tools ++multipath-tools-boot ++nano ++ncurses-base ++ncurses-bin ++ndisc6 ++netcat-openbsd ++nfs-kernel-server ++nftables ++ntp ++ntpdate ++nvme-cli ++open-iscsi ++openssh-server ++original-awk ++ovmf ++pciutils ++pinentry-curses ++pipexec ++postgresql-13 ++psmisc ++puppet-module-adrienthebo-filemapper ++puppet-module-asciiduck-sssd ++puppet-module-barbican ++puppet-module-duritong-sysctl ++puppet-module-puppetlabs-mount-core ++puppet-module-voxpupuli-collectd ++puppet-module-vswitch ++pv ++python3-amqplib ++python3-boto3 ++python3-castellan ++python3-cherrypy3 ++python3-contextlib2 ++python3-coverage ++python3-daemon ++python3-dev ++python3-django-debreach ++python3-django-pyscss ++python3-enmerkar ++python3-falcon ++python3-fixtures ++python3-flask-restful ++python3-ipaddr ++python3-keystonemiddleware ++python3-kubernetes ++python3-ldap3 ++python3-ldappool ++python3-lz4 ++python3-mechanize ++python3-mysqldb ++python3-os-client-config ++python3-oslo.config ++python3-oslo.db ++python3-oslo.log ++python3-oslo.policy ++python3-oslo.rootwrap ++python3-oslo.upgradecheck ++python3-oslo.versionedobjects ++python3-osprofiler ++python3-paramiko ++python3-parted ++python3-passlib ++python3-pastescript ++python3-pecan ++python3-pexpect ++python3-pip ++python3-psutil ++python3-pyelftools ++python3-pyghmi ++python3-pymongo ++python3-pysaml2 ++python3-q-text-as-data ++python3-redis ++python3-requests-toolbelt ++python3-retrying ++python3-ruamel.yaml ++python3-scapy ++python3-scrypt ++python3-semantic-version ++python3-sh ++python3-simplejson ++python3-sklearn ++python3-sortedcontainers ++python3-swiftclient ++python3-testtools ++python3-ujson ++python3-warlock ++python3-websockify ++python3-xstatic-angular-bootstrap ++python3-xstatic-angular-fileupload ++python3-xstatic-angular-gettext ++python3-xstatic-angular-lrdragndrop ++python3-xstatic-angular-schema-form ++python3-xstatic-angular-ui-router ++python3-xstatic-bootstrap-datepicker ++python3-xstatic-bootstrap-scss ++python3-xstatic-bootswatch ++python3-xstatic-d3 ++python3-xstatic-font-awesome ++python3-xstatic-hogan ++python3-xstatic-jasmine ++python3-xstatic-jquery-migrate ++python3-xstatic-jquery.quicksearch ++python3-xstatic-jquery.tablesorter ++python3-xstatic-jquery-ui ++python3-xstatic-jsencrypt ++python3-xstatic-magic-search ++python3-xstatic-mdi ++python3-xstatic-objectpath ++python3-xstatic-rickshaw ++python3-xstatic-smart-table ++python3-xstatic-spin ++python3-xstatic-term.js ++python-is-python3 ++redfishtool ++rng-tools ++rpm ++rsync ++ruby-json ++screen ++seabios ++smartmontools ++socat ++spectre-meltdown-checker ++ssg-debian ++sshpass ++sssd ++sssd-tools ++startpar ++strace ++strongswan ++strongswan-swanctl ++sudo-ldap ++syslog-ng ++sysstat ++sysvinit-utils ++targetcli-fb ++tasksel ++tasksel-data ++tcpdump ++time ++traceroute ++tuned ++tzdata ++udhcpc ++unzip ++uwsgi-plugin-apparmor ++uwsgi-plugin-python3 ++vim ++vim-tiny ++vlan ++w3m ++wget ++whiptail ++xclip ++xfsprogs ++zip +-- +2.30.2 + -- 2.16.6