pytorch-lightning
168 строк · 5.7 Кб
1# Copyright The Lightning AI team.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
16import socket
17from typing import Optional
18
19from lightning_cloud.openapi import AppinstancesIdBody, Externalv1LightningappInstance, V1NetworkConfig
20
21from lightning.app.utilities.network import LightningClient, find_free_network_port
22
23
24def is_port_in_use(port: int) -> bool:
25"""Checks if the given port is in use."""
26with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
27return s.connect_ex(("localhost", port)) == 0
28
29
30def _find_lit_app_port(default_port: int) -> int:
31"""Make a request to the cloud controlplane to find a disabled port of the flow, enable it and return it."""
32app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None)
33project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None)
34enable_multiple_works_in_default_container = bool(int(os.getenv("ENABLE_MULTIPLE_WORKS_IN_DEFAULT_CONTAINER", "0")))
35
36if not app_id or not project_id or not enable_multiple_works_in_default_container:
37app_port = default_port
38
39# If the default port is not available, picks any other available one
40if is_port_in_use(default_port):
41app_port = find_free_network_port()
42
43return app_port
44
45client = LightningClient()
46list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id)
47lit_app: Optional[Externalv1LightningappInstance] = None
48
49for lapp in list_apps_resp.lightningapps:
50if lapp.id == app_id:
51lit_app = lapp
52
53if not lit_app:
54raise RuntimeError(
55"App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues."
56)
57
58found_nc = None
59
60for nc in lit_app.spec.network_config:
61if not nc.enable:
62found_nc = nc
63nc.enable = True
64break
65
66client.lightningapp_instance_service_update_lightningapp_instance(
67project_id=project_id,
68id=lit_app.id,
69body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec),
70)
71
72if not found_nc:
73raise RuntimeError(
74"No available port was found. Please open an issue at https://github.com/lightning-AI/lightning/issues."
75)
76
77# Note: This is required for the framework to know we need to use the CloudMultiProcessRuntime.
78os.environ["APP_SERVER_HOST"] = f"https://{found_nc.host}"
79
80return found_nc.port
81
82
83def enable_port() -> V1NetworkConfig:
84"""Make a request to the cloud controlplane to open a port of the flow."""
85app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None)
86project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None)
87
88if not app_id or not project_id:
89raise Exception("The app_id and project_id should be defined.")
90
91client = LightningClient()
92list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id)
93lit_app: Optional[Externalv1LightningappInstance] = None
94
95for lapp in list_apps_resp.lightningapps:
96if lapp.id == app_id:
97lit_app = lapp
98
99if not lit_app:
100raise RuntimeError(
101"App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues."
102)
103
104found_nc = None
105
106for nc in lit_app.spec.network_config:
107if not nc.enable:
108found_nc = nc
109nc.enable = True
110break
111
112client.lightningapp_instance_service_update_lightningapp_instance(
113project_id=project_id,
114id=lit_app.id,
115body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec),
116)
117
118if not found_nc:
119raise RuntimeError(
120"No available port was found. Please open an issue at https://github.com/lightning-AI/lightning/issues."
121)
122
123return found_nc
124
125
126def disable_port(port: int, ignore_disabled: bool = True) -> None:
127"""Make a request to the cloud controlplane to close a port of the flow."""
128app_id = os.getenv("LIGHTNING_CLOUD_APP_ID", None)
129project_id = os.getenv("LIGHTNING_CLOUD_PROJECT_ID", None)
130
131if not app_id or not project_id:
132raise Exception("The app_id and project_id should be defined.")
133
134client = LightningClient()
135list_apps_resp = client.lightningapp_instance_service_list_lightningapp_instances(project_id=project_id)
136lit_app: Optional[Externalv1LightningappInstance] = None
137
138for lapp in list_apps_resp.lightningapps:
139if lapp.id == app_id:
140lit_app = lapp
141
142if not lit_app:
143raise RuntimeError(
144"App was not found. Please open an issue at https://github.com/lightning-AI/lightning/issues."
145)
146
147found_nc = None
148
149for nc in lit_app.spec.network_config:
150if nc.port == port:
151if not nc.enable and not ignore_disabled:
152raise RuntimeError(f"The port {port} was already disabled.")
153
154nc.enable = False
155found_nc = nc
156break
157
158client.lightningapp_instance_service_update_lightningapp_instance(
159project_id=project_id,
160id=lit_app.id,
161body=AppinstancesIdBody(name=lit_app.name, spec=lit_app.spec),
162)
163
164if not found_nc:
165ports = [nc.port for nc in lit_app.spec.network_config]
166raise ValueError(f"The provided port doesn't exists. Available ports are {ports}.")
167
168assert found_nc
169