remoteRF-server 1.7.0__tar.gz → 1.7.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/PKG-INFO +1 -1
  2. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/pyproject.toml +1 -1
  3. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/device_manager.py +20 -0
  4. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/cluster.py +24 -3
  5. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/global_onboarding.py +3 -2
  6. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/rpc_manager.py +11 -2
  7. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/PKG-INFO +1 -1
  8. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/SOURCES.txt +1 -0
  9. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_global_home.py +29 -0
  10. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_remote_admin.py +8 -3
  11. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_reservation_handoff.py +25 -0
  12. remoterf_server-1.7.4/tests/test_rpc_manager_host_legacy.py +49 -0
  13. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_rpc_manager_rx_n.py +1 -1
  14. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/LICENSE +0 -0
  15. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/README.md +0 -0
  16. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/setup.cfg +0 -0
  17. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/__init__.py +0 -0
  18. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/__init__.py +0 -0
  19. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/__init__.py +0 -0
  20. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/deployment_capabilities.proto +0 -0
  21. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/deployment_capabilities_pb2.py +0 -0
  22. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/deployment_capabilities_pb2_grpc.py +0 -0
  23. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/federation.proto +0 -0
  24. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/federation_pb2.py +0 -0
  25. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/federation_pb2_grpc.py +0 -0
  26. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/grpc_host_pb2.py +0 -0
  27. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/grpc_host_pb2_grpc.py +0 -0
  28. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/grpc_pb2.py +0 -0
  29. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/grpc_pb2_grpc.py +0 -0
  30. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/grpc/v2_codec.py +0 -0
  31. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/__init__.py +0 -0
  32. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/device_schema.py +0 -0
  33. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/pluto_mimo_schema.py +0 -0
  34. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/pluto_schema.py +0 -0
  35. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/schema.py +0 -0
  36. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/idl/v2.py +0 -0
  37. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/__init__.py +0 -0
  38. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/ansi_codes.py +0 -0
  39. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/api_token.py +0 -0
  40. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/db_connection.py +0 -0
  41. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/db_location.py +0 -0
  42. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/list_string.py +0 -0
  43. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/panel.py +0 -0
  44. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/common/utils/process_arg.py +0 -0
  45. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/__init__.py +0 -0
  46. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/__init__.py +0 -0
  47. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/pluto_diag.py +0 -0
  48. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/pluto_mimo_schema.py +0 -0
  49. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/pluto_remote_server.py +0 -0
  50. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/pluto_schema.py +0 -0
  51. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/adalm_pluto/poe.py +0 -0
  52. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/bluetooth_diag.py +0 -0
  53. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/gps_diag.py +0 -0
  54. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/hackrf/__init__.py +0 -0
  55. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/hackrf/hackrf_schema.py +0 -0
  56. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/rtl_sdr/__init__.py +0 -0
  57. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/rtl_sdr/rtl_sdr_diag.py +0 -0
  58. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/rtl_sdr/rtl_sdr_schema.py +0 -0
  59. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/ti_mmwave/__init__.py +0 -0
  60. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/ti_mmwave/ti_mmwave_schema.py +0 -0
  61. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/__init__.py +0 -0
  62. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/policy.py +0 -0
  63. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/profiles.py +0 -0
  64. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/uhd_manifest.py +0 -0
  65. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/usrp_diag.py +0 -0
  66. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp/usrp_schema.py +0 -0
  67. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp_phaser/__init__.py +0 -0
  68. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/drivers/usrp_phaser/usrp_phaser_schema.py +0 -0
  69. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/host/__init__.py +0 -0
  70. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/host/host_auth_token.py +0 -0
  71. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/host/host_directory_store.py +0 -0
  72. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/host/host_tunnel_server.py +0 -0
  73. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/remote_admin_shell.py +0 -0
  74. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/__init__.py +0 -0
  75. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/acc_perms.py +0 -0
  76. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/cert_provider.py +0 -0
  77. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/commands.py +0 -0
  78. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/console.py +0 -0
  79. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/control.py +0 -0
  80. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/deployment/__init__.py +0 -0
  81. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/deployment/capabilities.py +0 -0
  82. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/diag.py +0 -0
  83. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/direct_path.py +0 -0
  84. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/dynamic_v2.py +0 -0
  85. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/dynamic_v2_bridge.py +0 -0
  86. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/__init__.py +0 -0
  87. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/admin.py +0 -0
  88. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/cli.py +0 -0
  89. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/contracts.py +0 -0
  90. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/destination.py +0 -0
  91. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/devices.py +0 -0
  92. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/enrollment.py +0 -0
  93. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/global_home.py +0 -0
  94. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/home.py +0 -0
  95. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/home_devices.py +0 -0
  96. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/identity.py +0 -0
  97. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/legacy_state.py +0 -0
  98. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/links.py +0 -0
  99. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/migrations.py +0 -0
  100. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/peers.py +0 -0
  101. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/permissions.py +0 -0
  102. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/principals.py +0 -0
  103. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/runtime.py +0 -0
  104. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/federation/trust.py +0 -0
  105. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/grpc_server.py +0 -0
  106. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/host_direct.py +0 -0
  107. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/host_dynamic_v2.py +0 -0
  108. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/remote_admin.py +0 -0
  109. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/remote_admin_ssh.py +0 -0
  110. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/reservation.py +0 -0
  111. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/schema_registry.py +0 -0
  112. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/startup_check.py +0 -0
  113. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/user_group_cli.py +0 -0
  114. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/user_group_handler.py +0 -0
  115. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/server/v2_errors.py +0 -0
  116. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/serverrf_cli.py +0 -0
  117. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/tools/__init__.py +0 -0
  118. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/tools/gen_certs.py +0 -0
  119. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/tools/gist_status.py +0 -0
  120. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/tools/gist_status_testing.py +0 -0
  121. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server/tools/introspect_uhd.py +0 -0
  122. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/dependency_links.txt +0 -0
  123. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/entry_points.txt +0 -0
  124. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/requires.txt +0 -0
  125. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/src/remoteRF_server.egg-info/top_level.txt +0 -0
  126. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_account_hardening.py +0 -0
  127. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_account_names.py +0 -0
  128. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_account_removal.py +0 -0
  129. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_activity_log.py +0 -0
  130. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_availability.py +0 -0
  131. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_bind_host.py +0 -0
  132. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_cert_provider.py +0 -0
  133. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_client_sessions.py +0 -0
  134. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_cluster.py +0 -0
  135. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_commands.py +0 -0
  136. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_console.py +0 -0
  137. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_contrib_drivers.py +0 -0
  138. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_default_rtl_sdr_schema.py +0 -0
  139. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_default_usrp_schema.py +0 -0
  140. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_deployment_capabilities.py +0 -0
  141. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_detached_device_rpc.py +0 -0
  142. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_device_core_aliases.py +0 -0
  143. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_device_handles.py +0 -0
  144. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_device_init.py +0 -0
  145. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_devices_add_wizard.py +0 -0
  146. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_devices_list.py +0 -0
  147. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_diag.py +0 -0
  148. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_direct_fixed_port.py +0 -0
  149. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_direct_path_server.py +0 -0
  150. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_dynamic_v2.py +0 -0
  151. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_federated_direct_path.py +0 -0
  152. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_federated_dynamic_v2.py +0 -0
  153. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_federation_edges.py +0 -0
  154. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_first_run.py +0 -0
  155. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_d_contracts.py +0 -0
  156. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_e_federation.py +0 -0
  157. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_e_proto.py +0 -0
  158. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_f_enrollment.py +0 -0
  159. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_g1_logging.py +0 -0
  160. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_g_permissions.py +0 -0
  161. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_h_devices.py +0 -0
  162. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gate_i_direct_path.py +0 -0
  163. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_gen_certs.py +0 -0
  164. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_global_accounts_migration.py +0 -0
  165. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_global_onboarding.py +0 -0
  166. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_global_v1_disposal.py +0 -0
  167. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_hackrf_schema.py +0 -0
  168. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_home_device_plane.py +0 -0
  169. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_host_direct.py +0 -0
  170. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_host_directory_store.py +0 -0
  171. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_host_dynamic_v2.py +0 -0
  172. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_idl_schema.py +0 -0
  173. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_lab_logins.py +0 -0
  174. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_panel.py +0 -0
  175. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_peer_transport.py +0 -0
  176. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_pluto_compat.py +0 -0
  177. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_pluto_poe.py +0 -0
  178. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_process_arg.py +0 -0
  179. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_proxy_lifecycle.py +0 -0
  180. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_reservation_policy_b.py +0 -0
  181. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_reservation_timestamps.py +0 -0
  182. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_rpc_manager_batch.py +0 -0
  183. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_rpc_manager_calln.py +0 -0
  184. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_rtl_sdr_schema.py +0 -0
  185. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_schema_registry.py +0 -0
  186. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_soak_federation.py +0 -0
  187. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_startup_check.py +0 -0
  188. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_status_push.py +0 -0
  189. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_ti_mmwave_hardware.py +0 -0
  190. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_ti_mmwave_schema.py +0 -0
  191. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_user_group_cli.py +0 -0
  192. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_b205mini_uhd410_hardware.py +0 -0
  193. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_client_server_hardware.py +0 -0
  194. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_client_server_localhost.py +0 -0
  195. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_n210_client_server_hardware.py +0 -0
  196. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_preload.py +0 -0
  197. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_profiles.py +0 -0
  198. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_remoterf_rx_hardware.py +0 -0
  199. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_usrp_uhd410_hardware.py +0 -0
  200. {remoterf_server-1.7.0 → remoterf_server-1.7.4}/tests/test_wipe.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remoteRF-server
3
- Version: 1.7.0
3
+ Version: 1.7.4
4
4
  Summary: RemoteRF server-side control package
5
5
  License: GPL-3.0-or-later
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "remoteRF-server"
7
- version = "1.7.0"
7
+ version = "1.7.4"
8
8
  description = "RemoteRF server-side control package"
9
9
  license = { text = "GPL-3.0-or-later" }
10
10
  requires-python = ">=3.10"
@@ -18,6 +18,7 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import importlib
21
+ import logging
21
22
  import os
22
23
  import re
23
24
  import secrets
@@ -37,6 +38,8 @@ from ..common.utils import validate_token, get_remoterf_root, get_drivers_dir, d
37
38
  from ..common.idl.schema import get_driver_class, load_drivers
38
39
  from ..host import host_tunnel_server as hts
39
40
 
41
+ logger = logging.getLogger(__name__)
42
+
40
43
  _state_lock = threading.RLock()
41
44
  _reservation_end_callbacks: list = []
42
45
  # token -> (gid, salt, hsh): see reservation_bridge_token()
@@ -807,6 +810,7 @@ def set_device(device_id: int, salt: str, hash: str):
807
810
  return
808
811
 
809
812
  notify_end = False
813
+ host_start = None
810
814
  with _state_lock:
811
815
  st = _devices.get(int(device_id))
812
816
  if not st:
@@ -819,6 +823,8 @@ def set_device(device_id: int, salt: str, hash: str):
819
823
  all(held) and previous != held and st.origin == "local"
820
824
  and callable(getattr(st.dev, "prepare_for_holder", None))
821
825
  )
826
+ if all(held) and previous != held and st.origin == "host" and isinstance(st.dev, VirtualDevice):
827
+ host_start = st.dev
822
828
  # The holder changed: the reservation ended, or a back-to-back one
823
829
  # replaced it without the device ever being free.
824
830
  notify_end = any(previous) and previous != (st.salt, st.hsh)
@@ -836,10 +842,24 @@ def set_device(device_id: int, salt: str, hash: str):
836
842
  # Now, not at the next call: a transmitter left running must stop
837
843
  # even when nobody reserves the device next.
838
844
  threading.Thread(target=_reset_if_pending, args=(int(device_id),), daemon=True).start()
845
+ if host_start is not None:
846
+ _start_host_reservation(host_start)
839
847
  if prepare:
840
848
  threading.Thread(target=_prepare_for_holder, args=(int(device_id), held), daemon=True).start()
841
849
 
842
850
 
851
+ def _start_host_reservation(device: VirtualDevice) -> None:
852
+ try:
853
+ registry = hts.get_tunnel_registry(create=False)
854
+ if registry is None or not registry.send_control(
855
+ device.host_id, kind="reservation_start", device_id=device.device_id,
856
+ payload={"at": time.time()},
857
+ ):
858
+ logger.warning("host reservation start unavailable for %s", device.host_id)
859
+ except Exception as exc:
860
+ logger.warning("host reservation start unavailable for %s: %s", device.host_id, exc)
861
+
862
+
843
863
  def _prepare_for_holder(device_id: int, held: Tuple[str, str]) -> None:
844
864
  """A reservation started: ready the device (a PoE Pluto boots) before the
845
865
  holder's first call, which waits on io_lock for this same boot meanwhile."""
@@ -1080,7 +1080,16 @@ def _sync_contract(party: dict, peer: str, directory: list[dict]) -> str:
1080
1080
  for item in directory:
1081
1081
  if item["contract_id"] == party["contract_id"] and item.get("terms"):
1082
1082
  _import(store, item["terms"], item["events"])
1083
- return store.show(party["contract_id"], 1)["state"]
1083
+ try:
1084
+ return store.show(party["contract_id"], 1)["state"]
1085
+ except ContractError as exc:
1086
+ if exc.code != "unknown_contract":
1087
+ raise
1088
+ # Neither this store nor Global has it: the lab's database was reset while its
1089
+ # federation state survived. Forget it; a member adopts afresh, a proposer proposes again.
1090
+ party.pop("contract_id")
1091
+ party.update(state="created", published=[])
1092
+ return _sync_contract(party, peer, directory)
1084
1093
 
1085
1094
 
1086
1095
  def _event_order(signed_event: str) -> tuple:
@@ -1112,6 +1121,9 @@ def _advance(party: dict, peer: str, directory: list[dict], *, label: str, notif
1112
1121
  if before in ("pending", "revoked"):
1113
1122
  return
1114
1123
  state = _sync_contract(party, peer, directory)
1124
+ if not party.get("contract_id") and not is_member and (other := _identity_of(peer)) is not None:
1125
+ _contract_with(party, other) # the stale contract was dropped: propose a new one
1126
+ state = "proposed"
1115
1127
  store = _contracts()
1116
1128
  if state == "proposed" and is_member:
1117
1129
  store.accept(party["contract_id"], 1, actor_admin_ref="cluster")
@@ -1291,13 +1303,22 @@ def _walk_in(pools: list[dict], notify) -> None:
1291
1303
  active. Any other open door (an older lab's own) is ignored."""
1292
1304
  from . import global_home
1293
1305
 
1294
- if GLOBAL in load():
1295
- return
1296
1306
  state = global_home.load()
1297
1307
  home = (state.get("identity") or {}).get("deployment_id")
1298
1308
  party = state.get("party") or {}
1309
+ clusters = load()
1310
+ if GLOBAL in clusters and (clusters[GLOBAL].get("peer") == home or not home):
1311
+ return
1299
1312
  if not home or party.get("state") != "active":
1300
1313
  return
1314
+ if GLOBAL in clusters:
1315
+ # Joined under an earlier Global home (this lab's state outlived a Global
1316
+ # reset): drop it and rejoin the current one, keeping what it shared.
1317
+ stale = clusters.pop(GLOBAL)
1318
+ queued = state.setdefault("public_groups", [])
1319
+ queued += [group_id for group_id in stale.get("groups", []) if group_id not in queued]
1320
+ save(clusters)
1321
+ global_home.save(state)
1301
1322
  for pool in pools:
1302
1323
  owner = (pool.get("owner") or {}).get("identity") or {}
1303
1324
  if pool.get("cluster_name") != GLOBAL or owner.get("deployment_id") != home:
@@ -65,8 +65,9 @@ time reserved so far (a single number), and your LAN address. Nothing else leave
65
65
  server -- no credentials, no user or reservation details -- and the
66
66
  connection only goes outward.
67
67
 
68
- A RemoteRF admin reviews each new deployment by hand, so there is a short wait
69
- before your address goes live. You can join or leave whenever you like:
68
+ A RemoteRF admin will review your new deployment before its address goes live.
69
+ If you opt out, you cannot opt back in without a full data reset. You may leave
70
+ at any time:
70
71
 
71
72
  serverrf global join
72
73
  serverrf global leave"""
@@ -252,14 +252,23 @@ class RpcManager:
252
252
  fwd_args = dict(args)
253
253
  fwd_args.pop('a', None)
254
254
  fwd_args['g'] = map_arg(int(gid))
255
- return hts.handle_host_device(
255
+ results = hts.handle_host_device(
256
256
  hts.get_tunnel_registry(create=False),
257
257
  host_id=dev.host_id,
258
258
  device_id=dev.device_id,
259
259
  function_name=function_name,
260
260
  args=fwd_args,
261
- timeout_sec=10.0,
261
+ timeout_sec=25.0,
262
262
  )
263
+ failed = "Error" in results
264
+ if "Ok" in results:
265
+ failed = failed or not bool(unmap_arg(results["Ok"]))
266
+ if failed:
267
+ error = str(unmap_arg(results["Error"]) or "") if "Error" in results else ""
268
+ return {"a": map_arg(
269
+ error or "The device did not answer in time; it may still be powering on. Try again."
270
+ )}
271
+ return results
263
272
 
264
273
  return self._dispatch_local_schema(function_name=function_name, args=args, gid=gid, dev=dev)
265
274
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remoteRF-server
3
- Version: 1.7.0
3
+ Version: 1.7.4
4
4
  Summary: RemoteRF server-side control package
5
5
  License: GPL-3.0-or-later
6
6
  Classifier: Programming Language :: Python :: 3
@@ -177,6 +177,7 @@ tests/test_reservation_policy_b.py
177
177
  tests/test_reservation_timestamps.py
178
178
  tests/test_rpc_manager_batch.py
179
179
  tests/test_rpc_manager_calln.py
180
+ tests/test_rpc_manager_host_legacy.py
180
181
  tests/test_rpc_manager_rx_n.py
181
182
  tests/test_rtl_sdr_schema.py
182
183
  tests/test_schema_registry.py
@@ -67,6 +67,35 @@ class GlobalHomeContractTests(unittest.TestCase):
67
67
  self.assertEqual(global_home.contract_id(), party["contract_id"])
68
68
  self.assertIn("[cluster] RemoteRF Global is active", self.notes)
69
69
 
70
+ def test_a_contract_neither_the_lab_nor_global_has_is_dropped_and_proposed_again(self):
71
+ with self.server(H):
72
+ home_identity = cluster._identity()
73
+ with self.server(A), mock.patch.object(global_home, "fetch_identity", return_value=home_identity):
74
+ # The lab's database was reset; its federation state still names the old contract.
75
+ global_home.save({"party": {"state": "proposed", "display_name": global_home.LABEL,
76
+ "contract_id": "8a2e3f10-0000-4000-8000-0000000000ff", "published": []}})
77
+ global_home.tick(self.notes.append)
78
+ party = global_home.load()["party"]
79
+ self.assertEqual(party["state"], "proposed")
80
+ self.assertNotEqual(party["contract_id"], "8a2e3f10-0000-4000-8000-0000000000ff")
81
+ self.assertEqual([c["contract_id"] for c in self.broker.call("GET", "/v2/broker/contracts")["contracts"]],
82
+ [party["contract_id"]])
83
+
84
+ def test_a_global_cluster_joined_under_an_earlier_home_is_rejoined_with_its_groups(self):
85
+ with self.server(H):
86
+ home_identity = cluster._identity()
87
+ cluster._public_note(cluster.GLOBAL, "open")
88
+ self._standing(B, home_identity)
89
+ with self.server(B):
90
+ # State from before a Global reset: the cluster names a home that is gone.
91
+ cluster.save({cluster.GLOBAL: {"role": "member", "state": "active", "public": True, "peer": C,
92
+ "contract_id": "8a2e3f10-0000-4000-8000-0000000000ff",
93
+ "published": [], "groups": [7]}})
94
+ cluster.tick(self.notes.append)
95
+ item = cluster.load()[cluster.GLOBAL]
96
+ self.assertEqual((item["peer"], item["contract_id"], item["groups"]), (H, global_home.contract_id(), [7]))
97
+ self.assertNotIn("public_groups", global_home.load())
98
+
70
99
  def _standing(self, lab, home_identity):
71
100
  """The lab proposes its standing contract; the home accepts; the lab sees it active."""
72
101
  with self.server(lab), mock.patch.object(global_home, "fetch_identity", return_value=home_identity):
@@ -536,9 +536,14 @@ def test_a_real_openssh_session_through_the_tunnel(lab, tmp_path):
536
536
  out = _expect(ssh_argv("jdoe"), [("Password for remote admin jdoe:", "a long password!"),
537
537
  ("jdoe@lab>", "exit")])
538
538
  assert "jdoe@lab>" in out, out
539
- time.sleep(1.5)
540
- with contextlib.closing(ra.connect()) as conn:
541
- seen = [r[0] for r in conn.execute("SELECT event FROM remote_admin_audit ORDER BY id")]
539
+ # session_end is written after the server closes the channel, so ssh can exit first.
540
+ deadline = time.monotonic() + 20
541
+ while True:
542
+ with contextlib.closing(ra.connect()) as conn:
543
+ seen = [r[0] for r in conn.execute("SELECT event FROM remote_admin_audit ORDER BY id")]
544
+ if seen.count("session_end") >= 2 or time.monotonic() > deadline:
545
+ break
546
+ time.sleep(0.1)
542
547
  assert seen.count("session_start") == 2 and seen.count("session_end") == 2, seen
543
548
  assert "device_approved" in seen and "refused" in seen
544
549
  finally:
@@ -122,6 +122,31 @@ class HandoffTests(unittest.TestCase):
122
122
  self.assertEqual(self._wait_log(2), ["reset"])
123
123
 
124
124
 
125
+ class HostReservationStartTests(unittest.TestCase):
126
+ def test_start_is_sent_once_for_a_new_holder_only(self):
127
+ sent = []
128
+
129
+ class Registry:
130
+ def send_control(self, host_id, *, kind, device_id, payload):
131
+ sent.append((host_id, kind, device_id, payload))
132
+ return True
133
+
134
+ device_manager._devices[GID] = device_manager._DeviceState(
135
+ dev=device_manager.VirtualDevice(GID, "host-1", "d1"), origin="host", online=True,
136
+ salt="", hsh="", name="dev", ident="X", dtype="adalm_pluto",
137
+ )
138
+ self.addCleanup(device_manager._devices.pop, GID, None)
139
+ with patch.object(device_manager, "_sync_host_devices"), patch.object(
140
+ device_manager, "_reservation_end_callbacks", []
141
+ ), patch.object(device_manager.hts, "get_tunnel_registry", return_value=Registry()):
142
+ device_manager.set_device(GID, "s1", "h1")
143
+ device_manager.set_device(GID, "s1", "h1")
144
+ device_manager.set_device(GID, "", "")
145
+
146
+ self.assertEqual(len(sent), 1)
147
+ self.assertEqual(sent[0][:3], ("host-1", "reservation_start", "d1"))
148
+ self.assertEqual(set(sent[0][3]), {"at"})
149
+
125
150
 
126
151
  if __name__ == "__main__":
127
152
  unittest.main()
@@ -0,0 +1,49 @@
1
+ import sys
2
+ import types
3
+ import unittest
4
+ from unittest.mock import patch
5
+
6
+ sys.modules.setdefault("adi", types.ModuleType("adi"))
7
+
8
+ from remoteRF_server.common.utils.process_arg import map_arg, unmap_arg
9
+ from remoteRF_server.server import rpc_manager as rpc_module
10
+ from remoteRF_server.server.device_manager import VirtualDevice
11
+ from remoteRF_server.server.rpc_manager import RpcManager
12
+
13
+
14
+ class HostLegacyTests(unittest.TestCase):
15
+ def test_failure_becomes_client_error_and_uses_25_second_timeout(self):
16
+ calls = []
17
+
18
+ def forward(registry, **kwargs):
19
+ calls.append(kwargs)
20
+ return {"Ok": map_arg(False)}
21
+
22
+ device = VirtualDevice(gid=5, host_id="host-1", device_id="d1", kind="fake")
23
+ with patch.object(rpc_module.hts, "handle_host_device", forward), patch.object(
24
+ rpc_module.hts, "get_tunnel_registry", return_value=None
25
+ ):
26
+ result = RpcManager()._dispatch_acquired(
27
+ function_name="Fake:gain:SET", args={"gain": map_arg(1)}, gid=5, dev=device
28
+ )
29
+
30
+ self.assertEqual(calls[0]["timeout_sec"], 25.0)
31
+ self.assertEqual(
32
+ unmap_arg(result["a"]),
33
+ "The device did not answer in time; it may still be powering on. Try again.",
34
+ )
35
+
36
+ def test_host_error_text_becomes_client_error(self):
37
+ device = VirtualDevice(gid=5, host_id="host-1", device_id="d1", kind="fake")
38
+ with patch.object(
39
+ rpc_module.hts, "handle_host_device",
40
+ return_value={"Error": map_arg("host failed")},
41
+ ), patch.object(rpc_module.hts, "get_tunnel_registry", return_value=None):
42
+ result = RpcManager()._dispatch_acquired(
43
+ function_name="Fake:gain:GET", args={}, gid=5, dev=device
44
+ )
45
+ self.assertEqual(unmap_arg(result["a"]), "host failed")
46
+
47
+
48
+ if __name__ == "__main__":
49
+ unittest.main()
@@ -86,7 +86,7 @@ class RxNTests(unittest.TestCase):
86
86
  sent.append(None)
87
87
  sent.append(None) # the next host rx answers with an Error first
88
88
  first_error = rx_n(dev, 4, gid=5)
89
- self.assertEqual(unmap_arg(first_error["Error"]), "host overflow")
89
+ self.assertEqual(unmap_arg(first_error["a"]), "host overflow")
90
90
 
91
91
 
92
92
  if __name__ == "__main__":
File without changes