Repository: Azure/WALinuxAgent
Pull request #1725 (2019-12-04 20:20:57)

Initialize CPU usage
The CPU usage for the cgroup was not initialized when creating the CpuCgroup (the system usage was).

Now initialization sets both values and is done when we start tracking the cgroup (as opposed as when it is created). We can create cgroups and never track them so this is a better place for initialization.

Now CPU is computed as a percentage of usage for all cores (e.g. if a cgroup was using 2 cores at 100% on a 4-core system, now we report 50% instead of 200%). This makes data easier to use.

Also, added field #8 of /proc/stat to the computation of CPU (see "man proc"):
> steal (since Linux 2.6.11)
     (8) Stolen time, which is the time spent in other operating systems when running in a virtualized environment

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/azure/walinuxagent/1725)
<!-- Reviewable:end -->


codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=h1) Report
> Merging [#1725](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=desc) into [develop](https://codecov.io/gh/Azure/WALinuxAgent/commit/00c75b12bc50a1eb72e816c798f8d179b832fa37?src=pr&el=desc) will **increase** coverage by `0.03%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725/graphs/tree.svg?width=650&token=ae90E2KYCw&height=150&src=pr)](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=tree)

```diff
@@             Coverage Diff             @@
##           develop    #1725      +/-   ##
===========================================
+ Coverage    68.16%   68.19%   +0.03%     
===========================================
  Files           80       80              
  Lines        11609    11617       +8     
  Branches      1631     1634       +3     
===========================================
+ Hits          7913     7922       +9     
+ Misses        3359     3357       -2     
- Partials       337      338       +1
```


| [Impacted Files](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [azurelinuxagent/common/cgroup.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXAucHk=) | `91.05% <100%> (+0.37%)` | :arrow_up: |
| [azurelinuxagent/common/osutil/default.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9vc3V0aWwvZGVmYXVsdC5weQ==) | `59.9% <100%> (-0.12%)` | :arrow_down: |
| [azurelinuxagent/common/cgroupstelemetry.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBzdGVsZW1ldHJ5LnB5) | `96.64% <100%> (+0.06%)` | :arrow_up: |
| [azurelinuxagent/common/cgroupapi.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBhcGkucHk=) | `85.18% <0%> (+0.74%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=footer). Last update [00c75b1...9a3bb6d](https://codecov.io/gh/Azure/WALinuxAgent/pull/1725?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 7533c59c..80468e39 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@
 # Microsoft Azure Linux Agent
 
-## Master branch status
+## Develop branch status
 
 [![Travis CI](https://travis-ci.org/Azure/WALinuxAgent.svg?branch=develop)](https://travis-ci.org/Azure/WALinuxAgent/branches)
 [![CodeCov](https://codecov.io/gh/Azure/WALinusAgent/branch/develop/graph/badge.svg)](https://codecov.io/gh/Azure/WALinuxAgent/branch/develop)
 
 Each badge below represents our basic validation tests for an image, which are executed several times each day. These include provisioning, user account, disk, extension and networking scenarios.
 
+Note: These badges represent testing to our develop branch which might not be stable. For a stable build please use master branch instead. 
+
 Image | Status |
 ------|--------|
 Canonical UbuntuServer 14.04.5-LTS|![badge](https://dcrbadges.blob.core.windows.net/scenarios/Canonical_UbuntuServer_14.04.5-LTS__agent--bvt.svg)
diff --git a/azurelinuxagent/common/cgroup.py b/azurelinuxagent/common/cgroup.py
index 858fa9da..1f940b5f 100644
--- a/azurelinuxagent/common/cgroup.py
+++ b/azurelinuxagent/common/cgroup.py
@@ -61,13 +61,9 @@ class CGroup(object):
         :return: Entire contents of the file
         :rtype: str
         """
-
         parameter_file = self._get_cgroup_file(file_name)
 
-        try:
-            return fileutil.read_file(parameter_file)
-        except Exception:
-            raise
+        return fileutil.read_file(parameter_file)
 
     def _get_parameters(self, parameter_name, first_line_only=False):
         """
@@ -118,76 +114,78 @@ class CGroup(object):
 
 class CpuCgroup(CGroup):
     def __init__(self, name, cgroup_path):
-        """
-        Initialize _data collection for the Cpu controller. User must call update() before attempting to get
-        any useful metrics.
-
-        :return: CpuCgroup
-        """
         super(CpuCgroup, self).__init__(name, cgroup_path, "cpu")
 
         self._osutil = get_osutil()
-        self._current_cpu_total = 0
-        self._previous_cpu_total = 0
-        self._current_system_cpu = self._osutil.get_total_cpu_ticks_since_boot()
-        self._previous_system_cpu = 0
+        self._previous_cgroup_cpu = None
+        self._previous_system_cpu = None
+        self._current_cgroup_cpu = None
+        self._current_system_cpu = None
 
     def __str__(self):
         return "cgroup: Name: {0}, cgroup_path: {1}; Controller: {2}".format(
             self.name, self.path, self.controller
         )
 
-    def _get_current_cpu_total(self):
+    def _get_cpu_ticks(self, allow_no_such_file_or_directory_error=False):
         """
-        Compute the number of USER_HZ of CPU time (user and system) consumed by this cgroup since boot.
+        Returns the number of USER_HZ of CPU time (user and system) consumed by this cgroup.
 
-        :return: int
+        If allow_no_such_file_or_directory_error is set to True and cpuacct.stat does not exist the function
+        returns 0; this is useful when the function can be called before the cgroup has been created.
         """
-        cpu_total = 0
         try:
             cpu_stat = self._get_file_contents('cpuacct.stat')
         except Exception as e:
-            if isinstance(e, (IOError, OSError)) and e.errno == errno.ENOENT:
+            if not isinstance(e, (IOError, OSError)) or e.errno != errno.ENOENT:
+                raise CGroupsException("Failed to read cpuacct.stat: {0}".format(ustr(e)))
+            if not allow_no_such_file_or_directory_error:
                 raise e
-            raise CGroupsException("Exception while attempting to read {0}".format("cpuacct.stat"), e)
+            cpu_stat = None
+
+        cpu_ticks = 0
+
+        if cpu_stat is not None:
+            match = re_user_system_times.match(cpu_stat)
+            if not match:
+                raise CGroupsException("The contents of {0} are invalid: {1}".format(self._get_cgroup_file('cpuacct.stat'), cpu_stat))
+            cpu_ticks = int(match.groups()[0]) + int(match.groups()[1])
+
+        return cpu_ticks
 
-        if cpu_stat:
-            m = re_user_system_times.match(cpu_stat)
-            if m:
-                cpu_total = int(m.groups()[0]) + int(m.groups()[1])
-        return cpu_total
+    def _cpu_usage_initialized(self):
+        return self._current_cgroup_cpu is not None and self._current_system_cpu is not None
 
-    def _update_cpu_data(self):
+    def initialize_cpu_usage(self):
         """
-        Update all raw _data required to compute metrics of interest. The intent is to call update() once, then
-        call the various get_*() methods which use this _data, which we've collected exactly once.
+        Sets the initial values of CPU usage. This function must be invoked before calling get_cpu_usage().
         """
-        self._previous_cpu_total = self._current_cpu_total
-        self._previous_system_cpu = self._current_system_cpu
-        self._current_cpu_total = self._get_current_cpu_total()
+        if self._cpu_usage_initialized():
+            raise CGroupsException("initialize_cpu_usage() should be invoked only once")
+        self._current_cgroup_cpu = self._get_cpu_ticks(allow_no_such_file_or_directory_error=True)
         self._current_system_cpu = self._osutil.get_total_cpu_ticks_since_boot()
 
-    def _get_cpu_percent(self):
+    def get_cpu_usage(self):
         """
-        Compute the percent CPU time used by this cgroup over the elapsed time since the last time this instance was
-        update()ed.  If the cgroup fully consumed 2 cores on a 4 core system, return 200.
+        Computes the CPU used by the cgroup since the last call to this function.
+
+        The usage is measured as a percentage of utilization of all cores in the system. For example,
+        using 1 core at 100% on a 4-core system would be reported as 25%.
 
-        :return: CPU usage in percent of a single core
-        :rtype: float
+        NOTE: initialize_cpu_usage() must be invoked before calling get_cpu_usage()
         """
-        cpu_delta = self._current_cpu_total - self._previous_cpu_total
-        system_delta = max(1, self._current_system_cpu - self._previous_system_cpu)
+        if not self._cpu_usage_initialized():
+            raise CGroupsException("initialize_cpu_usage() must be invoked before the first call to get_cpu_usage()")
 
-        return round(float(cpu_delta * self._osutil.get_processor_cores() * 100) / float(system_delta), 3)
+        self._previous_cgroup_cpu = self._current_cgroup_cpu
+        self._previous_system_cpu = self._current_system_cpu
+        self._current_cgroup_cpu = self._get_cpu_ticks()
+        self._current_system_cpu = self._osutil.get_total_cpu_ticks_since_boot()
 
-    def get_cpu_usage(self):
-        """
-        Collects and return the cpu usage.
+        cgroup_delta = self._current_cgroup_cpu - self._previous_cgroup_cpu
+        system_delta = max(1, self._current_system_cpu - self._previous_system_cpu)
 
-        :rtype: float
-        """
-        self._update_cpu_data()
-        return self._get_cpu_percent()
+        return round(100.0 * float(cgroup_delta) / float(system_delta), 3)
 
 
 class MemoryCgroup(CGroup):
diff --git a/azurelinuxagent/common/cgroupstelemetry.py b/azurelinuxagent/common/cgroupstelemetry.py
index dcc586a3..3d136520 100644
--- a/azurelinuxagent/common/cgroupstelemetry.py
+++ b/azurelinuxagent/common/cgroupstelemetry.py
@@ -19,6 +19,7 @@ from collections import namedtuple
 from datetime import datetime as dt
 
 from azurelinuxagent.common import logger
+from azurelinuxagent.common.cgroup import CpuCgroup
 from azurelinuxagent.common.exception import CGroupsException
 from azurelinuxagent.common.future import ustr
 
@@ -68,6 +69,10 @@ class CGroupsTelemetry(object):
         """
         Adds the given item to the dictionary of tracked cgroups
         """
+        if isinstance(cgroup, CpuCgroup):
+            # set the current cpu usage
+            cgroup.initialize_cpu_usage()
+
         with CGroupsTelemetry._rlock:
             if not CGroupsTelemetry.is_tracked(cgroup.path):
                 CGroupsTelemetry._tracked.append(cgroup)
diff --git a/azurelinuxagent/common/osutil/default.py b/azurelinuxagent/common/osutil/default.py
index b99bca43..90a6e739 100644
--- a/azurelinuxagent/common/osutil/default.py
+++ b/azurelinuxagent/common/osutil/default.py
@@ -1354,7 +1354,7 @@ class DefaultOSUtil(object):
         if proc_stat is not None:
             for line in proc_stat.splitlines():
                 if ALL_CPUS_REGEX.match(line):
-                    system_cpu = sum(int(i) for i in line.split()[1:7])
+                    system_cpu = sum(int(i) for i in line.split()[1:8])  # see "man proc" for a description of these fields
                     break
         return system_cpu
 
diff --git a/azurelinuxagent/daemon/resourcedisk/default.py b/azurelinuxagent/daemon/resourcedisk/default.py
index 5ed14b01..35ddfb4e 100644
--- a/azurelinuxagent/daemon/resourcedisk/default.py
+++ b/azurelinuxagent/daemon/resourcedisk/default.py
@@ -249,14 +249,20 @@ class ResourceDiskHandler(object):
 
         return err_code, output
 
-    @staticmethod
-    def get_mount_string(mount_options, partition, mount_point):
+    def get_mount_string(self, mount_options, partition, mount_point):
         if mount_options is not None:
-            return 'mount -o {0} {1} {2}'.format(mount_options,
-                                                 partition,
-                                                 mount_point)
+            return 'mount -t {0} -o {1} {2} {3}'.format(
+                self.fs,
+                mount_options,
+                partition,
+                mount_point
+            )
         else:
-            return 'mount {0} {1}'.format(partition, mount_point)
+            return 'mount -t {0} {1} {2}'.format(
+                self.fs,
+                partition,
+                mount_point
+            )
 
     @staticmethod
     def check_existing_swap_file(swapfile, swaplist, size):


Test patch:
diff --git a/tests/common/test_cgroupconfigurator.py b/tests/common/test_cgroupconfigurator.py
index fcc816cf..0f4e9108 100644
--- a/tests/common/test_cgroupconfigurator.py
+++ b/tests/common/test_cgroupconfigurator.py
@@ -203,15 +203,18 @@ class CGroupConfiguratorTestCase(AgentTestCase):
             self.assertEqual(mock_start_extension_command.call_count, 1)
 
     def test_start_extension_command_should_start_tracking_the_extension_cgroups(self):
-        CGroupConfigurator.get_instance().start_extension_command(
-            extension_name="Microsoft.Compute.TestExtension-1.2.3",
-            command="date",
-            timeout=300,
-            shell=False,
-            cwd=self.tmp_dir,
-            env={},
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE)
+        # CPU usage is initialized when we begin tracking a CPU cgroup; since this test does not retrieve the
+        # CPU usage, there is no need for initialization
+        with patch("azurelinuxagent.common.cgroup.CpuCgroup.initialize_cpu_usage"):
+            CGroupConfigurator.get_instance().start_extension_command(
+                extension_name="Microsoft.Compute.TestExtension-1.2.3",
+                command="date",
+                timeout=300,
+                shell=False,
+                cwd=self.tmp_dir,
+                env={},
+                stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE)
 
         self.assertTrue(CGroupsTelemetry.is_tracked(os.path.join(
             self.cgroups_file_system_root, "cpu", "walinuxagent.extensions/Microsoft.Compute.TestExtension_1.2.3")))
diff --git a/tests/common/test_cgroups.py b/tests/common/test_cgroups.py
index b33bc94f..6827fb8b 100644
--- a/tests/common/test_cgroups.py
+++ b/tests/common/test_cgroups.py
@@ -17,6 +17,7 @@
 
 from __future__ import print_function
 
+import errno
 import os
 import random
 
@@ -46,10 +47,7 @@ class TestCGroup(AgentTestCase):
         with open(os.path.join(data_dir, "cgroups", "memory_mount", "tasks"), mode="wb") as tasks:
             tasks.truncate(0)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    def test_correct_creation(self, *_):
+    def test_correct_creation(self):
         test_cgroup = CGroup.create("dummy_path", "cpu", "test_extension")
         self.assertIsInstance(test_cgroup, CpuCgroup)
         self.assertEqual(test_cgroup.controller, "cpu")
@@ -62,10 +60,7 @@ class TestCGroup(AgentTestCase):
         self.assertEqual(test_cgroup.path, "dummy_path")
         self.assertEqual(test_cgroup.name, "test_extension")
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    def test_is_active(self, *_):
+    def test_is_active(self):
         test_cgroup = CGroup.create(os.path.join(data_dir, "cgroups", "cpu_mount"), "cpu", "test_extension")
         self.assertEqual(False, test_cgroup.is_active())
 
@@ -82,11 +77,8 @@ class TestCGroup(AgentTestCase):
 
         self.assertEqual(True, test_cgroup.is_active())
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch("azurelinuxagent.common.logger.periodic_warn")
-    def test_is_active_file_not_present(self, patch_periodic_warn, *_):
+    def test_is_active_file_not_present(self, patch_periodic_warn):
         test_cgroup = CGroup.create(os.path.join(data_dir, "cgroups", "not_cpu_mount"), "cpu", "test_extension")
         self.assertEqual(False, test_cgroup.is_active())
 
@@ -95,11 +87,8 @@ class TestCGroup(AgentTestCase):
 
         self.assertEqual(0, patch_periodic_warn.call_count)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch("azurelinuxagent.common.logger.periodic_warn")
-    def test_is_active_incorrect_file(self, patch_periodic_warn, *_):
+    def test_is_active_incorrect_file(self, patch_periodic_warn):
         test_cgroup = CGroup.create(os.path.join(data_dir, "cgroups", "cpu_mount", "tasks"), "cpu", "test_extension")
         self.assertEqual(False, test_cgroup.is_active())
         self.assertEqual(1, patch_periodic_warn.call_count)
@@ -110,49 +99,115 @@ class TestCGroup(AgentTestCase):
 
 
 class TestCpuCgroup(AgentTestCase):
+    @classmethod
+    def setUpClass(cls):
+        AgentTestCase.setUpClass()
+
+        original_read_file = fileutil.read_file
+
+        #
+        # Tests that need to mock the contents of /proc/stat or */cpuacct/stat can set this map from
+        # the file that needs to be mocked to the mock file (each test starts with an empty map). If
+        # an Exception is given instead of a path, the exception is raised
+        #
+        cls.mock_read_file_map = {}
+
+        def mock_read_file(filepath, **args):
+            if filepath in cls.mock_read_file_map:
+                mapped_value = cls.mock_read_file_map[filepath]
+                if isinstance(mapped_value, Exception):
+                    raise mapped_value
+                filepath = mapped_value
+            return original_read_file(filepath, **args)
+
+        cls.mock_read_file = patch("azurelinuxagent.common.utils.fileutil.read_file", side_effect=mock_read_file)
+        cls.mock_read_file.start()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.mock_read_file.stop()
+        AgentTestCase.tearDownClass()
+
     def setUp(self):
         AgentTestCase.setUp(self)
+        TestCpuCgroup.mock_read_file_map.clear()
+
+    def test_initialize_cpu_usage_should_set_current_cpu_usage(self):
+        cgroup = CpuCgroup("test", "/sys/fs/cgroup/cpu/system.slice/test")
+
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t0"),
+            os.path.join(cgroup.path, "cpuacct.stat"): os.path.join(data_dir, "cgroups", "cpuacct.stat_t0")
+        }
+
+        cgroup.initialize_cpu_usage()
+
+        self.assertEquals(cgroup._current_cgroup_cpu, 63763)
+        self.assertEquals(cgroup._current_system_cpu, 5496872)
+
+    def test_get_cpu_usage_should_return_the_cpu_usage_since_its_last_invocation(self):
+        cgroup = CpuCgroup("test", "/sys/fs/cgroup/cpu/system.slice/test")
+
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t0"),
+            os.path.join(cgroup.path, "cpuacct.stat"): os.path.join(data_dir, "cgroups", "cpuacct.stat_t0")
+        }
+
+        cgroup.initialize_cpu_usage()
+
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t1"),
+            os.path.join(cgroup.path, "cpuacct.stat"): os.path.join(data_dir, "cgroups", "cpuacct.stat_t1")
+        }
+
+        cpu_usage = cgroup.get_cpu_usage()
+
+        self.assertEquals(cpu_usage, 0.031)
+
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t2"),
+            os.path.join(cgroup.path, "cpuacct.stat"): os.path.join(data_dir, "cgroups", "cpuacct.stat_t2")
+        }
+
+        cpu_usage = cgroup.get_cpu_usage()
+
+        self.assertEquals(cpu_usage, 0.045)
+
+    def test_initialie_cpu_usage_should_set_the_cgroup_usage_to_0_when_the_cgroup_does_not_exist(self):
+        cgroup = CpuCgroup("test", "/sys/fs/cgroup/cpu/system.slice/test")
+
+        io_error_2 = IOError()
+        io_error_2.errno = errno.ENOENT  # "No such directory"
+
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t0"),
+            os.path.join(cgroup.path, "cpuacct.stat"): io_error_2
+        }
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    def test_cpu_cgroup_create(self, patch_get_proc_stat):
-        patch_get_proc_stat.return_value = fileutil.read_file(os.path.join(data_dir, "cgroups", "dummy_proc_stat"))
-        test_cpu_cg = CpuCgroup("test_extension", "dummy_path")
+        cgroup.initialize_cpu_usage()
 
-        self.assertEqual(398488, test_cpu_cg._current_system_cpu)
-        self.assertEqual(0, test_cpu_cg._current_cpu_total)
-        self.assertEqual(0, test_cpu_cg._previous_cpu_total)
-        self.assertEqual(0, test_cpu_cg._previous_system_cpu)
+        self.assertEquals(cgroup._current_cgroup_cpu, 0)
+        self.assertEquals(cgroup._current_system_cpu, 5496872)  # check the system usage just for test sanity
 
-        self.assertEqual("cpu", test_cpu_cg.controller)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_processor_cores", return_value=1)
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    def test_get_cpu_usage(self, patch_get_proc_stat, *args):
-        patch_get_proc_stat.return_value = fileutil.read_file(os.path.join(data_dir, "cgroups", "dummy_proc_stat"))
-        test_cpu_cg = CpuCgroup("test_extension", os.path.join(data_dir, "cgroups", "cpu_mount"))
+    def test_initialize_cpu_usage_should_raise_an_exception_when_called_more_than_once(self):
+        cgroup = CpuCgroup("test", "/sys/fs/cgroup/cpu/system.slice/test")
 
-        # Mocking CPU consumption
-        patch_get_proc_stat.return_value = fileutil.read_file(os.path.join(data_dir, "cgroups",
-                                                                           "dummy_proc_stat_updated"))
+        TestCpuCgroup.mock_read_file_map = {
+            "/proc/stat": os.path.join(data_dir, "cgroups", "proc_stat_t0"),
+            os.path.join(cgroup.path, "cpuacct.stat"): os.path.join(data_dir, "cgroups", "cpuacct.stat_t0")
+        }
 
-        cpu_usage = test_cpu_cg.get_cpu_usage()
+        cgroup.initialize_cpu_usage()
 
-        self.assertEqual(5.114, cpu_usage)
+        with self.assertRaises(CGroupsException):
+            cgroup.initialize_cpu_usage()
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    def test_get_current_cpu_total_exception_handling(self, *_):
-        test_cpu_cg = CpuCgroup("test_extension", "dummy_path")
-        self.assertRaises(IOError, test_cpu_cg._get_current_cpu_total)
+    def test_get_cpu_usage_should_raise_an_exception_when_initialize_cpu_usage_has_not_been_invoked(self):
+        cgroup = CpuCgroup("test", "/sys/fs/cgroup/cpu/system.slice/test")
 
-        # Trying to raise ERRNO 20.
-        test_cpu_cg = CpuCgroup("test_extension", os.path.join(data_dir, "cgroups", "cpu_mount", "cpuacct.stat"))
-        self.assertRaises(CGroupsException, test_cpu_cg._get_current_cpu_total)
+        with self.assertRaises(CGroupsException):
+            cpu_usage = cgroup.get_cpu_usage()
 
 
 class TestMemoryCgroup(AgentTestCase):
@@ -176,4 +231,4 @@ class TestMemoryCgroup(AgentTestCase):
         self.assertEqual(0, memory_usage)
 
         max_memory_usage = test_mem_cg.get_max_memory_usage()
-        self.assertEqual(0, max_memory_usage)
\ No newline at end of file
+        self.assertEqual(0, max_memory_usage)
diff --git a/tests/common/test_cgroupstelemetry.py b/tests/common/test_cgroupstelemetry.py
index e53b08cc..c6d14d48 100644
--- a/tests/common/test_cgroupstelemetry.py
+++ b/tests/common/test_cgroupstelemetry.py
@@ -24,10 +24,11 @@ from azurelinuxagent.common.cgroupconfigurator import CGroupConfigurator
 from azurelinuxagent.common.cgroupstelemetry import CGroupsTelemetry, Metric
 from azurelinuxagent.common.osutil.default import BASE_CGROUPS, DefaultOSUtil
 from azurelinuxagent.common.protocol.restapi import ExtHandlerProperties, ExtHandler
+from azurelinuxagent.common.utils import fileutil
 from azurelinuxagent.ga.exthandlers import ExtHandlerInstance
 from nose.plugins.attrib import attr
 from tests.tools import AgentTestCase, skip_if_predicate_false, skip_if_predicate_true, \
-                        are_cgroups_enabled, is_trusty_in_travis, i_am_root, patch
+                        are_cgroups_enabled, is_trusty_in_travis, i_am_root, data_dir, patch
 
 
 def raise_ioerror(*_):
@@ -77,6 +78,28 @@ def make_new_cgroup(name="test-cgroup"):
 
 
 class TestCGroupsTelemetry(AgentTestCase):
+    @classmethod
+    def setUpClass(cls):
+        AgentTestCase.setUpClass()
+
+        # CPU Cgroups compute usage based on /proc/stat and /sys/fs/cgroup/.../cpuacct.stat; use mock data for those files
+        original_read_file = fileutil.read_file
+
+        def mock_read_file(filepath, **args):
+            if filepath == "/proc/stat":
+                filepath = os.path.join(data_dir, "cgroups", "proc_stat_t0")
+            elif filepath.endswith("/cpuacct.stat"):
+                filepath = os.path.join(data_dir, "cgroups", "cpuacct.stat_t0")
+            return original_read_file(filepath, **args)
+
+        cls._mock_read_cpu_cgroup_file = patch("azurelinuxagent.common.utils.fileutil.read_file", side_effect=mock_read_file)
+        cls._mock_read_cpu_cgroup_file.start()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls._mock_read_cpu_cgroup_file.stop()
+        AgentTestCase.tearDownClass()
+
     def setUp(self):
         AgentTestCase.setUp(self)
         CGroupsTelemetry.reset()
@@ -104,8 +127,6 @@ class TestCGroupsTelemetry(AgentTestCase):
                 elif metric.counter == "Max Memory Usage":
                     self.assertEqual(metric.value, max_memory_metric_value)
 
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_telemetry_polling_with_active_cgroups(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -118,7 +139,7 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage") as patch_get_memory_max_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
-                with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
+                with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
                     with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
                         patch_is_active.return_value = True
 
@@ -126,7 +147,7 @@ class TestCGroupsTelemetry(AgentTestCase):
                         current_memory = 209715200
                         current_max_memory = 471859200
 
-                        patch_get_cpu_percent.return_value = current_cpu
+                        patch_get_cpu_usage.return_value = current_cpu
                         patch_get_memory_usage.return_value = current_memory  # example 200 MB
                         patch_get_memory_max_usage.return_value = current_max_memory  # example 450 MB
 
@@ -147,8 +168,6 @@ class TestCGroupsTelemetry(AgentTestCase):
                         self.assertEqual(CGroupsTelemetry._cgroup_metrics.__len__(), num_extensions)
                         self._assert_cgroup_metrics_equal([], [], [])
 
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_telemetry_polling_with_inactive_cgroups(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -161,7 +180,7 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage") as patch_get_memory_max_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
-                with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
+                with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
                     with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
                         patch_is_active.return_value = False
 
@@ -171,7 +190,7 @@ class TestCGroupsTelemetry(AgentTestCase):
                         current_memory = 209715200
                         current_max_memory = 471859200
 
-                        patch_get_cpu_percent.return_value = current_cpu
+                        patch_get_cpu_usage.return_value = current_cpu
                         patch_get_memory_usage.return_value = current_memory  # example 200 MB
                         patch_get_memory_max_usage.return_value = current_max_memory  # example 450 MB
 
@@ -198,8 +217,6 @@ class TestCGroupsTelemetry(AgentTestCase):
                         self.assertEqual(CGroupsTelemetry._cgroup_metrics.__len__(), no_extensions_expected)
                         self._assert_cgroup_metrics_equal([], [], [])
 
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_telemetry_polling_with_changing_cgroups_state(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -212,7 +229,7 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage") as patch_get_memory_max_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
-                with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
+                with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
                     with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
                         patch_is_active.return_value = True
 
@@ -223,7 +240,7 @@ class TestCGroupsTelemetry(AgentTestCase):
                         current_memory = 209715200
                         current_max_memory = 471859200
 
-                        patch_get_cpu_percent.return_value = current_cpu
+                        patch_get_cpu_usage.return_value = current_cpu
                         patch_get_memory_usage.return_value = current_memory  # example 200 MB
                         patch_get_memory_max_usage.return_value = current_max_memory  # example 450 MB
 
@@ -257,13 +274,8 @@ class TestCGroupsTelemetry(AgentTestCase):
                         self.assertEqual(CGroupsTelemetry._cgroup_metrics.__len__(), no_extensions_expected)
                         self._assert_cgroup_metrics_equal([], [], [])
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch("azurelinuxagent.common.logger.periodic_warn")
-    @patch("azurelinuxagent.common.utils.fileutil.read_file")
-    def test_telemetry_polling_to_not_generate_transient_logs_ioerror_file_not_found(self, mock_read_file,
-                                                                                     patch_periodic_warn, *args):
+    def test_telemetry_polling_to_not_generate_transient_logs_ioerror_file_not_found(self, patch_periodic_warn):
         num_extensions = 1
         for i in range(num_extensions):
             dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
@@ -278,20 +290,15 @@ class TestCGroupsTelemetry(AgentTestCase):
         # Not expecting logs present for io_error with errno=errno.ENOENT
         io_error_2 = IOError()
         io_error_2.errno = errno.ENOENT
-        mock_read_file.side_effect = io_error_2
 
-        poll_count = 1
-        for data_count in range(poll_count, 10):
-            CGroupsTelemetry.poll_all_tracked()
-            self.assertEqual(0, patch_periodic_warn.call_count)
+        with patch("azurelinuxagent.common.utils.fileutil.read_file", side_effect=io_error_2):
+            poll_count = 1
+            for data_count in range(poll_count, 10):
+                CGroupsTelemetry.poll_all_tracked()
+                self.assertEqual(0, patch_periodic_warn.call_count)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch("azurelinuxagent.common.logger.periodic_warn")
-    @patch("azurelinuxagent.common.utils.fileutil.read_file")
-    def test_telemetry_polling_to_generate_transient_logs_ioerror_permission_denied(self, mock_read_file,
-                                                                                    patch_periodic_warn, *args):
+    def test_telemetry_polling_to_generate_transient_logs_ioerror_permission_denied(self, patch_periodic_warn):
         num_extensions = 1
         num_controllers = 2
         is_active_check_per_controller = 2
@@ -309,22 +316,18 @@ class TestCGroupsTelemetry(AgentTestCase):
         # Expecting logs to be present for different kind of errors
         io_error_3 = IOError()
         io_error_3.errno = errno.EPERM
-        mock_read_file.side_effect = io_error_3
 
-        poll_count = 1
-        expected_count_per_call = num_controllers + is_active_check_per_controller
-        # each collect per controller would generate a log statement, and each cgroup would invoke a
-        # is active check raising an exception
+        with patch("azurelinuxagent.common.utils.fileutil.read_file", side_effect=io_error_3):
+            poll_count = 1
+            expected_count_per_call = num_controllers + is_active_check_per_controller
+            # each collect per controller would generate a log statement, and each cgroup would invoke a
+            # is active check raising an exception
 
-        for data_count in range(poll_count, 10):
-            CGroupsTelemetry.poll_all_tracked()
-            self.assertEqual(poll_count * expected_count_per_call, patch_periodic_warn.call_count)
+            for data_count in range(poll_count, 10):
+                CGroupsTelemetry.poll_all_tracked()
+                self.assertEqual(poll_count * expected_count_per_call, patch_periodic_warn.call_count)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
-    @patch("azurelinuxagent.common.utils.fileutil.read_file")
-    def test_telemetry_polling_to_generate_transient_logs_index_error(self, mock_read_file, *args):
+    def test_telemetry_polling_to_generate_transient_logs_index_error(self):
         num_extensions = 1
         for i in range(num_extensions):
             dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
@@ -336,17 +339,13 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         # Generating a different kind of error (non-IOError) to check the logging.
         # Trying to invoke IndexError during the getParameter call
-        mock_read_file.return_value = ''
-
-        with patch("azurelinuxagent.common.logger.periodic_warn") as patch_periodic_warn:
-            expected_call_count = 1  # called only once at start, and then gets removed from the tracked data.
-            for data_count in range(1, 10):
-                CGroupsTelemetry.poll_all_tracked()
-                self.assertEqual(expected_call_count, patch_periodic_warn.call_count)
+        with patch("azurelinuxagent.common.utils.fileutil.read_file", return_value=''):
+            with patch("azurelinuxagent.common.logger.periodic_warn") as patch_periodic_warn:
+                expected_call_count = 2  # 1 periodic warning for the cpu cgroups, and 1 for memory
+                for data_count in range(1, 10):
+                    CGroupsTelemetry.poll_all_tracked()
+                    self.assertEqual(expected_call_count, patch_periodic_warn.call_count)
 
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._update_cpu_data")
     def test_telemetry_calculations(self, *args):
         num_polls = 10
         num_extensions = 1
@@ -370,11 +369,11 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage") as patch_get_memory_max_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
-                with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
+                with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
                     with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
                         for i in range(num_polls):
                             patch_is_active.return_value = True
-                            patch_get_cpu_percent.return_value = cpu_percent_values[i]
+                            patch_get_cpu_usage.return_value = cpu_percent_values[i]
                             patch_get_memory_usage.return_value = memory_usage_values[i]  # example 200 MB
                             patch_get_memory_max_usage.return_value = max_memory_usage_values[i]  # example 450 MB
                             metrics = CGroupsTelemetry.poll_all_tracked()
@@ -404,29 +403,25 @@ class TestCGroupsTelemetry(AgentTestCase):
             self.assertListEqual(generate_metric_list(cpu_percent_values),
                                  collected_metrics[name]["cpu"]["cur_cpu"][0:5])
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     def test_cgroup_tracking(self, *args):
-        num_extensions = 5
-        num_controllers = 2
-        for i in range(num_extensions):
-            dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
-            CGroupsTelemetry.track_cgroup(dummy_cpu_cgroup)
+        with patch("azurelinuxagent.common.cgroup.CpuCgroup.initialize_cpu_usage") as patch_initialize_cpu_usage:
+            num_extensions = 5
+            num_controllers = 2
+            for i in range(num_extensions):
+                dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
+                CGroupsTelemetry.track_cgroup(dummy_cpu_cgroup)
 
-            dummy_memory_cgroup = CGroup.create("dummy_memory_path_{0}".format(i), "memory",
-                                                "dummy_extension_{0}".format(i))
-            CGroupsTelemetry.track_cgroup(dummy_memory_cgroup)
+                dummy_memory_cgroup = CGroup.create("dummy_memory_path_{0}".format(i), "memory",
+                                                    "dummy_extension_{0}".format(i))
+                CGroupsTelemetry.track_cgroup(dummy_memory_cgroup)
 
-        for i in range(num_extensions):
-            self.assertTrue(CGroupsTelemetry.is_tracked("dummy_cpu_path_{0}".format(i)))
-            self.assertTrue(CGroupsTelemetry.is_tracked("dummy_memory_path_{0}".format(i)))
+            for i in range(num_extensions):
+                self.assertTrue(CGroupsTelemetry.is_tracked("dummy_cpu_path_{0}".format(i)))
+                self.assertTrue(CGroupsTelemetry.is_tracked("dummy_memory_path_{0}".format(i)))
 
-        self.assertEqual(num_extensions * num_controllers, len(CGroupsTelemetry._tracked))
+            self.assertEqual(num_extensions * num_controllers, len(CGroupsTelemetry._tracked))
+            self.assertEqual(num_extensions, patch_initialize_cpu_usage.call_count)
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     def test_cgroup_pruning(self, *args):
         num_extensions = 5
         num_controllers = 2
@@ -452,9 +447,6 @@ class TestCGroupsTelemetry(AgentTestCase):
 
         self.assertEqual(0, len(CGroupsTelemetry._tracked))
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     def test_cgroup_is_tracked(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -472,9 +464,6 @@ class TestCGroupsTelemetry(AgentTestCase):
         self.assertFalse(CGroupsTelemetry.is_tracked("not_present_cpu_dummy_path"))
         self.assertFalse(CGroupsTelemetry.is_tracked("not_present_memory_dummy_path"))
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     def test_process_cgroup_metric_with_incorrect_cgroups_mounted(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -501,8 +490,6 @@ class TestCGroupsTelemetry(AgentTestCase):
                     collected_metrics[name] = CGroupsTelemetry._process_cgroup_metric(cgroup_metrics)
                     self.assertEqual(collected_metrics[name], {})  # empty
 
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_process_cgroup_metric_with_no_memory_cgroup_mounted(self, *args):
         num_extensions = 5
 
@@ -514,14 +501,14 @@ class TestCGroupsTelemetry(AgentTestCase):
                                                 "dummy_extension_{0}".format(i))
             CGroupsTelemetry.track_cgroup(dummy_memory_cgroup)
 
-        with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
+        with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
                 with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
                     patch_is_active.return_value = True
                     patch_get_memory_usage.side_effect = Exception("File not found")
 
                     current_cpu = 30
-                    patch_get_cpu_percent.return_value = current_cpu
+                    patch_get_cpu_usage.return_value = current_cpu
 
                     poll_count = 1
 
@@ -538,8 +525,6 @@ class TestCGroupsTelemetry(AgentTestCase):
                     self.assertEqual(CGroupsTelemetry._cgroup_metrics.__len__(), num_extensions)
                     self._assert_cgroup_metrics_equal([], [], [])
 
-    @patch("azurelinuxagent.common.cgroup.CpuCgroup._get_current_cpu_total")
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_process_cgroup_metric_with_no_cpu_cgroup_mounted(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
@@ -585,7 +570,6 @@ class TestCGroupsTelemetry(AgentTestCase):
     @patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage", side_effect=raise_ioerror)
     @patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage", side_effect=raise_ioerror)
     @patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage", side_effect=raise_ioerror)
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil.get_total_cpu_ticks_since_boot")
     def test_extension_telemetry_not_sent_for_empty_perf_metrics(self, *args):
         num_extensions = 5
         for i in range(num_extensions):
diff --git a/tests/daemon/test_resourcedisk.py b/tests/daemon/test_resourcedisk.py
index 3f43c733..ebaa18c9 100644
--- a/tests/daemon/test_resourcedisk.py
+++ b/tests/daemon/test_resourcedisk.py
@@ -26,7 +26,7 @@ class TestResourceDisk(AgentTestCase):
         partition = '/dev/sdb1'
         mountpoint = '/mnt/resource'
         options = None
-        expected = 'mount /dev/sdb1 /mnt/resource'
+        expected = 'mount -t ext3 /dev/sdb1 /mnt/resource'
         rdh = ResourceDiskHandler()
         mount_string = rdh.get_mount_string(options, partition, mountpoint)
         self.assertEqual(expected, mount_string)
@@ -35,7 +35,7 @@ class TestResourceDisk(AgentTestCase):
         partition = '/dev/sdb1'
         mountpoint = '/mnt/resource'
         options = 'noexec,noguid,nodev'
-        expected = 'mount -o noexec,noguid,nodev /dev/sdb1 /mnt/resource'
+        expected = 'mount -t ext3 -o noexec,noguid,nodev /dev/sdb1 /mnt/resource'
         rdh = ResourceDiskHandler()
         mount_string = rdh.get_mount_string(options, partition, mountpoint)
         self.assertEqual(expected, mount_string)
diff --git a/tests/data/cgroups/cpuacct.stat_t0 b/tests/data/cgroups/cpuacct.stat_t0
new file mode 100644
index 00000000..fd0576fd
--- /dev/null
+++ b/tests/data/cgroups/cpuacct.stat_t0
@@ -0,0 +1,2 @@
+user 42380
+system 21383
diff --git a/tests/data/cgroups/cpuacct.stat_t1 b/tests/data/cgroups/cpuacct.stat_t1
new file mode 100644
index 00000000..3c0def97
--- /dev/null
+++ b/tests/data/cgroups/cpuacct.stat_t1
@@ -0,0 +1,2 @@
+user 42390
+system 21390
diff --git a/tests/data/cgroups/cpuacct.stat_t2 b/tests/data/cgroups/cpuacct.stat_t2
new file mode 100644
index 00000000..c79bfeb9
--- /dev/null
+++ b/tests/data/cgroups/cpuacct.stat_t2
@@ -0,0 +1,2 @@
+user 42417
+system 21428
diff --git a/tests/data/cgroups/dummy_proc_stat b/tests/data/cgroups/proc_stat_t0
similarity index 53%
rename from tests/data/cgroups/dummy_proc_stat
rename to tests/data/cgroups/proc_stat_t0
index 37288001..5f5ebda6 100644
--- a/tests/data/cgroups/dummy_proc_stat
+++ b/tests/data/cgroups/proc_stat_t0
@@ -1,12 +1,12 @@
-cpu  40362 2657 5493 349635 341 0 938 0 0 0
-cpu0 10043 1084 1319 86971 129 0 369 0 0 0
-cpu1 10069 653 1244 87708 51 0 202 0 0 0
-cpu2 10416 528 1492 87075 86 0 239 0 0 0
-cpu3 9833 391 1436 87878 73 0 126 0 0 0
-intr 1202440 15 1020 0 0 0 0 0 0 1 579 0 0 85138 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 572 65513 499 34 53368 177617 392 149 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-ctxt 2294069
-btime 1562092648
-processes 3715
-procs_running 1
+cpu  1242996 18547 360544 3839094 7843 0 27848 0 0 0
+cpu0 305718 4380 129988 2580650 5164 0 11050 0 0 0
+cpu1 316342 4742 80358 416652 1001 0 8333 0 0 0
+cpu2 311233 4916 75691 419501 720 0 4268 0 0 0
+cpu3 309702 4508 74507 422289 956 0 4196 0 0 0
+intr 78869641 14 5118 0 0 0 0 0 0 1 17275956 0 0 977671 0 0 0 0 0 0 0 1285764 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24614913 290 40 7069 56 9208 8660 8574436 0 0 0 0 0 0 0 0 0 0 0 0 10238 107667 2597 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ctxt 145952189
+btime 1575311513
+processes 49655
+procs_running 2
 procs_blocked 0
-softirq 1244004 191505 366613 7 1187 62878 0 1006 328256 2205 290347
\ No newline at end of file
+softirq 36699327 11497379 8043346 4993 1111315 54 54 1755674 7556345 0 6730167
diff --git a/tests/data/cgroups/proc_stat_t1 b/tests/data/cgroups/proc_stat_t1
new file mode 100644
index 00000000..59e41c00
--- /dev/null
+++ b/tests/data/cgroups/proc_stat_t1
@@ -0,0 +1,12 @@
+cpu  1251670 18548 368052 3877822 7926 0 28103 0 0 0
+cpu0 307860 4380 135060 2583922 5171 0 11173 0 0 0
+cpu1 318474 4742 81276 428425 1019 0 8384 0 0 0
+cpu2 313521 4916 76464 431225 748 0 4297 0 0 0
+cpu3 311814 4508 75250 434248 986 0 4247 0 0 0
+intr 81910494 14 5118 0 0 0 0 0 0 1 18573886 0 0 977671 0 0 0 0 0 0 0 1291486 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25913782 290 40 7152 56 9383 8954 8604958 0 0 0 0 0 0 0 0 0 0 0 0 10367 107667 2672 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ctxt 150920611
+btime 1575311513
+processes 49693
+procs_running 4
+procs_blocked 0
+softirq 37131388 11544829 8149486 5023 1127332 54 54 1776947 7667169 0 6860494
diff --git a/tests/data/cgroups/dummy_proc_stat_updated b/tests/data/cgroups/proc_stat_t2
similarity index 53%
rename from tests/data/cgroups/dummy_proc_stat_updated
rename to tests/data/cgroups/proc_stat_t2
index f0ef0c91..63ecce02 100644
--- a/tests/data/cgroups/dummy_proc_stat_updated
+++ b/tests/data/cgroups/proc_stat_t2
@@ -1,12 +1,12 @@
-cpu  286534 2705 70195 2971012 1358 0 11637 0 0 0
-cpu0 73053 1096 18020 739721 460 0 3510 0 0 0
-cpu1 70934 664 16722 745032 184 0 2552 0 0 0
-cpu2 74991 539 17715 739096 505 0 3128 0 0 0
-cpu3 67554 405 17736 747162 208 0 2446 0 0 0
-intr 16171532 15 6790 0 0 0 0 0 0 1 2254 0 0 550798 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50645 129322 4209 34 458202 1721987 504 149 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-ctxt 36112837
-btime 1562092648
-processes 27949
+cpu  1293131 18554 388040 3961230 8246 0 28928 0 0 0
+cpu0 317730 4381 146935 2591197 5184 0 11535 0 0 0
+cpu1 329039 4746 84213 453402 1178 0 8587 0 0 0
+cpu2 324213 4917 79154 456426 826 0 4410 0 0 0
+cpu3 322147 4509 77737 460203 1057 0 4395 0 0 0
+intr 89815534 14 5118 0 0 0 0 0 0 1 21544211 0 0 977671 0 0 0 0 0 0 0 1306547 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29282036 290 40 7566 56 10241 9584 8929545 0 0 0 0 0 0 0 0 0 0 0 0 11076 107667 2867 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ctxt 162816290
+btime 1575311513
+processes 49900
 procs_running 2
-procs_blocked 1
-softirq 17121870 1838273 5563635 21 8079 119728 0 6931 5982692 2629 3599882
\ No newline at end of file
+procs_blocked 0
+softirq 38518020 11917848 8439326 5100 1170153 54 54 1834614 7944771 0 7206100
diff --git a/tests/ga/test_monitor.py b/tests/ga/test_monitor.py
index 33bd5208..8b3a2144 100644
--- a/tests/ga/test_monitor.py
+++ b/tests/ga/test_monitor.py
@@ -30,7 +30,7 @@ from nose.plugins.attrib import attr
 
 import azurelinuxagent.common.conf as conf
 from azurelinuxagent.common import event, logger
-from azurelinuxagent.common.cgroup import CGroup, CpuCgroup
+from azurelinuxagent.common.cgroup import CGroup, CpuCgroup, MemoryCgroup
 from azurelinuxagent.common.cgroupconfigurator import CGroupConfigurator
 from azurelinuxagent.common.cgroupstelemetry import CGroupsTelemetry, MetricValue
 from azurelinuxagent.common.datacontract import get_properties
@@ -901,9 +901,6 @@ class TestExtensionMetricsDataTelemetry(AgentTestCase):
         self.assertEqual(0, patch_add_metric.call_count)
         monitor_handler.stop()
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch('azurelinuxagent.common.event.EventLogger.add_metric')
     @patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage")
     @patch('azurelinuxagent.common.logger.Logger.periodic_warn')
@@ -914,7 +911,7 @@ class TestExtensionMetricsDataTelemetry(AgentTestCase):
         ioerror.errno = 2
         patch_get_memory_usage.side_effect = ioerror
 
-        CGroupsTelemetry._tracked.append(CpuCgroup("cgroup_name", "/test/path"))
+        CGroupsTelemetry._tracked.append(MemoryCgroup("cgroup_name", "/test/path"))
 
         monitor_handler = get_monitor_handler()
         monitor_handler.init_protocols()
@@ -925,9 +922,6 @@ class TestExtensionMetricsDataTelemetry(AgentTestCase):
         self.assertEqual(0, patch_add_metric.call_count)  # No metrics should be sent.
         monitor_handler.stop()
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     @patch('azurelinuxagent.common.event.EventLogger.add_metric')
     @patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage")
     @patch('azurelinuxagent.common.logger.Logger.periodic_warn')
@@ -1141,9 +1135,6 @@ for i in range(3):
 
         monitor_handler.stop()
 
-    # mocking get_proc_stat to make it run on Mac and other systems. This test does not need to read the values of the
-    # /proc/stat file on the filesystem.
-    @patch("azurelinuxagent.common.osutil.default.DefaultOSUtil._get_proc_stat")
     def test_generate_extension_metrics_telemetry_dictionary(self, *args):
         num_polls = 10
         num_extensions = 1
@@ -1155,27 +1146,28 @@ for i in range(3):
         memory_usage_values = [random.randint(0, 8 * 1024 ** 3) for _ in range(num_polls)]
         max_memory_usage_values = [random.randint(0, 8 * 1024 ** 3) for _ in range(num_polls)]
 
-        for i in range(num_extensions):
-            dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
-            CGroupsTelemetry.track_cgroup(dummy_cpu_cgroup)
+        # no need to initialize the CPU usage, since we mock get_cpu_usage() below
+        with patch("azurelinuxagent.common.cgroup.CpuCgroup.initialize_cpu_usage"):
+            for i in range(num_extensions):
+                dummy_cpu_cgroup = CGroup.create("dummy_cpu_path_{0}".format(i), "cpu", "dummy_extension_{0}".format(i))
+                CGroupsTelemetry.track_cgroup(dummy_cpu_cgroup)
 
-            dummy_memory_cgroup = CGroup.create("dummy_memory_path_{0}".format(i), "memory",
-                                                "dummy_extension_{0}".format(i))
-            CGroupsTelemetry.track_cgroup(dummy_memory_cgroup)
+                dummy_memory_cgroup = CGroup.create("dummy_memory_path_{0}".format(i), "memory",
+                                                    "dummy_extension_{0}".format(i))
+                CGroupsTelemetry.track_cgroup(dummy_memory_cgroup)
 
         self.assertEqual(2 * num_extensions, len(CGroupsTelemetry._tracked))
 
         with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_max_memory_usage") as patch_get_memory_max_usage:
             with patch("azurelinuxagent.common.cgroup.MemoryCgroup.get_memory_usage") as patch_get_memory_usage:
-                with patch("azurelinuxagent.common.cgroup.CpuCgroup._get_cpu_percent") as patch_get_cpu_percent:
-                    with patch("azurelinuxagent.common.cgroup.CpuCgroup._update_cpu_data") as patch_update_cpu_data:
-                        with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
-                            for i in range(num_polls):
-                                patch_is_active.return_value = True
-                                patch_get_cpu_percent.return_value = cpu_percent_values[i]
-                                patch_get_memory_usage.return_value = memory_usage_values[i]  # example 200 MB
-                                patch_get_memory_max_usage.return_value = max_memory_usage_values[i]  # example 450 MB
-                                CGroupsTelemetry.poll_all_tracked()
+                with patch("azurelinuxagent.common.cgroup.CpuCgroup.get_cpu_usage") as patch_get_cpu_usage:
+                    with patch("azurelinuxagent.common.cgroup.CGroup.is_active") as patch_is_active:
+                        for i in range(num_polls):
+                            patch_is_active.return_value = True
+                            patch_get_cpu_usage.return_value = cpu_percent_values[i]
+                            patch_get_memory_usage.return_value = memory_usage_values[i]  # example 200 MB
+                            patch_get_memory_max_usage.return_value = max_memory_usage_values[i]  # example 450 MB
+                            CGroupsTelemetry.poll_all_tracked()
 
         performance_metrics = CGroupsTelemetry.report_all_tracked()