def test_run_without_inspection_and_apiurl(self, mock_list_hardware, mock_wsgi, mock_dispatch, mock_inspector, mock_wait, mock_mdns): mock_mdns.side_effect = lib_exc.ServiceLookupFailure() # 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 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 get_endpoint(self, service_type): """Get an endpoint and its properties from mDNS. If the requested endpoint is already in the built-in server cache, and its TTL is not exceeded, the cached value is returned. :param service_type: OpenStack service type. :returns: tuple (endpoint URL, properties as a dict). :raises: :exc:`.ServiceLookupFailure` if the service cannot be found. """ delay = 0.1 for attempt in range(CONF.mdns.lookup_attempts): name = '%s.%s' % (service_type, _MDNS_DOMAIN) info = self._zc.get_service_info(name, name) if info is not None: break elif attempt == CONF.mdns.lookup_attempts - 1: raise exception.ServiceLookupFailure(service=service_type) else: time.sleep(delay) delay *= 2 # TODO(dtantsur): IPv6 support address = socket.inet_ntoa(info.address) properties = {} for key, value in info.properties.items(): try: if isinstance(key, bytes): key = key.decode('utf-8') except UnicodeError as exc: raise exception.ServiceLookupFailure( _('Invalid properties for service %(svc)s. Cannot decode ' 'key %(key)r: %(exc)r') % { 'svc': service_type, 'key': key, 'exc': exc }) try: if isinstance(value, bytes): value = value.decode('utf-8') except UnicodeError as exc: LOG.debug( 'Cannot convert value %(value)r for key %(key)s ' 'to string, assuming binary: %(exc)s', { 'key': key, 'value': value, 'exc': exc }) properties[key] = value path = properties.pop('path', '') protocol = properties.pop('protocol', None) if not protocol: if info.port == 80: protocol = 'http' else: protocol = 'https' if info.server.endswith('.local.'): # Local hostname means that the catalog lists an IP address, # so use it host = address else: # Otherwise use the provided hostname. host = info.server.rstrip('.') return ('{proto}://{host}:{port}{path}'.format(proto=protocol, host=host, port=info.port, path=path), properties)