Repository: Azure/WALinuxAgent
Pull request #1545 (2019-06-04 16:34:52)

Improve error handling in remove cgroups
<!-- DO NOT DELETE THIS TEMPLATE -->

## Description

Issue # <!-- if any -->
<!--
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).
- [ ] Except for special cases involving multiple contributors, the PR is started from a fork of the main repository, not a branch.
- [ ] If applicable, the PR references the bug/issue that it fixes in the description.
- [ ] New Unit tests were added for the changes made and Travis.CI is passing.

### Quality of Code and Contribution Guidelines
- [ ] I have read the [contribution guidelines](https://github.com/Azure/WALinuxAgent/blob/master/.github/CONTRIBUTING.md).

<!-- 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/1545)
<!-- Reviewable:end -->


codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`cgroups@6e2a02a`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `85.71%`.

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

```diff
@@            Coverage Diff             @@
##             cgroups    #1545   +/-   ##
==========================================
  Coverage           ?   63.05%           
==========================================
  Files              ?       78           
  Lines              ?    10977           
  Branches           ?     1540           
==========================================
  Hits               ?     6922           
  Misses             ?     3721           
  Partials           ?      334
```


| [Impacted Files](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [azurelinuxagent/common/cgroupapi.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBhcGkucHk=) | `61.57% <85.71%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?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/1545?src=pr&el=footer). Last update [6e2a02a...221ab97](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`cgroups@6e2a02a`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `85.71%`.

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

```diff
@@            Coverage Diff             @@
##             cgroups    #1545   +/-   ##
==========================================
  Coverage           ?   63.05%           
==========================================
  Files              ?       78           
  Lines              ?    10977           
  Branches           ?     1540           
==========================================
  Hits               ?     6922           
  Misses             ?     3721           
  Partials           ?      334
```


| [Impacted Files](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [azurelinuxagent/common/cgroupapi.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545/diff?src=pr&el=tree#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9jZ3JvdXBhcGkucHk=) | `61.57% <85.71%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?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/1545?src=pr&el=footer). Last update [6e2a02a...221ab97](https://codecov.io/gh/Azure/WALinuxAgent/pull/1545?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/azurelinuxagent/common/cgroupapi.py b/azurelinuxagent/common/cgroupapi.py
index 0a6f5197..104522d1 100644
--- a/azurelinuxagent/common/cgroupapi.py
+++ b/azurelinuxagent/common/cgroupapi.py
@@ -16,7 +16,6 @@
 
 import errno
 import os
-import shutil
 import subprocess
 
 from azurelinuxagent.common import logger
@@ -244,7 +243,13 @@ class FileSystemCgroupsApi(CGroupsApi):
         def remove_cgroup(controller):
             path = self._get_extension_cgroup_path(controller, extension_name)
 
-            shutil.rmtree(path)
+            if os.path.exists(path):
+                try:
+                    os.rmdir(path)
+                    logger.info('Deleted cgroup "{0}".'.format(path))
+                except OSError as exception:
+                    if exception.errno == 16:  # [Errno 16] Device or resource busy
+                        logger.warn('CGroup "{0}" still has active tasks; will not remove it.'.format(path))
 
         self._foreach_controller(remove_cgroup, 'Failed to delete cgroups for extension {0}'.format(extension_name))
 


Test patch:
diff --git a/tests/common/test_cgroupapi.py b/tests/common/test_cgroupapi.py
index f7f7ea6c..12cd8ace 100644
--- a/tests/common/test_cgroupapi.py
+++ b/tests/common/test_cgroupapi.py
@@ -189,6 +189,18 @@ class FileSystemCgroupsApiTestCase(AgentTestCase):
         for cgroup in extension_cgroups:
             self.assertFalse(os.path.exists(cgroup.path))
 
+    def test_remove_extension_cgroups_should_log_a_warning_when_the_cgroup_contains_active_tasks(self):
+        api = FileSystemCgroupsApi()
+        api.create_extension_cgroups_root()
+        extension_cgroups = api.create_extension_cgroups("Microsoft.Compute.TestExtension-1.2.3")
+
+        with patch("azurelinuxagent.common.cgroupapi.logger.warn") as mock_logger_warn:
+            with patch("azurelinuxagent.common.cgroupapi.os.rmdir", side_effect=OSError(16, "Device or resource busy")):
+                api.remove_extension_cgroups("Microsoft.Compute.TestExtension-1.2.3")
+
+            args, kwargs = mock_logger_warn.call_args
+            message = args[0]
+            self.assertIn("still has active tasks", message)
 
     def test_get_extension_cgroups_should_return_all_cgroups(self):
         api = FileSystemCgroupsApi()