github.com/openshift/installer@v1.4.17/pkg/asset/agent/manifests/network-scripts.go (about)

     1  package manifests
     2  
     3  // This file is copied from https://github.com/openshift/assisted-service/blob/master/internal/constants/scripts.go
     4  // as its in the internal directory so can't be imported
     5  
     6  // PreNetworkConfigScript script runs on hosts before network manager service starts in order to apply
     7  // user's provided network configuration on the host.
     8  // If the user provides static network configuration, the network config files will be stored in directory
     9  // /etc/assisted/network in the following structure:
    10  //
    11  //		+-- host1
    12  //		|      +--- *.nmconnection
    13  //		|      +--- mac_interface.ini
    14  //		+-- host2
    15  //		      +--- *.nmconnection
    16  //		      +--- mac_interface.ini
    17  //	 1. *.nmconnections - files generated by nmstate based on yaml files provided by the user
    18  //	 2. mac_interface.ini - the file contains mapping of mac-address to logical interface name.
    19  //	    There are two usages for the file:
    20  //	 1. Map logical interface name to MAC Address of the host. The logical interface name is a
    21  //	    name provided by the user for the interface. It will be replaced by the script with the
    22  //	    actual network interface name.
    23  //	 2. Identify if a host directory belongs to the current host by matching a MAC Address
    24  //	    from the mapping file with host network interfaces.
    25  //
    26  // Applying the network configuration of each host will be done by:
    27  //  1. Associate the current host with its matching hostX directories. The association will be done by
    28  //     matching host's mac addresses with those in mac_interface.ini.
    29  //  2. Replace logical interface name in nmconnection files with the interface name as set on the host
    30  //  3. Rename nmconnection files to start with the interface name (instead of the logical interface name)
    31  //  4. Copy the nmconnection files to the target directory. That will be
    32  //     '/etc/NetworkManager/system-connections' when the script is part of the full ISO and
    33  //     '/etc/coreos-firstboot-network' when the script is part of the minimal ISO.
    34  const PreNetworkConfigScript = `#!/bin/bash
    35  
    36  PATH_PREFIX=${PATH_PREFIX:=''}
    37  
    38  # The directory that contains nmconnection files of all nodes
    39  NMCONNECTIONS_DIR=${PATH_PREFIX}/etc/assisted/network
    40  MAC_NIC_MAPPING_FILE=mac_interface.ini
    41  
    42  if [[ ! -d "$NMCONNECTIONS_DIR" ]]
    43  then
    44    echo "Error (exiting): Expected to find the directory $NMCONNECTIONS_DIR on the host but this was not present."
    45    exit 0
    46  fi
    47  
    48  # A map of host mac addresses to interface names
    49  declare -A host_macs_to_hw_iface
    50  
    51  # A mac-to-nic map created from the mapping file associated with the host
    52  declare -A logical_mac_nic_map
    53  
    54  # A map from old vlan interface names to new ones
    55  declare -A vlan_replacements
    56  
    57  # Working directory used for storage of processed files before installation in the target directory
    58  work_dir=$(mktemp -d)
    59  
    60  # Find destination directory based on ISO mode
    61  if [[ -f ${PATH_PREFIX}/etc/initrd-release ]]; then
    62    ETC_NETWORK_MANAGER="${PATH_PREFIX}/etc/coreos-firstboot-network"
    63  else
    64    ETC_NETWORK_MANAGER="${PATH_PREFIX}/etc/NetworkManager/system-connections"
    65  fi
    66  echo "Info: ETC_NETWORK_MANAGER was set to $ETC_NETWORK_MANAGER"
    67  
    68  # Create a map of host mac addresses to their network interfaces
    69  function map_host_macs_to_interfaces() {
    70    SYS_CLASS_NET_DIR="${PATH_PREFIX}/sys/class/net"
    71    for nic in $( ls $SYS_CLASS_NET_DIR )
    72    do
    73      mac=$(cat $SYS_CLASS_NET_DIR/$nic/address | tr '[:lower:]' '[:upper:]')
    74      [[ -n "$mac" ]] && host_macs_to_hw_iface[$mac]=$nic
    75    done
    76  }
    77  
    78  # Copy all nmstate files representing a host nic.  All these files have the host nic as filename prefix.
    79  function copy_physical_nics_files() {
    80    host_src_dir=$1
    81    mapping_file=$2
    82    host_work_dir=$3
    83    for mac_address in $(cat $mapping_file | cut -d= -f1 | tr '[:lower:]' '[:upper:]');  do
    84      host_nic="${host_macs_to_hw_iface[${mac_address}]:-}"
    85      if [[  -n "$host_nic" ]]; then
    86        logical_nic="${logical_mac_nic_map[${mac_address}]:-}"
    87        if [[ -n "$(ls -A $host_src_dir/*.nmconnection )" ]] ; then
    88          for nmfile in $host_src_dir/*.nmconnection ; do
    89            filename=$(basename $nmfile)
    90            prefix="${filename%%.*}"
    91            extension="${filename#*.}"
    92  
    93            if [[ -n "$prefix" ]] && [[ "$prefix" == "$logical_nic" ]] ; then
    94  
    95              # Check to see if adding the vlan id will push the interface name over 15 characters and trim the host interface if so
    96              # NetworkManager has a 15 character limit on interface names
    97              this_host_nic=${host_nic}
    98              vlan_id="$(echo ${extension} | cut -s -d'.' -f1)"
    99              if [[ -n "${vlan_id}" ]] ; then
   100                len=$(echo -n "${host_nic}.${vlan_id}" | wc -m)
   101                if [ "$len" -gt "15" ] ; then
   102                  extra=$(($len - 15))
   103                  nic_len=$(echo -n "${host_nic}" | wc -m)
   104                  this_host_nic=$(echo ${host_nic} | cut -c -$(($nic_len-$extra)))
   105                  # record this substitution to be used later
   106                  vlan_replacements[${host_nic}.${vlan_id}]=${this_host_nic}.${vlan_id}
   107                fi
   108              fi
   109  
   110              target_file=$host_work_dir/${this_host_nic}.${extension}
   111              mv -f $nmfile $target_file
   112              echo "Info: Copied $nmfile to $target_file"
   113            fi
   114          done
   115        fi
   116      fi
   117    done
   118  }
   119  
   120  # Copy all files that were not copied already by the function copy_physical_nics_files.  These files represent nics
   121  # that do not have prefix of physical nic (example: eth0).  In this case the file is either copied as is
   122  # having the same name as the source file, or if such a name already exists an error is generated
   123  function copy_other_files() {
   124    host_src_dir=$1
   125    host_work_dir=$2
   126    if [[ -n "$(ls -A ${host_src_dir}/*.nmconnection)" ]] ; then
   127      for nmfile in ${host_src_dir}/*.nmconnection ; do
   128        filename=$(basename $nmfile)
   129        target_file=$host_work_dir/$filename
   130  
   131        # Copy the file only if the file name was not used already
   132        if ! [[ -f $work_dir/$filename ]] ; then
   133          mv -f $nmfile $target_file
   134          echo "Info: Copied $nmfile to $target_file"
   135        else
   136          echo "Error: connection file name ${filename} is already in use. Please rename"
   137        fi
   138      done
   139    fi
   140  }
   141  
   142  # Update references to host nics in the nmstate files
   143  function update_physical_nics_references() {
   144    mapping_file=$1
   145    host_work_dir=$2
   146    if [ "$(ls -A $host_work_dir )" ] ; then
   147      for mac_address in $(cat $mapping_file | cut -d= -f1 | tr '[:lower:]' '[:upper:]'); do
   148        host_nic="${host_macs_to_hw_iface[${mac_address}]:-}"
   149        if [[  -n "$host_nic" ]]; then
   150          logical_nic="${logical_mac_nic_map[${mac_address}]:-}"
   151          for nmfile in $host_work_dir/*.nmconnection ; do
   152            sed -i -e "s/=$logical_nic$/=$host_nic/g" -e "s/=$logical_nic\./=$host_nic\./g" $nmfile
   153            echo "Info: Using logical interface name '$logical_nic' for interface with Mac address '$mac_address', updated $nmfile"
   154  
   155  	  for vlan in "${!vlan_replacements[@]}"; do
   156              sed -i "s/=${vlan}/=${vlan_replacements[${vlan}]}/g" $nmfile
   157              echo "Info: Replacing instances of logical vlan name ${vlan} with ${vlan_replacements[${vlan}]} in $nmfile"
   158            done
   159          done
   160        fi
   161      done
   162    fi
   163  }
   164  
   165  # Iterate over the host directories and process any of them that having matching interfaces with any of the local nics.
   166  # A host directory matches a host if the MAC address of one of the nics of the local host appears in the file
   167  # mac_mapping.ini in the directory.
   168  function process_host_directories_by_mac_address() {
   169    pattern="$(echo -n ${!host_macs_to_hw_iface[@]} | sed 's/  */|/g')"
   170    if [[ -z "$pattern" ]] ; then
   171      return
   172    fi
   173    src_dir=$(mktemp -d)
   174    cp -r ${NMCONNECTIONS_DIR}/host* $src_dir || /bin/true
   175    for host_src_dir in $(ls -1 -d $src_dir/host* || echo)
   176    do
   177      mapping_file="${host_src_dir}/${MAC_NIC_MAPPING_FILE}"
   178      if [[ ! -f "$mapping_file" ]]
   179      then
   180        echo "Warning: Mapping file $mapping_file is missing. Skipping on directory $host_src_dir"
   181        continue
   182      fi
   183  
   184      if [[ -z "$(ls -A $host_src_dir/*.nmconnection)" ]]
   185      then
   186        echo "Warning: Host directory does not contain any nmconnection files, skipping"
   187        continue
   188      fi
   189  
   190      if grep -q -i -E "$pattern" $mapping_file; then
   191        echo "Info: Found host directory: $(basename $host_src_dir) , copying configuration"
   192        host_work_dir=$(mktemp -d)
   193  
   194        echo "Info: Copying physical interface files for host $(basename $host_src_dir)"
   195        # Copy all physical nics files that match logical nics in the mapping file
   196        copy_physical_nics_files $host_src_dir $mapping_file $host_work_dir
   197  
   198        echo "Info: Copying other interface files for host $(basename $host_src_dir)"
   199        # Copy the rest of the files from the host directory
   200        copy_other_files $host_src_dir $host_work_dir
   201  
   202        echo "Info: Updating references for host $(basename $host_src_dir)"
   203        # Update references in the nmstate files to host nics
   204        update_physical_nics_references $mapping_file $host_work_dir
   205  
   206        cp $host_work_dir/* $work_dir || /bin/true
   207        rm -rf $host_work_dir
   208      fi
   209    done
   210    rm -rf $src_dir
   211  }
   212  
   213  function map_mac_logical_nic_mapping() {
   214    echo "Info: Checking all '${MAC_NIC_MAPPING_FILE}' for mac to logical nic mappings"
   215    # initialize logical_mac_nic_map with mapping file entries
   216    for f in $(echo ${NMCONNECTIONS_DIR}/host*/${MAC_NIC_MAPPING_FILE} || echo) ; do
   217      readarray -t lines < "${f}"
   218      for line in "${lines[@]}"
   219      do
   220        mac=${line%%=*}
   221        nic=${line#*=}
   222        logical_mac_nic_map[${mac^^}]=$nic
   223      done
   224    done
   225  }
   226  
   227  
   228  echo "PreNetworkConfig Start"
   229  
   230  # Get the mac to host nic mapping from local machine
   231  map_host_macs_to_interfaces
   232  
   233  # Get mac to local nic mapping from all mac_mapping.ini files in host directories
   234  map_mac_logical_nic_mapping
   235  
   236  # Process all relevant files and put them in work_dir
   237  process_host_directories_by_mac_address
   238  
   239  # Make sure we do not run any of the following functions if there was no matching config.
   240  if [ "$(ls -A $work_dir )" ];  then
   241      # Remove default connection file create by NM(nm-initrd-generator). This is a WA until
   242      # NM is back to supporting priority between nmconnections.
   243      #
   244      # Note that when this is intended mostly for the full ISO scenario. In the minimal ISO scenario
   245      # this script runs before the 'coreos-coreos-copy-firstboot-network' service, and that script
   246      # already removes the connection files, but it doesn't hurt to do it again.
   247      mkdir -p ${ETC_NETWORK_MANAGER}
   248      echo "Info: Removing default connection files in '$ETC_NETWORK_MANAGER'"
   249      rm -f ${ETC_NETWORK_MANAGER}/*
   250      echo "Info: Copying files from working directory to '$ETC_NETWORK_MANAGER'"
   251      cp -v $work_dir/* ${ETC_NETWORK_MANAGER}
   252  else
   253      echo "Info: No matching host directories found"
   254  fi
   255  rm -rf $work_dir
   256  echo "PreNetworkConfig End"
   257  `