Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NM should not be restarted during hostname publish if NM_CONTROLLED=y #3008

Merged
merged 8 commits into from
Jan 9, 2024
32 changes: 30 additions & 2 deletions azurelinuxagent/common/osutil/redhat.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,39 @@ def set_hostname(self, hostname):
logger.warn("[{0}] failed, attempting fallback".format(' '.join(hostnamectl_cmd)))
DefaultOSUtil.set_hostname(self, hostname)

def get_nm_controlled(self):
ifname = self.get_if_name()
filepath = "/etc/sysconfig/network-scripts/ifcfg-{0}".format(ifname)
nm_controlled_cmd = ['grep', 'NM_CONTROLLED=', filepath]
try:
result = shellutil.run_command(nm_controlled_cmd, log_error=False, encode_output=False).rstrip()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is encide_output needed?

Copy link
Contributor Author

@maddieford maddieford Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If encode_output is True the stdout is returned as a string, otherwise it is returned as a bytes object.

When True, the result is unicode (u'no'). It was easier to do the comparison if encode_output=False and the result is in bytes


if result and len(result.split('=')) > 1:
# Remove trailing white space and ' or " characters
value = result.split('=')[1].replace("'", '').replace('"', '').rstrip()
if value == "n" or value == "no":
return False
except shellutil.CommandError as e:
# Command might fail because NM_CONTROLLED value is not in interface config file (exit code 1).
# Log warning for any other exit code.
# NM_CONTROLLED=y by default if not specified.
if e.returncode != 1:
logger.warn("[{0}] failed: {1}.\nAgent will continue to publish hostname without NetworkManager restart".format(' '.join(nm_controlled_cmd), e))
except Exception as e:
logger.warn("Unexpected error while retrieving value of NM_CONTROLLED in {0}: {1}.\nAgent will continue to publish hostname without NetworkManager restart".format(filepath, e))

return True

def publish_hostname(self, hostname):
"""
Restart NetworkManager first before publishing hostname
Restart NetworkManager first before publishing hostname, only if the network interface is not controlled by the
NetworkManager service (as determined by NM_CONTROLLED=n in the interface configuration). If the NetworkManager
service is restarted before the agent publishes the hostname, and NM_controlled=y, a race condition may happen
between the NetworkManager service and the Guest Agent making changes to the network interface configuration
simultaneously.
"""
shellutil.run("service NetworkManager restart")
if not self.get_nm_controlled():
shellutil.run("service NetworkManager restart")
super(RedhatOSUtil, self).publish_hostname(hostname)

def register_agent_service(self):
Expand Down