flwr-nightly 1.13.0.dev20241021__py3-none-any.whl → 1.13.0.dev20241106__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 (81) 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 +18 -83
  8. flwr/client/app.py +13 -14
  9. flwr/client/clientapp/app.py +1 -2
  10. flwr/client/{node_state.py → run_info_store.py} +4 -3
  11. flwr/client/supernode/app.py +6 -8
  12. flwr/common/constant.py +39 -4
  13. flwr/common/context.py +9 -4
  14. flwr/common/date.py +3 -3
  15. flwr/common/logger.py +103 -0
  16. flwr/common/serde.py +24 -0
  17. flwr/common/telemetry.py +0 -6
  18. flwr/common/typing.py +9 -0
  19. flwr/proto/exec_pb2.py +6 -6
  20. flwr/proto/exec_pb2.pyi +8 -2
  21. flwr/proto/log_pb2.py +29 -0
  22. flwr/proto/log_pb2.pyi +39 -0
  23. flwr/proto/log_pb2_grpc.py +4 -0
  24. flwr/proto/log_pb2_grpc.pyi +4 -0
  25. flwr/proto/message_pb2.py +8 -8
  26. flwr/proto/message_pb2.pyi +4 -1
  27. flwr/proto/serverappio_pb2.py +52 -0
  28. flwr/proto/{driver_pb2.pyi → serverappio_pb2.pyi} +54 -0
  29. flwr/proto/serverappio_pb2_grpc.py +376 -0
  30. flwr/proto/serverappio_pb2_grpc.pyi +147 -0
  31. flwr/proto/simulationio_pb2.py +38 -0
  32. flwr/proto/simulationio_pb2.pyi +65 -0
  33. flwr/proto/simulationio_pb2_grpc.py +171 -0
  34. flwr/proto/simulationio_pb2_grpc.pyi +68 -0
  35. flwr/server/app.py +247 -105
  36. flwr/server/driver/driver.py +15 -1
  37. flwr/server/driver/grpc_driver.py +26 -33
  38. flwr/server/driver/inmemory_driver.py +6 -14
  39. flwr/server/run_serverapp.py +29 -23
  40. flwr/server/{superlink/state → serverapp}/__init__.py +3 -9
  41. flwr/server/serverapp/app.py +270 -0
  42. flwr/server/strategy/fedadam.py +11 -1
  43. flwr/server/superlink/driver/__init__.py +1 -1
  44. flwr/server/superlink/driver/{driver_grpc.py → serverappio_grpc.py} +19 -16
  45. flwr/server/superlink/driver/{driver_servicer.py → serverappio_servicer.py} +125 -39
  46. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +4 -2
  47. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +2 -2
  48. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -2
  49. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -2
  50. flwr/server/superlink/fleet/message_handler/message_handler.py +7 -7
  51. flwr/server/superlink/fleet/rest_rere/rest_api.py +7 -7
  52. flwr/server/superlink/fleet/vce/vce_api.py +23 -23
  53. flwr/server/superlink/linkstate/__init__.py +28 -0
  54. flwr/server/superlink/{state/in_memory_state.py → linkstate/in_memory_linkstate.py} +180 -21
  55. flwr/server/superlink/{state/state.py → linkstate/linkstate.py} +144 -15
  56. flwr/server/superlink/{state/state_factory.py → linkstate/linkstate_factory.py} +9 -9
  57. flwr/server/superlink/{state/sqlite_state.py → linkstate/sqlite_linkstate.py} +300 -50
  58. flwr/server/superlink/{state → linkstate}/utils.py +84 -2
  59. flwr/server/superlink/simulation/__init__.py +15 -0
  60. flwr/server/superlink/simulation/simulationio_grpc.py +65 -0
  61. flwr/server/superlink/simulation/simulationio_servicer.py +132 -0
  62. flwr/simulation/__init__.py +2 -0
  63. flwr/simulation/app.py +1 -1
  64. flwr/simulation/ray_transport/ray_client_proxy.py +2 -2
  65. flwr/simulation/run_simulation.py +57 -131
  66. flwr/simulation/simulationio_connection.py +86 -0
  67. flwr/superexec/app.py +6 -134
  68. flwr/superexec/deployment.py +60 -65
  69. flwr/superexec/exec_grpc.py +15 -8
  70. flwr/superexec/exec_servicer.py +34 -63
  71. flwr/superexec/executor.py +22 -4
  72. flwr/superexec/simulation.py +13 -8
  73. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241106.dist-info}/METADATA +1 -1
  74. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241106.dist-info}/RECORD +77 -64
  75. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241106.dist-info}/entry_points.txt +1 -0
  76. flwr/client/node_state_tests.py +0 -66
  77. flwr/proto/driver_pb2.py +0 -42
  78. flwr/proto/driver_pb2_grpc.py +0 -239
  79. flwr/proto/driver_pb2_grpc.pyi +0 -94
  80. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241106.dist-info}/LICENSE +0 -0
  81. {flwr_nightly-1.13.0.dev20241021.dist-info → flwr_nightly-1.13.0.dev20241106.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,169 @@ 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
+ # Parse IP addresses
219
+ serverappio_address, _, _ = _format_address(args.serverappio_api_address)
220
+ exec_address, _, _ = _format_address(args.exec_api_address)
221
+ simulationio_address, _, _ = _format_address(args.simulationio_api_address)
210
222
 
211
223
  # Obtain certificates
212
224
  certificates = _try_obtain_certificates(args)
213
225
 
214
226
  # Initialize StateFactory
215
- state_factory = StateFactory(args.database)
227
+ state_factory = LinkStateFactory(args.database)
216
228
 
217
229
  # Initialize FfsFactory
218
230
  ffs_factory = FfsFactory(args.storage_dir)
219
231
 
220
- # Start Driver API
221
- driver_server: grpc.Server = run_driver_api_grpc(
222
- address=driver_address,
232
+ # Start Exec API
233
+ executor = load_executor(args)
234
+ exec_server: grpc.Server = run_exec_api_grpc(
235
+ address=exec_address,
223
236
  state_factory=state_factory,
224
237
  ffs_factory=ffs_factory,
238
+ executor=executor,
225
239
  certificates=certificates,
240
+ config=parse_config_args(
241
+ [args.executor_config] if args.executor_config else args.executor_config
242
+ ),
226
243
  )
244
+ grpc_servers = [exec_server]
227
245
 
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)
240
-
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
- )
246
+ # Determine Exec plugin
247
+ # If simulation is used, don't start ServerAppIo and Fleet APIs
248
+ sim_exec = isinstance(executor, SimulationEngine)
265
249
 
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)]
250
+ bckg_threads = []
301
251
 
302
- fleet_server = _run_fleet_api_grpc_rere(
303
- address=fleet_address,
252
+ if sim_exec:
253
+ simulationio_server: grpc.Server = run_simulationio_api_grpc(
254
+ address=simulationio_address,
304
255
  state_factory=state_factory,
305
256
  ffs_factory=ffs_factory,
306
257
  certificates=certificates,
307
- interceptors=interceptors,
308
258
  )
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,
259
+ grpc_servers.append(simulationio_server)
260
+
261
+ else:
262
+ # Start ServerAppIo API
263
+ serverappio_server: grpc.Server = run_serverappio_api_grpc(
264
+ address=serverappio_address,
313
265
  state_factory=state_factory,
314
266
  ffs_factory=ffs_factory,
315
267
  certificates=certificates,
316
268
  )
317
- grpc_servers.append(fleet_server)
318
- else:
319
- raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
269
+ grpc_servers.append(serverappio_server)
270
+
271
+ # Start Fleet API
272
+ if not args.fleet_api_address:
273
+ if args.fleet_api_type in [
274
+ TRANSPORT_TYPE_GRPC_RERE,
275
+ TRANSPORT_TYPE_GRPC_ADAPTER,
276
+ ]:
277
+ args.fleet_api_address = FLEET_API_GRPC_RERE_DEFAULT_ADDRESS
278
+ elif args.fleet_api_type == TRANSPORT_TYPE_REST:
279
+ args.fleet_api_address = FLEET_API_REST_DEFAULT_ADDRESS
280
+
281
+ fleet_address, host, port = _format_address(args.fleet_api_address)
282
+
283
+ num_workers = args.fleet_api_num_workers
284
+ if num_workers != 1:
285
+ log(
286
+ WARN,
287
+ "The Fleet API currently supports only 1 worker. "
288
+ "You have specified %d workers. "
289
+ "Support for multiple workers will be added in future releases. "
290
+ "Proceeding with a single worker.",
291
+ args.fleet_api_num_workers,
292
+ )
293
+ num_workers = 1
294
+
295
+ if args.fleet_api_type == TRANSPORT_TYPE_REST:
296
+ if (
297
+ importlib.util.find_spec("requests")
298
+ and importlib.util.find_spec("starlette")
299
+ and importlib.util.find_spec("uvicorn")
300
+ ) is None:
301
+ sys.exit(MISSING_EXTRA_REST)
302
+
303
+ _, ssl_certfile, ssl_keyfile = (
304
+ certificates if certificates is not None else (None, None, None)
305
+ )
306
+
307
+ fleet_thread = threading.Thread(
308
+ target=_run_fleet_api_rest,
309
+ args=(
310
+ host,
311
+ port,
312
+ ssl_keyfile,
313
+ ssl_certfile,
314
+ state_factory,
315
+ ffs_factory,
316
+ num_workers,
317
+ ),
318
+ )
319
+ fleet_thread.start()
320
+ bckg_threads.append(fleet_thread)
321
+ elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
322
+ maybe_keys = _try_setup_node_authentication(args, certificates)
323
+ interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None
324
+ if maybe_keys is not None:
325
+ (
326
+ node_public_keys,
327
+ server_private_key,
328
+ server_public_key,
329
+ ) = maybe_keys
330
+ state = state_factory.state()
331
+ state.store_node_public_keys(node_public_keys)
332
+ state.store_server_private_public_key(
333
+ private_key_to_bytes(server_private_key),
334
+ public_key_to_bytes(server_public_key),
335
+ )
336
+ log(
337
+ INFO,
338
+ "Node authentication enabled with %d known public keys",
339
+ len(node_public_keys),
340
+ )
341
+ interceptors = [AuthenticateServerInterceptor(state)]
342
+
343
+ fleet_server = _run_fleet_api_grpc_rere(
344
+ address=fleet_address,
345
+ state_factory=state_factory,
346
+ ffs_factory=ffs_factory,
347
+ certificates=certificates,
348
+ interceptors=interceptors,
349
+ )
350
+ grpc_servers.append(fleet_server)
351
+ elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_ADAPTER:
352
+ fleet_server = _run_fleet_api_grpc_adapter(
353
+ address=fleet_address,
354
+ state_factory=state_factory,
355
+ ffs_factory=ffs_factory,
356
+ certificates=certificates,
357
+ )
358
+ grpc_servers.append(fleet_server)
359
+ else:
360
+ raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
361
+
362
+ if args.isolation == ISOLATION_MODE_SUBPROCESS:
363
+ # Scheduler thread
364
+ scheduler_th = threading.Thread(
365
+ target=_flwr_serverapp_scheduler,
366
+ args=(
367
+ state_factory,
368
+ args.serverappio_api_address,
369
+ args.ssl_ca_certfile,
370
+ ),
371
+ )
372
+ scheduler_th.start()
373
+ bckg_threads.append(scheduler_th)
320
374
 
321
375
  # Graceful shutdown
322
376
  register_exit_handlers(
@@ -331,7 +385,46 @@ def run_superlink() -> None:
331
385
  for thread in bckg_threads:
332
386
  if not thread.is_alive():
333
387
  sys.exit(1)
334
- driver_server.wait_for_termination(timeout=1)
388
+ exec_server.wait_for_termination(timeout=1)
389
+
390
+
391
+ def _flwr_serverapp_scheduler(
392
+ state_factory: LinkStateFactory,
393
+ serverappio_api_address: str,
394
+ ssl_ca_certfile: Optional[str],
395
+ ) -> None:
396
+ log(DEBUG, "Started flwr-serverapp scheduler thread.")
397
+
398
+ state = state_factory.state()
399
+
400
+ # Periodically check for a pending run in the LinkState
401
+ while True:
402
+ sleep(3)
403
+ pending_run_id = state.get_pending_run_id()
404
+
405
+ if pending_run_id:
406
+
407
+ log(
408
+ INFO,
409
+ "Launching `flwr-serverapp` subprocess. Connects to SuperLink on %s",
410
+ serverappio_api_address,
411
+ )
412
+ # Start ServerApp subprocess
413
+ command = [
414
+ "flwr-serverapp",
415
+ "--superlink",
416
+ serverappio_api_address,
417
+ ]
418
+ if ssl_ca_certfile:
419
+ command.append("--root-certificates")
420
+ command.append(ssl_ca_certfile)
421
+ else:
422
+ command.append("--insecure")
423
+
424
+ subprocess.Popen( # pylint: disable=consider-using-with
425
+ command,
426
+ text=True,
427
+ )
335
428
 
336
429
 
337
430
  def _format_address(address: str) -> tuple[str, str, int]:
@@ -489,7 +582,7 @@ def _try_obtain_certificates(
489
582
 
490
583
  def _run_fleet_api_grpc_rere(
491
584
  address: str,
492
- state_factory: StateFactory,
585
+ state_factory: LinkStateFactory,
493
586
  ffs_factory: FfsFactory,
494
587
  certificates: Optional[tuple[bytes, bytes, bytes]],
495
588
  interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
@@ -517,7 +610,7 @@ def _run_fleet_api_grpc_rere(
517
610
 
518
611
  def _run_fleet_api_grpc_adapter(
519
612
  address: str,
520
- state_factory: StateFactory,
613
+ state_factory: LinkStateFactory,
521
614
  ffs_factory: FfsFactory,
522
615
  certificates: Optional[tuple[bytes, bytes, bytes]],
523
616
  ) -> grpc.Server:
@@ -548,11 +641,11 @@ def _run_fleet_api_rest(
548
641
  port: int,
549
642
  ssl_keyfile: Optional[str],
550
643
  ssl_certfile: Optional[str],
551
- state_factory: StateFactory,
644
+ state_factory: LinkStateFactory,
552
645
  ffs_factory: FfsFactory,
553
646
  num_workers: int,
554
647
  ) -> None:
555
- """Run Driver API (REST-based)."""
648
+ """Run ServerAppIo API (REST-based)."""
556
649
  try:
557
650
  import uvicorn
558
651
 
@@ -579,14 +672,16 @@ def _run_fleet_api_rest(
579
672
 
580
673
 
581
674
  def _parse_args_run_superlink() -> argparse.ArgumentParser:
582
- """Parse command line arguments for both Driver API and Fleet API."""
675
+ """Parse command line arguments for both ServerAppIo API and Fleet API."""
583
676
  parser = argparse.ArgumentParser(
584
677
  description="Start a Flower SuperLink",
585
678
  )
586
679
 
587
680
  _add_args_common(parser=parser)
588
- _add_args_driver_api(parser=parser)
681
+ _add_args_serverappio_api(parser=parser)
589
682
  _add_args_fleet_api(parser=parser)
683
+ _add_args_exec_api(parser=parser)
684
+ _add_args_simulationio_api(parser=parser)
590
685
 
591
686
  return parser
592
687
 
@@ -618,6 +713,19 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
618
713
  "to create a secure connection.",
619
714
  type=str,
620
715
  )
716
+ parser.add_argument(
717
+ "--isolation",
718
+ default=ISOLATION_MODE_SUBPROCESS,
719
+ required=False,
720
+ choices=[
721
+ ISOLATION_MODE_SUBPROCESS,
722
+ ISOLATION_MODE_PROCESS,
723
+ ],
724
+ help="Isolation mode when running a `ServerApp` (`subprocess` by default, "
725
+ "possible values: `subprocess`, `process`). Use `subprocess` to configure "
726
+ "SuperLink to run a `ServerApp` in a subprocess. Use `process` to indicate "
727
+ "that a separate independent process gets created outside of SuperLink.",
728
+ )
621
729
  parser.add_argument(
622
730
  "--database",
623
731
  help="A string representing the path to the database "
@@ -650,11 +758,11 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
650
758
  )
651
759
 
652
760
 
653
- def _add_args_driver_api(parser: argparse.ArgumentParser) -> None:
761
+ def _add_args_serverappio_api(parser: argparse.ArgumentParser) -> None:
654
762
  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,
763
+ "--serverappio-api-address",
764
+ help="ServerAppIo API (gRPC) server address (IPv4, IPv6, or a domain name).",
765
+ default=SERVERAPPIO_API_DEFAULT_ADDRESS,
658
766
  )
659
767
 
660
768
 
@@ -681,3 +789,37 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None:
681
789
  type=int,
682
790
  help="Set the number of concurrent workers for the Fleet API server.",
683
791
  )
792
+
793
+
794
+ def _add_args_exec_api(parser: argparse.ArgumentParser) -> None:
795
+ """Add command line arguments for Exec API."""
796
+ parser.add_argument(
797
+ "--exec-api-address",
798
+ help="Exec API server address (IPv4, IPv6, or a domain name)",
799
+ default=EXEC_API_DEFAULT_ADDRESS,
800
+ )
801
+ parser.add_argument(
802
+ "--executor",
803
+ help="For example: `deployment:exec` or `project.package.module:wrapper.exec`. "
804
+ "The default is `flwr.superexec.deployment:executor`",
805
+ default="flwr.superexec.deployment:executor",
806
+ )
807
+ parser.add_argument(
808
+ "--executor-dir",
809
+ help="The directory for the executor.",
810
+ default=".",
811
+ )
812
+ parser.add_argument(
813
+ "--executor-config",
814
+ help="Key-value pairs for the executor config, separated by spaces. "
815
+ "For example:\n\n`--executor-config 'verbose=true "
816
+ 'root-certificates="certificates/superlink-ca.crt"\'`',
817
+ )
818
+
819
+
820
+ def _add_args_simulationio_api(parser: argparse.ArgumentParser) -> None:
821
+ parser.add_argument(
822
+ "--simulationio-api-address",
823
+ help="SimulationIo API (gRPC) server address (IPv4, IPv6, or a domain name).",
824
+ default=SIMULATIONIO_API_DEFAULT_ADDRESS,
825
+ )
@@ -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 init_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