def __init__(self, remote_host, remote_port=56000):
        """
        :param remote_host: The IP address of the PushBot
        :type remote_host: str
        :param remote_port: The port number of the PushBot (default 56000)
        :type remote_port: int
        :raise spinnman.exceptions.SpinnmanIOException: \
            If there is an error setting up the communication channel
        """
        try:
            # Create a TCP Socket
            self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        except Exception as e:
            raise_from(
                SpinnmanIOException("Error setting up socket: {}".format(e)),
                e)

        # Get the port to connect to
        self.__remote_port = int(remote_port)

        # Get the host to connect to
        self.__remote_ip_address = socket.gethostbyname(remote_host)

        try:
            logger.info("Trying to connect to the PushBot via Wi-Fi")
            # Connect the socket
            self.__socket.connect(
                (self.__remote_ip_address, self.__remote_port))
            logger.info("Succeeded in connecting to PushBot via Wi-Fi")

        except Exception as e:
            raise_from(
                SpinnmanIOException("Error binding socket to {}:{}: {}".format(
                    self.__remote_ip_address, self.__remote_port, e)), e)

        # Get the details of where the socket is connected
        try:
            self.__local_ip_address, self.__local_port =\
                self.__socket.getsockname()

            # Ensure that a standard address is used for the INADDR_ANY
            # hostname
            if (self.__local_ip_address is None
                    or self.__local_ip_address == ""):
                self.__local_ip_address = "0.0.0.0"
        except Exception as e:
            raise_from(
                SpinnmanIOException("Error querying socket: {}".format(e)), e)

        # Set a general timeout on the socket
        self.__socket.settimeout(0)
Beispiel #2
0
    def send(self, data):
        """ Send data down this connection

        :param data: The data to be sent
        :type data: bytestring
        :raise SpinnmanIOException: If there is an error sending the data
        """
        if not self._can_send:
            raise SpinnmanIOException(
                "Remote host and/or port not set - data cannot be sent with"
                " this connection")
        try:
            self._socket.send(data)
        except Exception as e:
            raise SpinnmanIOException(str(e))
    def __run(self):
        # pylint: disable=broad-except
        self.__running = True
        logger.info(
            "{}:{} Waiting for message to indicate that the database is "
            "ready", self.local_ip_address, self.local_port)
        try:
            while self.__running:
                try:
                    data, address = self.receive_with_address(timeout=3)
                except SpinnmanTimeoutException:
                    continue
                self.__read_db(address, data)

                # Wait for the start of the simulation
                if self.__start_resume_callback is not None:
                    self.__start_resume()

                # Wait for the end of the simulation
                if self.__pause_and_stop_callback is not None:
                    self.__pause_stop()
        except Exception as e:
            logger.error("Failure processing database callback", exc_info=True)
            raise_from(SpinnmanIOException(str(e)), e)
        finally:
            self.__running = False
Beispiel #4
0
 def _get_boot_image_file():
     """
     :rtype: tuple(str,int)
     """
     this_dir, _ = os.path.split(__file__)
     file_name = os.path.join(this_dir, "boot_data", _BOOT_DATA_FILE_NAME)
     file_size = os.stat(file_name).st_size
     if file_size > _BOOT_IMAGE_MAX_BYTES:
         raise SpinnmanIOException(
             "The boot file is too big at {} bytes (only files up to 32KB "
             "are acceptable".format(file_size))
     elif file_size % 4 != 0:
         raise SpinnmanIOException(
             "The boot file size of {} bytes must be divisible by 4".format(
                 file_size))
     return file_name, file_size
Beispiel #5
0
def connect_socket(sock, remote_address, remote_port):
    """ Wrapper round connect() system call.
    """
    try:
        sock.connect((str(remote_address), int(remote_port)))
    except Exception as exception:  # pylint: disable=broad-except
        raise SpinnmanIOException("Error connecting to {}:{}: {}".format(
            remote_address, remote_port, exception)) from exception
Beispiel #6
0
def resolve_host(host):
    """ Wrapper round gethostbyname() system call.
    """
    try:
        return socket.gethostbyname(host)
    except Exception as exception:  # pylint: disable=broad-except
        raise SpinnmanIOException("Error getting IP address for {}: {}".format(
            host, exception)) from exception
Beispiel #7
0
def bind_socket(sock, host, port):
    """ Wrapper round bind() system call.
    """
    try:
        # Bind the socket
        sock.bind((str(host), int(port)))
    except Exception as exception:  # pylint: disable=broad-except
        raise SpinnmanIOException("Error binding socket to {}:{}: {}".format(
            host, port, exception)) from exception
Beispiel #8
0
def get_socket():
    """ Wrapper round socket() system call.
    """
    try:
        # Create a UDP Socket
        return socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    except Exception as exception:  # pylint: disable=broad-except
        raise SpinnmanIOException(
            "Error setting up socket: {}".format(exception)) from exception
Beispiel #9
0
    def send(self, data):
        """ Send data down this connection

        :param bytearray data: The data to be sent
        :raise SpinnmanIOException: If there is an error sending the data
        """
        try:
            self.__socket.send(data)
        except Exception as e:  # pylint: disable=broad-except
            raise_from(SpinnmanIOException(str(e)), e)
    def send(self, data):
        """ Send data down this connection

        :param data: The data to be sent
        :type data: bytestring
        :raise SpinnmanIOException: If there is an error sending the data
        """
        try:
            self.__socket.send(data)
        except Exception as e:
            raise_from(SpinnmanIOException(str(e)), e)
Beispiel #11
0
    def send(self, data):
        """ Send data down this connection

        :param data: The data to be sent
        :type data: bytes or bytearray
        :raise SpinnmanIOException: If there is an error sending the data
        """
        if self._socket._closed:
            raise SpinnmanEOFException()
        if not self._can_send:
            raise SpinnmanIOException(
                "Remote host and/or port not set - data cannot be sent with"
                " this connection")
        try:
            while not self._socket.send(data):
                if self._socket._closed:
                    raise SpinnmanEOFException()
        except SpinnmanIOException:
            raise
        except Exception as e:  # pylint: disable=broad-except
            raise SpinnmanIOException(str(e)) from e
Beispiel #12
0
    def send_to(self, data, address):
        """ Send data down this connection

        :param data: The data to be sent
        :type data: bytestring
        :param address: A tuple of (address, port) to send the data to
        :type address: (str, int)
        :raise SpinnmanIOException: If there is an error sending the data
        """
        try:
            self._socket.sendto(data, address)
        except Exception as e:
            raise SpinnmanIOException(str(e))
Beispiel #13
0
def get_socket_address(sock):
    """ Wrapper round getsockname() system call.
    """
    try:
        addr, port = sock.getsockname()
        # Ensure that a standard address is used for the INADDR_ANY
        # hostname
        if addr is None or addr == "":
            addr = "0.0.0.0"
        return addr, port
    except Exception as exception:  # pylint: disable=broad-except
        raise SpinnmanIOException(
            "Error querying socket: {}".format(exception)) from exception
 def run(self):
     self._running = True
     logger.info(
         "{}:{} Waiting for message to indicate that the database is "
         "ready", self.local_ip_address, self.local_port)
     try:
         while self._running:
             data, address = self._retrieve_database_address()
             if data is not None:
                 self._process_message(address, data)
     except Exception as e:
         logger.error("Failure processing database callback",
                      exc_info=True)
         raise_from(SpinnmanIOException(str(e)), e)
     finally:
         self._running = False
    def receive(self, timeout=None):
        """ Receive data from the connection

        :param timeout: The timeout, or None to wait forever
        :type timeout: float or None
        :return: The data received
        :rtype: bytestring
        :raise SpinnmanTimeoutException: \
            If a timeout occurs before any data is received
        :raise SpinnmanIOException: If an error occurs receiving the data
        """
        try:
            self.__socket.settimeout(timeout)
            return self.__socket.recv(1024)
        except socket.timeout:
            raise SpinnmanTimeoutException("receive", timeout)
        except Exception as e:
            raise_from(SpinnmanIOException(str(e)), e)
Beispiel #16
0
    def receive(self, timeout=None):
        """ Receive data from the connection

        :param float timeout: The timeout in seconds, or None to wait forever
        :return: The data received as a bytestring
        :rtype: bytes
        :raise SpinnmanTimeoutException:
            If a timeout occurs before any data is received
        :raise SpinnmanIOException: If an error occurs receiving the data
        """
        if self._socket._closed:
            raise SpinnmanEOFException()
        try:
            self._socket.settimeout(timeout)
            return self._socket.recv(300)
        except socket.timeout as e:
            raise SpinnmanTimeoutException("receive", timeout) from e
        except Exception as e:  # pylint: disable=broad-except
            raise SpinnmanIOException(str(e)) from e
Beispiel #17
0
    def send_to(self, data, address):
        """ Send data down this connection

        :param data: The data to be sent as a bytestring
        :type data: bytes or bytearray
        :param tuple(str,int) address:
            A tuple of (address, port) to send the data to
        :raise SpinnmanIOException: If there is an error sending the data
        """
        if self._socket._closed:
            raise SpinnmanEOFException()
        try:
            while not self._socket.sendto(data, address):
                if self._socket._closed:
                    raise SpinnmanEOFException()
        except SpinnmanIOException:
            raise
        except Exception as e:  # pylint: disable=broad-except
            raise SpinnmanIOException(str(e)) from e
Beispiel #18
0
    def receive_with_address(self, timeout=None):
        """ Receive data from the connection along with the address where the\
            data was received from

        :param timeout: The timeout, or None to wait forever
        :type timeout: None
        :return: A tuple of the data received and a tuple of the\
                (address, port) received from
        :rtype: (bytestring, (str, int))
        :raise SpinnmanTimeoutException: If a timeout occurs before any data\
                    is received
        :raise SpinnmanIOException: If an error occurs receiving the data
        """
        try:
            self._socket.settimeout(timeout)
            return self._socket.recvfrom(300)
        except socket.timeout:
            raise SpinnmanTimeoutException("receive", timeout)
        except Exception as e:
            raise SpinnmanIOException(str(e))
Beispiel #19
0
    def receive_with_address(self, timeout=None):
        """ Receive data from the connection along with the address where the\
            data was received from

        :param float timeout: The timeout, or None to wait forever
        :return: A tuple of the data received and a tuple of the
            (address, port) received from
        :rtype: tuple(bytes, tuple(str, int))
        :raise SpinnmanTimeoutException:
            If a timeout occurs before any data is received
        :raise SpinnmanIOException: If an error occurs receiving the data
        """
        if self._socket._closed:
            raise SpinnmanEOFException()
        try:
            self._socket.settimeout(timeout)
            return self._socket.recvfrom(300)
        except socket.timeout as e:
            raise SpinnmanTimeoutException("receive", timeout) from e
        except Exception as e:  # pylint: disable=broad-except
            raise SpinnmanIOException(str(e)) from e
Beispiel #20
0
    def _resend(self, seq, request_sent, reason):
        if self._retries[seq] <= 0:
            # Report timeouts as timeout exception
            if all(reason == "timeout" for reason in self._retry_reason[seq]):
                raise SpinnmanTimeoutException(
                    request_sent.scp_request_header.command,
                    self._packet_timeout)

            # Report any other exception
            raise SpinnmanIOException(
                "Errors sending request {} to {}, {}, {} over {} retries: {}".
                format(request_sent.scp_request_header.command,
                       request_sent.sdp_header.destination_chip_x,
                       request_sent.sdp_header.destination_chip_y,
                       request_sent.sdp_header.destination_cpu,
                       self._n_retries, self._retry_reason[seq]))

        # If the request can be retried, retry it
        self._retries[seq] -= 1
        self._in_progress += 1
        self._requests[seq] = request_sent
        self._retry_reason[seq].append(reason)
        self._connection.send(self._request_data[seq])
        self._n_resent += 1
    def __init__(
            self, board_version, width, height, number_of_boards):
        """
        builds the boot messages needed to boot the spinnaker machine

        :param board_version: The version of the board to be booted
        :type board_version: int
        :param width: The width of the machine in chips
        :type width: int or None
        :param height: The height of the machine in chips
        :type height: int or None
        :param number_of_boards: the number of boards that this spinnaker
            machine is built up from
        :type number_of_boards: int
        :raise spinnman.exceptions.SpinnmanInvalidParameterException: If the\
                    board version is not supported
        :raise spinnman.exceptions.SpinnmanIOException: If there is an error\
                    assembling the packets
        """
        if board_version not in variable_boot_values.spinnaker_boot_values:
            raise SpinnmanInvalidParameterException(
                "board_version", str(board_version), "Unknown board version")

        # Get the boot packet values
        spinnaker_boot_value = \
            variable_boot_values.spinnaker_boot_values[board_version]

        current_time = int(time.time())
        spinnaker_boot_value.set_value(
            SystemVariableDefinition.unix_timestamp, current_time)
        spinnaker_boot_value.set_value(
            SystemVariableDefinition.boot_signature, current_time)
        spinnaker_boot_value.set_value(
            SystemVariableDefinition.is_root_chip, 1)
        spinnaker_boot_value.set_value(
            SystemVariableDefinition.x_size, int(width))
        spinnaker_boot_value.set_value(
            SystemVariableDefinition.y_size, int(height))

        # add any updates for multi-board systems
        for multi_board_n_boards, extra_variables in (
                variable_boot_values
                .spinnaker_multi_board_extra_configs.iteritems()):
            if number_of_boards >= multi_board_n_boards:
                for extra_variable, extra_value in extra_variables.iteritems():
                    spinnaker_boot_value.set_value(extra_variable, extra_value)

        # Get the data as an array, to be used later
        self._spinnaker_boot_data = array.array(
            "I", spinnaker_boot_value.bytestring)

        # Find the data file and size
        this_dir, _ = os.path.split(__file__)
        boot_data_file_name = os.path.join(
            this_dir, "boot_data", _BOOT_DATA_FILE_NAME)
        boot_data_file_size = os.stat(boot_data_file_name).st_size
        if boot_data_file_size > _BOOT_IMAGE_MAX_BYTES:
            raise SpinnmanIOException(
                "The boot file is too big at {} bytes ("
                "only files up to 32KB are acceptable".format(
                    boot_data_file_size))
        elif boot_data_file_size % 4 != 0:
            raise SpinnmanIOException(
                "The boot file size of {} bytes must"
                " be divisible by 4".format(boot_data_file_size))

        # Compute how many packets to send
        self._boot_data_file = open(boot_data_file_name, "rb")
        self._no_data_packets = int(math.ceil(
            float(boot_data_file_size) / float(_BOOT_MESSAGE_DATA_BYTES)))
        self._n_words_to_read = boot_data_file_size / 4
Beispiel #22
0
    def __init__(self,
                 local_host=None,
                 local_port=None,
                 remote_host=None,
                 remote_port=None):
        """
        :param local_host: The local host name or ip address to bind to.\
                    If not specified defaults to bind to all interfaces,\
                    unless remote_host is specified, in which case binding is\
                    _done to the ip address that will be used to send packets
        :type local_host: str or None
        :param local_port: The local port to bind to, between 1025 and 65535.\
                    If not specified, defaults to a random unused local port
        :type local_port: int
        :param remote_host: The remote host name or ip address to send packets\
                    to.  If not specified, the socket will be available for\
                    listening only, and will throw and exception if used for\
                    sending
        :type remote_host: str or None
        :param remote_port: The remote port to send packets to.  If\
                    remote_host is None, this is ignored.  If remote_host is\
                    specified, this must also be specified for the connection\
                    to allow sending
        :raise spinnman.exceptions.SpinnmanIOException: If there is an error\
                    setting up the communication channel
        """

        self._socket = None
        try:

            # Create a UDP Socket
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        except Exception as exception:
            raise SpinnmanIOException(
                "Error setting up socket: {}".format(exception))

        # Get the port to bind to locally
        local_bind_port = 0
        if local_port is not None:
            local_bind_port = int(local_port)

        # Get the host to bind to locally
        local_bind_host = ""
        if local_host is not None:
            local_bind_host = str(local_host)

        try:
            # Bind the socket
            self._socket.bind((local_bind_host, local_bind_port))

        except Exception as exception:
            raise SpinnmanIOException(
                "Error binding socket to {}:{}: {}".format(
                    local_bind_host, local_bind_port, exception))

        # Mark the socket as non-sending, unless the remote host is
        # specified - send requests will then cause an exception
        self._can_send = False
        self._remote_ip_address = None
        self._remote_port = None

        # Get the host to connect to remotely
        if remote_host is not None and remote_port is not None:
            self._can_send = True
            self._remote_port = remote_port

            try:
                self._remote_ip_address = socket.gethostbyname(remote_host)
            except Exception as exception:
                raise SpinnmanIOException(
                    "Error getting ip address for {}: {}".format(
                        remote_host, exception))

            try:
                self._socket.connect((self._remote_ip_address, remote_port))
            except Exception as exception:
                raise SpinnmanIOException(
                    "Error connecting to {}:{}: {}".format(
                        self._remote_ip_address, remote_port, exception))

        # Get the details of where the socket is connected
        self._local_ip_address = None
        self._local_port = None
        try:
            self._local_ip_address, self._local_port =\
                self._socket.getsockname()

            # Ensure that a standard address is used for the INADDR_ANY
            # hostname
            if self._local_ip_address is None or self._local_ip_address == "":
                self._local_ip_address = "0.0.0.0"
        except Exception as exception:
            raise SpinnmanIOException(
                "Error querying socket: {}".format(exception))

        # Set a general timeout on the socket
        self._socket.settimeout(1.0)