def head(self, session): """Get headers from a remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_head` is not set to ``True``. """ if not self.allow_head: raise exceptions.MethodNotSupported(self, "head") request = self._prepare_request() endpoint_override = self.service.get_endpoint_override() response = session.head(request.uri, endpoint_filter=self.service, endpoint_override=endpoint_override, headers={"Accept": ""}) self._translate_response(response) return self
def head_data_by_id(cls, session, resource_id, path_args=None): """Get a dictionary representing the headers of a remote resource. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param resource_id: This resource's identifier, if needed by the request. The default is ``None``. :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :return: A ``dict`` containing the headers. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_head` is not set to ``True``. """ if not cls.allow_head: raise exceptions.MethodNotSupported(cls, 'head') url = cls._get_url(path_args, resource_id) data = session.head(url, service=cls.service, accept=None).headers return {HEADERS: data}
def delete_by_id(cls, session, resource_id, path_args=None, error_message=None): """Delete a remote resource with the given id. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param resource_id: This resource's identifier, if needed by the request. :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :return: ``None`` :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_delete` is not set to ``True``. """ if not cls.allow_delete: raise exceptions.MethodNotSupported(cls, 'delete') url = cls._get_url(path_args, resource_id) headers = {'Accept': ''} response = session.delete(url, headers=headers) exceptions.raise_from_response(response, error_message=error_message)
def get(self, session, requires_id=True, error_message=None): """Get a remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param boolean requires_id: A boolean indicating whether resource ID should be part of the requested URI. :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_get` is not set to ``True``. """ if not self.allow_get: raise exceptions.MethodNotSupported(self, "get") request = self._prepare_request(requires_id=requires_id) session = self._get_session(session) response = session.get(request.url) kwargs = {} if error_message: kwargs['error_message'] = error_message self._translate_response(response, **kwargs) return self
def delete(self, session, error_message=None): """Delete the remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_update` is not set to ``True``. """ if not self.allow_delete: raise exceptions.MethodNotSupported(self, "delete") request = self._prepare_request() session = self._get_session(session) response = session.delete(request.url, headers={"Accept": ""}) kwargs = {} if error_message: kwargs['error_message'] = error_message self._translate_response(response, has_body=False, **kwargs) return self
def get(self, session, requires_id=True): """Get a remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param boolean requires_id: A boolean indicating whether resource ID should be part of the requested URI. :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_get` is not set to ``True``. """ if not self.allow_get: raise exceptions.MethodNotSupported(self, "get") request = self._prepare_request(requires_id=requires_id) endpoint_override = self.service.get_endpoint_override() service = self.get_service_filter(self, session) response = session.get(request.uri, endpoint_filter=self.service, microversion=service.microversion, endpoint_override=endpoint_override) self._translate_response(response) return self
def list_once(cls, session, **params): """ :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource2.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~openstack.session.Session.get`. They are additionally checked against the :data:`~openstack.resource2.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A instance of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") query_params = cls._query_mapping._transpose(params) uri = cls.get_list_uri(params) service = cls.get_service_filter(cls, session) endpoint_override = cls.service.get_endpoint_override() resp = session.get(uri, endpoint_filter=cls.service, microversion=service.microversion, endpoint_override=endpoint_override, headers={"Accept": "application/json"}, params=query_params) response_json = resp.json() if not response_json: return value = cls.existing(**response_json) return value
def create(self, session, prepend_key=True, has_body=False): """Create a remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param prepend_key: A boolean indicating whether the resource_key should be prepended in a resource creation request. Default to True. :param bool has_body: should mapping response body to resource. :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_create` is not set to ``True``. """ if not self.allow_create: raise exceptions.MethodNotSupported(self, "create") endpoint_override = self.service.get_endpoint_override() if self.put_create: request = self._prepare_request(requires_id=True, prepend_key=prepend_key) response = session.put(request.uri, endpoint_filter=self.service, endpoint_override=endpoint_override, json=request.body, headers=request.headers) else: request = self._prepare_request(requires_id=False, prepend_key=prepend_key) response = session.post(request.uri, endpoint_filter=self.service, endpoint_override=endpoint_override, json=request.body, headers=request.headers) self._translate_response(response, has_body=has_body) return self
def delete(self, session, error_message=None, endpoint_override=None, headers=None, requests_auth=None, params=None): """Delete the remote resource based on this instance. This function overrides default Resource.delete to enable headers :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_update` is not set to ``True``. """ if not self.allow_delete: raise exceptions.MethodNotSupported(self, "delete") request = self._prepare_request() session = self._get_session(session) # Build additional arguments to the DELETE call delete_args = self._prepare_override_args( endpoint_override=endpoint_override, request_headers=request.headers, additional_headers=headers, requests_auth=requests_auth) if params: delete_args['params'] = params response = session.delete(request.url, **delete_args) kwargs = {} if error_message: kwargs['error_message'] = error_message self._translate_response(response, has_body=False, **kwargs) return self
def get_data_by_id(cls, session, resource_id, path_args=None, include_headers=False): """Get a the attributes of a remote resource from an id. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param resource_id: This resource's identifier, if needed by the request. The default is ``None``. :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :param bool include_headers: ``True`` if header data should be included in the response body, ``False`` if not. :return: A ``dict`` representing the response body. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_retrieve` is not set to ``True``. """ if not cls.allow_retrieve: raise exceptions.MethodNotSupported('retrieve') if path_args: url = cls.base_path % path_args else: url = cls.base_path url = utils.urljoin(url, resource_id) response = session.get(url, service=cls.service) body = response.body if cls.resource_key: body = body[cls.resource_key] if include_headers: body[HEADERS] = response.headers return body
def list(cls, session, paginated=False, endpoint_override=None, headers=None, requests_auth=None, **params): if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") cls._query_mapping._validate(params, base_path=cls.base_path) query_params = cls._query_mapping._transpose(params, cls) response = session.get(session.get_endpoint(), params=query_params.copy(), requests_auth=requests_auth) root = ET.fromstring(response.content) if root.tag != ET.QName(cls.OBS_NS, 'ListAllMyBucketsResult'): _logger.warn('Namespace in the response does not match ' 'expectation') cls.OBS_NS = root.tag.split('}', 1)[0][1:] for elements in root: if elements.tag == ET.QName(cls.OBS_NS, cls.resources_key): for el in elements: if el.tag == ET.QName(cls.OBS_NS, cls.resource_key): # Convert XML part into dict dict_raw_resource = cls.etree_to_dict(el) # extract resource data dict_resource = dict_raw_resource[cls.resource_key] value = cls.existing(**dict_resource) yield value return
def update(self, session, prepend_key=True, has_body=True): """Update the remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param prepend_key: A boolean indicating whether the resource_key should be prepended in a resource update request. Default to True. :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_update` is not set to ``True``. """ # The id cannot be dirty for an update self._body._dirty.discard("id") # Only try to update if we actually have anything to update. if not any([self._body.dirty, self._header.dirty]): return self if not self.allow_update: raise exceptions.MethodNotSupported(self, "update") request = self._prepare_request(prepend_key=prepend_key) if self.patch_update: response = session.patch(request.url, json=request.body, headers=request.headers) else: response = session.put(request.url, json=request.body, headers=request.headers) self._translate_response(response, has_body=has_body) return self
def delete_by_id(cls, session, resource_id, path_args=None): """Delete a remote resource with the given id. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param resource_id: This resource's identifier, if needed by the request. The default is ``None``. :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :return: ``None`` :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_delete` is not set to ``True``. """ if not cls.allow_delete: raise exceptions.MethodNotSupported(cls, 'delete') if path_args: url = cls.base_path % path_args else: url = cls.base_path url = utils.urljoin(url, resource_id) session.delete(url, service=cls.service, accept=None)
def create_by_id(cls, session, attrs, r_id=None, path_args=None): if not cls.allow_create: raise exceptions.MethodNotSupported('create') if cls.resource_key: body = {cls.resource_key: attrs} else: body = attrs if path_args: url = cls.base_path % path_args else: url = cls.base_path if r_id: url = utils.urljoin(url, r_id) resp = session.put(url, service=cls.service, json=body).body else: resp = session.post(url, service=cls.service, json=body).body if cls.resource_key: resp = resp[cls.resource_key] return resp
def list(cls, session, paginated=True, base_path=None, allow_unknown_params=False, **params): if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) microversion = cls._get_microversion_for_list(session) if base_path is None: base_path = cls.base_path datastore_type = params.get('datastore_name', 'DDS-Community') uri = utils.urljoin(base_path, datastore_type, 'versions') response = session.get(uri, headers={"Accept": "application/json"}, microversion=microversion) exceptions.raise_from_response(response) data = response.json() resources = data['versions'] if not isinstance(resources, list): resources = [resources] for raw_resource in resources: value = cls.existing(microversion=microversion, connection=session._get_connection(), type=datastore_type, storage_engine='wiredTiger', version=raw_resource) yield value
def update(self, session, prepend_key=True, has_body=True): """Update the remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param prepend_key: A boolean indicating whether the resource_key should be prepended in a resource update request. Default to True. :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_update` is not set to ``True``. """ # The id cannot be dirty for an update self._body._dirty.discard("id") id_mapping_name = self._body_mapping()["id"] self._body._dirty.discard(id_mapping_name) if not self.allow_update: raise exceptions.MethodNotSupported(self, "update") request = self._prepare_request(requires_id=False, prepend_key=prepend_key) request.body = None service = self.get_service_filter(self, session) endpoint_override = self.service.get_endpoint_override() if self.service.get_endpoint_override() \ else self.get_endpoint_override(session) response = session.put(request.uri, endpoint_filter=self.service, microversion=service.microversion, endpoint_override=endpoint_override, json=request.body, headers=request.headers) self._translate_response(response, has_body=has_body) return self
def delete(self, session, has_body=False, params=None): """Delete the remote resource based on this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :return: This :class:`Resource` instance. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_update` is not set to ``True``. """ if not self.allow_delete: raise exceptions.MethodNotSupported(self, "delete") request = self._prepare_request() endpoint_override = self.service.get_endpoint_override() if endpoint_override is None: request.uri = self._get_custom_url(session, request.uri) else: endpoint_override = self._get_custom_override(endpoint_override) response = session.delete(request.uri, endpoint_filter=self.service, endpoint_override=endpoint_override, headers=request.headers) self._translate_response(response, has_body=False) return self
def create(self, session, prepend_key=True, endpoint_override=None, headers=None, requests_auth=None): if not self.allow_create: raise exceptions.MethodNotSupported(self, "create") session = self._get_session(session) request = self._prepare_request() req_args = self._prepare_override_args( endpoint_override=endpoint_override, request_headers=request.headers, additional_headers=headers, requests_auth=requests_auth) response = session.put(request.url, data=request.body, **req_args) self._translate_response(response) return self
def list_by_offset(cls, session, paginated=False, **params): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource2.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~openstack.session.Session.get`. They are additionally checked against the :data:`~openstack.resource2.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") more_data = True query_params = cls._query_mapping._transpose(params) uri = cls.get_list_uri(params) offset = query_params.get("offset") limit = query_params.get("limit") while more_data: endpoint_override = cls.service.get_endpoint_override() resp = session.get(uri, endpoint_filter=cls.service, endpoint_override=endpoint_override, headers={"Accept": "application/json"}, params=query_params) response_json = resp.json() resources = response_json if not resources: return resources.pop("self", None) value = cls.existing(**resources) yield value if not paginated: return if offset is None: return if limit is None: return resource_list = resources[cls.resources_key] current_page_size = len(resource_list) # Check if you need to continue sending requests. if current_page_size < int(limit): return else: if int(query_params.get("offset")) == 0: query_params["offset"] = 2 else: query_params["offset"] = int( query_params.get("offset")) + 1
def list(cls, session, paginated=False, base_path=None, **params): if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) # pop scaling_group_id, as it should not be also present in the query scaling_group_id = params.pop('scaling_group_id', None) uri_params = {} if scaling_group_id: uri_params = {'scaling_group_id': scaling_group_id} cls._query_mapping._validate(params, base_path=cls.base_path) query_params = cls._query_mapping._transpose(params, cls) uri = cls.base_path % uri_params limit = query_params.get('limit') total_yielded = 0 while uri: response = session.get(uri, params=query_params.copy()) exceptions.raise_from_response(response) data = response.json() # Discard any existing pagination keys query_params.pop('marker', None) query_params.pop('limit', None) if cls.resources_key: resources = cls.find_value_by_accessor(data, cls.resources_key) else: resources = data if not isinstance(resources, list): resources = [resources] marker = None for raw_resource in resources: # Do not allow keys called "self" through. Glance chose # to name a key "self", so we need to pop it out because # we can't send it through cls.existing and into the # Resource initializer. "self" is already the first # argument and is practically a reserved word. raw_resource.pop("self", None) if cls.resource_key and cls.resource_key in raw_resource: raw_resource = raw_resource[cls.resource_key] value = cls.existing(**raw_resource) marker = value.id yield value total_yielded += 1 if resources and paginated: uri, next_params = cls._get_next_link(uri, response, data, marker, limit, total_yielded) query_params.update(next_params) else: return
def list(cls, session, paginated=False, **params): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~keystoneauth1.adapter.Adapter.get`. They are additionally checked against the :data:`~openstack.resource.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. :raises: :exc:`~openstack.exceptions.InvalidResourceQuery` if query contains invalid params. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) cls._query_mapping._validate(params, base_path=cls.base_path) query_params = cls._query_mapping._transpose(params) uri = cls.base_path % params limit = query_params.get('limit') # Track the total number of resources yielded so we can paginate # swift objects total_yielded = 0 while uri: # Copy query_params due to weird mock unittest interactions response = session.get(uri, headers={"Accept": "application/json"}, params=query_params.copy()) exceptions.raise_from_response(response) data = response.json() # Discard any existing pagination keys query_params.pop('marker', None) query_params.pop('limit', None) if cls.resources_key: resources = data[cls.resources_key] else: resources = data if not isinstance(resources, list): resources = [resources] marker = None for raw_resource in resources: # Do not allow keys called "self" through. Glance chose # to name a key "self", so we need to pop it out because # we can't send it through cls.existing and into the # Resource initializer. "self" is already the first # argument and is practically a reserved word. raw_resource.pop("self", None) value = cls.existing(**raw_resource) marker = value.id yield value total_yielded += 1 if resources and paginated: uri, next_params = cls._get_next_link(uri, response, data, marker, limit, total_yielded) query_params.update(next_params) else: return
def list(cls, session, paginated=False, **params): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource2.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~openstack.session.Session.get`. They are additionally checked against the :data:`~openstack.resource2.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") more_data = True query_params = cls._query_mapping._transpose(params) uri = cls.base_path % params while more_data: endpoint_override = cls.service.get_endpoint_override() if endpoint_override is None: uri = cls._get_custom_url(session, uri) else: endpoint_override = cls._get_custom_override(endpoint_override) resp = session.get(uri, endpoint_filter=cls.service, endpoint_override=endpoint_override, headers={ "Content-type": "application/json", "X-Language": "en-us" }, params=query_params) resp = resp.json() if cls.resources_key: resp = resp[cls.resources_key] if not resp: more_data = False # Keep track of how many items we've yielded. If we yielded # less than our limit, we don't need to do an extra request # to get back an empty data set, which acts as a sentinel. yielded = 0 new_marker = None for data in resp: # Do not allow keys called "self" through. Glance chose # to name a key "self", so we need to pop it out because # we can't send it through cls.existing and into the # Resource initializer. "self" is already the first # argument and is practically a reserved word. data.pop("self", None) if cls.resource_key and cls.resource_key in data: data = data[cls.resource_key] value = cls.existing(**data) new_marker = value.id yielded += 1 yield value if not paginated: return if "limit" in query_params and yielded < query_params["limit"]: return query_params["limit"] = yielded query_params["marker"] = new_marker
def test_method_not_supported(self): exc = exceptions.MethodNotSupported(self.__class__, 'list') expected = ('The list method is not supported for ' + 'openstack.tests.unit.test_exceptions.Test_Exception') self.assertEqual(expected, str(exc))
def list(cls, session, limit=None, marker=None, path_args=None, paginated=False, **params): """Get a response that is a list of objects. This method starts at ``limit`` and ``marker`` (both defaulting to None), advances the marker to the last item received in each response, and continues making requests for more resources until no results are returned. When no ``limit`` is provided, the server will return its maximum amount of items per page. After that response, the limit will be determined and sent in subsequent requests to the server. That limit will be used to calculate when all items have been received. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param limit: The maximum amount of results to retrieve. The default is ``None``, which means no limit will be set, and the underlying API will return its default amount of responses. :param marker: The position in the list to begin requests from. The type of value to use for ``marker`` depends on the API being called. :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: Parameters to be passed into the underlying :meth:`~openstack.session.Session.get` method. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, 'list') more_data = True while more_data: resp = cls.page(session, limit, marker, path_args, **params) if not resp: more_data = False # Keep track of how many items we've yielded. If we yielded # less than our limit, we don't need to do an extra request # to get back an empty data set, which acts as a sentinel. yielded = 0 for data in resp: value = cls.existing(**data) marker = value.id yielded += 1 yield value if not paginated or limit and yielded < limit: more_data = False limit = yielded
def list(cls, session, paginated=False, base_path=None, allow_unknown_params=False, **params): if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) microversion = cls._get_microversion_for_list(session) if base_path is None: base_path = cls.base_path params = cls._query_mapping._validate( params, base_path=base_path, allow_unknown_params=allow_unknown_params) query_params = cls._query_mapping._transpose(params, cls) uri = base_path % params limit = query_params.get('limit') # Track the total number of resources yielded so we can paginate # swift objects total_yielded = query_params.get('start', 0) while uri: # Copy query_params due to weird mock unittest interactions response = session.get(uri, headers={"Accept": "application/json"}, params=query_params.copy(), microversion=microversion) exceptions.raise_from_response(response) data = response.json() # Discard any existing pagination keys query_params.pop('start', None) query_params.pop('limit', None) if cls.resources_key: resources = data[cls.resources_key] else: resources = data if not isinstance(resources, list): resources = [resources] marker = None for raw_resource in resources: value = cls.existing(microversion=microversion, connection=session._get_connection(), **raw_resource) marker = total_yielded + 1 yield value total_yielded += 1 if resources and paginated: uri, next_params = cls._get_next_link(uri, response, data, marker, limit, total_yielded) query_params.update(next_params) else: return
def list(cls, session, path_args=None, paginated=False, params=None): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param dict path_args: A dictionary of arguments to construct a compound URL. See `How path_args are used`_ for details. :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: Query parameters to be passed into the underlying :meth:`~openstack.session.Session.get` method. Values that the server may support include `limit` and `marker`. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, 'list') more_data = True params = {} if params is None else params url = cls._get_url(path_args) headers = {'Accept': 'application/json'} while more_data: resp = session.get(url, endpoint_filter=cls.service, headers=headers, params=params) resp = resp.json() if cls.resources_key: resp = resp[cls.resources_key] if not resp: more_data = False # Keep track of how many items we've yielded. If we yielded # less than our limit, we don't need to do an extra request # to get back an empty data set, which acts as a sentinel. yielded = 0 new_marker = None for data in resp: value = cls.existing(**data) new_marker = value.id yielded += 1 yield value if not paginated: return if 'limit' in params and yielded < params['limit']: return params['limit'] = yielded params['marker'] = new_marker
def list(cls, session, paginated=True, base_path=None, **params): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param str base_path: Base part of the URI for listing resources, if different from :data:`~openstack.resource.Resource.base_path`. :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~keystoneauth1.adapter.Adapter.get`. They are additionally checked against the :data:`~openstack.resource.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. :raises: :exc:`~openstack.exceptions.InvalidResourceQuery` if query contains invalid params. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) microversion = cls._get_microversion_for_list(session) if base_path is None: base_path = cls.base_path cls._query_mapping._validate(params, base_path=base_path) query_params = cls._query_mapping._transpose(params, cls) uri = base_path % params # Copy query_params due to weird mock unittest interactions response = session.get(uri, headers={ "Accept": "application/json", "Content-type": "application/json" }, params=query_params.copy(), microversion=microversion) exceptions.raise_from_response(response) data = response.json() resources = data['backups'] for raw_resource in resources: raw_resource.pop("self", None) value = cls.existing( microversion=microversion, connection=session._get_connection(), # version="1.0", **raw_resource) yield value
def list(cls, session, paginated=True, endpoint_override=None, headers=None, **kwargs): if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") uri = None if not hasattr(cls, 'list_path'): uri = cls.base_path else: uri = cls.list_path body = {} limit = None if 'limit' in kwargs: limit = kwargs['limit'] body['limit'] = limit if 'marker' in kwargs: body['marker'] = kwargs['marker'] if 'key_state' in kwargs: body['key_state'] = kwargs['key_state'] if 'sequence' in kwargs: body['sequence'] = kwargs['sequence'] total_yielded = 0 while uri: session = cls._get_session(session) args = cls._prepare_override_args( endpoint_override=endpoint_override, additional_headers=headers) response = session.post(uri, json=body, **args) data = response.json() if cls.resources_key: resources = data[cls.resources_key] else: resources = data if not isinstance(resources, list): resources = [resources] marker = None for raw_resource in resources: raw_resource.pop("self", None) if cls.resource_key and cls.resource_key in raw_resource: raw_resource = raw_resource[cls.resource_key] value = cls.existing(**raw_resource) marker = value.id yield value total_yielded += 1 if resources and paginated: uri, next_params = cls._get_next_link(uri, response, data, marker, limit, total_yielded) body.update(next_params) else: return
def list(cls, session, paginated=False, **params): """This method is a generator which yields resource objects. This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource2.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~openstack.session.Session.get`. They are additionally checked against the :data:`~openstack.resource2.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") more_data = True query_params = cls._query_mapping._transpose(params) uri = cls.get_list_uri(params) while more_data: endpoint_override = cls.service.get_endpoint_override() resp = session.get(uri, endpoint_filter=cls.service, endpoint_override=endpoint_override, headers={"Accept": "application/json"}, params=query_params) response_json = resp.json() if cls.resources_key: resources = cls.find_value_by_accessor(response_json, cls.resources_key) else: resources = response_json if not resources: more_data = False # Keep track of how many items we've yielded. If we yielded # less than our limit, we don't need to do an extra request # to get back an empty data set, which acts as a sentinel. yielded = 0 new_marker = None for data in resources: # Do not allow keys called "self" through. Glance chose # to name a key "self", so we need to pop it out because # we can't send it through cls.existing and into the # Resource initializer. "self" is already the first # argument and is practically a reserved word. data.pop("self", None) value = cls.existing(**data) new_marker = value.id yielded += 1 yield value query_params = dict(query_params) # if `next marker path` is explicit specified, use it as marker next_marker = cls.get_next_marker(response_json, yielded, query_params) if next_marker: new_marker = next_marker if next_marker != -1 else None # if cls.next_marker_path: # if isinstance(cls.next_marker_path, six.string_types): # new_marker = cls.find_value_by_accessor(response_json, # cls.next_marker_path) # elif callable(cls.next_marker_path): # new_marker = cls.next_marker_path(response_json, yielded) if not new_marker: return if not paginated: return if cls.query_limit_key in query_params: if yielded < query_params["limit"]: return query_params[cls.query_limit_key] = yielded query_params[cls.query_marker_key] = new_marker
def list_ext(cls, session, paginated=False, endpoint_override=None, headers=None, **params): """Override default list to incorporate endpoint overriding and custom headers Since SDK Resource.list method is passing hardcoded headers do override the function This resource object list generator handles pagination and takes query params for response filtering. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param bool paginated: ``True`` if a GET to this resource returns a paginated series of responses, or ``False`` if a GET returns only one page of data. **When paginated is False only one page of data will be returned regardless of the API's support of pagination.** :param dict params: These keyword arguments are passed through the :meth:`~openstack.resource.QueryParamter._transpose` method to find if any of them match expected query parameters to be sent in the *params* argument to :meth:`~keystoneauth1.adapter.Adapter.get`. They are additionally checked against the :data:`~openstack.resource.Resource.base_path` format string to see if any path fragments need to be filled in by the contents of this argument. :return: A generator of :class:`Resource` objects. :raises: :exc:`~openstack.exceptions.MethodNotSupported` if :data:`Resource.allow_list` is not set to ``True``. :raises: :exc:`~openstack.exceptions.InvalidResourceQuery` if query contains invalid params. """ if not cls.allow_list: raise exceptions.MethodNotSupported(cls, "list") session = cls._get_session(session) # pop scaling_group_id, as it should not be also present in the query scaling_group_id = params.pop('scaling_group_id', None) uri_params = {} if scaling_group_id: uri_params = {'scaling_group_id': scaling_group_id} cls._query_mapping._validate(params, base_path=cls.base_path) query_params = cls._query_mapping._transpose(params) uri = None if not hasattr(cls, 'list_path'): uri = cls.base_path % uri_params else: uri = cls.list_path % uri_params limit = query_params.get('limit') # Build additional arguments to the GET call get_args = cls._prepare_override_args( endpoint_override=endpoint_override, # request_headers=request.headers, additional_headers=headers) total_yielded = 0 while uri: response = session.get(uri, params=query_params.copy(), **get_args) exceptions.raise_from_response(response) data = response.json() # Discard any existing pagination keys query_params.pop('marker', None) query_params.pop('limit', None) if cls.resources_key: resources = cls.find_value_by_accessor(data, cls.resources_key) else: resources = data if not isinstance(resources, list): resources = [resources] marker = None for raw_resource in resources: # Do not allow keys called "self" through. Glance chose # to name a key "self", so we need to pop it out because # we can't send it through cls.existing and into the # Resource initializer. "self" is already the first # argument and is practically a reserved word. raw_resource.pop("self", None) if cls.resource_key and cls.resource_key in raw_resource: raw_resource = raw_resource[cls.resource_key] value = cls.existing(**raw_resource) marker = value.id yield value total_yielded += 1 if resources and paginated: uri, next_params = cls._get_next_link(uri, response, data, marker, limit, total_yielded) query_params.update(next_params) else: return