class Test(resource.Resource): base_path = "/ramones" service = "punk" allow_create = True allow_update = True hey = resource.header("vocals") ho = resource.header("guitar") letsgo = resource.header("bass")
class Account(_base.BaseResource): base_path = "/" allow_retrieve = True allow_update = True allow_head = True #: The total number of bytes that are stored in Object Storage for #: the account. account_bytes_used = resource.header("x-account-bytes-used", type=int) #: The number of containers. account_container_count = resource.header("x-account-container-count", type=int) #: The number of objects in the account. account_object_count = resource.header("x-account-object-count", type=int) #: The secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key = resource.header("x-account-meta-temp-url-key") #: A second secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2")
class Account(_base.BaseResource): _custom_metadata_prefix = "X-Account-Meta-" base_path = "/" allow_retrieve = True allow_update = True allow_head = True #: The total number of bytes that are stored in Object Storage for #: the account. account_bytes_used = resource.header("x-account-bytes-used", type=int) #: The number of containers. account_container_count = resource.header("x-account-container-count", type=int) #: The number of objects in the account. account_object_count = resource.header("x-account-object-count", type=int) #: The secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key = resource.header("x-account-meta-temp-url-key") #: A second secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2") #: The timestamp of the transaction. #: *Type: datetime object parsed from a UNIX epoch* timestamp = resource.header("x-timestamp", type=format.UNIXEpoch)
class Object(_base.BaseResource): _custom_metadata_prefix = "X-Object-Meta-" _system_metadata = { "content_disposition": "content-disposition", "content_encoding": "content-encoding", "content_type": "content-type", "delete_after": "x-delete-after", "delete_at": "x-delete-at", "is_content_type_detected": "x-detect-content-type", } base_path = "/%(container)s" service = object_store_service.ObjectStoreService() id_attribute = "name" allow_create = True allow_retrieve = True allow_update = True allow_delete = True allow_list = True allow_head = True # Data to be passed during a POST call to create an object on the server. data = None # URL parameters #: The unique name for the container. container = resource.prop("container") #: The unique name for the object. name = resource.prop("name") # Object details hash = resource.prop("hash") bytes = resource.prop("bytes") # Headers for HEAD and GET requests #: If set to True, Object Storage queries all replicas to return #: the most recent one. If you omit this header, Object Storage #: responds faster after it finds one valid replica. Because #: setting this header to True is more expensive for the back end, #: use it only when it is absolutely needed. *Type: bool* is_newest = resource.header("x-newest", type=bool) #: TODO(briancurtin) there's a lot of content here... range = resource.header("range", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_match = resource.header("if-match", type=dict) #: In combination with Expect: 100-Continue, specify an #: "If-None-Match: \*" header to query whether the server already #: has a copy of the object before any data is sent. if_none_match = resource.header("if-none-match", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_modified_since = resource.header("if-modified-since", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_unmodified_since = resource.header("if-unmodified-since", type=dict) # Query parameters #: Used with temporary URLs to sign the request. For more #: information about temporary URLs, see OpenStack Object Storage #: API v1 Reference. signature = resource.header("signature") #: Used with temporary URLs to specify the expiry time of the #: signature. For more information about temporary URLs, see #: OpenStack Object Storage API v1 Reference. expires_at = resource.header("expires") #: If you include the multipart-manifest=get query parameter and #: the object is a large object, the object contents are not #: returned. Instead, the manifest is returned in the #: X-Object-Manifest response header for dynamic large objects #: or in the response body for static large objects. multipart_manifest = resource.header("multipart-manifest") # Response headers from HEAD and GET #: HEAD operations do not return content. However, in this #: operation the value in the Content-Length header is not the #: size of the response body. Instead it contains the size of #: the object, in bytes. content_length = resource.header("content-length") #: The MIME type of the object. content_type = resource.header("content-type") #: The type of ranges that the object accepts. accept_ranges = resource.header("accept-ranges") #: For objects smaller than 5 GB, this value is the MD5 checksum #: of the object content. The value is not quoted. #: For manifest objects, this value is the MD5 checksum of the #: concatenated string of MD5 checksums and ETags for each of #: the segments in the manifest, and not the MD5 checksum of #: the content that was downloaded. Also the value is enclosed #: in double-quote characters. #: You are strongly recommended to compute the MD5 checksum of #: the response body as it is received and compare this value #: with the one in the ETag header. If they differ, the content #: was corrupted, so retry the operation. etag = resource.header("etag") #: Set to True if this object is a static large object manifest object. #: *Type: bool* is_static_large_object = resource.header("x-static-large-object", type=bool) #: If set, the value of the Content-Encoding metadata. #: If not set, this header is not returned by this operation. content_encoding = resource.header("content-encoding") #: If set, specifies the override behavior for the browser. #: For example, this header might specify that the browser use #: a download program to save this file rather than show the file, #: which is the default. #: If not set, this header is not returned by this operation. content_disposition = resource.header("content-disposition") #: Specifies the number of seconds after which the object is #: removed. Internally, the Object Storage system stores this #: value in the X-Delete-At metadata item. delete_after = resource.header("x-delete-after", type=int) #: If set, the time when the object will be deleted by the system #: in the format of a UNIX Epoch timestamp. #: If not set, this header is not returned by this operation. delete_at = resource.header("x-delete-at") #: If set, to this is a dynamic large object manifest object. #: The value is the container and object name prefix of the #: segment objects in the form container/prefix. object_manifest = resource.header("x-object-manifest") #: The timestamp of the transaction. timestamp = resource.header("x-timestamp") #: The date and time that the object was created or the last #: time that the metadata was changed. last_modified_at = resource.header("last_modified", alias="last-modified") # Headers for PUT and POST requests #: Set to chunked to enable chunked transfer encoding. If used, #: do not set the Content-Length header to a non-zero value. transfer_encoding = resource.header("transfer-encoding") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the #: Content-Type header, if present. *Type: bool* is_content_type_detected = resource.header("x-detect-content-type", type=bool) #: If set, this is the name of an object used to create the new #: object by copying the X-Copy-From object. The value is in form #: {container}/{object}. You must UTF-8-encode and then URL-encode #: the names of the container and object before you include them #: in the header. #: Using PUT with X-Copy-From has the same effect as using the #: COPY operation to copy an object. copy_from = resource.header("x-copy-from") # The Object Store treats the metadata for its resources inconsistently so # Object.set_metadata must override the BaseResource.set_metadata to # account for it. def set_metadata(self, session, metadata): # Filter out items with empty values so the create metadata behaviour # is the same as account and container filtered_metadata = \ {key: value for key, value in metadata.items() if value} # Get a copy of the original metadata so it doesn't get erased on POST # and update it with the new metadata values. obj = self.head(session) metadata2 = copy.deepcopy(obj.metadata) metadata2.update(filtered_metadata) # Include any original system metadata so it doesn't get erased on POST for key in self._system_metadata: value = getattr(obj, key) if value and key not in metadata2: metadata2[key] = value super(Object, self).set_metadata(session, metadata2) # The Object Store treats the metadata for its resources inconsistently so # Object.delete_metadata must override the BaseResource.delete_metadata to # account for it. def delete_metadata(self, session, keys): # Get a copy of the original metadata so it doesn't get erased on POST # and update it with the new metadata values. obj = self.head(session) metadata = copy.deepcopy(obj.metadata) # Include any original system metadata so it doesn't get erased on POST for key in self._system_metadata: value = getattr(obj, key) if value: metadata[key] = value # Remove the metadata for key in keys: if key == 'delete_after': del (metadata['delete_at']) else: del (metadata[key]) url = self._get_url(self, self.id) session.post(url, headers=self._calculate_headers(metadata)) def get(self, session, include_headers=False, args=None, error_message=None): url = self._get_url(self, self.id) headers = {'Accept': 'bytes'} resp = session.get(url, headers=headers, error_message=error_message) resp = resp.content self._set_metadata() return resp def create(self, session): url = self._get_url(self, self.id) headers = self.get_headers() headers['Accept'] = '' if self.data is not None: resp = session.put(url, data=self.data, headers=headers).headers else: resp = session.post(url, data=None, headers=headers).headers self.set_headers(resp) return self
class Object(resource.Resource): base_path = "/%(container)s" service = object_store_service.ObjectStoreService() id_attribute = "name" allow_create = True allow_retrieve = True allow_update = True allow_delete = True allow_list = True allow_head = True # Data to be passed during a POST call to create an object on the server. data = None # URL parameters #: The unique name for the container. container = resource.prop("container") #: The unique name for the object. name = resource.prop("name") # Object details hash = resource.prop("hash") bytes = resource.prop("bytes") # Headers for HEAD and GET requests #: If set to True, Object Storage queries all replicas to return #: the most recent one. If you omit this header, Object Storage #: responds faster after it finds one valid replica. Because #: setting this header to True is more expensive for the back end, #: use it only when it is absolutely needed. newest = resource.header("x-newest", type=bool) #: TODO(briancurtin) there's a lot of content here... range = resource.header("range", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_match = resource.header("if-match", type=dict) #: In combination with Expect: 100-Continue, specify an #: "If-None-Match: \*" header to query whether the server already #: has a copy of the object before any data is sent. if_none_match = resource.header("if-none-match", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_modified_since = resource.header("if-modified-since", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. if_unmodified_since = resource.header("if-unmodified-since", type=dict) # Query parameters #: Used with temporary URLs to sign the request. For more #: information about temporary URLs, see OpenStack Object Storage #: API v1 Reference. signature = resource.header("signature") #: Used with temporary URLs to specify the expiry time of the #: signature. For more information about temporary URLs, see #: OpenStack Object Storage API v1 Reference. expires = resource.header("expires") #: If you include the multipart-manifest=get query parameter and #: the object is a large object, the object contents are not #: returned. Instead, the manifest is returned in the #: X-Object-Manifest response header for dynamic large objects #: or in the response body for static large objects. multipart_manifest = resource.header("multipart-manifest") # Response headers from HEAD and GET #: HEAD operations do not return content. However, in this #: operation the value in the Content-Length header is not the #: size of the response body. Instead it contains the size of #: the object, in bytes. content_length = resource.header("content-length") #: The MIME type of the object. content_type = resource.header("content_type", alias="content-type") #: The type of ranges that the object accepts. accept_ranges = resource.header("accept-ranges") #: The date and time that the object was created or the last #: time that the metadata was changed. last_modified = resource.header("last_modified", alias="last-modified") #: For objects smaller than 5 GB, this value is the MD5 checksum #: of the object content. The value is not quoted. #: For manifest objects, this value is the MD5 checksum of the #: concatenated string of MD5 checksums and ETags for each of #: the segments in the manifest, and not the MD5 checksum of #: the content that was downloaded. Also the value is enclosed #: in double-quote characters. #: You are strongly recommended to compute the MD5 checksum of #: the response body as it is received and compare this value #: with the one in the ETag header. If they differ, the content #: was corrupted, so retry the operation. etag = resource.header("etag") #: Set to True if this object is a static large object manifest object. is_static_large_object = resource.header("x-static-large-object") #: The transaction date and time. date = resource.header("date") #: If set, the value of the Content-Encoding metadata. #: If not set, this header is not returned by this operation. content_encoding = resource.header("content-encoding") #: If set, specifies the override behavior for the browser. #: For example, this header might specify that the browser use #: a download program to save this file rather than show the file, #: which is the default. #: If not set, this header is not returned by this operation. content_disposition = resource.header("content-disposition") #: If set, the time when the object will be deleted by the system #: in the format of a UNIX Epoch timestamp. #: If not set, this header is not returned by this operation. delete_at = resource.header("x-delete-at", type=int) #: If set, to this is a dynamic large object manifest object. #: The value is the container and object name prefix of the #: segment objects in the form container/prefix. object_manifest = resource.header("x-object-manifest") #: The UNIX timestamp of the transaction. timestamp = resource.header("x-timestamp") # Headers for PUT and POST requests #: Set to chunked to enable chunked transfer encoding. If used, #: do not set the Content-Length header to a non-zero value. transfer_encoding = resource.header("transfer-encoding") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the #: Content-Type header, if present. detect_content_type = resource.header("x-detect-content-type", type=bool) #: If set, this is the name of an object used to create the new #: object by copying the X-Copy-From object. The value is in form #: {container}/{object}. You must UTF-8-encode and then URL-encode #: the names of the container and object before you include them #: in the header. #: Using PUT with X-Copy-From has the same effect as using the #: COPY operation to copy an object. copy_from = resource.header("x-copy-from") #: Specifies the number of seconds after which the object is #: removed. Internally, the Object Storage system stores this #: value in the X-Delete-At metadata item. delete_after = resource.header("x-delete-after", type=int) def get(self, session): url = self._get_url(self, self.id) # TODO(thowe): Add filter header support bug #1488269 resp = session.get(url, service=self.service, accept="bytes").content return resp def create(self, session): """Create a remote resource from this instance.""" url = self._get_url(self, self.id) headers = self.get_headers() if self.data is not None: resp = session.put(url, service=self.service, data=self.data, accept="bytes", headers=headers).headers else: resp = session.post(url, service=self.service, data=None, accept=None, headers=headers).headers self.set_headers(resp) return self
class Container(_base.BaseResource): _custom_metadata_prefix = "X-Container-Meta-" _system_metadata = { "content_type": "content-type", "detect_content_type": "x-detect-content-type", "versions_location": "x-versions-location", "read_ACL": "x-container-read", "write_ACL": "x-container-write", "sync_to": "x-container-sync-to", "sync_key": "x-container-sync-key" } base_path = "/" id_attribute = "name" allow_create = True allow_retrieve = True allow_update = True allow_delete = True allow_list = True allow_head = True # Container body data (when id=None) #: The name of the container. name = resource.prop("name") #: The number of objects in the container. count = resource.prop("count") #: The total number of bytes that are stored in Object Storage #: for the container. bytes = resource.prop("bytes") # Container metadata (when id=name) #: The number of objects. object_count = resource.header("x-container-object-count", type=int) #: The count of bytes used in total. bytes_used = resource.header("x-container-bytes-used", type=int) #: The timestamp of the transaction. timestamp = resource.header("x-timestamp", type=format.UNIXEpoch) # Request headers (when id=None) #: If set to True, Object Storage queries all replicas to return the #: most recent one. If you omit this header, Object Storage responds #: faster after it finds one valid replica. Because setting this #: header to True is more expensive for the back end, use it only #: when it is absolutely needed. newest = resource.header("x-newest", type=bool) # Request headers (when id=name) #: The ACL that grants read access. If not set, this header is not #: returned by this operation. read_ACL = resource.header("x-container-read") #: The ACL that grants write access. If not set, this header is not #: returned by this operation. write_ACL = resource.header("x-container-write") #: The destination for container synchronization. If not set, #: this header is not returned by this operation. sync_to = resource.header("x-container-sync-to") #: The secret key for container synchronization. If not set, #: this header is not returned by this operation. sync_key = resource.header("x-container-sync-key") #: Enables versioning on this container. The value is the name #: of another container. You must UTF-8-encode and then URL-encode #: the name before you include it in the header. To disable #: versioning, set the header to an empty string. versions_location = resource.header("x-versions-location") #: The MIME type of the list of names. content_type = resource.header("content-type") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the #: Content-Type header, if present. detect_content_type = resource.header("x-detect-content-type", type=bool) #: In combination with Expect: 100-Continue, specify an #: "If-None-Match: \*" header to query whether the server already #: has a copy of the object before any data is sent. if_none_match = resource.header("if-none-match") @classmethod def create_by_id(cls, session, attrs, resource_id=None): """Create a Resource from its attributes. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param dict attrs: The attributes to be sent in the body of the request. :param resource_id: This resource's identifier, if needed by the request. The default is ``None``. :return: A ``dict`` representing the response headers. """ url = cls._get_url(None, resource_id) headers = attrs.get(resource.HEADERS, dict()) headers['Accept'] = '' return session.put(url, endpoint_filter=cls.service, headers=headers).headers def create(self, session): """Create a Resource from this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :return: This instance. """ resp = self.create_by_id(session, self._attrs, self.id) self.set_headers(resp) self._reset_dirty() return self
class FakeResource2(FakeResource): header1 = resource.header("header1") header2 = resource.header("header2")
class Container(resource.Resource): base_path = "/" service = object_store_service.ObjectStoreService() id_attribute = "name" allow_create = True allow_retrieve = True allow_update = True allow_delete = True allow_list = True allow_head = True # Account data (when id=None) #: The total number of bytes that are stored in Object Storage for #: the account. account_bytes_used = resource.header("x-account-bytes-used", type=int) #: The number of containers. account_container_count = resource.header("x-account-container-count", type=int) #: The number of objects in the account. account_object_count = resource.header("x-account-object-count", type=int) #: The secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key = resource.header("x-account-meta-temp-url-key") #: A second secret key value for temporary URLs. If not set, #: this header is not returned by this operation. meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2") # Container body data (when id=None) #: The name of the container. name = resource.prop("name") #: The number of objects in the container. count = resource.prop("count") #: The total number of bytes that are stored in Object Storage #: for the container. bytes = resource.prop("bytes") # Container metadata (when id=name) #: The number of objects. object_count = resource.header("x-container-object-count", type=int) #: The count of bytes used in total. bytes_used = resource.header("x-container-bytes-used", type=int) # Request headers (when id=None) #: If set to True, Object Storage queries all replicas to return the #: most recent one. If you omit this header, Object Storage responds #: faster after it finds one valid replica. Because setting this #: header to True is more expensive for the back end, use it only #: when it is absolutely needed. newest = resource.header("x-newest", type=bool) # Request headers (when id=name) #: The ACL that grants read access. If not set, this header is not #: returned by this operation. read_ACL = resource.header("x-container-read") #: The ACL that grants write access. If not set, this header is not #: returned by this operation. write_ACL = resource.header("x-container-write") #: The destination for container synchronization. If not set, #: this header is not returned by this operation. sync_to = resource.header("x-container-sync-to") #: The secret key for container synchronization. If not set, #: this header is not returned by this operation. sync_key = resource.header("x-container-sync-key") #: Enables versioning on this container. The value is the name #: of another container. You must UTF-8-encode and then URL-encode #: the name before you include it in the header. To disable #: versioning, set the header to an empty string. versions_location = resource.header("x-versions-location") #: Set to any value to disable versioning. remove_versions_location = resource.header("x-remove-versions-location") #: Changes the MIME type for the object. content_type = resource.header("content-type") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the #: Content-Type header, if present. detect_content_type = resource.header("x-detect-content-type", type=bool) #: In combination with Expect: 100-Continue, specify an #: "If-None-Match: \*" header to query whether the server already #: has a copy of the object before any data is sent. if_none_match = resource.header("if-none-match") @classmethod def update_by_id(cls, session, resource_id, attrs, path_args=None): """Update a Container with the given attributes. :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 attrs: The attributes to be sent in the body of the request. :param dict path_args: This parameter is sent by the base class but is ignored for this method. :return: A ``dict`` representing the response headers. """ url = cls._get_url(None, resource_id) headers = attrs.get(resource.HEADERS, dict()) return session.post(url, service=cls.service, accept=None, headers=headers).headers @classmethod def create_by_id(cls, session, attrs, resource_id=None): """Create a Container from its attributes. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :param dict attrs: The attributes to be sent in the body of the request. :param resource_id: This resource's identifier, if needed by the request. The default is ``None``. :return: A ``dict`` representing the response headers. """ url = cls._get_url(None, resource_id) headers = attrs.get(resource.HEADERS, dict()) return session.put(url, service=cls.service, accept=None, headers=headers).headers def create(self, session): """Create a Container from this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` :return: This :class:`~openstack.object_store.v1.container.Container` instance. """ resp = self.create_by_id(session, self._attrs, self.id) self.set_headers(resp) self._reset_dirty() return self
class Image(resource.Resource): resources_key = 'images' base_path = '/images' service = image_service.ImageService() # capabilities allow_create = True allow_retrieve = True allow_update = True allow_delete = True allow_list = True patch_update = True # The image data (bytes or a file-like object) data = None # URI for the image location = resource.header("location") # Properties #: Hash of the image data used. The Image service uses this value #: for verification. checksum = resource.prop('checksum') #: The container format refers to whether the VM image is in a file #: format that also contains metadata about the actual VM. #: Container formats include OVF and Amazon AMI. In addition, #: a VM image might not have a container format - instead, #: the image is just a blob of unstructured data. container_format = resource.prop('container_format') #: The date and time when the image was created. created_at = resource.prop('created_at') #: Valid values are: aki, ari, ami, raw, iso, vhd, vdi, qcow2, or vmdk. #: The disk format of a VM image is the format of the underlying #: disk image. Virtual appliance vendors have different formats #: for laying out the information contained in a VM disk image. disk_format = resource.prop('disk_format') #: The minimum disk size in GB that is required to boot the image. min_disk = resource.prop('min_disk') #: The name of the image. name = resource.prop('name') #: The ID of the owner, or tenant, of the image. owner = resource.prop('owner') #: Properties, if any, that are associated with the image. properties = resource.prop('properties') #: Defines whether the image can be deleted. protected = resource.prop('protected', type=bool) #: The size of the image data, in bytes. size = resource.prop('size', type=int) #: When present, Glance will attempt to store the disk image data in the #: backing store indicated by the value of the header. When not present, #: Glance will store the disk image data in the backing store that is #: marked default. Valid values are: file, s3, rbd, swift, cinder, #: gridfs, sheepdog, or vsphere. store = resource.prop('store') #: The image status. status = resource.prop('status') #: Tags, if any, that are associated with the image. tags = resource.prop('tags') #: The date and time when the image was updated. updated_at = resource.prop('updated_at') #: The virtual size of the image. virtual_size = resource.prop('virtual_size') #: The image visibility. visibility = resource.prop('visibility') def upload_image(self, session): url = utils.urljoin(self._get_url(resource_id=self.id), 'file') headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers['Accept'] = '' session.put(url, endpoint_filter=self.service, data=self.data, headers=headers)
class Test(resource.Resource): hey = resource.header("vocals") ho = resource.header("guitar") letsgo = resource.header("bass")