code: def run(**kwargs):
      
      log_init()
      loop = asyncio.get_event_loop()
      log.info("API server version:  {}".format(__version__))
      if not os.environ.get("ENABLE_VIRTUAL_SMOOTHIE"):
          initialize_robot(loop)
          if ff.use_protocol_api_v2():
              loop.run_until_complete(hardware.cache_instruments())
          if not ff.disable_home_on_boot():
              log.info("Homing Z axes")
              if ff.use_protocol_api_v2():
                  loop.run_until_complete(hardware.home_z())
              else:
                  hardware.home_z()
          try:
              udev.setup_rules_file()
          except Exception:
              log.exception(
                  "Could not setup udev rules, modules may not be detected")
      # Explicitly unlock resin updates in case a prior server left them locked
      resin.unlock_updates()
  
      server.run(kwargs.get('hostname'), kwargs.get('port'), kwargs.get('path'),
                 loop)
docs: This function was necessary to separate from main() to accommodate for
      server startup path on system 3.0, which is server.main. In the case where
      the api is on system 3.0, server.main will redirect to this function with
      an additional argument of 'patch_old_init'. kwargs are hence used to allow
      the use of different length args