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.
- flwr/cli/new/new.py +187 -35
- flwr/client/grpc_adapter_client/connection.py +4 -6
- flwr/client/grpc_rere_client/connection.py +47 -24
- flwr/client/grpc_rere_client/grpc_adapter.py +0 -16
- flwr/client/rest_client/connection.py +70 -33
- flwr/common/constant.py +3 -1
- flwr/proto/fleet_pb2.py +31 -39
- flwr/proto/fleet_pb2.pyi +0 -48
- flwr/proto/fleet_pb2_grpc.py +0 -66
- flwr/proto/fleet_pb2_grpc.pyi +0 -20
- flwr/server/app.py +30 -16
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -6
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +92 -124
- flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +14 -5
- flwr/server/superlink/fleet/message_handler/message_handler.py +66 -23
- flwr/server/superlink/fleet/rest_rere/rest_api.py +20 -28
- flwr/server/superlink/fleet/vce/vce_api.py +3 -3
- flwr/server/superlink/linkstate/in_memory_linkstate.py +4 -3
- flwr/server/superlink/linkstate/sqlite_linkstate.py +4 -4
- flwr/supercore/constant.py +4 -0
- flwr/supernode/cli/flower_supernode.py +7 -0
- flwr/supernode/start_client_internal.py +3 -9
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/METADATA +1 -1
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/RECORD +26 -26
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/WHEEL +0 -0
- {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\"
|
|
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['
|
|
32
|
-
_globals['
|
|
33
|
-
_globals['
|
|
34
|
-
_globals['
|
|
35
|
-
_globals['
|
|
36
|
-
_globals['
|
|
37
|
-
_globals['
|
|
38
|
-
_globals['
|
|
39
|
-
_globals['
|
|
40
|
-
_globals['
|
|
41
|
-
_globals['
|
|
42
|
-
_globals['
|
|
43
|
-
_globals['
|
|
44
|
-
_globals['
|
|
45
|
-
_globals['
|
|
46
|
-
_globals['
|
|
47
|
-
_globals['
|
|
48
|
-
_globals['
|
|
49
|
-
_globals['
|
|
50
|
-
_globals['
|
|
51
|
-
_globals['
|
|
52
|
-
_globals['
|
|
53
|
-
_globals['
|
|
54
|
-
_globals['
|
|
55
|
-
_globals['
|
|
56
|
-
_globals['
|
|
57
|
-
_globals['
|
|
58
|
-
_globals['
|
|
59
|
-
_globals['
|
|
60
|
-
_globals['
|
|
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
|
flwr/proto/fleet_pb2_grpc.py
CHANGED
|
@@ -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,
|
flwr/proto/fleet_pb2_grpc.pyi
CHANGED
|
@@ -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
|
-
#
|
|
236
|
+
# Check for incompatible args with SuperNode authentication
|
|
237
237
|
enable_supernode_auth: bool = args.enable_supernode_auth
|
|
238
|
-
if enable_supernode_auth
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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=
|
|
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
|
|
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
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
|
188
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|