Assuming you have a virtual machine on a disk image that you want to run in qemu such that:
- the target can access the network at large from inside the target
- you can access the target's network from the host
- you don't want to assign a static IP within the image itself but you want to be able to flexibly set up the image on any sort of network (class A, class B, class C) with any IP address without having to make changes to the image itself
here are some notes on how to go about accomplishing these goals.
$ qemu-img create -f qcow2 myimage.qcow2 200G
- install your favourite distribution into the disk file
$ qemu-system-x86_64 \
-enable-kvm \
-smp 2 \
-cpu host \
-m 4096 \
-drive file=/.../myimage.qcow2,if=virtio \
-net nic,model=virtio \
-net user \
-cdrom /.../openSUSE-Tumbleweed-NET-x86_64-Snapshot20150126-Media.iso
$ qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-smp 6 \
-m 4096 \
-net nic,model=virtio \
-net user \
-drive file=/.../myimage.qcow2 \
-nographic
- tweak it to your preferences
edit /etc/default/grub, edit GRUB_CMDLINE_LINUX_DEFAULT:
to add
" console=ttyS0,115200"
to remove
"splash=silent quiet"
# grub2-mkconfig -o /boot/grub2/grub.cfg
configure /tmp for tmpfs, add the following to /etc/fstab:
none /tmp tmpfs defaults,noatime 0 0
$ qemu-img snapshot -c afterInstallAndConfig myimage.qcow2
- create a configuration file named CONFIG
checkenv() {
if [ -z "${!1}" ]; then
echo "required env var '$1' not defined"
exit 1
fi
}
findcmd() {
which $1 > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "can't find required binary: '$1'"
exit 1
fi
}
MACADDR=DE:AD:BE:EF:00:01
USERID=trevor
GROUPID=users
IPBASE=192.168.8.
HOSTIP=${IPBASE}1
- create a "super script" called start_vm
#!/bin/bash
if [ $# -ne 1 ]; then
echo "usage: $(basename $0) <image>"
exit 1
fi
source CONFIG
checkenv MACADDR
checkenv USERID
checkenv GROUPID
checkenv IPBASE
THISDIR=$(pwd)
IMAGE=$1
TAPDEV=$(sudo $THISDIR/qemu-ifup)
if [ $? -ne 0 ]; then
echo "qemu-ifup failed"
exit 1
fi
echo "tap device: $TAPDEV"
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-smp sockets=1,cores=2,threads=2 \
-m 4096 \
-drive file=$IMAGE,if=virtio \
-net nic,model=virtio,macaddr=$MACADDR \
-net tap,ifname=$TAPDEV,script=no,downscript=no \
-nographic
sudo $THISDIR/qemu-ifdown $TAPDEV
- create an "up" script called qemu-ifup
#!/bin/bash
source CONFIG
usage() {
echo "sudo $(basename $0)"
}
checkenv USERID
checkenv GROUPID
checkenv IPBASE
checkenv HOSTIP
findcmd tunctl
findcmd ip
findcmd iptables
findcmd dnsmasq
if [ $EUID -ne 0 ]; then
echo "Error: This script must be run with root privileges"
exit 1
fi
if [ $# -ne 0 ]; then
usage
exit 1
fi
TAPDEV=$(tunctl -b -u $USERID -g $GROUPID 2>&1)
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "tunctl failed:"
exit 1
fi
ip addr add $HOSTIP/32 broadcast ${IPBASE}255 dev $TAPDEV
ip link set dev $TAPDEV up
ip route add ${IPBASE}0/24 dev $TAPDEV
# setup NAT for tap$n interface to have internet access in QEMU
iptables -t nat -A POSTROUTING -j MASQUERADE -s ${IPBASE}0/24
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/$TAPDEV/proxy_arp
iptables -P FORWARD ACCEPT
# startup dnsmasq
dnsmasq \
--strict-order \
--except-interface=lo \
--interface=$TAPDEV \
--listen-address=$HOSTIP \
--bind-interfaces \
-d \
-q \
--dhcp-range=${TAPDEV},${IPBASE}5,${IPBASE}20,255.255.255.0,${IPBASE}255 \
--conf-file="" \
> dnsmasq.log 2>&1 &
echo $! > dnsmasq.pid
echo $TAPDEV
exit 0
- create a "down" script called qemu-ifdown
#!/bin/bash
source CONFIG
checkenv IPBASE
findcmd tunctl
findcmd iptables
usage() {
echo "sudo $(basename $0) <tap-dev>"
}
if [ $EUID -ne 0 ]; then
echo "Error: This script (runqemu-ifdown) must be run with root privileges"
exit 1
fi
if [ $# -ne 1 ]; then
usage
exit 1
fi
TAPDEV=$1
tunctl -d $TAPDEV
# cleanup the remaining iptables rules
iptables -t nat -D POSTROUTING -j MASQUERADE -s ${IPBASE}0/24
# kill dnsmasq
if [ -f dnsmasq.pid ]; then
kill $(cat dnsmasq.pid)
rm -f dnsmasq.pid
rm -f dnsmasq.log
fi
This setup is driven by the CONFIG file and the start_vm script. Edit CONFIG to your liking, then run start_vm specifying your image file.
No comments:
New comments are not allowed.