Repository: Azure/WALinuxAgent
Pull request #2450 (2021-12-22 21:06:13)

Cgroup coverage for RedHat and Centos
<!-- DO NOT DELETE THIS TEMPLATE -->

## Description
Cgroup coverage for RedHat and CentOs

<!--
Please add an informative description that covers that changes made by the pull request. 
This checklist is used to make sure that common issues in a pull request are addressed.
This will expedite the process of getting your pull request merged and avoid extra work on your part to fix issues discovered during the review process.
-->

---

### PR information
- [ ] The title of the PR is clear and informative.
- [ ] There are a small number of commits, each of which has an informative message. This means that previously merged commits do not appear in the history of the PR. For information on cleaning up the commits in your pull request, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md).
- [ ] If applicable, the PR references the bug/issue that it fixes in the description.
- [ ] New Unit tests were added for the changes made

### Quality of Code and Contribution Guidelines
- [ ] I have read the [contribution guidelines](https://github.com/Azure/WALinuxAgent/blob/master/.github/CONTRIBUTING.md).

codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) Report
> Merging [#2450](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (ee109e1) into [develop](https://codecov.io/gh/Azure/WALinuxAgent/commit/2d1edd397b86775206fcafbc79220d6c7a464fc7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (2d1edd3) will **increase** coverage by `0.00%`.
> The diff coverage is `65.21%`.

> :exclamation: Current head ee109e1 differs from pull request most recent head 7278883. Consider uploading reports for the commit 7278883 to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450/graphs/tree.svg?width=650&height=150&src=pr&token=ae90E2KYCw&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)

```diff
@@           Coverage Diff            @@
##           develop    #2450   +/-   ##
========================================
  Coverage    71.84%   71.85%           
========================================
  Files          101      101           
  Lines        14944    14940    -4     
  Branches      2367     2367           
========================================
- Hits         10737    10735    -2     
+ Misses        3727     3725    -2     
  Partials       480      480           
```


| [Impacted Files](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | Coverage Δ | |
|---|---|---|
| [azurelinuxagent/common/cgroupconfigurator.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBjb25maWd1cmF0b3IucHk=) | `71.31% <56.25%> (+0.11%)` | :arrow_up: |
| [azurelinuxagent/common/cgroupapi.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBhcGkucHk=) | `81.50% <85.71%> (+0.10%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure). Last update [2d1edd3...7278883](https://codecov.io/gh/Azure/WALinuxAgent/pull/2450?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).


Patch:
diff --git a/azurelinuxagent/common/cgroupapi.py b/azurelinuxagent/common/cgroupapi.py
index db281661..6225a052 100644
--- a/azurelinuxagent/common/cgroupapi.py
+++ b/azurelinuxagent/common/cgroupapi.py
@@ -26,7 +26,8 @@ from azurelinuxagent.common import logger
 from azurelinuxagent.common.cgroup import CpuCgroup
 from azurelinuxagent.common.cgroupstelemetry import CGroupsTelemetry
 from azurelinuxagent.common.conf import get_agent_pid_file_path
-from azurelinuxagent.common.exception import CGroupsException, ExtensionErrorCodes, ExtensionError, ExtensionOperationError
+from azurelinuxagent.common.exception import CGroupsException, ExtensionErrorCodes, ExtensionError, \
+    ExtensionOperationError
 from azurelinuxagent.common.future import ustr
 from azurelinuxagent.common.osutil import systemd
 from azurelinuxagent.common.utils import fileutil, shellutil
@@ -39,10 +40,12 @@ CGROUPS_FILE_SYSTEM_ROOT = '/sys/fs/cgroup'
 CGROUP_CONTROLLERS = ["cpu", "memory"]
 EXTENSION_SLICE_PREFIX = "azure-vmextensions"
 
+
 class SystemdRunError(CGroupsException):
     """
     Raised when systemd-run fails
     """
+
     def __init__(self, msg=None):
         super(SystemdRunError, self).__init__(msg)
 
@@ -56,7 +59,9 @@ class CGroupsApi(object):
             distro_version = FlexibleVersion(distro_info[1])
         except ValueError:
             return False
-        return distro_name.lower() == 'ubuntu' and distro_version.major >= 16
+        return ((distro_name.lower() == 'ubuntu' and distro_version.major >= 16) or
+                (distro_name.lower() in ("centos", "redhat") and
+                 ((distro_version.major == 7 and distro_version.minor >= 8) or distro_version.major >= 8)))
 
     @staticmethod
     def track_cgroups(extension_cgroups):
@@ -118,6 +123,7 @@ class SystemdCgroupsApi(CGroupsApi):
     """
     Cgroups interface via systemd
     """
+
     def __init__(self):
         self._cgroup_mountpoints = None
         self._agent_unit_name = None
@@ -156,7 +162,7 @@ class SystemdCgroupsApi(CGroupsApi):
                         memory = path
             self._cgroup_mountpoints = {'cpu': cpu, 'memory': memory}
 
-        return self._cgroup_mountpoints['cpu'],  self._cgroup_mountpoints['memory']
+        return self._cgroup_mountpoints['cpu'], self._cgroup_mountpoints['memory']
 
     @staticmethod
     def get_process_cgroup_relative_paths(process_id):
@@ -253,7 +259,8 @@ class SystemdCgroupsApi(CGroupsApi):
         # Since '-' is used as a separator in systemd unit names, we replace it with '_' to prevent side-effects.
         return EXTENSION_SLICE_PREFIX + "-" + extension_name.replace('-', '_') + ".slice"
 
-    def start_extension_command(self, extension_name, command, cmd_name, timeout, shell, cwd, env, stdout, stderr, error_code=ExtensionErrorCodes.PluginUnknownFailure):
+    def start_extension_command(self, extension_name, command, cmd_name, timeout, shell, cwd, env, stdout, stderr,
+                                error_code=ExtensionErrorCodes.PluginUnknownFailure):
         scope = "{0}_{1}".format(cmd_name, uuid.uuid4())
         extension_slice_name = self.get_extension_slice_name(extension_name)
         with self._systemd_run_commands_lock:
@@ -293,7 +300,8 @@ class SystemdCgroupsApi(CGroupsApi):
 
         # Wait for process completion or timeout
         try:
-            return handle_process_completion(process=process, command=command, timeout=timeout, stdout=stdout, stderr=stderr, error_code=error_code)
+            return handle_process_completion(process=process, command=command, timeout=timeout, stdout=stdout,
+                                             stderr=stderr, error_code=error_code)
         except ExtensionError as e:
             # The extension didn't terminate successfully. Determine whether it was due to systemd errors or
             # extension errors.
@@ -309,7 +317,8 @@ class SystemdCgroupsApi(CGroupsApi):
 
             if isinstance(e, ExtensionOperationError):
                 # no-member: Instance of 'ExtensionError' has no 'exit_code' member (no-member) - Disabled: e is actually an ExtensionOperationError
-                err_msg = 'Systemd process exited with code %s and output %s' % (e.exit_code, process_output)  # pylint: disable=no-member
+                err_msg = 'Systemd process exited with code %s and output %s' % (
+                    e.exit_code, process_output)  # pylint: disable=no-member
             else:
                 err_msg = "Systemd timed-out, output: %s" % process_output
             raise SystemdRunError(err_msg)
diff --git a/azurelinuxagent/common/cgroupconfigurator.py b/azurelinuxagent/common/cgroupconfigurator.py
index f23a77e1..b0bb012e 100644
--- a/azurelinuxagent/common/cgroupconfigurator.py
+++ b/azurelinuxagent/common/cgroupconfigurator.py
@@ -96,11 +96,13 @@ CPUQuota={0}
 """
 _AGENT_THROTTLED_TIME_THRESHOLD = 120  # 2 minutes
 
+
 class DisableCgroups(object):
     ALL = "all"
     AGENT = "agent"
     EXTENSIONS = "extensions"
 
+
 def _log_cgroup_info(format_string, *args):
     message = format_string.format(*args)
     logger.info("[CGI] " + message)
@@ -120,6 +122,7 @@ class CGroupConfigurator(object):
     NOTE: with the exception of start_extension_command, none of the methods in this class
     raise exceptions (cgroup operations should not block extensions)
     """
+
     class _Impl(object):
         def __init__(self):
             self._initialized = False
@@ -165,7 +168,9 @@ class CGroupConfigurator(object):
                 self.__setup_azure_slice()
 
                 cpu_controller_root, memory_controller_root = self.__get_cgroup_controllers()
-                self._agent_cpu_cgroup_path, self._agent_memory_cgroup_path = self.__get_agent_cgroups(agent_slice, cpu_controller_root, memory_controller_root)
+                self._agent_cpu_cgroup_path, self._agent_memory_cgroup_path = self.__get_agent_cgroups(agent_slice,
+                                                                                                       cpu_controller_root,
+                                                                                                       memory_controller_root)
 
                 if self._agent_cpu_cgroup_path is not None:
                     _log_cgroup_info("Agent CPU cgroup: {0}", self._agent_cpu_cgroup_path)
@@ -218,7 +223,7 @@ class CGroupConfigurator(object):
             agent_service_name = get_osutil().get_service_name()
             try:
                 fragment_path = systemd.get_unit_property(agent_service_name, "FragmentPath")
-                if fragment_path != "/lib/systemd/system/{0}.service".format(agent_service_name):
+                if fragment_path != systemd.get_agent_unit_file():
                     agent_unit_files.append(fragment_path)
             except Exception as exception:
                 _log_cgroup_warning("Failed to query the agent's FragmentPath: {0}", ustr(exception))
@@ -233,7 +238,8 @@ class CGroupConfigurator(object):
             for unit_file in agent_unit_files:
                 try:
                     with open(unit_file, "r") as file_object:
-                        _log_cgroup_info("Found a custom unit file for the agent: {0}\n{1}", unit_file, file_object.read())
+                        _log_cgroup_info("Found a custom unit file for the agent: {0}\n{1}", unit_file,
+                                         file_object.read())
                 except Exception as exception:
                     _log_cgroup_warning("Can't read {0}: {1}", unit_file, ustr(exception))
 
@@ -269,7 +275,8 @@ class CGroupConfigurator(object):
             #
             cgroup2_mount_point, cgroup2_controllers = self._cgroups_api.get_cgroup2_controllers()
             if cgroup2_mount_point is not None:
-                _log_cgroup_info("cgroups v2 mounted at {0}.  Controllers: [{1}]", cgroup2_mount_point, cgroup2_controllers)
+                _log_cgroup_info("cgroups v2 mounted at {0}.  Controllers: [{1}]", cgroup2_mount_point,
+                                 cgroup2_controllers)
 
             return cpu_controller_root, memory_controller_root
 
@@ -322,7 +329,7 @@ class CGroupConfigurator(object):
 
             if not os.path.exists(logcollector_slice):
                 slice_contents = _LOGCOLLECTOR_SLICE_CONTENTS_FMT.format(cpu_quota=_LOGCOLLECTOR_CPU_QUOTA,
-                    memory_limit=_LOGCOLLECTOR_MEMORY_LIMIT)
+                                                                         memory_limit=_LOGCOLLECTOR_MEMORY_LIMIT)
 
                 files_to_create.append((logcollector_slice, slice_contents))
 
@@ -408,7 +415,8 @@ class CGroupConfigurator(object):
             agent_unit_name = systemd.get_agent_unit_name()
 
             expected_relative_path = os.path.join(agent_slice, agent_unit_name)
-            cpu_cgroup_relative_path, memory_cgroup_relative_path = self._cgroups_api.get_process_cgroup_relative_paths("self")
+            cpu_cgroup_relative_path, memory_cgroup_relative_path = self._cgroups_api.get_process_cgroup_relative_paths(
+                "self")
 
             if cpu_cgroup_relative_path is None:
                 _log_cgroup_warning("The agent's process is not within a CPU cgroup")
@@ -417,11 +425,11 @@ class CGroupConfigurator(object):
                     _log_cgroup_info('CPUAccounting: {0}', systemd.get_unit_property(agent_unit_name, "CPUAccounting"))
                     _log_cgroup_info('CPUQuota: {0}', systemd.get_unit_property(agent_unit_name, "CPUQuotaPerSecUSec"))
                 else:
-                    cpu_cgroup_relative_path = None  # Set the path to None to prevent monitoring
                     _log_cgroup_warning(
                         "The Agent is not in the expected CPU cgroup; will not enable monitoring. Cgroup:[{0}] Expected:[{1}]",
                         cpu_cgroup_relative_path,
                         expected_relative_path)
+                    cpu_cgroup_relative_path = None  # Set the path to None to prevent monitoring
 
             if memory_cgroup_relative_path is None:
                 _log_cgroup_warning("The agent's process is not within a memory cgroup")
@@ -430,11 +438,11 @@ class CGroupConfigurator(object):
                     memory_accounting = systemd.get_unit_property(agent_unit_name, "MemoryAccounting")
                     _log_cgroup_info('MemoryAccounting: {0}', memory_accounting)
                 else:
-                    memory_cgroup_relative_path = None  # Set the path to None to prevent monitoring
                     _log_cgroup_info(
                         "The Agent is not in the expected memory cgroup; will not enable monitoring. CGroup:[{0}] Expected:[{1}]",
                         memory_cgroup_relative_path,
                         expected_relative_path)
+                    memory_cgroup_relative_path = None  # Set the path to None to prevent monitoring
 
             if cpu_controller_root is not None and cpu_cgroup_relative_path is not None:
                 agent_cpu_cgroup_path = os.path.join(cpu_controller_root, cpu_cgroup_relative_path)
@@ -462,30 +470,30 @@ class CGroupConfigurator(object):
 
         def enable(self):
             if not self.supported():
-                raise CGroupsException("Attempted to enable cgroups, but they are not supported on the current platform")
+                raise CGroupsException(
+                    "Attempted to enable cgroups, but they are not supported on the current platform")
             self._agent_cgroups_enabled = True
             self._extensions_cgroups_enabled = True
             self.__set_cpu_quota(conf.get_agent_cpu_quota())
 
-        def disable(self, reason, disableCgroups):
+        def disable(self, reason, disable_cgroups):
             # Todo: disable/reset extension when ext quotas introduced
-            if disableCgroups == DisableCgroups.ALL:                 # disable all
+            if disable_cgroups == DisableCgroups.ALL:  # disable all
                 self._agent_cgroups_enabled = False
                 self._extensions_cgroups_enabled = False
                 self.__reset_agent_cpu_quota()
                 CGroupsTelemetry.reset()
-            elif disableCgroups == DisableCgroups.AGENT: # disable agent
+            elif disable_cgroups == DisableCgroups.AGENT:  # disable agent
                 self._agent_cgroups_enabled = False
                 self.__reset_agent_cpu_quota()
                 CGroupsTelemetry.stop_tracking(CpuCgroup(AGENT_NAME_TELEMETRY, self._agent_cpu_cgroup_path))
-            elif disableCgroups == DisableCgroups.EXTENSIONS: # disable extensions
+            elif disable_cgroups == DisableCgroups.EXTENSIONS:  # disable extensions
                 self._extensions_cgroups_enabled = False
 
             message = "[CGW] Disabling resource usage monitoring. Reason: {0}".format(reason)
             logger.info(message)  # log as INFO for now, in the future it should be logged as WARNING
             add_event(op=WALAEventOperation.CGroupsDisabled, message=message, is_success=False, log_event=False)
 
-
         @staticmethod
         def __set_cpu_quota(quota):
             """
@@ -510,6 +518,7 @@ class CGroupConfigurator(object):
             logger.info("Resetting agent's CPUQuota")
             if CGroupConfigurator._Impl.__try_set_cpu_quota(''):  # setting an empty value resets to the default (infinity)
                 CGroupsTelemetry.set_track_throttled_time(False)
+                _log_cgroup_info('CPUQuota: {0}', systemd.get_unit_property(systemd.get_agent_unit_name(), "CPUQuotaPerSecUSec"))
 
         @staticmethod
         def __try_set_cpu_quota(quota):
@@ -589,7 +598,8 @@ class CGroupConfigurator(object):
                     if process in (daemon, extension_handler) or process in systemd_run_commands:
                         continue
                     # systemd_run_commands contains the shell that started systemd-run, so we also need to check for the parent
-                    if self._get_parent(process) in systemd_run_commands and self._get_command(process) == 'systemd-run':
+                    if self._get_parent(process) in systemd_run_commands and self._get_command(
+                            process) == 'systemd-run':
                         continue
                     # check if the process is a command started by the agent or a descendant of one of those commands
                     current = process
@@ -697,7 +707,8 @@ class CGroupConfigurator(object):
             except Exception as exception:
                 logger.info("Failed to stop tracking resource usage for the extension service: {0}", ustr(exception))
 
-        def start_extension_command(self, extension_name, command, cmd_name, timeout, shell, cwd, env, stdout, stderr, error_code=ExtensionErrorCodes.PluginUnknownFailure):
+        def start_extension_command(self, extension_name, command, cmd_name, timeout, shell, cwd, env, stdout, stderr,
+                                    error_code=ExtensionErrorCodes.PluginUnknownFailure):
             """
             Starts a command (install/enable/etc) for an extension and adds the command's PID to the extension's cgroup
             :param extension_name: The extension executing the command
@@ -713,9 +724,12 @@ class CGroupConfigurator(object):
             """
             if self.enabled():
                 try:
-                    return self._cgroups_api.start_extension_command(extension_name, command, cmd_name, timeout, shell=shell, cwd=cwd, env=env, stdout=stdout, stderr=stderr, error_code=error_code)
+                    return self._cgroups_api.start_extension_command(extension_name, command, cmd_name, timeout,
+                                                                     shell=shell, cwd=cwd, env=env, stdout=stdout,
+                                                                     stderr=stderr, error_code=error_code)
                 except SystemdRunError as exception:
-                    reason = 'Failed to start {0} using systemd-run, will try invoking the extension directly. Error: {1}'.format(extension_name, ustr(exception))
+                    reason = 'Failed to start {0} using systemd-run, will try invoking the extension directly. Error: {1}'.format(
+                        extension_name, ustr(exception))
                     self.disable(reason, DisableCgroups.ALL)
                     # fall-through and re-invoke the extension
 
@@ -735,7 +749,7 @@ class CGroupConfigurator(object):
             if self.enabled():
                 unit_file_install_path = systemd.get_unit_file_install_path()
                 extension_slice_path = os.path.join(unit_file_install_path,
-                                                     SystemdCgroupsApi.get_extension_slice_name(extension_name))
+                                                    SystemdCgroupsApi.get_extension_slice_name(extension_name))
                 try:
                     slice_contents = _EXTENSION_SLICE_CONTENTS.format(extension_name=extension_name)
                     CGroupConfigurator._Impl.__create_unit_file(extension_slice_path, slice_contents)
@@ -755,12 +769,6 @@ class CGroupConfigurator(object):
                 if os.path.exists(extension_slice_path):
                     self.stop_tracking_extension_cgroups(extension_name)
                     CGroupConfigurator._Impl.__cleanup_unit_file(extension_slice_path)
-                # stop the unit gracefully; the extensions slices will be removed from /sys/fs/cgroup path
-                try:
-                    logger.info("Executing systemctl stop {0}".format(extension_slice_name))
-                    shellutil.run_command(["systemctl", "stop", extension_slice_name])
-                except Exception as exception:
-                    _log_cgroup_warning("systemctl stop failed (remove slice): {0}", ustr(exception))
 
         def set_extension_services_cpu_memory_quota(self, services_list):
             """
diff --git a/init/ubuntu/azure-vmextensions.slice b/init/azure-vmextensions.slice
similarity index 100%
rename from init/ubuntu/azure-vmextensions.slice
rename to init/azure-vmextensions.slice
diff --git a/init/ubuntu/azure.slice b/init/azure.slice
similarity index 100%
rename from init/ubuntu/azure.slice
rename to init/azure.slice
diff --git a/init/redhat/py2/waagent.service b/init/redhat/py2/waagent.service
new file mode 100644
index 00000000..c6d15420
--- /dev/null
+++ b/init/redhat/py2/waagent.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Azure Linux Agent
+Wants=network-online.target sshd.service sshd-keygen.service
+After=network-online.target
+
+ConditionFileIsExecutable=/usr/sbin/waagent
+ConditionPathExists=/etc/waagent.conf
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/python -u /usr/sbin/waagent -daemon
+Restart=always
+RestartSec=5
+Slice=azure.slice
+CPUAccounting=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/init/redhat/waagent.service b/init/redhat/waagent.service
index 39d01d1c..dc11fbb1 100644
--- a/init/redhat/waagent.service
+++ b/init/redhat/waagent.service
@@ -11,6 +11,8 @@ Type=simple
 ExecStart=/usr/bin/python3 -u /usr/sbin/waagent -daemon
 Restart=always
 RestartSec=5
+Slice=azure.slice
+CPUAccounting=yes
 
 [Install]
 WantedBy=multi-user.target
diff --git a/setup.py b/setup.py
index 28b41478..12c9e1d6 100755
--- a/setup.py
+++ b/setup.py
@@ -43,6 +43,7 @@ def set_bin_files(data_files, dest, src=None):
         src = ["bin/waagent", "bin/waagent2.0"]
     data_files.append((dest, src))
 
+
 def set_conf_files(data_files, dest="/etc", src=None):
     if src is None:
         src = ["config/waagent.conf"]
@@ -108,12 +109,21 @@ def get_data_files(name, version, fullname):  # pylint: disable=R0912
         if version.startswith("8.2"):
             # redhat 8+ uses systemd and python3
             set_systemd_files(data_files, dest=systemd_dir_path,
-                              src=["init/redhat/waagent.service"])
+                              src=["init/redhat/waagent.service",
+                              "init/azure.slice",
+                              "init/azure-vmextensions.slice"
+                                   ])
+
         elif version.startswith("6"):
             set_sysv_files(data_files)
         else:
             # redhat7.0+ use systemd
-            set_systemd_files(data_files, dest=systemd_dir_path)
+            set_systemd_files(data_files, dest=systemd_dir_path,
+                              src=[
+                                  "init/redhat/py2/waagent.service",
+                                  "init/azure.slice",
+                                  "init/azure-vmextensions.slice"
+                              ])
             if version.startswith("7.1"):
                 # TODO this is a mitigation to systemctl bug on 7.1
                 set_sysv_files(data_files)
@@ -167,8 +177,8 @@ def get_data_files(name, version, fullname):  # pylint: disable=R0912
             set_systemd_files(data_files, dest=systemd_dir_path,
                               src=[
                                   "init/ubuntu/walinuxagent.service",
-                                  "init/ubuntu/azure.slice",
-                                  "init/ubuntu/azure-vmextensions.slice"
+                                  "init/azure.slice",
+                                  "init/azure-vmextensions.slice"
                               ])
     elif name == 'suse' or name == 'opensuse':  # pylint: disable=R1714
         set_bin_files(data_files, dest=agent_bin_path)
@@ -184,9 +194,9 @@ def get_data_files(name, version, fullname):  # pylint: disable=R0912
         else:
             # sles 12+ and openSUSE 13.2+ use systemd
             set_systemd_files(data_files, dest=systemd_dir_path)
-    elif name == 'sles': # sles 15+ distro named as sles
+    elif name == 'sles':  # sles 15+ distro named as sles
         set_bin_files(data_files, dest=agent_bin_path,
-                      src = ["bin/py3/waagent", "bin/waagent2.0"])
+                      src=["bin/py3/waagent", "bin/waagent2.0"])
         set_conf_files(data_files, src=["config/suse/waagent.conf"])
         set_logrotate_files(data_files)
         set_udev_files(data_files)


Test patch:
diff --git a/tests/common/test_cgroupapi.py b/tests/common/test_cgroupapi.py
index ee18ba3d..9f7e4200 100644
--- a/tests/common/test_cgroupapi.py
+++ b/tests/common/test_cgroupapi.py
@@ -56,9 +56,14 @@ class CGroupsApiTestCase(_MockedFileSystemTestCase):
             (['ubuntu', '18.10', 'cosmic'], True),
             (['ubuntu', '20.04', 'focal'], True),
             (['ubuntu', '20.10', 'groovy'], True),
+            (['centos', '7.8', 'Source'], True),
+            (['redhat', '7.8', 'Maipo'], True),
+            (['redhat', '7.9.1908', 'Core'], True),
+            (['centos', '8.1', 'Source'], True),
+            (['redhat', '8.2', 'Maipo'], True),
+            (['redhat', '8.2.2111', 'Core'], True),
             (['centos', '7.5', 'Source'], False),
-            (['redhat', '7.7', 'Maipo'], False),
-            (['redhat', '7.7.1908', 'Core'], False),
+            (['redhat', '7.5', 'Maipo'], False),
             (['bigip', '15.0.1', 'Final'], False),
             (['gaia', '273.562', 'R80.30'], False),
             (['debian', '9.1', ''], False),