Browse Source

Add qemu hook to set correct VLAN of bridge VM interfaces if desired.

  Vlan-Aware-Bridges for the win!

Signed-off-by: Maximilian Wilhelm <max@rfc2324.org>
Maximilian Wilhelm 7 years ago
parent
commit
a3e78fad0e
2 changed files with 87 additions and 0 deletions
  1. 17 0
      kvm/init.sls
  2. 70 0
      kvm/qemu-hook

+ 17 - 0
kvm/init.sls

@@ -0,0 +1,17 @@
+#
+# KVM host
+#
+
+virt-pkgs:
+  pkg.installed:
+    - pkgs:
+      - qemu-kvm
+      - libvirt-bin
+      - xmlstarlet
+
+/etc/libvirt/hooks/qemu:
+  file.managed:
+    - source: salt://kvm/qemu-hook
+    - mode: 755
+    - require:
+      - pkg: virt-pkgs

+ 70 - 0
kvm/qemu-hook

@@ -0,0 +1,70 @@
+#!/bin/sh -e
+#
+# Libvirt qemu hook to magically connect VM bridge interfaces to desired untagged Vlan
+#
+#  IF
+#   * the VM interface if configured to be connected to a bridge,
+#   * the bridge is configured to be vlan aware (vlan_filtering = 1)
+#   * the VM interface name ends with _vXXXX with XXXX being a one to four
+#     digit number
+#  the interface will be configured as an untagged port connected to vlan XXXX.
+#
+#  See <man bridge> for more details about vlan aware bridges.
+#
+# Maximilian Wilhelm <max@sdn.clinic>
+#  -- Wed, 31 Aug 2016 20:48:02 +0200
+
+my_name="qemu-magic"
+
+# We only care for the "started" event.
+if [ "$2" != 'started' ]; then
+	exit 0
+fi
+
+if ! which xmlstarlet >/dev/null 2>/dev/null; then
+	logger -t "${my_name}" "ERROR: xmlstarlet not found. Dying of shame."
+	echo "${my_name}: ERROR: xmlstarlet not found. Dying of shame." >&2
+	exit 1
+fi
+
+xmlstarlet sel -t -m '//interface[@type="bridge"]' -v 'concat(target/@dev, " ", source/@bridge)'  --nl | while read iface bridge; do
+	if [ ! -d "/sys/class/net/${bridge}/bridge" ]; then
+		logger -t "${my_name}" "Bridge \"${bridge}\" for iface \"${iface}\" doesn't exist or isn't a bridge."
+		exit 2
+	fi
+
+	# If this kernel does not support vlan-aware bridges there's nothing to be done here.
+	if [ ! -f "/sys/class/net/${bridge}/bridge/vlan_filtering" ]; then
+		continue
+	fi
+
+	# If this bridge isn't configured to be vlan-aware, there's nothing to be done here either.
+	vlan_filtering=$(cat "/sys/class/net/${bridge}/bridge/vlan_filtering")
+	if [ "${vlan_filtering}" = 0 ]; then
+		continue
+	fi
+
+	# If the interface is named *_vXXXX, with X being a 1-4 digit number
+	# we assume that this is iface should be connected to Vlan XXXX with
+	# an untagged port.
+	vlan_id=$(echo ${iface} | grep -o '_v[0-9]\{1,4\}$' | cut -c3-)
+	if [ "${vlan_id}" ]; then
+		# Remove association with vlan 1 and add association with
+		# vlan $vlan_id with packages being sent out untagged and
+		# untagged ingress packets get tagged accordingly.
+		bridge vlan del vid 1 dev "${iface}"
+		bridge vlan add vid "${vlan_id}" dev "${iface}" pvid untagged
+		logger -t "${my_name}" "Configured untagged pvid ${vlan_id} for ${iface} in bridge ${bridge}."
+
+
+	# If the interface doesn't suggest an untagged Vlan association go
+	# for an /etc/network/interface entry which we try to get up and
+	# running with ifup. Proceed with fingers crossed.
+	else
+		if ifup $iface; then
+			logger -t qemu-magic "ifup'ed ${iface}."
+		else
+			logger -t qemu-magic "ifup ${iface} FAILED."
+		fi
+	fi
+done