Skip to content

Commit

Permalink
CP-45506: Archive /etc/systemd a tar archive inside the output
Browse files Browse the repository at this point in the history
Signed-off-by: Bernhard Kaindl <bernhard.kaindl@cloud.com>
  • Loading branch information
Bernhard Kaindl authored and bernhardkaindl committed Oct 2, 2023
1 parent 8babe28 commit 7a24a4c
Showing 1 changed file with 72 additions and 2 deletions.
74 changes: 72 additions & 2 deletions xen-bugtool
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#

import getopt
import io
import re
import os
import StringIO
Expand Down Expand Up @@ -1152,6 +1153,7 @@ exclude those logs from the archive.
archive = TarOutput(subdir, output_type, output_fd)
else:
archive = ZipOutput(subdir)
archive.declare_subarchive("/etc/systemd", subdir + "/etc/systemd.tar")

# collect selected data now
output_ts('Running commands to collect data')
Expand Down Expand Up @@ -1634,8 +1636,65 @@ def removeNoError(filename):
except OSError:
pass

class TarOutput:
class TarSubArchive(io.BytesIO):
"""Utility class for adding subarchives to an ZIP or tar output archive"""

def __init__(self, basepath, tar_filename):
"""
Create the object, defining the base path of the files and the tar file name.
:param basepath: path below which all files shall be captured into the subarchive
:param tar_filename: Name of the tar file in the parent archive
"""
self.basepath = basepath
self.mtime = time.time()
self.name = tar_filename
self.tar = tarfile.open(fileobj=self, mode="w|", dereference=True)

def add(self, name, filename):
"""
Add a file to the subarchive
:param name: Recorded path of the the file in the tar archive for extraction
:param filename: Real file name of the file to be added to the tar archive
"""
self.tar.addfile(self.tar.gettarinfo(filename, name), open(filename, "rb"))

class ArchiveWithTarSubarchives(object):
"""Base class for TarOutput and ZipOutput with support to create sub-archives"""

def __init__(self):
"""Initialize the defined sub-archives to be an empty list"""
self.subarchives = []

def declare_subarchive(self, basepath, tar_filename):
"""
Declare a subarchive by defining the base path of the files and the tar file name.
:param basepath: path below which all files shall be captured into the subarchive
:param tar_filename: Name of the tar file in the parent archive
"""
self.subarchives.append(TarSubArchive(basepath, tar_filename))

def addFileToSubarchive(self, name, filename):
"""If filename belongs to a subarchive, add the file to it and return True"""
for subarchive in self.subarchives:
if filename.startswith(subarchive.basepath):
subarchive.add(name, filename)
return True
return False

def add_subarchives(self):
"""Close all subarchives and add the archive files to the Tar/Zip output"""
for subarchive in self.subarchives:
if len(subarchive.archive.getmembers()):
subarchive.archive.close()
self.addFile(subarchive.name, subarchive)

def addFile(self, _name, _data):
"""Needs to be implemented by subclasses to add the subarchive to the output"""
pass

class TarOutput(ArchiveWithTarSubarchives):
def __init__(self, subdir, suffix, output_fd):
super(TarOutput, self).__init__()
self.output_fd = output_fd
self.subdir = subdir
mode = 'w|'
Expand All @@ -1655,6 +1714,9 @@ class TarOutput:
return ti

def addRealFile(self, name, filename):
"""Read file contents for adding to the output tar file or a subarchive of it"""
if self.addFileToSubarchive(name, filename):
return
ti = self._getTi(name)
s = os.stat(filename)
ti.mtime = s.st_mtime
Expand All @@ -1669,6 +1731,8 @@ class TarOutput:
self.tf.addfile(ti, data)

def close(self):
"""Add all subarchives to the output tar file and write it"""
self.add_subarchives()
try:
self.tf.close()
if self.output_fd == -1:
Expand All @@ -1686,13 +1750,17 @@ class TarOutput:
removeNoError(self.filename)
return False

class ZipOutput:
class ZipOutput(ArchiveWithTarSubarchives):
def __init__(self, subdir):
super(ZipOutput, self).__init__()
self.subdir = subdir
self.filename = "%s/%s.zip" % (BUG_DIR, subdir)
self.zf = zipfile.ZipFile(self.filename, 'w', zipfile.ZIP_DEFLATED)

def addRealFile(self, name, filename):
"""Read file contents for adding to the output ZIP or a subarchive of it"""
if self.addFileToSubarchive(name, filename):
return
if os.stat(filename).st_size < 50:
compress_type = zipfile.ZIP_STORED
else:
Expand All @@ -1703,6 +1771,8 @@ class ZipOutput:
self.zf.writestr(name, data.getvalue())

def close(self):
"""Add all subarchives to the output ZIP file and write it"""
self.add_subarchives()
try:
self.zf.close()
output ('Writing archive %s successful.' % self.filename)
Expand Down

0 comments on commit 7a24a4c

Please sign in to comment.