def test_add_user_already_existing(self, _):
     with patch("azurelinuxagent.ga.remoteaccess.get_osutil",
                return_value=MockOSUtil()):
         rah = RemoteAccessHandler(Mock())
         tstpassword = "******"
         tstuser = "******"
         expiration_date = datetime.utcnow() + timedelta(days=1)
         pwd = tstpassword
         rah._add_user(tstuser, pwd, expiration_date)
         users = get_user_dictionary(rah._os_util.get_users())
         self.assertTrue(tstuser in users,
                         "{0} missing from users".format(tstuser))
         self.assertEqual(1, len(users.keys()))
         actual_user = users[tstuser]
         self.assertEqual(actual_user[7],
                          (expiration_date +
                           timedelta(days=1)).strftime("%Y-%m-%d"))
         # add the new duplicate user, ensure it's not created and does not overwrite the existing user.
         # this does not test the user add function as that's mocked, it tests processing skips the remaining
         # calls after the initial failure
         new_user_expiration = datetime.utcnow() + timedelta(days=5)
         self.assertRaises(Exception, rah._add_user, tstuser, pwd,
                           new_user_expiration)
         # refresh users
         users = get_user_dictionary(rah._os_util.get_users())
         self.assertTrue(
             tstuser in users,
             "{0} missing from users after dup user attempted".format(
                 tstuser))
         self.assertEqual(1, len(users.keys()))
         actual_user = users[tstuser]
         self.assertEqual(actual_user[7],
                          (expiration_date +
                           timedelta(days=1)).strftime("%Y-%m-%d"))
Esempio n. 2
0
    def test_valid_routes(self):
        routing_table = \
            'Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT   \n' \
            'eth0\t00000000\tC1BB910A\t0003\t0\t0\t0\t00000000\t0\t0\t0    \n' \
            'eth0\tC0BB910A\t00000000\t0001\t0\t0\t0\tC0FFFFFF\t0\t0\t0    \n' \
            'eth0\t10813FA8\tC1BB910A\t000F\t0\t0\t0\tFFFFFFFF\t0\t0\t0    \n' \
            'eth0\tFEA9FEA9\tC1BB910A\t0007\t0\t0\t0\tFFFFFFFF\t0\t0\t0    \n' \
            'docker0\t002BA8C0\t00000000\t0001\t0\t0\t10\t00FFFFFF\t0\t0\t0    \n'
        known_sha1_hash = b'\x1e\xd1k\xae[\xf8\x9b\x1a\x13\xd0\xbbT\xa4\xe3Y\xa3\xdd\x0b\xbd\xa9'

        mo = mock.mock_open(read_data=routing_table)
        with patch(open_patch(), mo):
            raw_route_list = osutil.DefaultOSUtil().read_route_table()

        self.assertEqual(len(raw_route_list), 6)
        self.assertEqual(textutil.hash_strings(raw_route_list), known_sha1_hash)

        route_list = osutil.DefaultOSUtil().get_list_of_routes(raw_route_list)

        self.assertEqual(len(route_list), 5)
        self.assertEqual(route_list[0].gateway_quad(), '10.145.187.193')
        self.assertEqual(route_list[1].gateway_quad(), '0.0.0.0')
        self.assertEqual(route_list[1].mask_quad(), '255.255.255.192')
        self.assertEqual(route_list[2].destination_quad(), '168.63.129.16')
        self.assertEqual(route_list[1].flags, 1)
        self.assertEqual(route_list[2].flags, 15)
        self.assertEqual(route_list[3].flags, 7)
        self.assertEqual(route_list[3].metric, 0)
        self.assertEqual(route_list[4].metric, 10)
        self.assertEqual(route_list[0].interface, 'eth0')
        self.assertEqual(route_list[4].interface, 'docker0')
 def test_read_output_should_return_no_content(self):
     with patch(
             'azurelinuxagent.common.utils.extensionprocessutil.TELEMETRY_MESSAGE_MAX_LEN',
             0):
         expected = ""
         actual = read_output(self.stdout, self.stderr)
         self.assertEqual(expected, actual)
Esempio n. 4
0
    def test_dhcp_skip_cache(self):
        handler = dhcp.get_dhcp_handler()
        handler.osutil = osutil.DefaultOSUtil()
        with patch('os.path.exists', return_value=False):
            with patch.object(osutil.DefaultOSUtil, 'get_dhcp_lease_endpoint')\
                    as patch_dhcp_cache:
                with patch.object(dhcp.DhcpHandler, 'send_dhcp_req') \
                        as patch_dhcp_send:

                    endpoint = 'foo'
                    patch_dhcp_cache.return_value = endpoint

                    # endpoint comes from cache
                    self.assertFalse(handler.skip_cache)
                    handler.run()
                    self.assertTrue(patch_dhcp_cache.call_count == 1)
                    self.assertTrue(patch_dhcp_send.call_count == 0)
                    self.assertTrue(handler.endpoint == endpoint)

                    # reset
                    handler.skip_cache = True
                    handler.endpoint = None

                    # endpoint comes from dhcp request
                    self.assertTrue(handler.skip_cache)
                    handler.run()
                    self.assertTrue(patch_dhcp_cache.call_count == 1)
                    self.assertTrue(patch_dhcp_send.call_count == 1)
Esempio n. 5
0
    def test_collect_and_send_with_call_wireserver_returns_http_error(
            self, mock_lib_dir, *args):
        mock_lib_dir.return_value = self.lib_dir
        fileutil.mkdir(self.event_dir)
        add_event(name="MonitorTests",
                  op=WALAEventOperation.HeartBeat,
                  is_success=True,
                  message="Test heartbeat")

        with _create_monitor_handler(
                enabled_operations=["collect_and_send_events"
                                    ]) as monitor_handler:

            def http_post_handler(url, _, **__):
                if self.is_telemetry_request(url):
                    return HttpError("A test exception")
                return None

            monitor_handler.get_mock_wire_protocol().set_http_handlers(
                http_post_handler=http_post_handler)

            with patch("azurelinuxagent.common.logger.warn") as mock_warn:
                monitor_handler.run_and_wait()

                self.assertEqual(1, mock_warn.call_count)
                self.assertEqual(0, len(os.listdir(self.event_dir)))
Esempio n. 6
0
    def _assert_validation(self, http_status_code, http_response,
                           expected_valid, expected_response):
        test_subject = imds.ImdsClient(restutil.KNOWN_WIRESERVER_IP)
        with patch("azurelinuxagent.common.utils.restutil.http_get"
                   ) as mock_http_get:
            mock_http_get.return_value = ResponseMock(status=http_status_code,
                                                      reason='reason',
                                                      response=http_response)
            validate_response = test_subject.validate()

        self.assertEqual(1, mock_http_get.call_count)
        positional_args, kw_args = mock_http_get.call_args

        self.assertTrue('User-Agent' in kw_args['headers'])
        self.assertEqual(restutil.HTTP_USER_AGENT_HEALTH,
                         kw_args['headers']['User-Agent'])
        self.assertTrue('Metadata' in kw_args['headers'])
        self.assertEqual(True, kw_args['headers']['Metadata'])
        self.assertEqual(
            'http://169.254.169.254/metadata/instance?api-version=2018-02-01',
            positional_args[0])
        self.assertEqual(expected_valid, validate_response[0])
        self.assertTrue(
            expected_response in validate_response[1],
            "Expected: '{0}', Actual: '{1}'".format(expected_response,
                                                    validate_response[1]))
Esempio n. 7
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 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"
                )))
        self.assertTrue(
            CGroupsTelemetry.is_tracked(
                os.path.join(
                    self.cgroups_file_system_root, "memory",
                    "walinuxagent.extensions/Microsoft.Compute.TestExtension_1.2.3"
                )))
Esempio n. 8
0
    def test_start_extension_command_should_use_systemd_and_not_the_fallback_option_if_successful(
            self, _):
        self.assertTrue(i_am_root(), "Test does not run when non-root")

        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.subprocess.Popen", wraps=subprocess.Popen) \
                        as patch_mock_popen:
                    extension_cgroups, process_output = SystemdCgroupsApi(
                    ).start_extension_command(
                        extension_name="Microsoft.Compute.TestExtension-1.2.3",
                        command="date",
                        timeout=300,
                        shell=True,
                        cwd=self.tmp_dir,
                        env={},
                        stdout=stdout,
                        stderr=stderr)

                    # We should have invoked the extension command only once and succeeded
                    self.assertEquals(1, patch_mock_popen.call_count)

                    args = patch_mock_popen.call_args[0][0]
                    self.assertIn("systemd-run --unit", args)

                    self.assert_cgroups_created(extension_cgroups)
Esempio n. 9
0
    def test_create_should_return_a_FileSystemCgroupsApi_on_non_systemd_platforms(
            self):
        with patch("azurelinuxagent.common.cgroupapi.CGroupsApi._is_systemd",
                   return_value=False):
            api = CGroupsApi.create()

        self.assertTrue(type(api) == FileSystemCgroupsApi)
Esempio n. 10
0
    def test_foreach_controller_should_handle_errors_in_individual_controllers(
            self):
        successful_controllers = []

        def controller_operation(controller):
            if controller == 'cpu':
                raise Exception('A test exception')

            successful_controllers.append(controller)

        with patch("azurelinuxagent.common.cgroupapi.logger.warn"
                   ) as mock_logger_warn:
            CGroupsApi._foreach_controller(controller_operation,
                                           'A dummy message')

            self.assertIn(
                'memory', successful_controllers,
                'The operation was not executed on the memory controller')
            self.assertEqual(
                len(successful_controllers), 1,
                'The operation was not executed on unexpected controllers: {0}'
                .format(successful_controllers))

            args, kwargs = mock_logger_warn.call_args
            (message_format, controller, error, message) = args
            self.assertEquals(message_format,
                              'Error in cgroup controller "{0}": {1}. {2}')
            self.assertEquals(controller, 'cpu')
            self.assertEquals(error, 'A test exception')
            self.assertEquals(message, 'A dummy message')
Esempio n. 11
0
    def test_remove_extension_cgroups_should_log_a_warning_when_the_cgroup_contains_active_tasks(
            self):
        api = FileSystemCgroupsApi()
        api.create_extension_cgroups_root()
        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_handle_remote_access_remove_and_add(self, _):
     with patch("azurelinuxagent.ga.remoteaccess.get_osutil",
                return_value=MockOSUtil()):
         rah = RemoteAccessHandler(Mock())
         data_str = load_data('wire/remote_access_10_accounts.xml')
         remote_access = RemoteAccess(data_str)
         count = 0
         for user in remote_access.user_list.users:
             count += 1
             user.name = "tstuser{0}".format(count)
             expiration_date = datetime.utcnow() + timedelta(days=count)
             user.expiration = expiration_date.strftime(
                 "%a, %d %b %Y %H:%M:%S ") + "UTC"
         rah._remote_access = remote_access
         rah._handle_remote_access()
         users = rah._os_util.get_users()
         self.assertEqual(10, len(users))
         # now remove the user from RemoteAccess
         new_user = "******"
         deleted_user = rah._remote_access.user_list.users[3]
         rah._remote_access.user_list.users[3].name = new_user
         rah._handle_remote_access()
         users = rah._os_util.get_users()
         self.assertTrue(deleted_user not in users,
                         "{0} still in users".format(deleted_user))
         self.assertTrue(new_user in [u[0] for u in users],
                         "user {0} not in users".format(new_user))
         self.assertEqual(10, len(users))
 def test_remove_user_not_exists(self):
     with patch("azurelinuxagent.ga.remoteaccess.get_osutil",
                return_value=MockOSUtil()):
         rah = RemoteAccessHandler(Mock())
         user = "******"
         error = "test exception, user does not exist to delete"
         self.assertRaisesRegex(Exception, error, rah._remove_user, user)
 def test_handle_remote_access_deleted_user_readded(self, _):
     with patch("azurelinuxagent.ga.remoteaccess.get_osutil",
                return_value=MockOSUtil()):
         rah = RemoteAccessHandler(Mock())
         data_str = load_data('wire/remote_access_single_account.xml')
         remote_access = RemoteAccess(data_str)
         tstuser = remote_access.user_list.users[0].name
         expiration_date = datetime.utcnow() + timedelta(days=1)
         expiration = expiration_date.strftime(
             "%a, %d %b %Y %H:%M:%S ") + "UTC"
         remote_access.user_list.users[0].expiration = expiration
         rah._remote_access = remote_access
         rah._handle_remote_access()
         users = get_user_dictionary(rah._os_util.get_users())
         self.assertTrue(tstuser in users,
                         "{0} missing from users".format(tstuser))
         os_util = rah._os_util
         os_util.__class__ = MockOSUtil
         os_util.all_users.clear()  # pylint: disable=no-member
         # refresh users
         users = get_user_dictionary(rah._os_util.get_users())
         self.assertTrue(tstuser not in users)
         rah._handle_remote_access()
         # refresh users
         users = get_user_dictionary(rah._os_util.get_users())
         self.assertTrue(tstuser in users,
                         "{0} missing from users".format(tstuser))
Esempio n. 15
0
    def test_it_should_log_command_failures_as_errors(self):
        return_code = 99
        command = "exit {0}".format(return_code)

        with patch("azurelinuxagent.common.utils.shellutil.logger",
                   autospec=True) as mock_logger:
            shellutil.run_get_output(command, log_cmd=False)

        self.assertEqual(mock_logger.error.call_count, 1)

        args, _ = mock_logger.error.call_args

        message = args[
            0]  # message is similar to "Command: [exit 99], return code: [99], result: []"
        self.assertIn("[{0}]".format(command), message)
        self.assertIn("[{0}]".format(return_code), message)

        self.assertEqual(
            mock_logger.info.call_count, 0,
            "Did not expect any info messages. Got: {0}".format(
                mock_logger.info.call_args_list))
        self.assertEqual(
            mock_logger.warn.call_count, 0,
            "Did not expect any warnings. Got: {0}".format(
                mock_logger.warn.call_args_list))
Esempio n. 16
0
    def test_start_extension_command_should_not_use_fallback_option_if_extension_fails(
            self, *args):
        self.assertTrue(i_am_root(), "Test does not run when non-root")

        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.subprocess.Popen", wraps=subprocess.Popen) \
                        as patch_mock_popen:
                    with self.assertRaises(ExtensionError) as context_manager:
                        SystemdCgroupsApi().start_extension_command(
                            extension_name=
                            "Microsoft.Compute.TestExtension-1.2.3",
                            command="ls folder_does_not_exist",
                            timeout=300,
                            shell=True,
                            cwd=self.tmp_dir,
                            env={},
                            stdout=stdout,
                            stderr=stderr)

                        # We should have invoked the extension command only once, in the systemd-run case
                        self.assertEquals(1, patch_mock_popen.call_count)
                        args = patch_mock_popen.call_args[0][0]
                        self.assertIn("systemd-run --unit", args)

                        self.assertEquals(
                            context_manager.exception.code,
                            ExtensionErrorCodes.PluginUnknownFailure)
                        self.assertIn("Non-zero exit code",
                                      ustr(context_manager.exception))
Esempio n. 17
0
    def test_archive03(self):
        """
        All archives should be purged, both with the new naming (with incarnation number) and with the old naming.
        """
        start = datetime.now()
        timestamp1 = start + timedelta(seconds=5)
        timestamp2 = start + timedelta(seconds=10)

        dir_old = timestamp1.isoformat()
        dir_new = "{0}_incarnation_1".format(timestamp2.isoformat())

        archive_old = "{0}.zip".format(timestamp1.isoformat())
        archive_new = "{0}_incarnation_1.zip".format(timestamp2.isoformat())

        self._write_file(
            os.path.join("history", dir_old, "Prod.0.manifest.xml"))
        self._write_file(
            os.path.join("history", dir_new, "Prod.1.manifest.xml"))
        self._write_file(os.path.join("history", archive_old))
        self._write_file(os.path.join("history", archive_new))

        self.assertEqual(4, len(os.listdir(self.history_dir)),
                         "Not all entries were archived!")

        test_subject = StateArchiver(self.tmp_dir)
        with patch("azurelinuxagent.common.utils.archive._MAX_ARCHIVED_STATES",
                   0):
            test_subject.purge()

        archived_entries = os.listdir(self.history_dir)
        self.assertEqual(0, len(archived_entries),
                         "Not all entries were purged!")
    def test_start_extension_command_should_not_use_systemd_when_cgroups_are_not_enabled(
            self, _):
        configurator = CGroupConfiguratorSystemdTestCase._get_new_cgroup_configurator_instance(
        )
        configurator.disable()

        with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen",
                   wraps=subprocess.Popen) as patcher:
            configurator.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)

            command_calls = [
                args[0] for args, _ in patcher.call_args_list
                if len(args) > 0 and "date" in args[0]
            ]
            self.assertEqual(
                len(command_calls), 1,
                "The test command should have been called exactly once [{0}]".
                format(command_calls))
            self.assertNotIn(
                "systemd-run", command_calls[0],
                "The command should not have been invoked using systemd")
            self.assertEqual(command_calls[0], "date",
                             "The command line should not have been modified")
Esempio n. 19
0
    def test_cgroup_operations_should_not_invoke_the_cgroup_api_when_cgroups_are_not_enabled(
            self):
        configurator = CGroupConfigurator.get_instance()
        configurator.disable()

        # List of operations to test, and the functions to mock used in order to do verifications
        operations = [
            [
                lambda: configurator.create_agent_cgroups(track_cgroups=False),
                "azurelinuxagent.common.cgroupapi.FileSystemCgroupsApi.create_agent_cgroups"
            ],
            [
                lambda: configurator.cleanup_legacy_cgroups(),
                "azurelinuxagent.common.cgroupapi.FileSystemCgroupsApi.cleanup_legacy_cgroups"
            ],
            [
                lambda: configurator.create_extension_cgroups_root(),
                "azurelinuxagent.common.cgroupapi.FileSystemCgroupsApi.create_extension_cgroups_root"
            ],
            [
                lambda: configurator.create_extension_cgroups("A.B.C-1.0.0"),
                "azurelinuxagent.common.cgroupapi.FileSystemCgroupsApi.create_extension_cgroups"
            ],
            [
                lambda: configurator.remove_extension_cgroups("A.B.C-1.0.0"),
                "azurelinuxagent.common.cgroupapi.FileSystemCgroupsApi.remove_extension_cgroups"
            ]
        ]

        for op in operations:
            with patch(op[1]) as mock_cgroup_api_operation:
                op[0]()

            self.assertEqual(mock_cgroup_api_operation.call_count, 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")
Esempio n. 21
0
    def test_init_should_mount_the_cgroups_file_system(self):
        with patch(
                "azurelinuxagent.common.osutil.default.DefaultOSUtil.mount_cgroups"
        ) as mock_mount_cgroups:
            CGroupConfigurator.get_instance()

        self.assertEqual(mock_mount_cgroups.call_count, 1)
    def test_start_extension_command_should_raise_an_exception_when_the_command_cannot_be_started(
            self):
        configurator = CGroupConfiguratorSystemdTestCase._get_new_cgroup_configurator_instance(
        )

        original_popen = subprocess.Popen

        def mock_popen(command_arg, *args, **kwargs):
            if "test command" in command_arg:
                raise Exception("A TEST EXCEPTION")
            return original_popen(command_arg, *args, **kwargs)

        with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen",
                   side_effect=mock_popen) as patcher:
            with self.assertRaises(Exception) as context_manager:
                configurator.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)

                self.assertIn("A TEST EXCEPTION",
                              str(context_manager.exception))
Esempio n. 23
0
    def test_collect_and_send_with_http_post_returning_503(
            self, mock_lib_dir, *_):
        mock_lib_dir.return_value = self.lib_dir
        fileutil.mkdir(self.event_dir)

        with _create_monitor_handler(
                enabled_operations=["collect_and_send_events"
                                    ]) as monitor_handler:

            def http_post_handler(url, _, **__):
                if self.is_telemetry_request(url):
                    return MockHttpResponse(
                        restutil.httpclient.SERVICE_UNAVAILABLE)
                return None

            protocol = monitor_handler.get_mock_wire_protocol()
            protocol.set_http_handlers(http_post_handler=http_post_handler)

            sizes = [1, 2, 3]  # get the powers of 2, and multiple by 1024.

            for power in sizes:
                size = 2**power * 1024
                self._create_extension_event(size)

            with patch("azurelinuxagent.common.logger.warn") as mock_warn:
                monitor_handler.run_and_wait()
                self.assertEqual(1, mock_warn.call_count)
                message = "[ProtocolError] [Wireserver Exception] [ProtocolError] [Wireserver Failed] URI http://{0}/machine?comp=telemetrydata  [HTTP Failed] Status Code 503".format(
                    protocol.get_endpoint())
                self.assertIn(message, mock_warn.call_args[0][0])
                self.assertEqual(0, len(os.listdir(self.event_dir)))
    def test_it_should_cleanup_files_on_error(self):

        orig_write_file = fileutil.write_file
        files_to_fail = []

        def mock_write_file(path, _, *__):
            if files_to_fail[0] in path:
                raise IOError("Invalid file: {0}".format(path))
            return orig_write_file(path, _, *__)

        self.__replace_popen_cmd = TestPersistFirewallRulesHandler.__mock_network_setup_service_disabled
        with self._get_persist_firewall_rules_handler() as handler:
            test_files = [self._binary_file, self._network_service_unit_file]
            for file_to_fail in test_files:
                files_to_fail = [file_to_fail]
                with patch("azurelinuxagent.common.persist_firewall_rules.fileutil.write_file",
                           side_effect=mock_write_file):
                    with self.assertRaises(Exception) as context_manager:
                        handler.setup()
                    self.assertIn("Invalid file: {0}".format(file_to_fail), ustr(context_manager.exception))
                    self.assertFalse(os.path.exists(file_to_fail), "File should be deleted: {0}".format(file_to_fail))

                # Cleanup remaining files for test clarity
                for test_file in test_files:
                    try:
                        os.remove(test_file)
                    except Exception:
                        pass
Esempio n. 25
0
    def test_error_heartbeat_creates_no_signal(self, patch_report_heartbeat,
                                               patch_http_get, patch_add_event,
                                               *args):

        monitor_handler = get_monitor_handler()
        protocol = WireProtocol('endpoint')
        protocol.update_goal_state = MagicMock()
        with patch(
                'azurelinuxagent.common.protocol.util.ProtocolUtil.get_protocol',
                return_value=protocol):
            monitor_handler.init_protocols()
            monitor_handler.last_host_plugin_heartbeat = datetime.datetime.utcnow(
            ) - timedelta(hours=1)

            patch_http_get.side_effect = IOError('client error')
            monitor_handler.send_host_plugin_heartbeat()

            # health report should not be made
            self.assertEqual(0, patch_report_heartbeat.call_count)

            # telemetry with failure details is sent
            self.assertEqual(1, patch_add_event.call_count)
            self.assertEqual('HostPluginHeartbeat',
                             patch_add_event.call_args[1]['op'])
            self.assertTrue(
                'client error' in patch_add_event.call_args[1]['message'])

            self.assertEqual(False, patch_add_event.call_args[1]['is_success'])
            monitor_handler.stop()
Esempio n. 26
0
    def test_sleep_until_next_operation_should_wait_for_the_closest_operation(
            self):
        operations = [
            PeriodicOperation("one",
                              lambda: None,
                              period=datetime.timedelta(seconds=60)),
            PeriodicOperation("one",
                              lambda: None,
                              period=datetime.timedelta(hours=1)),
            PeriodicOperation(
                "one", lambda: None,
                period=datetime.timedelta(seconds=10)),  # closest operation
            PeriodicOperation("one",
                              lambda: None,
                              period=datetime.timedelta(minutes=11)),
            PeriodicOperation("one",
                              lambda: None,
                              period=datetime.timedelta(days=1))
        ]
        for op in operations:  # pylint: disable=invalid-name
            op.run()

        def mock_sleep(seconds):
            mock_sleep.seconds = seconds

        mock_sleep.seconds = 0

        with patch("azurelinuxagent.ga.periodic_operation.time.sleep",
                   side_effect=mock_sleep):
            PeriodicOperation.sleep_until_next_operation(operations)
            self.assertAlmostEqual(mock_sleep.seconds, 10, 0,
                                   "did not sleep for the expected time")
    def test_handle_process_completion_should_raise_on_timeout(self):
        command = "sleep 1m"
        timeout = 20
        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('time.sleep') as mock_sleep:
                    with self.assertRaises(ExtensionError) as context_manager:
                        process = subprocess.Popen(
                            command,  # pylint: disable=subprocess-popen-preexec-fn
                            shell=True,
                            cwd=self.tmp_dir,
                            env={},
                            stdout=stdout,
                            stderr=stderr,
                            preexec_fn=os.setsid)

                        handle_process_completion(process=process,
                                                  command=command,
                                                  timeout=timeout,
                                                  stdout=stdout,
                                                  stderr=stderr,
                                                  error_code=42)

                    # We're mocking sleep to avoid prolonging the test execution time, but we still want to make sure
                    # we're "waiting" the correct amount of time before killing the process and raising an exception
                    # Due to an extra call to sleep at some point in the call stack which only happens sometimes,
                    # we are relaxing this assertion to allow +/- 2 sleep calls.
                    self.assertTrue(abs(mock_sleep.call_count - timeout) <= 2)

                    self.assertEqual(
                        context_manager.exception.code,
                        ExtensionErrorCodes.PluginHandlerScriptTimedout)
                    self.assertIn("Timeout({0})".format(timeout),
                                  ustr(context_manager.exception))
Esempio n. 28
0
    def test_it_should_read_only_the_head_of_large_outputs(self):
        command = "produce_long_output.py"
        self.create_script(os.path.join(self.ext_handler_instance.get_base_dir(), command), '''
import sys

sys.stdout.write("O" * 5 * 1024 * 1024)
sys.stderr.write("E" * 5 * 1024 * 1024)
''')

        # Mocking the call to file.read() is difficult, so instead we mock the call to format_stdout_stderr, which takes the
        # return value of the calls to file.read(). The intention of the test is to verify we never read (and load in memory)
        # more than a few KB of data from the files used to capture stdout/stderr
        with patch('azurelinuxagent.common.utils.extensionprocessutil.format_stdout_stderr', side_effect=format_stdout_stderr) as mock_format:
            output = self.ext_handler_instance.launch_command(command)

        self.assertGreaterEqual(len(output), 1024)
        self.assertLessEqual(len(output), TELEMETRY_MESSAGE_MAX_LEN)

        mock_format.assert_called_once()

        args, kwargs = mock_format.call_args  # pylint: disable=unused-variable
        stdout, stderr = args

        self.assertGreaterEqual(len(stdout), 1024)
        self.assertLessEqual(len(stdout), TELEMETRY_MESSAGE_MAX_LEN)

        self.assertGreaterEqual(len(stderr), 1024)
        self.assertLessEqual(len(stderr), TELEMETRY_MESSAGE_MAX_LEN)
Esempio n. 29
0
    def test_log_collector_should_truncate_large_text_files_and_ignore_large_binary_files(
            self):
        # Set the size limit so that some files are too large to collect in full.
        with patch("azurelinuxagent.common.logcollector._FILE_SIZE_LIMIT",
                   SMALL_FILE_SIZE):
            log_collector = LogCollector()
            archive = log_collector.collect_logs_and_get_archive()

        self._assert_archive_created(archive)

        expected_files = [
            os.path.join(self.root_collect_dir, "waagent.log"),
            self._truncated_path(
                os.path.join(
                    self.root_collect_dir,
                    "waagent.log.1")),  # this file should be truncated
            os.path.join(self.root_collect_dir, "waagent.log.2.gz"),
            os.path.join(self.root_collect_dir, "less_important_file"),
            os.path.join(self.root_collect_dir, "another_dir",
                         "least_important_file")
        ]
        unexpected_files = [
            os.path.join(self.root_collect_dir, "waagent.log.3.gz"
                         )  # binary files cannot be truncated, ignore it
        ]
        self._assert_files_are_in_archive(expected_files)
        self._assert_files_are_not_in_archive(unexpected_files)

        no_files = self._get_number_of_files_in_archive()
        self.assertEqual(
            5, no_files,
            "Expected 5 files in archive, found {0}!".format(no_files))
Esempio n. 30
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")