sonic-net / sonic-buildimage

Scripts which perform an installable binary image build for SONiC
Other
737 stars 1.43k forks source link

/etc/hosts regulary updated with identical records #20579

Open johndexter1 opened 3 weeks ago

johndexter1 commented 3 weeks ago

Description

sethostname hook compares hostname -s instead of hostname and when dhcp provides FQDN it never matches the IF statement and new records are appended to /etc/hosts on every dhcp renew

Steps to reproduce the issue:

  1. Set up dhcp client on mgmt port
  2. Provide DHCP with FQDN as hostname option
  3. On each renew new entry will be appended to /etc/hosts
  4. Over some time /etc/hosts becomes huge. Depends on lease times, of course.

Describe the results you received:

A lot of identical lines in /etc/hosts

Describe the results you expected:

Only new (only if hostname has really changed) are added to /etc/hosts from dhcp

Output of show version:

202405

Additional information you deem important (e.g. issue happens only occasionally):

I have tested this PR (https://github.com/sonic-net/sonic-buildimage/pull/20404) and it solved the problem.

wdoekes commented 5 days ago

The cause: /etc/dhcp/dhclient-exit-hooks.d/sethostname (./files/dhcp/sethostname):

case $reason in
    BOUND|RENEW|REBIND|REBOOT)
        current_host_name=`hostname -s`
        if [ "$current_host_name" != "$new_host_name" ] && [ -n "$new_host_name" ]
        then
            echo $new_host_name > /etc/hostname
            hostname -F /etc/hostname
            sed -i "/\s$current_host_name$/d" /etc/hosts
            echo "127.0.0.1 $new_host_name" >> /etc/hosts
        fi
        ;;
esac

We have fqdn's, so we get this:

# reason=RENEW new_host_name=leaf1.dostno.systems sh -x /etc/dhcp/dhclient-exit-hooks.d/sethostname
+ hostname -s
+ current_host_name=leaf1
+ [ leaf1 != leaf1.dostno.systems ]
+ [ -n leaf1.dostno.systems ]
+ echo leaf1.dostno.systems
+ hostname -F /etc/hostname
+ sed -i /\sleaf1$/d /etc/hosts
+ echo 127.0.0.1 leaf1.dostno.systems

It would stay fixed for short hostnames:

# reason=RENEW new_host_name=leaf1 sh -x /etc/dhcp/dhclient-exit-hooks.d/sethostname
+ hostname -s
+ current_host_name=leaf1
+ [ leaf1 != leaf1 ]

Fix:

case $reason in
    BOUND|RENEW|REBIND|REBOOT)
        if [ -n "$new_host_name" ]; then
            current_host_long=$(hostname -f)
            current_host_short=$(hostname -s)

            case "$new_host_name" in
            *.*)
                current_host_name=$current_host_long
                new_host_short=${new_host_name%%.*}
                new_host_long=$new_host_name
                ;;
            *)
                current_host_name=$current_host_short
                new_host_short=$new_host_name
                new_host_long=$new_host_short.$(hostname -d 2>/dev/null)
                new_host_long=${new_host_long%.}
                ;;
            esac
            if [ "$current_host_name" != "$new_host_name" ]; then
                echo $new_host_name > /etc/hostname
                hostname -F /etc/hostname
                echo "127.0.0.1 $new_host_long $new_host_short" >> /etc/hosts
                sed -i "/\s$current_host_long\s\+$current_host_short$/d" /etc/hosts
            fi
        fi
        ;;
esac

Test:

# reason=RENEW new_host_name=test1 sh -x /etc/dhcp/dhclient-exit-hooks.d/sethostname
+ set -u
+ [ -n test1 ]
+ hostname -f
+ current_host_long=leaf2.dostno.systems
+ hostname -s
+ current_host_short=leaf2
+ current_host_name=leaf2
+ new_host_short=test1
+ hostname -d
+ new_host_long=test1.dostno.systems
+ new_host_long=test1.dostno.systems
+ [ leaf2 != test1 ]
+ echo test1
+ hostname -F /etc/hostname
+ echo 127.0.0.1 test1.dostno.systems test1
+ sed -i /\sleaf2.dostno.systems\s\+leaf2$/d /etc/hosts
# cat /etc/hosts
127.0.0.1       localhost
127.0.0.1 test1.dostno.systems test1

^- change: both fqdn and short hostname

# reason=RENEW new_host_name=test1 sh -x /etc/dhcp/dhclient-exit-hooks.d/sethostname
+ set -u
+ [ -n test1 ]
+ hostname -f
+ current_host_long=test1.dostno.systems
+ hostname -s
+ current_host_short=test1
+ current_host_name=test1
+ new_host_short=test1
+ hostname -d
+ new_host_long=test1.dostno.systems
+ new_host_long=test1.dostno.systems
+ [ test1 != test1 ]

^- no change, as expected

johndexter1 commented 4 days ago

I have tested this script, and it successfully performs the intended task