virt-manager/virtinst/initrdinject.py

116 lines
3.8 KiB
Python

#
# Copyright 2006-2009, 2013, 2014 Red Hat, Inc.
# Daniel P. Berrange <berrange@redhat.com>
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import logging
import os
import shutil
import subprocess
import tempfile
def _rhel4_initrd_inject(initrd, injections):
try:
file_proc = subprocess.Popen(["file", "-z", initrd],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
s = bytes("ext2 filesystem", "ascii")
if s not in file_proc.communicate()[0]:
return False
except Exception:
logging.exception("Failed to file command for rhel4 initrd detection")
return False
logging.debug("Is RHEL4 initrd")
# Uncompress the initrd
newinitrd = open(initrd + ".new", "wb")
gzip_proc = subprocess.Popen(["gzip", "-d", "-f", "-c", initrd],
stdout=newinitrd,
stderr=subprocess.PIPE)
gzip_proc.wait()
newinitrd.close()
debugfserr = bytes()
for filename in injections:
# We have an ext2 filesystem, use debugfs to inject files
cmd = ["debugfs", "-w", "-R",
"write %s %s" % (filename, os.path.basename(filename)),
newinitrd.name]
logging.debug("Copying %s to the initrd with cmd=%s", filename, cmd)
debugfs_proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
debugfs_proc.wait()
debugfserr += debugfs_proc.stderr.read() or bytes()
gziperr = gzip_proc.stderr.read()
if gziperr:
logging.debug("gzip stderr=%s", gziperr)
if debugfserr:
logging.debug("debugfs stderr=%s", debugfserr)
# Recompress the initrd
gzip_proc = subprocess.Popen(["gzip"],
stdin=open(newinitrd.name, "rb"),
stdout=open(initrd, "wb"),
stderr=subprocess.PIPE)
gzip_proc.wait()
gziperr = gzip_proc.stderr.read()
if gziperr:
logging.debug("gzip stderr=%s", gziperr)
os.unlink(newinitrd.name)
return True
def perform_initrd_injections(initrd, injections, scratchdir):
"""
Insert files into the root directory of the initial ram disk
"""
if not injections:
return
if _rhel4_initrd_inject(initrd, injections):
return
tempdir = tempfile.mkdtemp(dir=scratchdir)
os.chmod(tempdir, 0o775)
for filename in injections:
logging.debug("Copying %s to the initrd.", filename)
shutil.copy(filename, tempdir)
logging.debug("Appending to the initrd.")
find_proc = subprocess.Popen(['find', '.', '-print0'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=tempdir)
cpio_proc = subprocess.Popen(['cpio', '-o', '--null', '-Hnewc', '--quiet'],
stdin=find_proc.stdout,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=tempdir)
f = open(initrd, 'ab')
gzip_proc = subprocess.Popen(['gzip'], stdin=cpio_proc.stdout,
stdout=f, stderr=subprocess.PIPE)
cpio_proc.wait()
find_proc.wait()
gzip_proc.wait()
f.close()
shutil.rmtree(tempdir)
finderr = find_proc.stderr.read()
cpioerr = cpio_proc.stderr.read()
gziperr = gzip_proc.stderr.read()
if finderr:
logging.debug("find stderr=%s", finderr)
if cpioerr:
logging.debug("cpio stderr=%s", cpioerr)
if gziperr:
logging.debug("gzip stderr=%s", gziperr)