コード例 #1
0
    def test_start_extension_command_should_start_tracking_the_extension_cgroups(
            self, _):
        # 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 mock_cgroup_commands():
            CGroupConfiguratorSystemdTestCase._get_new_cgroup_configurator_instance(
            ).start_extension_command(
                extension_name="Microsoft.Compute.TestExtension-1.2.3",
                command="test command",
                timeout=300,
                shell=False,
                cwd=self.tmp_dir,
                env={},
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE)

        tracked = CGroupsTelemetry._tracked

        self.assertTrue(
            any(cg for cg in tracked
                if cg.name == 'Microsoft.Compute.TestExtension-1.2.3'
                and 'cpu' in cg.path),
            "The extension's CPU is not being tracked")
        self.assertTrue(
            any(cg for cg in tracked
                if cg.name == 'Microsoft.Compute.TestExtension-1.2.3'
                and 'memory' in cg.path),
            "The extension's memory is not being tracked")
コード例 #2
0
 def _get_new_cgroup_configurator_instance(initialize=True):
     CGroupConfigurator._instance = None
     configurator = CGroupConfigurator.get_instance()
     if initialize:
         with mock_cgroup_commands():
             configurator.initialize()
     return configurator
コード例 #3
0
    def test_get_processes_in_agent_cgroup_should_return_the_processes_within_the_agent_cgroup(
            self):
        with mock_cgroup_commands():
            configurator = CGroupConfiguratorSystemdTestCase._get_new_cgroup_configurator_instance(
            )

            processes = configurator.get_processes_in_agent_cgroup()

            self.assertTrue(
                len(processes) >= 2,
                "The cgroup should contain at least 2 procceses (daemon and extension handler): [{0}]"
                .format(processes))

            daemon_present = any("waagent -daemon" in command
                                 for (pid, command) in processes)
            self.assertTrue(
                daemon_present,
                "Could not find the daemon in the cgroup: [{0}]".format(
                    processes))

            extension_handler_present = any(
                re.search("(WALinuxAgent-.+\.egg|waagent) -run-exthandlers",
                          command) for (pid, command) in processes)
            self.assertTrue(
                extension_handler_present,
                "Could not find the extension handler in the cgroup: [{0}]".
                format(processes))
コード例 #4
0
    def test_start_extension_command_should_use_systemd_run_when_cgroups_are_enabled(
            self, _):
        with mock_cgroup_commands():
            with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen",
                       wraps=subprocess.Popen) as popen_patch:
                CGroupConfiguratorSystemdTestCase._get_new_cgroup_configurator_instance(
                ).start_extension_command(
                    extension_name="Microsoft.Compute.TestExtension-1.2.3",
                    command="the-test-extension-command",
                    timeout=300,
                    shell=False,
                    cwd=self.tmp_dir,
                    env={},
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

                command_calls = [
                    args[0] for (args, _) in popen_patch.call_args_list
                    if "the-test-extension-command" in args[0]
                ]

                self.assertEqual(
                    len(command_calls), 1,
                    "The test command should have been called exactly once [{0}]"
                    .format(command_calls))
                self.assertIn(
                    "systemd-run --unit=Microsoft.Compute.TestExtension_1.2.3",
                    command_calls[0],
                    "The extension should have been invoked using systemd")
コード例 #5
0
    def test_start_extension_command_should_execute_the_command_in_a_cgroup(
            self, _):
        with mock_cgroup_commands():
            SystemdCgroupsApi().start_extension_command(
                extension_name="Microsoft.Compute.TestExtension-1.2.3",
                command="test command",
                shell=False,
                timeout=300,
                cwd=self.tmp_dir,
                env={},
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE)

            tracked = CGroupsTelemetry._tracked

            self.assertTrue(
                any(cg for cg in tracked
                    if cg.name == 'Microsoft.Compute.TestExtension-1.2.3'
                    and 'cpu' in cg.path),
                "The extension's CPU is not being tracked")
            self.assertTrue(
                any(cg for cg in tracked
                    if cg.name == 'Microsoft.Compute.TestExtension-1.2.3'
                    and 'memory' in cg.path),
                "The extension's memory is not being tracked")
コード例 #6
0
    def test_start_extension_command_should_use_systemd_to_execute_the_command(
            self, _):
        with mock_cgroup_commands():
            with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen",
                       wraps=subprocess.Popen) as popen_patch:
                SystemdCgroupsApi().start_extension_command(
                    extension_name="Microsoft.Compute.TestExtension-1.2.3",
                    command="the-test-extension-command",
                    timeout=300,
                    shell=True,
                    cwd=self.tmp_dir,
                    env={},
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

                extension_calls = [
                    args[0] for (args, _) in popen_patch.call_args_list
                    if "the-test-extension-command" in args[0]
                ]

                self.assertEquals(
                    1, len(extension_calls),
                    "The extension should have been invoked exactly once")
                self.assertIn(
                    "systemd-run --unit=Microsoft.Compute.TestExtension_1.2.3",
                    extension_calls[0],
                    "The extension should have been invoked using systemd")
コード例 #7
0
    def test_get_processes_in_cgroup_should_return_the_processes_within_the_cgroup(
            self):
        with mock_cgroup_commands():
            processes = SystemdCgroupsApi.get_processes_in_cgroup(
                "/sys/fs/cgroup/cpu/system.slice/walinuxagent.service")

            self.assertTrue(
                len(processes) >= 2,
                "The cgroup should contain at least 2 procceses (daemon and extension handler): [{0}]"
                .format(processes))

            daemon_present = any("waagent -daemon" in command
                                 for (pid, command) in processes)
            self.assertTrue(
                daemon_present,
                "Could not find the daemon in the cgroup: [{0}]".format(
                    processes))

            extension_handler_present = any(
                re.search("(WALinuxAgent-.+\.egg|waagent) -run-exthandlers",
                          command) for (pid, command) in processes)
            self.assertTrue(
                extension_handler_present,
                "Could not find the extension handler in the cgroup: [{0}]".
                format(processes))
コード例 #8
0
    def test_start_extension_command_should_return_the_command_output(self, _):
        original_popen = subprocess.Popen

        def mock_popen(command, *args, **kwargs):
            if command.startswith(
                    'systemd-run --unit=Microsoft.Compute.TestExtension_1.2.3'
            ):
                command = "echo TEST_OUTPUT"
            return original_popen(command, *args, **kwargs)

        with mock_cgroup_commands() as mock_commands:
            with tempfile.TemporaryFile(dir=self.tmp_dir,
                                        mode="w+b") as output_file:
                with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen",
                           side_effect=mock_popen) as popen_patch:
                    command_output = SystemdCgroupsApi(
                    ).start_extension_command(
                        extension_name="Microsoft.Compute.TestExtension-1.2.3",
                        command="A_TEST_COMMAND",
                        shell=True,
                        timeout=300,
                        cwd=self.tmp_dir,
                        env={},
                        stdout=output_file,
                        stderr=output_file)

                    self.assertIn("[stdout]\nTEST_OUTPUT\n", command_output,
                                  "The test output was not captured")
コード例 #9
0
 def test_get_systemd_version_should_return_a_version_number(self):
     with mock_cgroup_commands():
         version_info = SystemdCgroupsApi.get_systemd_version()
         found = re.search("systemd \d+", version_info) is not None
         self.assertTrue(
             found, "Could not determine the systemd version: {0}".format(
                 version_info))
コード例 #10
0
    def test_get_unit_property_should_return_the_value_of_the_given_property(
            self):
        with mock_cgroup_commands():
            cpu_accounting = SystemdCgroupsApi.get_unit_property(
                "walinuxagent.service", "CPUAccounting")

            self.assertEquals(
                cpu_accounting, "no",
                "Property {0} of {1} is incorrect".format(
                    "CPUAccounting", "walinuxagent.service"))
コード例 #11
0
 def test_get_cpu_and_memory_mount_points_should_return_the_cgroup_mount_points(
         self):
     with mock_cgroup_commands():
         cpu, memory = SystemdCgroupsApi().get_cgroup_mount_points()
         self.assertEquals(
             cpu, '/sys/fs/cgroup/cpu,cpuacct',
             "The mount point for the CPU controller is incorrect")
         self.assertEquals(
             memory, '/sys/fs/cgroup/memory',
             "The mount point for the memory controller is incorrect")
コード例 #12
0
 def test_get_cpu_and_memory_cgroup_relative_paths_for_process_should_return_the_cgroup_relative_paths(
         self):
     with mock_cgroup_commands():
         cpu, memory = SystemdCgroupsApi.get_process_cgroup_relative_paths(
             'self')
         self.assertEquals(
             cpu, "system.slice/walinuxagent.service",
             "The relative path for the CPU cgroup is incorrect")
         self.assertEquals(
             memory, "system.slice/walinuxagent.service",
             "The relative memory for the CPU cgroup is incorrect")
コード例 #13
0
    def test_get_cgroup2_controllers_should_return_the_v2_cgroup_controllers(
            self):
        with mock_cgroup_commands():
            mount_point, controllers = SystemdCgroupsApi.get_cgroup2_controllers(
            )

            self.assertEquals(mount_point, "/sys/fs/cgroup/unified",
                              "Invalid mount point for V2 cgroups")
            self.assertIn(
                "cpu", controllers,
                "The CPU controller is not in the list of V2 controllers")
            self.assertIn(
                "memory", controllers,
                "The memory controller is not in the list of V2 controllers")
コード例 #14
0
    def test_it_should_report_processes_that_do_not_belong_to_the_agent_cgroup(
            self):
        with mock_cgroup_commands() as mock_commands:
            mock_commands.add_command(
                r'^systemd-cgls.+/walinuxagent.service$', '''
Directory /sys/fs/cgroup/cpu/system.slice/walinuxagent.service:
├─27519 /usr/bin/python3 -u /usr/sbin/waagent -daemon
├─27547 python3 -u bin/WALinuxAgent-2.2.48.1-py2.7.egg -run-exthandlers
├─6200 systemd-cgls /sys/fs/cgroup/cpu,cpuacct/system.slice/walinuxagent.service
├─5821 pidof systemd-networkd
├─5822 iptables --version
├─5823 iptables -w -t security -D OUTPUT -d 168.63.129.16 -p tcp -m conntrack --ctstate INVALID,NEW -j ACCEPT
├─5824 iptables -w -t security -D OUTPUT -d 168.63.129.16 -p tcp -m owner --uid-owner 0 -j ACCEPT
├─5825 ip route show
├─5826 ifdown eth0 && ifup eth0
├─5699 bash /var/lib/waagent/Microsoft.CPlat.Core.RunCommandLinux-1.0.1/bin/run-command-shim enable
├─5701 tee -ia /var/log/azure/run-command/handler.log
├─5719 /var/lib/waagent/Microsoft.CPlat.Core.RunCommandLinux-1.0.1/bin/run-command-extension enable
├─5727 /bin/sh -c /var/lib/waagent/run-command/download/1/script.sh
└─5728 /bin/sh /var/lib/waagent/run-command/download/1/script.sh
''')
            with patch("azurelinuxagent.ga.monitor.add_event"
                       ) as add_event_patcher:
                PollResourceUsageOperation().run()

                messages = [
                    kwargs["message"]
                    for (_, kwargs) in add_event_patcher.call_args_list
                    if "The agent's cgroup includes unexpected processes" in
                    kwargs["message"]
                ]

                self.assertEqual(
                    1, len(messages),
                    "Exactly 1 telemetry event should have been reported. Events: {0}"
                    .format(messages))

                unexpected_processes = [
                    'bash /var/lib/waagent/Microsoft.CPlat.Core.RunCommandLinux-1.0.1/bin/run-command-shim enable',
                    'tee -ia /var/log/azure/run-command/handler.log',
                    '/var/lib/waagent/Microsoft.CPlat.Core.RunCommandLinux-1.0.1/bin/run-command-extension enable',
                    '/bin/sh -c /var/lib/waagent/run-command/download/1/script.sh',
                    '/bin/sh /var/lib/waagent/run-command/download/1/script.sh',
                ]

                for fp in unexpected_processes:
                    self.assertIn(
                        fp, messages[0],
                        "[{0}] was not reported as an unexpected process. Events: {1}"
                        .format(fp, messages))

                # The list of processes in the message is an array of strings: "['foo', ..., 'bar']"
                search = re.search(r'\[(?P<processes>.+)\]', messages[0])
                self.assertIsNotNone(
                    search,
                    "The event message is not in the expected format: {0}".
                    format(messages[0]))
                processes = search.group('processes')
                self.assertEquals(
                    5, len(processes.split(',')),
                    'Extra processes were reported as unexpected: {0}'.format(
                        processes))
コード例 #15
0
 def setUpClass(cls):
     AgentTestCase.setUpClass()
     # ensure cgroups are enabled by forcing a new instance
     CGroupConfigurator._instance = None
     with mock_cgroup_commands():
         CGroupConfigurator.get_instance().initialize()