aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmpm/python/usrp_hwd.py5
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py8
-rw-r--r--mpm/python/usrp_mpm/periph_manager/n310.py16
-rw-r--r--mpm/python/usrp_mpm/rpc_server.py91
4 files changed, 105 insertions, 15 deletions
diff --git a/mpm/python/usrp_hwd.py b/mpm/python/usrp_hwd.py
index fef02087a..d6e860a0c 100755
--- a/mpm/python/usrp_hwd.py
+++ b/mpm/python/usrp_hwd.py
@@ -137,7 +137,8 @@ def main():
# with cmake (-DMPM_DEVICE).
# mgr is thus derived from PeriphManagerBase (see periph_manager/base.py)
log.info("Spawning periph manager...")
- mgr = periph_manager(args)
+ mgr_generator = lambda: periph_manager(args)
+ mgr = mgr_generator()
discovery_info = {
"type": mgr.get_device_info().get("type", "n/a"),
"serial": mgr.get_device_info().get("serial", "n/a"),
@@ -162,7 +163,7 @@ def main():
)
log.info("Spawning RPC process...")
_PROCESSES.append(
- mpm.spawn_rpc_process(mpm.mpmtypes.MPM_RPC_PORT, shared, mgr))
+ mpm.spawn_rpc_process(mpm.mpmtypes.MPM_RPC_PORT, shared, mgr, mgr_generator))
log.info("Processes launched. Registering signal handlers.")
signal.signal(signal.SIGTERM, kill_time)
signal.signal(signal.SIGINT, kill_time)
diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py
index 87544e451..2be8c7570 100644
--- a/mpm/python/usrp_mpm/periph_manager/base.py
+++ b/mpm/python/usrp_mpm/periph_manager/base.py
@@ -352,6 +352,13 @@ class PeriphManagerBase(object):
self.log.trace("Resetting SID pool...")
self._available_endpoints = list(range(256))
+ def tear_down(self):
+ """
+ Tear down all members that need to be specially handled before
+ deconstruction.
+ """
+ self.log.debug("Teardown called for Peripheral Manager base.")
+
@no_claim
def list_updateable_components(self):
"""
@@ -456,7 +463,6 @@ class PeriphManagerBase(object):
update_func(filepath, metadata)
return True
-
def load_fpga_image(self, target=None):
"""
load a new fpga image
diff --git a/mpm/python/usrp_mpm/periph_manager/n310.py b/mpm/python/usrp_mpm/periph_manager/n310.py
index 7adbc85f0..79c866aa4 100644
--- a/mpm/python/usrp_mpm/periph_manager/n310.py
+++ b/mpm/python/usrp_mpm/periph_manager/n310.py
@@ -31,6 +31,7 @@ from ..net import get_mac_addr
from ..mpmtypes import SID
from usrp_mpm.rpc_server import no_rpc
from usrp_mpm import net
+from usrp_mpm import dtoverlay
from ..sysfs_gpio import SysFSGPIO
from ..ethtable import EthDispatcherTable
from ..liberiotable import LiberioDispatcherTable
@@ -476,10 +477,12 @@ class n310(PeriphManagerBase):
'fpga': {
'callback': "update_fpga",
'path': '/lib/firmware/n3xx.bin',
+ 'reset': True,
},
'dts': {
'callback': "update_dts",
'path': '/lib/firmware/n3xx.dts',
+ 'reset': False,
},
}
@@ -586,6 +589,19 @@ class n310(PeriphManagerBase):
for xport_mgr in itervalues(self._xport_mgrs):
xport_mgr.deinit()
+ def tear_down(self):
+ """
+ Tear down all members that need to be specially handled before
+ deconstruction.
+ For N310, this means the overlay.
+ """
+ active_overlays = self.list_active_overlays()
+ self.log.trace("N310 has active device tree overlays: {}".format(
+ active_overlays
+ ))
+ for overlay in active_overlays:
+ dtoverlay.rm_overlay(overlay)
+
###########################################################################
# Transport API
###########################################################################
diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py
index 2cd44dfe5..38c9107ee 100644
--- a/mpm/python/usrp_mpm/rpc_server.py
+++ b/mpm/python/usrp_mpm/rpc_server.py
@@ -54,22 +54,20 @@ class MPMServer(RPCServer):
RPC calls to appropiate calls in the periph_manager and dboard_managers.
"""
# This is a list of methods in this class which require a claim
- default_claimed_methods = ['init', 'reclaim', 'unclaim']
+ default_claimed_methods = ['init', 'update_component', 'reclaim', 'unclaim']
- def __init__(self, state, mgr, *args, **kwargs):
+ def __init__(self, state, mgr, mgr_generator=None, *args, **kwargs):
self.log = get_main_logger().getChild('RPCServer')
self._state = state
self._timer = Greenlet()
self.session_id = None
self.periph_manager = mgr
+ self._mgr_generator = mgr_generator
self._db_methods = []
self._mb_methods = []
self.claimed_methods = copy.copy(self.default_claimed_methods)
self._last_error = ""
- self._update_component_commands(mgr, '', '_mb_methods')
- for db_slot, dboard in enumerate(mgr.dboards):
- cmd_prefix = 'db_' + str(db_slot) + '_'
- self._update_component_commands(dboard, cmd_prefix, '_db_methods')
+ self._init_rpc_calls(mgr)
# We call the server __init__ function here, and not earlier, because
# first the commands need to be registered
super(MPMServer, self).__init__(
@@ -78,6 +76,15 @@ class MPMServer(RPCServer):
**kwargs
)
+ def _init_rpc_calls(self, mgr):
+ """
+ Register all RPC calls for the motherboard and daughterboards
+ """
+ self._update_component_commands(mgr, '', '_mb_methods')
+ for db_slot, dboard in enumerate(mgr.dboards):
+ cmd_prefix = 'db_' + str(db_slot) + '_'
+ self._update_component_commands(dboard, cmd_prefix, '_db_methods')
+
def _check_token_valid(self, token):
"""
Returns True iff:
@@ -93,7 +100,6 @@ class MPMServer(RPCServer):
len(token) == TOKEN_LEN and \
self._state.claim_token.value == token
-
def _update_component_commands(self, component, namespace, storage):
"""
Detect available methods for an object and add them to the RPC server.
@@ -137,6 +143,7 @@ class MPMServer(RPCServer):
raise RuntimeError("Invalid token!")
try:
return function(*args)
+
except Exception as ex:
self.log.error(
"Uncaught exception in method %s: %s",
@@ -251,6 +258,66 @@ class MPMServer(RPCServer):
self._reset_timer()
return result
+ def reset_mgr(self):
+ """
+ Reset the Peripheral Manager for this RPC server.
+ """
+ # reassign
+ self.periph_manager.tear_down()
+ self.periph_manager = None
+ if self._mgr_generator is None:
+ raise RuntimeError("Can't reset peripheral manager- no generator function.")
+ self.periph_manager = self._mgr_generator()
+ self._init_rpc_calls(self.periph_manager)
+
+ def update_component(self, token, file_metadata_l, data_l):
+ """"
+ Updates the device component files specified by the metadata and data
+ :param file_metadata_l: List of dictionary of strings containing metadata
+ :param data_l: List of binary string with the file contents to be written
+ """
+ self._timer.kill() # Stop the timer, update_component can take some time.
+ # Check the claimed status
+ if not self._check_token_valid(token):
+ self._last_error =\
+ "Attempt to update component without valid claim from {}".format(
+ self.client_host
+ )
+ self.log.error(self._last_error)
+ raise RuntimeError("Attempt to update component without valid claim.")
+ result = self.periph_manager.update_component(file_metadata_l, data_l)
+ if not result:
+ component_ids = [metadata['id'] for metadata in file_metadata_l]
+ raise RuntimeError("Failed to update components: {}".format(component_ids))
+
+ # Check if we need to reset the peripheral manager
+ reset_now = False
+ for metadata, data in zip(file_metadata_l, data_l):
+ # Make sure the component is in the updateable_components
+ component_id = metadata['id']
+ if component_id in self.periph_manager.updateable_components:
+ # Check if that updating that component means the PM should be reset
+ if self.periph_manager.updateable_components[component_id]['reset']:
+ reset_now = True
+ else:
+ self.log.debug("ID {} not in updateable components ({})".format(
+ component_id, self.periph_manager.updateable_components))
+
+ try:
+ self.log.trace("Reset after updating component? {}".format(reset_now))
+ if reset_now:
+ self.reset_mgr()
+ self.log.debug("Reset the periph manager")
+ except Exception as ex:
+ self.log.error(
+ "Error in update_component while resetting: {}".format(
+ ex
+ ))
+ self._last_error = str(ex)
+
+ self.log.debug("End of update_component")
+ self._reset_timer()
+
def reclaim(self, token):
"""
reclaim a MPM device with a token. This operation will fail
@@ -286,8 +353,8 @@ class MPMServer(RPCServer):
self._state.claim_status.value = False
self._state.claim_token.value = b''
self.session_id = None
- self.periph_manager.claimed = False
try:
+ self.periph_manager.claimed = False
self.periph_manager.set_connection_type(None)
self.periph_manager.deinit()
except Exception as ex:
@@ -334,14 +401,14 @@ class MPMServer(RPCServer):
-def _rpc_server_process(shared_state, port, mgr):
+def _rpc_server_process(shared_state, port, mgr, mgr_generator):
"""
This is the actual process that's running the RPC server.
"""
connections = Pool(1000)
server = StreamServer(
('0.0.0.0', port),
- handle=MPMServer(shared_state, mgr),
+ handle=MPMServer(shared_state, mgr, mgr_generator),
spawn=connections)
# catch signals and stop the stream server
signal(signal.SIGTERM, lambda *args: server.stop())
@@ -349,12 +416,12 @@ def _rpc_server_process(shared_state, port, mgr):
server.serve_forever()
-def spawn_rpc_process(state, udp_port, mgr):
+def spawn_rpc_process(state, udp_port, mgr, mgr_generator):
"""
Returns a process that contains the RPC server
"""
- proc_args = [udp_port, state, mgr]
+ proc_args = [udp_port, state, mgr, mgr_generator]
proc = Process(target=_rpc_server_process, args=proc_args)
proc.start()
return proc