Unpack bootstrap img in context manager

Change-Id: I386ea151c5675f93da4359fadd8adaa6ba890e67
This commit is contained in:
Sergey Abramov 2016-03-02 18:05:01 +03:00
parent f78d006175
commit b3242d9d59
3 changed files with 112 additions and 14 deletions

View File

@ -11,12 +11,11 @@
# under the License. # under the License.
import os.path import os.path
import shutil
import tempfile
from cliff import command as cmd from cliff import command as cmd
from octane import magic_consts from octane import magic_consts
from octane.util import archivate
from octane.util import docker from octane.util import docker
from octane.util import subprocess from octane.util import subprocess
@ -55,19 +54,9 @@ def revert_initramfs():
def patch_initramfs(): def patch_initramfs():
backup = magic_consts.BOOTSTRAP_INITRAMFS + '.bkup' with archivate.update_cpio(magic_consts.BOOTSTRAP_INITRAMFS) as chroot:
chroot = tempfile.mkdtemp()
try:
os.rename(magic_consts.BOOTSTRAP_INITRAMFS, backup)
subprocess.call("gunzip -c {0} | cpio -id".format(backup),
shell=True, cwd=chroot)
patch_fuel_agent(chroot) patch_fuel_agent(chroot)
with open(magic_consts.BOOTSTRAP_INITRAMFS, "wb") as f: docker.run_in_container("cobbler", ["cobbler", "sync"])
subprocess.call("find | grep -v '^\.$' | cpio --format newc -o"
" | gzip -c", shell=True, stdout=f, cwd=chroot)
docker.run_in_container("cobbler", ["cobbler", "sync"])
finally:
shutil.rmtree(chroot)
def patch_fuel_agent(chroot): def patch_fuel_agent(chroot):

View File

@ -82,3 +82,75 @@ def test_archivate_container_cmd_output(mocker):
test_archive.addfile.assert_called_once_with( test_archive.addfile.assert_called_once_with(
tar_info, io_mock.return_value) tar_info, io_mock.return_value)
assert io_mock.return_value.getvalue() == output_data assert io_mock.return_value.getvalue() == output_data
def test_update_cpio_with_exception(mocker, mock_subprocess):
mocker.patch("tempfile.mkdtemp", return_value="tmp_dir_name")
shutil_mocker = mocker.patch("shutil.rmtree")
class TestException(Exception):
pass
test_msg = "Fake exception"
with pytest.raises(TestException) as exc_info:
with archivate.update_cpio("fake_img_path.img"):
raise TestException(test_msg)
assert test_msg == exc_info.value.message
shutil_mocker.assert_called_once_with("tmp_dir_name")
assert [
mock.call(
["gunzip", "-c", "fake_img_path.img"],
stdout=subprocess.PIPE),
mock.call(
["cpio", "-id"],
stdin=mock_subprocess.return_value.__enter__.return_value.stdout,
cwd="tmp_dir_name"),
] == mock_subprocess.call_args_list
def test_update_cpio(mocker, mock_subprocess):
tmp_dir_name = "tmp_dir_name"
mocker.patch("tempfile.mkdtemp", return_value=tmp_dir_name)
tmp_file = mocker.patch(
"tempfile.NamedTemporaryFile"
).return_value.__enter__.return_value
shutil_rm_mocker = mocker.patch("shutil.rmtree")
shutil_mv_mocker = mocker.patch("shutil.move")
mock_subprocess.return_value.__enter__.return_value = \
mock_subprocess.return_value
walk_mocker = mocker.patch(
"os.walk",
return_value=[(os.path.join(tmp_dir_name, "path"),
["dir_1", "dir_2"],
["file_1", "file_2"])])
with archivate.update_cpio("fake_img_path.img") as tmp_dir_name_context:
pass
assert tmp_dir_name == tmp_dir_name_context
walk_mocker.assert_called_once_with(tmp_dir_name)
shutil_rm_mocker.assert_called_once_with(tmp_dir_name)
shutil_mv_mocker.assert_called_once_with(
tmp_file.name, "fake_img_path.img")
assert [
mock.call("path/{0}\n".format(i)) for i in
["dir_1", "dir_2", "file_1", "file_2"]
] == mock_subprocess.return_value.stdin.write.call_args_list
assert [
mock.call(
["gunzip", "-c", "fake_img_path.img"],
stdout=subprocess.PIPE),
mock.call(
["cpio", "-id"],
stdin=mock_subprocess.return_value.stdout,
cwd=tmp_dir_name),
mock.call(
["cpio", "--format", "newc", "-o"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd=tmp_dir_name),
mock.call(
["gzip", "-c"],
stdin=mock_subprocess.return_value.stdout,
stdout=tmp_file,
cwd=tmp_dir_name),
] == mock_subprocess.call_args_list
assert not tmp_file.delete

View File

@ -10,9 +10,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import contextlib
import io import io
import itertools
import os import os
import shutil
import tarfile import tarfile
import tempfile
from octane.util import docker from octane.util import docker
from octane.util import subprocess from octane.util import subprocess
@ -63,3 +67,36 @@ def filter_members(archive, dir_name):
for member in archive: for member in archive:
if member.isfile() and member.name.startswith(dir_name): if member.isfile() and member.name.startswith(dir_name):
yield member yield member
@contextlib.contextmanager
def update_cpio(img_path, dir_path=None):
tmp_dir = tempfile.mkdtemp(dir=dir_path)
try:
with subprocess.popen(
["gunzip", "-c", img_path],
stdout=subprocess.PIPE) as proc:
subprocess.call(
["cpio", "-id"], stdin=proc.stdout, cwd=tmp_dir)
yield tmp_dir
tmp_dir_len = len(tmp_dir)
with tempfile.NamedTemporaryFile(dir=dir_path) as new_img:
with subprocess.popen(
["cpio", "--format", "newc", "-o"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd=tmp_dir) as cpio:
with subprocess.popen(
["gzip", "-c"],
stdin=cpio.stdout,
stdout=new_img,
cwd=tmp_dir):
for path, dirs, files in os.walk(tmp_dir):
for name in itertools.chain(dirs, files):
p_name = os.path.join(path, name)[tmp_dir_len + 1:]
cpio.stdin.write("{0}\n".format(p_name))
cpio.stdin.close()
shutil.move(new_img.name, img_path)
new_img.delete = False
finally:
shutil.rmtree(tmp_dir)