Exemple #1
0
 def test_read_output_it_should_truncate_the_content(self):
     with patch(
             'azurelinuxagent.common.utils.processutil.TELEMETRY_MESSAGE_MAX_LEN',
             10):
         expected = "[stdout]\nThe quick \n\n[stderr]\nThe five b"
         actual = read_output(self.stdout, self.stderr)
         self.assertEqual(expected, actual)
Exemple #2
0
    def test_save_event_message_with_non_ascii_characters(self):
        test_data_dir = os.path.join(
            data_dir, "events", "collect_and_send_extension_stdout_stderror")
        msg = ""

        with open(os.path.join(test_data_dir,
                               "dummy_stdout_with_non_ascii_characters"),
                  mode="r+b") as stdout:
            with open(os.path.join(test_data_dir,
                                   "dummy_stderr_with_non_ascii_characters"),
                      mode="r+b") as stderr:
                msg = read_output(stdout, stderr)

        duration = elapsed_milliseconds(datetime.utcnow())
        log_msg = "{0}\n{1}".format(
            "DummyCmd",
            "\n".join([line for line in msg.split('\n') if line != ""]))

        add_event('test_extension', message=log_msg, duration=duration)

        for tld_file in os.listdir(self.tmp_dir):
            event_str = MonitorHandler.collect_event(
                os.path.join(self.tmp_dir, tld_file))
            event_json = json.loads(event_str)

            self.assertEqual(len(event_json["parameters"]), 8)

            for i in event_json["parameters"]:
                if i["name"] == "Name":
                    self.assertEqual(i["value"], "test_extension")
                if i["name"] == "Message":
                    self.assertEqual(i["value"], log_msg)
Exemple #3
0
 def test_read_output_it_should_return_no_content(self):
     with patch(
             'azurelinuxagent.common.utils.processutil.TELEMETRY_MESSAGE_MAX_LEN',
             0):
         expected = "[stdout]\n\n\n[stderr]\n"
         actual = read_output(self.stdout, self.stderr)
         self.assertEqual(expected, actual)
Exemple #4
0
 def test_read_output_it_should_return_all_content(self):
     with patch(
             'azurelinuxagent.common.utils.processutil.TELEMETRY_MESSAGE_MAX_LEN',
             50):
         expected = "[stdout]\nThe quick brown fox jumps over the lazy dog.\n\n" \
                    "[stderr]\nThe five boxing wizards jump quickly."
         actual = read_output(self.stdout, self.stderr)
         self.assertEqual(expected, actual)
    def test_start_extension_command_should_capture_only_the_last_subprocess_output(
            self):
        original_popen = subprocess.Popen

        def mock_popen(*args, **kwargs):
            # Inject a syntax error to the call
            systemd_command = args[0].replace('systemd-run',
                                              'systemd-run syntax_error')
            new_args = (systemd_command, )
            return original_popen(new_args, **kwargs)

        with tempfile.TemporaryFile(dir=self.tmp_dir, mode="w+b") as stdout:
            with tempfile.TemporaryFile(dir=self.tmp_dir,
                                        mode="w+b") as stderr:
                with patch("azurelinuxagent.common.cgroupapi.add_event"
                           ) as mock_add_event:
                    with patch(
                            "azurelinuxagent.common.cgroupapi.subprocess.Popen",
                            side_effect=mock_popen) as patch_mock_popen:
                        # We expect this call to fail because of the syntax error
                        process, extension_cgroups = SystemdCgroupsApi(
                        ).start_extension_command(
                            extension_name=
                            "Microsoft.Compute.TestExtension-1.2.3",
                            command="echo 'very specific test message'",
                            shell=True,
                            cwd=self.tmp_dir,
                            env={},
                            stdout=stdout,
                            stderr=stderr)

                        process.wait()
                        process_output = read_output(stdout, stderr)
                        self.assertEquals(
                            "[stdout]\nvery specific test message\n\n\n[stderr]\n",
                            process_output)
Exemple #6
0
 def test_read_output_it_should_handle_exceptions(self):
     with patch(
             'azurelinuxagent.common.utils.processutil.TELEMETRY_MESSAGE_MAX_LEN',
             "type error"):
         actual = read_output(self.stdout, self.stderr)
         self.assertIn("Cannot read stdout/stderr", actual)
Exemple #7
0
    def start_extension_command(self, extension_name, command, shell, cwd, env,
                                stdout, stderr):
        scope_name = "{0}_{1}".format(
            self._get_extension_cgroup_name(extension_name), uuid.uuid4())

        process = subprocess.Popen("systemd-run --unit={0} --scope {1}".format(
            scope_name, command),
                                   shell=shell,
                                   cwd=cwd,
                                   stdout=stdout,
                                   stderr=stderr,
                                   env=env,
                                   preexec_fn=os.setsid)

        # Wait a bit and check if we completed with error
        time.sleep(1)
        return_code = process.poll()

        if return_code is not None and return_code != 0:
            process_output = read_output(stdout, stderr)

            # When systemd-run successfully invokes a command, thereby creating its unit, it will output the
            # unit's name. Since the scope name is only known to systemd-run, and not to the extension itself,
            # if scope_name appears in the output, we are certain systemd-run managed to run.
            if scope_name not in process_output:
                logger.warn(
                    'Failed to run systemd-run for unit {0}.scope '
                    'Process exited with code {1} and output {2}'.format(
                        scope_name, return_code, process_output))

                add_event(
                    AGENT_NAME,
                    version=CURRENT_VERSION,
                    op=WALAEventOperation.InvokeCommandUsingSystemd,
                    is_success=False,
                    message='Failed to run systemd-run for unit {0}.scope. '
                    'Process exited with code {1} and output {2}'.format(
                        scope_name, return_code, process_output))

                # Try starting the process without systemd-run
                process = subprocess.Popen(command,
                                           shell=shell,
                                           cwd=cwd,
                                           env=env,
                                           stdout=stdout,
                                           stderr=stderr,
                                           preexec_fn=os.setsid)

                return process, []

        cgroups = []

        logger.info("Started extension using scope '{0}'", scope_name)

        def create_cgroup(controller):
            cgroup_path = os.path.join(CGROUPS_FILE_SYSTEM_ROOT, controller,
                                       'system.slice', scope_name + ".scope")
            cgroups.append(
                CGroup.create(cgroup_path, controller, extension_name))

        self._foreach_controller(
            create_cgroup,
            'Cannot create cgroup for extension {0}; resource usage will not be tracked.'
            .format(extension_name))

        return process, cgroups