Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
/azurelinuxagent/common/rdma.py @longlimsft
/azurelinuxagent/pa/rdma/ @longlimsft

#
# Azure Container Linux (ACL)
#
/azurelinuxagent/common/osutil/acl.py @mayankfz
/config/acl/ @mayankfz
/init/acl/ @mayankfz

#
# Linux Agent team
#
Expand Down
79 changes: 79 additions & 0 deletions azurelinuxagent/common/osutil/acl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#
# Copyright 2018 Microsoft Corporation
#
# 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.
#
# Requires Python 2.6+ and Openssl 1.0+
#
# Azure Container Linux (ACL) is an immutable, sysext-based distro derived
# from Flatcar. This osutil is a standalone copy of MarinerOSUtil with
# ACL-specific overrides so that future Azure-Linux changes do not
# inadvertently affect the immutable ACL image.
Comment on lines +18 to +21
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The module header says ACL is "derived from Flatcar", but the PR description states ACL is derived from Azure Linux. This inconsistency makes it unclear what behavior/assumptions this OSUtil should follow (e.g., Flatcar/CoreOS vs Azure Linux/Mariner). Please align the comment (or the PR description) to the correct lineage to avoid future maintenance mistakes.

Copilot uses AI. Check for mistakes.
#

from azurelinuxagent.common.osutil.default import DefaultOSUtil


class AclOSUtil(DefaultOSUtil):
def __init__(self):
super(AclOSUtil, self).__init__()
self.jit_enabled = True

@staticmethod
def get_systemd_unit_file_install_path():
# ACL delivers waagent as a sysext; /usr is read-only.
# Writable systemd units must go to /etc/systemd/system.
return "/etc/systemd/system"

@staticmethod
def get_agent_bin_path():
return "/usr/bin"

def is_dhcp_enabled(self):
return True

def start_network(self):
self._run_command_without_raising(["systemctl", "start", "systemd-networkd"], log_error=False)

def restart_if(self, ifname=None, retries=None, wait=None):
self._run_command_without_raising(["systemctl", "restart", "systemd-networkd"])

def restart_ssh_service(self):
# ACL uses sshd.socket for socket-activated SSH (similar to
# Flatcar/CoreOS). Restarting sshd.service would conflict with
# the active sshd.socket.
pass

def stop_dhcp_service(self):
self._run_command_without_raising(["systemctl", "stop", "systemd-networkd"], log_error=False)

def start_dhcp_service(self):
self._run_command_without_raising(["systemctl", "start", "systemd-networkd"], log_error=False)

def start_agent_service(self):
self._run_command_without_raising(["systemctl", "start", "{0}".format(self.service_name)], log_error=False)

def stop_agent_service(self):
self._run_command_without_raising(["systemctl", "stop", "{0}".format(self.service_name)], log_error=False)

def register_agent_service(self):
self._run_command_without_raising(["systemctl", "enable", "{0}".format(self.service_name)], log_error=False)

def unregister_agent_service(self):
self._run_command_without_raising(["systemctl", "disable", "{0}".format(self.service_name)], log_error=False)

def get_dhcp_pid(self):
return self._get_dhcp_pid(["pidof", "systemd-networkd"])

def conf_sshd(self, disable_password):
pass
7 changes: 7 additions & 0 deletions azurelinuxagent/common/osutil/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import azurelinuxagent.common.logger as logger
from azurelinuxagent.common.version import DISTRO_NAME, DISTRO_CODE_NAME, DISTRO_VERSION, DISTRO_FULL_NAME
from azurelinuxagent.common.utils.distro_version import DistroVersion
from .acl import AclOSUtil
from .alpine import AlpineOSUtil
from .arch import ArchUtil
from .bigip import BigIpOSUtil
Expand Down Expand Up @@ -146,6 +147,12 @@ def _get_osutil(distro_name, distro_code_name, distro_version, distro_full_name)
if distro_name == "iosxe":
return IosxeOSUtil()

# distro_name is same for azurelinux/mariner and Azure Container Linux (ACL).
# ACL is a flavor of Azure Linux, differentiation is based on distro_full_name.
# For Azure Container Linux, distro_name will be made "azurecontainerlinux".
if distro_name == "azurecontainerlinux":
return AclOSUtil()

if distro_name in ["mariner", "azurelinux"]:
return MarinerOSUtil()

Expand Down
8 changes: 8 additions & 0 deletions azurelinuxagent/common/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ def get_distro():
if os.path.exists("/etc/mariner-release"):
osinfo[0] = "mariner"

if os.path.exists("/etc/os-release"):
try:
with open("/etc/os-release", "r") as f:
if re.search(r'^VARIANT_ID=azurecontainerlinux$', f.read(), re.MULTILINE):
osinfo[0] = "azurecontainerlinux"
except Exception:
pass

# The platform.py lib has issue with detecting BIG-IP linux distribution.
# Merge the following patch provided by F5.
if os.path.exists("/shared/vadc"):
Expand Down
37 changes: 37 additions & 0 deletions config/acl/waagent.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
Comment thread
mayankfz marked this conversation as resolved.
# Microsoft Azure Linux Agent Configuration (ACL)
#

Extensions.Enabled=y

# Auto-detect the provisioning agent (coreos-cloudinit or waagent).
Provisioning.Agent=auto
Provisioning.DeleteRootPassword=n
Provisioning.RegenerateSshHostKeyPair=n
Provisioning.SshHostKeyPairType=auto
Provisioning.MonitorHostName=y
Provisioning.DecodeCustomData=y
Provisioning.ExecuteCustomData=n
Provisioning.AllowResetSysUser=n

ResourceDisk.Format=y
Comment thread
narrieta marked this conversation as resolved.
ResourceDisk.Filesystem=ext4
ResourceDisk.MountPoint=/mnt/resource
ResourceDisk.EnableSwap=n
ResourceDisk.SwapSizeMB=0
ResourceDisk.MountOptions=None

LBProbeResponder=y

Logs.Verbose=n
# Logs.Console=y

OS.EnableFIPS=n
OS.SshDir=/etc/ssh
OS.RootDeviceScsiTimeout=300
OS.OpensslPath=None

#AutoUpdate.Enabled=n

# Add firewall rules to protect access to Azure host node services
OS.EnableFirewall=y
13 changes: 13 additions & 0 deletions init/acl/10-waagent-sysext.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Drop-in for multi-user.target on Azure Container Linux (ACL).
#
# WALinuxAgent is delivered as a systemd-sysext image. Sysext units are
# only visible after systemd-sysext.service merges the overlay, which
# happens *after* the default target is already queued. Without an
# explicit "Upholds=", systemd has no dependency edge to pull
# waagent.service into the boot transaction.
#
# "Upholds=" (systemd 249+) is a soft requirement: it starts the unit
# whenever multi-user.target is active but does not fail the target if
# waagent.service cannot start.
[Unit]
Comment thread
narrieta marked this conversation as resolved.
Upholds=waagent.service
18 changes: 18 additions & 0 deletions init/acl/waagent.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Microsoft Azure Linux Agent (ACL)
Wants=network-online.target sshd.service sshd-keygen.service
After=network-online.target sshd-keygen.service systemd-sysext.service
Comment thread
mayankfz marked this conversation as resolved.

ConditionFileIsExecutable=/usr/bin/waagent
ConditionPathExists=/etc/waagent.conf

[Service]
Type=simple

ExecStart=/usr/bin/python -u /usr/bin/waagent -daemon

Comment thread
nagworld9 marked this conversation as resolved.
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target
10 changes: 10 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ def get_data_files(name, version, fullname): # pylint: disable=R0912
src=["config/clearlinux/waagent.conf"])
set_systemd_files(data_files, dest=systemd_dir_path,
src=["init/clearlinux/waagent.service"])
elif name == 'azurecontainerlinux':
set_bin_files(data_files, dest=agent_bin_path)
set_logrotate_files(data_files)
set_conf_files(data_files, dest="/etc",
src=["config/acl/waagent.conf"])
set_systemd_files(data_files, dest=systemd_dir_path,
src=["init/acl/waagent.service"])
multi_user_target_drop_in_dir = os.path.join(systemd_dir_path, "multi-user.target.d")
set_systemd_files(data_files, dest=multi_user_target_drop_in_dir,
src=["init/acl/10-waagent-sysext.conf"])
elif name in ["mariner", "azurelinux"]:
set_bin_files(data_files, dest=agent_bin_path)
set_conf_files(data_files, dest="/etc",
Expand Down
9 changes: 9 additions & 0 deletions tests/common/osutil/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from azurelinuxagent.common.osutil.suse import SUSEOSUtil, SUSE11OSUtil
from azurelinuxagent.common.osutil.ubuntu import UbuntuOSUtil, Ubuntu12OSUtil, Ubuntu14OSUtil, \
UbuntuSnappyOSUtil, Ubuntu16OSUtil, Ubuntu18OSUtil
from azurelinuxagent.common.osutil.acl import AclOSUtil
from tests.lib.tools import AgentTestCase, patch


Expand Down Expand Up @@ -158,6 +159,14 @@ def test_get_osutil_it_should_return_coreos(self):
self.assertTrue(isinstance(ret, CoreOSUtil))
self.assertEqual(ret.get_service_name(), "waagent")

def test_get_osutil_it_should_return_acl(self):
ret = _get_osutil(distro_name="azurecontainerlinux",
distro_code_name="",
distro_version="3.0",
distro_full_name="Microsoft Azure Container Linux")
self.assertTrue(isinstance(ret, AclOSUtil))
self.assertEqual(ret.get_service_name(), "waagent")

def test_get_osutil_it_should_return_suse(self):
ret = _get_osutil(distro_name="suse",
distro_code_name="",
Expand Down
Loading