Beispiel #1
0
    def _add_base_image_to_payload(self, json_payload):
        if self.base_image:
            if not self.runtime.lower(
            ) in CUSTOM_BASE_IMAGE_SUPPORTED_RUNTIMES.keys():
                runtimes = '|'.join(
                    CUSTOM_BASE_IMAGE_SUPPORTED_RUNTIMES.keys())
                raise WebserviceException(
                    'Custom base image is not supported for {} run time. '
                    'Supported runtimes are: {}'.format(
                        self.runtime, runtimes),
                    logger=module_logger)
            json_payload['baseImage'] = self.base_image
            json_payload['targetRuntime'][
                'runtimeType'] = CUSTOM_BASE_IMAGE_SUPPORTED_RUNTIMES[
                    self.runtime.lower()]

            if self.base_image_registry is not None:
                if self.base_image_registry.address and \
                        self.base_image_registry.username and \
                        self.base_image_registry.password:
                    json_payload['baseImageRegistryInfo'] = {
                        'location': self.base_image_registry.address,
                        'user': self.base_image_registry.username,
                        'password': self.base_image_registry.password
                    }
                elif self.base_image_registry.address or \
                        self.base_image_registry.username or \
                        self.base_image_registry.password:
                    raise WebserviceException(
                        'Address, Username and Password '
                        'must be provided for base image registry',
                        logger=module_logger)
Beispiel #2
0
    def convert_model(self, request):
        """
        :param request:
        :type request: ModelConvertRequest
        :return: submit model conversion and return opertion id
        :rtype: str
        """

        headers = {'Content-Type': 'application/json'}
        headers.update(self._workspace._auth.get_authentication_header())
        params = {'api-version': MMS_WORKSPACE_API_VERSION}

        if request.model_id:
            model_endpoint = self._mms_endpoint + '/models' + '/{}/convert'.format(
                request.model_id)
        else:
            raise Exception(
                'Model id is missing in the request {}.'.format(request))

        json_payload = json.loads(request.toJSON())

        try:
            resp = requests.post(model_endpoint,
                                 params=params,
                                 headers=headers,
                                 json=json_payload)
            resp.raise_for_status()
        except requests.ConnectionError:
            raise Exception('Error connecting to {}.'.format(model_endpoint))
        except requests.exceptions.HTTPError:
            raise Exception(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content))

        if resp.status_code != 202:
            raise WebserviceException('Error occurred converting model:\n'
                                      'Response Code: {}\n'
                                      'Headers: {}\n'
                                      'Content: {}'.format(
                                          resp.status_code, resp.headers,
                                          resp.content))

        if 'Operation-Location' in resp.headers:
            operation_location = resp.headers['Operation-Location']
        else:
            raise WebserviceException(
                'Missing response header key: Operation-Location')

        operation_status_id = operation_location.split('/')[-1]

        return operation_status_id
Beispiel #3
0
    def get_operation_state(self, operation_id):
        """
        :param operation_id:
        :type operation_id: str
        :return: operation state, operation content
        :rtype: (str, object)
        """
        headers = {'Content-Type': 'application/json'}
        headers.update(self._workspace._auth.get_authentication_header())
        params = {'api-version': MMS_WORKSPACE_API_VERSION}

        operation_endpoint = self._mms_endpoint + '/operations/{}'.format(
            operation_id)
        resp = requests.get(operation_endpoint,
                            headers=headers,
                            params=params,
                            timeout=MMS_SYNC_TIMEOUT_SECONDS)
        try:
            resp.raise_for_status()
        except requests.exceptions.HTTPError:
            raise WebserviceException(
                'Received bad response from Resource Provider:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content))
        content = resp.content
        if isinstance(content, bytes):
            content = content.decode('utf-8')
        content = json.loads(content)
        state = content['state']
        return state, content
Beispiel #4
0
    def update(self, tags):
        """Update the image.

        :param tags: A dictionary of tags to update the image with. Will overwrite any existing tags.
        :type tags: dict[str, str]
        :raises: azureml.exceptions.WebserviceException
        """
        headers = {'Content-Type': 'application/json-patch+json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        patch_list = []
        self.tags = tags
        patch_list.append({
            'op': 'replace',
            'path': '/kvTags',
            'value': self.tags
        })

        resp = ClientBase._execute_func(get_requests_session().patch,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        json=patch_list,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code >= 400:
            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)
Beispiel #5
0
    def model_error_response_to_webservice_exception(ex, **kwargs):
        if not isinstance(ex, ModelErrorResponseException):
            raise WebserviceException(
                'Received unexpected exception: {}'.format(ex),
                logger=module_logger)

        if ex.error.status_code == 404:
            error_message = populate_model_not_found_details(**kwargs)

            raise WebserviceException(error_message, logger=module_logger)

        raise WebserviceException(
            'Received bad response from Model Management Service:\n'
            'Response Code: {}\n'
            'Correlation: {}\n'
            'Content: {}'.format(ex.error.status_code, ex.error.correlation,
                                 ex.error.details),
            logger=module_logger)
Beispiel #6
0
def _extract_credentials(registry_dict):
    try:
        username = registry_dict["containerRegistryCredentials"]["username"]
        passwords = registry_dict["containerRegistryCredentials"]["passwords"]
        password = passwords[0]["value"]
    except KeyError:
        raise WebserviceException(
            "Unable to retrieve workspace keys to run image, response "
            "payload missing container registry credentials.")

    return username, password
Beispiel #7
0
    def wait_for_creation(self, show_output=False):
        """Wait for the image to finish creating.

        Wait for image creation to reach a terminal state. Will throw a WebserviceException if it reaches a
        non-successful terminal state.

        :param show_output: Boolean option to print more verbose output. Defaults to False.
        :type show_output: bool
        :raises: azureml.exceptions.WebserviceException
        """
        operation_state, error = self._get_operation_state()
        current_state = operation_state

        if show_output:
            sys.stdout.write('{}'.format(current_state))
            sys.stdout.flush()

        while operation_state != 'Cancelled' and operation_state != 'Succeeded' and operation_state != 'Failed' \
                and operation_state != 'TimedOut':
            time.sleep(5)
            operation_state, error = self._get_operation_state()
            if show_output:
                sys.stdout.write('.')
                if operation_state != current_state:
                    sys.stdout.write('\n{}'.format(operation_state))
                    current_state = operation_state
                sys.stdout.flush()
        sys.stdout.write('\n')
        sys.stdout.flush()

        self.update_creation_state()
        if operation_state != 'Succeeded':
            if error and 'statusCode' in error and 'message' in error:
                error_response = ('StatusCode: {}\n'
                                  'Message: {}'.format(error['statusCode'],
                                                       error['message']))
            else:
                error_response = error

            print(
                'More information about this error is available here: {}\n'
                'For more help with troubleshooting, see https://aka.ms/debugimage'
                .format(self.image_build_log_uri))
            raise WebserviceException(
                'Image creation polling reached non-successful terminal state, '
                'current state: {}\n'
                'Error response from server:\n'
                '{}'.format(self.creation_state, error_response),
                logger=module_logger)

        print('Image creation operation finished for image {}, operation "{}"'.
              format(self.id, operation_state))
Beispiel #8
0
    def update_creation_state(self):
        """Refresh the current state of the in-memory object.

        Perform an in-place update of the properties of the object based on the current state of the
        corresponding cloud object. Primarily useful for manual polling of creation state.

        :raises: azureml.exceptions.WebserviceException
        """
        headers = {'Content-Type': 'application/json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        resp = ClientBase._execute_func(get_requests_session().get,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code == 200:
            image = Image(self.workspace, id=self.id)
            for key in image.__dict__.keys():
                if key is not "_operation_endpoint":
                    self.__dict__[key] = image.__dict__[key]
        elif resp.status_code == 404:
            raise WebserviceException('Error: image {} not found:\n'
                                      'Response Code: {}\n'
                                      'Headers: {}\n'
                                      'Content: {}'.format(
                                          self.id, resp.status_code,
                                          resp.headers, resp.content),
                                      logger=module_logger)
        else:
            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)
Beispiel #9
0
    def _get_operation_state(self):
        """Get the current async operation state for the image.

        :return:
        :rtype: (str, dict)
        """
        if not self._operation_endpoint:
            self.update_deployment_state()
            raise WebserviceException(
                'Long running operation information not known, unable to poll. '
                'Current state is {}'.format(self.creation_state),
                logger=module_logger)

        headers = {'Content-Type': 'application/json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        resp = ClientBase._execute_func(get_requests_session().get,
                                        self._operation_endpoint,
                                        headers=headers,
                                        params=params,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)
        try:
            resp.raise_for_status()
        except requests.exceptions.HTTPError:
            raise WebserviceException(
                'Received bad response from Resource Provider:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)
        content = resp.content
        if isinstance(content, bytes):
            content = content.decode('utf-8')
        content = json.loads(content)
        state = content['state']
        error = content['error'] if 'error' in content else None
        return state, error
Beispiel #10
0
    def _validate_get_payload(cls, payload):
        """Validate the returned _ModelEvaluationResultBase payload.

        :param payload:
        :type payload: dict
        :return:
        :rtype: None
        """
        for payload_key in cls._expected_payload_keys:
            if payload_key not in payload:
                raise WebserviceException(
                    'Invalid payload for %s, missing %s:\n %s'
                    % (cls._model_eval_type, payload_key, payload)
                )
Beispiel #11
0
    def _validate_get_payload(cls, payload):
        """Validate the returned image payload.

        :param payload:
        :type payload: dict
        :return:
        :rtype: None
        """
        for payload_key in cls._expected_payload_keys:
            if payload_key not in payload:
                raise WebserviceException(
                    'Invalid image payload, missing {} for image:\n'
                    '{}'.format(payload_key, payload),
                    logger=module_logger)
Beispiel #12
0
    def create_local_debug_payload(self, workspace, model_ids):
        """
        Build the creation payload for the Container image.

        :param workspace: The workspace object to create the image in.
        :type workspace: azureml.core.Workspace
        :param model_ids: A list of model IDs to package into the image.
        :type model_ids: builtin.list[str]
        :return: Container image creation payload.
        :rtype: dict
        :raises: azureml.exceptions.WebserviceException
        """
        import copy
        from azureml._model_management._util import image_payload_template

        json_payload = copy.deepcopy(image_payload_template)
        json_payload['name'] = 'local'
        json_payload['kvTags'] = self.tags
        json_payload['imageFlavor'] = WEBAPI_IMAGE_FLAVOR
        json_payload['properties'] = self.properties
        json_payload['description'] = self.description
        json_payload['targetRuntime']['runtimeType'] = SUPPORTED_RUNTIMES[
            self.runtime.lower()]
        json_payload['targetRuntime'][
            'targetArchitecture'] = ARCHITECTURE_AMD64

        if self.enable_gpu or self.cuda_version:
            raise WebserviceException('Local web services do not support GPUs',
                                      logger=module_logger)

        json_payload['targetRuntime']['properties'][
            'pipRequirements'] = "requirements.txt"

        if self.docker_file:
            docker_file = self.docker_file.rstrip(os.sep)
            (json_payload['dockerFileUri'],
             _) = upload_dependency(workspace, docker_file)

        if self.conda_file:
            conda_file = self.conda_file.rstrip(os.sep)
            json_payload['targetRuntime']['properties'][
                'condaEnvFile'] = os.path.basename(conda_file)

        if model_ids:
            json_payload['modelIds'] = model_ids

        self._add_base_image_to_payload(json_payload)

        return json_payload
Beispiel #13
0
    def delete(self):
        """Delete an image from its corresponding workspace.

        .. remarks::

            This method fails if the image has been deployed to a live webservice.

        :raises: azureml.exceptions.WebserviceException
        """
        headers = self._auth.get_authentication_header()
        params = {}

        resp = ClientBase._execute_func(get_requests_session().delete,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code >= 400:
            if resp.status_code == 412 and "DeletionRequired" in resp.content:
                raise WebserviceException(
                    'The image cannot be deleted because it is currently being used in one or '
                    'more webservices. To know what webservices contain the image, run '
                    '"Webservice.list(<workspace>, image_id={})"'.format(
                        self.id),
                    logger=module_logger)

            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)
        else:
            self.creation_state = 'Deleting'
Beispiel #14
0
    def deserialize(payload_obj):
        """Convert a JSON object into a ResourceConfiguration object.

        :param payload_obj: A JSON object to convert to a ResourceConfiguration object.
        :type payload_obj: dict
        :return: The ResourceConfiguration representation of the provided JSON object.
        :rtype: azureml.core.resource_configuration.ResourceConfiguration
        """
        if payload_obj is None:
            return None
        for payload_key in ResourceConfiguration._expected_payload_keys:
            if payload_key not in payload_obj:
                raise WebserviceException('Invalid webservice payload, missing {} for ResourceConfiguration:\n'
                                          '{}'.format(payload_key, payload_obj), logger=module_logger)

        return ResourceConfiguration(payload_obj['cpu'], payload_obj['memoryInGB'], payload_obj['gpu'])
Beispiel #15
0
    def remove_tags(self, tags):
        """Remove tags from the image.

        :param tags: A list of keys corresponding to tags to be removed.
        :type tags: builtin.list[str]
        :raises: azureml.exceptions.WebserviceException
        """
        headers = {'Content-Type': 'application/json-patch+json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        patch_list = []
        if self.tags is None:
            print('Image has no tags to remove.')
            return
        else:
            if type(tags) is not list:
                tags = [tags]
            for key in tags:
                if key in self.tags:
                    del self.tags[key]
                else:
                    print('Tag with key {} not found.'.format(key))

        patch_list.append({
            'op': 'replace',
            'path': '/kvTags',
            'value': self.tags
        })

        resp = ClientBase._execute_func(get_requests_session().patch,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        json=patch_list,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code >= 400:
            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)

        print('Image tag remove operation complete.')
Beispiel #16
0
    def _validate_configuration(self):
        """Check that the specified configuration values are valid.

        Will raise a :class:`azureml.exceptions.WebserviceException` if validation fails.

        :raises: azureml.exceptions.WebserviceException
        """
        error = ""
        if self.cpu and self.cpu <= 0:
            error += 'Invalid configuration, cpu must be greater than zero.\n'
        if self.memory_in_gb and self.memory_in_gb <= 0:
            error += 'Invalid configuration, memory_in_gb must be greater than zero.\n'
        if self.gpu and not isinstance(self.gpu, int) and self.gpu <= 0:
            error += 'Invalid configuration, gpu must be integer and greater than zero.\n'

        if error:
            raise WebserviceException(error, logger=module_logger)
Beispiel #17
0
 def diagnostics(self, uri):
     """
     Retrieves the diagnostics in the working directory of the current run.
     """
     auth = self.run._service_context.get_auth()
     headers = auth.get_authentication_header()
     with create_session_with_retry() as session:
         try:
             response = ClientBase._execute_func(session.get, uri, headers=headers)
             response.raise_for_status()
         except requests.exceptions.HTTPError:
             raise WebserviceException('Received bad response from Execution Service:\n'
                                       'Response Code: {}\n'
                                       'Headers: {}\n'
                                       'Content: {}'.format(response.status_code, response.headers,
                                                            response.content),
                                       logger=module_logger)
     return response
Beispiel #18
0
    def deserialize(payload_obj):
        """Convert a JSON object into an Asset object.

        :param payload_obj: A JSON object to convert to an Asset object.
        :type payload_obj: dict
        :return: The Asset representation of the provided JSON object.
        :rtype: Asset
        :raises: azureml.exceptions.WebserviceException
        """
        for payload_key in Asset._expected_payload_keys:
            if payload_key not in payload_obj:
                raise WebserviceException(
                    'Invalid image payload, missing {} for asset:\n'
                    '{}'.format(payload_key, payload_obj),
                    logger=module_logger)

        return Asset(payload_obj['id'], payload_obj['mimeType'],
                     payload_obj['unpack'], payload_obj['url'])
Beispiel #19
0
    def run(self, input_data):
        """
        Run the image locally with the given input data.

        Must have Docker installed and running to work. This method will only work on CPU, as the GPU-enabled image
        can only run on Microsoft Azure Services.

        :param input_data: The input data to pass to the image when run
        :type input_data: varies
        :return: The results of running the image.
        :rtype: varies
        :raises: azureml.exceptions.WebserviceException
        """
        if not input_data:
            raise WebserviceException('Error: You must provide input data.',
                                      logger=module_logger)

        username, password = get_workspace_registry_credentials(self.workspace)

        client = get_docker_client()
        login_to_docker_registry(client, username, password,
                                 self.image_location)

        pull_docker_image(client, self.image_location, username, password)

        ports = {
            DOCKER_IMAGE_HTTP_PORT: ('127.0.0.1', None)
        }  # None assigns a random free port.

        container_name = self.id + str(uuid.uuid4())[:8]
        container = run_docker_container(client,
                                         self.image_location,
                                         container_name,
                                         ports=ports)

        docker_port = get_docker_port(client, container_name, container)

        docker_url = container_health_check(docker_port, container)

        scoring_result = container_scoring_call(docker_port, input_data,
                                                container, docker_url)

        cleanup_container(container)
        return scoring_result
Beispiel #20
0
    def add_tags(self, tags):
        """Add tags to the image.

        :param tags: A dictionary of tags to add.
        :type tags: dict[str, str]
        :raises: azureml.exceptions.WebserviceException
        """
        headers = {'Content-Type': 'application/json-patch+json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        patch_list = []
        if self.tags is None:
            self.tags = copy.deepcopy(tags)
        else:
            for key in tags:
                if key in self.tags:
                    print("Replacing tag {} -> {} with {} -> {}".format(
                        key, self.tags[key], key, tags[key]))
                self.tags[key] = tags[key]

        patch_list.append({
            'op': 'replace',
            'path': '/kvTags',
            'value': self.tags
        })

        resp = ClientBase._execute_func(get_requests_session().patch,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        json=patch_list,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code >= 400:
            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)

        print('Image tag add operation complete.')
Beispiel #21
0
    def add_properties(self, properties):
        """Add properties to the image.

        :param properties: A dictionary of properties to add.
        :type properties: dict[str, str]
        :raises: azureml.exceptions.WebserviceException
        """
        check_duplicate_properties(self.properties, properties)

        headers = {'Content-Type': 'application/json-patch+json'}
        headers.update(self._auth.get_authentication_header())
        params = {}

        patch_list = []
        if self.properties is None:
            self.properties = copy.deepcopy(properties)
        else:
            for key in properties:
                self.properties[key] = properties[key]

        patch_list.append({
            'op': 'add',
            'path': '/properties',
            'value': self.properties
        })

        resp = ClientBase._execute_func(get_requests_session().patch,
                                        self._mms_endpoint,
                                        headers=headers,
                                        params=params,
                                        json=patch_list,
                                        timeout=MMS_SYNC_TIMEOUT_SECONDS)

        if resp.status_code >= 400:
            raise WebserviceException(
                'Received bad response from Model Management Service:\n'
                'Response Code: {}\n'
                'Headers: {}\n'
                'Content: {}'.format(resp.status_code, resp.headers,
                                     resp.content),
                logger=module_logger)

        print('Image properties add operation complete.')
Beispiel #22
0
def file_stream_to_object(file_stream):
    """
    Take a YAML or JSON file_stream and return the dictionary object.

    :param file_stream: File stream from with open(file) as file_stream
    :type file_stream:
    :return: File dictionary
    :rtype: dict
    """
    file_data = file_stream.read()

    try:
        return yaml.safe_load(file_data)
    except Exception as ex:
        pass

    try:
        return json.loads(file_data)
    except Exception as ex:
        raise WebserviceException('Error while parsing file. Must be valid JSON or YAML file.', content=ex)
Beispiel #23
0
    def _update_creation_state(self):
        """Refresh the current state of the in-memory object.

        Perform an in-place update of the properties of the object based on the current state of the
        corresponding cloud object. Primarily useful for manual polling of creation state.

        :raises: azureml.exceptions.WebserviceException
        """
        resp = get_operation_output(self.workspace, self._model_test_result_suffix, self._model_test_result_params)
        if resp.status_code != 200:
            error_message = 'Model {} result with name {}'.format(
                self.__class__._model_eval_type, self.name
            )
            error_message += ' not found in provided workspace'
            raise WebserviceException(error_message)
        content = resp.content
        if isinstance(content, bytes):
            content = content.decode('utf-8')
        model_test_json = json.loads(content)['value'][0]
        self._validate_get_payload(model_test_json)
        self._initialize(model_test_json)
Beispiel #24
0
    def deserialize(payload_obj):
        """Convert a JSON object into a ContainerResourceRequirements object.

        :param payload_obj: A JSON object to convert to a ContainerResourceRequirements object.
        :type payload_obj: dict
        :return: The ContainerResourceRequirements representation of the provided JSON object.
        :rtype: azureml.core.webservice.webservice.ContainerResourceRequirements
        """
        for payload_key in ContainerResourceRequirements._expected_payload_keys:
            if payload_key not in payload_obj:
                raise WebserviceException(
                    'Invalid webservice payload, missing {} for ContainerResourceRequirements:\n'
                    '{}'.format(payload_key, payload_obj),
                    logger=module_logger)

        return ContainerResourceRequirements(
            cpu=payload_obj['cpu'],
            memory_in_gb=payload_obj['memoryInGB'],
            gpu=payload_obj['gpu'],
            cpu_limit=payload_obj['cpuLimit'],
            memory_in_gb_limit=payload_obj['memoryInGBLimit'])
Beispiel #25
0
    def deserialize(payload_obj):
        """Convert a JSON object into a TargetRuntime object.

        :param payload_obj: A JSON object to convert to a TargetRuntime object.
        :type payload_obj: dict
        :return: The TargetRuntime representation of the provided JSON object.
        :rtype: TargetRuntime
        :raises: azureml.exceptions.WebserviceException
        """
        for payload_key in TargetRuntime._expected_payload_keys:
            if payload_key not in payload_obj:
                raise WebserviceException(
                    'Invalid image payload, missing {} for targetRuntime:\n'
                    '{}'.format(payload_key, payload_obj),
                    logger=module_logger)

        targetArchitecture = ARCHITECTURE_AMD64
        if 'targetArchitecture' in payload_obj:
            targetArchitecture = payload_obj['targetArchitecture']

        return TargetRuntime(payload_obj['properties'],
                             payload_obj['runtimeType'], targetArchitecture)
Beispiel #26
0
def _registry_dict_for(subscription_id, resource_group, workspace_name,
                       authentication_header):
    keys_endpoint = _KEYS_URL.format(subscription_id, resource_group,
                                     workspace_name)
    # headers = self.workspace._auth.get_authentication_header()
    params = {"api-version": WORKSPACE_RP_API_VERSION}
    try:
        keys_resp = requests.post(keys_endpoint,
                                  headers=authentication_header,
                                  params=params)
        keys_resp.raise_for_status()
    except requests.exceptions.HTTPError:
        raise WebserviceException(
            "Unable to retrieve workspace keys to run image:\n"
            "Response Code: {}\n"
            "Headers: {}\n"
            "Content: {}".format(keys_resp.status_code, keys_resp.headers,
                                 keys_resp.content))
    content = keys_resp.content
    if isinstance(content, bytes):
        content = content.decode("utf-8")
    return json.loads(content)
Beispiel #27
0
    def result(self):
        """
        If the model conversion completed return the converted model.

        :return: converted model if convert model operation succeeded.
        :rtype: azureml.core.model
        """
        operation_state, content = self._client.get_operation_state(
            self._operation_id)

        if operation_state == 'Succeeded':
            if 'resourceLocation' in content:
                resource_location = content['resourceLocation']
                model_id = resource_location.split('/')[-1]
                return Model(self._workspace, id=model_id)
            else:
                raise WebserviceException(
                    'Invalid operation payload, missing resourceLocation:\n'
                    '{}'.format(resource_location))
        elif operation_state == 'Cancelled' or operation_state == 'Failed' or operation_state == 'TimedOut':
            raise ValueError("Model conversion is not successful")
        else:
            raise ValueError("Model conversion is not complete")
Beispiel #28
0
    def validate_configuration(self):
        """Check that the specified configuration values are valid.

        Raises a :class:azureml.exceptions.WebserviceException` if validation fails.

        :raises: azureml.exceptions.WebserviceException
        """
        if self.allow_absolute_path is False:
            # The execution script must have a relative path
            if os.path.isabs(self.execution_script):
                raise WebserviceException(
                    'Unable to use absolute path for execution script. '
                    'Use a relative path for execution script and try again.',
                    logger=module_logger)

            # The execution script must be in the current directory
            if not os.getcwd() == self.execution_script_path:
                raise WebserviceException(
                    'Unable to use an execution script not in current directory. '
                    'Please navigate to the location of the execution script and try again.',
                    logger=module_logger)

        validate_path_exists_or_throw(self.execution_script,
                                      "Execution script")

        execution_script_name, execution_script_extension = os.path.splitext(
            os.path.basename(self.execution_script))
        if execution_script_extension != '.py':
            raise WebserviceException(
                'Invalid driver type. Currently only Python drivers are supported.',
                logger=module_logger)
        validate_entry_script_name(execution_script_name)

        if self.runtime.lower() not in SUPPORTED_RUNTIMES.keys():
            runtimes = '|'.join(x for x in SUPPORTED_RUNTIMES.keys()
                                if x not in UNDOCUMENTED_RUNTIMES)
            raise WebserviceException(
                'Provided runtime not supported. '
                'Possible runtimes are: {}'.format(runtimes),
                logger=module_logger)

        if self.cuda_version is not None:
            if self.cuda_version.lower() not in SUPPORTED_CUDA_VERSIONS:
                cuda_versions = '|'.join(SUPPORTED_CUDA_VERSIONS)
                raise WebserviceException(
                    'Provided cuda_version not supported. '
                    'Possible values are: {}'.format(cuda_versions),
                    logger=module_logger)

        if self.conda_file:
            validate_path_exists_or_throw(self.conda_file, "Conda file")

        if self.docker_file:
            validate_path_exists_or_throw(self.docker_file, "Docker file")

        if self.dependencies:
            for dependency in self.dependencies:
                validate_path_exists_or_throw(dependency, "Dependency")

        if self.schema_file:
            validate_path_exists_or_throw(self.schema_file, "Schema file")
            schema_file_path = os.path.abspath(
                os.path.dirname(self.schema_file))
            common_prefix = os.path.commonprefix(
                [self.execution_script_path, schema_file_path])
            if not common_prefix == self.execution_script_path:
                raise WebserviceException(
                    'Schema file must be in the same directory as the execution script, '
                    'or in a subdirectory.',
                    logger=module_logger)
Beispiel #29
0
def submit_update_call(service, models, inference_config, deploy_config, aks_endpoint_version_config):
    if service._webservice_type.lower() == ACI_WEBSERVICE_TYPE.lower():
        # aci update
        service.update(auth_enabled=deploy_config.auth_enabled,
                       ssl_enabled=deploy_config.ssl_enabled,
                       ssl_cert_pem_file=deploy_config.ssl_cert_pem_file,
                       ssl_key_pem_file=deploy_config.ssl_key_pem_file,
                       ssl_cname=deploy_config.ssl_cname,
                       enable_app_insights=deploy_config.enable_app_insights,
                       models=models,
                       inference_config=inference_config)
    elif service._webservice_type.lower() == AKS_WEBSERVICE_TYPE.lower():
        # aks update
        service.update(autoscale_enabled=deploy_config.autoscale_enabled,
                       autoscale_min_replicas=deploy_config.autoscale_min_replicas,
                       autoscale_max_replicas=deploy_config.autoscale_max_replicas,
                       autoscale_refresh_seconds=deploy_config.autoscale_refresh_seconds,
                       autoscale_target_utilization=deploy_config.autoscale_target_utilization,
                       collect_model_data=deploy_config.collect_model_data,
                       auth_enabled=deploy_config.auth_enabled,
                       cpu_cores=deploy_config.cpu_cores,
                       memory_gb=deploy_config.memory_gb,
                       enable_app_insights=deploy_config.enable_app_insights,
                       scoring_timeout_ms=deploy_config.scoring_timeout_ms,
                       replica_max_concurrent_requests=deploy_config.replica_max_concurrent_requests,
                       max_request_wait_time=deploy_config.max_request_wait_time,
                       num_replicas=deploy_config.num_replicas,
                       token_auth_enabled=deploy_config.token_auth_enabled,
                       models=models, inference_config=inference_config,
                       cpu_cores_limit=deploy_config.cpu_cores_limit,
                       memory_gb_limit=deploy_config.memory_gb_limit)
    elif service._webservice_type.lower() == AKS_ENDPOINT_TYPE.lower():
        # aksendpoint update
        if aks_endpoint_version_config and aks_endpoint_version_config['version_operation_type'] is not None:
            version_operation_type = aks_endpoint_version_config['version_operation_type'].lower()
            is_default = aks_endpoint_version_config['is_default']
            is_control_version_type = aks_endpoint_version_config['is_control_version']

            if version_operation_type == AKS_ENDPOINT_CREATE_VERSION.lower():
                service.create_version(
                    version_name=deploy_config.version_name,
                    autoscale_enabled=deploy_config.autoscale_enabled,
                    autoscale_min_replicas=deploy_config.autoscale_min_replicas,
                    autoscale_max_replicas=deploy_config.autoscale_max_replicas,
                    autoscale_refresh_seconds=deploy_config.autoscale_refresh_seconds,
                    autoscale_target_utilization=deploy_config.autoscale_target_utilization,
                    collect_model_data=deploy_config.collect_model_data,
                    cpu_cores=deploy_config.cpu_cores,
                    memory_gb=deploy_config.memory_gb,
                    scoring_timeout_ms=deploy_config.scoring_timeout_ms,
                    replica_max_concurrent_requests=deploy_config.replica_max_concurrent_requests,
                    max_request_wait_time=deploy_config.max_request_wait_time,
                    num_replicas=deploy_config.num_replicas,
                    models=models, inference_config=inference_config,
                    gpu_cores=deploy_config.gpu_cores,
                    period_seconds=deploy_config.period_seconds,
                    initial_delay_seconds=deploy_config.initial_delay_seconds,
                    timeout_seconds=deploy_config.timeout_seconds,
                    success_threshold=deploy_config.success_threshold,
                    failure_threshold=deploy_config.failure_threshold,
                    traffic_percentile=deploy_config.traffic_percentile, is_default=is_default,
                    is_control_version_type=is_control_version_type,
                    cpu_cores_limit=deploy_config.cpu_cores_limit,
                    memory_gb_limit=deploy_config.memory_gb_limit)
            elif version_operation_type == AKS_ENDPOINT_DELETE_VERSION.lower():
                service.delete_version(version_name=deploy_config.version_name)
            elif version_operation_type == AKS_ENDPOINT_UPDATE_VERSION.lower():
                service.update_version(
                    version_name=deploy_config.version_name,
                    autoscale_enabled=deploy_config.autoscale_enabled,
                    autoscale_min_replicas=deploy_config.autoscale_min_replicas,
                    autoscale_max_replicas=deploy_config.autoscale_max_replicas,
                    autoscale_refresh_seconds=deploy_config.autoscale_refresh_seconds,
                    autoscale_target_utilization=deploy_config.autoscale_target_utilization,
                    collect_model_data=deploy_config.collect_model_data,
                    cpu_cores=deploy_config.cpu_cores,
                    memory_gb=deploy_config.memory_gb,
                    scoring_timeout_ms=deploy_config.scoring_timeout_ms,
                    replica_max_concurrent_requests=deploy_config.replica_max_concurrent_requests,
                    max_request_wait_time=deploy_config.max_request_wait_time,
                    num_replicas=deploy_config.num_replicas,
                    models=models, inference_config=inference_config,
                    gpu_cores=deploy_config.gpu_cores,
                    period_seconds=deploy_config.period_seconds,
                    initial_delay_seconds=deploy_config.initial_delay_seconds,
                    timeout_seconds=deploy_config.timeout_seconds,
                    success_threshold=deploy_config.success_threshold,
                    failure_threshold=deploy_config.failure_threshold,
                    traffic_percentile=deploy_config.traffic_percentile, is_default=is_default,
                    is_control_version_type=is_control_version_type,
                    cpu_cores_limit=deploy_config.cpu_cores_limit,
                    memory_gb_limit=deploy_config.memory_gb_limit)
        else:
            service.update(auth_enabled=deploy_config.auth_enabled,
                           token_auth_enabled=deploy_config.token_auth_enabled,
                           enable_app_insights=deploy_config.enable_app_insights)
    elif service._webservice_type.lower() == 'local':
        # local update
        deployment_config = \
            LocalWebservice.deploy_configuration(port=deploy_config.port if deploy_config else None)

        service.update(models=models,
                       deployment_config=deployment_config,
                       inference_config=inference_config)
    else:
        raise WebserviceException("Unknown deployment type: {}".format(service._webservice_type))
Beispiel #30
0
    print("Attempting to deploy model to web service")
    # Deploy this particular web service to your AKS cluster.
    service = Model.deploy(workspace=ws,
                           name=web_service_name,
                           models=[model],
                           inference_config=inf_config,
                           deployment_config=aks_config,
                           deployment_target=aks_target,
                           overwrite=True)

    print("Waiting for deployment to complete:")
    try:
        service.wait_for_deployment()
        print('Deployed AKS Webservice: {} \nWebservice Uri: {}'.format(
            service.name, service.scoring_uri))
    except:
        print(service.get_logs())

    try:
        service_key = service.get_keys()[0]
    except WebserviceException as e:
        raise WebserviceException(
            'Error attempting to retrieve service keys for use with scoring:\n{}'
            .format(e.message))

    web_service_details = {}
    web_service_details['service_name'] = service.name
    web_service_details['service_url'] = service.scoring_uri
    web_service_details["key"] = service_key
    with open('./service_details.json', 'w') as outfile:
        json.dump(obj=web_service_details, fp=outfile)