← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1860250] [NEW] fail to start cloud init because of failure to start net interfaces

 

Public bug reported:

I find that baremetals fail to fetch metadata , and I conclude that the net inferfaces enahisic2i0 fail to fetch ip with dhcp.
cat /etc/network/interfaces:
allow-hotplug eth0
iface eth0 inet dhcp

so ,we can edit /etc/default/grub and let the os name the interfaces ehtXX 
biosdevname=0 net.ifnames=0

finally, the  baremetals succed to fetch metadata. However,I think the
solution is not the best way. the interfaces is unchangeable and in
order to  automatically start interfaces witch changeable names  ,I come
up with the follwing solution including tree steps.


fistly,create  /usr/lib/systemd/system/dhcp-interface@.service
cat /usr/lib/systemd/system/dhcp-interface@.service
[Unit]
Description=DHCP interface %i
DefaultDependencies=no
After=network.target
Before=network-online.target
Wants=network-online.target

ConditionPathExists=!/etc/sysconfig/network-scripts/ifcfg-%i

[Service]
Type=oneshot
User=root
ExecStartPre=/usr/local/sbin/dhcp-all-interfaces.sh %i
ExecStart=/sbin/ifup %i
RemainAfterExit=true
TimeoutStartSec=30s

[Install]
WantedBy=multi-user.target


secondly,create /usr/local/sbin/dhcp-all-interfaces.sh
 cat  /usr/local/sbin/dhcp-all-interfaces.sh
#!/bin/bash

if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
    set -x
fi
set -eu
set -o pipefail

INTERFACE=${1:-} #optional, if not specified configure all available interfaces
ENI_FILE="/etc/network/interfaces"

PATH=/sbin:$PATH

if [ -d "/etc/network" ]; then
    CONF_TYPE="eni"
elif [ -d "/etc/sysconfig/network-scripts/" ]; then
    CONF_TYPE="rhel-netscripts"
    SCRIPTS_PATH="/etc/sysconfig/network-scripts/"
elif [ -d "/etc/sysconfig/network/" ]; then
    # SUSE network scripts location
    CONF_TYPE="suse-netscripts"
    SCRIPTS_PATH="/etc/sysconfig/network/"
else
    echo "Unsupported network configuration type!"
    exit 1
fi

ARGS="$0 $@"

function serialize_me() {
    if [ "$CONF_TYPE" == "eni" ]; then
        # Serialize runs so that we don't miss hot-add interfaces
        FLOCKED=${FLOCKED:-}
        if [ -z "$FLOCKED" ] ; then
            FLOCKED=true exec flock -x $ENI_FILE $ARGS
        fi
    fi
}

function get_if_link() {
    cat /sys/class/net/${1}/carrier || echo 0
}

function get_if_type() {
    cat /sys/class/net/${1}/type
}

function enable_interface() {
    local interface=$1

    serialize_me
    if [ "$CONF_TYPE" == "eni" ]; then
        printf "auto $interface\niface $interface inet dhcp\n\n" >>$ENI_FILE
    elif [ "$CONF_TYPE" == "rhel-netscripts" ]; then
        if [ "$(get_if_type $interface)" == "32" ]; then
            printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"InfiniBand\"\nCONNECTED_MODE=\"no\"\nDEFROUTE=\"yes\"\nPEERDNS=\"yes\"\nPEERROUTES=\"yes\"\nIPV4_FAILURE_FATAL=\"yes\"\nIPV6INIT=\"no\"" >"${SCRIPTS_PATH}ifcfg-$interface"
        else
            printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"" >"${SCRIPTS_PATH}ifcfg-$interface"
    fi
    elif [ "$CONF_TYPE" == "suse-netscripts" ]; then
        printf "BOOTPROTO=\"dhcp\"\nSTARTMODE=\"auto\"" >"${SCRIPTS_PATH}ifcfg-$interface"
    fi
    echo "Configured $1"

}


function config_exists() {
    local interface=$1
    if [[ "$CONF_TYPE" =~ "netscripts" ]]; then
        if [ -f "${SCRIPTS_PATH}ifcfg-$interface" ]; then
            return 0
        fi
    else
        if ifquery $interface >/dev/null 2>&1; then
            if [ -z "$(ifquery $interface 2>&1)" ]; then
                return 1
            else
                return 0
            fi
        else
            return 1
        fi
    fi
    return 1
}

function inspect_interface() {
    local interface=$1
    local mac_addr_type
    mac_addr_type=$(cat /sys/class/net/${interface}/addr_assign_type)

    echo -n "Inspecting interface: $interface..."
    if config_exists $interface; then
        echo "Has config, skipping."
    elif [ "$mac_addr_type" != "0" ]; then
        echo "Device has generated MAC, skipping."
    else
        local has_link
        local tries=30
        for ((; tries > 0; tries--)); do
            # Need to set the link up on each iteration
            ip link set dev $interface up &>/dev/null
            has_link=$(get_if_link $interface)
            [ "$has_link" == "1" ] && break
            sleep 1
        done
        if [ "$has_link" == "1" ]; then
            enable_interface "$interface"
        else
            echo "No link detected, skipping"
        fi
    fi
}

if [ -n "$INTERFACE" ]; then
    inspect_interface $INTERFACE
else
    for iface in $(ls /sys/class/net | grep -v ^lo$); do
        inspect_interface $iface
    done
fi

thirdly, create /etc/udev/rules.d/99-dhcp-all-interfaces.rules
 cat /etc/udev/rules.d/99-dhcp-all-interfaces.rules
SUBSYSTEM=="net", KERNEL!="lo", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="dhcp-interface@$name.service"

** Affects: cloud-init
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to cloud-init.
https://bugs.launchpad.net/bugs/1860250

Title:
  fail to start cloud init because of failure to start net interfaces

Status in cloud-init:
  New

Bug description:
  I find that baremetals fail to fetch metadata , and I conclude that the net inferfaces enahisic2i0 fail to fetch ip with dhcp.
  cat /etc/network/interfaces:
  allow-hotplug eth0
  iface eth0 inet dhcp

  so ,we can edit /etc/default/grub and let the os name the interfaces ehtXX 
  biosdevname=0 net.ifnames=0

  finally, the  baremetals succed to fetch metadata. However,I think the
  solution is not the best way. the interfaces is unchangeable and in
  order to  automatically start interfaces witch changeable names  ,I
  come up with the follwing solution including tree steps.

  
  fistly,create  /usr/lib/systemd/system/dhcp-interface@.service
  cat /usr/lib/systemd/system/dhcp-interface@.service
  [Unit]
  Description=DHCP interface %i
  DefaultDependencies=no
  After=network.target
  Before=network-online.target
  Wants=network-online.target

  ConditionPathExists=!/etc/sysconfig/network-scripts/ifcfg-%i

  [Service]
  Type=oneshot
  User=root
  ExecStartPre=/usr/local/sbin/dhcp-all-interfaces.sh %i
  ExecStart=/sbin/ifup %i
  RemainAfterExit=true
  TimeoutStartSec=30s

  [Install]
  WantedBy=multi-user.target

  
  secondly,create /usr/local/sbin/dhcp-all-interfaces.sh
   cat  /usr/local/sbin/dhcp-all-interfaces.sh
  #!/bin/bash

  if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
      set -x
  fi
  set -eu
  set -o pipefail

  INTERFACE=${1:-} #optional, if not specified configure all available interfaces
  ENI_FILE="/etc/network/interfaces"

  PATH=/sbin:$PATH

  if [ -d "/etc/network" ]; then
      CONF_TYPE="eni"
  elif [ -d "/etc/sysconfig/network-scripts/" ]; then
      CONF_TYPE="rhel-netscripts"
      SCRIPTS_PATH="/etc/sysconfig/network-scripts/"
  elif [ -d "/etc/sysconfig/network/" ]; then
      # SUSE network scripts location
      CONF_TYPE="suse-netscripts"
      SCRIPTS_PATH="/etc/sysconfig/network/"
  else
      echo "Unsupported network configuration type!"
      exit 1
  fi

  ARGS="$0 $@"

  function serialize_me() {
      if [ "$CONF_TYPE" == "eni" ]; then
          # Serialize runs so that we don't miss hot-add interfaces
          FLOCKED=${FLOCKED:-}
          if [ -z "$FLOCKED" ] ; then
              FLOCKED=true exec flock -x $ENI_FILE $ARGS
          fi
      fi
  }

  function get_if_link() {
      cat /sys/class/net/${1}/carrier || echo 0
  }

  function get_if_type() {
      cat /sys/class/net/${1}/type
  }

  function enable_interface() {
      local interface=$1

      serialize_me
      if [ "$CONF_TYPE" == "eni" ]; then
          printf "auto $interface\niface $interface inet dhcp\n\n" >>$ENI_FILE
      elif [ "$CONF_TYPE" == "rhel-netscripts" ]; then
          if [ "$(get_if_type $interface)" == "32" ]; then
              printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"InfiniBand\"\nCONNECTED_MODE=\"no\"\nDEFROUTE=\"yes\"\nPEERDNS=\"yes\"\nPEERROUTES=\"yes\"\nIPV4_FAILURE_FATAL=\"yes\"\nIPV6INIT=\"no\"" >"${SCRIPTS_PATH}ifcfg-$interface"
          else
              printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"" >"${SCRIPTS_PATH}ifcfg-$interface"
      fi
      elif [ "$CONF_TYPE" == "suse-netscripts" ]; then
          printf "BOOTPROTO=\"dhcp\"\nSTARTMODE=\"auto\"" >"${SCRIPTS_PATH}ifcfg-$interface"
      fi
      echo "Configured $1"

  }

  
  function config_exists() {
      local interface=$1
      if [[ "$CONF_TYPE" =~ "netscripts" ]]; then
          if [ -f "${SCRIPTS_PATH}ifcfg-$interface" ]; then
              return 0
          fi
      else
          if ifquery $interface >/dev/null 2>&1; then
              if [ -z "$(ifquery $interface 2>&1)" ]; then
                  return 1
              else
                  return 0
              fi
          else
              return 1
          fi
      fi
      return 1
  }

  function inspect_interface() {
      local interface=$1
      local mac_addr_type
      mac_addr_type=$(cat /sys/class/net/${interface}/addr_assign_type)

      echo -n "Inspecting interface: $interface..."
      if config_exists $interface; then
          echo "Has config, skipping."
      elif [ "$mac_addr_type" != "0" ]; then
          echo "Device has generated MAC, skipping."
      else
          local has_link
          local tries=30
          for ((; tries > 0; tries--)); do
              # Need to set the link up on each iteration
              ip link set dev $interface up &>/dev/null
              has_link=$(get_if_link $interface)
              [ "$has_link" == "1" ] && break
              sleep 1
          done
          if [ "$has_link" == "1" ]; then
              enable_interface "$interface"
          else
              echo "No link detected, skipping"
          fi
      fi
  }

  if [ -n "$INTERFACE" ]; then
      inspect_interface $INTERFACE
  else
      for iface in $(ls /sys/class/net | grep -v ^lo$); do
          inspect_interface $iface
      done
  fi

  thirdly, create /etc/udev/rules.d/99-dhcp-all-interfaces.rules
   cat /etc/udev/rules.d/99-dhcp-all-interfaces.rules
  SUBSYSTEM=="net", KERNEL!="lo", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="dhcp-interface@$name.service"

To manage notifications about this bug go to:
https://bugs.launchpad.net/cloud-init/+bug/1860250/+subscriptions


Follow ups