flwr-nightly 1.23.0.dev20251029__py3-none-any.whl → 1.23.0.dev20251031__py3-none-any.whl

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.

Potentially problematic release.


This version of flwr-nightly might be problematic. Click here for more details.

Files changed (26) hide show
  1. flwr/cli/new/new.py +187 -35
  2. flwr/client/grpc_adapter_client/connection.py +4 -6
  3. flwr/client/grpc_rere_client/connection.py +47 -24
  4. flwr/client/grpc_rere_client/grpc_adapter.py +0 -16
  5. flwr/client/rest_client/connection.py +70 -33
  6. flwr/common/constant.py +3 -1
  7. flwr/proto/fleet_pb2.py +31 -39
  8. flwr/proto/fleet_pb2.pyi +0 -48
  9. flwr/proto/fleet_pb2_grpc.py +0 -66
  10. flwr/proto/fleet_pb2_grpc.pyi +0 -20
  11. flwr/server/app.py +30 -16
  12. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -6
  13. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +92 -124
  14. flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +14 -5
  15. flwr/server/superlink/fleet/message_handler/message_handler.py +66 -23
  16. flwr/server/superlink/fleet/rest_rere/rest_api.py +20 -28
  17. flwr/server/superlink/fleet/vce/vce_api.py +3 -3
  18. flwr/server/superlink/linkstate/in_memory_linkstate.py +4 -3
  19. flwr/server/superlink/linkstate/sqlite_linkstate.py +4 -4
  20. flwr/supercore/constant.py +4 -0
  21. flwr/supernode/cli/flower_supernode.py +7 -0
  22. flwr/supernode/start_client_internal.py +3 -9
  23. {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/METADATA +1 -1
  24. {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/RECORD +26 -26
  25. {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/WHEEL +0 -0
  26. {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/entry_points.txt +0 -0
flwr/proto/fleet_pb2.py CHANGED
@@ -19,7 +19,7 @@ from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
19
19
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
20
20
 
21
21
 
22
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"C\n\x11\x43reateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\".\n\x18RegisterNodeFleetRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\"\x1b\n\x19RegisterNodeFleetResponse\"E\n\x13\x41\x63tivateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"\'\n\x14\x41\x63tivateNodeResponse\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"(\n\x15\x44\x65\x61\x63tivateNodeRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x18\n\x16\x44\x65\x61\x63tivateNodeResponse\"-\n\x1aUnregisterNodeFleetRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x1d\n\x1bUnregisterNodeFleetResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\xa2\x01\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\x97\x01\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\xc9\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12\x17\n\x0fobjects_to_push\x18\x03 \x03(\t\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xbe\t\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12]\n\x0cRegisterNode\x12$.flwr.proto.RegisterNodeFleetRequest\x1a%.flwr.proto.RegisterNodeFleetResponse\"\x00\x12S\n\x0c\x41\x63tivateNode\x12\x1f.flwr.proto.ActivateNodeRequest\x1a .flwr.proto.ActivateNodeResponse\"\x00\x12Y\n\x0e\x44\x65\x61\x63tivateNode\x12!.flwr.proto.DeactivateNodeRequest\x1a\".flwr.proto.DeactivateNodeResponse\"\x00\x12\x63\n\x0eUnregisterNode\x12&.flwr.proto.UnregisterNodeFleetRequest\x1a\'.flwr.proto.UnregisterNodeFleetResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x12q\n\x16\x43onfirmMessageReceived\x12).flwr.proto.ConfirmMessageReceivedRequest\x1a*.flwr.proto.ConfirmMessageReceivedResponse\"\x00\x62\x06proto3')
22
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\".\n\x18RegisterNodeFleetRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\"\x1b\n\x19RegisterNodeFleetResponse\"E\n\x13\x41\x63tivateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"\'\n\x14\x41\x63tivateNodeResponse\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"(\n\x15\x44\x65\x61\x63tivateNodeRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x18\n\x16\x44\x65\x61\x63tivateNodeResponse\"-\n\x1aUnregisterNodeFleetRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x1d\n\x1bUnregisterNodeFleetResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\xa2\x01\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\x97\x01\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\xc9\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12\x17\n\x0fobjects_to_push\x18\x03 \x03(\t\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xa0\x08\n\x05\x46leet\x12]\n\x0cRegisterNode\x12$.flwr.proto.RegisterNodeFleetRequest\x1a%.flwr.proto.RegisterNodeFleetResponse\"\x00\x12S\n\x0c\x41\x63tivateNode\x12\x1f.flwr.proto.ActivateNodeRequest\x1a .flwr.proto.ActivateNodeResponse\"\x00\x12Y\n\x0e\x44\x65\x61\x63tivateNode\x12!.flwr.proto.DeactivateNodeRequest\x1a\".flwr.proto.DeactivateNodeResponse\"\x00\x12\x63\n\x0eUnregisterNode\x12&.flwr.proto.UnregisterNodeFleetRequest\x1a\'.flwr.proto.UnregisterNodeFleetResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x12q\n\x16\x43onfirmMessageReceived\x12).flwr.proto.ConfirmMessageReceivedRequest\x1a*.flwr.proto.ConfirmMessageReceivedResponse\"\x00\x62\x06proto3')
23
23
 
24
24
  _globals = globals()
25
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -28,42 +28,34 @@ if _descriptor._USE_C_DESCRIPTORS == False:
28
28
  DESCRIPTOR._options = None
29
29
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._options = None
30
30
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
31
- _globals['_CREATENODEREQUEST']._serialized_start=159
32
- _globals['_CREATENODEREQUEST']._serialized_end=226
33
- _globals['_CREATENODERESPONSE']._serialized_start=228
34
- _globals['_CREATENODERESPONSE']._serialized_end=280
35
- _globals['_DELETENODEREQUEST']._serialized_start=282
36
- _globals['_DELETENODEREQUEST']._serialized_end=333
37
- _globals['_DELETENODERESPONSE']._serialized_start=335
38
- _globals['_DELETENODERESPONSE']._serialized_end=355
39
- _globals['_REGISTERNODEFLEETREQUEST']._serialized_start=357
40
- _globals['_REGISTERNODEFLEETREQUEST']._serialized_end=403
41
- _globals['_REGISTERNODEFLEETRESPONSE']._serialized_start=405
42
- _globals['_REGISTERNODEFLEETRESPONSE']._serialized_end=432
43
- _globals['_ACTIVATENODEREQUEST']._serialized_start=434
44
- _globals['_ACTIVATENODEREQUEST']._serialized_end=503
45
- _globals['_ACTIVATENODERESPONSE']._serialized_start=505
46
- _globals['_ACTIVATENODERESPONSE']._serialized_end=544
47
- _globals['_DEACTIVATENODEREQUEST']._serialized_start=546
48
- _globals['_DEACTIVATENODEREQUEST']._serialized_end=586
49
- _globals['_DEACTIVATENODERESPONSE']._serialized_start=588
50
- _globals['_DEACTIVATENODERESPONSE']._serialized_end=612
51
- _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_start=614
52
- _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_end=659
53
- _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_start=661
54
- _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_end=690
55
- _globals['_PULLMESSAGESREQUEST']._serialized_start=692
56
- _globals['_PULLMESSAGESREQUEST']._serialized_end=766
57
- _globals['_PULLMESSAGESRESPONSE']._serialized_start=769
58
- _globals['_PULLMESSAGESRESPONSE']._serialized_end=931
59
- _globals['_PUSHMESSAGESREQUEST']._serialized_start=934
60
- _globals['_PUSHMESSAGESREQUEST']._serialized_end=1085
61
- _globals['_PUSHMESSAGESRESPONSE']._serialized_start=1088
62
- _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1289
63
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1243
64
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1289
65
- _globals['_RECONNECT']._serialized_start=1291
66
- _globals['_RECONNECT']._serialized_end=1321
67
- _globals['_FLEET']._serialized_start=1324
68
- _globals['_FLEET']._serialized_end=2538
31
+ _globals['_REGISTERNODEFLEETREQUEST']._serialized_start=159
32
+ _globals['_REGISTERNODEFLEETREQUEST']._serialized_end=205
33
+ _globals['_REGISTERNODEFLEETRESPONSE']._serialized_start=207
34
+ _globals['_REGISTERNODEFLEETRESPONSE']._serialized_end=234
35
+ _globals['_ACTIVATENODEREQUEST']._serialized_start=236
36
+ _globals['_ACTIVATENODEREQUEST']._serialized_end=305
37
+ _globals['_ACTIVATENODERESPONSE']._serialized_start=307
38
+ _globals['_ACTIVATENODERESPONSE']._serialized_end=346
39
+ _globals['_DEACTIVATENODEREQUEST']._serialized_start=348
40
+ _globals['_DEACTIVATENODEREQUEST']._serialized_end=388
41
+ _globals['_DEACTIVATENODERESPONSE']._serialized_start=390
42
+ _globals['_DEACTIVATENODERESPONSE']._serialized_end=414
43
+ _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_start=416
44
+ _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_end=461
45
+ _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_start=463
46
+ _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_end=492
47
+ _globals['_PULLMESSAGESREQUEST']._serialized_start=494
48
+ _globals['_PULLMESSAGESREQUEST']._serialized_end=568
49
+ _globals['_PULLMESSAGESRESPONSE']._serialized_start=571
50
+ _globals['_PULLMESSAGESRESPONSE']._serialized_end=733
51
+ _globals['_PUSHMESSAGESREQUEST']._serialized_start=736
52
+ _globals['_PUSHMESSAGESREQUEST']._serialized_end=887
53
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_start=890
54
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1091
55
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1045
56
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1091
57
+ _globals['_RECONNECT']._serialized_start=1093
58
+ _globals['_RECONNECT']._serialized_end=1123
59
+ _globals['_FLEET']._serialized_start=1126
60
+ _globals['_FLEET']._serialized_end=2182
69
61
  # @@protoc_insertion_point(module_scope)
flwr/proto/fleet_pb2.pyi CHANGED
@@ -13,54 +13,6 @@ import typing_extensions
13
13
 
14
14
  DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
15
15
 
16
- class CreateNodeRequest(google.protobuf.message.Message):
17
- """CreateNode messages"""
18
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
19
- PUBLIC_KEY_FIELD_NUMBER: builtins.int
20
- HEARTBEAT_INTERVAL_FIELD_NUMBER: builtins.int
21
- public_key: builtins.bytes
22
- heartbeat_interval: builtins.float
23
- def __init__(self,
24
- *,
25
- public_key: builtins.bytes = ...,
26
- heartbeat_interval: builtins.float = ...,
27
- ) -> None: ...
28
- def ClearField(self, field_name: typing_extensions.Literal["heartbeat_interval",b"heartbeat_interval","public_key",b"public_key"]) -> None: ...
29
- global___CreateNodeRequest = CreateNodeRequest
30
-
31
- class CreateNodeResponse(google.protobuf.message.Message):
32
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
33
- NODE_FIELD_NUMBER: builtins.int
34
- @property
35
- def node(self) -> flwr.proto.node_pb2.Node: ...
36
- def __init__(self,
37
- *,
38
- node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
39
- ) -> None: ...
40
- def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
41
- def ClearField(self, field_name: typing_extensions.Literal["node",b"node"]) -> None: ...
42
- global___CreateNodeResponse = CreateNodeResponse
43
-
44
- class DeleteNodeRequest(google.protobuf.message.Message):
45
- """DeleteNode messages"""
46
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
47
- NODE_FIELD_NUMBER: builtins.int
48
- @property
49
- def node(self) -> flwr.proto.node_pb2.Node: ...
50
- def __init__(self,
51
- *,
52
- node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
53
- ) -> None: ...
54
- def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
55
- def ClearField(self, field_name: typing_extensions.Literal["node",b"node"]) -> None: ...
56
- global___DeleteNodeRequest = DeleteNodeRequest
57
-
58
- class DeleteNodeResponse(google.protobuf.message.Message):
59
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
60
- def __init__(self,
61
- ) -> None: ...
62
- global___DeleteNodeResponse = DeleteNodeResponse
63
-
64
16
  class RegisterNodeFleetRequest(google.protobuf.message.Message):
65
17
  """RegisterNode messages (add prefix to avoid name clash)"""
66
18
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
@@ -18,16 +18,6 @@ class FleetStub(object):
18
18
  Args:
19
19
  channel: A grpc.Channel.
20
20
  """
21
- self.CreateNode = channel.unary_unary(
22
- '/flwr.proto.Fleet/CreateNode',
23
- request_serializer=flwr_dot_proto_dot_fleet__pb2.CreateNodeRequest.SerializeToString,
24
- response_deserializer=flwr_dot_proto_dot_fleet__pb2.CreateNodeResponse.FromString,
25
- )
26
- self.DeleteNode = channel.unary_unary(
27
- '/flwr.proto.Fleet/DeleteNode',
28
- request_serializer=flwr_dot_proto_dot_fleet__pb2.DeleteNodeRequest.SerializeToString,
29
- response_deserializer=flwr_dot_proto_dot_fleet__pb2.DeleteNodeResponse.FromString,
30
- )
31
21
  self.RegisterNode = channel.unary_unary(
32
22
  '/flwr.proto.Fleet/RegisterNode',
33
23
  request_serializer=flwr_dot_proto_dot_fleet__pb2.RegisterNodeFleetRequest.SerializeToString,
@@ -93,18 +83,6 @@ class FleetStub(object):
93
83
  class FleetServicer(object):
94
84
  """Missing associated documentation comment in .proto file."""
95
85
 
96
- def CreateNode(self, request, context):
97
- """Missing associated documentation comment in .proto file."""
98
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
99
- context.set_details('Method not implemented!')
100
- raise NotImplementedError('Method not implemented!')
101
-
102
- def DeleteNode(self, request, context):
103
- """Missing associated documentation comment in .proto file."""
104
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
105
- context.set_details('Method not implemented!')
106
- raise NotImplementedError('Method not implemented!')
107
-
108
86
  def RegisterNode(self, request, context):
109
87
  """Register Node
110
88
  """
@@ -194,16 +172,6 @@ class FleetServicer(object):
194
172
 
195
173
  def add_FleetServicer_to_server(servicer, server):
196
174
  rpc_method_handlers = {
197
- 'CreateNode': grpc.unary_unary_rpc_method_handler(
198
- servicer.CreateNode,
199
- request_deserializer=flwr_dot_proto_dot_fleet__pb2.CreateNodeRequest.FromString,
200
- response_serializer=flwr_dot_proto_dot_fleet__pb2.CreateNodeResponse.SerializeToString,
201
- ),
202
- 'DeleteNode': grpc.unary_unary_rpc_method_handler(
203
- servicer.DeleteNode,
204
- request_deserializer=flwr_dot_proto_dot_fleet__pb2.DeleteNodeRequest.FromString,
205
- response_serializer=flwr_dot_proto_dot_fleet__pb2.DeleteNodeResponse.SerializeToString,
206
- ),
207
175
  'RegisterNode': grpc.unary_unary_rpc_method_handler(
208
176
  servicer.RegisterNode,
209
177
  request_deserializer=flwr_dot_proto_dot_fleet__pb2.RegisterNodeFleetRequest.FromString,
@@ -274,40 +242,6 @@ def add_FleetServicer_to_server(servicer, server):
274
242
  class Fleet(object):
275
243
  """Missing associated documentation comment in .proto file."""
276
244
 
277
- @staticmethod
278
- def CreateNode(request,
279
- target,
280
- options=(),
281
- channel_credentials=None,
282
- call_credentials=None,
283
- insecure=False,
284
- compression=None,
285
- wait_for_ready=None,
286
- timeout=None,
287
- metadata=None):
288
- return grpc.experimental.unary_unary(request, target, '/flwr.proto.Fleet/CreateNode',
289
- flwr_dot_proto_dot_fleet__pb2.CreateNodeRequest.SerializeToString,
290
- flwr_dot_proto_dot_fleet__pb2.CreateNodeResponse.FromString,
291
- options, channel_credentials,
292
- insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
293
-
294
- @staticmethod
295
- def DeleteNode(request,
296
- target,
297
- options=(),
298
- channel_credentials=None,
299
- call_credentials=None,
300
- insecure=False,
301
- compression=None,
302
- wait_for_ready=None,
303
- timeout=None,
304
- metadata=None):
305
- return grpc.experimental.unary_unary(request, target, '/flwr.proto.Fleet/DeleteNode',
306
- flwr_dot_proto_dot_fleet__pb2.DeleteNodeRequest.SerializeToString,
307
- flwr_dot_proto_dot_fleet__pb2.DeleteNodeResponse.FromString,
308
- options, channel_credentials,
309
- insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
310
-
311
245
  @staticmethod
312
246
  def RegisterNode(request,
313
247
  target,
@@ -12,14 +12,6 @@ import grpc
12
12
 
13
13
  class FleetStub:
14
14
  def __init__(self, channel: grpc.Channel) -> None: ...
15
- CreateNode: grpc.UnaryUnaryMultiCallable[
16
- flwr.proto.fleet_pb2.CreateNodeRequest,
17
- flwr.proto.fleet_pb2.CreateNodeResponse]
18
-
19
- DeleteNode: grpc.UnaryUnaryMultiCallable[
20
- flwr.proto.fleet_pb2.DeleteNodeRequest,
21
- flwr.proto.fleet_pb2.DeleteNodeResponse]
22
-
23
15
  RegisterNode: grpc.UnaryUnaryMultiCallable[
24
16
  flwr.proto.fleet_pb2.RegisterNodeFleetRequest,
25
17
  flwr.proto.fleet_pb2.RegisterNodeFleetResponse]
@@ -86,18 +78,6 @@ class FleetStub:
86
78
 
87
79
 
88
80
  class FleetServicer(metaclass=abc.ABCMeta):
89
- @abc.abstractmethod
90
- def CreateNode(self,
91
- request: flwr.proto.fleet_pb2.CreateNodeRequest,
92
- context: grpc.ServicerContext,
93
- ) -> flwr.proto.fleet_pb2.CreateNodeResponse: ...
94
-
95
- @abc.abstractmethod
96
- def DeleteNode(self,
97
- request: flwr.proto.fleet_pb2.DeleteNodeRequest,
98
- context: grpc.ServicerContext,
99
- ) -> flwr.proto.fleet_pb2.DeleteNodeResponse: ...
100
-
101
81
  @abc.abstractmethod
102
82
  def RegisterNode(self,
103
83
  request: flwr.proto.fleet_pb2.RegisterNodeFleetRequest,
flwr/server/app.py CHANGED
@@ -233,20 +233,36 @@ def run_superlink() -> None:
233
233
  log(WARN, "The `--artifact-provider-config` flag is highly experimental.")
234
234
  artifact_provider = get_ee_artifact_provider(cfg_path)
235
235
 
236
- # If supernode authentication is disabled, warn users
236
+ # Check for incompatible args with SuperNode authentication
237
237
  enable_supernode_auth: bool = args.enable_supernode_auth
238
- if enable_supernode_auth and args.insecure:
239
- url_v = f"https://flower.ai/docs/framework/v{package_version}/en/"
240
- page = "how-to-authenticate-supernodes.html"
241
- flwr_exit(
242
- ExitCode.SUPERLINK_INVALID_ARGS,
243
- "The `--enable-supernode-auth` flag requires encrypted TLS communications. "
244
- "Please provide TLS certificates using the `--ssl-certfile`, "
245
- "`--ssl-keyfile` and `--ssl-ca-certfile` arguments to your SuperLink. "
246
- "Please refer to the Flower documentation for more information: "
247
- f"{url_v}{page}",
248
- )
249
- if not enable_supernode_auth:
238
+ if enable_supernode_auth:
239
+ if args.insecure:
240
+ url_v = f"https://flower.ai/docs/framework/v{package_version}/en/"
241
+ page = "how-to-authenticate-supernodes.html"
242
+ flwr_exit(
243
+ ExitCode.SUPERLINK_INVALID_ARGS,
244
+ "The `--enable-supernode-auth` flag requires encrypted TLS "
245
+ "communications. Please provide TLS certificates using the "
246
+ "`--ssl-certfile`, `--ssl-keyfile` and `--ssl-ca-certfile` "
247
+ "arguments to your SuperLink. Please refer to the Flower "
248
+ f"documentation for more information: {url_v}{page}",
249
+ )
250
+ if args.fleet_api_type != TRANSPORT_TYPE_GRPC_RERE:
251
+ flwr_exit(
252
+ ExitCode.SUPERLINK_INVALID_ARGS,
253
+ "The `--enable-supernode-auth` flag is only supported "
254
+ "with the gRPC-rere Fleet API transport. Please set "
255
+ f"`--fleet-api-type` to `{TRANSPORT_TYPE_GRPC_RERE}`.",
256
+ )
257
+ if args.simulation:
258
+ log(
259
+ WARN,
260
+ "SuperNode authentication is not applicable with the simulation, "
261
+ "runtime as no SuperNodes can connect to this SuperLink. "
262
+ "Proceeding...",
263
+ )
264
+ # If supernode authentication is disabled, warn users
265
+ else:
250
266
  log(
251
267
  WARN,
252
268
  "SuperNode authentication is disabled. The SuperLink will accept "
@@ -384,7 +400,6 @@ def run_superlink() -> None:
384
400
  state_factory=state_factory,
385
401
  ffs_factory=ffs_factory,
386
402
  objectstore_factory=objectstore_factory,
387
- enable_supernode_auth=enable_supernode_auth,
388
403
  certificates=certificates,
389
404
  )
390
405
  grpc_servers.append(fleet_server)
@@ -570,7 +585,6 @@ def _run_fleet_api_grpc_adapter(
570
585
  state_factory: LinkStateFactory,
571
586
  ffs_factory: FfsFactory,
572
587
  objectstore_factory: ObjectStoreFactory,
573
- enable_supernode_auth: bool,
574
588
  certificates: Optional[tuple[bytes, bytes, bytes]],
575
589
  ) -> grpc.Server:
576
590
  """Run Fleet API (GrpcAdapter)."""
@@ -579,7 +593,7 @@ def _run_fleet_api_grpc_adapter(
579
593
  state_factory=state_factory,
580
594
  ffs_factory=ffs_factory,
581
595
  objectstore_factory=objectstore_factory,
582
- enable_supernode_auth=enable_supernode_auth,
596
+ enable_supernode_auth=False,
583
597
  )
584
598
  fleet_add_servicer_to_server_fn = add_GrpcAdapterServicer_to_server
585
599
  fleet_grpc_server = generic_create_grpc_server(
@@ -34,9 +34,7 @@ from flwr.proto import grpcadapter_pb2_grpc # pylint: disable=E0611
34
34
  from flwr.proto.fab_pb2 import GetFabRequest # pylint: disable=E0611
35
35
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
36
36
  ActivateNodeRequest,
37
- CreateNodeRequest,
38
37
  DeactivateNodeRequest,
39
- DeleteNodeRequest,
40
38
  PullMessagesRequest,
41
39
  PushMessagesRequest,
42
40
  RegisterNodeFleetRequest,
@@ -86,10 +84,6 @@ class GrpcAdapterServicer(grpcadapter_pb2_grpc.GrpcAdapterServicer, FleetService
86
84
  ) -> MessageContainer:
87
85
  """."""
88
86
  log(DEBUG, "GrpcAdapterServicer.SendReceive")
89
- if request.grpc_message_name == CreateNodeRequest.__qualname__:
90
- return _handle(request, context, CreateNodeRequest, self.CreateNode)
91
- if request.grpc_message_name == DeleteNodeRequest.__qualname__:
92
- return _handle(request, context, DeleteNodeRequest, self.DeleteNode)
93
87
  if request.grpc_message_name == RegisterNodeFleetRequest.__qualname__:
94
88
  return _handle(
95
89
  request, context, RegisterNodeFleetRequest, self.RegisterNode
@@ -21,7 +21,7 @@ from logging import DEBUG, ERROR, INFO
21
21
  import grpc
22
22
  from google.protobuf.json_format import MessageToDict
23
23
 
24
- from flwr.common.constant import SUPERNODE_NOT_CREATED_FROM_CLI_MESSAGE
24
+ from flwr.common.constant import PUBLIC_KEY_ALREADY_IN_USE_MESSAGE
25
25
  from flwr.common.inflatable import UnexpectedObjectContentError
26
26
  from flwr.common.logger import log
27
27
  from flwr.common.typing import InvalidRunStatusException
@@ -30,12 +30,8 @@ from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=
30
30
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
31
31
  ActivateNodeRequest,
32
32
  ActivateNodeResponse,
33
- CreateNodeRequest,
34
- CreateNodeResponse,
35
33
  DeactivateNodeRequest,
36
34
  DeactivateNodeResponse,
37
- DeleteNodeRequest,
38
- DeleteNodeResponse,
39
35
  PullMessagesRequest,
40
36
  PullMessagesResponse,
41
37
  PushMessagesRequest,
@@ -57,12 +53,10 @@ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
57
53
  PushObjectRequest,
58
54
  PushObjectResponse,
59
55
  )
60
- from flwr.proto.node_pb2 import Node # pylint: disable=E0611
61
56
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
62
57
  from flwr.server.superlink.fleet.message_handler import message_handler
63
58
  from flwr.server.superlink.linkstate import LinkStateFactory
64
59
  from flwr.server.superlink.utils import abort_grpc_context
65
- from flwr.supercore.constant import NodeStatus
66
60
  from flwr.supercore.ffs import FfsFactory
67
61
  from flwr.supercore.object_store import ObjectStoreFactory
68
62
 
@@ -83,147 +77,121 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
83
77
  self.enable_supernode_auth = enable_supernode_auth
84
78
  self.lock = threading.Lock()
85
79
 
86
- def CreateNode(
87
- self, request: CreateNodeRequest, context: grpc.ServicerContext
88
- ) -> CreateNodeResponse:
89
- """."""
90
- log(
91
- INFO,
92
- "[Fleet.CreateNode] Request heartbeat_interval=%s",
93
- request.heartbeat_interval,
94
- )
95
- log(DEBUG, "[Fleet.CreateNode] Request: %s", MessageToDict(request))
96
- try:
97
-
98
- state = self.state_factory.state()
99
-
100
- # Check if public key is already in use
101
- if node_id := state.get_node_id_by_public_key(request.public_key):
102
-
103
- # Ensure only one request that requires checking the node state
104
- # is processed at a time. This avoids race conditions when two
105
- # SuperNodes try to connect at the same time with the same
106
- # public key.
107
- with self.lock:
108
- node_info = state.get_node_info(node_ids=[node_id])[0]
109
- if node_info.status == NodeStatus.ONLINE:
110
- # Node is already active
111
- log(
112
- ERROR,
113
- "Public key already in use (node_id=%s)",
114
- node_id,
115
- )
116
- raise ValueError(
117
- "Public key already in use by an active SuperNode"
118
- )
119
-
120
- # Prepare response with existing node_id
121
- response = CreateNodeResponse(node=Node(node_id=node_id))
122
- # Awknowledge heartbeat to mark node as online
123
- state.acknowledge_node_heartbeat(
124
- node_id=node_id,
125
- heartbeat_interval=request.heartbeat_interval,
126
- )
127
- else:
128
- if self.enable_supernode_auth:
129
- # When SuperNode authentication is enabled,
130
- # only SuperNodes created from the CLI are allowed to
131
- # stablish a connection with the Fleet API
132
- log(ERROR, SUPERNODE_NOT_CREATED_FROM_CLI_MESSAGE)
133
- raise ValueError(SUPERNODE_NOT_CREATED_FROM_CLI_MESSAGE)
134
-
135
- # When SuperNode authentication is disabled, auto-auth
136
- # allows creating a new node
137
- response = message_handler.create_node(
138
- request=request,
139
- state=state,
140
- )
141
- log(
142
- INFO, "[Fleet.CreateNode] Created node_id=%s", response.node.node_id
143
- )
144
-
145
- except ValueError as e:
146
- # Public key already in use
147
- context.abort(grpc.StatusCode.FAILED_PRECONDITION, str(e))
148
- log(DEBUG, "[Fleet.CreateNode] Response: %s", MessageToDict(response))
149
- return response
150
-
151
80
  def RegisterNode(
152
81
  self, request: RegisterNodeFleetRequest, context: grpc.ServicerContext
153
82
  ) -> RegisterNodeFleetResponse:
154
- """Register a node (not implemented)."""
155
- log(ERROR, "[Fleet.RegisterNode] RegisterNode is not implemented")
156
- context.abort(
157
- grpc.StatusCode.UNIMPLEMENTED,
158
- "RegisterNode RPC is not yet implemented",
159
- )
160
- raise NotImplementedError
83
+ """Register a node."""
84
+ # Prevent registration when SuperNode authentication is enabled
85
+ if self.enable_supernode_auth:
86
+ log(ERROR, "SuperNode registration is disabled through Fleet API.")
87
+ context.abort(
88
+ grpc.StatusCode.FAILED_PRECONDITION,
89
+ "SuperNode authentication is enabled. "
90
+ "All SuperNodes must be registered via the CLI.",
91
+ )
92
+
93
+ try:
94
+ return message_handler.register_node(
95
+ request=request,
96
+ state=self.state_factory.state(),
97
+ )
98
+ except ValueError:
99
+ # Public key already in use
100
+ log(ERROR, PUBLIC_KEY_ALREADY_IN_USE_MESSAGE)
101
+ context.abort(
102
+ grpc.StatusCode.FAILED_PRECONDITION, PUBLIC_KEY_ALREADY_IN_USE_MESSAGE
103
+ )
104
+
105
+ raise RuntimeError # Make mypy happy
161
106
 
162
107
  def ActivateNode(
163
108
  self, request: ActivateNodeRequest, context: grpc.ServicerContext
164
109
  ) -> ActivateNodeResponse:
165
- """Activate a node (not implemented)."""
166
- log(ERROR, "[Fleet.ActivateNode] ActivateNode is not implemented")
167
- context.abort(
168
- grpc.StatusCode.UNIMPLEMENTED,
169
- "ActivateNode RPC is not yet implemented",
170
- )
171
- raise NotImplementedError
110
+ """Activate a node."""
111
+ try:
112
+ response = message_handler.activate_node(
113
+ request=request,
114
+ state=self.state_factory.state(),
115
+ )
116
+ log(INFO, "[Fleet.ActivateNode] Activated node_id=%s", response.node_id)
117
+ return response
118
+ except message_handler.InvalidHeartbeatIntervalError:
119
+ # Heartbeat interval is invalid
120
+ log(ERROR, "[Fleet.ActivateNode] Invalid heartbeat interval")
121
+ context.abort(
122
+ grpc.StatusCode.INVALID_ARGUMENT, "Invalid heartbeat interval"
123
+ )
124
+ except ValueError as e:
125
+ log(ERROR, "[Fleet.ActivateNode] Activation failed: %s", str(e))
126
+ context.abort(grpc.StatusCode.FAILED_PRECONDITION, str(e))
127
+
128
+ raise RuntimeError # Make mypy happy
172
129
 
173
130
  def DeactivateNode(
174
131
  self, request: DeactivateNodeRequest, context: grpc.ServicerContext
175
132
  ) -> DeactivateNodeResponse:
176
- """Deactivate a node (not implemented)."""
177
- log(ERROR, "[Fleet.DeactivateNode] DeactivateNode is not implemented")
178
- context.abort(
179
- grpc.StatusCode.UNIMPLEMENTED,
180
- "DeactivateNode RPC is not yet implemented",
181
- )
182
- raise NotImplementedError
133
+ """Deactivate a node."""
134
+ try:
135
+ response = message_handler.deactivate_node(
136
+ request=request,
137
+ state=self.state_factory.state(),
138
+ )
139
+ log(INFO, "[Fleet.DeactivateNode] Deactivated node_id=%s", request.node_id)
140
+ return response
141
+ except ValueError as e:
142
+ log(ERROR, "[Fleet.DeactivateNode] Deactivation failed: %s", str(e))
143
+ context.abort(grpc.StatusCode.FAILED_PRECONDITION, str(e))
144
+
145
+ raise RuntimeError # Make mypy happy
183
146
 
184
147
  def UnregisterNode(
185
148
  self, request: UnregisterNodeFleetRequest, context: grpc.ServicerContext
186
149
  ) -> UnregisterNodeFleetResponse:
187
- """Unregister a node (not implemented)."""
188
- log(ERROR, "[Fleet.UnregisterNode] UnregisterNode is not implemented")
189
- context.abort(
190
- grpc.StatusCode.UNIMPLEMENTED,
191
- "UnregisterNode RPC is not yet implemented",
192
- )
193
- raise NotImplementedError
194
-
195
- def DeleteNode(
196
- self, request: DeleteNodeRequest, context: grpc.ServicerContext
197
- ) -> DeleteNodeResponse:
198
- """."""
199
- log(INFO, "[Fleet.DeleteNode] Delete node_id=%s", request.node.node_id)
200
- log(DEBUG, "[Fleet.DeleteNode] Request: %s", MessageToDict(request))
201
- # This shall be refactored when renaming `Fleet.Create/DeleteNode`
202
- # to `Fleet.Activate/DeactivateNode`
150
+ """Unregister a node."""
151
+ # Prevent unregistration when SuperNode authentication is enabled
203
152
  if self.enable_supernode_auth:
204
- # SuperNodes can only be deleted from the CLI
205
- # We simply acknowledge the heartbeat with interval 0
206
- # to mark the node as offline
207
- state = self.state_factory.state()
208
- state.acknowledge_node_heartbeat(
209
- node_id=request.node.node_id, heartbeat_interval=0
153
+ log(ERROR, "SuperNode unregistration is disabled through Fleet API.")
154
+ context.abort(
155
+ grpc.StatusCode.FAILED_PRECONDITION,
156
+ "SuperNode authentication is enabled. "
157
+ "All SuperNodes must be unregistered via the CLI.",
210
158
  )
211
- return DeleteNodeResponse()
212
159
 
213
- return message_handler.delete_node(
214
- request=request,
215
- state=self.state_factory.state(),
216
- )
160
+ try:
161
+ response = message_handler.unregister_node(
162
+ request=request,
163
+ state=self.state_factory.state(),
164
+ )
165
+ log(
166
+ DEBUG, "[Fleet.UnregisterNode] Unregistered node_id=%s", request.node_id
167
+ )
168
+ return response
169
+ except ValueError as e:
170
+ log(
171
+ ERROR,
172
+ "[Fleet.UnregisterNode] Unregistration failed: %s",
173
+ str(e),
174
+ )
175
+ context.abort(grpc.StatusCode.FAILED_PRECONDITION, str(e))
176
+ raise RuntimeError from None # Make mypy happy
217
177
 
218
178
  def SendNodeHeartbeat(
219
179
  self, request: SendNodeHeartbeatRequest, context: grpc.ServicerContext
220
180
  ) -> SendNodeHeartbeatResponse:
221
181
  """."""
222
182
  log(DEBUG, "[Fleet.SendNodeHeartbeat] Request: %s", MessageToDict(request))
223
- return message_handler.send_node_heartbeat(
224
- request=request,
225
- state=self.state_factory.state(),
226
- )
183
+ try:
184
+ return message_handler.send_node_heartbeat(
185
+ request=request,
186
+ state=self.state_factory.state(),
187
+ )
188
+ except message_handler.InvalidHeartbeatIntervalError:
189
+ # Heartbeat interval is invalid
190
+ log(ERROR, "[Fleet.SendNodeHeartbeat] Invalid heartbeat interval")
191
+ context.abort(
192
+ grpc.StatusCode.INVALID_ARGUMENT, "Invalid heartbeat interval"
193
+ )
194
+ raise RuntimeError # Make mypy happy
227
195
 
228
196
  def PullMessages(
229
197
  self, request: PullMessagesRequest, context: grpc.ServicerContext