Skip to content

Commit

Permalink
Initial version for public
Browse files Browse the repository at this point in the history
  • Loading branch information
mark committed May 24, 2018
0 parents commit 3841392
Show file tree
Hide file tree
Showing 11 changed files with 597 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.img
*.zip
tmpmnt/
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# qemu-raspbian-network
Launch Raspberry Pi image using QEMU and provision from scripts.

```
git clone https://github.com/salty-vagrant/qemu-pi.git
cd qemu-pi
wget https://downloads.raspberrypi.org/raspbian_lite_latest -O raspbian_lite_latest.zip
unzip raspbian_lite_latest.zip
sudo ./qemu-pi <image file unzipped above>
```

Note that it is recommended to use `qemu-arm` not older than 2.8.0 (a warning is issued if your QEMU is out of date)
Binary file added kernel-qemu-4.4.34-jessie
Binary file not shown.
132 changes: 132 additions & 0 deletions lib/host_network.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/bin/bash

restore_qemu_up_down_scripts() {
echo " Restoring QEMU up/down scripts"
test -f /etc/qemu-ifup.bak && cp -nav /etc/qemu-ifup.bak /etc/qemu-ifup
test -f /etc/qemu-ifdown.bak && cp -nav /etc/qemu-ifdown.bak /etc/qemu-ifdown
}

qemu_up_down_scripts() {
echo " Configuring QEMU up/down scripts"
test -f /etc/qemu-ifup && cp -nav /etc/qemu-ifup /etc/qemu-ifup.bak
test -f /etc/qemu-ifdown && cp -nav /etc/qemu-ifdown /etc/qemu-ifdown.bak

prefix_trap "restore_qemu_up_down_scripts" EXIT

cat > /etc/qemu-ifup <<EOF
#!/bin/sh
echo "Executing /etc/qemu-ifup"
echo "Bringing up \$1 for bridged mode..."
sudo $BINARY_PATH/ip link set \$1 up promisc on
echo "Adding \$1 to $BRIDGE..."
sudo $BINARY_PATH/brctl addif $BRIDGE \$1
sleep 2
EOF

cat > /etc/qemu-ifdown <<EOF
#!/bin/sh
echo "Executing /etc/qemu-ifdown"
sudo $BINARY_PATH/ip link set \$1 down
sudo $BINARY_PATH/brctl delif $BRIDGE \$1
sudo $BINARY_PATH/ip link delete dev \$1
EOF

chmod 750 /etc/qemu-ifdown /etc/qemu-ifup
chown root:kvm /etc/qemu-ifup /etc/qemu-ifdown

}

restore_ip_forwarding() {
echo " Restoring ip forwarding"
sysctl net.ipv4.ip_forward=${IPFW} >/dev/null
}

set_ip_forwarding() {
IPFW=$( sysctl net.ipv4.ip_forward | cut -d= -f2 | xargs)
echo " Setting ip forwarding"
prefix_trap "restore_ip_forwarding" EXIT
sysctl net.ipv4.ip_forward=1 >/dev/null
}


remove_bridge_device() {
echo " Removing bridge device $BRIDGE"
brctl delbr $BRIDGE
}

tear_down_bridge() {
echo " Tearing down bridge dev $BRIDGE"
echo " Removing $IFACE interface from bridge $BRIDGE"
brctl delif $BRIDGE $IFACE
ip link set down dev $BRIDGE
# This is a bit brutal. Should really use DHCP if that's how the IF is configured and the IP is lost
echo " Restore IP (${IP}) to ${IFACE}"
ip address add $IP dev $IFACE
}

setup_bridge_dev() {
echo " Creating new bridge: $BRIDGE..."
brctl addbr $BRIDGE
prefix_trap "remove_bridge_device" EXIT
echo " Adding $IFACE interface to bridge $BRIDGE"
brctl addif $BRIDGE $IFACE
echo " Setting link up for: $BRIDGE"
ip link set up dev $BRIDGE
prefix_trap "tear_down_bridge" EXIT
echo " Adding IP address to bridge: $BRIDGE"
ip address add $IP dev $BRIDGE
}

restore_routes() {
echo " Restoring routes..."
echo " Flush routes on bridge dev $BRIDGE"
ip route flush dev $BRIDGE
echo " Flush routes on dev $IFACE"
ip route flush dev $IFACE
echo " Rewriting $IFACE routes"
echo "$ROUTES" | tac | while read l; do ip route add $l; done
}

setup_routes() {
echo " Setting up new routes..."
echo " Getting routes for interface: $IFACE"
ROUTES=$( ip route | grep $IFACE )
echo " Changing those routes to bridge interface: $BRIDGE"
BRROUT=$( echo "$ROUTES" | sed "s=$IFACE=$BRIDGE=" )
echo " Flushing routes to interface: $IFACE"
prefix_trap "restore_routes" EXIT
ip route flush dev $IFACE
echo " Adding routes to bridge: $BRIDGE"
echo "$BRROUT" | tac | while read l; do ip route add $l; done
echo " Routes to bridge $BRIDGE added"
}


teardown_tap_dev() {
# Under normal circumstances this is done by the qemuif-down script
# this is just a precaution against abnormal shutdown
echo " Tearing down tap dev $TAPIF"
ip link set down dev $TAPIF 2>/dev/null
ip tuntap del $TAPIF mode tap 2>/dev/null
}

setup_tap_dev() {
echo " Setting up tap device"
precreationg=$(ip tuntap list | cut -d: -f1 | sort)
ip tuntap add user $USER mode tap
postcreation=$(ip tuntap list | cut -d: -f1 | sort)
TAPIF=$(comm -13 <(echo "$precreationg") <(echo "$postcreation"))
prefix_trap "teardown_tap_dev" EXIT
}


setup_host_network() {
echo "Setting up host network"
qemu_up_down_scripts
set_ip_forwarding
setup_bridge_dev
setup_routes
setup_tap_dev
prefix_trap 'echo "Restoring host network..."' EXIT
}

117 changes: 117 additions & 0 deletions lib/pi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/bin/bash
# Various routines to mangle the Raspberry pi image

mount_image_partition() {
local _image="$1"
local _partName=$2
local _mountpoint="$3"

local _sector=$( fdisk -l "${_image}" | grep ${_partName} | awk '{ print $2 }' )
local _offset=$(( ${_sector} * 512 ))

[ ! -d "${_mountpoint}" ] && mkdir -p "${_mountpoint}"
mount "${_image}" -o offset=${_offset} "${_mountpoint}"
}

# SSH
# The pi image uses a simple file 'ssh' in the boot sector to indicate
# that the SSH daemon should be started. This is a convenience and only applies
# to the Raspbian images.
turn_off_ssh() {
local _image="$1"

echo " Disabling SSH"

[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

mount_image_partition "${_image}" FAT32 tmpmnt
rm -f tmpmnt/ssh
umount tmpmnt

rmdir tmpmnt
}

turn_on_ssh() {
local _image="$1"

echo " Enabling SSH"

[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

[[ "$NO_SSH" == "1" ]] && prefix_trap "turn_off_ssh ${_image}" EXIT
mount_image_partition "${_image}" FAT32 tmpmnt
touch tmpmnt/ssh
umount tmpmnt

rmdir tmpmnt
}

remove_drive_remapping() {
local _image="$1"

echo " Removing drive remapping"

[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

mount_image_partition "${_image}" Linux tmpmnt
rm -f tmpmnt/etc/udev/rules.d/90-qemu.rules
umount tmpmnt
rmdir tmpmnt
}

add_drive_remapping() {
local _image="$1"

echo " Adding drive remapping"

prefix_trap "remove_drive_remapping ${_image}" EXIT

[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

mount_image_partition "${_image}" Linux tmpmnt
cat > tmpmnt/etc/udev/rules.d/90-qemu.rules <<EOF
KERNEL=="sda", SYMLINK+="mmcblk0"
KERNEL=="sda?", SYMLINK+="mmcblk0p%n"
KERNEL=="sda2", SYMLINK+="root"
EOF

umount tmpmnt
rmdir tmpmnt
}

remove_qemu_arm_patch() {
echo " Removing QEMU ARM patch"
[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

mount_image_partition "${_image}" Linux tmpmnt
sed -i '/^#.*libarmmem.so/s/^#\(.*\)$/\1/' tmpmnt/etc/ld.so.preload

umount tmpmnt
rmdir tmpmnt
}

# Work around a known issue with qemu-arm, versatile board and raspbian for at least qemu-arm < 2.8.0
# This works but modifies the image so it is recommended to upgrade QEMU
# Ref: http://stackoverflow.com/questions/38837606/emulate-raspberry-pi-raspbian-with-qemu
apply_qemu_arm_patch() {
local _image=$1

local _qemu_version=$( qemu-system-arm --version | grep -oP '\d+\.\d+\.\d+' )
local _qemu_major=$( echo ${_qemu_version} | head -1 | cut -d. -f1 )
local _qemu_minor=$( echo ${_qemu_version} | head -1 | cut -d. -f2 )

[ $_qemu_major -gt 2 ] && echo " QEMU version (${_qemu_version}) > 2, no ARM patch required" && return
[ $_qemu_major -eq 2 ] && [ $_qemu_minor -le 8 ] && echo " QEMU version (${_qemu_version}) >= 2.8, no ARM patch required" && return

echo " Applying QEMU ARM patch"
echo " (It is recommended that you update your QEMU to the latest version)"
prefix_trap "remove_qemu_arm_patch ${_image}" EXIT

[ ! -d "tmpmnt" ] && mkdir -p "tmpmnt"

mount_image_partition "${_image}" Linux tmpmnt
sed -i '/^[^#].*libarmmem.so/s/^\(.*\)$/#\1/' tmpmnt/etc/ld.so.preload

umount tmpmnt
rmdir tmpmnt
}
29 changes: 29 additions & 0 deletions lib/processes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
# Kudos to http://stas-blogspot.blogspot.co.uk/2010/02/kill-all-child-processes-from-shell.html for inspiring this.

kill_child_processes() {
local _curPid=$1
local _signal=${2:-SIGHUP}
local _isTopmost=${3:-1}

local _childPids=`ps -o pid --no-headers --ppid ${_curPid}`

for childPid in ${_childPids}
do
kill_child_processes ${childPid} ${_signal} 0
done

if [ ${_isTopmost} -eq 0 ]; then
kill -{$_signal} ${_curPid} 2> /dev/null
fi
}


kill_process_tree() {
local _pid=$1
local _signal=${2:-SIGHUP}

kill_child_processes ${_pid} ${_signal}

kill -{$_signal} ${_pid} 2> /dev/null
}
Loading

0 comments on commit 3841392

Please sign in to comment.