|
14 | 14 |
|
15 | 15 | from azure.ai.ml._telemetry import ActivityType, monitor_with_activity, monitor_with_telemetry_mixin
|
16 | 16 | from azure.ai.ml._utils._logger_utils import OpsLogger
|
17 |
| -from azure.ai.ml.entities import Job, Schedule |
| 17 | +from azure.ai.ml.entities import Job, JobSchedule, Schedule |
| 18 | +from azure.ai.ml.entities._monitoring.schedule import MonitorSchedule |
18 | 19 | from azure.core.credentials import TokenCredential
|
19 | 20 | from azure.core.polling import LROPoller
|
20 | 21 | from azure.core.tracing.decorator import distributed_trace
|
21 | 22 |
|
22 | 23 | from .._restclient.v2022_10_01.models import ScheduleListViewType
|
| 24 | +from .._utils._arm_id_utils import is_ARM_id_for_parented_resource |
| 25 | +from .._utils.utils import snake_to_camel |
23 | 26 | from .._utils._azureml_polling import AzureMLPolling
|
24 |
| -from ..constants._common import AzureMLResourceType, LROConfigurations |
| 27 | +from ..constants._common import ( |
| 28 | + ARM_ID_PREFIX, |
| 29 | + AzureMLResourceType, |
| 30 | + LROConfigurations, |
| 31 | + NAMED_RESOURCE_ID_FORMAT_WITH_PARENT, |
| 32 | + AZUREML_RESOURCE_PROVIDER, |
| 33 | +) |
| 34 | +from ..constants._monitoring import MonitorSignalType |
25 | 35 | from . import JobOperations
|
26 | 36 | from ._job_ops_helper import stream_logs_until_completion
|
27 | 37 | from ._operation_orchestrator import OperationOrchestrator
|
@@ -171,10 +181,14 @@ def begin_create_or_update(
|
171 | 181 | :rtype: Union[LROPoller, ~azure.ai.ml.entities.Schedule]
|
172 | 182 | """
|
173 | 183 |
|
174 |
| - schedule._validate(raise_error=True) |
175 |
| - if isinstance(schedule.create_job, Job): |
176 |
| - # Create all dependent resources for job inside schedule |
177 |
| - self._job_operations._resolve_arm_id_or_upload_dependencies(schedule.create_job) |
| 184 | + if isinstance(schedule, JobSchedule): |
| 185 | + schedule._validate(raise_error=True) |
| 186 | + if isinstance(schedule.create_job, Job): |
| 187 | + # Create all dependent resources for job inside schedule |
| 188 | + self._job_operations._resolve_arm_id_or_upload_dependencies(schedule.create_job) |
| 189 | + elif isinstance(schedule, MonitorSchedule): |
| 190 | + # resolve ARM id for target, compute, and input datasets for each signal |
| 191 | + self._resolve_monitor_schedule_arm_id(schedule) |
178 | 192 | # Create schedule
|
179 | 193 | schedule_data = schedule._to_rest_object()
|
180 | 194 | poller = self.service_client.begin_create_or_update(
|
@@ -221,3 +235,64 @@ def begin_disable(
|
221 | 235 | schedule = self.get(name=name)
|
222 | 236 | schedule._is_enabled = False
|
223 | 237 | return self.begin_create_or_update(schedule)
|
| 238 | + |
| 239 | + def _resolve_monitor_schedule_arm_id(self, schedule: MonitorSchedule) -> None: |
| 240 | + # resolve compute ID |
| 241 | + schedule.create_monitor.compute = self._orchestrators.get_asset_arm_id( |
| 242 | + schedule.create_monitor.compute, AzureMLResourceType.COMPUTE, register_asset=False |
| 243 | + ) |
| 244 | + |
| 245 | + # resolve target ARM ID |
| 246 | + target = schedule.create_monitor.monitoring_target |
| 247 | + if target and target.endpoint_deployment_id: |
| 248 | + target.endpoint_deployment_id = ( |
| 249 | + target.endpoint_deployment_id[len(ARM_ID_PREFIX) :] |
| 250 | + if target.endpoint_deployment_id.startswith(ARM_ID_PREFIX) |
| 251 | + else target.endpoint_deployment_id |
| 252 | + ) |
| 253 | + |
| 254 | + # if it is an ARM ID, don't process it |
| 255 | + if not is_ARM_id_for_parented_resource( |
| 256 | + target.endpoint_deployment_id, |
| 257 | + snake_to_camel(AzureMLResourceType.ONLINE_ENDPOINT), |
| 258 | + AzureMLResourceType.DEPLOYMENT, |
| 259 | + ): |
| 260 | + endpoint_name, deployment_name = target.endpoint_deployment_id.split(":") |
| 261 | + target.endpoint_deployment_id = NAMED_RESOURCE_ID_FORMAT_WITH_PARENT.format( |
| 262 | + self._subscription_id, |
| 263 | + self._resource_group_name, |
| 264 | + AZUREML_RESOURCE_PROVIDER, |
| 265 | + self._workspace_name, |
| 266 | + snake_to_camel(AzureMLResourceType.ONLINE_ENDPOINT), |
| 267 | + endpoint_name, |
| 268 | + AzureMLResourceType.DEPLOYMENT, |
| 269 | + deployment_name, |
| 270 | + ) |
| 271 | + |
| 272 | + elif target and target.model_id: |
| 273 | + target.model_id = self._orchestrators.get_asset_arm_id( |
| 274 | + target.model_id, |
| 275 | + AzureMLResourceType.MODEL, |
| 276 | + register_asset=False, |
| 277 | + ) |
| 278 | + |
| 279 | + # resolve input paths and preprocessing component ids |
| 280 | + for signal in schedule.create_monitor.monitoring_signals.values(): |
| 281 | + if signal.type == MonitorSignalType.CUSTOM: |
| 282 | + for input_value in signal.input_datasets.values(): |
| 283 | + self._job_operations._resolve_job_input(input_value.input_dataset, schedule._base_path) |
| 284 | + input_value.pre_processing_component = self._orchestrators.get_asset_arm_id( |
| 285 | + asset=input_value.pre_processing_component, azureml_type=AzureMLResourceType.COMPONENT |
| 286 | + ) |
| 287 | + else: |
| 288 | + self._job_operations._resolve_job_inputs( |
| 289 | + [signal.target_dataset.dataset.input_dataset, signal.baseline_dataset.input_dataset], |
| 290 | + schedule._base_path, |
| 291 | + ) |
| 292 | + signal.target_dataset.dataset.pre_processing_component = self._orchestrators.get_asset_arm_id( |
| 293 | + asset=signal.target_dataset.dataset.pre_processing_component, |
| 294 | + azureml_type=AzureMLResourceType.COMPONENT, |
| 295 | + ) |
| 296 | + signal.baseline_dataset.pre_processing_component = self._orchestrators.get_asset_arm_id( |
| 297 | + asset=signal.baseline_dataset.pre_processing_component, azureml_type=AzureMLResourceType.COMPONENT |
| 298 | + ) |
0 commit comments