UMGUM.COM 

KVM + Bash-Supervisor + Network ( Функция инициализации виртуальных сетевых интерфейсов. )

21 июля 2011  (обновлено 28 октября 2018)

Эта публикация скрыта. Она доступна только по прямой ссылке.

Здесь размещено описание одного из функциональных блоков инструкции с примером управления виртуальными машинами "Qemu-KVM" через простейшие BASH-скрипты. Отдельно неприменимо.

Пример опций конфигурационного файла виртуальной машины:

# vi /usr/local/etc/kvm/conf.d/mashine0.cnf

....
# Явно указываем имя виртуального сетевого интерфейса, тип эмулируемой сетевой карты и MAC

# # adapter={rtl8139|e1000|virtio} (на практике rtl8139 - самый стабильный, хоть и медленный, зато распознаётся практически всеми системами без каких-либо телодвижений; e1000 (intel) - скоростной, но "глючный" до такой странной степени, что порой вообще перестаёт работать после очередного обновления виртуальной операционной системы).

network.virtif=tap0
network.tap0.adapter=virtio
network.tap0.mac=52:54:0c:b8:71:b0
network.tap0.connect=bridged
network.tap0.bridge=br0

network.virtif=tap2
network.tap2.adapter=virtio
network.tap2.mac=52:54:0c:b8:71:b2
network.tap2.connect=routed
network.tap2.ip=10.10.12.101
....

Поддерживаются два способа связи сетей виртуальной и несущей машины, с разделением их на "bridged" (схема с ручной преднастройкой на несущем хосте "Public Bridge") и "routed". Первый подразумевает создание прямой прозрачной среды между виртуальным и реальным сетевым интерфейсами мимо сетевой среды несущей машины, а второй обеспечивает маршрутизацию трафика виртуального сетевого интерфейса через сетевую среду несущей виртуальной машины (разумеется, для этого из виртуальной машины нужно будет указать путь к ближайшему доступному шлюзу на несущей машине).

Первый, "прозрачный" режим, проще в настройке и реализации, но не позволяет использовать всю пропускную способность агрегированных сетевых интерфейсов несущей машины. Второй сложнее, но более гибкий в настройках и совместим с любым типом сетевого оборудования (например беспроводные сетевые карты и модемы почти всегда невозможно включить в "прозрачный мост").

Фрагмент кода с функциями подготовки строки инициализации сетевых устройств виртуальной машины:

# vi /etc/kvm/fnc.d/5.network.fnc

#!/bin/bash
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)

# Функция инициализации виртуальных сетевых интерфейсов
function start-network() {

  # Зачищаем исходящую строку описания от результатов работы предыдущей итерации
  NSTRING=""

  # Перебираем все строки именований виртуальных сетевых интерфейсов
  for NIFS in `grep --ignore-case "^network.virtif=" "${CNF}" | uniq`
  do

    NIF=`echo ${NIFS} | awk -F = '{print $2}'`

    # Проверяем наличие в сетевом окружении целевого виртуального сетевого интерфейса
    STATE=`ifconfig -a | grep --count --ignore-case ${NIF}`
    if [ ${STATE} -ne 0 ]; then
      echo "${DATE}: Виртуальный сетевой интерфейс ${NIF} уже инициирован." | tee -a "${LOGT}"
    else

      # Инициируем виртуальный сетевой интерфейс
      STATE=`tunctl -b -u ${USER} -t ${NIF}`
      if [ ${?} -eq 0 -a "${STATE}" == "${NIF}" ]; then
        ifconfig ${NIF} 0.0.0.0 up
      else
        echo "${DATE}: Ошибка инициализации виртуального интерфейса ${NIF}." | tee -a "${LOGT}"
        return 1
      fi
    fi

    # Выясняем тип сетевого подключения ("прозрачный мост" или "маршрутизация")
    CTYPE=`grep --ignore-case --max-count=1 "^network.${NIF}.connect=" "${CNF}" | awk -F = '{print $2}'`
    if [ "${CTYPE}" == "bridged" ] ; then

      NBRIDGE=`grep --ignore-case --max-count=1 "^network.${NIF}.bridge=" "${CNF}" | awk -F = '{print $2}'`

      # Проверяем наличие в сетевом окружении целевого "моста"
      STATE=`brctl show | grep --count --ignore-case ${NBRIDGE}`
      if [ ${STATE} -ne 0 ]; then

        # Проверяем включение в какой либо "мост" целевого виртуального сетевого интерфейса
        STATE=`brctl show | grep --count --ignore-case ${NIF}`
        if [ ${STATE} -ne 0 ]; then
          echo "${DATE}: Виртуальный сетевой интерфейс ${NIF} уже инициирован и подключен к мосту ${NBRIDGE}." | tee -a "${LOGT}"
        else

          # Включаем виртуальный интерфейс в "мост"
          brctl addif ${NBRIDGE} ${NIF}
         fi

      else
        echo "${DATE}: Еarget bridge interface ${NBRIDGE} is missing. Abort operations." | tee -a "${LOGT}"
        return 1
      fi

    elif [ "${CTYPE}" == "routed" ] ; then

      # Явно включаем подсистему маршрутизации пакетов IPv4
      sysctl --write net.ipv4.ip_forward=1 >/dev/null

      # Явно включаем подсистему обмена MAC-адресами между сетевыми интерфейсами (Proxy ARP)
      sysctl --write  net.ipv4.conf.all.proxy_arp=1 >/dev/null

      # Перебираем все IPv4-адреса, объявленные за целевым виртуальным интерфейсом
      for IPS in `grep --ignore-case "^network.${NIF}.ip=" "${CNF}"`
      do

        IP=`echo ${IPS} | awk -F = '{print $2}'`

        # Добавляем в таблицу маршрутизации путь к адресу, объявленному за целевым виртуальным интерфейсом
        route add -host ${IP} dev ${NIF} >/dev/null
      done

    else
      echo "${DATE}: Ошибка подключения в сеть виртуального интерфейса ${NIF}: неопределённый тип сети." | tee -a "${LOGT}"
      return 1
    fi

    # Дочитываем ряд параметров сетевых интерфейсов
    NIC=`grep --ignore-case --max-count=1 "^network.${NIF}.adapter=" "${CNF}" | awk -F = '{print $2}'`
    MAC=`grep --ignore-case --max-count=1 "^network.${NIF}.mac=" "${CNF}" | awk -F = '{print $2}'`

    # Формируем строку описания сетевых интерфейсов виртуальной машины
    if [ "${NIC}" != "" -a "${MAC}" != "" ]; then

      NSTRING="${NSTRING} -net nic,macaddr=${MAC},model=${NIC} -net tap,ifname=${NIF},script=no,downscript=no"

    else
      echo "${DATE}: No full details of a network environment. Abort operations." | tee -a "${LOGT}"
      return 1
    fi

  done

return 0
}

# Функция деактивации виртуальных сетевых интерфейсов
function stop-network() {

  # Перебираем все строки именований виртуальных сетевых интерфейсов
  for NIFS in `grep --ignore-case "^network.virtif=" "${CNF}" | uniq`
  do

    NIF=`echo ${NIFS} | awk -F = '{print $2}'`

    # Выясняем тип сетевого подключения ("прозрачный мост" или "маршрутизация")
    CTYPE=`grep --ignore-case --max-count=1 "^network.${NIF}.connect=" "${CNF}" | awk -F = '{print $2}'`
    if [ "${CTYPE}" == "bridged" ] ; then

      NBRIDGE=`grep --ignore-case --max-count=1 "^network.${NIF}.bridge=" "${CNF}" | awk -F = '{print $2}'`

      # Проверяем наличие целевого виртуального сетевого интерфейса в составе "моста"
      STATE=`brctl show ${NBRIDGE} | grep --count --ignore-case ${NIF}`
      if [ ${STATE} -ne 0 ]; then

        # Удаляем из "моста" целевой виртуальный сетевой интерфейс
        brctl delif ${NBRIDGE} ${NIF}
      fi

    elif [ "${CTYPE}" == "routed" ] ; then

      # Перебираем все IPv4-адреса, объявленные за целевым виртуальным интерфейсом
      for IPS in `grep --ignore-case "^network.${NIF}.ip=" "${CNF}"`
      do

        IP=`echo ${IPS} | awk -F = '{print $2}'`

        # Удаляем из таблицы маршрутизации путь к адресам, объявленным за целевым виртуальным интерфейсом
        route del -host ${IP} dev ${NIF} >/dev/null
      done

    else
      echo "${DATE}: Ошибка отключения от сети виртуального интерфейса ${NIF}: неопределённый тип сети." | tee -a "${LOGT}"
      return 1
    fi

    # Проверяем наличие в сетевом окружении целевого виртуального сетевого интерфейса
    STATE=`ifconfig -a | grep --count --ignore-case ${NIF}`
    if [ ${STATE} -ne 0 ]; then

      # Деактивируем виртуальный сетевой интерфейс
      ifconfig ${NIF} 0.0.0.0 down
      STATE=`tunctl -d ${NIF}`
      if [ ${?} -eq 0 ]; then
        echo "${DATE}: Виртуальный сетевой интерфейс ${NIF} успешно деактивирован." | tee -a "${LOGT}"
      fi
    fi

  done

return 0
}


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )