Exemple #1
0
def fetch_resource(rest_end_point, href):
    """This is the method you should use to create a Resource instance if you
    have the href for it. It gets the current state of the resource with the
    given *href*. Once the current state is fetched from the Space server, this
    method creates a new instance of ``jnpr.space.resource.Resource`` with this
    state and returns it.

    :param rest_end_point: A *Space* object encapsulating the Junos
        Space cluster which contains this resource.
    :type rest_end_point: jnpr.space.rest.Space

    :param str href: The href of the resource that needs to be fetched.

    :returns: A new instance of jnpr.space.resource.Resource

    :raises: ``jnpr.space.rest.RestException`` if the GET request results in an
        error response. The exception's ``response`` attribute will have the
        full response from Space.
    """
    response = rest_end_point.get(href)
    if response.status_code != 200:
        raise rest.RestException("GET failed on %s" % href, response)

    media_type = response.headers['content-type']
    end = media_type.index('+')
    parts = media_type[:end].split('.')
    app_ = parts[len(parts)-3]
    service_ = parts[len(parts)-2]
    type_ = parts[len(parts)-1]

    if app_ == 'space':
        type_name = xmlutil.unmake_xml_name('.'.join([service_, type_]))
    else:
        type_name = xmlutil.unmake_xml_name('.'.join([app_, service_, type_]))

    xml_data = xmlutil.get_xml_obj_from_response(response)
    return make_resource(type_name, rest_end_point, xml_data)
Exemple #2
0
    def post(self,
             new_obj=None,
             accept=None,
             content_type=None,
             request_body=None,
             xml_name=None,
             task_monitor=None):
        """
        Sends a POST request to the Space server to create a new Resource in
        this collection.

        :param new_obj: The new Resource that needs to be created as a member
            of this collection. This can be omitted in which case the caller
            must supply a request body for the POST request as the
            ``request_body`` argument.
        :type new_obj: A single ``jnpr.space.resource.Resource`` instance
            or a list of them.

        :param str accept: This can be used to supply a media-type that must
            be used as the Accept header in the request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param str content_type: This can be used to supply a media-type that must
            be used as the Content-Type header in the request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param str request_body: This can be used to supply a string that must
            be used as the request body in the request. This defaults to
            ``None`` and in this case the caller must supply the ``new_obj``
            argument from which the request body will be formed.

        :param str xml_name: Can be used to override the name of the top-level
            XML element in the generated request body. This is useful in some
            cases such as creating a quick config template.
            This parameter defaults to ``None``.

        :param task_monitor: A TaskMonitor object that can be used to monitor
            the progress of the POST request, in case of asynchronous
            invocations. You need to check Junos Space API documentation to
            see if the POST invocation on this resource has asynchronous
            semantics and supply the task_monitor parameter only if it is
            asynchronous. Otherwise, this will default to ``None`` and the
            method will behave with synchronous semantics.
        :type task_monitor: jnpr.space.async.TaskMonitor

        :returns: If the new_obj parameter is a list, then the same list is
            returned. Otherwise, this method creates a new Resource object
            based on the state of the newly created resource, as extracted from
            the POST response body. In the case of asynchronous
            invocation, this will represent a Task object and will contain the
            unique id of the Task executing the POST request in Space.

        :raises: ``jnpr.space.rest.RestException`` if the POST method results in
            an error response. The exception's ``response`` attribute will have
            the full response from Space.

        """
        if content_type is not None:
            media_type = content_type
        elif isinstance(new_obj, list):
            if self._meta_object.content_type is not None:
                media_type = self._meta_object.content_type
            else:
                media_type = self._meta_object.get_media_type(None)
        else:
            if new_obj is None:
                raise ValueError(
                    'Must provide content_type when providing request_body')
            media_type = new_obj.get_meta_object().get_media_type(None)

        headers = {'content-type': media_type}
        if accept is not None:
            headers['accept'] = accept

        if request_body is not None:
            body = request_body
            saved_root_tag = None
            if new_obj is not None:
                raise ValueError('Cannot use both request_body and new_obj!')
        else:
            if new_obj is None:
                raise ValueError('Cannot omit both request_body and new_obj!')

            xml_obj = None
            if isinstance(new_obj, list):
                xml_obj = etree.Element(self._meta_object.xml_name)
                for obj in new_obj:
                    xml_obj.append(obj.form_xml())
            else:
                xml_obj = new_obj.form_xml()

            saved_root_tag = xml_obj.tag

            if xml_name is not None:
                xml_obj.tag = xml_name

            body = xmlutil.cleanup(etree.tostring(xml_obj, encoding='unicode'))

        url = self.get_href()
        if task_monitor is not None:
            url = '?queue='.join([url, task_monitor.get_queue_url()])

        response = self._rest_end_point.post(url, headers, body)

        if response.status_code == 204:  # Special case of post with null response
            return new_obj

        if response.status_code not in [200, 202]:
            raise rest.RestException("POST failed on %s" % self.get_href(),
                                     response)

        if task_monitor is not None:
            resp_str = xmlutil.get_text_from_response(response)
            return xmlutil.xml2obj(resp_str)

        if not isinstance(new_obj, list):
            # Fixing issue #17
            #r = response.text
            # Skip the <?xml> line to avoid encoding errors in lxml
            #start = r.index('?><') + 2
            #root = etree.fromstring(r[start:])
            root = xmlutil.get_xml_obj_from_response(response)
            #new_obj._xml_data = root
            #new_obj._rest_end_point = self._rest_end_point
            if saved_root_tag is not None:
                root.tag = saved_root_tag
            new_obj = self._create_resource(root)

        return new_obj
    def post(self, new_obj=None, accept=None, content_type=None,
             request_body=None, xml_name=None, task_monitor=None):
        """
        Sends a POST request to the Space server to create a new Resource in
        this collection.

        :param new_obj: The new Resource that needs to be created as a member
            of this collection. This can be omitted in which case the caller
            must supply a request body for the POST request as the
            ``request_body`` argument.
        :type new_obj: A single ``jnpr.space.resource.Resource`` instance
            or a list of them.

        :param str accept: This can be used to supply a media-type that must
            be used as the Accept header in the request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param str content_type: This can be used to supply a media-type that must
            be used as the Content-Type header in the request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param str request_body: This can be used to supply a string that must
            be used as the request body in the request. This defaults to
            ``None`` and in this case the caller must supply the ``new_obj``
            argument from which the request body will be formed.

        :param str xml_name: Can be used to override the name of the top-level
            XML element in the generated request body. This is useful in some
            cases such as creating a quick config template.
            This parameter defaults to ``None``.

        :param task_monitor: A TaskMonitor object that can be used to monitor
            the progress of the POST request, in case of asynchronous
            invocations. You need to check Junos Space API documentation to
            see if the POST invocation on this resource has asynchronous
            semantics and supply the task_monitor parameter only if it is
            asynchronous. Otherwise, this will default to ``None`` and the
            method will behave with synchronous semantics.
        :type task_monitor: jnpr.space.async.TaskMonitor

        :returns: If the new_obj parameter is a list, then the same list is
            returned. Otherwise, this method creates a new Resource object
            based on the state of the newly created resource, as extracted from
            the POST response body. In the case of asynchronous
            invocation, this will represent a Task object and will contain the
            unique id of the Task executing the POST request in Space.

        :raises: ``jnpr.space.rest.RestException`` if the POST method results in
            an error response. The exception's ``response`` attribute will have
            the full response from Space.

        """
        if content_type is not None:
            media_type = content_type
        elif isinstance(new_obj, list):
            if self._meta_object.content_type is not None:
                media_type = self._meta_object.content_type
            else:
                media_type = self._meta_object.get_media_type(None)
        else:
            if new_obj is None:
                raise ValueError('Must provide content_type when providing request_body')
            media_type = new_obj.get_meta_object().get_media_type(None)

        headers = {'content-type': media_type}
        if accept is not None:
            headers['accept'] = accept

        if request_body is not None:
            body = request_body
            saved_root_tag = None
            if new_obj is not None:
                raise ValueError('Cannot use both request_body and new_obj!')
        else:
            if new_obj is None:
                raise ValueError('Cannot omit both request_body and new_obj!')

            xml_obj = None
            if isinstance(new_obj, list):
                xml_obj = etree.Element(self._meta_object.xml_name)
                for obj in new_obj:
                    xml_obj.append(obj.form_xml())
            else:
                xml_obj = new_obj.form_xml()

            saved_root_tag = xml_obj.tag

            if xml_name is not None:
                xml_obj.tag = xml_name

            body = xmlutil.cleanup(etree.tostring(xml_obj, encoding='unicode'))

        url = self.get_href()
        if task_monitor is not None:
            url = '?queue='.join([url, task_monitor.get_queue_url()])

        response = self._rest_end_point.post(url,
                                             headers,
                                             body)

        if response.status_code == 204: # Special case of post with null response
            return new_obj

        if response.status_code not in [200, 202]:
            raise rest.RestException("POST failed on %s" % self.get_href(),
                                     response)

        if task_monitor is not None:
            resp_str = xmlutil.get_text_from_response(response)
            return xmlutil.xml2obj(resp_str)

        if not isinstance(new_obj, list):
            # Fixing issue #17
            #r = response.text
            # Skip the <?xml> line to avoid encoding errors in lxml
            #start = r.index('?><') + 2
            #root = etree.fromstring(r[start:])
            root = xmlutil.get_xml_obj_from_response(response)
            #new_obj._xml_data = root
            #new_obj._rest_end_point = self._rest_end_point
            if saved_root_tag is not None:
                root.tag = saved_root_tag
            new_obj = self._create_resource(root)

        return new_obj
Exemple #4
0
    def get(self,
            accept=None,
            filter_=None,
            domain_id=None,
            paging=None,
            sortby=None):
        """Gets the contained resources of this collection from Space.

        :param str accept: This can be used to supply a media-type that must
            be used as the Accept header in the GET request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param filter_: A filter expression to apply on the collection. This
            can be given as a dict with name:value pairs to filter with. For
            example, ``{'name':'user1'}``. Or this can be given as a string
            which forms a valid filter expression for this collection as per
            Junos Space API documentation.
            This parameter defaults to ``None``.
        :type filter_: str or dict

        :param paging: A paging expression to apply on the collection. This
            must be given as a dict with entries giving values for ``start``
            and ``limit`` paging parameters. For example, ``{'start':10,
            'limit':100}``.
            This parameter defaults to ``None``.
        :type paging: dict

        :param sortby: A list of field names to sort the results by.
            This parameter defaults to ``None``.
        :type sortby: list of str

        :returns: A list of ``jnpr.space.resource.Resource`` objects.

        :raises: ``jnpr.space.rest.RestException`` if the GET method results in an
            error response. The exception's ``response`` attribute will have the
            full response from Space.

        """
        url = self._form_get_url(filter_, domain_id, paging, sortby)

        if accept is not None:
            mtype = accept
        else:
            mtype = self._meta_object.get_media_type(None)

        if mtype is not None:
            if not self._meta_object.retain_charset_in_accept:
                end = mtype.find(';charset=')
                if end > 0:
                    mtype = mtype[0:end]
            headers = {'accept': mtype}
        else:
            headers = {}

        resource_list = []
        response = self._rest_end_point.get(url, headers)
        if response.status_code != 200:
            if response.status_code == 204:
                return []
            raise rest.RestException("GET failed on %s" % url, response)

        # Fixing issue #17
        #r = response.text
        # Skip the <?xml> line to avoid encoding errors in lxml
        #start = r.index('?><') + 2
        #root = etree.fromstring(r[start:])

        root = xmlutil.get_xml_obj_from_response(response)

        if self._meta_object.single_object_collection:
            resource_list.append(self._create_resource(root))
        elif self._meta_object.named_members:
            for key, value in self._meta_object.named_members.items():
                resrc = self._create_named_resource(key, value, root)
                resrc.id = key
                resource_list.append(resrc)
        else:
            for child in root:
                try:
                    resrc = self._create_resource(child)
                    resource_list.append(resrc)
                except Exception as ex:
                    if ex.ignore:
                        pass
                    else:
                        raise ex

        return ResourceList(resource_list)
    def get(self, accept=None, filter_=None,
            domain_id=None, paging=None, sortby=None):
        """Gets the contained resources of this collection from Space.

        :param str accept: This can be used to supply a media-type that must
            be used as the Accept header in the GET request. This defaults to
            ``None`` and in this case SpaceEZ will use the media-type modeled
            in the description file.

        :param filter_: A filter expression to apply on the collection. This
            can be given as a dict with name:value pairs to filter with. For
            example, ``{'name':'user1'}``. Or this can be given as a string
            which forms a valid filter expression for this collection as per
            Junos Space API documentation.
            This parameter defaults to ``None``.
        :type filter_: str or dict

        :param paging: A paging expression to apply on the collection. This
            must be given as a dict with entries giving values for ``start``
            and ``limit`` paging parameters. For example, ``{'start':10,
            'limit':100}``.
            This parameter defaults to ``None``.
        :type paging: dict

        :param sortby: A list of field names to sort the results by.
            This parameter defaults to ``None``.
        :type sortby: list of str

        :returns: A list of ``jnpr.space.resource.Resource`` objects.

        :raises: ``jnpr.space.rest.RestException`` if the GET method results in an
            error response. The exception's ``response`` attribute will have the
            full response from Space.

        """
        url = self._form_get_url(filter_, domain_id, paging, sortby)

        if accept is not None:
            mtype = accept
        else:
            mtype = self._meta_object.get_media_type(None)

        if mtype is not None:
            if not self._meta_object.retain_charset_in_accept:
                end = mtype.find(';charset=')
                if end > 0:
                    mtype = mtype[0:end]
            headers = {'accept' : mtype}
        else:
            headers = {}

        resource_list = []
        response = self._rest_end_point.get(url, headers)
        if response.status_code != 200:
            if response.status_code == 204:
                return []
            raise rest.RestException("GET failed on %s" % url, response)

        # Fixing issue #17
        #r = response.text
        # Skip the <?xml> line to avoid encoding errors in lxml
        #start = r.index('?><') + 2
        #root = etree.fromstring(r[start:])

        root = xmlutil.get_xml_obj_from_response(response)

        if self._meta_object.single_object_collection:
            resource_list.append(self._create_resource(root))
        elif self._meta_object.named_members:
            for key, value in self._meta_object.named_members.items():
                resrc = self._create_named_resource(key, value, root)
                resrc.id = key
                resource_list.append(resrc)
        else:
            for child in root:
                try:
                    resrc = self._create_resource(child)
                    resource_list.append(resrc)
                except Exception as ex:
                    if ex.ignore:
                        pass
                    else:
                        raise ex

        return ResourceList(resource_list)