lightning-sdk 0.2.6__py3-none-any.whl → 0.2.7__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.
- lightning_sdk/__init__.py +1 -1
- lightning_sdk/api/ai_hub_api.py +1 -0
- lightning_sdk/api/lit_container_api.py +84 -24
- lightning_sdk/api/teamspace_api.py +8 -9
- lightning_sdk/api/utils.py +0 -1
- lightning_sdk/cli/docker.py +1 -1
- lightning_sdk/cli/download.py +10 -2
- lightning_sdk/cli/serve.py +16 -29
- lightning_sdk/cli/upload.py +41 -6
- lightning_sdk/lightning_cloud/openapi/__init__.py +8 -0
- lightning_sdk/lightning_cloud/openapi/api/cloud_space_service_api.py +202 -0
- lightning_sdk/lightning_cloud/openapi/models/__init__.py +8 -0
- lightning_sdk/lightning_cloud/openapi/models/alerts_config_billing.py +175 -0
- lightning_sdk/lightning_cloud/openapi/models/alerts_config_studios.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/orgs_id_body.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/projects_id_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/server_id_alerts_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_alert_method.py +102 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_alerts_config.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_cold_start_metrics.py +617 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_conversation_response_chunk.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_create_project_request.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_google_cloud_direct_v1.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_list_cloud_space_cold_start_metrics_response.py +123 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_message.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_organization.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_project_settings.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_report_cloud_space_instance_stop_at_response.py +97 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_server_alert.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_server_alert_phase.py +104 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +53 -1
- lightning_sdk/lightning_cloud/rest_client.py +42 -44
- lightning_sdk/lit_container.py +19 -4
- lightning_sdk/models.py +1 -1
- lightning_sdk/serve.py +86 -17
- lightning_sdk/teamspace.py +32 -18
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/METADATA +1 -1
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/RECORD +42 -34
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/LICENSE +0 -0
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/WHEEL +0 -0
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-0.2.6.dist-info → lightning_sdk-0.2.7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
external/v1/auth_service.proto
|
|
5
|
+
|
|
6
|
+
No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) # noqa: E501
|
|
7
|
+
|
|
8
|
+
OpenAPI spec version: version not set
|
|
9
|
+
|
|
10
|
+
Generated by: https://github.com/swagger-api/swagger-codegen.git
|
|
11
|
+
|
|
12
|
+
NOTE
|
|
13
|
+
----
|
|
14
|
+
standard swagger-codegen-cli for this python client has been modified
|
|
15
|
+
by custom templates. The purpose of these templates is to include
|
|
16
|
+
typing information in the API and Model code. Please refer to the
|
|
17
|
+
main grid repository for more info
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import pprint
|
|
21
|
+
import re # noqa: F401
|
|
22
|
+
|
|
23
|
+
from typing import TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
import six
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from datetime import datetime
|
|
29
|
+
from lightning_sdk.lightning_cloud.openapi.models import *
|
|
30
|
+
|
|
31
|
+
class V1ServerAlertPhase(object):
|
|
32
|
+
"""NOTE: This class is auto generated by the swagger code generator program.
|
|
33
|
+
|
|
34
|
+
Do not edit the class manually.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
allowed enum values
|
|
39
|
+
"""
|
|
40
|
+
UNSPECIFIED = "SERVER_ALERT_PHASE_UNSPECIFIED"
|
|
41
|
+
STARTUP = "SERVER_ALERT_PHASE_STARTUP"
|
|
42
|
+
SHUTDOWN = "SERVER_ALERT_PHASE_SHUTDOWN"
|
|
43
|
+
"""
|
|
44
|
+
Attributes:
|
|
45
|
+
swagger_types (dict): The key is attribute name
|
|
46
|
+
and the value is attribute type.
|
|
47
|
+
attribute_map (dict): The key is attribute name
|
|
48
|
+
and the value is json key in definition.
|
|
49
|
+
"""
|
|
50
|
+
swagger_types = {
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
attribute_map = {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
def __init__(self): # noqa: E501
|
|
57
|
+
"""V1ServerAlertPhase - a model defined in Swagger""" # noqa: E501
|
|
58
|
+
self.discriminator = None
|
|
59
|
+
|
|
60
|
+
def to_dict(self) -> dict:
|
|
61
|
+
"""Returns the model properties as a dict"""
|
|
62
|
+
result = {}
|
|
63
|
+
|
|
64
|
+
for attr, _ in six.iteritems(self.swagger_types):
|
|
65
|
+
value = getattr(self, attr)
|
|
66
|
+
if isinstance(value, list):
|
|
67
|
+
result[attr] = list(map(
|
|
68
|
+
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
|
|
69
|
+
value
|
|
70
|
+
))
|
|
71
|
+
elif hasattr(value, "to_dict"):
|
|
72
|
+
result[attr] = value.to_dict()
|
|
73
|
+
elif isinstance(value, dict):
|
|
74
|
+
result[attr] = dict(map(
|
|
75
|
+
lambda item: (item[0], item[1].to_dict())
|
|
76
|
+
if hasattr(item[1], "to_dict") else item,
|
|
77
|
+
value.items()
|
|
78
|
+
))
|
|
79
|
+
else:
|
|
80
|
+
result[attr] = value
|
|
81
|
+
if issubclass(V1ServerAlertPhase, dict):
|
|
82
|
+
for key, value in self.items():
|
|
83
|
+
result[key] = value
|
|
84
|
+
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
def to_str(self) -> str:
|
|
88
|
+
"""Returns the string representation of the model"""
|
|
89
|
+
return pprint.pformat(self.to_dict())
|
|
90
|
+
|
|
91
|
+
def __repr__(self) -> str:
|
|
92
|
+
"""For `print` and `pprint`"""
|
|
93
|
+
return self.to_str()
|
|
94
|
+
|
|
95
|
+
def __eq__(self, other: 'V1ServerAlertPhase') -> bool:
|
|
96
|
+
"""Returns true if both objects are equal"""
|
|
97
|
+
if not isinstance(other, V1ServerAlertPhase):
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
return self.__dict__ == other.__dict__
|
|
101
|
+
|
|
102
|
+
def __ne__(self, other: 'V1ServerAlertPhase') -> bool:
|
|
103
|
+
"""Returns true if both objects are not equal"""
|
|
104
|
+
return not self == other
|
|
@@ -79,6 +79,7 @@ class V1UserFeatures(object):
|
|
|
79
79
|
'lambda_labs': 'bool',
|
|
80
80
|
'landing_studios': 'bool',
|
|
81
81
|
'lit_logger': 'bool',
|
|
82
|
+
'manage_default_studio_machine': 'bool',
|
|
82
83
|
'marketplace': 'bool',
|
|
83
84
|
'mmt_fault_tolerance': 'bool',
|
|
84
85
|
'mmt_strategy_selector': 'bool',
|
|
@@ -107,6 +108,7 @@ class V1UserFeatures(object):
|
|
|
107
108
|
'runnable_public_studio_page': 'bool',
|
|
108
109
|
'security_docs': 'bool',
|
|
109
110
|
'show_dev_admin': 'bool',
|
|
111
|
+
'single_wallet': 'bool',
|
|
110
112
|
'slurm': 'bool',
|
|
111
113
|
'slurm_machine_selector': 'bool',
|
|
112
114
|
'stop_ide_container_on_shutdown': 'bool',
|
|
@@ -159,6 +161,7 @@ class V1UserFeatures(object):
|
|
|
159
161
|
'lambda_labs': 'lambdaLabs',
|
|
160
162
|
'landing_studios': 'landingStudios',
|
|
161
163
|
'lit_logger': 'litLogger',
|
|
164
|
+
'manage_default_studio_machine': 'manageDefaultStudioMachine',
|
|
162
165
|
'marketplace': 'marketplace',
|
|
163
166
|
'mmt_fault_tolerance': 'mmtFaultTolerance',
|
|
164
167
|
'mmt_strategy_selector': 'mmtStrategySelector',
|
|
@@ -187,6 +190,7 @@ class V1UserFeatures(object):
|
|
|
187
190
|
'runnable_public_studio_page': 'runnablePublicStudioPage',
|
|
188
191
|
'security_docs': 'securityDocs',
|
|
189
192
|
'show_dev_admin': 'showDevAdmin',
|
|
193
|
+
'single_wallet': 'singleWallet',
|
|
190
194
|
'slurm': 'slurm',
|
|
191
195
|
'slurm_machine_selector': 'slurmMachineSelector',
|
|
192
196
|
'stop_ide_container_on_shutdown': 'stopIdeContainerOnShutdown',
|
|
@@ -200,7 +204,7 @@ class V1UserFeatures(object):
|
|
|
200
204
|
'vultr': 'vultr'
|
|
201
205
|
}
|
|
202
206
|
|
|
203
|
-
def __init__(self, affiliate_links: 'bool' =None, agents_v2: 'bool' =None, ai_hub_monetization: 'bool' =None, auto_fast_load: 'bool' =None, auto_join_orgs: 'bool' =None, b2c_experience: 'bool' =None, byoc_litcr: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation_byoc: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, chat_models: 'bool' =None, cloud_space_environment_templates: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, cost_attribution_settings: 'bool' =None, custom_app_domain: 'bool' =None, custom_instance_types: 'bool' =None, datasets: 'bool' =None, default_one_cluster: 'bool' =None, deployment_alerts: 'bool' =None, deployment_persistent_disk: 'bool' =None, deployment_reservations: 'bool' =None, dgx_cloud: 'bool' =None, docs_agent: 'bool' =None, drive_v2: 'bool' =None, enable_crypto_crackdown: 'bool' =None, enable_storage_limits: 'bool' =None, enterprise_compute_admin: 'bool' =None, fair_share: 'bool' =None, featured_studios_admin: 'bool' =None, filestore: 'bool' =None, inactive_notify_delete: 'bool' =None, instant_capacity_reservation: 'bool' =None, job_artifacts_v2: 'bool' =None, lambda_labs: 'bool' =None, landing_studios: 'bool' =None, lit_logger: 'bool' =None, marketplace: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, multicloud_saas: 'bool' =None, multiple_studio_versions: 'bool' =None, org_admin_alerts: 'bool' =None, org_level_member_permissions: 'bool' =None, pipelines: 'bool' =None, plugin_distributed: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_lightning_apps: 'bool' =None, plugin_lightning_apps_distributed: 'bool' =None, plugin_milvus: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_react: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, plugin_weviate: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, project_selector: 'bool' =None, publish_pipelines: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, security_docs: 'bool' =None, show_dev_admin: 'bool' =None, slurm: 'bool' =None, slurm_machine_selector: 'bool' =None, stop_ide_container_on_shutdown: 'bool' =None, studio_config: 'bool' =None, studio_on_stop: 'bool' =None, studio_version_visibility: 'bool' =None, studios_dashboard: 'bool' =None, teamspace_storage_tab: 'bool' =None, trainium2: 'bool' =None, use_rclone_mounts_only: 'bool' =None, vultr: 'bool' =None): # noqa: E501
|
|
207
|
+
def __init__(self, affiliate_links: 'bool' =None, agents_v2: 'bool' =None, ai_hub_monetization: 'bool' =None, auto_fast_load: 'bool' =None, auto_join_orgs: 'bool' =None, b2c_experience: 'bool' =None, byoc_litcr: 'bool' =None, cap_add: 'list[str]' =None, cap_drop: 'list[str]' =None, capacity_reservation_byoc: 'bool' =None, capacity_reservation_dry_run: 'bool' =None, chat_models: 'bool' =None, cloud_space_environment_templates: 'bool' =None, code_tab: 'bool' =None, collab_screen_sharing: 'bool' =None, cost_attribution_settings: 'bool' =None, custom_app_domain: 'bool' =None, custom_instance_types: 'bool' =None, datasets: 'bool' =None, default_one_cluster: 'bool' =None, deployment_alerts: 'bool' =None, deployment_persistent_disk: 'bool' =None, deployment_reservations: 'bool' =None, dgx_cloud: 'bool' =None, docs_agent: 'bool' =None, drive_v2: 'bool' =None, enable_crypto_crackdown: 'bool' =None, enable_storage_limits: 'bool' =None, enterprise_compute_admin: 'bool' =None, fair_share: 'bool' =None, featured_studios_admin: 'bool' =None, filestore: 'bool' =None, inactive_notify_delete: 'bool' =None, instant_capacity_reservation: 'bool' =None, job_artifacts_v2: 'bool' =None, lambda_labs: 'bool' =None, landing_studios: 'bool' =None, lit_logger: 'bool' =None, manage_default_studio_machine: 'bool' =None, marketplace: 'bool' =None, mmt_fault_tolerance: 'bool' =None, mmt_strategy_selector: 'bool' =None, multicloud_saas: 'bool' =None, multiple_studio_versions: 'bool' =None, org_admin_alerts: 'bool' =None, org_level_member_permissions: 'bool' =None, pipelines: 'bool' =None, plugin_distributed: 'bool' =None, plugin_inference: 'bool' =None, plugin_label_studio: 'bool' =None, plugin_langflow: 'bool' =None, plugin_lightning_apps: 'bool' =None, plugin_lightning_apps_distributed: 'bool' =None, plugin_milvus: 'bool' =None, plugin_python_profiler: 'bool' =None, plugin_react: 'bool' =None, plugin_service: 'bool' =None, plugin_sweeps: 'bool' =None, plugin_weviate: 'bool' =None, pricing_updates: 'bool' =None, product_generator: 'bool' =None, project_selector: 'bool' =None, publish_pipelines: 'bool' =None, restartable_jobs: 'bool' =None, runnable_public_studio_page: 'bool' =None, security_docs: 'bool' =None, show_dev_admin: 'bool' =None, single_wallet: 'bool' =None, slurm: 'bool' =None, slurm_machine_selector: 'bool' =None, stop_ide_container_on_shutdown: 'bool' =None, studio_config: 'bool' =None, studio_on_stop: 'bool' =None, studio_version_visibility: 'bool' =None, studios_dashboard: 'bool' =None, teamspace_storage_tab: 'bool' =None, trainium2: 'bool' =None, use_rclone_mounts_only: 'bool' =None, vultr: 'bool' =None): # noqa: E501
|
|
204
208
|
"""V1UserFeatures - a model defined in Swagger""" # noqa: E501
|
|
205
209
|
self._affiliate_links = None
|
|
206
210
|
self._agents_v2 = None
|
|
@@ -240,6 +244,7 @@ class V1UserFeatures(object):
|
|
|
240
244
|
self._lambda_labs = None
|
|
241
245
|
self._landing_studios = None
|
|
242
246
|
self._lit_logger = None
|
|
247
|
+
self._manage_default_studio_machine = None
|
|
243
248
|
self._marketplace = None
|
|
244
249
|
self._mmt_fault_tolerance = None
|
|
245
250
|
self._mmt_strategy_selector = None
|
|
@@ -268,6 +273,7 @@ class V1UserFeatures(object):
|
|
|
268
273
|
self._runnable_public_studio_page = None
|
|
269
274
|
self._security_docs = None
|
|
270
275
|
self._show_dev_admin = None
|
|
276
|
+
self._single_wallet = None
|
|
271
277
|
self._slurm = None
|
|
272
278
|
self._slurm_machine_selector = None
|
|
273
279
|
self._stop_ide_container_on_shutdown = None
|
|
@@ -356,6 +362,8 @@ class V1UserFeatures(object):
|
|
|
356
362
|
self.landing_studios = landing_studios
|
|
357
363
|
if lit_logger is not None:
|
|
358
364
|
self.lit_logger = lit_logger
|
|
365
|
+
if manage_default_studio_machine is not None:
|
|
366
|
+
self.manage_default_studio_machine = manage_default_studio_machine
|
|
359
367
|
if marketplace is not None:
|
|
360
368
|
self.marketplace = marketplace
|
|
361
369
|
if mmt_fault_tolerance is not None:
|
|
@@ -412,6 +420,8 @@ class V1UserFeatures(object):
|
|
|
412
420
|
self.security_docs = security_docs
|
|
413
421
|
if show_dev_admin is not None:
|
|
414
422
|
self.show_dev_admin = show_dev_admin
|
|
423
|
+
if single_wallet is not None:
|
|
424
|
+
self.single_wallet = single_wallet
|
|
415
425
|
if slurm is not None:
|
|
416
426
|
self.slurm = slurm
|
|
417
427
|
if slurm_machine_selector is not None:
|
|
@@ -1233,6 +1243,27 @@ class V1UserFeatures(object):
|
|
|
1233
1243
|
|
|
1234
1244
|
self._lit_logger = lit_logger
|
|
1235
1245
|
|
|
1246
|
+
@property
|
|
1247
|
+
def manage_default_studio_machine(self) -> 'bool':
|
|
1248
|
+
"""Gets the manage_default_studio_machine of this V1UserFeatures. # noqa: E501
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
:return: The manage_default_studio_machine of this V1UserFeatures. # noqa: E501
|
|
1252
|
+
:rtype: bool
|
|
1253
|
+
"""
|
|
1254
|
+
return self._manage_default_studio_machine
|
|
1255
|
+
|
|
1256
|
+
@manage_default_studio_machine.setter
|
|
1257
|
+
def manage_default_studio_machine(self, manage_default_studio_machine: 'bool'):
|
|
1258
|
+
"""Sets the manage_default_studio_machine of this V1UserFeatures.
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
:param manage_default_studio_machine: The manage_default_studio_machine of this V1UserFeatures. # noqa: E501
|
|
1262
|
+
:type: bool
|
|
1263
|
+
"""
|
|
1264
|
+
|
|
1265
|
+
self._manage_default_studio_machine = manage_default_studio_machine
|
|
1266
|
+
|
|
1236
1267
|
@property
|
|
1237
1268
|
def marketplace(self) -> 'bool':
|
|
1238
1269
|
"""Gets the marketplace of this V1UserFeatures. # noqa: E501
|
|
@@ -1821,6 +1852,27 @@ class V1UserFeatures(object):
|
|
|
1821
1852
|
|
|
1822
1853
|
self._show_dev_admin = show_dev_admin
|
|
1823
1854
|
|
|
1855
|
+
@property
|
|
1856
|
+
def single_wallet(self) -> 'bool':
|
|
1857
|
+
"""Gets the single_wallet of this V1UserFeatures. # noqa: E501
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
:return: The single_wallet of this V1UserFeatures. # noqa: E501
|
|
1861
|
+
:rtype: bool
|
|
1862
|
+
"""
|
|
1863
|
+
return self._single_wallet
|
|
1864
|
+
|
|
1865
|
+
@single_wallet.setter
|
|
1866
|
+
def single_wallet(self, single_wallet: 'bool'):
|
|
1867
|
+
"""Sets the single_wallet of this V1UserFeatures.
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
:param single_wallet: The single_wallet of this V1UserFeatures. # noqa: E501
|
|
1871
|
+
:type: bool
|
|
1872
|
+
"""
|
|
1873
|
+
|
|
1874
|
+
self._single_wallet = single_wallet
|
|
1875
|
+
|
|
1824
1876
|
@property
|
|
1825
1877
|
def slurm(self) -> 'bool':
|
|
1826
1878
|
"""Gets the slurm of this V1UserFeatures. # noqa: E501
|
|
@@ -2,41 +2,39 @@ import functools
|
|
|
2
2
|
import logging
|
|
3
3
|
import time
|
|
4
4
|
from functools import wraps
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Callable, Optional, Any
|
|
6
6
|
|
|
7
7
|
import urllib3
|
|
8
|
-
|
|
9
8
|
from lightning_sdk.lightning_cloud import env
|
|
10
9
|
from lightning_sdk.lightning_cloud.login import Auth
|
|
11
10
|
from lightning_sdk.lightning_cloud.openapi import (
|
|
12
11
|
ApiClient,
|
|
13
|
-
AssistantsServiceApi,
|
|
14
12
|
AuthServiceApi,
|
|
15
|
-
BillingServiceApi,
|
|
16
|
-
CloudSpaceEnvironmentTemplateServiceApi,
|
|
17
13
|
CloudSpaceServiceApi,
|
|
18
14
|
ClusterServiceApi,
|
|
19
15
|
Configuration,
|
|
20
16
|
DataConnectionServiceApi,
|
|
21
|
-
DatasetServiceApi,
|
|
22
|
-
DeploymentTemplatesServiceApi,
|
|
23
|
-
EndpointServiceApi,
|
|
24
|
-
JobsServiceApi,
|
|
25
17
|
LightningappInstanceServiceApi,
|
|
26
18
|
LightningappV2ServiceApi,
|
|
27
19
|
LightningworkServiceApi,
|
|
28
|
-
LitLoggerServiceApi,
|
|
29
|
-
LitRegistryServiceApi,
|
|
30
|
-
ModelsStoreApi,
|
|
31
|
-
OrganizationsServiceApi,
|
|
32
|
-
PipelinesServiceApi,
|
|
33
20
|
ProjectsServiceApi,
|
|
34
|
-
SchedulesServiceApi,
|
|
35
21
|
SecretServiceApi,
|
|
36
|
-
SlurmJobsUserServiceApi,
|
|
37
22
|
SSHPublicKeyServiceApi,
|
|
38
|
-
|
|
23
|
+
DatasetServiceApi,
|
|
24
|
+
OrganizationsServiceApi,
|
|
39
25
|
UserServiceApi,
|
|
26
|
+
BillingServiceApi,
|
|
27
|
+
EndpointServiceApi,
|
|
28
|
+
SlurmJobsUserServiceApi,
|
|
29
|
+
LitLoggerServiceApi,
|
|
30
|
+
JobsServiceApi,
|
|
31
|
+
AssistantsServiceApi,
|
|
32
|
+
StorageServiceApi,
|
|
33
|
+
DeploymentTemplatesServiceApi,
|
|
34
|
+
ModelsStoreApi,
|
|
35
|
+
LitRegistryServiceApi,
|
|
36
|
+
PipelinesServiceApi,
|
|
37
|
+
SchedulesServiceApi,
|
|
40
38
|
)
|
|
41
39
|
from lightning_sdk.lightning_cloud.openapi.rest import ApiException
|
|
42
40
|
from lightning_sdk.lightning_cloud.source_code.logs_socket_api import LightningLogsSocketAPI
|
|
@@ -73,34 +71,34 @@ def create_swagger_client(check_context=True):
|
|
|
73
71
|
|
|
74
72
|
|
|
75
73
|
class GridRestClient(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
CloudSpaceEnvironmentTemplateServiceApi,
|
|
74
|
+
LightningLogsSocketAPI,
|
|
75
|
+
LightningappInstanceServiceApi,
|
|
76
|
+
LightningappV2ServiceApi,
|
|
77
|
+
AuthServiceApi,
|
|
78
|
+
CloudSpaceServiceApi,
|
|
79
|
+
ClusterServiceApi,
|
|
80
|
+
ProjectsServiceApi,
|
|
81
|
+
LightningworkServiceApi,
|
|
82
|
+
SecretServiceApi,
|
|
83
|
+
SSHPublicKeyServiceApi,
|
|
84
|
+
DataConnectionServiceApi,
|
|
85
|
+
DatasetServiceApi,
|
|
86
|
+
OrganizationsServiceApi,
|
|
87
|
+
UserServiceApi,
|
|
88
|
+
BillingServiceApi,
|
|
89
|
+
EndpointServiceApi,
|
|
90
|
+
SlurmJobsUserServiceApi,
|
|
91
|
+
LitLoggerServiceApi,
|
|
92
|
+
JobsServiceApi,
|
|
93
|
+
AssistantsServiceApi,
|
|
94
|
+
StorageServiceApi,
|
|
95
|
+
DeploymentTemplatesServiceApi,
|
|
96
|
+
ModelsStoreApi,
|
|
97
|
+
LitRegistryServiceApi,
|
|
98
|
+
PipelinesServiceApi,
|
|
99
|
+
SchedulesServiceApi,
|
|
103
100
|
):
|
|
101
|
+
|
|
104
102
|
def __init__(self, api_client: Optional[ApiClient] = None):
|
|
105
103
|
api_client = api_client if api_client else create_swagger_client()
|
|
106
104
|
api_client.request = request_auth_warning_wrapper(api_client.request)
|
lightning_sdk/lit_container.py
CHANGED
|
@@ -64,7 +64,14 @@ class LitContainer:
|
|
|
64
64
|
return self._api.delete_container(project_id, container)
|
|
65
65
|
|
|
66
66
|
def upload_container(
|
|
67
|
-
self,
|
|
67
|
+
self,
|
|
68
|
+
container: str,
|
|
69
|
+
teamspace: str,
|
|
70
|
+
org: Optional[str] = None,
|
|
71
|
+
user: Optional[str] = None,
|
|
72
|
+
tag: str = "latest",
|
|
73
|
+
cloud_account: Optional[str] = None,
|
|
74
|
+
platform: Optional[str] = "linux/amd64",
|
|
68
75
|
) -> None:
|
|
69
76
|
"""Upload a container to the docker registry.
|
|
70
77
|
|
|
@@ -74,18 +81,26 @@ class LitContainer:
|
|
|
74
81
|
org: The organization which contains the container.
|
|
75
82
|
user: The user which contains the container.
|
|
76
83
|
tag: The tag to use for the container.
|
|
84
|
+
cloud_account: The cloud account where the container is stored.
|
|
85
|
+
platform: The platform the container is meant to run on.
|
|
77
86
|
"""
|
|
78
87
|
try:
|
|
79
88
|
teamspace = _resolve_teamspace(teamspace=teamspace, org=org, user=user)
|
|
80
89
|
except Exception as e:
|
|
81
90
|
raise ValueError(f"Could not resolve teamspace: {e}") from e
|
|
82
91
|
|
|
83
|
-
resp = self._api.upload_container(container, teamspace, tag)
|
|
92
|
+
resp = self._api.upload_container(container, teamspace, tag, cloud_account, platform=platform)
|
|
84
93
|
for line in resp:
|
|
85
94
|
print(line)
|
|
86
95
|
|
|
87
96
|
def download_container(
|
|
88
|
-
self,
|
|
97
|
+
self,
|
|
98
|
+
container: str,
|
|
99
|
+
teamspace: str,
|
|
100
|
+
org: Optional[str] = None,
|
|
101
|
+
user: Optional[str] = None,
|
|
102
|
+
tag: str = "latest",
|
|
103
|
+
cloud_account: Optional[str] = None,
|
|
89
104
|
) -> None:
|
|
90
105
|
"""Download a container from the docker registry.
|
|
91
106
|
|
|
@@ -101,4 +116,4 @@ class LitContainer:
|
|
|
101
116
|
except Exception as e:
|
|
102
117
|
raise ValueError(f"Could not resolve teamspace: {e}") from e
|
|
103
118
|
|
|
104
|
-
return self._api.download_container(container, teamspace, tag)
|
|
119
|
+
return self._api.download_container(container, teamspace, tag, cloud_account)
|
lightning_sdk/models.py
CHANGED
|
@@ -144,7 +144,7 @@ def download_model(
|
|
|
144
144
|
|
|
145
145
|
def upload_model(
|
|
146
146
|
name: str,
|
|
147
|
-
path: Union[Path, str] = ".",
|
|
147
|
+
path: Union[str, Path, List[Union[str, Path]]] = ".",
|
|
148
148
|
cloud_account: Optional[str] = None,
|
|
149
149
|
progress_bar: bool = True,
|
|
150
150
|
) -> UploadedModelInfo:
|
lightning_sdk/serve.py
CHANGED
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
import shlex
|
|
3
3
|
import subprocess
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Generator, Optional
|
|
5
|
+
from typing import Generator, List, Optional, Union
|
|
6
6
|
from urllib.parse import urlencode
|
|
7
7
|
|
|
8
8
|
import docker
|
|
@@ -10,7 +10,7 @@ from rich.console import Console
|
|
|
10
10
|
from rich.progress import Progress
|
|
11
11
|
|
|
12
12
|
from lightning_sdk import Deployment, Machine, Teamspace
|
|
13
|
-
from lightning_sdk.api.deployment_api import AutoScaleConfig
|
|
13
|
+
from lightning_sdk.api.deployment_api import AutoScaleConfig, DeploymentApi, Env, Secret
|
|
14
14
|
from lightning_sdk.api.lit_container_api import LitContainerApi
|
|
15
15
|
from lightning_sdk.api.utils import _get_cloud_url
|
|
16
16
|
from lightning_sdk.lightning_cloud import env
|
|
@@ -35,16 +35,18 @@ class _Auth(Auth):
|
|
|
35
35
|
_AuthServer().login_with_browser(self)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def authenticate() -> None:
|
|
39
|
+
auth = _Auth()
|
|
40
|
+
auth.authenticate()
|
|
41
|
+
|
|
42
|
+
|
|
38
43
|
class _LitServeDeployer:
|
|
39
|
-
def __init__(self) -> None:
|
|
44
|
+
def __init__(self, name: Optional[str], teamspace: Optional[Teamspace]) -> None:
|
|
45
|
+
self.name = name
|
|
46
|
+
self.teamspace = teamspace
|
|
40
47
|
self._console = Console()
|
|
41
48
|
self._client = None
|
|
42
49
|
|
|
43
|
-
@staticmethod
|
|
44
|
-
def authenticate() -> None:
|
|
45
|
-
auth = _Auth()
|
|
46
|
-
auth.authenticate()
|
|
47
|
-
|
|
48
50
|
@property
|
|
49
51
|
def client(self) -> docker.DockerClient:
|
|
50
52
|
if self._client is None:
|
|
@@ -56,6 +58,10 @@ class _LitServeDeployer:
|
|
|
56
58
|
raise RuntimeError(_DOCKER_NOT_RUNNING_MSG) from None
|
|
57
59
|
return self._client
|
|
58
60
|
|
|
61
|
+
@property
|
|
62
|
+
def created(self) -> bool:
|
|
63
|
+
return DeploymentApi().get_deployment_by_name(self.name, self.teamspace.id) is not None
|
|
64
|
+
|
|
59
65
|
def dockerize_api(
|
|
60
66
|
self,
|
|
61
67
|
server_filename: str,
|
|
@@ -194,13 +200,19 @@ Update [underline]{os.path.abspath("Dockerfile")}[/underline] to add any additio
|
|
|
194
200
|
progress.update(build_task, description="[green]Build completed![/green]")
|
|
195
201
|
|
|
196
202
|
def push_container(
|
|
197
|
-
self,
|
|
203
|
+
self,
|
|
204
|
+
repository: str,
|
|
205
|
+
tag: str,
|
|
206
|
+
teamspace: Teamspace,
|
|
207
|
+
lit_cr: LitContainerApi,
|
|
208
|
+
progress: Progress,
|
|
209
|
+
cloud_account: str,
|
|
198
210
|
) -> dict:
|
|
199
211
|
console = self._console
|
|
200
212
|
push_task = progress.add_task("Pushing to registry", total=None)
|
|
201
213
|
console.print("\nPushing image...", style="bold blue")
|
|
202
214
|
lit_cr.authenticate()
|
|
203
|
-
push_status = lit_cr.upload_container(repository, teamspace, tag=tag)
|
|
215
|
+
push_status = lit_cr.upload_container(repository, teamspace, tag=tag, cloud_account=cloud_account)
|
|
204
216
|
last_status = {}
|
|
205
217
|
for line in push_status:
|
|
206
218
|
last_status = line
|
|
@@ -214,7 +226,38 @@ Update [underline]{os.path.abspath("Dockerfile")}[/underline] to add any additio
|
|
|
214
226
|
progress.update(push_task, description="[green]Push completed![/green]")
|
|
215
227
|
return last_status
|
|
216
228
|
|
|
217
|
-
def
|
|
229
|
+
def _update_deployment(
|
|
230
|
+
self,
|
|
231
|
+
deployment: Deployment,
|
|
232
|
+
machine: Optional[Machine] = None,
|
|
233
|
+
image: Optional[str] = None,
|
|
234
|
+
entrypoint: Optional[str] = None,
|
|
235
|
+
command: Optional[str] = None,
|
|
236
|
+
env: Optional[List[Union[Env, Secret]]] = None,
|
|
237
|
+
min_replica: Optional[int] = 0,
|
|
238
|
+
max_replica: Optional[int] = 1,
|
|
239
|
+
spot: Optional[bool] = None,
|
|
240
|
+
replicas: Optional[int] = 1,
|
|
241
|
+
cloud_account: Optional[str] = None,
|
|
242
|
+
port: Optional[int] = 8000,
|
|
243
|
+
include_credentials: Optional[bool] = True,
|
|
244
|
+
) -> None:
|
|
245
|
+
return deployment.update(
|
|
246
|
+
machine=machine,
|
|
247
|
+
image=image,
|
|
248
|
+
entrypoint=entrypoint,
|
|
249
|
+
command=command,
|
|
250
|
+
env=env,
|
|
251
|
+
max_replicas=max_replica,
|
|
252
|
+
min_replicas=min_replica,
|
|
253
|
+
replicas=replicas,
|
|
254
|
+
spot=spot,
|
|
255
|
+
cloud_account=cloud_account,
|
|
256
|
+
ports=[port],
|
|
257
|
+
include_credentials=include_credentials,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def run_on_cloud(
|
|
218
261
|
self,
|
|
219
262
|
deployment_name: str,
|
|
220
263
|
teamspace: Teamspace,
|
|
@@ -229,18 +272,44 @@ Update [underline]{os.path.abspath("Dockerfile")}[/underline] to add any additio
|
|
|
229
272
|
port: Optional[int] = 8000,
|
|
230
273
|
include_credentials: Optional[bool] = True,
|
|
231
274
|
) -> dict:
|
|
275
|
+
"""Run a deployment on the cloud. If the deployment already exists, it will be updated.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
deployment_name: The name of the deployment.
|
|
279
|
+
teamspace: The teamspace to run the deployment on.
|
|
280
|
+
image: The image to run the deployment on.
|
|
281
|
+
metric: The metric to use for autoscaling. Defaults to None.
|
|
282
|
+
machine: The machine to run the deployment on. Defaults to None.
|
|
283
|
+
min_replica: The minimum number of replicas to run. Defaults to 0.
|
|
284
|
+
max_replica: The maximum number of replicas to run. Defaults to 1.
|
|
285
|
+
spot: Whether to run the deployment on spot instances. Defaults to None.
|
|
286
|
+
replicas: The number of replicas to run. Defaults to 1.
|
|
287
|
+
cloud_account: The cloud account to run the deployment on. Defaults to None.
|
|
288
|
+
port: The port to run the deployment on. Defaults to 8000.
|
|
289
|
+
include_credentials: Whether to include credentials in the deployment. Defaults to True.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
dict: The deployment and the URL of the deployment.
|
|
293
|
+
"""
|
|
232
294
|
url = f"{_get_cloud_url()}/{teamspace.owner.name}/{teamspace.name}/jobs/{deployment_name}"
|
|
233
295
|
machine = machine or Machine.CPU
|
|
234
296
|
metric = metric or ("CPU" if machine.is_cpu() else "GPU")
|
|
235
297
|
deployment = Deployment(deployment_name, teamspace)
|
|
236
298
|
if deployment.is_started:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
299
|
+
self._console.print(f"Deployment with name {deployment_name} already running. Updating the deployment.")
|
|
300
|
+
self._update_deployment(
|
|
301
|
+
deployment,
|
|
302
|
+
machine,
|
|
303
|
+
image,
|
|
304
|
+
min_replica=min_replica,
|
|
305
|
+
max_replica=max_replica,
|
|
306
|
+
spot=spot,
|
|
307
|
+
replicas=replicas,
|
|
308
|
+
cloud_account=cloud_account,
|
|
309
|
+
port=port,
|
|
310
|
+
include_credentials=include_credentials,
|
|
243
311
|
)
|
|
312
|
+
return {"deployment": deployment, "url": url, "updated": True}
|
|
244
313
|
autoscale = AutoScaleConfig(min_replicas=min_replica, max_replicas=max_replica, metric=metric, threshold=0.95)
|
|
245
314
|
deployment.start(
|
|
246
315
|
machine=machine,
|
lightning_sdk/teamspace.py
CHANGED
|
@@ -243,7 +243,7 @@ class Teamspace:
|
|
|
243
243
|
|
|
244
244
|
def upload_model(
|
|
245
245
|
self,
|
|
246
|
-
path: Union[str, Path],
|
|
246
|
+
path: Union[str, Path, List[Union[str, Path]]],
|
|
247
247
|
name: str,
|
|
248
248
|
cloud_account: Optional[str] = None,
|
|
249
249
|
progress_bar: bool = True,
|
|
@@ -261,30 +261,33 @@ class Teamspace:
|
|
|
261
261
|
raise ValueError("No path provided to upload")
|
|
262
262
|
if not name:
|
|
263
263
|
raise ValueError("No name provided for the model")
|
|
264
|
-
path = Path(path).resolve()
|
|
265
|
-
if not path.exists():
|
|
266
|
-
raise FileNotFoundError(str(path))
|
|
267
264
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
265
|
+
if isinstance(path, (str, Path)):
|
|
266
|
+
path = [path]
|
|
267
|
+
file_paths, relative_paths = [], []
|
|
268
|
+
for p in path:
|
|
269
|
+
lpaths, rpaths = _list_files(p)
|
|
270
|
+
file_paths.extend(lpaths)
|
|
271
|
+
relative_paths.extend(rpaths)
|
|
272
272
|
|
|
273
|
-
if not
|
|
273
|
+
if not file_paths:
|
|
274
274
|
raise FileNotFoundError(
|
|
275
275
|
"The path to upload doesn't contain any files. Make sure it points to a file or"
|
|
276
276
|
f" non-empty folder: {path}"
|
|
277
277
|
)
|
|
278
|
+
if len(relative_paths) != len(set(relative_paths)):
|
|
279
|
+
raise RuntimeError(
|
|
280
|
+
"The paths to upload contain files with the same name or relative path in folders."
|
|
281
|
+
f"The listed files are: {file_paths}\nThe relative paths are: {relative_paths}"
|
|
282
|
+
)
|
|
278
283
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
filenames = ",".join(str(f.relative_to(root_path)) for f in filepaths)
|
|
284
|
+
cloud_account = (
|
|
285
|
+
self._teamspace_api._determine_cloud_account(self.id) if cloud_account is None else cloud_account
|
|
286
|
+
)
|
|
284
287
|
|
|
285
288
|
model = self._teamspace_api.create_model(
|
|
286
289
|
name=name,
|
|
287
|
-
metadata={"filenames":
|
|
290
|
+
metadata={"filenames": ",".join(relative_paths)},
|
|
288
291
|
private=True,
|
|
289
292
|
teamspace_id=self.id,
|
|
290
293
|
cloud_account=cloud_account,
|
|
@@ -292,9 +295,8 @@ class Teamspace:
|
|
|
292
295
|
self._teamspace_api.upload_model_files(
|
|
293
296
|
model_id=model.model_id,
|
|
294
297
|
version=model.version,
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
cloud_account=cloud_account,
|
|
298
|
+
file_paths=file_paths,
|
|
299
|
+
remote_paths=relative_paths,
|
|
298
300
|
teamspace_id=self.id,
|
|
299
301
|
progress_bar=progress_bar,
|
|
300
302
|
)
|
|
@@ -371,6 +373,18 @@ class Teamspace:
|
|
|
371
373
|
self._teamspace_api.delete_model(name=name, version=version, teamspace_id=self.id)
|
|
372
374
|
|
|
373
375
|
|
|
376
|
+
def _list_files(path: Union[str, Path]) -> Tuple[List[Path], List[str]]:
|
|
377
|
+
"""List all folders in a directory and return them as a list and relative path."""
|
|
378
|
+
path = Path(path).resolve()
|
|
379
|
+
if not path.exists():
|
|
380
|
+
raise FileNotFoundError(f"Path {path} does not exist")
|
|
381
|
+
if not path.is_dir():
|
|
382
|
+
return [path], [str(path.name)]
|
|
383
|
+
local_paths = [p for p in path.rglob("*") if p.is_file()]
|
|
384
|
+
relative_paths = [str(p.relative_to(path)) for p in local_paths]
|
|
385
|
+
return local_paths, relative_paths
|
|
386
|
+
|
|
387
|
+
|
|
374
388
|
def _resolve_valueerror_message(error: ValueError, owner: Owner, teamspace_name: str) -> ValueError:
|
|
375
389
|
"""Resolves the ValueError Message and replaces it with a nicer message."""
|
|
376
390
|
message = error.args[0]
|