class_docstr: Base class for server nodes in a distributed cluster.
docstr: This creates an HTTP Server running on this node
docstr_tok: ["This","creates","an","HTTP","Server","running","on","this","node"]
code: def start_http_server(
      self, routes, dashboard_address, default_port=0, ssl_options=None
  ):
      """This creates an HTTP Server running on this node"""
  
      self.http_application = RoutingApplication(routes)
  
      # TLS configuration
      tls_key = dask.config.get(
          "distributed.scheduler.dashboard.tls.key"
      )
      tls_cert = dask.config.get(
          "distributed.scheduler.dashboard.tls.cert"
      )
      tls_ca_file = dask.config.get(
          "distributed.scheduler.dashboard.tls.ca-file"
      )
      if tls_cert:
          ssl_options = ssl.create_default_context(
              cafile=tls_ca_file, purpose=ssl.Purpose.CLIENT_AUTH
          )
          ssl_options.load_cert_chain(tls_cert, keyfile=tls_key)
  
      self.http_server = HTTPServer(
          self.http_application, ssl_options=ssl_options
      )
  
      http_addresses = clean_dashboard_address(
          dashboard_address or default_port
      )
  
      for http_address in http_addresses:
          if http_address["address"] is None:
              address = self._start_address
              if isinstance(address, (list, tuple)):
                  address = address[0]
              if address:
                  with suppress(ValueError):
                      http_address["address"] = get_address_host(
                          address
                      )
  
          change_port = False
          retries_left = 3
          while True:
              try:
                  if not change_port:
                      self.http_server.listen(**http_address)
                  else:
                      self.http_server.listen(
                          **tlz.merge(http_address, {"port": 0})
                      )
                  break
              except Exception:
                  change_port = True
                  retries_left = retries_left - 1
                  if retries_left < 1:
                      raise
  
      bound_addresses = get_tcp_server_addresses(self.http_server)
  
      # If more than one address is configured we just use the first here
      self.http_server.address, self.http_server.port = bound_addresses[
          0
      ]
      self.services["dashboard"] = self.http_server
  
      # Warn on port changes
      for expected, actual in zip(
          [a["port"] for a in http_addresses],
          [b[1] for b in bound_addresses],
      ):
          if expected != actual and expected > 0:
              warnings.warn(
                  f"Port {expected} is already in use.\n"
                  "Perhaps you already have a cluster running?\n"
                  f"Hosting the HTTP server on port {actual} instead"
              )
  
imports: from __future__ import annotations
  import logging
  import ssl
  import warnings
  import weakref
  from contextlib import suppress
  import tlz
  from tornado.httpserver import HTTPServer
  import dask
  from distributed.comm import get_address_host, get_tcp_server_addresses
  from distributed.core import Server
  from distributed.http.routing import RoutingApplication
  from distributed.utils import DequeHandler, clean_dashboard_address
  from distributed.versions import get_versions
label_desc: Use image node_id 7 for calling the ServerNode obj's underlying member method code with example usage: obj.start_http_server(routes, dashboard_address, default_port, ssl_options) without return types