@@ -7,6 +7,7 @@
"""Extract and export rootfs tarballs for NFS booting."""
import os
+import signal
import subprocess
import sys
@@ -122,3 +123,124 @@ def extract_sdk_main(argv=None):
print('Error: %s' % exc)
return 1
return 0
+
+
+_NFS_ACTIONS = ('start', 'stop', 'restart')
+
+
+def _nfs_paths(instance):
+ state_dir = os.path.join(os.path.expanduser('~'), '.runqemu-sdk')
+ os.makedirs(state_dir, exist_ok=True)
+ return {
+ 'exports': os.path.join(state_dir, 'exports%s' % instance),
+ 'nfs_pid': os.path.join(state_dir, 'nfs%s.pid' % instance),
+ }
+
+
+def _nfs_ports(instance):
+ nfs_port = int(os.environ.get('NFSD_PORT', 3049 + 2 * instance))
+ mount_port = int(os.environ.get('MOUNTD_PORT', 3048 + 2 * instance))
+ return nfs_port, mount_port
+
+
+def _export_usage():
+ return 'Usage: %s {%s} <nfs-export-dir>' % (
+ sys.argv[0], '|'.join(_NFS_ACTIONS))
+
+
+def export_rootfs(action, rootfs_dir):
+ """Start, stop, or restart the userspace NFS server for *rootfs_dir*."""
+ if action not in _NFS_ACTIONS:
+ raise RunQemuRootfsError("Unknown command '%s'" % action)
+ if not os.path.isdir(rootfs_dir):
+ raise RunQemuRootfsError("'%s' does not exist" % rootfs_dir)
+
+ rootfs_dir = os.path.realpath(rootfs_dir)
+ state_dir = pseudo_state_dir(rootfs_dir)
+ if not os.path.isdir(state_dir):
+ raise RunQemuRootfsError(
+ '%s does not exist.\n'
+ 'Did you create the export directory using runqemu-extract-sdk?' % state_dir)
+
+ if action == 'restart':
+ export_rootfs('stop', rootfs_dir)
+ return export_rootfs('start', rootfs_dir)
+
+ instance = int(os.environ.get('NFS_INSTANCE', '0'))
+ paths = _nfs_paths(instance)
+ if action == 'stop':
+ if os.path.exists(paths['nfs_pid']):
+ print('Stopping rpc.nfsd')
+ with open(paths['nfs_pid']) as pid_file:
+ pid = pid_file.read().strip()
+ try:
+ os.kill(int(pid), signal.SIGTERM)
+ except (ValueError, ProcessLookupError):
+ # A stale PID file must not stop the cleanup below.
+ print('rpc.nfsd is not running')
+ os.unlink(paths['nfs_pid'])
+ else:
+ print('No PID file, not stopping rpc.nfsd')
+ if os.path.exists(paths['exports']):
+ print('Removing exports file')
+ os.unlink(paths['exports'])
+ return
+
+ environment = native_environment()
+ native_sysroot = environment.get('OECORE_NATIVE_SYSROOT')
+ pseudo = environment.get('PSEUDO')
+ if not native_sysroot or not pseudo:
+ raise RunQemuRootfsError('qemu-helper-native did not provide pseudo')
+
+ unfsd = os.path.join(native_sysroot, 'usr', 'bin', 'unfsd')
+ if not os.path.exists(unfsd):
+ raise RunQemuRootfsError(
+ 'Unable to find unfsd binary in %s/usr/bin/\n'
+ "This shouldn't happen - something is missing from your toolchain installation"
+ % native_sysroot)
+
+ nfs_port, mount_port = _nfs_ports(instance)
+ environment['PSEUDO_LOCALSTATEDIR'] = state_dir
+ with open(paths['exports'], 'w') as exports_file:
+ exports_file.write('%s (rw,no_root_squash,no_all_squash,insecure)\n' % rootfs_dir)
+
+ command = [pseudo, '-P', os.path.join(native_sysroot, 'usr'), unfsd,
+ '-p', '-i', paths['nfs_pid'], '-e', paths['exports'],
+ '-n', str(nfs_port), '-m', str(mount_port)]
+ print('Creating exports file...')
+ print('Starting User Mode nfsd')
+ print(' %s' % ' '.join(command))
+ try:
+ subprocess.run(command, env=environment, check=True)
+ except subprocess.CalledProcessError as exc:
+ raise RunQemuRootfsError('Error starting nfsd') from exc
+
+ if not os.path.exists(paths['nfs_pid']):
+ raise RunQemuRootfsError('rpc.nfsd did not start correctly')
+ with open(paths['nfs_pid']) as pid_file:
+ try:
+ os.kill(int(pid_file.read()), 0)
+ except OSError as exc:
+ raise RunQemuRootfsError('rpc.nfsd did not start correctly') from exc
+
+ print('')
+ print('On your target please remember to add the following options for NFS')
+ print('nfsroot=IP_ADDRESS:%s,nfsvers=3,port=%s,udp,mountport=%s' %
+ (rootfs_dir, nfs_port, mount_port))
+
+
+def export_rootfs_main(argv=None):
+ argv = sys.argv[1:] if argv is None else argv
+ if len(argv) != 2:
+ print(_export_usage())
+ return 1
+ if argv[0] not in _NFS_ACTIONS:
+ print("Unknown command '%s'" % argv[0])
+ print(_export_usage())
+ return 1
+ try:
+ export_rootfs(*argv)
+ except RunQemuRootfsError as exc:
+ print('Error: %s' % exc)
+ return 1
+ return 0
@@ -1,127 +1,13 @@
-#!/bin/bash
-#
-# Copyright (c) 2005-2009 Wind River Systems, Inc.
+#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-only
-#
-usage() {
- echo "Usage: $0 {start|stop|restart} <nfs-export-dir>"
-}
+import os
+import sys
-if [ $# != 2 ]; then
- usage
- exit 1
-fi
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib'))
-if [[ "$1" != "start" && "$1" != "stop" && "$1" != "restart" ]]; then
- echo "Unknown command '$1'"
- usage
- exit 1
-fi
+from runqemu_utils import export_rootfs_main
-if [ ! -d "$2" ]; then
- echo "Error: '$2' does not exist"
- usage
- exit 1
-fi
-# Ensure the nfs-export-dir is an absolute path
-NFS_EXPORT_DIR=$(cd "$2" && pwd)
-SYSROOT_SETUP_SCRIPT=`which oe-find-native-sysroot 2> /dev/null`
-if [ -z "$SYSROOT_SETUP_SCRIPT" ]; then
- echo "Error: Unable to find the oe-find-native-sysroot script"
- echo "Did you forget to source your build environment setup script?"
- exit 1
-fi
-. $SYSROOT_SETUP_SCRIPT qemu-helper-native
-
-if [ ! -e "$OECORE_NATIVE_SYSROOT/usr/bin/unfsd" ]; then
- echo "Error: Unable to find unfsd binary in $OECORE_NATIVE_SYSROOT/usr/bin/"
-
- echo "This shouldn't happen - something is missing from your toolchain installation"
- exit 1
-fi
-
-if [ ! -d ~/.runqemu-sdk ]; then
- mkdir -p ~/.runqemu-sdk
-fi
-
-NFS_INSTANCE=${NFS_INSTANCE:=0}
-EXPORTS=~/.runqemu-sdk/exports$NFS_INSTANCE
-RMTAB=~/.runqemu-sdk/rmtab$NFS_INSTANCE
-NFSPID=~/.runqemu-sdk/nfs$NFS_INSTANCE.pid
-MOUNTPID=~/.runqemu-sdk/mount$NFS_INSTANCE.pid
-
-PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr"
-PSEUDO_LOCALSTATEDIR="$NFS_EXPORT_DIR/../$(basename $NFS_EXPORT_DIR).pseudo_state"
-export PSEUDO_LOCALSTATEDIR
-
-if [ ! -d "$PSEUDO_LOCALSTATEDIR" ]; then
- echo "Error: $PSEUDO_LOCALSTATEDIR does not exist."
- echo "Did you create the export directory using runqemu-extract-sdk?"
- exit 1
-fi
-
-# NFS server port number
-NFSD_PORT=${NFSD_PORT:=$[ 3049 + 2 * $NFS_INSTANCE ]}
-# mountd port number
-MOUNTD_PORT=${MOUNTD_PORT:=$[ 3048 + 2 * $NFS_INSTANCE ]}
-
-## For debugging you would additionally add
-## --debug all
-UNFSD_OPTS="-p -i $NFSPID -e $EXPORTS -n $NFSD_PORT -m $MOUNTD_PORT"
-
-# See how we were called.
-case "$1" in
- start)
- echo "Creating exports file..."
- echo "$NFS_EXPORT_DIR (rw,no_root_squash,no_all_squash,insecure)" > $EXPORTS
-
- echo "Starting User Mode nfsd"
- echo " $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/bin/unfsd $UNFSD_OPTS"
- $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/bin/unfsd $UNFSD_OPTS
- if [ ! $? = 0 ]; then
- echo "Error starting nfsd"
- exit 1
- fi
- # Check to make sure everything started ok.
- if [ ! -f $NFSPID ]; then
- echo "rpc.nfsd did not start correctly"
- exit 1
- fi
- ps -fp `cat $NFSPID` > /dev/null 2> /dev/null
- if [ ! $? = 0 ]; then
- echo "rpc.nfsd did not start correctly"
- exit 1
- fi
- echo " "
- echo "On your target please remember to add the following options for NFS"
- echo "nfsroot=IP_ADDRESS:$NFS_EXPORT_DIR,nfsvers=3,port=$NFSD_PORT,udp,mountport=$MOUNTD_PORT"
- ;;
- stop)
- if [ -f "$NFSPID" ]; then
- echo "Stopping rpc.nfsd"
- kill `cat $NFSPID`
- rm -f $NFSPID
- else
- echo "No PID file, not stopping rpc.nfsd"
- fi
- if [ -f "$EXPORTS" ]; then
- echo "Removing exports file"
- rm -f $EXPORTS
- fi
- ;;
- restart)
- $0 stop $NFS_EXPORT_DIR
- $0 start $NFS_EXPORT_DIR
- if [ ! $? = 0 ]; then
- exit 1
- fi
- ;;
- *)
- echo "$0 {start|stop|restart} <nfs-export-dir>"
- ;;
-esac
-
-exit 0
+sys.exit(export_rootfs_main())