Source code for wxc_sdk.telephony.jobs

"""
Jobs API
"""
import json
from collections.abc import Generator
from dataclasses import dataclass
from datetime import datetime
from typing import Optional

from pydantic import Field

from ...base import ApiModel
from ...common import DeviceCustomization
from ...rest import RestSession
from ...api_child import ApiChild

__all__ = ['StepExecutionStatus', 'JobExecutionStatus', 'StartJobResponse', 'JobErrorMessage', 'JobError',
           'JobErrorItem', 'JobsApi', 'DeviceSettingsJobsApi', 'NumberItem', 'MoveNumberCounts', 'NumberJob',
           'ErrorMessageObject', 'ErrorObject', 'ManageNumberErrorItem', 'ManageNumbersJobsApi']


[docs]class StepExecutionStatus(ApiModel): #: Unique identifier that identifies each step in a job. id: str #: Step execution start time. start_time: datetime #: Step execution end time. end_time: Optional[datetime] #: Last updated time for a step. last_updated: datetime #: Displays status for a step. status_message: str #: ExitCode for a step. exit_code: str #: Step name. name: str #: Time lapsed since the step execution started. time_elapsed: str
[docs]class JobExecutionStatus(ApiModel): #: Unique identifier that identifies each instance of the job. id: str #: Step execution start time. start_time: Optional[datetime] #: Step execution end time. end_time: Optional[datetime] #: Last updated time post one of the step execution completion. last_updated: datetime #: Displays status for overall steps that are part of the job. status_message: str #: Exit code for a job. exit_code: str #: Job creation time. created_time: datetime #: Time lapsed since the job execution started. time_elapsed: str #: Status of each step within a job. step_execution_statuses: list[StepExecutionStatus] = Field(default_factory=list)
[docs]class StartJobResponse(ApiModel): #: Job name. name: Optional[str] #: Unique identifier of the job. id: str #: Unique identifier to track the flow of HTTP requests. tracking_id: str #: Unique identifier to identify which user has run the job. source_user_id: str #: Unique identifier to identify the customer who has run the job. source_customer_id: str #: Unique identifier to identify the customer for which the job was run. target_customer_id: str #: Unique identifier to identify the instance of the job. instance_id: str #: Displays the most recent step's execution status. Contains execution statuses of all the steps involve in the #: execution of the job. job_execution_status: list[JobExecutionStatus] #: Indicates the most recent status (STARTING, STARTED, COMPLETED, or FAILED) of the job at the time of invocation. latest_execution_status: str #: indicates if all the devices within this location will be customized with new requested customizations(if set to #: true) or will be overridden with the one at organization level (if set to false or any other value). This field #: has no effect when the job is being triggered at organization level. location_customizations_enabled: bool #: Indicates if the job was run at organization level ('CUSTOMER') or location ('LOCATION') level. target: str #: Unique location identifier for which the job was run. location_id: str #: name of location for which the job was run, only present for target LOCATION location_name: Optional[str] #: Displays job completion percentage percentage_complete: str device_count: Optional[int]
[docs]class JobErrorMessage(ApiModel): #: Error message. description: str #: Internal error code. code: Optional[str] #: Message describing the location or point of failure. location: Optional[str] location_id: Optional[str]
[docs]class JobError(ApiModel): #: HTTP error code. key: str message: list[JobErrorMessage]
[docs]class JobErrorItem(ApiModel): #: Index of error number. item_number: int #: Unique identifier to track the HTTP requests. tracking_id: str error: JobError
[docs]class DeviceSettingsJobsApi(ApiChild, base='telephony/config/jobs/devices/callDeviceSettings'): """ API for jobs to update device settings at the location and organization level """
[docs] def change(self, location_id: Optional[str], customization: DeviceCustomization, org_id: str = None) -> StartJobResponse: """ Change device settings across organization or locations jobs. Performs bulk and asynchronous processing for all types of device settings initiated by organization and system admins in a stateful persistent manner. This job will modify the requested device settings across all the devices. Whenever a location ID is specified in the request, it will modify the requested device settings only for the devices that are part of the provided location within an organization. Returns a unique job ID which can then be utilized further to retrieve status and errors for the same. Only one job per customer can be running at any given time within the same organization. An attempt to run multiple jobs at the same time will result in a 409 error response. Running a job requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_write. :param location_id: Location within an organization where changes of device settings will be applied to all the devices within it. :type location_id: str :param customization: customization. Atttribute custom_enabled Indicates if all the devices within this location will be customized with new requested customizations(if set to true) or will be overridden with the one at organization level (if set to false or any other value). This field has no effect when the job is being triggered at organization level. :type customization: DeviceCustomization :param org_id: Apply change device settings for all the devices under this organization. :type org_id: str :return: information about the created job :rtype: StartJobResponse """ url = self.ep() params = org_id and {'prgId': org_id} or None body = {} if location_id: body['locationId'] = location_id body['locationCustomizationsEnabled'] = customization.custom_enabled if customization.custom_enabled or not location_id: body['customizations'] = json.loads(customization.customizations.json()) data = self.post(url=url, params=params, json=body) return StartJobResponse.parse_obj(data)
[docs] def list(self, org_id: str = None, **params) -> Generator[StartJobResponse, None, None]: """ List change device settings jobs. Lists all the jobs for jobType calldevicesettings for the given organization in order of most recent one to oldest one irrespective of its status. This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param org_id: Retrieve list of 'calldevicesettings' jobs for this organization. :type org_id: str :param params: optional parameters :return: Generator of :class:`StartJobResponse` instances """ if org_id is not None: params['orgId'] = org_id url = self.ep() # noinspection PyTypeChecker return self.session.follow_pagination(url=url, model=StartJobResponse, params=params)
[docs] def get_status(self, job_id: str, org_id: str = None) -> StartJobResponse: """ Get change device settings job status. Provides details of the job with jobId of jobType calldevicesettings. This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param job_id: Retrieve job details for this jobId. :type job_id: str :param org_id: Retrieve job details for this org :type org_id: str :return: job details :rtype: StartJobResponse """ url = self.ep(job_id) params = org_id and {'orgId': org_id} or None data = self.get(url=url, params=params) return StartJobResponse.parse_obj(data)
[docs] def job_errors(self, job_id: str, org_id: str = None) -> Generator[JobErrorItem, None, None]: """ List change device settings job errors. Lists all error details of the job with jobId of jobType calldevicesettings. This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param job_id: Retrieve job details for this jobId. :param org_id: Retrieve list of jobs for this organization. :return: """ params = org_id and {'orgId': org_id} or None url = self.ep(f'{job_id}/errors') # noinspection PyTypeChecker return self.session.follow_pagination(url=url, model=JobErrorItem, params=params)
[docs]class NumberItem(ApiModel): #: The source location of the numbers to be moved. location_id: Optional[str] #: Indicates the numbers to be moved from one location to another location. numbers: Optional[list[str]]
[docs]class MoveNumberCounts(ApiModel): #: Indicates the total number of phone numbers requested to be moved. total_numbers: Optional[int] #: Indicates the total number of phone numbers successfully deleted. numbers_deleted: Optional[int] #: Indicates the total number of phone numbers successfully moved. numbers_moved: Optional[int] #: Indicates the total number of phone numbers failed. numbers_failed: Optional[int]
[docs]class NumberJob(ApiModel): #: Unique identifier of the job. id: Optional[str] #: job name name: Optional[str] #: Job type. job_type: Optional[str] #: Unique identifier to track the flow of HTTP requests. tracking_id: Optional[str] #: Unique identifier to identify which user has run the job. source_user_id: Optional[str] #: Unique identifier to identify the customer who has run the job. source_customer_id: Optional[str] #: Unique identifier to identify the customer for which the job was run. target_customer_id: Optional[str] #: Unique identifier to identify the instance of the job. instance_id: Optional[int] #: Displays the most recent step's execution status. Contains execution statuses of all the steps involved in the # execution of the job. job_execution_status: Optional[list[JobExecutionStatus]] #: Indicates the most recent status (STARTING, STARTED, COMPLETED, FAILED) of the job at the time of invocation. latest_execution_status: Optional[str] #: Indicates operation type that was carried out. operation_type: Optional[str] #: Unique location identifier for which the job was run. source_location_id: Optional[str] #: Unique location identifier for which the numbers have been moved. target_location_id: Optional[str] #: The location name for which the job was run. source_location_name: Optional[str] #: The location name for which the numbers have been moved. target_location_name: Optional[str] #: Job statistics. counts: Optional[MoveNumberCounts]
[docs]class ErrorMessageObject(ApiModel): code: Optional[str] description: Optional[str] #: Error messages describing the location id in which the error occurs. For a move operation this is the target # location ID. location_id: Optional[str]
[docs]class ErrorObject(ApiModel): #: HTTP error code. key: Optional[str] message: Optional[list[ErrorMessageObject]]
[docs]class ManageNumberErrorItem(ApiModel): #: Phone number item: Optional[str] #: Index of error number. item_number: Optional[int] #: Unique identifier to track the HTTP requests. tracking_id: Optional[str] error: Optional[ErrorObject]
class InitiateMoveNumberJobsBody(ApiModel): #: Indicates the kind of operation to be carried out. operation: Optional[str] #: The target location within organization where the unassigned numbers will be moved from the source location. target_location_id: Optional[str] #: Indicates the numbers to be moved from source to target locations. number_list: Optional[list[NumberItem]]
[docs]class ManageNumbersJobsApi(ApiChild, base='telephony/config/jobs/numbers'): """ API for jobs to manage numbers """
[docs] def list_jobs(self, org_id: str = None, **params) -> Generator[NumberJob, None, None]: """ Lists all Manage Numbers jobs for the given organization in order of most recent one to oldest one irrespective of its status. The public API only supports initiating jobs which move numbers between locations. Via Control Hub they can initiate both the move and delete, so this listing can show both. This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param org_id: Retrieve list of Manage Number jobs for this organization. :type org_id: str """ if org_id is not None: params['orgId'] = org_id url = self.ep('manageNumbers') return self.session.follow_pagination(url=url, model=NumberJob, params=params)
[docs] def initiate_job(self, operation: str, target_location_id: str, number_list: list[NumberItem]) -> NumberJob: """ Starts the numbers move from one location to another location. Although jobs can do both MOVE and DELETE actions internally, only MOVE is supported publicly. In order to move a number, For example, you can move from Cisco PSTN to Cisco PSTN, but you cannot move from Cisco PSTN to a location with Cloud Connected PSTN. This API requires a full administrator auth token with a scope of spark-admin:telephony_config_write. :param operation: Indicates the kind of operation to be carried out. :type operation: str :param target_location_id: The target location within organization where the unassigned numbers will be moved from the source location. :type target_location_id: str :param number_list: Indicates the numbers to be moved from source to target locations. :type number_list: list[NumberItem] """ body = InitiateMoveNumberJobsBody(operation=operation, target_location_id=target_location_id, number_list=number_list) url = self.ep('manageNumbers') data = super().post(url=url, data=body.json()) return NumberJob.parse_obj(data)
[docs] def job_status(self, job_id: str = None) -> NumberJob: """ Returns the status and other details of the job. This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param job_id: Retrieve job details for this jobId. :type job_id: str """ url = self.ep(f'manageNumbers/{job_id}') data = super().get(url=url) return NumberJob.parse_obj(data)
[docs] def pause_job(self, job_id: str = None, org_id: str = None): """ Pause the running Manage Numbers Job. A paused job can be resumed or abandoned. This API requires a full administrator auth token with a scope of spark-admin:telephony_config_write. :param job_id: Pause the Manage Numbers job for this jobId. :type job_id: str :param org_id: Pause the Manage Numbers job for this organization. :type org_id: str """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'manageNumbers/{job_id}/actions/pause/invoke') super().post(url=url, params=params) return
[docs] def resume_job(self, job_id: str = None, org_id: str = None): """ Resume the paused Manage Numbers Job. A paused job can be resumed or abandoned. This API requires a full administrator auth token with a scope of spark-admin:telephony_config_write. :param job_id: Resume the Manage Numbers job for this jobId. :type job_id: str :param org_id: Resume the Manage Numbers job for this organization. :type org_id: str """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'manageNumbers/{job_id}/actions/resume/invoke') super().post(url=url, params=params) return
[docs] def abandon_job(self, job_id: str = None, org_id: str = None): """ Abandon the Manage Numbers Job. This API requires a full administrator auth token with a scope of spark-admin:telephony_config_write. :param job_id: Abandon the Manage Numbers job for this jobId. :type job_id: str :param org_id: Abandon the Manage Numbers job for this organization. :type org_id: str """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'manageNumbers/{job_id}/actions/abandon/invoke') super().post(url=url, params=params) return
[docs] def list_job_errors(self, job_id: str = None, org_id: str = None, **params) -> Generator[ManageNumberErrorItem, None, None]: """ Lists all error details of Manage Numbers job. This will not list any errors if exitCode is COMPLETED. If the status is COMPLETED_WITH_ERRORS then this lists the cause of failures. List of possible Errors: This API requires a full or read-only administrator auth token with a scope of spark-admin:telephony_config_read. :param job_id: Retrieve the error details for this jobId. :type job_id: str :param org_id: Retrieve list of jobs for this organization. :type org_id: str """ if org_id is not None: params['orgId'] = org_id url = self.ep(f'manageNumbers/{job_id}/errors') return self.session.follow_pagination(url=url, model=ManageNumberErrorItem, params=params)
[docs]@dataclass(init=False) class JobsApi(ApiChild, base='telephony/config/jobs'): """ Jobs API """ #: API for device settings jobs device_settings: DeviceSettingsJobsApi #: API for manage numbers jobs manage_numbers: ManageNumbersJobsApi def __init__(self, *, session: RestSession): super().__init__(session=session) self.device_settings = DeviceSettingsJobsApi(session=session) self.manage_numbers = ManageNumbersJobsApi(session=session)