From bfe99655e0c46a579fc0cb9920676913d3c25d5c Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Tue, 22 Nov 2022 19:21:10 +0000 Subject: [PATCH 01/33] update --- MANIFEST.in | 55 ++++++++++++++++++++++ src/lightning_app/core/app.py | 14 +++--- src/lightning_app/runners/multiprocess.py | 2 + src/lightning_app/utilities/app_helpers.py | 13 ----- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index ac8c2556d4f02..ad7764a37ee84 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,3 +5,58 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/core/app.py b/src/lightning_app/core/app.py index 128b6cfb2980f..58fd516eeee9b 100644 --- a/src/lightning_app/core/app.py +++ b/src/lightning_app/core/app.py @@ -27,17 +27,13 @@ from lightning_app.storage import Drive, Path, Payload from lightning_app.storage.path import _storage_root_dir from lightning_app.utilities import frontend -from lightning_app.utilities.app_helpers import ( - _delta_to_app_state_delta, - _LightningAppRef, - _should_dispatch_app, - Logger, -) +from lightning_app.utilities.app_helpers import _delta_to_app_state_delta, _LightningAppRef, Logger from lightning_app.utilities.commands.base import _process_requests from lightning_app.utilities.component import _convert_paths_after_init, _validate_root_flow from lightning_app.utilities.enum import AppStage, CacheCallsKeys from lightning_app.utilities.exceptions import CacheMissException, ExitAppException from lightning_app.utilities.layout import _collect_layout +from lightning_app.utilities.network import find_free_network_port from lightning_app.utilities.proxies import ComponentDelta from lightning_app.utilities.scheduler import SchedulerThread from lightning_app.utilities.tree import breadth_first @@ -59,6 +55,7 @@ def __init__( flow_cloud_compute: Optional["lightning_app.CloudCompute"] = None, log_level: str = "info", info: frontend.AppInfo = None, + debug: bool = False, root_path: str = "", ): """The Lightning App, or App in short runs a tree of one or more components that interact to create end-to-end @@ -169,9 +166,10 @@ def __init__( logger.debug(f"ENV: {os.environ}") - if _should_dispatch_app(): + if debug and not bool(int(os.getenv("LIGHTNING_DISPATCHED", "0"))): os.environ["LIGHTNING_DISPATCHED"] = "1" - from lightning_app.runners import MultiProcessRuntime + os.environ["LIGHTNING_APP_SERVER_PORT"] = str(find_free_network_port()) + from lightning.app.runners import MultiProcessRuntime MultiProcessRuntime(self).dispatch() diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index 8abd0a443ac32..7dfa50547dca5 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -5,6 +5,7 @@ from lightning_app.api.http_methods import _add_tags_to_api, _validate_api from lightning_app.core.api import start_server +from lightning_app.core.constants import APP_SERVER_HOST from lightning_app.runners.backends import Backend from lightning_app.runners.runtime import Runtime from lightning_app.storage.orchestrator import StorageOrchestrator @@ -24,6 +25,7 @@ class MultiProcessRuntime(Runtime): queues to enable communication between the different processes. """ + host: str = "0.0.0.0" if "http://lightningapp" in APP_SERVER_HOST else APP_SERVER_HOST backend: Union[str, Backend] = "multiprocessing" def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwargs: Any): diff --git a/src/lightning_app/utilities/app_helpers.py b/src/lightning_app/utilities/app_helpers.py index d63e33db6addb..a4cebf2b8d9a6 100644 --- a/src/lightning_app/utilities/app_helpers.py +++ b/src/lightning_app/utilities/app_helpers.py @@ -514,16 +514,3 @@ def _mock_missing_imports(): def is_static_method(klass_or_instance, attr) -> bool: return isinstance(inspect.getattr_static(klass_or_instance, attr), staticmethod) - - -def _debugger_is_active() -> bool: - """Return if the debugger is currently active.""" - return hasattr(sys, "gettrace") and sys.gettrace() is not None - - -def _should_dispatch_app() -> bool: - return ( - _debugger_is_active() - and not bool(int(os.getenv("LIGHTNING_DISPATCHED", "0"))) - and "LIGHTNING_APP_STATE_URL" not in os.environ - ) From 926b2dfe8773b9119f73fec7c5665075bc4638c5 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 17:42:16 +0000 Subject: [PATCH 02/33] update --- .storage/boring_file.txt | 5 + MANIFEST.in | 154 ++++++++++++++++++ src/lightning_app/cli/lightning_cli.py | 2 +- src/lightning_app/core/constants.py | 4 +- .../runners/backends/__init__.py | 5 +- .../runners/backends/mp_process.py | 27 +++ src/lightning_app/runners/multiprocess.py | 16 +- src/lightning_app/utilities/cloud.py | 2 +- src/lightning_app/utilities/port.py | 123 ++++++++++++++ 9 files changed, 332 insertions(+), 6 deletions(-) create mode 100644 .storage/boring_file.txt create mode 100644 src/lightning_app/utilities/port.py diff --git a/.storage/boring_file.txt b/.storage/boring_file.txt new file mode 100644 index 0000000000000..2a8574fb54178 --- /dev/null +++ b/.storage/boring_file.txt @@ -0,0 +1,5 @@ + +Hello there! +This tab is currently an IFrame of the FastAPI Server running in `DestinationFileAndServeWork`. +Also, the content of this file was created in `SourceFileWork` and then transferred to `DestinationFileAndServeWork`. +Are you already 🤯 ? Stick with us, this is only the beginning. Lightning is 🚀. diff --git a/MANIFEST.in b/MANIFEST.in index ad7764a37ee84..c4ce963f0edf5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -60,3 +60,157 @@ include src/lightning/app/components/serve/catimage.png prune src/lightning_app prune src/lightning_lite prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/cli/lightning_cli.py b/src/lightning_app/cli/lightning_cli.py index 905581490972d..9f6682bce6a75 100644 --- a/src/lightning_app/cli/lightning_cli.py +++ b/src/lightning_app/cli/lightning_cli.py @@ -54,7 +54,7 @@ def get_app_url(runtime_type: RuntimeType, *args: Any, need_credits: bool = Fals action = "?action=add_credits" if need_credits else "" return f"{get_lightning_cloud_url()}/me/apps/{lit_app.id}{action}" else: - return "http://127.0.0.1:7501/view" + return os.getenv("APP_SERVER_HOST", "http://127.0.0.1:7501/view") def main() -> None: diff --git a/src/lightning_app/core/constants.py b/src/lightning_app/core/constants.py index 4a9cfece63590..8bf2c64876bc8 100644 --- a/src/lightning_app/core/constants.py +++ b/src/lightning_app/core/constants.py @@ -3,6 +3,8 @@ import lightning_cloud.env +from lightning_app.utilities.port import _find_lit_app_port + def get_lightning_cloud_url() -> str: # DO NOT CHANGE! @@ -19,7 +21,7 @@ def get_lightning_cloud_url() -> str: FLOW_DURATION_SAMPLES = 5 APP_SERVER_HOST = os.getenv("LIGHTNING_APP_STATE_URL", "http://127.0.0.1") -APP_SERVER_PORT = 7501 +APP_SERVER_PORT = _find_lit_app_port(7501) APP_STATE_MAX_SIZE_BYTES = 1024 * 1024 # 1 MB CLOUD_QUEUE_TYPE = os.getenv("LIGHTNING_CLOUD_QUEUE_TYPE", None) diff --git a/src/lightning_app/runners/backends/__init__.py b/src/lightning_app/runners/backends/__init__.py index d5bfb0e780c50..4414991a997d8 100644 --- a/src/lightning_app/runners/backends/__init__.py +++ b/src/lightning_app/runners/backends/__init__.py @@ -1,9 +1,10 @@ from enum import Enum +from lightning_app.core.constants import APP_SERVER_HOST from lightning_app.runners.backends.backend import Backend from lightning_app.runners.backends.cloud import CloudBackend from lightning_app.runners.backends.docker import DockerBackend -from lightning_app.runners.backends.mp_process import MultiProcessingBackend +from lightning_app.runners.backends.mp_process import CloudMultiProcessingBackend, MultiProcessingBackend class BackendType(Enum): @@ -13,6 +14,8 @@ class BackendType(Enum): def get_backend(self, entrypoint_file: str) -> "Backend": if self == BackendType.MULTIPROCESSING: + if "http://lightningapp" in APP_SERVER_HOST: + return CloudMultiProcessingBackend(entrypoint_file) return MultiProcessingBackend(entrypoint_file) elif self == BackendType.DOCKER: return DockerBackend(entrypoint_file) diff --git a/src/lightning_app/runners/backends/mp_process.py b/src/lightning_app/runners/backends/mp_process.py index 3ad83aab55341..91b7c8155706c 100644 --- a/src/lightning_app/runners/backends/mp_process.py +++ b/src/lightning_app/runners/backends/mp_process.py @@ -1,4 +1,5 @@ import multiprocessing +import os from typing import List, Optional import lightning_app @@ -6,6 +7,7 @@ from lightning_app.runners.backends.backend import Backend, WorkManager from lightning_app.utilities.enum import WorkStageStatus from lightning_app.utilities.network import _check_service_url_is_ready +from lightning_app.utilities.port import close_port, open_port from lightning_app.utilities.proxies import ProxyWorkRun, WorkRunner @@ -57,6 +59,10 @@ class MultiProcessingBackend(Backend): def __init__(self, entrypoint_file: str): super().__init__(entrypoint_file=entrypoint_file, queues=QueuingSystem.MULTIPROCESS, queue_id="0") + # Note: In case the runtime is used in the cloud. + self.should_open_ports = "http://lightningapp" in os.getenv("LIGHTNING_APP_STATE_URL", "") + self.ports = [] + def create_work(self, app, work) -> None: app.processes[work.name] = MultiProcessWorkManager(app, work) app.processes[work.name].start() @@ -83,3 +89,24 @@ def resolve_url(self, app, base_url: Optional[str] = None) -> None: def stop_work(self, app, work: "lightning_app.LightningWork") -> None: work_manager: MultiProcessWorkManager = app.processes[work.name] work_manager.kill() + + +class CloudMultiProcessingBackend(MultiProcessingBackend): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Note: In case the runtime is used in the cloud. + self.ports = [] + + def create_work(self, app, work) -> None: + work._host = "0.0.0.0" + nc = open_port() + self.ports.append(nc.port) + work._port = nc.port + work._future_url = f"https://{nc.host}" + return super().create_work(app, work) + + def stop_work(self, app, work: "lightning_app.LightningWork") -> None: + close_port(work._port) + self.ports = [port for port in self.ports if port != work._port] + return super().stop_work(app, work) diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index 7dfa50547dca5..b8474a20bb254 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -5,7 +5,6 @@ from lightning_app.api.http_methods import _add_tags_to_api, _validate_api from lightning_app.core.api import start_server -from lightning_app.core.constants import APP_SERVER_HOST from lightning_app.runners.backends import Backend from lightning_app.runners.runtime import Runtime from lightning_app.storage.orchestrator import StorageOrchestrator @@ -14,6 +13,7 @@ from lightning_app.utilities.component import _set_flow_context, _set_frontend_context from lightning_app.utilities.load_app import extract_metadata_from_app from lightning_app.utilities.network import find_free_network_port +from lightning_app.utilities.port import close_port @dataclass @@ -25,7 +25,6 @@ class MultiProcessRuntime(Runtime): queues to enable communication between the different processes. """ - host: str = "0.0.0.0" if "http://lightningapp" in APP_SERVER_HOST else APP_SERVER_HOST backend: Union[str, Backend] = "multiprocessing" def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwargs: Any): @@ -33,6 +32,12 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg try: _set_flow_context() + self.ports = [] + + # Note: In case the runtime is used in the cloud. + self.should_track_port = "http://lightningapp" in self.host + self.host = "0.0.0.0" if self.should_track_port else self.host + self.app.backend = self.backend self.backend._prepare_queues(self.app) self.backend.resolve_url(self.app, "http://127.0.0.1") @@ -111,3 +116,10 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg raise finally: self.terminate() + + def terminate(self): + if self.should_track_port: + ports = [self.port] + self.backend.ports + for port in ports: + close_port(port) + super().terminate() diff --git a/src/lightning_app/utilities/cloud.py b/src/lightning_app/utilities/cloud.py index 20ab6d14827c9..2a9ce415fac66 100644 --- a/src/lightning_app/utilities/cloud.py +++ b/src/lightning_app/utilities/cloud.py @@ -4,9 +4,9 @@ from lightning_cloud.openapi import V1Membership import lightning_app +from lightning.app.utilities.network import LightningClient from lightning_app.core.constants import LIGHTNING_CLOUD_PROJECT_ID from lightning_app.utilities.enum import AppStage -from lightning_app.utilities.network import LightningClient def _get_project(client: LightningClient, project_id: str = LIGHTNING_CLOUD_PROJECT_ID) -> V1Membership: diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py new file mode 100644 index 0000000000000..c28bd8eaa2c6a --- /dev/null +++ b/src/lightning_app/utilities/port.py @@ -0,0 +1,123 @@ +import os +from typing import Optional + +from lightning_cloud.openapi import AppinstancesIdBody, Externalv1LightningappInstance + +from lightning.app.utilities.network import LightningClient + + +def _find_lit_app_port(default_port: int) -> int: + + app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) + project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) + + if not app_id or not project_id: + return default_port + + assert project_id + + client = LightningClient() + list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) + lit_app: Optional[Externalv1LightningappInstance] = None + + for lightningapp in list_apps_resp.lightningapps: + if lightningapp.id == app_id: + lit_app = lightningapp + + assert lit_app + + found_nc = None + + for nc in lit_app.spec.network_config: + if not nc.enable: + found_nc = nc + nc.enable = True + break + + client.lightningapp_instance_service_update_lightningapp_instance( + project_id=project_id, + id=lit_app.id, + body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), + ) + + assert found_nc + + os.environ["APP_SERVER_HOST"] = f"https:/{found_nc.host}" + + return found_nc.port + + +def open_port(): + + app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) + project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) + + if not app_id or not project_id: + raise Exception("The app_id and project_id should be defined.") + + assert project_id + + client = LightningClient() + list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) + lit_app: Optional[Externalv1LightningappInstance] = None + + for lightningapp in list_apps_resp.lightningapps: + if lightningapp.id == app_id: + lit_app = lightningapp + + assert lit_app + + found_nc = None + + for nc in lit_app.spec.network_config: + if not nc.enable: + found_nc = nc + nc.enable = True + break + + client.lightningapp_instance_service_update_lightningapp_instance( + project_id=project_id, + id=lit_app.id, + body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), + ) + + assert found_nc + + return found_nc + + +def close_port(port: int) -> None: + + app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) + project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) + + if not app_id or not project_id: + raise Exception("The app_id and project_id should be defined.") + + assert project_id + + client = LightningClient() + list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) + lit_app: Optional[Externalv1LightningappInstance] = None + + for lightningapp in list_apps_resp.lightningapps: + if lightningapp.id == app_id: + lit_app = lightningapp + + assert lit_app + + found_nc = None + + for nc in lit_app.spec.network_config: + if nc.port == port: + nc.enable = False + found_nc = nc + break + + client.lightningapp_instance_service_update_lightningapp_instance( + project_id=project_id, + id=lit_app.id, + body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), + ) + + assert found_nc From 91fc68367507078bbdc80eb27c9739525da07b80 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 17:57:04 +0000 Subject: [PATCH 03/33] update --- .storage/boring_file.txt | 5 - MANIFEST.in | 209 --------------------------------------- 2 files changed, 214 deletions(-) delete mode 100644 .storage/boring_file.txt diff --git a/.storage/boring_file.txt b/.storage/boring_file.txt deleted file mode 100644 index 2a8574fb54178..0000000000000 --- a/.storage/boring_file.txt +++ /dev/null @@ -1,5 +0,0 @@ - -Hello there! -This tab is currently an IFrame of the FastAPI Server running in `DestinationFileAndServeWork`. -Also, the content of this file was created in `SourceFileWork` and then transferred to `DestinationFileAndServeWork`. -Are you already 🤯 ? Stick with us, this is only the beginning. Lightning is 🚀. diff --git a/MANIFEST.in b/MANIFEST.in index c4ce963f0edf5..ac8c2556d4f02 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,212 +5,3 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning From ef8a5730abed5881bb559cdf63fdf2a674ba023d Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:01:16 +0000 Subject: [PATCH 04/33] update --- src/lightning_app/core/app.py | 2 -- src/lightning_app/runners/backends/mp_process.py | 7 +------ src/lightning_app/runners/multiprocess.py | 3 +-- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/lightning_app/core/app.py b/src/lightning_app/core/app.py index 58fd516eeee9b..cfeaaf901612f 100644 --- a/src/lightning_app/core/app.py +++ b/src/lightning_app/core/app.py @@ -33,7 +33,6 @@ from lightning_app.utilities.enum import AppStage, CacheCallsKeys from lightning_app.utilities.exceptions import CacheMissException, ExitAppException from lightning_app.utilities.layout import _collect_layout -from lightning_app.utilities.network import find_free_network_port from lightning_app.utilities.proxies import ComponentDelta from lightning_app.utilities.scheduler import SchedulerThread from lightning_app.utilities.tree import breadth_first @@ -168,7 +167,6 @@ def __init__( if debug and not bool(int(os.getenv("LIGHTNING_DISPATCHED", "0"))): os.environ["LIGHTNING_DISPATCHED"] = "1" - os.environ["LIGHTNING_APP_SERVER_PORT"] = str(find_free_network_port()) from lightning.app.runners import MultiProcessRuntime MultiProcessRuntime(self).dispatch() diff --git a/src/lightning_app/runners/backends/mp_process.py b/src/lightning_app/runners/backends/mp_process.py index 91b7c8155706c..90b5df9d253f0 100644 --- a/src/lightning_app/runners/backends/mp_process.py +++ b/src/lightning_app/runners/backends/mp_process.py @@ -1,5 +1,4 @@ import multiprocessing -import os from typing import List, Optional import lightning_app @@ -59,10 +58,6 @@ class MultiProcessingBackend(Backend): def __init__(self, entrypoint_file: str): super().__init__(entrypoint_file=entrypoint_file, queues=QueuingSystem.MULTIPROCESS, queue_id="0") - # Note: In case the runtime is used in the cloud. - self.should_open_ports = "http://lightningapp" in os.getenv("LIGHTNING_APP_STATE_URL", "") - self.ports = [] - def create_work(self, app, work) -> None: app.processes[work.name] = MultiProcessWorkManager(app, work) app.processes[work.name].start() @@ -95,7 +90,7 @@ class CloudMultiProcessingBackend(MultiProcessingBackend): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Note: In case the runtime is used in the cloud. + # Note: Track the open ports to close them on termination. self.ports = [] def create_work(self, app, work) -> None: diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index b8474a20bb254..5e22301551a00 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -32,8 +32,6 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg try: _set_flow_context() - self.ports = [] - # Note: In case the runtime is used in the cloud. self.should_track_port = "http://lightningapp" in self.host self.host = "0.0.0.0" if self.should_track_port else self.host @@ -119,6 +117,7 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg def terminate(self): if self.should_track_port: + # Close all the ports open for the App within the App. ports = [self.port] + self.backend.ports for port in ports: close_port(port) From 56c0582fe99d9ced7d5476359e4addc89b4347c9 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:35:50 +0000 Subject: [PATCH 05/33] update --- src/lightning_app/runners/cloud.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lightning_app/runners/cloud.py b/src/lightning_app/runners/cloud.py index af3eca424282d..49905a665f5cc 100644 --- a/src/lightning_app/runners/cloud.py +++ b/src/lightning_app/runners/cloud.py @@ -262,17 +262,17 @@ def dispatch( ) network_configs: Optional[List[V1NetworkConfig]] = None - if ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER: - network_configs = [] - initial_port = 8080 + 1 + len(frontend_specs) - for _ in range(DEFAULT_NUMBER_OF_EXPOSED_PORTS): - network_configs.append( - V1NetworkConfig( - name="w" + str(initial_port), - port=initial_port, - ) + + network_configs = [] + initial_port = 8080 + 1 + len(frontend_specs) + for _ in range(DEFAULT_NUMBER_OF_EXPOSED_PORTS): + network_configs.append( + V1NetworkConfig( + name="w" + str(initial_port), + port=initial_port, ) - initial_port += 1 + ) + initial_port += 1 # check if user has sufficient credits to run an app # if so set the desired state to running otherwise, create the app in stopped state, From 0a2add5d56e8821838e47a3b41115d139387e442 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:36:44 +0000 Subject: [PATCH 06/33] update --- src/lightning_app/utilities/port.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index c28bd8eaa2c6a..d49af0db28b8d 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -3,7 +3,7 @@ from lightning_cloud.openapi import AppinstancesIdBody, Externalv1LightningappInstance -from lightning.app.utilities.network import LightningClient +from lightning_app.utilities.network import LightningClient def _find_lit_app_port(default_port: int) -> int: From 8fc0e417b8c0e6a4ac22b4cf02c321d6d6626262 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:37:18 +0000 Subject: [PATCH 07/33] update --- src/lightning_app/runners/cloud.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lightning_app/runners/cloud.py b/src/lightning_app/runners/cloud.py index 49905a665f5cc..71b6387b913ed 100644 --- a/src/lightning_app/runners/cloud.py +++ b/src/lightning_app/runners/cloud.py @@ -261,9 +261,7 @@ def dispatch( project_id=project.project_id, body=app_body ) - network_configs: Optional[List[V1NetworkConfig]] = None - - network_configs = [] + network_configs: List[V1NetworkConfig] = [] initial_port = 8080 + 1 + len(frontend_specs) for _ in range(DEFAULT_NUMBER_OF_EXPOSED_PORTS): network_configs.append( From 3a9ca9d5fc0926594c241dafb4df90bebeb399ad Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:38:52 +0000 Subject: [PATCH 08/33] update --- src/lightning_app/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lightning_app/CHANGELOG.md b/src/lightning_app/CHANGELOG.md index 5673fcadf48d0..cdb3ab73567fc 100644 --- a/src/lightning_app/CHANGELOG.md +++ b/src/lightning_app/CHANGELOG.md @@ -11,6 +11,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added the CLI command `lightning run model` to launch a `LightningLite` accelerated script ([#15506](https://github.com/Lightning-AI/lightning/pull/15506)) +- Added the CloudMultiProcessBackend to run an children App within the Flow in the cloud ([#15800](https://github.com/Lightning-AI/lightning/pull/15800)) + + ### Changed - `lightning add ssh-key` CLI command has been transitioned to `lightning create ssh-key` with the same calling signature ([#15761](https://github.com/Lightning-AI/lightning/pull/15761)) From 0cd3acf77986f9bd67cef9aa8be802af2337c9f8 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:40:19 +0000 Subject: [PATCH 09/33] update --- src/lightning_app/cli/lightning_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lightning_app/cli/lightning_cli.py b/src/lightning_app/cli/lightning_cli.py index 9f6682bce6a75..905581490972d 100644 --- a/src/lightning_app/cli/lightning_cli.py +++ b/src/lightning_app/cli/lightning_cli.py @@ -54,7 +54,7 @@ def get_app_url(runtime_type: RuntimeType, *args: Any, need_credits: bool = Fals action = "?action=add_credits" if need_credits else "" return f"{get_lightning_cloud_url()}/me/apps/{lit_app.id}{action}" else: - return os.getenv("APP_SERVER_HOST", "http://127.0.0.1:7501/view") + return "http://127.0.0.1:7501/view" def main() -> None: From 496d13978d78b65826afc75b08b6df87b1e531a7 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:41:40 +0000 Subject: [PATCH 10/33] update --- src/lightning_app/cli/lightning_cli.py | 2 +- src/lightning_app/core/app.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/lightning_app/cli/lightning_cli.py b/src/lightning_app/cli/lightning_cli.py index 905581490972d..9f6682bce6a75 100644 --- a/src/lightning_app/cli/lightning_cli.py +++ b/src/lightning_app/cli/lightning_cli.py @@ -54,7 +54,7 @@ def get_app_url(runtime_type: RuntimeType, *args: Any, need_credits: bool = Fals action = "?action=add_credits" if need_credits else "" return f"{get_lightning_cloud_url()}/me/apps/{lit_app.id}{action}" else: - return "http://127.0.0.1:7501/view" + return os.getenv("APP_SERVER_HOST", "http://127.0.0.1:7501/view") def main() -> None: diff --git a/src/lightning_app/core/app.py b/src/lightning_app/core/app.py index cfeaaf901612f..128b6cfb2980f 100644 --- a/src/lightning_app/core/app.py +++ b/src/lightning_app/core/app.py @@ -27,7 +27,12 @@ from lightning_app.storage import Drive, Path, Payload from lightning_app.storage.path import _storage_root_dir from lightning_app.utilities import frontend -from lightning_app.utilities.app_helpers import _delta_to_app_state_delta, _LightningAppRef, Logger +from lightning_app.utilities.app_helpers import ( + _delta_to_app_state_delta, + _LightningAppRef, + _should_dispatch_app, + Logger, +) from lightning_app.utilities.commands.base import _process_requests from lightning_app.utilities.component import _convert_paths_after_init, _validate_root_flow from lightning_app.utilities.enum import AppStage, CacheCallsKeys @@ -54,7 +59,6 @@ def __init__( flow_cloud_compute: Optional["lightning_app.CloudCompute"] = None, log_level: str = "info", info: frontend.AppInfo = None, - debug: bool = False, root_path: str = "", ): """The Lightning App, or App in short runs a tree of one or more components that interact to create end-to-end @@ -165,9 +169,9 @@ def __init__( logger.debug(f"ENV: {os.environ}") - if debug and not bool(int(os.getenv("LIGHTNING_DISPATCHED", "0"))): + if _should_dispatch_app(): os.environ["LIGHTNING_DISPATCHED"] = "1" - from lightning.app.runners import MultiProcessRuntime + from lightning_app.runners import MultiProcessRuntime MultiProcessRuntime(self).dispatch() From 7c08b9a5d2777fe65df40cead8ef821b863f953c Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:44:13 +0000 Subject: [PATCH 11/33] update --- MANIFEST.in | 33 ++++++++++++++++++++++ src/lightning_app/utilities/app_helpers.py | 13 +++++++++ 2 files changed, 46 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index ac8c2556d4f02..eb5d5802756bc 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,3 +5,36 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/utilities/app_helpers.py b/src/lightning_app/utilities/app_helpers.py index a4cebf2b8d9a6..d63e33db6addb 100644 --- a/src/lightning_app/utilities/app_helpers.py +++ b/src/lightning_app/utilities/app_helpers.py @@ -514,3 +514,16 @@ def _mock_missing_imports(): def is_static_method(klass_or_instance, attr) -> bool: return isinstance(inspect.getattr_static(klass_or_instance, attr), staticmethod) + + +def _debugger_is_active() -> bool: + """Return if the debugger is currently active.""" + return hasattr(sys, "gettrace") and sys.gettrace() is not None + + +def _should_dispatch_app() -> bool: + return ( + _debugger_is_active() + and not bool(int(os.getenv("LIGHTNING_DISPATCHED", "0"))) + and "LIGHTNING_APP_STATE_URL" not in os.environ + ) From ddd1b19948af27db81e7c4ae20bd9ff7343f2e8e Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:44:54 +0000 Subject: [PATCH 12/33] update --- MANIFEST.in | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index eb5d5802756bc..ac8c2556d4f02 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,36 +5,3 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning From 6ea46c3a18ddc365459fb5fc1ac0f9b9a2d12044 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:46:50 +0000 Subject: [PATCH 13/33] update --- src/lightning_app/core/constants.py | 1 + src/lightning_app/runners/backends/__init__.py | 4 ++-- src/lightning_app/runners/multiprocess.py | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lightning_app/core/constants.py b/src/lightning_app/core/constants.py index 8bf2c64876bc8..d116e11af015c 100644 --- a/src/lightning_app/core/constants.py +++ b/src/lightning_app/core/constants.py @@ -21,6 +21,7 @@ def get_lightning_cloud_url() -> str: FLOW_DURATION_SAMPLES = 5 APP_SERVER_HOST = os.getenv("LIGHTNING_APP_STATE_URL", "http://127.0.0.1") +APP_SERVER_IN_CLOUD = "http://lightningapp" in APP_SERVER_HOST APP_SERVER_PORT = _find_lit_app_port(7501) APP_STATE_MAX_SIZE_BYTES = 1024 * 1024 # 1 MB diff --git a/src/lightning_app/runners/backends/__init__.py b/src/lightning_app/runners/backends/__init__.py index 4414991a997d8..51d68a678a5d5 100644 --- a/src/lightning_app/runners/backends/__init__.py +++ b/src/lightning_app/runners/backends/__init__.py @@ -1,6 +1,6 @@ from enum import Enum -from lightning_app.core.constants import APP_SERVER_HOST +from lightning_app.core.constants import APP_SERVER_IN_CLOUD from lightning_app.runners.backends.backend import Backend from lightning_app.runners.backends.cloud import CloudBackend from lightning_app.runners.backends.docker import DockerBackend @@ -14,7 +14,7 @@ class BackendType(Enum): def get_backend(self, entrypoint_file: str) -> "Backend": if self == BackendType.MULTIPROCESSING: - if "http://lightningapp" in APP_SERVER_HOST: + if APP_SERVER_IN_CLOUD: return CloudMultiProcessingBackend(entrypoint_file) return MultiProcessingBackend(entrypoint_file) elif self == BackendType.DOCKER: diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index 5e22301551a00..0eedc5114746d 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -5,6 +5,7 @@ from lightning_app.api.http_methods import _add_tags_to_api, _validate_api from lightning_app.core.api import start_server +from lightning_app.core.constants import APP_SERVER_IN_CLOUD from lightning_app.runners.backends import Backend from lightning_app.runners.runtime import Runtime from lightning_app.storage.orchestrator import StorageOrchestrator @@ -33,8 +34,7 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg _set_flow_context() # Note: In case the runtime is used in the cloud. - self.should_track_port = "http://lightningapp" in self.host - self.host = "0.0.0.0" if self.should_track_port else self.host + self.host = "0.0.0.0" if APP_SERVER_IN_CLOUD else self.host self.app.backend = self.backend self.backend._prepare_queues(self.app) @@ -116,7 +116,7 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg self.terminate() def terminate(self): - if self.should_track_port: + if APP_SERVER_IN_CLOUD: # Close all the ports open for the App within the App. ports = [self.port] + self.backend.ports for port in ports: From 7c476d384a410ce312af2adbf4ee2f39eb088aab Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 18:50:27 +0000 Subject: [PATCH 14/33] update --- src/lightning_app/utilities/cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lightning_app/utilities/cloud.py b/src/lightning_app/utilities/cloud.py index 2a9ce415fac66..20ab6d14827c9 100644 --- a/src/lightning_app/utilities/cloud.py +++ b/src/lightning_app/utilities/cloud.py @@ -4,9 +4,9 @@ from lightning_cloud.openapi import V1Membership import lightning_app -from lightning.app.utilities.network import LightningClient from lightning_app.core.constants import LIGHTNING_CLOUD_PROJECT_ID from lightning_app.utilities.enum import AppStage +from lightning_app.utilities.network import LightningClient def _get_project(client: LightningClient, project_id: str = LIGHTNING_CLOUD_PROJECT_ID) -> V1Membership: From c869442e998d1750e35cf5aec434507bad8e014b Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 19:09:59 +0000 Subject: [PATCH 15/33] updte --- pyproject.toml | 1 + src/lightning_app/core/constants.py | 7 ++++--- src/lightning_app/runners/cloud.py | 24 +++++++++++++----------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5e8a2bfa0e481..cf7adf6036610 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -139,6 +139,7 @@ module = [ "lightning_app.utilities.packaging.cloud_compute", "lightning_app.utilities.packaging.docker", "lightning_app.utilities.packaging.lightning_utils", + "lightning_app.utilities.port", "lightning_app.utilities.proxies", "lightning_app.utilities.scheduler", "lightning_app.utilities.state", diff --git a/src/lightning_app/core/constants.py b/src/lightning_app/core/constants.py index d116e11af015c..4038c85e7fc1e 100644 --- a/src/lightning_app/core/constants.py +++ b/src/lightning_app/core/constants.py @@ -55,9 +55,6 @@ def get_lightning_cloud_url() -> str: # EXPERIMENTAL: ENV VARIABLES TO ENABLE MULTIPLE WORKS IN THE SAME MACHINE DEFAULT_NUMBER_OF_EXPOSED_PORTS = int(os.getenv("DEFAULT_NUMBER_OF_EXPOSED_PORTS", "50")) -ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER = bool( - int(os.getenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "0")) -) # Note: This is disabled for the time being. ENABLE_MULTIPLE_WORKS_IN_NON_DEFAULT_CONTAINER = bool( int(os.getenv("ENABLE_MULTIPLE_WORKS_IN_NON_DEFAULT_CONTAINER", "0")) ) # This isn't used in the cloud yet. @@ -74,3 +71,7 @@ def get_lightning_cloud_url() -> str: ) ENABLE_STATE_WEBSOCKET = bool(int(os.getenv("ENABLE_STATE_WEBSOCKET", "0"))) ENABLE_UPLOAD_ENDPOINT = bool(int(os.getenv("ENABLE_UPLOAD_ENDPOINT", "1"))) + + +def enable_multiple_works_in_default_container() -> bool: + return bool(int(os.getenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "0"))) diff --git a/src/lightning_app/runners/cloud.py b/src/lightning_app/runners/cloud.py index c2a96b5b2be34..806378f53dda6 100644 --- a/src/lightning_app/runners/cloud.py +++ b/src/lightning_app/runners/cloud.py @@ -51,7 +51,7 @@ DEFAULT_NUMBER_OF_EXPOSED_PORTS, DISABLE_DEPENDENCY_CACHE, ENABLE_APP_COMMENT_COMMAND_EXECUTION, - ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER, + enable_multiple_works_in_default_container, ENABLE_MULTIPLE_WORKS_IN_NON_DEFAULT_CONTAINER, ENABLE_PULLING_STATE_ENDPOINT, ENABLE_PUSHING_STATE_ENDPOINT, @@ -243,7 +243,7 @@ def dispatch( if self.run_app_comment_commands or ENABLE_APP_COMMENT_COMMAND_EXECUTION: v1_env_vars.append(V1EnvVar(name="ENABLE_APP_COMMENT_COMMAND_EXECUTION", value="1")) - if ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER: + if enable_multiple_works_in_default_container(): v1_env_vars.append(V1EnvVar(name="ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", value="1")) if ENABLE_MULTIPLE_WORKS_IN_NON_DEFAULT_CONTAINER: @@ -302,16 +302,18 @@ def dispatch( project_id=project.project_id, body=app_body ) - network_configs: List[V1NetworkConfig] = [] - initial_port = 8080 + 1 + len(frontend_specs) - for _ in range(DEFAULT_NUMBER_OF_EXPOSED_PORTS): - network_configs.append( - V1NetworkConfig( - name="w" + str(initial_port), - port=initial_port, + network_configs: Optional[List[V1NetworkConfig]] = None + if enable_multiple_works_in_default_container(): + network_configs = [] + initial_port = 8080 + 1 + len(frontend_specs) + for _ in range(DEFAULT_NUMBER_OF_EXPOSED_PORTS): + network_configs.append( + V1NetworkConfig( + name="w" + str(initial_port), + port=initial_port, + ) ) - ) - initial_port += 1 + initial_port += 1 # check if user has sufficient credits to run an app # if so set the desired state to running otherwise, create the app in stopped state, From d8fa7d54b68d8e119057826c78541df39cc77a75 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 19:15:18 +0000 Subject: [PATCH 16/33] update --- src/lightning_app/utilities/port.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index d49af0db28b8d..522a37535dd79 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -7,11 +7,13 @@ def _find_lit_app_port(default_port: int) -> int: + """Make a request to the cloud controlplane to find a disabled port of the flow, enable it and return it.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) + enable_multiple_works_in_default_container = bool(int(os.getenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "0"))) - if not app_id or not project_id: + if not app_id or not project_id or not enable_multiple_works_in_default_container: return default_port assert project_id @@ -42,13 +44,14 @@ def _find_lit_app_port(default_port: int) -> int: assert found_nc + # Note: This is required for the framework to know we need to use the CloudMultiProcessRuntime. os.environ["APP_SERVER_HOST"] = f"https:/{found_nc.host}" return found_nc.port def open_port(): - + """Make a request to the cloud controlplane to open a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) @@ -87,6 +90,7 @@ def open_port(): def close_port(port: int) -> None: + """Make a request to the cloud controlplane to close a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) From 0be01195fd18e0cf8109633e38b74daac8d5e828 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 19:39:16 +0000 Subject: [PATCH 17/33] update --- src/lightning_app/utilities/port.py | 17 +++- tests/tests_app/utilities/test_port.py | 109 +++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 tests/tests_app/utilities/test_port.py diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 522a37535dd79..613010fec4ca3 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -1,7 +1,7 @@ import os from typing import Optional -from lightning_cloud.openapi import AppinstancesIdBody, Externalv1LightningappInstance +from lightning_cloud.openapi import AppinstancesIdBody, Externalv1LightningappInstance, V1NetworkConfig from lightning_app.utilities.network import LightningClient @@ -42,7 +42,8 @@ def _find_lit_app_port(default_port: int) -> int: body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), ) - assert found_nc + if not found_nc: + raise RuntimeError("No available port was found. Please, contact the Lightning Team.") # Note: This is required for the framework to know we need to use the CloudMultiProcessRuntime. os.environ["APP_SERVER_HOST"] = f"https:/{found_nc.host}" @@ -50,7 +51,7 @@ def _find_lit_app_port(default_port: int) -> int: return found_nc.port -def open_port(): +def open_port() -> V1NetworkConfig: """Make a request to the cloud controlplane to open a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) @@ -84,7 +85,8 @@ def open_port(): body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), ) - assert found_nc + if not found_nc: + raise RuntimeError("No available port was found. Please, contact the Lightning Team.") return found_nc @@ -114,6 +116,9 @@ def close_port(port: int) -> None: for nc in lit_app.spec.network_config: if nc.port == port: + if not nc.enable: + raise RuntimeError(f"The port {port} was already disabled.") + nc.enable = False found_nc = nc break @@ -124,4 +129,8 @@ def close_port(port: int) -> None: body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec), ) + if not found_nc: + ports = [nc.port for nc in lit_app.spec.network_config] + raise ValueError(f"The provided port doesn't exists. Available ports are {ports}.") + assert found_nc diff --git a/tests/tests_app/utilities/test_port.py b/tests/tests_app/utilities/test_port.py new file mode 100644 index 0000000000000..c50a873bb626c --- /dev/null +++ b/tests/tests_app/utilities/test_port.py @@ -0,0 +1,109 @@ +from unittest.mock import MagicMock + +import pytest +from lightning_cloud.openapi import V1NetworkConfig + +from lightning_app.utilities import port +from lightning_app.utilities.port import _find_lit_app_port, close_port, open_port + + +def test_find_lit_app_port(monkeypatch): + client = MagicMock() + monkeypatch.setattr(port, "LightningClient", MagicMock(return_value=client)) + + assert 5701 == _find_lit_app_port(5701) + + resp = MagicMock() + lit_app = MagicMock() + lit_app.id = "a" + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=False), + ] + resp.lightningapps = [lit_app] + client.lightningapp_instance_service_list_lightningapp_instances.return_value = resp + + monkeypatch.setenv("LIGHTNING_CLOUD_APP_ID", "a") + monkeypatch.setenv("LIGHTNING_CLOUD_PROJECT_ID", "a") + monkeypatch.setenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "1") + + assert _find_lit_app_port(5701) == 1 + + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=True), + ] + + with pytest.raises(RuntimeError, match="No available port was found. Please, contact the Lightning Team."): + _find_lit_app_port(5701) + + +def test_open_port(monkeypatch): + client = MagicMock() + monkeypatch.setattr(port, "LightningClient", MagicMock(return_value=client)) + + assert 5701 == _find_lit_app_port(5701) + + resp = MagicMock() + lit_app = MagicMock() + lit_app.id = "a" + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=False), + ] + resp.lightningapps = [lit_app] + client.lightningapp_instance_service_list_lightningapp_instances.return_value = resp + + monkeypatch.setenv("LIGHTNING_CLOUD_APP_ID", "a") + monkeypatch.setenv("LIGHTNING_CLOUD_PROJECT_ID", "a") + monkeypatch.setenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "1") + + assert open_port() + + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=True), + ] + + with pytest.raises(RuntimeError, match="No available port was found. Please, contact the Lightning Team."): + assert open_port() + + +def test_close_port(monkeypatch): + client = MagicMock() + monkeypatch.setattr(port, "LightningClient", MagicMock(return_value=client)) + + assert 5701 == _find_lit_app_port(5701) + + resp = MagicMock() + lit_app = MagicMock() + lit_app.id = "a" + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=False), + ] + resp.lightningapps = [lit_app] + client.lightningapp_instance_service_list_lightningapp_instances.return_value = resp + + monkeypatch.setenv("LIGHTNING_CLOUD_APP_ID", "a") + monkeypatch.setenv("LIGHTNING_CLOUD_PROJECT_ID", "a") + monkeypatch.setenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "1") + + close_port(0) + assert not lit_app.spec.network_config[0].enable + + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=False), + ] + + with pytest.raises(RuntimeError, match="The port 1 was already disabled."): + close_port(1) + + lit_app.spec.network_config = [ + V1NetworkConfig(host="a", port=0, enable=True), + V1NetworkConfig(host="a", port=1, enable=False), + ] + + with pytest.raises(ValueError, match="[0, 1]"): + assert close_port(10) From e50204bc449a1a39b4888b3d4bec1ee62d43e16b Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 22:56:41 +0000 Subject: [PATCH 18/33] update --- MANIFEST.in | 11 +++++++++++ src/lightning_app/runners/backends/mp_process.py | 6 +++--- src/lightning_app/runners/multiprocess.py | 4 ++-- src/lightning_app/utilities/port.py | 6 +++--- tests/tests_app/utilities/test_port.py | 16 ++++++++-------- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index ac8c2556d4f02..02660c0d076e5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,3 +5,14 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/runners/backends/mp_process.py b/src/lightning_app/runners/backends/mp_process.py index 90b5df9d253f0..36a067d0bfd80 100644 --- a/src/lightning_app/runners/backends/mp_process.py +++ b/src/lightning_app/runners/backends/mp_process.py @@ -6,7 +6,7 @@ from lightning_app.runners.backends.backend import Backend, WorkManager from lightning_app.utilities.enum import WorkStageStatus from lightning_app.utilities.network import _check_service_url_is_ready -from lightning_app.utilities.port import close_port, open_port +from lightning_app.utilities.port import disable_port, enable_port from lightning_app.utilities.proxies import ProxyWorkRun, WorkRunner @@ -95,13 +95,13 @@ def __init__(self, *args, **kwargs): def create_work(self, app, work) -> None: work._host = "0.0.0.0" - nc = open_port() + nc = enable_port() self.ports.append(nc.port) work._port = nc.port work._future_url = f"https://{nc.host}" return super().create_work(app, work) def stop_work(self, app, work: "lightning_app.LightningWork") -> None: - close_port(work._port) + disable_port(work._port) self.ports = [port for port in self.ports if port != work._port] return super().stop_work(app, work) diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index 0eedc5114746d..fd4ddbf0ceccd 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -14,7 +14,7 @@ from lightning_app.utilities.component import _set_flow_context, _set_frontend_context from lightning_app.utilities.load_app import extract_metadata_from_app from lightning_app.utilities.network import find_free_network_port -from lightning_app.utilities.port import close_port +from lightning_app.utilities.port import disable_port @dataclass @@ -120,5 +120,5 @@ def terminate(self): # Close all the ports open for the App within the App. ports = [self.port] + self.backend.ports for port in ports: - close_port(port) + disable_port(port) super().terminate() diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 613010fec4ca3..070a541d2ecf6 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -51,7 +51,7 @@ def _find_lit_app_port(default_port: int) -> int: return found_nc.port -def open_port() -> V1NetworkConfig: +def enable_port() -> V1NetworkConfig: """Make a request to the cloud controlplane to open a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None) @@ -91,7 +91,7 @@ def open_port() -> V1NetworkConfig: return found_nc -def close_port(port: int) -> None: +def disable_port(port: int, ignore_closed: bool = True) -> None: """Make a request to the cloud controlplane to close a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) @@ -116,7 +116,7 @@ def close_port(port: int) -> None: for nc in lit_app.spec.network_config: if nc.port == port: - if not nc.enable: + if not nc.enable and not ignore_closed: raise RuntimeError(f"The port {port} was already disabled.") nc.enable = False diff --git a/tests/tests_app/utilities/test_port.py b/tests/tests_app/utilities/test_port.py index c50a873bb626c..ea94fad48afa6 100644 --- a/tests/tests_app/utilities/test_port.py +++ b/tests/tests_app/utilities/test_port.py @@ -4,7 +4,7 @@ from lightning_cloud.openapi import V1NetworkConfig from lightning_app.utilities import port -from lightning_app.utilities.port import _find_lit_app_port, close_port, open_port +from lightning_app.utilities.port import _find_lit_app_port, disable_port, enable_port def test_find_lit_app_port(monkeypatch): @@ -38,7 +38,7 @@ def test_find_lit_app_port(monkeypatch): _find_lit_app_port(5701) -def test_open_port(monkeypatch): +def test_enable_port(monkeypatch): client = MagicMock() monkeypatch.setattr(port, "LightningClient", MagicMock(return_value=client)) @@ -58,7 +58,7 @@ def test_open_port(monkeypatch): monkeypatch.setenv("LIGHTNING_CLOUD_PROJECT_ID", "a") monkeypatch.setenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "1") - assert open_port() + assert enable_port() lit_app.spec.network_config = [ V1NetworkConfig(host="a", port=0, enable=True), @@ -66,10 +66,10 @@ def test_open_port(monkeypatch): ] with pytest.raises(RuntimeError, match="No available port was found. Please, contact the Lightning Team."): - assert open_port() + assert enable_port() -def test_close_port(monkeypatch): +def test_disable_port(monkeypatch): client = MagicMock() monkeypatch.setattr(port, "LightningClient", MagicMock(return_value=client)) @@ -89,7 +89,7 @@ def test_close_port(monkeypatch): monkeypatch.setenv("LIGHTNING_CLOUD_PROJECT_ID", "a") monkeypatch.setenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "1") - close_port(0) + disable_port(0) assert not lit_app.spec.network_config[0].enable lit_app.spec.network_config = [ @@ -98,7 +98,7 @@ def test_close_port(monkeypatch): ] with pytest.raises(RuntimeError, match="The port 1 was already disabled."): - close_port(1) + disable_port(1, ignore_closed=False) lit_app.spec.network_config = [ V1NetworkConfig(host="a", port=0, enable=True), @@ -106,4 +106,4 @@ def test_close_port(monkeypatch): ] with pytest.raises(ValueError, match="[0, 1]"): - assert close_port(10) + assert disable_port(10) From 982c03595cbeea49a31638f96921097127b5dbe9 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Wed, 23 Nov 2022 22:58:13 +0000 Subject: [PATCH 19/33] update --- MANIFEST.in | 11 +++++++++++ src/lightning_app/utilities/port.py | 4 ++-- tests/tests_app/utilities/test_port.py | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 02660c0d076e5..9dde003a6b7a0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,3 +16,14 @@ include src/lightning/app/components/serve/catimage.png prune src/lightning_app prune src/lightning_lite prune src/pytorch_lightning +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 070a541d2ecf6..5984dfa98d070 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -91,7 +91,7 @@ def enable_port() -> V1NetworkConfig: return found_nc -def disable_port(port: int, ignore_closed: bool = True) -> None: +def disable_port(port: int, ignore_disabled: bool = True) -> None: """Make a request to the cloud controlplane to close a port of the flow.""" app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None) @@ -116,7 +116,7 @@ def disable_port(port: int, ignore_closed: bool = True) -> None: for nc in lit_app.spec.network_config: if nc.port == port: - if not nc.enable and not ignore_closed: + if not nc.enable and not ignore_disabled: raise RuntimeError(f"The port {port} was already disabled.") nc.enable = False diff --git a/tests/tests_app/utilities/test_port.py b/tests/tests_app/utilities/test_port.py index ea94fad48afa6..1494af8fb9f4e 100644 --- a/tests/tests_app/utilities/test_port.py +++ b/tests/tests_app/utilities/test_port.py @@ -98,7 +98,7 @@ def test_disable_port(monkeypatch): ] with pytest.raises(RuntimeError, match="The port 1 was already disabled."): - disable_port(1, ignore_closed=False) + disable_port(1, ignore_disabled=False) lit_app.spec.network_config = [ V1NetworkConfig(host="a", port=0, enable=True), From 9ff083da0bcb8b008c956b8cb3ad050ea8a07c1e Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 09:21:39 +0000 Subject: [PATCH 20/33] update --- MANIFEST.in | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 9dde003a6b7a0..ac8c2556d4f02 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,25 +5,3 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning From ddfab6ff5c940fa06b6aa779b8333ace7c1e1c93 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 10:57:09 +0000 Subject: [PATCH 21/33] update --- MANIFEST.in | 11 +++++++++++ src/lightning_app/utilities/port.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index ac8c2556d4f02..02660c0d076e5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,3 +5,14 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 5984dfa98d070..4e29d5959c5ed 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -46,7 +46,7 @@ def _find_lit_app_port(default_port: int) -> int: raise RuntimeError("No available port was found. Please, contact the Lightning Team.") # Note: This is required for the framework to know we need to use the CloudMultiProcessRuntime. - os.environ["APP_SERVER_HOST"] = f"https:/{found_nc.host}" + os.environ["APP_SERVER_HOST"] = f"https://{found_nc.host}" return found_nc.port From 51004a8365fa1a4bc8c69c1f337e6a8257327077 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 10:58:21 +0000 Subject: [PATCH 22/33] update --- src/lightning_app/utilities/port.py | 8 ++++++-- tests/tests_app/utilities/test_port.py | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 4e29d5959c5ed..7722b7a7f50eb 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -43,7 +43,9 @@ def _find_lit_app_port(default_port: int) -> int: ) if not found_nc: - raise RuntimeError("No available port was found. Please, contact the Lightning Team.") + raise RuntimeError( + "No available port was found. Please open an issue at https://github.com/lightning-AI/lightning/issues." + ) # Note: This is required for the framework to know we need to use the CloudMultiProcessRuntime. os.environ["APP_SERVER_HOST"] = f"https://{found_nc.host}" @@ -86,7 +88,9 @@ def enable_port() -> V1NetworkConfig: ) if not found_nc: - raise RuntimeError("No available port was found. Please, contact the Lightning Team.") + raise RuntimeError( + "No available port was found. Please open an issue at https://github.com/lightning-AI/lightning/issues." + ) return found_nc diff --git a/tests/tests_app/utilities/test_port.py b/tests/tests_app/utilities/test_port.py index 1494af8fb9f4e..c371fe057e1bd 100644 --- a/tests/tests_app/utilities/test_port.py +++ b/tests/tests_app/utilities/test_port.py @@ -34,7 +34,7 @@ def test_find_lit_app_port(monkeypatch): V1NetworkConfig(host="a", port=1, enable=True), ] - with pytest.raises(RuntimeError, match="No available port was found. Please, contact the Lightning Team."): + with pytest.raises(RuntimeError, match="No available port was found. Please"): _find_lit_app_port(5701) @@ -65,7 +65,7 @@ def test_enable_port(monkeypatch): V1NetworkConfig(host="a", port=1, enable=True), ] - with pytest.raises(RuntimeError, match="No available port was found. Please, contact the Lightning Team."): + with pytest.raises(RuntimeError, match="No available port was found. Please"): assert enable_port() From a4ca231a6e769575b19288f4c65a8e3972d4abdd Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:00:05 +0000 Subject: [PATCH 23/33] update --- MANIFEST.in | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 02660c0d076e5..ac8c2556d4f02 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,14 +5,3 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning From f82ad0f80081c77ea3366950100d8925a6c1e597 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:03:25 +0000 Subject: [PATCH 24/33] update --- src/lightning_app/runners/multiprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lightning_app/runners/multiprocess.py b/src/lightning_app/runners/multiprocess.py index fd4ddbf0ceccd..1f7e0b906ba4b 100644 --- a/src/lightning_app/runners/multiprocess.py +++ b/src/lightning_app/runners/multiprocess.py @@ -118,7 +118,7 @@ def dispatch(self, *args: Any, on_before_run: Optional[Callable] = None, **kwarg def terminate(self): if APP_SERVER_IN_CLOUD: # Close all the ports open for the App within the App. - ports = [self.port] + self.backend.ports + ports = [self.port] + getattr(self.backend, "ports", []) for port in ports: disable_port(port) super().terminate() From 9e282b2cccd1fe549a164abe17fc859ad7874a77 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:15:38 +0000 Subject: [PATCH 25/33] update --- MANIFEST.in | 11 +++++++++++ src/lightning_app/core/app.py | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index ac8c2556d4f02..02660c0d076e5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,3 +5,14 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info +recursive-include src/lightning *.md +recursive-include requirements *.txt +recursive-include src/lightning/app/ui * +recursive-include src/lightning/cli/*-template * +include src/lightning/version.info + +include src/lightning/app/components/serve/catimage.png + +prune src/lightning_app +prune src/lightning_lite +prune src/pytorch_lightning diff --git a/src/lightning_app/core/app.py b/src/lightning_app/core/app.py index 128b6cfb2980f..ce1e81d57d9ea 100644 --- a/src/lightning_app/core/app.py +++ b/src/lightning_app/core/app.py @@ -138,6 +138,7 @@ def __init__( self._schedules: Dict[str, Dict] = {} self.threads: List[threading.Thread] = [] self.exception = None + self.collect_changes: bool = True # NOTE: Checkpointing is disabled by default for the time being. We # will enable it when resuming from full checkpoint is supported. Also, @@ -362,11 +363,14 @@ def _collect_deltas_from_ui_and_work_queues(self) -> List[Union[Delta, _APIReque delta.raise_errors = False return deltas - def maybe_apply_changes(self) -> bool: + def maybe_apply_changes(self) -> None: """Get the deltas from both the flow queue and the work queue, merge the two deltas and update the state.""" self._send_flow_to_work_deltas(self.state) + if not self.collect_changes: + return None + deltas = self._collect_deltas_from_ui_and_work_queues() if not deltas: From c39510dff0eadb64dae5e6d32ec6a09f6043661c Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:16:06 +0000 Subject: [PATCH 26/33] update --- MANIFEST.in | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 02660c0d076e5..ac8c2556d4f02 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,14 +5,3 @@ include .actions/setup_tools.py include .actions/assistant.py include src/version.info include *.cff # citation info -recursive-include src/lightning *.md -recursive-include requirements *.txt -recursive-include src/lightning/app/ui * -recursive-include src/lightning/cli/*-template * -include src/lightning/version.info - -include src/lightning/app/components/serve/catimage.png - -prune src/lightning_app -prune src/lightning_lite -prune src/pytorch_lightning From 41317b662844924982a6121389a1b748ff910682 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:04 +0000 Subject: [PATCH 27/33] Update src/lightning_app/CHANGELOG.md Co-authored-by: Ethan Harris --- src/lightning_app/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lightning_app/CHANGELOG.md b/src/lightning_app/CHANGELOG.md index cdb3ab73567fc..04a4b11e3c89b 100644 --- a/src/lightning_app/CHANGELOG.md +++ b/src/lightning_app/CHANGELOG.md @@ -11,7 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added the CLI command `lightning run model` to launch a `LightningLite` accelerated script ([#15506](https://github.com/Lightning-AI/lightning/pull/15506)) -- Added the CloudMultiProcessBackend to run an children App within the Flow in the cloud ([#15800](https://github.com/Lightning-AI/lightning/pull/15800)) +- Added a CloudMultiProcessBackend which enables running a child App from within the Flow in the cloud ([#15800](https://github.com/Lightning-AI/lightning/pull/15800)) ### Changed From 16e57389a43a571dfc22c014aaa68abbe4cc9ec1 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:12 +0000 Subject: [PATCH 28/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 7722b7a7f50eb..4059ea79bd166 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -16,8 +16,6 @@ def _find_lit_app_port(default_port: int) -> int: if not app_id or not project_id or not enable_multiple_works_in_default_container: return default_port - assert project_id - client = LightningClient() list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) lit_app: Optional[Externalv1LightningappInstance] = None From b26fc0c8aacfe9831e42ad9c9dc4610e1263012b Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:20 +0000 Subject: [PATCH 29/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 4059ea79bd166..965168aec5329 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -24,7 +24,10 @@ def _find_lit_app_port(default_port: int) -> int: if lightningapp.id == app_id: lit_app = lightningapp - assert lit_app + if not lit_app: + raise RuntimeError( + "App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues." + ) found_nc = None From f2f1b157e1853b975d4f012d0894d7729b9ba96b Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:26 +0000 Subject: [PATCH 30/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 965168aec5329..6a37593f4cc47 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -72,7 +72,10 @@ def enable_port() -> V1NetworkConfig: if lightningapp.id == app_id: lit_app = lightningapp - assert lit_app + if not lit_app: + raise RuntimeError( + "App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues." + ) found_nc = None From 175c46fa67e5c5728326de7f0876aaaf3005fbee Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:33 +0000 Subject: [PATCH 31/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 6a37593f4cc47..504c499527510 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -108,8 +108,6 @@ def disable_port(port: int, ignore_disabled: bool = True) -> None: if not app_id or not project_id: raise Exception("The app_id and project_id should be defined.") - assert project_id - client = LightningClient() list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) lit_app: Optional[Externalv1LightningappInstance] = None From ec870649d1367adaa388e98e901acb839bbd438a Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:42 +0000 Subject: [PATCH 32/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 504c499527510..1fa001421e77c 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -116,7 +116,10 @@ def disable_port(port: int, ignore_disabled: bool = True) -> None: if lightningapp.id == app_id: lit_app = lightningapp - assert lit_app + if not lit_app: + raise RuntimeError( + "App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues." + ) found_nc = None From 04daf575af34307c294022b3542a694ad432bbb2 Mon Sep 17 00:00:00 2001 From: thomas chaton Date: Thu, 24 Nov 2022 11:28:48 +0000 Subject: [PATCH 33/33] Update src/lightning_app/utilities/port.py Co-authored-by: Ethan Harris --- src/lightning_app/utilities/port.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lightning_app/utilities/port.py b/src/lightning_app/utilities/port.py index 1fa001421e77c..45877dfd85930 100644 --- a/src/lightning_app/utilities/port.py +++ b/src/lightning_app/utilities/port.py @@ -62,8 +62,6 @@ def enable_port() -> V1NetworkConfig: if not app_id or not project_id: raise Exception("The app_id and project_id should be defined.") - assert project_id - client = LightningClient() list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id) lit_app: Optional[Externalv1LightningappInstance] = None