• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / SpiNNFrontEndCommon / 8143402062

04 Mar 2024 04:13PM UTC coverage: 47.969% (-0.02%) from 47.992%
8143402062

push

github

web-flow
Merge pull request #1157 from SpiNNakerManchester/pylint_default

Pylint default

2050 of 4800 branches covered (42.71%)

Branch coverage included in aggregate %.

63 of 110 new or added lines in 37 files covered. (57.27%)

26 existing lines in 18 files now uncovered.

5484 of 10906 relevant lines covered (50.28%)

0.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.62
/spinn_front_end_common/abstract_models/impl/machine_allocation_controller.py
1
# Copyright (c) 2017 The University of Manchester
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     https://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
import logging
1✔
16
import sys
1✔
17
from threading import Thread
1✔
18
from typing import Dict, Optional, Tuple
1✔
19
from spinn_utilities.log import FormatAdapter
1✔
20
from spinn_utilities.abstract_base import AbstractBase, abstractmethod
1✔
21
from spinn_utilities.typing.coords import XY
1✔
22
from spinnman.constants import SCP_SCAMP_PORT
1✔
23
from spinnman.connections.udp_packet_connections import SCAMPConnection
1✔
24
from spinnman.transceiver import create_transceiver_from_hostname, Transceiver
1✔
25
from spinnman.connections.udp_packet_connections import EIEIOConnection
1✔
26
logger = FormatAdapter(logging.getLogger(__name__))
1✔
27

28

29
class MachineAllocationController(object, metaclass=AbstractBase):
1✔
30
    """
31
    How to manage the allocation of a machine so that it gets cleaned up
32
    neatly when the script dies.
33
    """
34
    __slots__ = (
1✔
35
        #: Boolean flag for telling this thread when the system has ended
36
        "_exited",
37
        #: the address of the root board of the allocation
38
        "__hostname",
39
        "__connection_data")
40

41
    def __init__(self, thread_name: str, hostname: Optional[str] = None,
1✔
42
                 connection_data: Optional[Dict[XY, str]] = None):
43
        """
44
        :param str thread_name:
45
        """
46
        thread = Thread(name=thread_name, target=self.__manage_allocation)
1✔
47
        thread.daemon = True
1✔
48
        self._exited = False
1✔
49
        self.__hostname = hostname
1✔
50
        self.__connection_data = connection_data
1✔
51
        thread.start()
1✔
52

53
    @abstractmethod
1✔
54
    def extend_allocation(self, new_total_run_time: float):
1✔
55
        """
56
        Extend the allocation of the machine from the original run time.
57

58
        :param float new_total_run_time:
59
            The total run time that is now required starting from when the
60
            machine was first allocated
61
        """
62
        raise NotImplementedError
63

64
    def close(self) -> None:
1✔
65
        """
66
        Indicate that the use of the machine is complete.
67
        """
68
        self._exited = True
1✔
69

70
    @abstractmethod
1✔
71
    def _wait(self) -> bool:
1✔
72
        """
73
        Wait for some bounded amount of time for a change in the status
74
        of the machine allocation.
75

76
        :return: Whether the machine is still (believed to be) allocated.
77
        :rtype: bool
78
        """
79
        raise NotImplementedError
80

81
    @abstractmethod
1✔
82
    def where_is_machine(
1✔
83
            self, chip_x: int, chip_y: int) -> Tuple[int, int, int]:
84
        """
85
        Locates and returns cabinet, frame, board for a given chip in a
86
        machine allocated to this job.
87

88
        :param int chip_x: chip x location
89
        :param int chip_y: chip y location
90
        :return: (cabinet, frame, board)
91
        :rtype: tuple(int,int,int)
92
        """
93
        raise NotImplementedError
94

95
    def _teardown(self) -> None:
1✔
96
        """
97
        Perform any extra tear-down that the thread requires. Does not
98
        need to be overridden if no action is desired.
99
        """
100

101
    def __manage_allocation(self) -> None:
1✔
102
        machine_still_allocated = True
1✔
103
        while machine_still_allocated and not self._exited:
1✔
104
            machine_still_allocated = self._wait()
1✔
105
        self._teardown()
1✔
106
        if not self._exited:
1✔
107
            logger.error(
1✔
108
                "The allocated machine has been released before the end of"
109
                " the script; this script will now exit")
110
            sys.exit(1)
1✔
111

112
    def create_transceiver(self) -> Transceiver:
1✔
113
        """
114
        Create a transceiver for talking to the allocated machine, and
115
        make sure everything is ready for use (i.e. boot and discover
116
        connections if needed).
117

118
        :rtype: ~spinnman.transceiver.Transceiver
119
        """
120
        if not self.__hostname:
×
121
            raise NotImplementedError("Needs a hostname")
122
        txrx = create_transceiver_from_hostname(self.__hostname)
×
123
        txrx.discover_scamp_connections()
×
124
        return txrx
×
125

126
    def can_create_transceiver(self) -> bool:
1✔
127
        """
128
        Detects if a call to create_transceiver could work.
129

130
        :rtype: bool
131
        """
UNCOV
132
        return self.__hostname is not None
×
133

134
    def __host(self, chip_x: int, chip_y: int) -> Optional[str]:
1✔
135
        if not self.__connection_data:
×
136
            return None
×
137
        return self.__connection_data.get((chip_x, chip_y))
×
138

139
    def open_sdp_connection(
1✔
140
            self, chip_x: int, chip_y: int,
141
            udp_port: int = SCP_SCAMP_PORT) -> Optional[SCAMPConnection]:
142
        """
143
        Open a connection to a specific Ethernet-enabled SpiNNaker chip.
144
        Caller will have to arrange for SpiNNaker to pay attention to the
145
        connection.
146

147
        The coordinates will be job-relative.
148

149
        :param int chip_x: Ethernet-enabled chip X coordinate
150
        :param int chip_y: Ethernet-enabled chip Y coordinate
151
        :param int udp_port:
152
            the UDP port on the chip to connect to; connecting to a non-SCP
153
            port will result in a connection that can't easily be configured.
154
        :rtype: ~spinnman.connections.udp_packet_connections.SDPConnection
155
        """
156
        host = self.__host(chip_x, chip_y)
×
157
        if not host:
×
158
            return None
×
159
        return SCAMPConnection(
×
160
            chip_x=chip_x, chip_y=chip_y,
161
            remote_host=host, remote_port=udp_port)
162

163
    def open_eieio_connection(
1✔
164
            self, chip_x: int, chip_y: int) -> Optional[EIEIOConnection]:
165
        """
166
        Open an unbound EIEIO connection. This may be used to communicate with
167
        any board of the job.
168

169
        :rtype: ~spinnman.connections.udp_packet_connections.EIEIOConnection
170
        """
171
        host = self.__host(chip_x, chip_y)
×
172
        if not host:
×
173
            return None
×
174
        return EIEIOConnection(remote_host=host, remote_port=SCP_SCAMP_PORT)
×
175

176
    def open_eieio_listener(self) -> EIEIOConnection:
1✔
177
        """
178
        Open an unbound EIEIO connection. This may be used to communicate with
179
        any board of the job.
180

181
        :rtype: ~spinnman.connections.udp_packet_connections.EIEIOConnection
182
        """
183
        return EIEIOConnection()
×
184

185
    @property
1✔
186
    def proxying(self) -> bool:
1✔
187
        """
188
        Whether this is a proxying connection. False unless overridden.
189

190
        :rtype: bool
191
        """
192
        return False
1✔
193

194
    def make_report(self, filename: str):
1✔
195
        """
196
        Asks the controller to make a report of details of allocations.
197
        By default, this does nothing.
198
        """
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc