Exemplo n.º 1
0
import base64
import logging
from collections import defaultdict
from enum import Enum
from typing import List

import ray
from ray._private.internal_api import node_stats
from ray._raylet import ActorID, JobID, TaskID

logger = logging.getLogger(__name__)

# These values are used to calculate if objectRefs are actor handles.
TASKID_BYTES_SIZE = TaskID.size()
ACTORID_BYTES_SIZE = ActorID.size()
JOBID_BYTES_SIZE = JobID.size()
# We need to multiply 2 because we need bits size instead of bytes size.
TASKID_RANDOM_BITS_SIZE = (TASKID_BYTES_SIZE - ACTORID_BYTES_SIZE) * 2
ACTORID_RANDOM_BITS_SIZE = (ACTORID_BYTES_SIZE - JOBID_BYTES_SIZE) * 2


def decode_object_ref_if_needed(object_ref: str) -> bytes:
    """Decode objectRef bytes string.

    gRPC reply contains an objectRef that is encodded by Base64.
    This function is used to decode the objectRef.
    Note that there are times that objectRef is already decoded as
    a hex string. In this case, just convert it to a binary number.
    """
    if object_ref.endswith("="):
        # If the object ref ends with =, that means it is base64 encoded.
Exemplo n.º 2
0
async def test_logs_manager_resolve_file(logs_manager):
    node_id = NodeID(b"1" * 28)
    """
    Test filename is given.
    """
    logs_client = logs_manager.data_source_client
    logs_client.get_all_registered_agent_ids = MagicMock()
    logs_client.get_all_registered_agent_ids.return_value = [node_id.hex()]
    expected_filename = "filename"
    log_file_name, n = await logs_manager.resolve_filename(
        node_id=node_id,
        log_filename=expected_filename,
        actor_id=None,
        task_id=None,
        pid=None,
        get_actor_fn=lambda _: True,
        timeout=10,
    )
    assert log_file_name == expected_filename
    assert n == node_id
    """
    Test actor id is given.
    """
    # Actor doesn't exist.
    with pytest.raises(ValueError):
        actor_id = ActorID(b"2" * 16)

        def get_actor_fn(id):
            if id == actor_id:
                return None
            assert False, "Not reachable."

        log_file_name, n = await logs_manager.resolve_filename(
            node_id=node_id,
            log_filename=None,
            actor_id=actor_id,
            task_id=None,
            pid=None,
            get_actor_fn=get_actor_fn,
            timeout=10,
        )

    # Actor exists, but it is not scheduled yet.
    actor_id = ActorID(b"2" * 16)

    with pytest.raises(ValueError):
        log_file_name, n = await logs_manager.resolve_filename(
            node_id=node_id,
            log_filename=None,
            actor_id=actor_id,
            task_id=None,
            pid=None,
            get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, None),
            timeout=10,
        )

    # Actor exists.
    actor_id = ActorID(b"2" * 16)
    worker_id = WorkerID(b"3" * 28)
    logs_manager.list_logs = AsyncMock()
    logs_manager.list_logs.return_value = {
        "worker_out": [f"worker-{worker_id.hex()}-123-123.out"]
    }
    log_file_name, n = await logs_manager.resolve_filename(
        node_id=node_id.hex(),
        log_filename=None,
        actor_id=actor_id,
        task_id=None,
        pid=None,
        get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, worker_id),
        timeout=10,
    )
    logs_manager.list_logs.assert_awaited_with(
        node_id.hex(), 10, glob_filter=f"*{worker_id.hex()}*"
    )
    assert log_file_name == f"worker-{worker_id.hex()}-123-123.out"
    assert n == node_id.hex()

    """
    Test task id is given.
    """
    with pytest.raises(NotImplementedError):
        task_id = TaskID(b"2" * 24)
        log_file_name, n = await logs_manager.resolve_filename(
            node_id=node_id.hex(),
            log_filename=None,
            actor_id=None,
            task_id=task_id,
            pid=None,
            get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, worker_id),
            timeout=10,
        )

    """
    Test pid is given.
    """
    # Pid doesn't exist.
    with pytest.raises(FileNotFoundError):
        pid = 456
        logs_manager.list_logs = AsyncMock()
        # Provide the wrong pid.
        logs_manager.list_logs.return_value = {"worker_out": ["worker-123-123-123.out"]}
        log_file_name = await logs_manager.resolve_filename(
            node_id=node_id.hex(),
            log_filename=None,
            actor_id=None,
            task_id=None,
            pid=pid,
            get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, worker_id),
            timeout=10,
        )

    # Pid exists.
    pid = 123
    logs_manager.list_logs = AsyncMock()
    # Provide the wrong pid.
    logs_manager.list_logs.return_value = {"worker_out": [f"worker-123-123-{pid}.out"]}
    log_file_name, n = await logs_manager.resolve_filename(
        node_id=node_id.hex(),
        log_filename=None,
        actor_id=None,
        task_id=None,
        pid=pid,
        get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, worker_id),
        timeout=10,
    )
    logs_manager.list_logs.assert_awaited_with(
        node_id.hex(), 10, glob_filter=f"*{pid}*"
    )
    assert log_file_name == f"worker-123-123-{pid}.out"

    """
    Test nothing is given.
    """
    with pytest.raises(FileNotFoundError):
        log_file_name = await logs_manager.resolve_filename(
            node_id=node_id.hex(),
            log_filename=None,
            actor_id=None,
            task_id=None,
            pid=None,
            get_actor_fn=lambda _: generate_actor_data(actor_id, node_id, worker_id),
            timeout=10,
        )
Exemplo n.º 3
0
async def test_api_manager_summary_tasks(state_api_manager):
    data_source_client = state_api_manager.data_source_client
    data_source_client.get_all_registered_raylet_ids = MagicMock()
    data_source_client.get_all_registered_raylet_ids.return_value = ["1", "2"]

    first_task_name = "1"
    second_task_name = "2"
    data_source_client.get_task_info = AsyncMock()
    ids = [TaskID((f"{i}" * 24).encode()) for i in range(5)]
    # 1: {SCHEDULED:3, RUNNING:1}, 2:{SCHEDULED: 1}
    data_source_client.get_task_info.side_effect = [
        GetTasksInfoReply(owned_task_info_entries=[
            generate_task_entry(
                id=ids[0].binary(),
                func_or_class=first_task_name,
                state=TaskStatus.SCHEDULED,
                type=TaskType.NORMAL_TASK,
            ),
            generate_task_entry(
                id=ids[1].binary(),
                func_or_class=first_task_name,
                state=TaskStatus.SCHEDULED,
                type=TaskType.NORMAL_TASK,
            ),
            generate_task_entry(
                id=ids[2].binary(),
                func_or_class=first_task_name,
                state=TaskStatus.SCHEDULED,
                type=TaskType.NORMAL_TASK,
            ),
        ]),
        GetTasksInfoReply(owned_task_info_entries=[
            generate_task_entry(
                id=ids[3].binary(),
                func_or_class=first_task_name,
                state=TaskStatus.RUNNING,
                type=TaskType.NORMAL_TASK,
            ),
            generate_task_entry(
                id=ids[4].binary(),
                func_or_class=second_task_name,
                state=TaskStatus.SCHEDULED,
                type=TaskType.ACTOR_TASK,
            ),
        ]),
    ]
    """
    Test cluster summary.
    """
    result = await state_api_manager.summarize_tasks(
        option=create_summary_options())
    assert "cluster" in result.result.node_id_to_summary

    data = result.result.node_id_to_summary["cluster"]
    assert data.summary[first_task_name].type == "NORMAL_TASK"
    assert data.summary[first_task_name].func_or_class_name == first_task_name
    assert data.summary[first_task_name].state_counts["SCHEDULED"] == 3
    assert data.summary[first_task_name].state_counts["RUNNING"] == 1

    assert data.summary[second_task_name].type == "ACTOR_TASK"
    assert data.summary[
        second_task_name].func_or_class_name == second_task_name
    assert data.summary[second_task_name].state_counts["SCHEDULED"] == 1

    assert data.total_tasks == 4
    assert data.total_actor_tasks == 1
    assert data.total_actor_scheduling_tasks == 0
    """
    Test if it can be correctly modified to a dictionary.
    """
    print(result.result)
    result_in_dict = asdict(result.result)
    assert json.loads(json.dumps(result_in_dict)) == result_in_dict