code: def get_storage_root(cls, storage_type):
      if storage_type == "s3":
          return CARD_S3ROOT
      elif storage_type == "azure":
          return CARD_AZUREROOT
      elif storage_type == "gs":
          return CARD_GSROOT
      elif storage_type == "local":
          # Borrowing some of the logic from LocalStorage.get_storage_root
          result = CARD_LOCALROOT
          if result is None:
              current_path = os.getcwd()
              check_dir = os.path.join(
                  current_path, DATASTORE_LOCAL_DIR, CARD_SUFFIX
              )
              check_dir = os.path.realpath(check_dir)
              orig_path = check_dir
              while not os.path.isdir(check_dir):
                  new_path = os.path.dirname(current_path)
                  if new_path == current_path:
                      break  # We are no longer making upward progress
                  current_path = new_path
                  check_dir = os.path.join(
                      current_path, DATASTORE_LOCAL_DIR, CARD_SUFFIX
                  )
              result = orig_path
  
          return result
      else:
          # Let's make it obvious we need to update this block for each new datastore backend...
          raise NotImplementedError(
              "Card datastore does not support backend %s"
              % (storage_type,)
          )
  
imports: from collections import namedtuple
  from io import BytesIO
  import os
  import json
  import shutil
  from metaflow.plugins.datastores.local_storage import LocalStorage
  from metaflow.metaflow_config import CARD_S3ROOT, CARD_LOCALROOT, DATASTORE_LOCAL_DIR, CARD_SUFFIX, CARD_AZUREROOT, CARD_GSROOT, SKIP_CARD_DUALWRITE
  import metaflow.metaflow_config
  from .exception import CardNotPresentException
label_desc: Use image node_id 1 for calling the CardDatastore obj's underlying member method code with example usage: obj.get_storage_root(cls, storage_type) and returns: CARD_S3ROOT, CARD_AZUREROOT, CARD_GSROOT, result