update/software/scripts/remove-temporary-data
Heitor Matsui f1a7ec2360 Improve deploy start upgrade scripts
This commit changes all deploy start upgrade scripts
to python, improve them by removing duplicated/needless
code and add more logging. The summary of the changes are:

- All shell scripts were converted to python code
- Some scripts were renamed to follow a naming convention
  and as a symlink with the old name was added to them for
  backwards compatibility
- Improved error logging and exception try/except blocks
- Removed from deploy start script the unnecessary initial
  step to initialize a temporary ostree_repo, changing it
  to checkout the ostree_repo directly from the feed

Test Plan:
PASS: AIO-SX stx-10 to stx-11 e2e upgrade
PASS: AIO-DX stx-10 to stx-11 e2e upgrade

Story: 2011357
Task: 51892

Change-Id: I63c324b169883c6e9007bc99fd67b5f5b2880668
Signed-off-by: Heitor Matsui <heitorvieira.matsui@windriver.com>
2025-04-03 17:15:31 -03:00

133 lines
5.0 KiB
Python

#!/usr/bin/python3
#
# Copyright (c) 2024-2025 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# This script removes artifacts created by the deploy start script:
# 1. Stop temporary database created for data migrations
# 2. Unmount the bind mounts used by the data migration process
# 3. Remove the staging deployment directory created by checking out TO release ostree branch
#
# It can be used either by another script (e.g. deploy-start) to automatically
# cleanup the environment after both success/failure paths of the data migration process,
# or can be used by a system administrator to manually cleanup the environment if the
# automatic cleanup process fails.
#
import configparser
import logging as LOG
import os
import shutil
import subprocess
import sys
import upgrade_utils
class RemoveTemporaryData:
def __init__(self, checkout_dir):
self._checkout_dir = checkout_dir
try:
default_section = configparser.DEFAULTSECT
cp = configparser.ConfigParser()
with open(os.path.join(self._checkout_dir, "usr/etc/build.info"), "r") as fp:
cp.read_string(f"[{default_section}]\n" + fp.read())
self._sw_version = cp.get(default_section, "SW_VERSION").strip('"')
except Exception as e:
LOG.error(f"Error getting SW_VERSION: {str(e)}")
raise
def stop_database(self):
db_dir = os.path.join(self._checkout_dir, "var/lib/postgresql", self._sw_version)
LOG.info(f"Attempting to stop the temporary database in {db_dir}...")
if os.path.isdir(db_dir):
try:
cmd = ["lsof", db_dir]
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError:
LOG.info("Database is not running")
return
try:
cmd = [os.path.join(self._checkout_dir, "usr/bin/pgconfig"), "--bindir"]
process = subprocess.run(cmd, check=True, text=True, capture_output=True)
db_bin_dir = process.stdout.strip()
cmd = ["sudo", "-u", "postgres", os.path.join(db_bin_dir, "pg_ctl"), "-D", db_dir, "stop"]
subprocess.run(cmd, check=True)
LOG.info("Success stopping database")
except subprocess.CalledProcessError:
LOG.error("Error stopping database")
raise
else:
LOG.warning("No database found in the specified directory")
def unmount_filesystems(self):
script_path = (f"/var/www/pages/feed/rel-{self._sw_version}"
f"/upgrades/software-deploy/prepare-chroot-mounts")
LOG.info(f"Attempting to unmount filesystems under {self._checkout_dir}...")
try:
cmd = [f"{script_path}", f"{self._checkout_dir}", "-u"]
subprocess.run(cmd, check=True, text=True, capture_output=True)
LOG.info("Success unmounting filesystems")
except subprocess.CalledProcessError as e:
LOG.error(f"Error unmounting filesystems: {e.stderr.strip()}")
raise
def remove_temp_directories(self):
script_path = (f"/var/www/pages/feed/rel-{self._sw_version}"
f"/upgrades/software-deploy/prepare-chroot-mounts")
temp_dirs = [self._checkout_dir]
LOG.info(f"Attempting to remove temporary deployment directories "
f"{temp_dirs}...")
try:
cmd = [f"{script_path}", f"{self._checkout_dir}", "-c"]
subprocess.run(cmd, check=True, text=True, capture_output=True)
except subprocess.CalledProcessError as e:
LOG.error(f"Some mount points are still mounted ({e.stdout.strip()}), "
f"cannot proceed with the cleanup: {e.stderr.strip()}")
raise
for temp_dir in temp_dirs:
shutil.rmtree(temp_dir, ignore_errors=True)
LOG.info(f"{temp_dir} removed successfully")
def run(self):
LOG.info("Starting temporary data cleanup...")
try:
self.stop_database()
self.unmount_filesystems()
self.remove_temp_directories()
LOG.info("Temporary data cleanup finished")
except Exception:
LOG.error("Error executing cleanup, please check the logs, fix the errors and retry")
return 1
return 0
if __name__ == "__main__":
upgrade_utils.configure_logging("/var/log/software.log", log_level=LOG.INFO)
checkout_dir = None
for arg in range(1, len(sys.argv)):
if arg == 1:
checkout_dir = sys.argv[arg]
if checkout_dir is None:
usage_msg = f"usage: {sys.argv[0]} <ostree-checkout-dir>"
print(usage_msg)
LOG.error(usage_msg)
sys.exit(1)
if not os.path.isdir(checkout_dir):
error_msg = f"Checkout directory {checkout_dir} does not exist, cannot proceed with cleanup"
print(error_msg)
LOG.error(error_msg)
sys.exit(1)
deploy_cleanup = RemoveTemporaryData(checkout_dir)
sys.exit(deploy_cleanup.run())