Home > LiNuX (based on debian), Networking, Trouble-Shooting > Send Ethernet bonding Status Change to KVM Guest

Send Ethernet bonding Status Change to KVM Guest

Test Environment

KVM Host
Debian buster 10.8 – with 2 ethernets (eno1 & eno2) bonded (as bond0) and bridged (as br0)

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 10 (buster)
Release: 10
Codename: buster

KVM Guest

Windows Server 2016 Standard Edition

with ethernet connected to br0 (KVM Host)

Create Main Script

vim /root/bin/bonding_status

#!/bin/bash
#
# 210428 LQman: create script to monitor physical link status on eno1 & eno2
#               add log only when change status
#

# debugging purpose only
#set -x

SCRIPTNAME=$(basename $0)
LOG="/tmp/${SCRIPTNAME}.log"

# clear log
cat /dev/null > ${LOG}

# function
output () {
  echo $*
  echo $* >> ${LOG}
}

# check script argument(s)
if [ $# -lt 2 ]; then
  output "script need 2 interface name to run correctly"
  output "for example interfaces are eno1 eno2"
  output "./$SCRIPTNAME eno1 eno2"
  exit 1
fi

# invinite loop
while [ TRUE ]; do
  DATE=`date +%Y-%m-%d`
  TIME=`date +%H:%M:%S`
  # check interface link status using mii-tool
  IF1_LINK_STATUS=`mii-tool $1 | grep "link ok"`
  IF2_LINK_STATUS=`mii-tool $2 | grep "link ok"`

  # map link status to value 0/1
  if [[ ! -z ${IF1_LINK_STATUS} ]]; then
    IF1_VALUE=1
  else
    IF1_VALUE=0
  fi

  if [[ ! -z ${IF2_LINK_STATUS} ]]; then
    IF2_VALUE=1
  else
    IF2_VALUE=0
  fi

  # sum all value
  TOTAL_VALUE=$(($IF1_VALUE + $IF2_VALUE))
  #output "Total Connected Interface = ${TOTAL_VALUE}"

  # list all VM within KVM Host
  declare -a VMS=(`virsh list --all | grep running | awk '{print $2}'`)

  # choose action
  case ${TOTAL_VALUE} in
    0) for VM in ${VMS[@]}; do
         VNET_DEV=`virsh domiflist ${VM} | grep br0 | awk '{print $1}'`
         VNET_STATUS=`virsh domif-getlink ${VM} ${VNET_DEV} | awk '{print $2}'`
         if [[ "${VNET_STATUS}" == "up" ]]; then
           output "[${DATE} ${TIME}] change ${VNET_DEV} link on ${VM} : UP -> DOWN"
           virsh domif-setlink ${VM} ${VNET_DEV} down >> ${LOG} 2>&1
         #else
         #  output "${VNET_DEV} on ${VM} already DOWN"
         fi
       done
       ;;
    *) for VM in ${VMS[@]}; do
         VNET_DEV=`virsh domiflist ${VM} | grep br0 | awk '{print $1}'`
         VNET_STATUS=`virsh domif-getlink ${VM} ${VNET_DEV} | awk '{print $2}'`
         if [[ "${VNET_STATUS}" == "down" ]]; then
           output "[${DATE} ${TIME}] change ${VNET_DEV} link on ${VM} : DOWN -> UP"
           virsh domif-setlink ${VM} ${VNET_DEV} up >> ${LOG} 2>&1
         #else
         #  output "${VNET_DEV} on ${VM} already UP"
         fi
       done
       ;;
  esac

  # add delay
  sleep 3
done

chmod +x /root/bin/bonding_status
ls -lah /root/bin/bonding_status

Create Service Definition

vim /root/bin/bonding_status.service

[Unit]
Description=Check Bonding Status and Update VM(s) link status

[Service]
ExecStart=/root/bin/bonding_status br0 eno1 eno2

[Install]
WantedBy=multi-user.target

Insert New Service to systemd

ln -s /root/bin/bonding_status.service /lib/systemd/system/
ls -lahrt /lib/systemd/system/bonding_status.service

Enable and Start Service

systemctl enable bonding_status.service
systemctl restart bonding_status.service
systemctl status bonding_status.service

Reference

Own Idea
man virsh
stackoverflow
  1. No comments yet.
  1. No trackbacks yet.

Leave a comment