Debian Patch Apply
This commit enables sw-patch apply functionality in a Debian env. Patch apply extracts software.tar and store its contents in a temporary location. The extracted contents include objects, refs, extensions, summary, tmp, state, etc. folders. All these folders are then recursively copied to the feed ostree stored at /var/www/pages/feed/rel-<SW-VERSION>/ostree_repo/ Test case: sw-patch apply Story: 2009969 Task: 45244 Signed-off-by: Jessica Castelino <jessica.castelino@windriver.com> Change-Id: I9134f90350265e9388d8b317adda7d671e72e2d9
This commit is contained in:
parent
13a5dd7ca6
commit
3aa513a7e3
|
@ -42,6 +42,9 @@ CLI_OPT_DRY_RUN = '--dry-run'
|
|||
CLI_OPT_RECURSIVE = '--recursive'
|
||||
CLI_OPT_RELEASE = '--release'
|
||||
|
||||
OSTREE_REF = "starlingx"
|
||||
FEED_OSTREE_BASE_DIR = "/var/www/pages/feed"
|
||||
|
||||
ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER = 'ENABLE_DEV_CERTIFICATE'
|
||||
|
||||
LOOPBACK_INTERFACE_NAME = "lo"
|
||||
|
|
|
@ -27,8 +27,8 @@ class ContentFail(PatchError):
|
|||
pass
|
||||
|
||||
|
||||
class OSTreeTarMissingFailure(PatchError):
|
||||
"""OSTree Tarball Missing error."""
|
||||
class OSTreeTarFail(PatchError):
|
||||
"""OSTree Tarball error."""
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import six
|
|||
from six.moves import configparser
|
||||
import socket
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
|
@ -35,7 +36,7 @@ from cgcs_patch.patch_functions import SW_VERSION
|
|||
from cgcs_patch.patch_functions import root_package_dir
|
||||
from cgcs_patch.exceptions import MetadataFail
|
||||
from cgcs_patch.exceptions import ContentFail
|
||||
from cgcs_patch.exceptions import OSTreeTarMissingFailure
|
||||
from cgcs_patch.exceptions import OSTreeTarFail
|
||||
from cgcs_patch.exceptions import PatchError
|
||||
from cgcs_patch.exceptions import PatchFail
|
||||
from cgcs_patch.exceptions import PatchInvalidRequest
|
||||
|
@ -863,6 +864,16 @@ class PatchController(PatchService):
|
|||
contentfile = "%s/%s" % (content_dir, contentname)
|
||||
return contentfile
|
||||
|
||||
def get_ostree_tar_filename(self, patch_sw_version, patch_id):
|
||||
'''
|
||||
Returns the path of the ostree tarball
|
||||
:param patch_sw_version: sw version this patch must be applied to
|
||||
:param patch_id: The patch ID
|
||||
'''
|
||||
ostree_tar_dir = package_dir[patch_sw_version]
|
||||
ostree_tar_filename = "%s/%s" % (ostree_tar_dir, patch_id)
|
||||
return ostree_tar_filename
|
||||
|
||||
def get_repo_filename(self, patch_sw_version, contentname):
|
||||
contentfile = self.get_store_filename(patch_sw_version, contentname)
|
||||
if not os.path.isfile(contentfile):
|
||||
|
@ -1047,8 +1058,6 @@ class PatchController(PatchService):
|
|||
msg_info += "There are no available patches to be applied.\n"
|
||||
return dict(info=msg_info, warning=msg_warning, error=msg_error)
|
||||
|
||||
repo_changed = False
|
||||
|
||||
# First, verify that all specified patches exist
|
||||
id_verification = True
|
||||
for patch_id in patch_list:
|
||||
|
@ -1117,6 +1126,81 @@ class PatchController(PatchService):
|
|||
msg_info += msg + "\n"
|
||||
continue
|
||||
|
||||
# OSTree Commit consistency check
|
||||
# Check if the patch can be applied on the system
|
||||
# Fetch the latest commit and checksum by running the command given below
|
||||
# and compare it with the base commit and base checksum values from metadata.xml
|
||||
#
|
||||
# Command: ostree log starlingx --repo=/var/www/pages/feed/rel-22.02/ostree_repo
|
||||
#
|
||||
# Output:
|
||||
#
|
||||
# commit 478bc21c1702b9b667b5a75fac62a3ef9203cc1767cbe95e89dface6dc7f205e
|
||||
# ContentChecksum: 61fc5bb4398d73027595a4d839daeb404200d0899f6e7cdb24bb8fb6549912ba
|
||||
# Date: 2022-04-28 18:58:57 +0000
|
||||
#
|
||||
# Commit-id: starlingx-intel-x86-64-20220428185802
|
||||
#
|
||||
# commit ad7057a94a1d06e38eaedee2ce3fe56826ae817497469bce5d5ac05bc506aaa7
|
||||
# ContentChecksum: dc42a42427a4f9e4de1210327c12b12ea3ad6a5d232497a903cc6478ca381e8b
|
||||
# Date: 2022-04-28 18:05:43 +0000
|
||||
#
|
||||
# Commit-id: starlingx-intel-x86-64-20220428180512
|
||||
|
||||
patch_sw_version = self.patch_data.metadata[patch_id]["sw_version"]
|
||||
|
||||
feed_ostree = "%s/rel-%s/ostree_repo" % (constants.FEED_OSTREE_BASE_DIR, patch_sw_version)
|
||||
|
||||
cmd = "ostree log %s --repo=%s" % (constants.OSTREE_REF, feed_ostree)
|
||||
output = subprocess.run(cmd, shell=True, check=True, capture_output=True)
|
||||
|
||||
# Store the output of the above command in a string
|
||||
output_string = output.stdout.decode('utf-8')
|
||||
|
||||
# Parse the string to get the latest commit and checksum on the controller
|
||||
split_output_string = output_string.split()
|
||||
latest_commit = split_output_string[1]
|
||||
latest_checksum = split_output_string[3]
|
||||
|
||||
if self.patch_data.contents[patch_id]["base"]["commit"] != latest_commit \
|
||||
and self.patch_data.contents[patch_id]["base"]["checksum"] != latest_checksum:
|
||||
msg = "The base commit and checksum for %s do not match the latest commit " \
|
||||
"and checksum on this system." % (patch_id)
|
||||
LOG.info(msg)
|
||||
msg_info += msg + "\n"
|
||||
continue
|
||||
|
||||
ostree_tar_filename = self.get_ostree_tar_filename(patch_sw_version, patch_id)
|
||||
|
||||
# Create a temporary working directory
|
||||
tmpdir = tempfile.mkdtemp(prefix="patch_")
|
||||
|
||||
# Save the current directory, so we can chdir back after
|
||||
orig_wd = os.getcwd()
|
||||
|
||||
# Change to the tmpdir
|
||||
os.chdir(tmpdir)
|
||||
|
||||
try:
|
||||
# Extract the software.tar
|
||||
tar = tarfile.open(ostree_tar_filename)
|
||||
tar.extractall()
|
||||
|
||||
# Copy extracted folders of software.tar to the feed ostree repo
|
||||
shutil.copytree(tmpdir, feed_ostree, dirs_exist_ok=True)
|
||||
except tarfile.TarError:
|
||||
msg = "Failed to extract the ostree tarball for %s" % patch_id
|
||||
LOG.exception(msg)
|
||||
raise OSTreeTarFail(msg)
|
||||
except shutil.Error:
|
||||
msg = "Failed to copy the ostree tarball for %s" % patch_id
|
||||
LOG.exception(msg)
|
||||
raise OSTreeTarFail(msg)
|
||||
finally:
|
||||
# Change back to original working dir
|
||||
os.chdir(orig_wd)
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
|
||||
try:
|
||||
# Move the patching metadata from avail to applied dir
|
||||
shutil.move("%s/%s-metadata.xml" % (avail_dir, patch_id),
|
||||
|
@ -1138,24 +1222,6 @@ class PatchController(PatchService):
|
|||
self.interim_state[patch_id] = list(self.hosts)
|
||||
self.hosts_lock.release()
|
||||
|
||||
repo_changed = True
|
||||
|
||||
if repo_changed:
|
||||
# Update the repo
|
||||
self.patch_data.gen_groups_xml()
|
||||
for ver, rdir in repo_dir.items():
|
||||
try:
|
||||
# todo(jcasteli) determine if ostree change needs additional actions
|
||||
# old code was calling 'createrepo' for rpms
|
||||
output = "OSTREE determined a change occurred rdir=%s" % rdir
|
||||
LOG.info("Repo[%s] updated:\n%s", ver, output)
|
||||
except Exception:
|
||||
msg = "Failed to update the repo for %s" % ver
|
||||
LOG.exception(msg)
|
||||
raise PatchFail(msg)
|
||||
else:
|
||||
LOG.info("Repository is unchanged")
|
||||
|
||||
return dict(info=msg_info, warning=msg_warning, error=msg_error)
|
||||
|
||||
def patch_remove_api(self, patch_ids, **kwargs):
|
||||
|
@ -1168,8 +1234,6 @@ class PatchController(PatchService):
|
|||
msg_error = ""
|
||||
remove_unremovable = False
|
||||
|
||||
repo_changed = False
|
||||
|
||||
# Protect against duplications
|
||||
patch_list = sorted(list(set(patch_ids)))
|
||||
|
||||
|
@ -1275,8 +1339,6 @@ class PatchController(PatchService):
|
|||
msg_info += msg + "\n"
|
||||
continue
|
||||
|
||||
repo_changed = True
|
||||
|
||||
patch_sw_version = self.patch_data.metadata[patch_id]["sw_version"]
|
||||
for contentname in self.patch_data.contents[patch_id]:
|
||||
contentfile = self.get_store_filename(patch_sw_version, contentname)
|
||||
|
@ -1318,22 +1380,6 @@ class PatchController(PatchService):
|
|||
self.interim_state[patch_id] = list(self.hosts)
|
||||
self.hosts_lock.release()
|
||||
|
||||
if repo_changed:
|
||||
# Update the repo
|
||||
self.patch_data.gen_groups_xml()
|
||||
for ver, rdir in repo_dir.items():
|
||||
try:
|
||||
# todo(jcasteli) determine if ostree change needs additional actions
|
||||
# old code was calling 'createrepo' for rpms
|
||||
output = "OSTREE determined a change occurred rdir=%s" % rdir
|
||||
LOG.info("Repo[%s] updated:\n%s", ver, output)
|
||||
except Exception:
|
||||
msg = "Failed to update the repo for %s" % ver
|
||||
LOG.exception(msg)
|
||||
raise PatchFail(msg)
|
||||
else:
|
||||
LOG.info("Repository is unchanged")
|
||||
|
||||
return dict(info=msg_info, warning=msg_warning, error=msg_error)
|
||||
|
||||
def patch_delete_api(self, patch_ids):
|
||||
|
@ -1381,8 +1427,7 @@ class PatchController(PatchService):
|
|||
# Handle operation
|
||||
for patch_id in patch_list:
|
||||
patch_sw_version = self.patch_data.metadata[patch_id]["sw_version"]
|
||||
abs_ostree_tar_dir = package_dir[patch_sw_version]
|
||||
ostree_tar_filename = "%s/%s-software.tar" % (abs_ostree_tar_dir, patch_id)
|
||||
ostree_tar_filename = self.get_ostree_tar_filename(patch_sw_version, patch_id)
|
||||
if not os.path.isfile(ostree_tar_filename):
|
||||
# We're deleting the patch anyway, so the missing file
|
||||
# doesn't really matter
|
||||
|
@ -1393,7 +1438,7 @@ class PatchController(PatchService):
|
|||
except OSError:
|
||||
msg = "Failed to remove ostree tarball %s" % ostree_tar_filename
|
||||
LOG.exception(msg)
|
||||
raise OSTreeTarMissingFailure(msg)
|
||||
raise OSTreeTarFail(msg)
|
||||
|
||||
try:
|
||||
# Delete the metadata
|
||||
|
|
|
@ -185,7 +185,7 @@ class BasePackageData(object):
|
|||
|
||||
def loaddirs(self):
|
||||
# Load up available package info
|
||||
base_dir = "/var/www/pages/feed"
|
||||
base_dir = constants.FEED_OSTREE_BASE_DIR
|
||||
if not os.path.exists(base_dir):
|
||||
# Return, since this could be running off-box
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue