Пример #1
0
    def test_run_without_inspection_and_apiurl(self, mock_list_hardware,
                                               mock_make_server, mock_dispatch,
                                               mock_inspector, mock_wait):
        # If both api_url and inspection_callback_url are not configured when
        # the agent starts, ensure that the inspection will be skipped and wsgi
        # server will work as usual. Also, make sure api_client and heartbeater
        # will not be initialized in this case.
        CONF.set_override('inspection_callback_url', None, enforce_type=True)

        self.agent = agent.IronicPythonAgent(None,
                                             agent.Host('203.0.113.1', 9990),
                                             agent.Host('192.0.2.1', 9999), 3,
                                             10, 'eth0', 300, 1, False)
        self.assertFalse(hasattr(self.agent, 'api_client'))
        self.assertFalse(hasattr(self.agent, 'heartbeater'))

        wsgi_server = mock_make_server.return_value
        wsgi_server.start.side_effect = KeyboardInterrupt()

        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_make_server.assert_called_once_with(
            listen_addr.hostname,
            listen_addr.port,
            self.agent.api,
            server_class=simple_server.WSGIServer)
        wsgi_server.serve_forever.assert_called_once_with()

        self.assertFalse(mock_inspector.called)
        self.assertFalse(mock_wait.called)
        self.assertFalse(mock_dispatch.called)
Пример #2
0
 def setUp(self):
     super(TestAgentStandalone, self).setUp()
     self.agent = agent.IronicPythonAgent(
         'https://fake_api.example.'
         'org:8081/', agent.Host(hostname='203.0.113.1', port=9990),
         agent.Host(hostname='192.0.2.1', port=9999), 3, 10, 'eth0', 300, 1,
         'agent_ipmitool', True)
Пример #3
0
def run():
    """Entrypoint for IronicPythonAgent."""
    # NOTE(dtantsur): this must happen very early of the files from
    # /etc/ironic-python-agent.d won't be loaded
    utils.copy_config_from_vmedia()

    log.register_options(CONF)
    CONF(args=sys.argv[1:])
    # Debug option comes from oslo.log, allow overriding it via kernel cmdline
    ipa_debug = config.APARAMS.get('ipa-debug')
    if ipa_debug is not None:
        ipa_debug = strutils.bool_from_string(ipa_debug)
        CONF.set_override('debug', ipa_debug)
    log.setup(CONF, 'ironic-python-agent')
    # Used for TLS configuration
    sslutils.register_opts(CONF)

    logger = log.getLogger(__name__)
    logger.debug("Configuration:")
    CONF.log_opt_values(logger, log.DEBUG)
    utils.log_early_log_to_logger()
    agent.IronicPythonAgent(
        CONF.api_url,
        agent.Host(hostname=CONF.advertise_host, port=CONF.advertise_port),
        agent.Host(hostname=CONF.listen_host, port=CONF.listen_port),
        CONF.ip_lookup_attempts, CONF.ip_lookup_sleep, CONF.network_interface,
        CONF.lookup_timeout, CONF.lookup_interval, False, CONF.agent_token,
        CONF.hardware_initialization_delay, CONF.advertise_protocol).run()
Пример #4
0
    def test_run_without_inspection_and_apiurl(self, mock_list_hardware,
                                               mock_wsgi, mock_dispatch,
                                               mock_inspector, mock_wait):
        # If both api_url and inspection_callback_url are not configured when
        # the agent starts, ensure that the inspection will be skipped and wsgi
        # server will work as usual. Also, make sure api_client and heartbeater
        # will not be initialized in this case.
        CONF.set_override('inspection_callback_url', None)

        self.agent = agent.IronicPythonAgent(None,
                                             agent.Host('203.0.113.1', 9990),
                                             agent.Host('192.0.2.1', 9999), 3,
                                             10, 'eth0', 300, 1, False)
        self.assertFalse(hasattr(self.agent, 'api_client'))
        self.assertFalse(hasattr(self.agent, 'heartbeater'))

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server = mock_wsgi.return_value
        wsgi_server.handle_request.side_effect = set_serve_api

        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_wsgi.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)
        self.assertTrue(wsgi_server.handle_request.called)

        self.assertFalse(mock_inspector.called)
        self.assertFalse(mock_wait.called)
        self.assertFalse(mock_dispatch.called)
Пример #5
0
    def setUp(self):
        super(TestAdvertiseAddress, self).setUp()

        self.agent = agent.IronicPythonAgent(
            api_url='https://fake_api.example.org:8081/',
            advertise_address=agent.Host(None, 9990),
            listen_address=agent.Host('0.0.0.0', 9999),
            ip_lookup_attempts=5,
            ip_lookup_sleep=10,
            network_interface=None,
            lookup_timeout=300,
            lookup_interval=1,
            standalone=False)
Пример #6
0
    def test_url_from_mdns_explicitly(self, mock_get_managers, mock_wsgi,
                                      mock_wait, mock_dispatch, mock_mdns):
        CONF.set_override('inspection_callback_url', '')
        CONF.set_override('disk_wait_attempts', 0)
        mock_mdns.return_value = 'https://example.com', {
            # configuration via mdns
            'ipa_disk_wait_attempts': '42',
        }

        wsgi_server = mock_wsgi.return_value

        self.agent = agent.IronicPythonAgent('mdns',
                                             agent.Host('203.0.113.1', 9990),
                                             agent.Host('192.0.2.1', 9999),
                                             3,
                                             10,
                                             'eth0',
                                             300,
                                             1,
                                             False,
                                             None)

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server.start.side_effect = set_serve_api
        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }

        self.agent.run()

        mock_wsgi.assert_called_once_with(CONF, 'ironic-python-agent',
                                          app=self.agent.api,
                                          host=mock.ANY, port=9999,
                                          use_ssl=False)
        wsgi_server.start.assert_called_once_with()
        mock_wait.assert_called_once_with(mock.ANY)
        self.assertEqual([mock.call('list_hardware_info'),
                          mock.call('wait_for_disks')],
                         mock_dispatch.call_args_list)
        self.agent.heartbeater.start.assert_called_once_with()
        # changed via mdns
        self.assertEqual(42, CONF.disk_wait_attempts)
Пример #7
0
    def setUp(self):
        super(TestBaseAgent, self).setUp()
        self.encoder = encoding.RESTJSONEncoder(indent=4)

        self.agent = agent.IronicPythonAgent(
            'https://fake_api.example.'
            'org:8081/', agent.Host('203.0.113.1', 9990),
            agent.Host('192.0.2.1', 9999), 3, 10, 'eth0', 300, 1, False)
        self.agent.ext_mgr = extension.ExtensionManager.\
            make_test_instance([extension.Extension('fake', None,
                                                    FakeExtension,
                                                    FakeExtension())])
        self.sample_nw_iface = hardware.NetworkInterface(
            "eth9", "AA:BB:CC:DD:EE:FF", "1.2.3.4", True)
Пример #8
0
    def test_run_raise_exception(self, mock_load_managers, mock_wsgi,
                                 mock_dispatch, mock_wait):
        CONF.set_override('inspection_callback_url', '')

        wsgi_server = mock_wsgi.return_value
        wsgi_server.handle_request.side_effect = KeyboardInterrupt()
        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }

        self.assertRaisesRegex(errors.IronicAPIError,
                               'Failed due to an unknown exception.',
                               self.agent.run)

        self.assertTrue(mock_wait.called)
        self.assertEqual(
            [mock.call('list_hardware_info'),
             mock.call('wait_for_disks')], mock_dispatch.call_args_list)
        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_wsgi.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)
        wsgi_server.set_app.assert_called_once_with(self.agent.api)
        self.assertTrue(wsgi_server.handle_request.called)
        self.agent.heartbeater.start.assert_called_once_with()
        self.assertTrue(wsgi_server.handle_request.called)
Пример #9
0
    def test_run_with_sleep(self, mock_make_server, mock_dispatch, mock_wait,
                            mock_sleep, mock_load_managers):
        CONF.set_override('inspection_callback_url', '')

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server = mock_make_server.return_value
        wsgi_server.handle_request.side_effect = set_serve_api

        self.agent.hardware_initialization_delay = 10
        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }
        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_make_server.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)

        self.agent.heartbeater.start.assert_called_once_with()
        mock_sleep.assert_called_once_with(10)
        self.assertTrue(mock_load_managers.called)
        self.assertTrue(mock_wait.called)
        self.assertEqual(
            [mock.call('list_hardware_info'),
             mock.call('wait_for_disks')], mock_dispatch.call_args_list)
Пример #10
0
    def test_run(self, mock_load_managers, mock_list_hardware, mock_wsgi,
                 mock_make_server):
        wsgi_server = mock_make_server.return_value
        wsgi_server.start.side_effect = KeyboardInterrupt()
        wsgi_server_request = mock_wsgi.return_value

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server_request.handle_request.side_effect = set_serve_api

        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()

        self.agent.run()

        self.assertTrue(mock_load_managers.called)
        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_wsgi.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)
        wsgi_server_request.set_app.assert_called_once_with(self.agent.api)

        self.assertTrue(wsgi_server_request.handle_request.called)
        self.assertFalse(self.agent.heartbeater.called)
        self.assertFalse(self.agent.api_client.lookup_node.called)
Пример #11
0
    def test_run(self, mock_list_hardware, mock_make_server):
        wsgi_server = mock_make_server.return_value
        wsgi_server.start.side_effect = KeyboardInterrupt()

        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }
        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_make_server.assert_called_once_with(
            listen_addr.hostname,
            listen_addr.port,
            self.agent.api,
            server_class=simple_server.WSGIServer)
        wsgi_server.serve_forever.assert_called_once_with()

        self.assertFalse(self.agent.heartbeater.called)
        self.assertFalse(self.agent.api_client.lookup_node.called)
Пример #12
0
    def test_run_with_sleep(self, mock_make_server, mock_dispatch,
                            mock_load_managers, mock_sleep, mock_wait):
        CONF.set_override('inspection_callback_url', '', enforce_type=True)
        wsgi_server = mock_make_server.return_value
        wsgi_server.start.side_effect = KeyboardInterrupt()

        self.agent.hardware_initialization_delay = 10
        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }
        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_make_server.assert_called_once_with(
            listen_addr.hostname,
            listen_addr.port,
            self.agent.api,
            server_class=simple_server.WSGIServer)
        wsgi_server.serve_forever.assert_called_once_with()

        self.agent.heartbeater.start.assert_called_once_with()
        mock_sleep.assert_called_once_with(10)
        self.assertTrue(mock_load_managers.called)
        self.assertTrue(mock_wait.called)
        mock_dispatch.assert_called_once_with('list_hardware_info')
Пример #13
0
def run():
    """Entrypoint for IronicPythonAgent."""
    log.register_options(CONF)
    CONF(args=sys.argv[1:])
    # Debug option comes from oslo.log, allow overriding it via kernel cmdline
    ipa_debug = config.APARAMS.get('ipa-debug')
    if ipa_debug is not None:
        ipa_debug = strutils.bool_from_string(ipa_debug)
        CONF.set_override('debug', ipa_debug)
    log.setup(CONF, 'ironic-python-agent')
    agent.IronicPythonAgent(
        CONF.api_url,
        agent.Host(hostname=CONF.advertise_host, port=CONF.advertise_port),
        agent.Host(hostname=CONF.listen_host, port=CONF.listen_port),
        CONF.ip_lookup_attempts, CONF.ip_lookup_sleep, CONF.network_interface,
        CONF.lookup_timeout, CONF.lookup_interval, CONF.driver_name,
        CONF.standalone, CONF.hardware_initialization_delay).run()
Пример #14
0
    def test_advertise_address_provided(self, mock_exec, mock_gethostbyname):
        self.agent.advertise_address = agent.Host('1.2.3.4', 9990)

        self.agent.set_agent_advertise_addr()

        self.assertEqual(('1.2.3.4', 9990), self.agent.advertise_address)
        self.assertFalse(mock_exec.called)
        self.assertFalse(mock_gethostbyname.called)
Пример #15
0
    def test_run_with_inspection_without_apiurl(self,
                                                mock_list_hardware,
                                                mock_wsgi,
                                                mock_dispatch,
                                                mock_inspector,
                                                mock_wait,
                                                mock_mdns):
        mock_mdns.side_effect = lib_exc.ServiceLookupFailure()
        # If inspection_callback_url is configured and api_url is not when the
        # agent starts, ensure that the inspection will be called and wsgi
        # server will work as usual. Also, make sure api_client and heartbeater
        # will not be initialized in this case.
        CONF.set_override('inspection_callback_url', 'http://foo/bar')

        self.agent = agent.IronicPythonAgent(None,
                                             agent.Host('203.0.113.1', 9990),
                                             agent.Host('192.0.2.1', 9999),
                                             3,
                                             10,
                                             'eth0',
                                             300,
                                             1,
                                             False,
                                             None)
        self.assertFalse(hasattr(self.agent, 'api_client'))
        self.assertFalse(hasattr(self.agent, 'heartbeater'))

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server = mock_wsgi.return_value
        wsgi_server.start.side_effect = set_serve_api

        self.agent.run()

        mock_wsgi.assert_called_once_with(CONF, 'ironic-python-agent',
                                          app=self.agent.api,
                                          host=mock.ANY, port=9999,
                                          use_ssl=False)
        wsgi_server.start.assert_called_once_with()

        mock_inspector.assert_called_once_with()

        self.assertTrue(mock_wait.called)
        self.assertFalse(mock_dispatch.called)
Пример #16
0
    def test_with_network_interface(self, mock_get_ipv4, mock_exec,
                                    mock_gethostbyname):
        self.agent.network_interface = 'em1'
        mock_get_ipv4.return_value = '1.2.3.4'

        self.agent.set_agent_advertise_addr()

        self.assertEqual(agent.Host('1.2.3.4', 9990),
                         self.agent.advertise_address)
        mock_get_ipv4.assert_called_once_with(mock.ANY, 'em1')
        self.assertFalse(mock_exec.called)
        self.assertFalse(mock_gethostbyname.called)
    def test_url_from_mdns_by_default(self, mock_load_managers, mock_wsgi,
                                      mock_wait, mock_dispatch, mock_mdns):
        CONF.set_override('inspection_callback_url', '')
        mock_mdns.return_value = 'https://example.com', {}

        wsgi_server = mock_wsgi.return_value

        self.agent = agent.IronicPythonAgent(None,
                                             agent.Host('203.0.113.1', 9990),
                                             agent.Host('192.0.2.1', 9999), 3,
                                             10, 'eth0', 300, 1, False)

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server.handle_request.side_effect = set_serve_api
        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300
            }
        }

        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_wsgi.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)
        wsgi_server.set_app.assert_called_once_with(self.agent.api)
        self.assertTrue(wsgi_server.handle_request.called)
        mock_wait.assert_called_once_with(mock.ANY)
        self.assertEqual(
            [mock.call('list_hardware_info'),
             mock.call('wait_for_disks')], mock_dispatch.call_args_list)
        self.agent.heartbeater.start.assert_called_once_with()
Пример #18
0
    def setUp(self):
        """Start the agent and wait for it to start"""
        super(FunctionalBase, self).setUp()
        mpl = multiprocessing.log_to_stderr()
        mpl.setLevel(logging.INFO)
        self.test_port = os.environ.get('TEST_PORT', '9999')
        # Build a basic standalone agent using the config option defaults.
        # 127.0.0.1:6835 is the fake Ironic client.

        self.agent = agent.IronicPythonAgent(
            api_url='http://127.0.0.1:6835',
            advertise_address=agent.Host('localhost', 9999),
            listen_address=agent.Host(netutils.get_wildcard_address(),
                                      int(self.test_port)),
            ip_lookup_attempts=3,
            ip_lookup_sleep=10,
            network_interface=None,
            lookup_timeout=300,
            lookup_interval=1,
            standalone=True,
            agent_token=None)
        self.process = multiprocessing.Process(target=self.agent.run)
        self.process.start()
        self.addCleanup(self.process.terminate)

        # Wait for process to start, otherwise we have a race for tests
        sleep_time = 0.1
        tries = 0
        max_tries = int(os.environ.get('IPA_WAIT_TRIES', '100'))
        while tries < max_tries:
            try:
                return self.request('get', 'commands')
            except requests.ConnectionError:
                time.sleep(sleep_time)
                tries += 1

        raise IOError('Agent did not start after %s seconds.' %
                      (max_tries * sleep_time))
Пример #19
0
    def test_run_with_inspection(self, mock_list_hardware, mock_wsgi,
                                 mock_dispatch, mock_inspector, mock_wait):
        CONF.set_override('inspection_callback_url', 'http://foo/bar')

        def set_serve_api():
            self.agent.serve_api = False

        wsgi_server = mock_wsgi.return_value
        wsgi_server.handle_request.side_effect = set_serve_api

        mock_inspector.return_value = 'uuid'

        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300,
            }
        }
        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        mock_wsgi.assert_called_once_with(
            (listen_addr.hostname, listen_addr.port),
            simple_server.WSGIRequestHandler)
        self.assertTrue(mock_wsgi.called)

        mock_inspector.assert_called_once_with()
        self.assertEqual(1, self.agent.api_client.lookup_node.call_count)
        self.assertEqual(
            'uuid',
            self.agent.api_client.lookup_node.call_args[1]['node_uuid'])

        mock_wait.assert_called_once_with(mock.ANY)
        self.assertEqual(
            [mock.call('list_hardware_info'),
             mock.call('wait_for_disks')], mock_dispatch.call_args_list)
        self.agent.heartbeater.start.assert_called_once_with()
Пример #20
0
    def test_run_with_inspection(self, mocked_list_hardware, wsgi_server_cls,
                                 mocked_dispatch, mocked_inspector,
                                 mocked_wait):
        CONF.set_override('inspection_callback_url',
                          'http://foo/bar',
                          enforce_type=True)

        wsgi_server = wsgi_server_cls.return_value
        wsgi_server.start.side_effect = KeyboardInterrupt()

        mocked_inspector.return_value = 'uuid'

        self.agent.heartbeater = mock.Mock()
        self.agent.api_client.lookup_node = mock.Mock()
        self.agent.api_client.lookup_node.return_value = {
            'node': {
                'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
            },
            'config': {
                'heartbeat_timeout': 300,
            }
        }
        self.agent.run()

        listen_addr = agent.Host('192.0.2.1', 9999)
        wsgi_server_cls.assert_called_once_with(
            listen_addr.hostname,
            listen_addr.port,
            self.agent.api,
            server_class=simple_server.WSGIServer)
        wsgi_server.serve_forever.assert_called_once_with()
        mocked_inspector.assert_called_once_with()
        self.assertEqual(1, self.agent.api_client.lookup_node.call_count)
        self.assertEqual(
            'uuid',
            self.agent.api_client.lookup_node.call_args[1]['node_uuid'])

        mocked_wait.assert_called_once_with()
        mocked_dispatch.assert_called_once_with("list_hardware_info")
        self.agent.heartbeater.start.assert_called_once_with()