class_docstr: Class for e2e local testing of BatchingNodeProvider.
  Recycles parts of the implementation of FakeMultiNodeProvider without inheriting it.
  
  This node provider requires the "available_node_types" section of the
  autoscaling config to be copied into the "provider" section.
  That's needed so that node resources can be accessed as
  provider_config["available_node_types"][node_type]["resources"].
  
  See the create_node_with_resources call in submit_scale_request.
  See class BatchingAutoscaler below.
code: def submit_scale_request(self, scale_request: ScaleRequest):
      worker_counts = self.cur_num_workers()
      for worker_to_delete in scale_request.workers_to_delete:
          node_type = self.node_tags(worker_to_delete)[
              TAG_RAY_USER_NODE_TYPE
          ]
          FakeMultiNodeProvider.terminate_node(self, worker_to_delete)
          worker_counts[node_type] -= 1
      for node_type in scale_request.desired_num_workers:
          diff = (
              scale_request.desired_num_workers[node_type]
              - worker_counts[node_type]
          )
          # It is non-standard for "available_node_types" to be included in the
          # provider config, but it is necessary for this node provider.
          resources = self.provider_config["available_node_types"][
              node_type
          ]["resources"]
          labels = self.provider_config["available_node_types"][
              node_type
          ].get("labels", {})
          tags = {
              TAG_RAY_NODE_KIND: NODE_KIND_WORKER,
              TAG_RAY_USER_NODE_TYPE: node_type,
              TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE,
          }
          FakeMultiNodeProvider.create_node_with_resources_and_labels(
              self,
              node_config={},
              tags=tags,
              count=diff,
              resources=resources,
              labels=labels,
          )
  
imports: from copy import deepcopy
  import sys
  import pytest
  import ray
  from ray._private.test_utils import wait_for_condition
  from ray.autoscaler.batching_node_provider import BatchingNodeProvider, NodeData, ScaleRequest
  from ray.autoscaler._private.fake_multi_node.node_provider import FakeMultiNodeProvider
  from ray.autoscaler._private.constants import FOREGROUND_NODE_LAUNCH_KEY
  from ray.autoscaler.tags import NODE_KIND_WORKER, STATUS_UP_TO_DATE, TAG_RAY_NODE_KIND, TAG_RAY_NODE_STATUS, TAG_RAY_USER_NODE_TYPE
  from ray.cluster_utils import AutoscalingCluster
  import logging
label_desc: Use image node_id 5 for calling the FakeBatchingNodeProvider obj's underlying member method code with example usage: obj.submit_scale_request(scale_request) without return types