def __call__(self,
                 spalloc_server,
                 spalloc_port=22244,
                 spalloc_machine=None):
        with ProtocolClient(spalloc_server, spalloc_port) as client:
            machines = client.list_machines()
            # Close the context immediately; don't want to keep this particular
            # connection around as there's not a great chance of this code
            # being rerun in this process any time soon.
        max_width = None
        max_height = None
        max_area = -1

        for machine in self._filter(machines, spalloc_machine):
            # Get the width and height in chips, and logical area in chips**2
            width, height, area = self._get_size(machine)

            # The "biggest" board is the one with the most chips
            if area > max_area:
                max_area = area
                max_width = width
                max_height = height

        # Return the width and height, and make no assumption about wrap-
        # arounds or version.
        return max_width, max_height, None, None
Exemplo n.º 2
0
def test_close(c, s, bg_accept):
    # If already connected, should be able to close
    assert not c._has_open_socket()
    c.connect()
    assert c._has_open_socket()
    c.close()
    assert not c._has_open_socket()
    bg_accept.join()
    s.close()

    # Should be able to close again
    c.close()
    assert not c._has_open_socket()

    # And should be able to close a newly created connection
    c = ProtocolClient("localhost")
    assert not c._has_open_socket()
    c.close()
    assert not c._has_open_socket()
Exemplo n.º 3
0
    def test_reconnect(self):
        # If previously connected, connecting should close the existing
        # connection and attempt to start a new one
        c = ProtocolClient("localhost")

        started = threading.Event()

        def accept_and_listen():
            s = MockServer()
            s.listen()
            started.set()
            s.connect()

        # Attempt several reconnects
        for _ in range(3):
            t = threading.Thread(target=accept_and_listen)
            t.start()
            started.wait()
            started.clear()
            c.connect()
            t.join()
Exemplo n.º 4
0
    def __call__(self,
                 spalloc_server,
                 spalloc_port=22244,
                 spalloc_machine=None,
                 max_sdram_size=None,
                 max_machine_core_reduction=0):
        """
        :param str spalloc_server:
        :param int spalloc_port:
        :param str spalloc_machine:
        :param int max_sdram_size:
        :param int max_machine_core_reduction:
        :rtype: ~.Machine
        """
        with ProtocolClient(spalloc_server, spalloc_port) as client:
            machines = client.list_machines()
            # Close the context immediately; don't want to keep this particular
            # connection around as there's not a great chance of this code
            # being rerun in this process any time soon.
        max_width = None
        max_height = None
        max_area = -1

        for machine in self._filter(machines, spalloc_machine):
            # Get the width and height in chips, and logical area in chips**2
            width, height, area = self._get_size(machine)

            # The "biggest" board is the one with the most chips
            if area > max_area:
                max_area = area
                max_width = width
                max_height = height

        if max_width is None:
            raise Exception(
                "The spalloc server appears to have no compatible machines")

        n_cpus_per_chip = (Machine.max_cores_per_chip() -
                           max_machine_core_reduction)

        # Return the width and height, and make no assumption about wrap-
        # arounds or version.
        return virtual_machine(width=max_width,
                               height=max_height,
                               sdram_per_chip=max_sdram_size,
                               n_cpus_per_chip=n_cpus_per_chip,
                               validate=False)
Exemplo n.º 5
0
def main(argv=None):
    t = Terminal(stream=sys.stderr)

    cfg = config.read_config()

    parser = argparse.ArgumentParser(description="List all active jobs.")

    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version=__version__)

    parser.add_argument("--watch",
                        "-w",
                        action="store_true",
                        default=False,
                        help="watch the list of live jobs in real time")

    filter_args = parser.add_argument_group("filtering arguments")

    filter_args.add_argument("--machine",
                             "-m",
                             help="list only jobs on the specified "
                             "machine")
    filter_args.add_argument("--owner",
                             "-o",
                             help="list only jobs belonging to a particular "
                             "owner")

    server_args = parser.add_argument_group("spalloc server arguments")

    server_args.add_argument("--hostname",
                             "-H",
                             default=cfg["hostname"],
                             help="hostname or IP of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--port",
                             "-P",
                             default=cfg["port"],
                             type=int,
                             help="port number of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--timeout",
                             default=cfg["timeout"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait for a response "
                             "from the server (default: %(default)s)")

    args = parser.parse_args(argv)

    # Fail if server not specified
    if args.hostname is None:
        parser.error("--hostname of spalloc server must be specified")

    client = ProtocolClient(args.hostname, args.port)
    try:
        # Connect to server and ensure compatible version
        client.connect()
        version = tuple(
            map(int,
                client.version(timeout=args.timeout).split(".")))
        if not (VERSION_RANGE_START <= version < VERSION_RANGE_STOP):
            sys.stderr.write("Incompatible server version ({}).\n".format(
                ".".join(map(str, version))))
            return 2

        if args.watch:
            client.notify_job(timeout=args.timeout)

        while True:
            jobs = client.list_jobs(timeout=args.timeout)

            # Clear the screen before reprinting the table
            if args.watch:
                sys.stdout.write(t.clear_screen())

            print(render_job_list(t, jobs, args.machine, args.owner))

            # Exit or wait for changes, if requested
            if not args.watch:
                return 0
            else:
                # Wait for state change
                try:
                    client.wait_for_notification()
                except KeyboardInterrupt:
                    # Gracefully exit
                    print("")
                    return 0

                # Print a newline to separate old table from the new table when
                # it gets printed if ANSI screen clearing is not possible.
                print("")

    except (IOError, OSError, ProtocolTimeoutError) as e:
        sys.stderr.write("Error communicating with server: {}\n".format(e))
        return 1
    finally:
        client.close()
Exemplo n.º 6
0
def main(argv=None):
    t = Terminal()

    cfg = config.read_config()

    parser = argparse.ArgumentParser(
        description="Get the state of individual machines.")

    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version=__version__)

    parser.add_argument("machine",
                        nargs="?",
                        help="if given, specifies the machine to inspect")

    parser.add_argument("--watch",
                        "-w",
                        action="store_true",
                        default=False,
                        help="update the output when things change.")

    parser.add_argument("--detailed",
                        "-d",
                        action="store_true",
                        default=False,
                        help="list detailed job information")

    server_args = parser.add_argument_group("spalloc server arguments")

    server_args.add_argument("--hostname",
                             "-H",
                             default=cfg["hostname"],
                             help="hostname or IP of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--port",
                             "-P",
                             default=cfg["port"],
                             type=int,
                             help="port number of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--timeout",
                             default=cfg["timeout"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait for a response "
                             "from the server (default: %(default)s)")

    args = parser.parse_args(argv)

    # Fail if server not specified
    if args.hostname is None:
        parser.error("--hostname of spalloc server must be specified")

    # Fail if --detailed used without specifying machine
    if args.machine is None and args.detailed:
        parser.error(
            "--detailed only works when a specific machine is specified")

    client = ProtocolClient(args.hostname, args.port)
    try:
        # Connect to server and ensure compatible version
        client.connect()
        version = tuple(
            map(int,
                client.version(timeout=args.timeout).split(".")))
        if not (VERSION_RANGE_START <= version < VERSION_RANGE_STOP):
            sys.stderr.write("Incompatible server version ({}).\n".format(
                ".".join(map(str, version))))
            return 2

        while True:
            if args.watch:
                client.notify_machine(args.machine, timeout=args.timeout)
                t.stream.write(t.clear_screen())
                # Prevent errors on stderr being cleared away due to clear
                # being buffered
                t.stream.flush()

            # Get all information
            machines = client.list_machines(timeout=args.timeout)
            jobs = client.list_jobs(timeout=args.timeout)

            # Display accordingly
            if args.machine is None:
                retval = list_machines(t, machines, jobs)
            else:
                retval = show_machine(t, machines, jobs, args.machine,
                                      not args.detailed)

            # Wait for changes (if required)
            if retval != 0 or not args.watch:
                return retval
            else:
                try:
                    client.wait_for_notification()
                    print("")
                except KeyboardInterrupt:
                    print("")
                    return 0

    except (IOError, OSError, ProtocolTimeoutError) as e:
        sys.stderr.write("Error communicating with server: {}\n".format(e))
        return 1
    finally:
        client.close()
Exemplo n.º 7
0
def main(argv=None):
    cfg = config.read_config()

    parser = argparse.ArgumentParser(
        description="Find out the location (physical or logical) "
        "of a chip or board.")

    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version=__version__)

    control_args = parser.add_mutually_exclusive_group(required=True)
    control_args.add_argument("--board",
                              "-b",
                              "--logical",
                              "-l",
                              nargs=4,
                              metavar=("MACHINE", "X", "Y", "Z"),
                              help="specify the logical board coordinate")
    control_args.add_argument("--physical",
                              "-p",
                              nargs=4,
                              metavar=("MACHINE", "CABINET", "FRAME", "BOARD"),
                              help="specify a board's physical location")
    control_args.add_argument("--chip",
                              "-c",
                              nargs=3,
                              metavar=("MACHINE", "X", "Y"),
                              help="specify a board by chip coordinates (as "
                              "if the whole machine is being used)")
    control_args.add_argument("--job-chip",
                              "-j",
                              nargs=3,
                              metavar=("JOB_ID", "X", "Y"),
                              help="specify the chip coordinates of a chip "
                              "within a job's boards")

    server_args = parser.add_argument_group("spalloc server arguments")

    server_args.add_argument("--hostname",
                             "-H",
                             default=cfg["hostname"],
                             help="hostname or IP of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--port",
                             "-P",
                             default=cfg["port"],
                             type=int,
                             help="port number of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--timeout",
                             default=cfg["timeout"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait for a response "
                             "from the server (default: %(default)s)")

    args = parser.parse_args(argv)

    # Fail if server not specified
    if args.hostname is None:
        parser.error("--hostname of spalloc server must be specified")

    client = ProtocolClient(args.hostname, args.port)
    try:
        # Connect to server and ensure compatible version
        client.connect()
        version = tuple(
            map(int,
                client.version(timeout=args.timeout).split(".")))
        if not (VERSION_RANGE_START <= version < VERSION_RANGE_STOP):
            sys.stderr.write("Incompatible server version ({}).\n".format(
                ".".join(map(str, version))))
            return 2

        # Work out what the user asked for
        try:
            show_board_chip = False
            if args.board:
                machine, x, y, z = args.board
                where_is_kwargs = {
                    "machine": machine,
                    "x": int(x),
                    "y": int(y),
                    "z": int(z),
                }
            elif args.physical:
                machine, c, f, b = args.physical
                where_is_kwargs = {
                    "machine": machine,
                    "cabinet": int(c),
                    "frame": int(f),
                    "board": int(b),
                }
            elif args.chip:
                machine, x, y = args.chip
                where_is_kwargs = {
                    "machine": machine,
                    "chip_x": int(x),
                    "chip_y": int(y),
                }
                show_board_chip = True
            elif args.job_chip:
                job_id, x, y = args.job_chip
                where_is_kwargs = {
                    "job_id": int(job_id),
                    "chip_x": int(x),
                    "chip_y": int(y),
                }
                show_board_chip = True
        except ValueError as e:
            parser.error("Error: {}".format(e))

        # Ask the server
        location = client.where_is(**where_is_kwargs)
        if location is None:
            sys.stderr.write("No boards at the specified location.\n")
            return 4
        else:
            out = OrderedDict()
            out["Machine"] = location["machine"]
            out["Physical location"] = "Cabinet {}, Frame {}, Board {}".format(
                *location["physical"])
            out["Board coordinate"] = tuple(location["logical"])
            out["Machine chip coordinates"] = tuple(location["chip"])
            if show_board_chip:
                out["Coordinates within board"] = tuple(location["board_chip"])
            out["Job using board"] = location["job_id"]
            if location["job_id"]:
                out["Coordinates within job"] = tuple(location["job_chip"])

            print(render_definitions(out))
            return 0

    except (IOError, OSError, ProtocolTimeoutError) as e:
        sys.stderr.write("Error communicating with server: {}\n".format(e))
        return 1
    finally:
        client.close()
Exemplo n.º 8
0
def main(argv=None):
    t = Terminal()

    cfg = config.read_config()

    parser = argparse.ArgumentParser(description="Manage running jobs.")

    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version=__version__)

    parser.add_argument("job_id",
                        type=int,
                        nargs="?",
                        help="the job ID of interest, optional if the current "
                        "owner only has one job")

    parser.add_argument("--owner",
                        "-o",
                        default=cfg["owner"],
                        help="if no job ID is provided and this owner has "
                        "only one job, this job is assumed "
                        "(default: %(default)s)")

    control_args = parser.add_mutually_exclusive_group()

    control_args.add_argument("--info",
                              "-i",
                              action="store_true",
                              help="Show basic job information (the default)")
    control_args.add_argument("--watch",
                              "-w",
                              action="store_true",
                              help="watch this job for state changes")
    control_args.add_argument("--power-on",
                              "--reset",
                              "-p",
                              "-r",
                              action="store_true",
                              help="power-on or reset the job's boards")
    control_args.add_argument("--power-off",
                              action="store_true",
                              help="power-off the job's boards")
    control_args.add_argument("--ethernet-ips",
                              "-e",
                              action="store_true",
                              help="output the IPs of all Ethernet connected "
                              "chips as a CSV")
    control_args.add_argument("--destroy",
                              "-D",
                              nargs="?",
                              metavar="REASON",
                              const="",
                              help="destroy a queued or running job")

    server_args = parser.add_argument_group("spalloc server arguments")

    server_args.add_argument("--hostname",
                             "-H",
                             default=cfg["hostname"],
                             help="hostname or IP of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--port",
                             "-P",
                             default=cfg["port"],
                             type=int,
                             help="port number of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--timeout",
                             default=cfg["timeout"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait for a response "
                             "from the server (default: %(default)s)")

    args = parser.parse_args(argv)

    # Fail if server not specified
    if args.hostname is None:
        parser.error("--hostname of spalloc server must be specified")

    # Fail if job *and* owner not specified
    if args.job_id is None and args.owner is None:
        parser.error("job ID (or --owner) not specified")

    client = ProtocolClient(args.hostname, args.port)
    try:
        # Connect to server and ensure compatible version
        client.connect()
        version = tuple(
            map(int,
                client.version(timeout=args.timeout).split(".")))
        if not (VERSION_RANGE_START <= version < VERSION_RANGE_STOP):
            sys.stderr.write("Incompatible server version ({}).\n".format(
                ".".join(map(str, version))))
            return 2

        # If no Job ID specified, attempt to discover one
        if args.job_id is None:
            jobs = client.list_jobs(timeout=args.timeout)
            job_ids = [
                job["job_id"] for job in jobs if job["owner"] == args.owner
            ]
            if len(job_ids) == 0:
                sys.stderr.write("Owner {} has no live jobs.\n".format(
                    args.owner))
                return 3
            elif len(job_ids) > 1:
                sys.stderr.write("Ambiguous: {} has {} live jobs: {}\n".format(
                    args.owner, len(job_ids), ", ".join(map(str, job_ids))))
                return 3
            else:
                args.job_id = job_ids[0]

        # Do as the user asked
        if args.watch:
            return watch_job(t, client, args.timeout, args.job_id)
        elif args.power_on:
            return power_job(client, args.timeout, args.job_id, True)
        elif args.power_off:
            return power_job(client, args.timeout, args.job_id, False)
        elif args.ethernet_ips:
            return list_ips(client, args.timeout, args.job_id)
        elif args.destroy is not None:
            # Set default destruction message
            if args.destroy == "" and args.owner:
                args.destroy = "Destroyed by {}".format(args.owner)
            return destroy_job(client, args.timeout, args.job_id, args.destroy)
        else:
            return show_job_info(t, client, args.timeout, args.job_id)

    except (IOError, OSError, ProtocolTimeoutError) as e:
        sys.stderr.write("Error communicating with server: {}\n".format(e))
        return 1
    finally:
        client.close()
Exemplo n.º 9
0
 def test_no_server(self):
     # Should just fail if there is no server
     c = ProtocolClient("localhost")
     with pytest.raises((IOError, OSError)):
         c.connect()
Exemplo n.º 10
0
def c():
    c = ProtocolClient("localhost")
    yield c
    c.close()