def test_external_storage_namespace_isolation(shutdown_only): addr = ray.init(namespace="a", _system_config={ "external_storage_namespace": "c1" }).address_info["address"] gcs_client = GcsClient(address=addr) assert gcs_client.internal_kv_put(b"ABC", b"DEF", True, None) == 1 assert gcs_client.internal_kv_get(b"ABC", None) == b"DEF" ray.shutdown() addr = ray.init(namespace="a", _system_config={ "external_storage_namespace": "c2" }).address_info["address"] gcs_client = GcsClient(address=addr) assert gcs_client.internal_kv_get(b"ABC", None) is None assert gcs_client.internal_kv_put(b"ABC", b"XYZ", True, None) == 1 assert gcs_client.internal_kv_get(b"ABC", None) == b"XYZ" ray.shutdown() addr = ray.init(namespace="a", _system_config={ "external_storage_namespace": "c1" }).address_info["address"] gcs_client = GcsClient(address=addr) assert gcs_client.internal_kv_get(b"ABC", None) == b"DEF"
def get_file_discovery_content(self): """Return the content for Prometheus service discovery.""" nodes = ray.nodes() metrics_export_addresses = [ "{}:{}".format(node["NodeManagerAddress"], node["MetricsExportPort"]) for node in nodes if node["alive"] is True ] gcs_client = GcsClient(address=self.gcs_address) autoscaler_addr = gcs_client.internal_kv_get(b"AutoscalerMetricsAddress", None) if autoscaler_addr: metrics_export_addresses.append(autoscaler_addr.decode("utf-8")) return json.dumps( [{"labels": {"job": "ray"}, "targets": metrics_export_addresses}] )
class RayInternalKVStore(KVStoreBase): """Wraps ray's internal_kv with a namespace to avoid collisions. Supports string keys and bytes values, caller must handle serialization. """ def __init__( self, namespace: str = None, ): if namespace is not None and not isinstance(namespace, str): raise TypeError("namespace must a string, got: {}.".format( type(namespace))) self.gcs_client = GcsClient( address=ray.get_runtime_context().gcs_address) self.timeout = RAY_SERVE_KV_TIMEOUT_S self.namespace = namespace or "" def get_storage_key(self, key: str) -> str: return "{ns}-{key}".format(ns=self.namespace, key=key) def put(self, key: str, val: bytes) -> bool: """Put the key-value pair into the store. Args: key (str) val (bytes) """ if not isinstance(key, str): raise TypeError("key must be a string, got: {}.".format(type(key))) if not isinstance(val, bytes): raise TypeError("val must be bytes, got: {}.".format(type(val))) try: return self.gcs_client.internal_kv_put( self.get_storage_key(key).encode(), val, overwrite=True, namespace=ray_constants.KV_NAMESPACE_SERVE, timeout=self.timeout, ) except Exception as e: raise KVStoreError(e.code()) def get(self, key: str) -> Optional[bytes]: """Get the value associated with the given key from the store. Args: key (str) Returns: The bytes value. If the key wasn't found, returns None. """ if not isinstance(key, str): raise TypeError("key must be a string, got: {}.".format(type(key))) try: return self.gcs_client.internal_kv_get( self.get_storage_key(key).encode(), namespace=ray_constants.KV_NAMESPACE_SERVE, timeout=self.timeout, ) except Exception as e: raise KVStoreError(e.code()) def delete(self, key: str): """Delete the value associated with the given key from the store. Args: key (str) """ if not isinstance(key, str): raise TypeError("key must be a string, got: {}.".format(type(key))) try: return self.gcs_client.internal_kv_del( self.get_storage_key(key).encode(), False, namespace=ray_constants.KV_NAMESPACE_SERVE, timeout=self.timeout, ) except Exception as e: raise KVStoreError(e.code())