예제 #1
0
def test_minimum_space() -> None:
    c = MinResourcePerNode("pcpus", 1)
    assert 1 == c.minimum_space(SchedulerNode("", {"pcpus": 1}))
    assert 2 == c.minimum_space(SchedulerNode("", {"pcpus": 2}))
    snode = SchedulerNode("", {"pcpus": 2})
    assert -1 == ExclusiveNode(assignment_id="1").minimum_space(snode)
    snode.assign("1")
    assert 0 == ExclusiveNode(assignment_id="1").minimum_space(snode)
        def do_draw(self, data: Any) -> ht.VMSize:
            import hypothesis.internal.conjecture.utils as d

            idx = d.integer_range(data, 0, 1_000_000_000)
            r = random.Random(idx)

            def draw_value() -> Optional[Any]:
                rtype_draw = r.randint(0, 4)
                if rtype_draw == 0:
                    return r.randint(0, 100)
                elif rtype_draw == 1:
                    return r.random() * 100
                elif rtype_draw == 2:

                    def draw_letter():
                        return r.choice(string.ascii_letters)

                    return "".join([draw_letter() for n in range(r.randint(0, 100))])
                elif rtype_draw == 3:
                    return r.random() < 0.5
                else:
                    return None

            hostname = "n-o-d-e_-{}".format(r.randint(1, 1000000))
            resources: Dict[str, Optional[Any]] = {}
            num_resources = r.randint(0, 10)
            for n in range(num_resources):
                rname = "res-{}".format(n)
                resources[rname] = draw_value()

            node = SchedulerNode(ht.Hostname(hostname), resources, "bucket-id-123")

            for job_id in range(r.randint(0, 10)):
                node.assign(str(job_id))

            num_meta = r.randint(0, 10)
            for n in range(num_meta):
                mname = "meta-{}".format(n)
                node.metadata[mname] = draw_value()

            for rname, rvalue in node.resources.items():
                if r.random() > 0.5:
                    if isinstance(rvalue, int):
                        node.available[rname] = rvalue - r.randint(0, rvalue + 1)
                    elif isinstance(rvalue, float):
                        node.available[rname] = rvalue * r.random()
                    elif isinstance(rvalue, bool):
                        node.available[rname] = rvalue ^ (r.random() < 0.5)
                    elif rvalue is None:
                        # in theory you can change a null resource
                        # into an actual value as available
                        if r.random() < 0.25:
                            node.available[rname] = draw_value()

            return node
def _print_demand(output_format: OutputFormat) -> str:
    stream = io.StringIO()

    node = SchedulerNode("tux", {"ncpus": 2, "mem": Memory.value_of("1.0g")})
    node.available["ncpus"] = 1
    node.assign("11")
    node.assign("12")

    result = DemandResult([], [node], [], [])
    print_demand(
        ["hostname", "job_ids", "ncpus", "*ncpus", "mem"],
        result,
        stream=stream,
        output_format=output_format,
    )
    return stream.getvalue()
예제 #4
0
def test_job_excl() -> None:
    s = SchedulerNode("")
    # typical exclusive behavior - one task per job per node
    job_excl = get_constraint({"exclusive": True})
    assert job_excl.job_exclusive
    assert isinstance(job_excl, ExclusiveNode)
    assert job_excl.satisfied_by_node(s)
    assert -1 == job_excl.minimum_space(s)
    assert job_excl.do_decrement(s)

    s.assign("1")
    job_excl.assignment_id = "1"
    # can't put the same jobid on the same node twice
    assert not job_excl.satisfied_by_node(s)
    assert not job_excl.do_decrement(s)
    assert s.closed
    assert 0 == job_excl.minimum_space(s)
예제 #5
0
def test_task_excl() -> None:
    s = SchedulerNode("")

    # now to test tack exclusive, where multiple tasks from the same
    # job can run on the same machine
    task_excl = get_constraint({"exclusive_task": True})
    assert not task_excl.job_exclusive
    assert isinstance(task_excl, ExclusiveNode)
    assert task_excl.satisfied_by_node(s)
    assert -1 == task_excl.minimum_space(s)
    assert task_excl.do_decrement(s)

    s.assign("1")
    task_excl.assignment_id = "1"
    assert task_excl.satisfied_by_node(s)
    assert task_excl.do_decrement(s)

    assert s.closed

    assert -1 == task_excl.minimum_space(s)
예제 #6
0
def parse_scheduler_node(
    ndict: Dict[str, Any],
    resource_definitions: Dict[str,
                               PBSProResourceDefinition]) -> SchedulerNode:
    """
    Implementation of parsing a single scheduler node.
    """
    parser = get_pbspro_parser()

    hostname = ndict["name"]
    res_avail = parser.parse_resources_available(ndict, filter_is_host=True)
    res_assigned = parser.parse_resources_assigned(ndict, filter_is_host=True)

    node = SchedulerNode(hostname, res_avail)
    jobs_expr = ndict.get("jobs", "")

    state = ndict.get("state") or ""

    if state == "free" and jobs_expr.strip():
        state = "partially-free"

    node.metadata["pbs_state"] = state

    if "down" in state:
        node.marked_for_deletion = True

    node.metadata["last_state_change_time"] = ndict.get(
        "last_state_change_time", "")

    for tok in jobs_expr.split(","):
        tok = tok.strip()
        if not tok:
            continue
        job_id_full, sub_job_id = tok.rsplit("/", 1)
        sched_host = ""
        if "." in job_id_full:
            job_id, sched_host = job_id_full.split(".", 1)
        else:
            job_id = job_id_full

        node.assign(job_id)

        if "job_ids_long" not in node.metadata:
            node.metadata["job_ids_long"] = [job_id_full]
        elif job_id_full not in node.metadata["job_ids_long"]:
            node.metadata["job_ids_long"].append(job_id_full)

    for res_name, value in res_assigned.items():
        resource = resource_definitions.get(res_name)

        if not resource or not resource.is_host:
            continue

        if resource.is_consumable:
            if res_name in node.available:
                node.available[res_name] -= value
            else:
                logging.warning(
                    "%s was not defined under resources_available, but was " +
                    "defined under resources_assigned for %s. Setting available to assigned.",
                    res_name,
                    node,
                )
                node.available[res_name] = value

    if "exclusive" in node.metadata["pbs_state"]:
        node.closed = True

    return node