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:
parent
cc06fd92c7
commit
178dbe2c44
|
@ -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")
|
Loading…
Reference in New Issue