flwr-nightly 1.13.0.dev20241111__py3-none-any.whl → 1.13.0.dev20241117__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/app.py +2 -0
- flwr/cli/build.py +37 -0
- flwr/cli/install.py +5 -3
- flwr/cli/ls.py +228 -0
- flwr/client/app.py +58 -13
- flwr/client/clientapp/app.py +34 -23
- flwr/client/grpc_rere_client/connection.py +2 -12
- flwr/client/rest_client/connection.py +4 -14
- flwr/client/supernode/app.py +57 -53
- flwr/common/args.py +72 -7
- flwr/common/constant.py +21 -6
- flwr/common/date.py +18 -0
- flwr/common/serde.py +10 -0
- flwr/common/typing.py +31 -10
- flwr/proto/exec_pb2.py +22 -13
- flwr/proto/exec_pb2.pyi +44 -0
- flwr/proto/exec_pb2_grpc.py +34 -0
- flwr/proto/exec_pb2_grpc.pyi +13 -0
- flwr/proto/run_pb2.py +30 -30
- flwr/proto/run_pb2.pyi +18 -1
- flwr/server/app.py +39 -68
- flwr/server/driver/grpc_driver.py +4 -14
- flwr/server/run_serverapp.py +8 -238
- flwr/server/serverapp/app.py +34 -23
- flwr/server/superlink/fleet/rest_rere/rest_api.py +10 -9
- flwr/server/superlink/linkstate/in_memory_linkstate.py +71 -46
- flwr/server/superlink/linkstate/linkstate.py +19 -5
- flwr/server/superlink/linkstate/sqlite_linkstate.py +81 -113
- flwr/server/superlink/linkstate/utils.py +193 -3
- flwr/simulation/app.py +6 -41
- flwr/simulation/legacy_app.py +21 -1
- flwr/simulation/run_simulation.py +7 -18
- flwr/simulation/simulationio_connection.py +2 -2
- flwr/superexec/deployment.py +12 -6
- flwr/superexec/exec_servicer.py +31 -2
- flwr/superexec/simulation.py +11 -46
- {flwr_nightly-1.13.0.dev20241111.dist-info → flwr_nightly-1.13.0.dev20241117.dist-info}/METADATA +6 -4
- {flwr_nightly-1.13.0.dev20241111.dist-info → flwr_nightly-1.13.0.dev20241117.dist-info}/RECORD +41 -40
- {flwr_nightly-1.13.0.dev20241111.dist-info → flwr_nightly-1.13.0.dev20241117.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.13.0.dev20241111.dist-info → flwr_nightly-1.13.0.dev20241117.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.13.0.dev20241111.dist-info → flwr_nightly-1.13.0.dev20241117.dist-info}/entry_points.txt +0 -0
flwr/proto/run_pb2.py
CHANGED
|
@@ -18,7 +18,7 @@ from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
|
|
|
18
18
|
from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/run.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\
|
|
21
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/run.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xce\x02\n\x03Run\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x0e\n\x06\x66\x61\x62_id\x18\x02 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x03 \x01(\t\x12<\n\x0foverride_config\x18\x04 \x03(\x0b\x32#.flwr.proto.Run.OverrideConfigEntry\x12\x10\n\x08\x66\x61\x62_hash\x18\x05 \x01(\t\x12\x12\n\npending_at\x18\x06 \x01(\t\x12\x13\n\x0bstarting_at\x18\x07 \x01(\t\x12\x12\n\nrunning_at\x18\x08 \x01(\t\x12\x13\n\x0b\x66inished_at\x18\t \x01(\t\x12%\n\x06status\x18\n \x01(\x0b\x32\x15.flwr.proto.RunStatus\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"@\n\tRunStatus\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x12\n\nsub_status\x18\x02 \x01(\t\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\t\"\xeb\x01\n\x10\x43reateRunRequest\x12\x0e\n\x06\x66\x61\x62_id\x18\x01 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x02 \x01(\t\x12I\n\x0foverride_config\x18\x03 \x03(\x0b\x32\x30.flwr.proto.CreateRunRequest.OverrideConfigEntry\x12\x1c\n\x03\x66\x61\x62\x18\x04 \x01(\x0b\x32\x0f.flwr.proto.Fab\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"#\n\x11\x43reateRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"?\n\rGetRunRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\".\n\x0eGetRunResponse\x12\x1c\n\x03run\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Run\"S\n\x16UpdateRunStatusRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12)\n\nrun_status\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus\"\x19\n\x17UpdateRunStatusResponse\"F\n\x13GetRunStatusRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0f\n\x07run_ids\x18\x02 \x03(\x04\"\xb1\x01\n\x14GetRunStatusResponse\x12L\n\x0frun_status_dict\x18\x01 \x03(\x0b\x32\x33.flwr.proto.GetRunStatusResponse.RunStatusDictEntry\x1aK\n\x12RunStatusDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus:\x02\x38\x01\"-\n\x1bGetFederationOptionsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"U\n\x1cGetFederationOptionsResponse\x12\x35\n\x12\x66\x65\x64\x65ration_options\x18\x01 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecordb\x06proto3')
|
|
22
22
|
|
|
23
23
|
_globals = globals()
|
|
24
24
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -32,33 +32,33 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
32
32
|
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._options = None
|
|
33
33
|
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_options = b'8\001'
|
|
34
34
|
_globals['_RUN']._serialized_start=138
|
|
35
|
-
_globals['_RUN']._serialized_end=
|
|
36
|
-
_globals['_RUN_OVERRIDECONFIGENTRY']._serialized_start=
|
|
37
|
-
_globals['_RUN_OVERRIDECONFIGENTRY']._serialized_end=
|
|
38
|
-
_globals['_RUNSTATUS']._serialized_start=
|
|
39
|
-
_globals['_RUNSTATUS']._serialized_end=
|
|
40
|
-
_globals['_CREATERUNREQUEST']._serialized_start=
|
|
41
|
-
_globals['_CREATERUNREQUEST']._serialized_end=
|
|
42
|
-
_globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=
|
|
43
|
-
_globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=
|
|
44
|
-
_globals['_CREATERUNRESPONSE']._serialized_start=
|
|
45
|
-
_globals['_CREATERUNRESPONSE']._serialized_end=
|
|
46
|
-
_globals['_GETRUNREQUEST']._serialized_start=
|
|
47
|
-
_globals['_GETRUNREQUEST']._serialized_end=
|
|
48
|
-
_globals['_GETRUNRESPONSE']._serialized_start=
|
|
49
|
-
_globals['_GETRUNRESPONSE']._serialized_end=
|
|
50
|
-
_globals['_UPDATERUNSTATUSREQUEST']._serialized_start=
|
|
51
|
-
_globals['_UPDATERUNSTATUSREQUEST']._serialized_end=
|
|
52
|
-
_globals['_UPDATERUNSTATUSRESPONSE']._serialized_start=
|
|
53
|
-
_globals['_UPDATERUNSTATUSRESPONSE']._serialized_end=
|
|
54
|
-
_globals['_GETRUNSTATUSREQUEST']._serialized_start=
|
|
55
|
-
_globals['_GETRUNSTATUSREQUEST']._serialized_end=
|
|
56
|
-
_globals['_GETRUNSTATUSRESPONSE']._serialized_start=
|
|
57
|
-
_globals['_GETRUNSTATUSRESPONSE']._serialized_end=
|
|
58
|
-
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_start=
|
|
59
|
-
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_end=
|
|
60
|
-
_globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_start=
|
|
61
|
-
_globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_end=
|
|
62
|
-
_globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_start=
|
|
63
|
-
_globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_end=
|
|
35
|
+
_globals['_RUN']._serialized_end=472
|
|
36
|
+
_globals['_RUN_OVERRIDECONFIGENTRY']._serialized_start=399
|
|
37
|
+
_globals['_RUN_OVERRIDECONFIGENTRY']._serialized_end=472
|
|
38
|
+
_globals['_RUNSTATUS']._serialized_start=474
|
|
39
|
+
_globals['_RUNSTATUS']._serialized_end=538
|
|
40
|
+
_globals['_CREATERUNREQUEST']._serialized_start=541
|
|
41
|
+
_globals['_CREATERUNREQUEST']._serialized_end=776
|
|
42
|
+
_globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=399
|
|
43
|
+
_globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=472
|
|
44
|
+
_globals['_CREATERUNRESPONSE']._serialized_start=778
|
|
45
|
+
_globals['_CREATERUNRESPONSE']._serialized_end=813
|
|
46
|
+
_globals['_GETRUNREQUEST']._serialized_start=815
|
|
47
|
+
_globals['_GETRUNREQUEST']._serialized_end=878
|
|
48
|
+
_globals['_GETRUNRESPONSE']._serialized_start=880
|
|
49
|
+
_globals['_GETRUNRESPONSE']._serialized_end=926
|
|
50
|
+
_globals['_UPDATERUNSTATUSREQUEST']._serialized_start=928
|
|
51
|
+
_globals['_UPDATERUNSTATUSREQUEST']._serialized_end=1011
|
|
52
|
+
_globals['_UPDATERUNSTATUSRESPONSE']._serialized_start=1013
|
|
53
|
+
_globals['_UPDATERUNSTATUSRESPONSE']._serialized_end=1038
|
|
54
|
+
_globals['_GETRUNSTATUSREQUEST']._serialized_start=1040
|
|
55
|
+
_globals['_GETRUNSTATUSREQUEST']._serialized_end=1110
|
|
56
|
+
_globals['_GETRUNSTATUSRESPONSE']._serialized_start=1113
|
|
57
|
+
_globals['_GETRUNSTATUSRESPONSE']._serialized_end=1290
|
|
58
|
+
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_start=1215
|
|
59
|
+
_globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_end=1290
|
|
60
|
+
_globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_start=1292
|
|
61
|
+
_globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_end=1337
|
|
62
|
+
_globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_start=1339
|
|
63
|
+
_globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_end=1424
|
|
64
64
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/run_pb2.pyi
CHANGED
|
@@ -37,12 +37,23 @@ class Run(google.protobuf.message.Message):
|
|
|
37
37
|
FAB_VERSION_FIELD_NUMBER: builtins.int
|
|
38
38
|
OVERRIDE_CONFIG_FIELD_NUMBER: builtins.int
|
|
39
39
|
FAB_HASH_FIELD_NUMBER: builtins.int
|
|
40
|
+
PENDING_AT_FIELD_NUMBER: builtins.int
|
|
41
|
+
STARTING_AT_FIELD_NUMBER: builtins.int
|
|
42
|
+
RUNNING_AT_FIELD_NUMBER: builtins.int
|
|
43
|
+
FINISHED_AT_FIELD_NUMBER: builtins.int
|
|
44
|
+
STATUS_FIELD_NUMBER: builtins.int
|
|
40
45
|
run_id: builtins.int
|
|
41
46
|
fab_id: typing.Text
|
|
42
47
|
fab_version: typing.Text
|
|
43
48
|
@property
|
|
44
49
|
def override_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
|
|
45
50
|
fab_hash: typing.Text
|
|
51
|
+
pending_at: typing.Text
|
|
52
|
+
starting_at: typing.Text
|
|
53
|
+
running_at: typing.Text
|
|
54
|
+
finished_at: typing.Text
|
|
55
|
+
@property
|
|
56
|
+
def status(self) -> global___RunStatus: ...
|
|
46
57
|
def __init__(self,
|
|
47
58
|
*,
|
|
48
59
|
run_id: builtins.int = ...,
|
|
@@ -50,8 +61,14 @@ class Run(google.protobuf.message.Message):
|
|
|
50
61
|
fab_version: typing.Text = ...,
|
|
51
62
|
override_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
|
|
52
63
|
fab_hash: typing.Text = ...,
|
|
64
|
+
pending_at: typing.Text = ...,
|
|
65
|
+
starting_at: typing.Text = ...,
|
|
66
|
+
running_at: typing.Text = ...,
|
|
67
|
+
finished_at: typing.Text = ...,
|
|
68
|
+
status: typing.Optional[global___RunStatus] = ...,
|
|
53
69
|
) -> None: ...
|
|
54
|
-
def
|
|
70
|
+
def HasField(self, field_name: typing_extensions.Literal["status",b"status"]) -> builtins.bool: ...
|
|
71
|
+
def ClearField(self, field_name: typing_extensions.Literal["fab_hash",b"fab_hash","fab_id",b"fab_id","fab_version",b"fab_version","finished_at",b"finished_at","override_config",b"override_config","pending_at",b"pending_at","run_id",b"run_id","running_at",b"running_at","starting_at",b"starting_at","status",b"status"]) -> None: ...
|
|
55
72
|
global___Run = Run
|
|
56
73
|
|
|
57
74
|
class RunStatus(google.protobuf.message.Message):
|
flwr/server/app.py
CHANGED
|
@@ -22,7 +22,6 @@ import sys
|
|
|
22
22
|
import threading
|
|
23
23
|
from collections.abc import Sequence
|
|
24
24
|
from logging import DEBUG, INFO, WARN
|
|
25
|
-
from os.path import isfile
|
|
26
25
|
from pathlib import Path
|
|
27
26
|
from time import sleep
|
|
28
27
|
from typing import Optional
|
|
@@ -37,23 +36,26 @@ from cryptography.hazmat.primitives.serialization import (
|
|
|
37
36
|
|
|
38
37
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
|
|
39
38
|
from flwr.common.address import parse_address
|
|
39
|
+
from flwr.common.args import try_obtain_server_certificates
|
|
40
40
|
from flwr.common.config import get_flwr_dir, parse_config_args
|
|
41
41
|
from flwr.common.constant import (
|
|
42
|
-
|
|
42
|
+
CLIENT_OCTET,
|
|
43
|
+
EXEC_API_DEFAULT_SERVER_ADDRESS,
|
|
43
44
|
FLEET_API_GRPC_BIDI_DEFAULT_ADDRESS,
|
|
44
45
|
FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
|
|
45
46
|
FLEET_API_REST_DEFAULT_ADDRESS,
|
|
46
47
|
ISOLATION_MODE_PROCESS,
|
|
47
48
|
ISOLATION_MODE_SUBPROCESS,
|
|
48
49
|
MISSING_EXTRA_REST,
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
SERVER_OCTET,
|
|
51
|
+
SERVERAPPIO_API_DEFAULT_SERVER_ADDRESS,
|
|
52
|
+
SIMULATIONIO_API_DEFAULT_SERVER_ADDRESS,
|
|
51
53
|
TRANSPORT_TYPE_GRPC_ADAPTER,
|
|
52
54
|
TRANSPORT_TYPE_GRPC_RERE,
|
|
53
55
|
TRANSPORT_TYPE_REST,
|
|
54
56
|
)
|
|
55
57
|
from flwr.common.exit_handlers import register_exit_handlers
|
|
56
|
-
from flwr.common.logger import log
|
|
58
|
+
from flwr.common.logger import log, warn_deprecated_feature
|
|
57
59
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
58
60
|
private_key_to_bytes,
|
|
59
61
|
public_key_to_bytes,
|
|
@@ -99,6 +101,11 @@ def start_server( # pylint: disable=too-many-arguments,too-many-locals
|
|
|
99
101
|
) -> History:
|
|
100
102
|
"""Start a Flower server using the gRPC transport layer.
|
|
101
103
|
|
|
104
|
+
Warning
|
|
105
|
+
-------
|
|
106
|
+
This function is deprecated since 1.13.0. Use the :code:`flower-superlink` command
|
|
107
|
+
instead to start a SuperLink.
|
|
108
|
+
|
|
102
109
|
Parameters
|
|
103
110
|
----------
|
|
104
111
|
server_address : Optional[str]
|
|
@@ -156,6 +163,17 @@ def start_server( # pylint: disable=too-many-arguments,too-many-locals
|
|
|
156
163
|
>>> )
|
|
157
164
|
>>> )
|
|
158
165
|
"""
|
|
166
|
+
msg = (
|
|
167
|
+
"flwr.server.start_server() is deprecated."
|
|
168
|
+
"\n\tInstead, use the `flower-superlink` CLI command to start a SuperLink "
|
|
169
|
+
"as shown below:"
|
|
170
|
+
"\n\n\t\t$ flower-superlink --insecure"
|
|
171
|
+
"\n\n\tTo view usage and all available options, run:"
|
|
172
|
+
"\n\n\t\t$ flower-superlink --help"
|
|
173
|
+
"\n\n\tUsing `start_server()` is deprecated."
|
|
174
|
+
)
|
|
175
|
+
warn_deprecated_feature(name=msg)
|
|
176
|
+
|
|
159
177
|
event(EventType.START_SERVER_ENTER)
|
|
160
178
|
|
|
161
179
|
# Parse IP address
|
|
@@ -227,7 +245,7 @@ def run_superlink() -> None:
|
|
|
227
245
|
simulationio_address, _, _ = _format_address(args.simulationio_api_address)
|
|
228
246
|
|
|
229
247
|
# Obtain certificates
|
|
230
|
-
certificates =
|
|
248
|
+
certificates = try_obtain_server_certificates(args, args.fleet_api_type)
|
|
231
249
|
|
|
232
250
|
# Initialize StateFactory
|
|
233
251
|
state_factory = LinkStateFactory(args.database)
|
|
@@ -367,7 +385,11 @@ def run_superlink() -> None:
|
|
|
367
385
|
|
|
368
386
|
if args.isolation == ISOLATION_MODE_SUBPROCESS:
|
|
369
387
|
|
|
370
|
-
|
|
388
|
+
_octet, _colon, _port = serverappio_address.rpartition(":")
|
|
389
|
+
io_address = (
|
|
390
|
+
f"{CLIENT_OCTET}:{_port}" if _octet == SERVER_OCTET else serverappio_address
|
|
391
|
+
)
|
|
392
|
+
address = simulationio_address if sim_exec else io_address
|
|
371
393
|
cmd = "flwr-simulation" if sim_exec else "flwr-serverapp"
|
|
372
394
|
|
|
373
395
|
# Scheduler thread
|
|
@@ -426,7 +448,7 @@ def _flwr_scheduler(
|
|
|
426
448
|
command = [
|
|
427
449
|
cmd,
|
|
428
450
|
"--run-once",
|
|
429
|
-
"--
|
|
451
|
+
"--serverappio-api-address",
|
|
430
452
|
io_api_address,
|
|
431
453
|
]
|
|
432
454
|
if ssl_ca_certfile:
|
|
@@ -540,60 +562,6 @@ def _try_setup_node_authentication(
|
|
|
540
562
|
)
|
|
541
563
|
|
|
542
564
|
|
|
543
|
-
def _try_obtain_certificates(
|
|
544
|
-
args: argparse.Namespace,
|
|
545
|
-
) -> Optional[tuple[bytes, bytes, bytes]]:
|
|
546
|
-
# Obtain certificates
|
|
547
|
-
if args.insecure:
|
|
548
|
-
log(WARN, "Option `--insecure` was set. Starting insecure HTTP server.")
|
|
549
|
-
return None
|
|
550
|
-
# Check if certificates are provided
|
|
551
|
-
if args.fleet_api_type in [TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_GRPC_ADAPTER]:
|
|
552
|
-
if args.ssl_certfile and args.ssl_keyfile and args.ssl_ca_certfile:
|
|
553
|
-
if not isfile(args.ssl_ca_certfile):
|
|
554
|
-
sys.exit("Path argument `--ssl-ca-certfile` does not point to a file.")
|
|
555
|
-
if not isfile(args.ssl_certfile):
|
|
556
|
-
sys.exit("Path argument `--ssl-certfile` does not point to a file.")
|
|
557
|
-
if not isfile(args.ssl_keyfile):
|
|
558
|
-
sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
|
|
559
|
-
certificates = (
|
|
560
|
-
Path(args.ssl_ca_certfile).read_bytes(), # CA certificate
|
|
561
|
-
Path(args.ssl_certfile).read_bytes(), # server certificate
|
|
562
|
-
Path(args.ssl_keyfile).read_bytes(), # server private key
|
|
563
|
-
)
|
|
564
|
-
return certificates
|
|
565
|
-
if args.ssl_certfile or args.ssl_keyfile or args.ssl_ca_certfile:
|
|
566
|
-
sys.exit(
|
|
567
|
-
"You need to provide valid file paths to `--ssl-certfile`, "
|
|
568
|
-
"`--ssl-keyfile`, and `—-ssl-ca-certfile` to create a secure "
|
|
569
|
-
"connection in Fleet API server (gRPC-rere)."
|
|
570
|
-
)
|
|
571
|
-
if args.fleet_api_type == TRANSPORT_TYPE_REST:
|
|
572
|
-
if args.ssl_certfile and args.ssl_keyfile:
|
|
573
|
-
if not isfile(args.ssl_certfile):
|
|
574
|
-
sys.exit("Path argument `--ssl-certfile` does not point to a file.")
|
|
575
|
-
if not isfile(args.ssl_keyfile):
|
|
576
|
-
sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
|
|
577
|
-
certificates = (
|
|
578
|
-
b"",
|
|
579
|
-
Path(args.ssl_certfile).read_bytes(), # server certificate
|
|
580
|
-
Path(args.ssl_keyfile).read_bytes(), # server private key
|
|
581
|
-
)
|
|
582
|
-
return certificates
|
|
583
|
-
if args.ssl_certfile or args.ssl_keyfile:
|
|
584
|
-
sys.exit(
|
|
585
|
-
"You need to provide valid file paths to `--ssl-certfile` "
|
|
586
|
-
"and `--ssl-keyfile` to create a secure connection "
|
|
587
|
-
"in Fleet API server (REST, experimental)."
|
|
588
|
-
)
|
|
589
|
-
sys.exit(
|
|
590
|
-
"Certificates are required unless running in insecure mode. "
|
|
591
|
-
"Please provide certificate paths to `--ssl-certfile`, "
|
|
592
|
-
"`--ssl-keyfile`, and `—-ssl-ca-certfile` or run the server "
|
|
593
|
-
"in insecure mode using '--insecure' if you understand the risks."
|
|
594
|
-
)
|
|
595
|
-
|
|
596
|
-
|
|
597
565
|
def _run_fleet_api_grpc_rere(
|
|
598
566
|
address: str,
|
|
599
567
|
state_factory: LinkStateFactory,
|
|
@@ -786,8 +754,9 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
|
|
|
786
754
|
def _add_args_serverappio_api(parser: argparse.ArgumentParser) -> None:
|
|
787
755
|
parser.add_argument(
|
|
788
756
|
"--serverappio-api-address",
|
|
789
|
-
|
|
790
|
-
|
|
757
|
+
default=SERVERAPPIO_API_DEFAULT_SERVER_ADDRESS,
|
|
758
|
+
help="ServerAppIo API (gRPC) server address (IPv4, IPv6, or a domain name). "
|
|
759
|
+
f"By default, it is set to {SERVERAPPIO_API_DEFAULT_SERVER_ADDRESS}.",
|
|
791
760
|
)
|
|
792
761
|
|
|
793
762
|
|
|
@@ -820,8 +789,9 @@ def _add_args_exec_api(parser: argparse.ArgumentParser) -> None:
|
|
|
820
789
|
"""Add command line arguments for Exec API."""
|
|
821
790
|
parser.add_argument(
|
|
822
791
|
"--exec-api-address",
|
|
823
|
-
help="Exec API server address (IPv4, IPv6, or a domain name)"
|
|
824
|
-
default
|
|
792
|
+
help="Exec API server address (IPv4, IPv6, or a domain name) "
|
|
793
|
+
f"By default, it is set to {EXEC_API_DEFAULT_SERVER_ADDRESS}.",
|
|
794
|
+
default=EXEC_API_DEFAULT_SERVER_ADDRESS,
|
|
825
795
|
)
|
|
826
796
|
parser.add_argument(
|
|
827
797
|
"--executor",
|
|
@@ -845,6 +815,7 @@ def _add_args_exec_api(parser: argparse.ArgumentParser) -> None:
|
|
|
845
815
|
def _add_args_simulationio_api(parser: argparse.ArgumentParser) -> None:
|
|
846
816
|
parser.add_argument(
|
|
847
817
|
"--simulationio-api-address",
|
|
848
|
-
|
|
849
|
-
|
|
818
|
+
default=SIMULATIONIO_API_DEFAULT_SERVER_ADDRESS,
|
|
819
|
+
help="SimulationIo API (gRPC) server address (IPv4, IPv6, or a domain name)."
|
|
820
|
+
f"By default, it is set to {SIMULATIONIO_API_DEFAULT_SERVER_ADDRESS}.",
|
|
850
821
|
)
|
|
@@ -23,14 +23,10 @@ from typing import Optional, cast
|
|
|
23
23
|
import grpc
|
|
24
24
|
|
|
25
25
|
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
|
26
|
-
from flwr.common.constant import
|
|
26
|
+
from flwr.common.constant import SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS
|
|
27
27
|
from flwr.common.grpc import create_channel
|
|
28
28
|
from flwr.common.logger import log
|
|
29
|
-
from flwr.common.serde import
|
|
30
|
-
message_from_taskres,
|
|
31
|
-
message_to_taskins,
|
|
32
|
-
user_config_from_proto,
|
|
33
|
-
)
|
|
29
|
+
from flwr.common.serde import message_from_taskres, message_to_taskins, run_from_proto
|
|
34
30
|
from flwr.common.typing import Run
|
|
35
31
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
36
32
|
from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
|
|
@@ -70,7 +66,7 @@ class GrpcDriver(Driver):
|
|
|
70
66
|
|
|
71
67
|
def __init__( # pylint: disable=too-many-arguments
|
|
72
68
|
self,
|
|
73
|
-
serverappio_service_address: str =
|
|
69
|
+
serverappio_service_address: str = SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS,
|
|
74
70
|
root_certificates: Optional[bytes] = None,
|
|
75
71
|
) -> None:
|
|
76
72
|
self._addr = serverappio_service_address
|
|
@@ -119,13 +115,7 @@ class GrpcDriver(Driver):
|
|
|
119
115
|
res: GetRunResponse = self._stub.GetRun(req)
|
|
120
116
|
if not res.HasField("run"):
|
|
121
117
|
raise RuntimeError(f"Cannot find the run with ID: {run_id}")
|
|
122
|
-
self._run =
|
|
123
|
-
run_id=res.run.run_id,
|
|
124
|
-
fab_id=res.run.fab_id,
|
|
125
|
-
fab_version=res.run.fab_version,
|
|
126
|
-
fab_hash=res.run.fab_hash,
|
|
127
|
-
override_config=user_config_from_proto(res.run.override_config),
|
|
128
|
-
)
|
|
118
|
+
self._run = run_from_proto(res.run)
|
|
129
119
|
|
|
130
120
|
@property
|
|
131
121
|
def run(self) -> Run:
|
flwr/server/run_serverapp.py
CHANGED
|
@@ -15,33 +15,15 @@
|
|
|
15
15
|
"""Run ServerApp."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
import argparse
|
|
19
18
|
import sys
|
|
20
|
-
from logging import DEBUG,
|
|
21
|
-
from pathlib import Path
|
|
19
|
+
from logging import DEBUG, ERROR
|
|
22
20
|
from typing import Optional
|
|
23
21
|
|
|
24
|
-
from flwr.
|
|
25
|
-
from flwr.
|
|
26
|
-
from flwr.common import Context, EventType, RecordSet, event
|
|
27
|
-
from flwr.common.config import (
|
|
28
|
-
get_flwr_dir,
|
|
29
|
-
get_fused_config_from_dir,
|
|
30
|
-
get_metadata_from_config,
|
|
31
|
-
get_project_config,
|
|
32
|
-
get_project_dir,
|
|
33
|
-
)
|
|
34
|
-
from flwr.common.constant import SERVERAPPIO_API_DEFAULT_ADDRESS
|
|
35
|
-
from flwr.common.logger import log, update_console_handler, warn_deprecated_feature
|
|
22
|
+
from flwr.common import Context
|
|
23
|
+
from flwr.common.logger import log, warn_unsupported_feature
|
|
36
24
|
from flwr.common.object_ref import load_app
|
|
37
|
-
from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
|
|
38
|
-
from flwr.proto.run_pb2 import ( # pylint: disable=E0611
|
|
39
|
-
CreateRunRequest,
|
|
40
|
-
CreateRunResponse,
|
|
41
|
-
)
|
|
42
25
|
|
|
43
26
|
from .driver import Driver
|
|
44
|
-
from .driver.grpc_driver import GrpcDriver
|
|
45
27
|
from .server_app import LoadServerAppError, ServerApp
|
|
46
28
|
|
|
47
29
|
|
|
@@ -87,221 +69,9 @@ def run(
|
|
|
87
69
|
# pylint: disable-next=too-many-branches,too-many-statements,too-many-locals
|
|
88
70
|
def run_server_app() -> None:
|
|
89
71
|
"""Run Flower server app."""
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# Check if the server app reference is passed.
|
|
95
|
-
# Since Flower 1.11, passing a reference is not allowed.
|
|
96
|
-
app_path: Optional[str] = args.app
|
|
97
|
-
# If the provided app_path doesn't exist, and contains a ":",
|
|
98
|
-
# it is likely to be a server app reference instead of a path.
|
|
99
|
-
if app_path is not None and not Path(app_path).exists() and ":" in app_path:
|
|
100
|
-
sys.exit(
|
|
101
|
-
"It appears you've passed a reference like `server:app`.\n\n"
|
|
102
|
-
"Note that since version `1.11.0`, `flower-server-app` no longer supports "
|
|
103
|
-
"passing a reference to a `ServerApp` attribute. Instead, you need to pass "
|
|
104
|
-
"the path to Flower app via the argument `--app`. This is the path to a "
|
|
105
|
-
"directory containing a `pyproject.toml`. You can create a valid Flower "
|
|
106
|
-
"app by executing `flwr new` and following the prompt."
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
if args.server != SERVERAPPIO_API_DEFAULT_ADDRESS:
|
|
110
|
-
warn = "Passing flag --server is deprecated. Use --superlink instead."
|
|
111
|
-
warn_deprecated_feature(warn)
|
|
112
|
-
|
|
113
|
-
if args.superlink != SERVERAPPIO_API_DEFAULT_ADDRESS:
|
|
114
|
-
# if `--superlink` also passed, then
|
|
115
|
-
# warn user that this argument overrides what was passed with `--server`
|
|
116
|
-
log(
|
|
117
|
-
WARN,
|
|
118
|
-
"Both `--server` and `--superlink` were passed. "
|
|
119
|
-
"`--server` will be ignored. Connecting to the "
|
|
120
|
-
"SuperLink ServerAppIo API at %s.",
|
|
121
|
-
args.superlink,
|
|
122
|
-
)
|
|
123
|
-
else:
|
|
124
|
-
args.superlink = args.server
|
|
125
|
-
|
|
126
|
-
update_console_handler(
|
|
127
|
-
level=DEBUG if args.verbose else INFO,
|
|
128
|
-
timestamps=args.verbose,
|
|
129
|
-
colored=True,
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
# Obtain certificates
|
|
133
|
-
if args.insecure:
|
|
134
|
-
if args.root_certificates is not None:
|
|
135
|
-
sys.exit(
|
|
136
|
-
"Conflicting options: The '--insecure' flag disables HTTPS, "
|
|
137
|
-
"but '--root-certificates' was also specified. Please remove "
|
|
138
|
-
"the '--root-certificates' option when running in insecure mode, "
|
|
139
|
-
"or omit '--insecure' to use HTTPS."
|
|
140
|
-
)
|
|
141
|
-
log(
|
|
142
|
-
WARN,
|
|
143
|
-
"Option `--insecure` was set. "
|
|
144
|
-
"Starting insecure HTTP client connected to %s.",
|
|
145
|
-
args.superlink,
|
|
146
|
-
)
|
|
147
|
-
root_certificates = None
|
|
148
|
-
else:
|
|
149
|
-
# Load the certificates if provided, or load the system certificates
|
|
150
|
-
cert_path = args.root_certificates
|
|
151
|
-
if cert_path is None:
|
|
152
|
-
root_certificates = None
|
|
153
|
-
else:
|
|
154
|
-
root_certificates = Path(cert_path).read_bytes()
|
|
155
|
-
log(
|
|
156
|
-
DEBUG,
|
|
157
|
-
"Starting secure HTTPS client connected to %s "
|
|
158
|
-
"with the following certificates: %s.",
|
|
159
|
-
args.superlink,
|
|
160
|
-
cert_path,
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
if not (app_path is None) ^ (args.run_id is None):
|
|
164
|
-
raise sys.exit(
|
|
165
|
-
"Please provide either a Flower App path or a Run ID, but not both. "
|
|
166
|
-
"For more details, use: ``flower-server-app -h``"
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
# Initialize GrpcDriver
|
|
170
|
-
if app_path is None:
|
|
171
|
-
# User provided `--run-id`, but not `app_dir`
|
|
172
|
-
driver = GrpcDriver(
|
|
173
|
-
serverappio_service_address=args.superlink,
|
|
174
|
-
root_certificates=root_certificates,
|
|
175
|
-
)
|
|
176
|
-
flwr_dir = get_flwr_dir(args.flwr_dir)
|
|
177
|
-
driver.set_run(args.run_id)
|
|
178
|
-
run_ = driver.run
|
|
179
|
-
if not run_.fab_hash:
|
|
180
|
-
raise ValueError("FAB hash not provided.")
|
|
181
|
-
fab_req = GetFabRequest(hash_str=run_.fab_hash)
|
|
182
|
-
# pylint: disable-next=W0212
|
|
183
|
-
fab_res: GetFabResponse = driver._stub.GetFab(fab_req)
|
|
184
|
-
if fab_res.fab.hash_str != run_.fab_hash:
|
|
185
|
-
raise ValueError("FAB hashes don't match.")
|
|
186
|
-
install_from_fab(fab_res.fab.content, flwr_dir, True)
|
|
187
|
-
fab_id, fab_version = get_fab_metadata(fab_res.fab.content)
|
|
188
|
-
|
|
189
|
-
app_path = str(get_project_dir(fab_id, fab_version, run_.fab_hash, flwr_dir))
|
|
190
|
-
config = get_project_config(app_path)
|
|
191
|
-
run_id = run_.run_id
|
|
192
|
-
else:
|
|
193
|
-
# User provided `app_dir`, but not `--run-id`
|
|
194
|
-
# Create run if run_id is not provided
|
|
195
|
-
driver = GrpcDriver(
|
|
196
|
-
serverappio_service_address=args.superlink,
|
|
197
|
-
root_certificates=root_certificates,
|
|
198
|
-
)
|
|
199
|
-
# Load config from the project directory
|
|
200
|
-
config = get_project_config(app_path)
|
|
201
|
-
fab_version, fab_id = get_metadata_from_config(config)
|
|
202
|
-
|
|
203
|
-
# Create run
|
|
204
|
-
req = CreateRunRequest(fab_id=fab_id, fab_version=fab_version)
|
|
205
|
-
res: CreateRunResponse = driver._stub.CreateRun(req) # pylint: disable=W0212
|
|
206
|
-
# Fetch full `Run` using `run_id`
|
|
207
|
-
driver.set_run(res.run_id) # pylint: disable=W0212
|
|
208
|
-
run_id = res.run_id
|
|
209
|
-
|
|
210
|
-
# Obtain server app reference and the run config
|
|
211
|
-
server_app_attr = config["tool"]["flwr"]["app"]["components"]["serverapp"]
|
|
212
|
-
server_app_run_config = get_fused_config_from_dir(
|
|
213
|
-
Path(app_path), driver.run.override_config
|
|
72
|
+
warn_unsupported_feature(
|
|
73
|
+
"The command `flower-server-app` is deprecated and no longer in use. "
|
|
74
|
+
"Use the `flwr-serverapp` exclusively instead."
|
|
214
75
|
)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
log(
|
|
219
|
-
DEBUG,
|
|
220
|
-
"root_certificates: `%s`",
|
|
221
|
-
root_certificates,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# Initialize Context
|
|
225
|
-
context = Context(
|
|
226
|
-
run_id=run_id,
|
|
227
|
-
node_id=0,
|
|
228
|
-
node_config={},
|
|
229
|
-
state=RecordSet(),
|
|
230
|
-
run_config=server_app_run_config,
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
# Run the ServerApp with the Driver
|
|
234
|
-
run(
|
|
235
|
-
driver=driver,
|
|
236
|
-
context=context,
|
|
237
|
-
server_app_dir=app_path,
|
|
238
|
-
server_app_attr=server_app_attr,
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
# Clean up
|
|
242
|
-
driver.close()
|
|
243
|
-
|
|
244
|
-
event(EventType.RUN_SERVER_APP_LEAVE)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def _parse_args_run_server_app() -> argparse.ArgumentParser:
|
|
248
|
-
"""Parse flower-server-app command line arguments."""
|
|
249
|
-
parser = argparse.ArgumentParser(
|
|
250
|
-
description="Start a Flower server app",
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
parser.add_argument(
|
|
254
|
-
"app",
|
|
255
|
-
nargs="?",
|
|
256
|
-
default=None,
|
|
257
|
-
help="Load and run the `ServerApp` from the specified Flower App path. "
|
|
258
|
-
"The `pyproject.toml` file must be located in the root of this path.",
|
|
259
|
-
)
|
|
260
|
-
parser.add_argument(
|
|
261
|
-
"--insecure",
|
|
262
|
-
action="store_true",
|
|
263
|
-
help="Run the `ServerApp` without HTTPS. By default, the app runs with "
|
|
264
|
-
"HTTPS enabled. Use this flag only if you understand the risks.",
|
|
265
|
-
)
|
|
266
|
-
parser.add_argument(
|
|
267
|
-
"--verbose",
|
|
268
|
-
action="store_true",
|
|
269
|
-
help="Set the logging to `DEBUG`.",
|
|
270
|
-
)
|
|
271
|
-
parser.add_argument(
|
|
272
|
-
"--root-certificates",
|
|
273
|
-
metavar="ROOT_CERT",
|
|
274
|
-
type=str,
|
|
275
|
-
help="Specifies the path to the PEM-encoded root certificate file for "
|
|
276
|
-
"establishing secure HTTPS connections.",
|
|
277
|
-
)
|
|
278
|
-
parser.add_argument(
|
|
279
|
-
"--server",
|
|
280
|
-
default=SERVERAPPIO_API_DEFAULT_ADDRESS,
|
|
281
|
-
help="Server address",
|
|
282
|
-
)
|
|
283
|
-
parser.add_argument(
|
|
284
|
-
"--superlink",
|
|
285
|
-
default=SERVERAPPIO_API_DEFAULT_ADDRESS,
|
|
286
|
-
help="SuperLink ServerAppIo API (gRPC-rere) address "
|
|
287
|
-
"(IPv4, IPv6, or a domain name)",
|
|
288
|
-
)
|
|
289
|
-
parser.add_argument(
|
|
290
|
-
"--run-id",
|
|
291
|
-
default=None,
|
|
292
|
-
type=int,
|
|
293
|
-
help="The identifier of the run.",
|
|
294
|
-
)
|
|
295
|
-
parser.add_argument(
|
|
296
|
-
"--flwr-dir",
|
|
297
|
-
default=None,
|
|
298
|
-
help="""The path containing installed Flower Apps.
|
|
299
|
-
By default, this value is equal to:
|
|
300
|
-
|
|
301
|
-
- `$FLWR_HOME/` if `$FLWR_HOME` is defined
|
|
302
|
-
- `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined
|
|
303
|
-
- `$HOME/.flwr/` in all other cases
|
|
304
|
-
""",
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
return parser
|
|
76
|
+
log(ERROR, "`flower-server-app` used.")
|
|
77
|
+
sys.exit()
|