Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standalone #31

Merged
merged 18 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions centos-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
python34
python34-devel
python34-pip
python36
python36-devel
python36-pip
rsync
libguestfs-tools
39 changes: 22 additions & 17 deletions full_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ LOGNAME=$(mktemp results_full_test.XXXX)

echo "Running Full Test. Results available in $LOGNAME"

# We pre-build to avoid potential timeouts on a fresh clone
echo "Pre-building base workloads" | tee -a $LOGNAME
./marshal build test/br-base.json
./marshal build test/fedora-base.json

echo "Running launch timeout test (should timeout):" | tee -a $LOGNAME
echo "This test will reset your terminal"
./marshal test test/timeout-run.json | grep "timeout while running"
Expand All @@ -30,23 +35,6 @@ else
echo "Success" | tee -a $LOGNAME
fi

# Run the specialized tests (tests that are too complicated for ./marshal
# test)
echo "Running clean test" | tee -a $LOGNAME
./test/clean/test.py >> $LOGNAME
if [ ${PIPESTATUS[0]} != 0 ]; then
echo "Failure" | tee -a $LOGNAME
SUITE_PASS=false
fi

echo "Running incremental test" | tee -a $LOGNAME
./test/incremental/test.py >> $LOGNAME
if [ ${PIPESTATUS[0]} != 0 ]; then
echo "Failure" | tee -a $LOGNAME
SUITE_PASS=false
exit 1
fi

# Run the bulk tests (all work with the 'test' command)
# Note the funny extended globbing, these are just lists of tests that
# shouldn't be tested (e.g. we exclude the base configs and some specialized
Expand Down Expand Up @@ -77,6 +65,23 @@ else
echo "Success" | tee -a $LOGNAME
fi

# Run the specialized tests (tests that are too complicated for ./marshal
# test)
echo "Running clean test" | tee -a $LOGNAME
./test/clean/test.py >> $LOGNAME
if [ ${PIPESTATUS[0]} != 0 ]; then
echo "Failure" | tee -a $LOGNAME
SUITE_PASS=false
fi

echo "Running incremental test" | tee -a $LOGNAME
./test/incremental/test.py >> $LOGNAME
if [ ${PIPESTATUS[0]} != 0 ]; then
echo "Failure" | tee -a $LOGNAME
SUITE_PASS=false
exit 1
fi

echo -e "\n\nMarshal full test complete. Log at: $LOGNAME"
if [ $SUITE_PASS = false ]; then
echo "FAILURE: Some tests failed" | tee -a $LOGNAME
Expand Down
5 changes: 3 additions & 2 deletions marshal
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import os
import logging
import wlutil
import contextlib
import shutil

if 'RISCV' not in os.environ:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't depend on this variable anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never depended on it explicitly. I was just using it as a proxy to detect if you'd sourced sourcme. In reality, we just depend on the riscv toolchain. I just added back a check for that instead.

sys.exit("Please source firesim/sourceme-manager-f1.sh first\n")
if not shutil.which('riscv64-unknown-linux-gnu-gcc'):
sys.exit("No riscv toolchain detected. Please install riscv-tools.")

# Delete a file but don't throw an exception if it doesn't exist
def deleteSafe(pth):
Expand Down
2 changes: 1 addition & 1 deletion wlutil/fedora/convert_raw.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ DD_BS=1048576

# Get the offset of the first partition within the image so we can strip it out
# output of parted looks like "###B ####B ###B ..." we cast it to an array here
PART_INFO=(`sudo parted -s $RAWIMG unit B print | tail -2`)
PART_INFO=(`parted -s $RAWIMG unit B print | tail -2`)

# The output at index 1 and 2 are the partition start and end byte offset. The : : -1 strips the "B" suffix.
# Also convert to units of 1MB blocks (I'd do that above, but parted output is weird)
Expand Down
8 changes: 7 additions & 1 deletion wlutil/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from .wlutil import *

# firesim workloads directory
fsWork = (Path(root_dir) / "../../deploy/workloads").resolve()
try:
fsWork = (Path(root_dir) / "../../deploy/workloads").resolve()
except:
fsWork = None

readmeTxt="""This workload was generated using firesim-software. See the following config
and workload directory for details:
Expand All @@ -18,6 +21,9 @@ def fullRel(base, target):
return os.path.relpath(str(target), start=str(base))

def installWorkload(cfgName, cfgs):
if fsWork == None:
raise RuntimeError("The install command is not supported when firesim-software is checked out standalone (i.e. not a submodule of firesim).")

targetCfg = cfgs[cfgName]
# if 'jobs' in targetCfg:
# raise NotImplementedError("Jobs not currently supported by the install command")
Expand Down
71 changes: 27 additions & 44 deletions wlutil/wlutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import sys
import collections
import shutil
import psutil
import errno
from contextlib import contextmanager

wlutil_dir = os.path.normpath(os.path.dirname(__file__))
Expand Down Expand Up @@ -128,59 +130,40 @@ def genRunScript(command):

return commandScript

# XXX This isn't working with the initramfs option. Go back to requiring sudo
# for now, I'll revisit later.

# Frustratingly, the same commands don't work/exist on various platforms so we
# need to figure out what mounting options are available to us:
# if shutil.which('guestmount') is not None:
# # This is the preferred method because it doesn't require sudo
# @contextmanager
# def mountImg(imgPath, mntPath):
# run(['guestmount', '-a', imgPath, '-m', '/dev/sda', mntPath])
# try:
# yield mntPath
# finally:
# run(['guestunmount', mntPath])
#
# elif shutil.whcih('fuse-ext2') is not None:
# # Roughly the same as guestmount
# @contextmanager
# def mountImg(imgPath, mntPath):
# run(['fuse-ext2', '-o', 'rw+', imgPath, mntPath])
# try:
# yield mntPath
# finally:
# run(['fusermount', '-u', mntPath])
#
# elif shutil.which('mount') is not None:
# # if True:
# # Should be available everywhere, requires sudo
# @contextmanager
# def mountImg(imgPath, mntPath):
# run(['sudo', 'mount', '-o', 'loop', imgPath, mntPath])
# try:
# yield mntPath
# finally:
# run(['sudo', 'umount', mntPath])
#
# else:
# raise ImportError("No compatible 'mount' command found")
# This is like os.waitpid, but it works for non-child processes
def waitpid(pid):
done = False
while not done:
try:
os.kill(pid, 0)
except OSError as err:
if err.errno == errno.ESRCH:
done = True
break
time.sleep(0.25)

@contextmanager
def mountImg(imgPath, mntPath):
run(['sudo', 'mount', '-o', 'loop', imgPath, mntPath])
run(['guestmount', '--pid-file', 'guestmount.pid', '-a', imgPath, '-m', '/dev/sda', mntPath])
try:
with open('./guestmount.pid', 'r') as pidFile:
mntPid = int(pidFile.readline())
yield mntPath
finally:
run(['sudo', 'umount', mntPath])
run(['guestunmount', mntPath])
os.remove('./guestmount.pid')

# There is a race-condition in guestmount where a background task keeps
# modifying the image for a period after unmount. This is the documented
# best-practice (see man guestmount).
waitpid(mntPid)

def toCpio(config, src, dst):
log = logging.getLogger()

with mountImg(src, mnt):
# Fedora needs a special init in order to boot from initramfs
run("sudo find -print0 | sudo cpio --owner root:root --null -ov --format=newc > " + dst, shell=True, cwd=mnt)
run("find -print0 | cpio --owner root:root --null -ov --format=newc > " + dst, shell=True, cwd=mnt)

# Ideally, the distro's themselves would provide initramfs-based versions.
# However, having two codepaths for disk images and cpio archives
Expand Down Expand Up @@ -210,13 +193,13 @@ def copyImgFiles(img, files, direction):
with mountImg(img, mnt):
for f in files:
# Overlays may not be owned by root, but the filesystem must be.
# Rsync lets us chown while copying.
# The FUSE mount automatically handles the chown from root to user
# Note: shell=True because f.src is allowed to contain globs
# Note: os.path.join can't handle overlay-style concats (e.g. join('foo/bar', '/baz') == '/baz')
if direction == 'in':
run('sudo rsync -a --chown=root:root ' + f.src + " " + os.path.normpath(mnt + f.dst), shell=True)
run('cp -a ' + f.src + " " + os.path.normpath(mnt + f.dst), shell=True)
elif direction == 'out':
uid = os.getuid()
run('sudo rsync -a --chown=' + str(uid) + ':' + str(uid) + ' ' + os.path.normpath(mnt + f.src) + " " + f.dst, shell=True)
run('cp -a ' + os.path.normpath(mnt + f.src) + " " + f.dst, shell=True)
else:
raise ValueError("direction option must be either 'in' or 'out'")