Skip to content

Commit 8f2dc7c

Browse files
[ODSC_52446_52447] Get loggroups logids and compartment list (#561)
2 parents f858388 + a2bfc83 commit 8f2dc7c

File tree

9 files changed

+335
-97
lines changed

9 files changed

+335
-97
lines changed

ads/aqua/base.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
# Copyright (c) 2024 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55
import oci
6-
from oci.exceptions import ClientError, ServiceError
7-
8-
from ads.aqua.exception import AquaClientError, AquaServiceError
96
from ads.common.auth import default_signer
7+
from ads.aqua.exception import AquaServiceError, AquaClientError
8+
from oci.exceptions import ServiceError, ClientError
9+
from ads.common import oci_client as oc
1010
from ads.common.utils import extract_region
1111

1212

@@ -15,7 +15,9 @@ class AquaApp:
1515

1616
def __init__(self) -> None:
1717
self._auth = default_signer()
18-
self.client = oci.data_science.DataScienceClient(**self._auth)
18+
self.ds_client = oc.OCIClientFactory(**self._auth).data_science
19+
self.logging_client = oc.OCIClientFactory(**self._auth).logging_management
20+
self.identity_client = oc.OCIClientFactory(**self._auth).identity
1921
self.region = extract_region(self._auth)
2022

2123
def list_resource(

ads/aqua/deployment.py

Lines changed: 98 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,108 @@
66
import logging
77
from typing import List, Dict
88

9-
from dataclasses import dataclass
9+
from dataclasses import dataclass, field
1010
from ads.aqua.base import AquaApp
1111
from ads.model.deployment import (
1212
ModelDeployment,
1313
ModelDeploymentInfrastructure,
1414
ModelDeploymentContainerRuntime,
1515
ModelDeploymentMode,
1616
)
17+
from ads.model.service.oci_datascience_model_deployment import (
18+
OCIDataScienceModelDeployment,
19+
)
20+
from ads.common.utils import get_console_link
1721
from ads.common.serializer import DataClassSerializable
18-
from ads.aqua.exception import AquaClientError, AquaServiceError
1922
from ads.config import COMPARTMENT_OCID
2023

24+
25+
# todo: move this to constants or have separate functions
2126
AQUA_SERVICE_MODEL = "aqua_service_model"
22-
CONSOLE_LINK_URL = (
23-
"https://cloud.oracle.com/data-science/model-deployments/{}?region={}"
24-
)
2527

26-
logger = logging.getLogger(__name__)
28+
29+
@dataclass
30+
class ShapeInfo:
31+
instance_shape: str = None
32+
instance_count: int = None
33+
ocpus: float = None
34+
memory_in_gbs: float = None
2735

2836

2937
@dataclass(repr=False)
3038
class AquaDeployment(DataClassSerializable):
3139
"""Represents an Aqua Model Deployment"""
32-
id: str
33-
display_name: str
34-
aqua_service_model: str
35-
state: str
36-
description: str
37-
created_on: str
38-
created_by: str
39-
endpoint: str
40-
instance_shape: str
41-
ocpus: float
42-
memory_in_gbs: float
43-
console_link: str
40+
41+
id: str = None
42+
display_name: str = None
43+
aqua_service_model: str = None
44+
state: str = None
45+
description: str = None
46+
created_on: str = None
47+
created_by: str = None
48+
endpoint: str = None
49+
console_link: str = None
50+
shape_info: field(default_factory=ShapeInfo) = None
51+
52+
@classmethod
53+
def from_oci_model_deployment(
54+
cls, oci_model_deployment: OCIDataScienceModelDeployment, region
55+
) -> "AquaDeployment":
56+
"""Converts oci model deployment response to AquaDeployment instance.
57+
58+
Parameters
59+
----------
60+
oci_model_deployment: oci.data_science.models.ModelDeployment
61+
The oci.data_science.models.ModelDeployment instance.
62+
region: str
63+
The region of this model deployment.
64+
65+
Returns
66+
-------
67+
AquaDeployment:
68+
The instance of the Aqua model deployment.
69+
"""
70+
instance_configuration = (
71+
oci_model_deployment.model_deployment_configuration_details.model_configuration_details.instance_configuration
72+
)
73+
instance_shape_config_details = (
74+
instance_configuration.model_deployment_instance_shape_config_details
75+
)
76+
instance_count = (
77+
oci_model_deployment.model_deployment_configuration_details.model_configuration_details.scaling_policy.instance_count
78+
)
79+
shape_info = ShapeInfo(
80+
instance_shape=instance_configuration.instance_shape_name,
81+
instance_count=instance_count,
82+
ocpus=(
83+
instance_shape_config_details.ocpus
84+
if instance_shape_config_details
85+
else None
86+
),
87+
memory_in_gbs=(
88+
instance_shape_config_details.memory_in_gbs
89+
if instance_shape_config_details
90+
else None
91+
),
92+
)
93+
return AquaDeployment(
94+
id=oci_model_deployment.id,
95+
display_name=oci_model_deployment.display_name,
96+
aqua_service_model=oci_model_deployment.freeform_tags.get(
97+
AQUA_SERVICE_MODEL
98+
),
99+
shape_info=shape_info,
100+
state=oci_model_deployment.lifecycle_state,
101+
description=oci_model_deployment.description,
102+
created_on=str(oci_model_deployment.time_created),
103+
created_by=oci_model_deployment.created_by,
104+
endpoint=oci_model_deployment.model_deployment_url,
105+
console_link=get_console_link(
106+
resource="model-deployments",
107+
ocid=oci_model_deployment.id,
108+
region=region,
109+
),
110+
)
44111

45112

46113
class AquaDeploymentApp(AquaApp):
@@ -181,7 +248,7 @@ def create(
181248
.with_runtime(container_runtime)
182249
).deploy(wait_for_completion=False)
183250

184-
return AquaDeploymentApp.from_oci_model_deployment(
251+
return AquaDeployment.from_oci_model_deployment(
185252
deployment.dsc_model_deployment, self.region
186253
)
187254

@@ -202,7 +269,9 @@ def list(self, **kwargs) -> List["AquaDeployment"]:
202269
compartment_id = kwargs.pop("compartment_id", COMPARTMENT_OCID)
203270

204271
model_deployments = self.list_resource(
205-
self.client.list_model_deployments, compartment_id=compartment_id, **kwargs
272+
self.ds_client.list_model_deployments,
273+
compartment_id=compartment_id,
274+
**kwargs,
206275
)
207276

208277
results = []
@@ -214,7 +283,7 @@ def list(self, **kwargs) -> List["AquaDeployment"]:
214283
)
215284
if aqua_service_model:
216285
results.append(
217-
AquaDeploymentApp.from_oci_model_deployment(
286+
AquaDeployment.from_oci_model_deployment(
218287
model_deployment, self.region
219288
)
220289
)
@@ -241,67 +310,20 @@ def get(self, model_deployment_id: str, **kwargs) -> "AquaDeployment":
241310
# add error handler
242311
# if not kwargs.get("model_deployment_id", None):
243312
# raise AquaClientError("Aqua model deployment ocid must be provided to fetch the deployment.")
244-
313+
245314
# add error handler
246-
model_deployment = self.client.get_model_deployment(
315+
model_deployment = self.ds_client.get_model_deployment(
247316
model_deployment_id=model_deployment_id, **kwargs
248317
).data
249-
250-
aqua_service_model=(
251-
model_deployment.freeform_tags.get(AQUA_SERVICE_MODEL, None)
252-
if model_deployment.freeform_tags else None
318+
319+
aqua_service_model = (
320+
model_deployment.freeform_tags.get(AQUA_SERVICE_MODEL, None)
321+
if model_deployment.freeform_tags
322+
else None
253323
)
254324

255325
# add error handler
256326
# if not aqua_service_model:
257327
# raise AquaClientError(f"Target deployment {model_deployment.id} is not Aqua deployment.")
258328

259-
return AquaDeploymentApp.from_oci_model_deployment(
260-
model_deployment, self.region
261-
)
262-
263-
@classmethod
264-
def from_oci_model_deployment(cls, oci_model_deployment, region) -> "AquaDeployment":
265-
"""Converts oci model deployment response to AquaDeployment instance.
266-
267-
Parameters
268-
----------
269-
oci_model_deployment: oci.data_science.models.ModelDeployment
270-
The oci.data_science.models.ModelDeployment instance.
271-
region: str
272-
The region of this model deployment.
273-
274-
Returns
275-
-------
276-
AquaDeployment:
277-
The instance of the Aqua model deployment.
278-
"""
279-
instance_configuration = (
280-
oci_model_deployment
281-
.model_deployment_configuration_details
282-
.model_configuration_details
283-
.instance_configuration
284-
)
285-
instance_shape_config_details = (
286-
instance_configuration.model_deployment_instance_shape_config_details
287-
)
288-
return AquaDeployment(
289-
id=oci_model_deployment.id,
290-
display_name=oci_model_deployment.display_name,
291-
aqua_service_model=oci_model_deployment.freeform_tags.get(AQUA_SERVICE_MODEL),
292-
state=oci_model_deployment.lifecycle_state,
293-
description=oci_model_deployment.description,
294-
created_on=str(oci_model_deployment.time_created),
295-
created_by=oci_model_deployment.created_by,
296-
endpoint=oci_model_deployment.model_deployment_url,
297-
instance_shape=instance_configuration.instance_shape_name,
298-
ocpus=(
299-
instance_shape_config_details.ocpus
300-
if instance_shape_config_details else None
301-
),
302-
memory_in_gbs=(
303-
instance_shape_config_details.memory_in_gbs
304-
if instance_shape_config_details else None
305-
),
306-
console_link=CONSOLE_LINK_URL.format(oci_model_deployment.id, region)
307-
)
329+
return AquaDeployment.from_oci_model_deployment(model_deployment, self.region)

ads/aqua/extension/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
from ads.aqua.extension.playground_handler import (
1616
__handlers__ as __playground_handlers__,
1717
)
18+
from ads.aqua.extension.ui_handler import __handlers__ as __ui_handlers__
1819

1920
__handlers__ = (
2021
__playground_handlers__
2122
+ __job_handlers__
2223
+ __model_handlers__
2324
+ __common_handlers__
2425
+ __deployment_handlers__
26+
+ __ui_handlers__
2527
)
2628

2729

ads/aqua/extension/deployment_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class AquaDeploymentHandler(AquaAPIhandler):
3232

3333
def get(self, id=""):
3434
"""Handle GET request."""
35-
# todo: handle list, read and logs for model deployment
3635
if not id:
3736
return self.list()
3837
return self.read(id)
@@ -112,7 +111,8 @@ def post(self, *args, **kwargs):
112111
AquaDeploymentApp().create(
113112
compartment_id=compartment_id,
114113
project_id=project_id,
115-
# todo: replace model_id with aqua_model.id
114+
# todo: replace model_id with aqua_model.id, use current model for deploy
115+
# but replace with model by reference is implemented
116116
model_id=model_id,
117117
aqua_service_model=aqua_service_model,
118118
display_name=display_name,

ads/aqua/extension/ui_handler.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
# Copyright (c) 2024 Oracle and/or its affiliates.
4+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5+
6+
from tornado.web import HTTPError
7+
from urllib.parse import urlparse
8+
from ads.aqua.extension.base_handler import AquaAPIhandler
9+
from ads.aqua.ui import AquaUIApp
10+
11+
12+
class AquaUIHandler(AquaAPIhandler):
13+
"""
14+
Handler for Aqua UI REST APIs.
15+
16+
Methods
17+
-------
18+
get(self, id="")
19+
Routes the request to fetch log groups, log ids details or compartments
20+
list_log_groups(self, id: str)
21+
Reads the AQUA deployment information.
22+
list_logs(self, log_group_id: str, **kwargs)
23+
Lists the specified log group's log objects.
24+
list_compartments(self, **kwargs)
25+
Lists the compartments in a compartment specified by ODSC_MODEL_COMPARTMENT_OCID env variable.
26+
27+
Raises
28+
------
29+
HTTPError: For various failure scenarios such as invalid input format, missing data, etc.
30+
"""
31+
32+
def get(self, id=""):
33+
"""Handle GET request."""
34+
url_parse = urlparse(self.request.path)
35+
paths = url_parse.path.strip("/")
36+
if paths.startswith("aqua/logging"):
37+
if not id:
38+
return self.list_log_groups()
39+
return self.list_logs(id)
40+
elif paths.startswith("aqua/compartments"):
41+
return self.list_compartments()
42+
else:
43+
raise HTTPError(400, f"The request {self.request.path} is invalid.")
44+
45+
def list_log_groups(self, **kwargs):
46+
"""Lists all log groups for the specified compartment or tenancy."""
47+
compartment_id = self.get_argument("compartment_id")
48+
try:
49+
return self.finish(
50+
AquaUIApp().list_log_groups(compartment_id=compartment_id, **kwargs)
51+
)
52+
except Exception as ex:
53+
raise HTTPError(500, str(ex))
54+
55+
def list_logs(self, log_group_id: str, **kwargs):
56+
"""Lists the specified log group's log objects."""
57+
try:
58+
return self.finish(
59+
AquaUIApp().list_logs(log_group_id=log_group_id, **kwargs)
60+
)
61+
except Exception as ex:
62+
raise HTTPError(500, str(ex))
63+
64+
def list_compartments(self, **kwargs):
65+
"""Lists the compartments in a compartment specified by ODSC_MODEL_COMPARTMENT_OCID env variable."""
66+
try:
67+
return self.finish(AquaUIApp().list_compartments(**kwargs))
68+
except Exception as ex:
69+
raise HTTPError(500, str(ex))
70+
71+
72+
__handlers__ = [
73+
("logging/?([^/]*)", AquaUIHandler),
74+
("compartments/?([^/]*)", AquaUIHandler),
75+
]

0 commit comments

Comments
 (0)