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)
 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)
    def test_ipv4_lookup(self, mock_get_ipv4, mock_list_net, mock_time_sleep,
                         mock_poll, mock_read):
        homeless_agent = agent.IronicPythonAgent(
            'https://fake_api.example.'
            'org:8081/', (None, 9990), ('192.0.2.1', 9999), 3, 10, None, 300,
            1, 'agent_ipmitool', False)

        mock_poll.return_value.poll.return_value = True
        mock_read.return_value = 'a'

        # Can't find network interfaces, and therefore can't find IP
        mock_list_net.return_value = []
        mock_get_ipv4.return_value = None
        self.assertRaises(errors.LookupAgentInterfaceError,
                          homeless_agent.set_agent_advertise_addr)

        # Can look up network interfaces, but not IP.  Network interface not
        # set, because no interface yields an IP.
        mock_ifaces = [
            hardware.NetworkInterface('eth0', '00:00:00:00:00:00'),
            hardware.NetworkInterface('eth1', '00:00:00:00:00:01')
        ]
        mock_list_net.return_value = mock_ifaces

        self.assertRaises(errors.LookupAgentIPError,
                          homeless_agent.set_agent_advertise_addr)
        self.assertEqual(6, mock_get_ipv4.call_count)
        self.assertEqual(None, homeless_agent.network_interface)

        # First interface eth0 has no IP, second interface eth1 has an IP
        mock_get_ipv4.side_effect = [None, '1.1.1.1']
        homeless_agent.heartbeater.run()
        self.assertEqual(('1.1.1.1', 9990), homeless_agent.advertise_address)
        self.assertEqual('eth1', homeless_agent.network_interface)
Exemple #4
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)
Exemple #5
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()
    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)
        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(
            'http://127.0.0.1:6835', 'localhost', ('0.0.0.0',
            int(test_port)), 3, 10, None, 300, 1,
            'agent_ipmitool', True)
        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
        tries = 0
        max_tries = os.environ.get('IPA_WAIT_TIME', '2')
        while tries < int(max_tries):
            try:
                return requests.get('http://localhost:%s/v1/commands' %
                        test_port)
            except requests.ConnectionError:
                time.sleep(.1)
                tries += 1

        raise IOError('Agent did not start after %s seconds.' % max_tries)
def run():
    CONF()
    log.setup('ironic-python-agent')
    agent.IronicPythonAgent(
        CONF.api_url, (CONF.advertise_host, CONF.advertise_port),
        (CONF.listen_host, 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).run()
Exemple #8
0
def run():
    """Entrypoint for IronicPythonAgent."""
    log.register_options(CONF)
    CONF(args=sys.argv[1:])
    log.setup(CONF, 'ironic-python-agent')
    agent.IronicPythonAgent(
        CONF.api_url, (CONF.advertise_host, CONF.advertise_port),
        (CONF.listen_host, 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).run()
    def setUp(self):
        super(TestBaseAgent, self).setUp()
        self.encoder = encoding.RESTJSONEncoder(indent=4)

        self.agent = agent.IronicPythonAgent(
            'https://fake_api.example.'
            'org:8081/', ('203.0.113.1', 9990), ('192.0.2.1', 9999), 3, 10,
            'eth0', 300, 1, 'agent_ipmitool', False)
        self.agent.ext_mgr = extension.ExtensionManager.\
            make_test_instance([extension.Extension('fake', None,
                                                    FakeExtension,
                                                    FakeExtension())])
    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)
Exemple #11
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)
    def setUp(self):
        super(TestBaseAgent, self).setUp()
        self.encoder = encoding.RESTJSONEncoder(indent=4)

        self.agent = agent.IronicPythonAgent(
            'https://fake_api.example.'
            'org:8081/', ('203.0.113.1', 9990), ('192.0.2.1', 9999), 3, 10,
            'eth0', 300, 1, 'agent_ipmitool', 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)
Exemple #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, (CONF.advertise_host, CONF.advertise_port),
        (CONF.listen_host, 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()
Exemple #14
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)
    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()
Exemple #16
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))