#!/bin/bash {{/* # Copyright 2017 AT&T Intellectual Property. All other rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. */}} set -e cat <<'EOF' > {{ .Values.conf.chroot_mnt_path | quote }}/tmp/ethtool_host.sh {{ include "divingbell.shcommon" . }} old_ethtool_path='/var/divingbell/ethtool' persist_path='/etc/systemd/system' if [ ! -d "${old_ethtool_path}" ]; then mkdir -p "${old_ethtool_path}" fi write_test "${old_ethtool_path}" write_test "${persist_path}" validate_operation(){ local param="${1}" shift [ "${param}" = 'on' ] || [ "${param}" = 'off' ] || die "Expected 'on' or 'off', got '${param}' $@" } ethtool_bin="$(type -p ethtool)" add_ethtool_param(){ die_if_null "${device}" ", 'device' env var not initialized" ifconfig "${device}" > /dev/null # verify interface is here die_if_null "${user_key}" ", 'user_key' env var not initialized" die_if_null "${user_val}" ", 'user_val' env var not initialized" # YAML parser converts unquoted 'on' and 'off' to boolean values # ethtool only works with 'on' and 'off', not 'true' or 'false' if [ "${user_val}" = 'true' ]; then user_val='on' elif [ "${user_val}" = 'false' ]; then user_val='off' fi validate_operation "${user_val}" : ${before:=docker.service} : ${after=network-online.target} # Call systemd-escapae to get systemd required filename local systemd_name systemd_name="$(systemd-escape \ -p --suffix=service "${device}.${user_key}")" # look for user requested value for this device local param_data param_data="$(${ethtool_bin} -k ${device} | grep "${user_key}:")" || die "Could not find requested param ${user_key} for ${device}" local audit_item audit_item="${device},${user_key},${user_val}" audit_items="${audit_items}${audit_item}"$'\n' # extract existing setting for device local current_val_raw current_val_raw="$(echo "${param_data}" | cut -d':' -f2)" [ "$(echo "${current_val_raw}" | wc -l)" -le 1 ] || die "More than one match for '${user_key}'" [[ ! ${current_val_raw} = *fixed* ]] || die "'${deivce}' does not permit changing the '${user_key}' setting" if [[ ${current_val_raw} = *off\ \[requested\ on\] ]]; then current_val_raw='off' elif [[ ${current_val_raw} = *on\ \[requested\ off\] ]]; then current_val_raw='on' fi local current_val current_val="$(echo "${current_val_raw}" | cut -d':' -f2 | tr -d '[:space:]')" die_if_null "${current_val}" "Value parse error on '${param_data}'" validate_operation "${current_val}" "for '${user_key}' on '${device}'" # write the original system setting for this device parameter local path_to_orig_val path_to_orig_val="${old_ethtool_path}/${systemd_name}" if [ ! -f "${path_to_orig_val}" ]; then echo "${device} ${user_key} ${current_val}" > "${path_to_orig_val}" fi # Read the original system setting for this device parameter and use it to # build the service 'stop' command (i.e. revert to original state) local stop_val stop_val="$(cat "${path_to_orig_val}" | cut -d' ' -f3)" validate_operation "${stop_val}" "from '${path_to_orig_val}'" local stop_cmd stop_cmd="${ethtool_bin} -K ${device} ${user_key} ${stop_val}" # Build service start command local start_cmd start_cmd="${ethtool_bin} -K ${device} ${user_key} ${user_val}" # Build the systemd unit file file_content="[Unit] Before=${before} After=${after} [Service] ExecStart=${start_cmd} #ExecStop=${stop_cmd} [Install] WantedBy=multi-user.target" local systemd_path="${persist_path}/${systemd_name}" local restart_service='' local service_updates='' if [ ! -f "${systemd_path}" ] || [ "$(cat ${systemd_path})" != "${file_content}" ] then echo "${file_content}" > "${systemd_path}" restart_service=true service_updates=true systemctl daemon-reload fi if [ "${current_val}" != "${user_val}" ]; then restart_service=true fi if [ -n "${restart_service}" ]; then systemctl restart "${systemd_name}" || die "Start failed: ${systemd_name}" fi # Mark the service for auto-start on boot systemctl is-enabled "${systemd_name}" > /dev/null || systemctl enable "${systemd_name}" || die "systemd persist failed: ${systemd_name}" log.INFO "Service successfully verified: ${systemd_name}" curr_ethtool="${curr_ethtool}${systemd_name}"$'\n' } {{- range $iface, $unused := .Values.conf.ethtool }} {{- range $ethtool_key, $ethtool_val := . }} device={{ $iface | squote }} \ user_key={{ $ethtool_key | squote }} \ user_val={{ $ethtool_val | squote }} \ add_ethtool_param {{- end }} {{- end }} # TODO: This should be done before applying new settings rather than after # Revert any previously applied services which are now absent prev_files="$(find "${old_ethtool_path}" -type f)" if [ -n "${prev_files}" ]; then basename -a ${prev_files} | sort > /tmp/prev_ethtool echo "${curr_ethtool}" | sort > /tmp/curr_ethtool revert_list="$(comm -23 /tmp/prev_ethtool /tmp/curr_ethtool)" IFS=$'\n' for prev_setting in ${revert_list}; do unset IFS args="$(cat "${old_ethtool_path}/${prev_setting}")" set -- $args ${ethtool_bin} -K "$@" if [ -f "${persist_path}/${prev_setting}" ]; then systemctl disable "${prev_setting}" rm "${persist_path}/${prev_setting}" fi rm "${old_ethtool_path}/${prev_setting}" log.INFO "Reverted ethtool settings: ${prev_setting}" done fi # Perform another pass on ethtool settings to identify any conflicting settings # among those specified by the user. Enabling/disabling some NIC settings will # implicitly enable/disable others. Ethtool reports conflicts for such # parameters as 'off [requested on]' and 'on [requested off]' for audit_item in ${audit_items}; do device="$(echo "${audit_item}" | cut -d',' -f1)" user_key="$(echo "${audit_item}" | cut -d',' -f2)" user_val="$(echo "${audit_item}" | cut -d',' -f3)" param_data="$(${ethtool_bin} -k ${device} | grep "${user_key}:")" current_val="$(echo "${param_data}" | cut -d':' -f2 | tr -d '[:space:]')" if [[ ${current_val} != ${user_val}* ]]; then if [[ ${param_data} = *\[requested\ on\] ]] || [[ ${param_data} = *\[requested\ off\] ]] then log.ERROR 'There is a conflict between settings chosen for this device.' fi die "Validation failure: Requested '${user_key}' to be set to" \ "'${user_val}' on '${device}'; got '${param_data}'." fi done if [ -n "${curr_ethtool}" ]; then log.INFO 'All ethtool successfully validated on this node.' else log.WARN 'No ethtool overrides defined for this node.' fi exit 0 EOF chmod 755 {{ .Values.conf.chroot_mnt_path | quote }}/tmp/ethtool_host.sh chroot {{ .Values.conf.chroot_mnt_path | quote }} /tmp/ethtool_host.sh sleep 1 echo 'INFO Putting the daemon to sleep.' while [ 1 ]; do sleep 300 done exit 0