flwr-nightly 1.13.0.dev20241021__py3-none-any.whl → 1.13.0.dev20241111__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 (92) hide show
  1. flwr/cli/build.py +2 -2
  2. flwr/cli/config_utils.py +97 -0
  3. flwr/cli/log.py +63 -97
  4. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +1 -1
  5. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -0
  6. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  7. flwr/cli/run/run.py +34 -88
  8. flwr/client/app.py +23 -20
  9. flwr/client/clientapp/app.py +22 -18
  10. flwr/client/nodestate/__init__.py +25 -0
  11. flwr/client/nodestate/in_memory_nodestate.py +38 -0
  12. flwr/client/nodestate/nodestate.py +30 -0
  13. flwr/client/nodestate/nodestate_factory.py +37 -0
  14. flwr/client/{node_state.py → run_info_store.py} +4 -3
  15. flwr/client/supernode/app.py +6 -8
  16. flwr/common/args.py +83 -0
  17. flwr/common/config.py +10 -0
  18. flwr/common/constant.py +39 -5
  19. flwr/common/context.py +9 -4
  20. flwr/common/date.py +3 -3
  21. flwr/common/logger.py +108 -1
  22. flwr/common/object_ref.py +47 -16
  23. flwr/common/serde.py +24 -0
  24. flwr/common/telemetry.py +0 -6
  25. flwr/common/typing.py +10 -1
  26. flwr/proto/exec_pb2.py +14 -17
  27. flwr/proto/exec_pb2.pyi +14 -22
  28. flwr/proto/log_pb2.py +29 -0
  29. flwr/proto/log_pb2.pyi +39 -0
  30. flwr/proto/log_pb2_grpc.py +4 -0
  31. flwr/proto/log_pb2_grpc.pyi +4 -0
  32. flwr/proto/message_pb2.py +8 -8
  33. flwr/proto/message_pb2.pyi +4 -1
  34. flwr/proto/run_pb2.py +32 -27
  35. flwr/proto/run_pb2.pyi +26 -0
  36. flwr/proto/serverappio_pb2.py +52 -0
  37. flwr/proto/{driver_pb2.pyi → serverappio_pb2.pyi} +54 -0
  38. flwr/proto/serverappio_pb2_grpc.py +376 -0
  39. flwr/proto/serverappio_pb2_grpc.pyi +147 -0
  40. flwr/proto/simulationio_pb2.py +38 -0
  41. flwr/proto/simulationio_pb2.pyi +65 -0
  42. flwr/proto/simulationio_pb2_grpc.py +205 -0
  43. flwr/proto/simulationio_pb2_grpc.pyi +81 -0
  44. flwr/server/app.py +272 -105
  45. flwr/server/driver/driver.py +15 -1
  46. flwr/server/driver/grpc_driver.py +25 -36
  47. flwr/server/driver/inmemory_driver.py +6 -16
  48. flwr/server/run_serverapp.py +29 -23
  49. flwr/server/{superlink/state → serverapp}/__init__.py +3 -9
  50. flwr/server/serverapp/app.py +214 -0
  51. flwr/server/strategy/aggregate.py +4 -4
  52. flwr/server/strategy/fedadam.py +11 -1
  53. flwr/server/superlink/driver/__init__.py +1 -1
  54. flwr/server/superlink/driver/{driver_grpc.py → serverappio_grpc.py} +19 -16
  55. flwr/server/superlink/driver/{driver_servicer.py → serverappio_servicer.py} +125 -39
  56. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +4 -2
  57. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +2 -2
  58. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -2
  59. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -2
  60. flwr/server/superlink/fleet/message_handler/message_handler.py +7 -7
  61. flwr/server/superlink/fleet/rest_rere/rest_api.py +7 -7
  62. flwr/server/superlink/fleet/vce/vce_api.py +23 -23
  63. flwr/server/superlink/linkstate/__init__.py +28 -0
  64. flwr/server/superlink/{state/in_memory_state.py → linkstate/in_memory_linkstate.py} +184 -36
  65. flwr/server/superlink/{state/state.py → linkstate/linkstate.py} +149 -19
  66. flwr/server/superlink/{state/state_factory.py → linkstate/linkstate_factory.py} +9 -9
  67. flwr/server/superlink/{state/sqlite_state.py → linkstate/sqlite_linkstate.py} +306 -65
  68. flwr/server/superlink/{state → linkstate}/utils.py +81 -30
  69. flwr/server/superlink/simulation/__init__.py +15 -0
  70. flwr/server/superlink/simulation/simulationio_grpc.py +65 -0
  71. flwr/server/superlink/simulation/simulationio_servicer.py +153 -0
  72. flwr/simulation/__init__.py +5 -1
  73. flwr/simulation/app.py +273 -345
  74. flwr/simulation/legacy_app.py +382 -0
  75. flwr/simulation/ray_transport/ray_client_proxy.py +2 -2
  76. flwr/simulation/run_simulation.py +57 -131
  77. flwr/simulation/simulationio_connection.py +86 -0
  78. flwr/superexec/app.py +6 -134
  79. flwr/superexec/deployment.py +61 -66
  80. flwr/superexec/exec_grpc.py +15 -8
  81. flwr/superexec/exec_servicer.py +36 -65
  82. flwr/superexec/executor.py +26 -7
  83. flwr/superexec/simulation.py +54 -107
  84. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/METADATA +5 -4
  85. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/RECORD +88 -69
  86. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/entry_points.txt +2 -0
  87. flwr/client/node_state_tests.py +0 -66
  88. flwr/proto/driver_pb2.py +0 -42
  89. flwr/proto/driver_pb2_grpc.py +0 -239
  90. flwr/proto/driver_pb2_grpc.pyi +0 -94
  91. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/LICENSE +0 -0
  92. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/WHEEL +0 -0
flwr/server/app.py CHANGED
@@ -17,12 +17,14 @@
17
17
  import argparse
18
18
  import csv
19
19
  import importlib.util
20
+ import subprocess
20
21
  import sys
21
22
  import threading
22
23
  from collections.abc import Sequence
23
- from logging import INFO, WARN
24
+ from logging import DEBUG, INFO, WARN
24
25
  from os.path import isfile
25
26
  from pathlib import Path
27
+ from time import sleep
26
28
  from typing import Optional
27
29
 
28
30
  import grpc
@@ -35,13 +37,17 @@ from cryptography.hazmat.primitives.serialization import (
35
37
 
36
38
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
37
39
  from flwr.common.address import parse_address
38
- from flwr.common.config import get_flwr_dir
40
+ from flwr.common.config import get_flwr_dir, parse_config_args
39
41
  from flwr.common.constant import (
40
- DRIVER_API_DEFAULT_ADDRESS,
42
+ EXEC_API_DEFAULT_ADDRESS,
41
43
  FLEET_API_GRPC_BIDI_DEFAULT_ADDRESS,
42
44
  FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
43
45
  FLEET_API_REST_DEFAULT_ADDRESS,
46
+ ISOLATION_MODE_PROCESS,
47
+ ISOLATION_MODE_SUBPROCESS,
44
48
  MISSING_EXTRA_REST,
49
+ SERVERAPPIO_API_DEFAULT_ADDRESS,
50
+ SIMULATIONIO_API_DEFAULT_ADDRESS,
45
51
  TRANSPORT_TYPE_GRPC_ADAPTER,
46
52
  TRANSPORT_TYPE_GRPC_RERE,
47
53
  TRANSPORT_TYPE_REST,
@@ -56,13 +62,16 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
56
62
  add_FleetServicer_to_server,
57
63
  )
58
64
  from flwr.proto.grpcadapter_pb2_grpc import add_GrpcAdapterServicer_to_server
65
+ from flwr.superexec.app import load_executor
66
+ from flwr.superexec.exec_grpc import run_exec_api_grpc
67
+ from flwr.superexec.simulation import SimulationEngine
59
68
 
60
69
  from .client_manager import ClientManager
61
70
  from .history import History
62
71
  from .server import Server, init_defaults, run_fl
63
72
  from .server_config import ServerConfig
64
73
  from .strategy import Strategy
65
- from .superlink.driver.driver_grpc import run_driver_api_grpc
74
+ from .superlink.driver.serverappio_grpc import run_serverappio_api_grpc
66
75
  from .superlink.ffs.ffs_factory import FfsFactory
67
76
  from .superlink.fleet.grpc_adapter.grpc_adapter_servicer import GrpcAdapterServicer
68
77
  from .superlink.fleet.grpc_bidi.grpc_server import (
@@ -71,7 +80,8 @@ from .superlink.fleet.grpc_bidi.grpc_server import (
71
80
  )
72
81
  from .superlink.fleet.grpc_rere.fleet_servicer import FleetServicer
73
82
  from .superlink.fleet.grpc_rere.server_interceptor import AuthenticateServerInterceptor
74
- from .superlink.state import StateFactory
83
+ from .superlink.linkstate import LinkStateFactory
84
+ from .superlink.simulation.simulationio_grpc import run_simulationio_api_grpc
75
85
 
76
86
  DATABASE = ":flwr-in-memory-state:"
77
87
  BASE_DIR = get_flwr_dir() / "superlink" / "ffs"
@@ -198,125 +208,180 @@ def start_server( # pylint: disable=too-many-arguments,too-many-locals
198
208
 
199
209
  # pylint: disable=too-many-branches, too-many-locals, too-many-statements
200
210
  def run_superlink() -> None:
201
- """Run Flower SuperLink (Driver API and Fleet API)."""
211
+ """Run Flower SuperLink (ServerAppIo API and Fleet API)."""
202
212
  args = _parse_args_run_superlink().parse_args()
203
213
 
204
214
  log(INFO, "Starting Flower SuperLink")
205
215
 
206
216
  event(EventType.RUN_SUPERLINK_ENTER)
207
217
 
208
- # Parse IP address
209
- driver_address, _, _ = _format_address(args.driver_api_address)
218
+ # Warn unused options
219
+ if args.flwr_dir is not None:
220
+ log(
221
+ WARN, "The `--flwr-dir` option is currently not in use and will be ignored."
222
+ )
223
+
224
+ # Parse IP addresses
225
+ serverappio_address, _, _ = _format_address(args.serverappio_api_address)
226
+ exec_address, _, _ = _format_address(args.exec_api_address)
227
+ simulationio_address, _, _ = _format_address(args.simulationio_api_address)
210
228
 
211
229
  # Obtain certificates
212
230
  certificates = _try_obtain_certificates(args)
213
231
 
214
232
  # Initialize StateFactory
215
- state_factory = StateFactory(args.database)
233
+ state_factory = LinkStateFactory(args.database)
216
234
 
217
235
  # Initialize FfsFactory
218
236
  ffs_factory = FfsFactory(args.storage_dir)
219
237
 
220
- # Start Driver API
221
- driver_server: grpc.Server = run_driver_api_grpc(
222
- address=driver_address,
238
+ # Start Exec API
239
+ executor = load_executor(args)
240
+ exec_server: grpc.Server = run_exec_api_grpc(
241
+ address=exec_address,
223
242
  state_factory=state_factory,
224
243
  ffs_factory=ffs_factory,
244
+ executor=executor,
225
245
  certificates=certificates,
246
+ config=parse_config_args(
247
+ [args.executor_config] if args.executor_config else args.executor_config
248
+ ),
226
249
  )
250
+ grpc_servers = [exec_server]
227
251
 
228
- grpc_servers = [driver_server]
229
- bckg_threads = []
230
- if not args.fleet_api_address:
231
- if args.fleet_api_type in [
232
- TRANSPORT_TYPE_GRPC_RERE,
233
- TRANSPORT_TYPE_GRPC_ADAPTER,
234
- ]:
235
- args.fleet_api_address = FLEET_API_GRPC_RERE_DEFAULT_ADDRESS
236
- elif args.fleet_api_type == TRANSPORT_TYPE_REST:
237
- args.fleet_api_address = FLEET_API_REST_DEFAULT_ADDRESS
238
-
239
- fleet_address, host, port = _format_address(args.fleet_api_address)
252
+ # Determine Exec plugin
253
+ # If simulation is used, don't start ServerAppIo and Fleet APIs
254
+ sim_exec = isinstance(executor, SimulationEngine)
240
255
 
241
- num_workers = args.fleet_api_num_workers
242
- if num_workers != 1:
243
- log(
244
- WARN,
245
- "The Fleet API currently supports only 1 worker. "
246
- "You have specified %d workers. "
247
- "Support for multiple workers will be added in future releases. "
248
- "Proceeding with a single worker.",
249
- args.fleet_api_num_workers,
250
- )
251
- num_workers = 1
252
-
253
- # Start Fleet API
254
- if args.fleet_api_type == TRANSPORT_TYPE_REST:
255
- if (
256
- importlib.util.find_spec("requests")
257
- and importlib.util.find_spec("starlette")
258
- and importlib.util.find_spec("uvicorn")
259
- ) is None:
260
- sys.exit(MISSING_EXTRA_REST)
261
-
262
- _, ssl_certfile, ssl_keyfile = (
263
- certificates if certificates is not None else (None, None, None)
264
- )
265
-
266
- fleet_thread = threading.Thread(
267
- target=_run_fleet_api_rest,
268
- args=(
269
- host,
270
- port,
271
- ssl_keyfile,
272
- ssl_certfile,
273
- state_factory,
274
- ffs_factory,
275
- num_workers,
276
- ),
277
- )
278
- fleet_thread.start()
279
- bckg_threads.append(fleet_thread)
280
- elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
281
- maybe_keys = _try_setup_node_authentication(args, certificates)
282
- interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None
283
- if maybe_keys is not None:
284
- (
285
- node_public_keys,
286
- server_private_key,
287
- server_public_key,
288
- ) = maybe_keys
289
- state = state_factory.state()
290
- state.store_node_public_keys(node_public_keys)
291
- state.store_server_private_public_key(
292
- private_key_to_bytes(server_private_key),
293
- public_key_to_bytes(server_public_key),
294
- )
295
- log(
296
- INFO,
297
- "Node authentication enabled with %d known public keys",
298
- len(node_public_keys),
299
- )
300
- interceptors = [AuthenticateServerInterceptor(state)]
256
+ bckg_threads = []
301
257
 
302
- fleet_server = _run_fleet_api_grpc_rere(
303
- address=fleet_address,
258
+ if sim_exec:
259
+ simulationio_server: grpc.Server = run_simulationio_api_grpc(
260
+ address=simulationio_address,
304
261
  state_factory=state_factory,
305
262
  ffs_factory=ffs_factory,
306
263
  certificates=certificates,
307
- interceptors=interceptors,
308
264
  )
309
- grpc_servers.append(fleet_server)
310
- elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_ADAPTER:
311
- fleet_server = _run_fleet_api_grpc_adapter(
312
- address=fleet_address,
265
+ grpc_servers.append(simulationio_server)
266
+
267
+ else:
268
+ # Start ServerAppIo API
269
+ serverappio_server: grpc.Server = run_serverappio_api_grpc(
270
+ address=serverappio_address,
313
271
  state_factory=state_factory,
314
272
  ffs_factory=ffs_factory,
315
273
  certificates=certificates,
316
274
  )
317
- grpc_servers.append(fleet_server)
318
- else:
319
- raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
275
+ grpc_servers.append(serverappio_server)
276
+
277
+ # Start Fleet API
278
+ if not args.fleet_api_address:
279
+ if args.fleet_api_type in [
280
+ TRANSPORT_TYPE_GRPC_RERE,
281
+ TRANSPORT_TYPE_GRPC_ADAPTER,
282
+ ]:
283
+ args.fleet_api_address = FLEET_API_GRPC_RERE_DEFAULT_ADDRESS
284
+ elif args.fleet_api_type == TRANSPORT_TYPE_REST:
285
+ args.fleet_api_address = FLEET_API_REST_DEFAULT_ADDRESS
286
+
287
+ fleet_address, host, port = _format_address(args.fleet_api_address)
288
+
289
+ num_workers = args.fleet_api_num_workers
290
+ if num_workers != 1:
291
+ log(
292
+ WARN,
293
+ "The Fleet API currently supports only 1 worker. "
294
+ "You have specified %d workers. "
295
+ "Support for multiple workers will be added in future releases. "
296
+ "Proceeding with a single worker.",
297
+ args.fleet_api_num_workers,
298
+ )
299
+ num_workers = 1
300
+
301
+ if args.fleet_api_type == TRANSPORT_TYPE_REST:
302
+ if (
303
+ importlib.util.find_spec("requests")
304
+ and importlib.util.find_spec("starlette")
305
+ and importlib.util.find_spec("uvicorn")
306
+ ) is None:
307
+ sys.exit(MISSING_EXTRA_REST)
308
+
309
+ _, ssl_certfile, ssl_keyfile = (
310
+ certificates if certificates is not None else (None, None, None)
311
+ )
312
+
313
+ fleet_thread = threading.Thread(
314
+ target=_run_fleet_api_rest,
315
+ args=(
316
+ host,
317
+ port,
318
+ ssl_keyfile,
319
+ ssl_certfile,
320
+ state_factory,
321
+ ffs_factory,
322
+ num_workers,
323
+ ),
324
+ )
325
+ fleet_thread.start()
326
+ bckg_threads.append(fleet_thread)
327
+ elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
328
+ maybe_keys = _try_setup_node_authentication(args, certificates)
329
+ interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None
330
+ if maybe_keys is not None:
331
+ (
332
+ node_public_keys,
333
+ server_private_key,
334
+ server_public_key,
335
+ ) = maybe_keys
336
+ state = state_factory.state()
337
+ state.store_node_public_keys(node_public_keys)
338
+ state.store_server_private_public_key(
339
+ private_key_to_bytes(server_private_key),
340
+ public_key_to_bytes(server_public_key),
341
+ )
342
+ log(
343
+ INFO,
344
+ "Node authentication enabled with %d known public keys",
345
+ len(node_public_keys),
346
+ )
347
+ interceptors = [AuthenticateServerInterceptor(state)]
348
+
349
+ fleet_server = _run_fleet_api_grpc_rere(
350
+ address=fleet_address,
351
+ state_factory=state_factory,
352
+ ffs_factory=ffs_factory,
353
+ certificates=certificates,
354
+ interceptors=interceptors,
355
+ )
356
+ grpc_servers.append(fleet_server)
357
+ elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_ADAPTER:
358
+ fleet_server = _run_fleet_api_grpc_adapter(
359
+ address=fleet_address,
360
+ state_factory=state_factory,
361
+ ffs_factory=ffs_factory,
362
+ certificates=certificates,
363
+ )
364
+ grpc_servers.append(fleet_server)
365
+ else:
366
+ raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
367
+
368
+ if args.isolation == ISOLATION_MODE_SUBPROCESS:
369
+
370
+ address = simulationio_address if sim_exec else serverappio_address
371
+ cmd = "flwr-simulation" if sim_exec else "flwr-serverapp"
372
+
373
+ # Scheduler thread
374
+ scheduler_th = threading.Thread(
375
+ target=_flwr_scheduler,
376
+ args=(
377
+ state_factory,
378
+ address,
379
+ args.ssl_ca_certfile,
380
+ cmd,
381
+ ),
382
+ )
383
+ scheduler_th.start()
384
+ bckg_threads.append(scheduler_th)
320
385
 
321
386
  # Graceful shutdown
322
387
  register_exit_handlers(
@@ -331,7 +396,49 @@ def run_superlink() -> None:
331
396
  for thread in bckg_threads:
332
397
  if not thread.is_alive():
333
398
  sys.exit(1)
334
- driver_server.wait_for_termination(timeout=1)
399
+ exec_server.wait_for_termination(timeout=1)
400
+
401
+
402
+ def _flwr_scheduler(
403
+ state_factory: LinkStateFactory,
404
+ io_api_address: str,
405
+ ssl_ca_certfile: Optional[str],
406
+ cmd: str,
407
+ ) -> None:
408
+ log(DEBUG, "Started %s scheduler thread.", cmd)
409
+
410
+ state = state_factory.state()
411
+
412
+ # Periodically check for a pending run in the LinkState
413
+ while True:
414
+ sleep(3)
415
+ pending_run_id = state.get_pending_run_id()
416
+
417
+ if pending_run_id:
418
+
419
+ log(
420
+ INFO,
421
+ "Launching %s subprocess. Connects to SuperLink on %s",
422
+ cmd,
423
+ io_api_address,
424
+ )
425
+ # Start subprocess
426
+ command = [
427
+ cmd,
428
+ "--run-once",
429
+ "--superlink",
430
+ io_api_address,
431
+ ]
432
+ if ssl_ca_certfile:
433
+ command.append("--root-certificates")
434
+ command.append(ssl_ca_certfile)
435
+ else:
436
+ command.append("--insecure")
437
+
438
+ subprocess.Popen( # pylint: disable=consider-using-with
439
+ command,
440
+ text=True,
441
+ )
335
442
 
336
443
 
337
444
  def _format_address(address: str) -> tuple[str, str, int]:
@@ -489,7 +596,7 @@ def _try_obtain_certificates(
489
596
 
490
597
  def _run_fleet_api_grpc_rere(
491
598
  address: str,
492
- state_factory: StateFactory,
599
+ state_factory: LinkStateFactory,
493
600
  ffs_factory: FfsFactory,
494
601
  certificates: Optional[tuple[bytes, bytes, bytes]],
495
602
  interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
@@ -517,7 +624,7 @@ def _run_fleet_api_grpc_rere(
517
624
 
518
625
  def _run_fleet_api_grpc_adapter(
519
626
  address: str,
520
- state_factory: StateFactory,
627
+ state_factory: LinkStateFactory,
521
628
  ffs_factory: FfsFactory,
522
629
  certificates: Optional[tuple[bytes, bytes, bytes]],
523
630
  ) -> grpc.Server:
@@ -548,11 +655,11 @@ def _run_fleet_api_rest(
548
655
  port: int,
549
656
  ssl_keyfile: Optional[str],
550
657
  ssl_certfile: Optional[str],
551
- state_factory: StateFactory,
658
+ state_factory: LinkStateFactory,
552
659
  ffs_factory: FfsFactory,
553
660
  num_workers: int,
554
661
  ) -> None:
555
- """Run Driver API (REST-based)."""
662
+ """Run ServerAppIo API (REST-based)."""
556
663
  try:
557
664
  import uvicorn
558
665
 
@@ -579,14 +686,16 @@ def _run_fleet_api_rest(
579
686
 
580
687
 
581
688
  def _parse_args_run_superlink() -> argparse.ArgumentParser:
582
- """Parse command line arguments for both Driver API and Fleet API."""
689
+ """Parse command line arguments for both ServerAppIo API and Fleet API."""
583
690
  parser = argparse.ArgumentParser(
584
691
  description="Start a Flower SuperLink",
585
692
  )
586
693
 
587
694
  _add_args_common(parser=parser)
588
- _add_args_driver_api(parser=parser)
695
+ _add_args_serverappio_api(parser=parser)
589
696
  _add_args_fleet_api(parser=parser)
697
+ _add_args_exec_api(parser=parser)
698
+ _add_args_simulationio_api(parser=parser)
590
699
 
591
700
  return parser
592
701
 
@@ -599,6 +708,17 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
599
708
  "paths are provided. By default, the server runs with HTTPS enabled. "
600
709
  "Use this flag only if you understand the risks.",
601
710
  )
711
+ parser.add_argument(
712
+ "--flwr-dir",
713
+ default=None,
714
+ help="""The path containing installed Flower Apps.
715
+ The default directory is:
716
+
717
+ - `$FLWR_HOME/` if `$FLWR_HOME` is defined
718
+ - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined
719
+ - `$HOME/.flwr/` in all other cases
720
+ """,
721
+ )
602
722
  parser.add_argument(
603
723
  "--ssl-certfile",
604
724
  help="Fleet API server SSL certificate file (as a path str) "
@@ -618,6 +738,19 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
618
738
  "to create a secure connection.",
619
739
  type=str,
620
740
  )
741
+ parser.add_argument(
742
+ "--isolation",
743
+ default=ISOLATION_MODE_SUBPROCESS,
744
+ required=False,
745
+ choices=[
746
+ ISOLATION_MODE_SUBPROCESS,
747
+ ISOLATION_MODE_PROCESS,
748
+ ],
749
+ help="Isolation mode when running a `ServerApp` (`subprocess` by default, "
750
+ "possible values: `subprocess`, `process`). Use `subprocess` to configure "
751
+ "SuperLink to run a `ServerApp` in a subprocess. Use `process` to indicate "
752
+ "that a separate independent process gets created outside of SuperLink.",
753
+ )
621
754
  parser.add_argument(
622
755
  "--database",
623
756
  help="A string representing the path to the database "
@@ -650,11 +783,11 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
650
783
  )
651
784
 
652
785
 
653
- def _add_args_driver_api(parser: argparse.ArgumentParser) -> None:
786
+ def _add_args_serverappio_api(parser: argparse.ArgumentParser) -> None:
654
787
  parser.add_argument(
655
- "--driver-api-address",
656
- help="Driver API (gRPC) server address (IPv4, IPv6, or a domain name).",
657
- default=DRIVER_API_DEFAULT_ADDRESS,
788
+ "--serverappio-api-address",
789
+ help="ServerAppIo API (gRPC) server address (IPv4, IPv6, or a domain name).",
790
+ default=SERVERAPPIO_API_DEFAULT_ADDRESS,
658
791
  )
659
792
 
660
793
 
@@ -681,3 +814,37 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None:
681
814
  type=int,
682
815
  help="Set the number of concurrent workers for the Fleet API server.",
683
816
  )
817
+
818
+
819
+ def _add_args_exec_api(parser: argparse.ArgumentParser) -> None:
820
+ """Add command line arguments for Exec API."""
821
+ parser.add_argument(
822
+ "--exec-api-address",
823
+ help="Exec API server address (IPv4, IPv6, or a domain name)",
824
+ default=EXEC_API_DEFAULT_ADDRESS,
825
+ )
826
+ parser.add_argument(
827
+ "--executor",
828
+ help="For example: `deployment:exec` or `project.package.module:wrapper.exec`. "
829
+ "The default is `flwr.superexec.deployment:executor`",
830
+ default="flwr.superexec.deployment:executor",
831
+ )
832
+ parser.add_argument(
833
+ "--executor-dir",
834
+ help="The directory for the executor.",
835
+ default=".",
836
+ )
837
+ parser.add_argument(
838
+ "--executor-config",
839
+ help="Key-value pairs for the executor config, separated by spaces. "
840
+ "For example:\n\n`--executor-config 'verbose=true "
841
+ 'root-certificates="certificates/superlink-ca.crt"\'`',
842
+ )
843
+
844
+
845
+ def _add_args_simulationio_api(parser: argparse.ArgumentParser) -> None:
846
+ parser.add_argument(
847
+ "--simulationio-api-address",
848
+ help="SimulationIo API (gRPC) server address (IPv4, IPv6, or a domain name).",
849
+ default=SIMULATIONIO_API_DEFAULT_ADDRESS,
850
+ )
@@ -24,7 +24,21 @@ from flwr.common.typing import Run
24
24
 
25
25
 
26
26
  class Driver(ABC):
27
- """Abstract base Driver class for the Driver API."""
27
+ """Abstract base Driver class for the ServerAppIo API."""
28
+
29
+ @abstractmethod
30
+ def set_run(self, run_id: int) -> None:
31
+ """Request a run to the SuperLink with a given `run_id`.
32
+
33
+ If a Run with the specified `run_id` exists, a local Run
34
+ object will be created. It enables further functionality
35
+ in the driver, such as sending `Messages`.
36
+
37
+ Parameters
38
+ ----------
39
+ run_id : int
40
+ The `run_id` of the Run this Driver object operates in.
41
+ """
28
42
 
29
43
  @property
30
44
  @abstractmethod