Debian: add test patches

Script to build test patches for debian using ostree.

This initial version is building a reboot required patch by changing
one package (logmgmt) and rebuilding it. The steps are as follows:

- create a clone of ostree_repo
- update logmgmt package
- rebuild package
- build-image to generate new ostree commit
- create patch

Story: 2009969
Task: 45635
Signed-off-by: Luis Sampaio <luis.sampaio@windriver.com>
Change-Id: I5eb2d768c8a390c98d34a00d43822ba87a284f70
This commit is contained in:
Luis Sampaio 2022-06-22 12:31:54 -07:00
parent cc06fd92c7
commit 178dbe2c44
1 changed files with 235 additions and 0 deletions

View File

@ -0,0 +1,235 @@
#!/bin/python3
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
"""
Debian Build Test Patches:
Reboot required - all nodes
Update package - logmgmt
rebuild the pkg
build-image to generate a new commit in the build ostree_repo
build a patch
Patches with dependency (reboot required)
TODO:
Patch A
update package - logmgmt
build-image to generate a new commit in the build ostree_repo
build patch A
Patch B (requires A)
Requires:
debchange (devscripts) - Tool for maintenance of the debian/changelog file in a source package
https://manpages.debian.org/jessie/devscripts/debchange.1.en.html
Steps to run:
# Setup debian build env
# For more information about how to setup the environment:
https://wiki.openstack.org/wiki/StarlingX/DebianBuildEnvironment
export PROJECT="stx-debian-build"
export STX_BUILD_HOME="/localdisk/designer/${USER}/${PROJECT}"
# Initialize the build containers
stx control start
./build_test_patches.py --help
"""
import argparse
import logging
import os
import shutil
import subprocess
import sys
from requests import patch
sys.path.insert(0, "../cgcs-patch")
from cgcs_make_patch.make_patch import PatchBuilder # noqa: E402 pylint: disable=wrong-import-position
from cgcs_make_patch.make_patch import PatchRecipeData # noqa: E402 pylint: disable=wrong-import-position
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)
log = logging.getLogger('build_test_patches')
def run_cmd(cmd):
'''
Run a cmd and return
param command: string representing the command to be executed
'''
log.debug("Running: %s", cmd)
return subprocess.run(
cmd,
shell=True,
executable='/bin/bash',
check=True)
class TestPatchInitException(Exception):
"""TestPatch initialization error"""
class TestPatchCreationException(Exception):
"""Patch creation error"""
class TestPatchBuilder():
"""
Build test patches
"""
def __init__(self, sw_version):
try:
self.project = os.environ.get("PROJECT")
self.build_home = os.environ.get("STX_BUILD_HOME")
self.repo = os.path.join(self.build_home, "repo")
self.repo_root = os.path.join(self.repo, "cgcs-root")
self.patch_repo_base = os.path.join(self.repo_root, "stx/update")
self.sw_version = sw_version
except TestPatchInitException:
log.exception("TestPatchBuilder initialization failure")
sys.exit(1)
def __upversion_pkg(self, pkg_dir):
"""
Updates changelog version in pkg_dir/debian/deb_folder
"""
log.info("Upversioning package %s", pkg_dir)
# cd pkg_dir/debian/deb_folder; dch -q "PATCH TEST" --changelog changelog
pwd = os.getcwd()
os.chdir(pkg_dir)
# Increase the change log version
cmd = "dch -q 'PATCH TEST' --changelog debian/deb_folder/changelog"
ret = run_cmd(cmd)
if ret.returncode != 0:
raise Exception("Error while changing the package version")
os.chdir(pwd)
def __delete_dir(self, dir_path):
"""
Deletes a directory - called when cleaning up the cloned ostree
param dir_path: Path to the directory
"""
if os.path.isdir(dir_path):
log.info("removing %s", dir_path)
shutil.rmtree(dir_path)
def build_pkg(self, pkg_name):
"""
Build package
"""
os.chdir(os.path.join(self.repo, "stx-tools"))
cmd = f'''
source import-stx
stx shell -c "build-pkgs -c -p {pkg_name}"
'''
ret = run_cmd(cmd)
log.info("Build pkgs return code %s", ret.returncode)
if ret.returncode != 0:
raise Exception("Failed to build packages")
def build_image(self):
"""
Build image - generates new ostree commit
"""
cmd = '''
source import-stx
stx shell -c "build-image"
'''
ret = run_cmd(cmd)
log.info("Build image return code %s", ret.returncode)
if ret.returncode != 0:
raise Exception("Failed to build image")
def update_pkg(self, pname):
"""
Make a change on the logmgmt package and upversions it
param pname: patch name that is added to the script and can be used as patch validation
"""
pkg_name = "logmgmt"
log.info("Updating package %s", pkg_name)
pkg_dir = os.path.join(self.repo_root, "stx/utilities/utilities", pkg_name)
pkg_script = os.path.join(pkg_dir, "scripts/init.d/logmgmt")
# Insert a message into /etc/init.d/$(basename $SCRIPT)
cmd = "sed -i 's|start).*|start) logger -t \\$(basename \\$0) \"" + pname + " patch is applied\"|' " + pkg_script
run_cmd(cmd)
self.__upversion_pkg(pkg_dir)
# build the pkg to apply the change
self.build_pkg(pkg_name)
def rr_allnodes_patch(self, pname, requires=False, formal=False):
"""
Creates a reboot required patch
param pname: Patch ID and file name
param requires: If set it will build the 2nd patch
"""
ostree_clone_name = "ostree_repo_patch"
patch_builder = PatchBuilder()
# Generating ostree_repo clone
patch_builder.prepare_env(ostree_clone_name)
# Update pkg
self.update_pkg(pname)
log.info("Generating RR patch for all nodes")
# build image to trigger a new ostree commit
self.build_image()
patch_data = PatchRecipeData()
patch_data.patch_id = pname
patch_data.sw_version = self.sw_version
patch_data.metadata = {
"SUMMARY": "RR ALL NODES",
"DESCRIPTION": "Test patch",
"INSTALL_INSTRUCTIONS": "Sample instructions",
"WARNINGS": "Sample Warning",
"STATUS": "DEV",
"UNREMOVABLE": "N",
"REBOOT_REQUIRED": "Y"
}
# Create a patch
log.info("Creating patch %s", pname)
patch_builder.create_patch(patch_data, ostree_clone_name, formal)
log.info("Patch build done")
clone_repo_path = os.path.join(patch_builder.deploy_dir, ostree_clone_name)
self.__delete_dir(clone_repo_path)
if requires:
# Build the 2nd patch which will follow similar steps but will set the requires flag
patch_builder.prepare_env(ostree_clone_name)
# Update pkg
self.update_pkg(pname + "_REQUIRES")
log.info("Generating RR Requires patch for all nodes")
# build image to trigger a new ostree commit
self.build_image()
# Update patch ID and set requires
patch_data.patch_id = pname + "_REQUIRES"
patch_data.requires.append(pname)
# Create a patch
log.info("Creating patch requires patch")
patch_builder.create_patch(patch_data, ostree_clone_name, formal)
log.info("Patch build done")
self.__delete_dir(clone_repo_path)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Debian build_test_patches")
parser.add_argument("-sw", "--software-version", type=str, help="Patch Software version, will prefix the patch name", default=None, required=True)
parser.add_argument("-r", "--requires", action="store_true", help="Build the 2nd patch which requires the rr_patch")
parser.add_argument("-f", "--formal", action="store_true", help="Signs the patch with formal key")
args = parser.parse_args()
log.debug("Args: %s", args)
try:
log.info("Building test patches")
patch_name = args.software_version + "_RR_ALL_NODES"
test_patch_builder = TestPatchBuilder(args.software_version)
test_patch_builder.rr_allnodes_patch(patch_name, args.requires, args.formal)
except TestPatchCreationException:
log.exception("Error while creating test patches")