def setup(opts)
      missing_opts = REQ_OPTS.select { |o| !opts.has_key? o }
      raise ArgumentError, "Missing options: #{missing_opts.join(', ')}" unless missing_opts.empty?
      @service = opts[:service]
      @token = opts[:token]
      @logger = opts[:logger] || make_logger()
      @cld_ctrl_uri = http_uri(opts[:cloud_controller_uri])
      @provisioner = opts[:provisioner]
      @hb_interval = opts[:heartbeat_interval] || 60
      @node_timeout = opts[:node_timeout]
      @handle_fetch_interval = opts[:handle_fetch_interval] || 1
      @check_orphan_interval = opts[:check_orphan_interval] || -1
      @double_check_orphan_interval = opts[:double_check_orphan_interval] || 300
      @handle_fetched = opts[:handle_fetched] || false
      @fetching_handles = false
      @version_aliases = (service[:version_aliases] ||= {})

      opts[:gateway_name] ||= "Service Gateway"

      @cc_api_version = opts[:cc_api_version] || "v1"
      if @cc_api_version == "v1"
        require 'catalog_manager_v1'
        @catalog_manager = VCAP::Services::CatalogManagerV1.new(opts)
      elsif @cc_api_version == "v2"
        require 'catalog_manager_v2'
        @catalog_manager = VCAP::Services::CatalogManagerV2.new(opts)
      else
        raise "Unknown cc_api_version: #{@cc_api_version}"
      end

      @event_machine = opts[:event_machine] || EM

      # Setup heartbeats and exit handlers
      event_machine.add_periodic_timer(@hb_interval) { send_heartbeat }
      event_machine.next_tick { send_heartbeat }
      Kernel.at_exit do
        if event_machine.reactor_running?
          # :/ We can't stop others from killing the event-loop here. Let's hope that they play nice
          send_deactivation_notice(false)
        else
          event_machine.run { send_deactivation_notice }
        end
      end

      # Add any necessary handles we don't know about
      update_callback = Proc.new do |resp|
        @provisioner.update_handles(resp.handles)
        @handle_fetched = true
        event_machine.cancel_timer(@fetch_handle_timer)

        # TODO remove it when we finish the migration
        current_version = @version_aliases && @version_aliases[:current]
        if current_version
          @provisioner.update_version_info(current_version)
        else
          logger.info("No current version alias is supplied, skip update version in CCDB.")
        end
      end

      @fetch_handle_timer = event_machine.add_periodic_timer(@handle_fetch_interval) { fetch_handles(&update_callback) }
      event_machine.next_tick { fetch_handles(&update_callback) }

      if @check_orphan_interval > 0
        handler_check_orphan = Proc.new do |resp|
          check_orphan(resp.handles,
                       lambda { logger.info("Check orphan is requested") },
                       lambda { |errmsg| logger.error("Error on requesting to check orphan #{errmsg}") })
        end
        event_machine.add_periodic_timer(@check_orphan_interval) { fetch_handles(&handler_check_orphan) }
      end

      # Register update handle callback
      @provisioner.register_update_handle_callback { |handle, &blk| update_service_handle(handle, &blk) }
    end
def setup(opts)
      missing_opts = REQ_OPTS.select { |o| !opts.has_key? o }
      raise ArgumentError, "Missing options: #{missing_opts.join(', ')}" unless missing_opts.empty?
      @service = opts[:service]
      @token = opts[:token]
      @logger = opts[:logger] || make_logger()
      @cld_ctrl_uri = http_uri(opts[:cloud_controller_uri])
      @provisioner = opts[:provisioner]
      @hb_interval = opts[:heartbeat_interval] || 60
      @node_timeout = opts[:node_timeout]
      @handle_fetch_interval = opts[:handle_fetch_interval] || 1
      @check_orphan_interval = opts[:check_orphan_interval] || -1
      @double_check_orphan_interval = opts[:double_check_orphan_interval] || 300
      @handle_fetched = opts[:handle_fetched] || false
      @fetching_handles = false
      @version_aliases = (service[:version_aliases] ||= {})

      opts[:gateway_name] ||= "Service Gateway"

      @cc_api_version = opts[:cc_api_version] || "v1"
      if @cc_api_version == "v1"
        require 'catalog_manager_v1'
        @catalog_manager = VCAP::Services::CatalogManagerV1.new(opts)
      elsif @cc_api_version == "v2"
        require 'catalog_manager_v2'
        @catalog_manager = VCAP::Services::CatalogManagerV2.new(opts)
      else
        raise "Unknown cc_api_version: #{@cc_api_version}"
      end

      @event_machine = opts[:event_machine] || EM

      # Setup heartbeats and exit handlers
      event_machine.add_periodic_timer(@hb_interval) { send_heartbeat }
      event_machine.next_tick { send_heartbeat }
      Kernel.at_exit do
        if event_machine.reactor_running?
          # :/ We can't stop others from killing the event-loop here. Let's hope that they play nice
          send_deactivation_notice(false)
        else
          event_machine.run { send_deactivation_notice }
        end
      end

      # Add any necessary handles we don't know about
      update_callback = Proc.new do |resp|
        @provisioner.update_handles(resp.handles)
        @handle_fetched = true
        event_machine.cancel_timer(@fetch_handle_timer)

        # TODO remove it when we finish the migration
        current_version = @version_aliases && @version_aliases[:current]
        if current_version
          @provisioner.update_version_info(current_version)
        else
          logger.info("No current version alias is supplied, skip update version in CCDB.")
        end
      end

      @fetch_handle_timer = event_machine.add_periodic_timer(@handle_fetch_interval) { fetch_handles(&update_callback) }
      event_machine.next_tick { fetch_handles(&update_callback) }

      if @check_orphan_interval > 0
        handler_check_orphan = Proc.new do |resp|
          check_orphan(resp.handles,
                       lambda { logger.info("Check orphan is requested") },
                       lambda { |errmsg| logger.error("Error on requesting to check orphan #{errmsg}") })
        end
        event_machine.add_periodic_timer(@check_orphan_interval) { fetch_handles(&handler_check_orphan) }
      end

      # Register update handle callback
      @provisioner.register_update_handle_callback { |handle, &blk| update_service_handle(handle, &blk) }
    end
setup the environment