def list_public(self, detail=False, filters={}, order=''): """ :param detail: (bool) :param filters: (dict) request filters :param order: (str) order listing by field (default is ascending, - for descending) :returns: (list) id,name + full image info if detail """ path = path4url('images', 'detail') if detail else ( '%s/' % path4url('images')) async_params = {} if isinstance(filters, dict): for key, value in filters.items(): if value: async_params[key] = value if order and order.startswith('-'): async_params['sort_dir'] = 'desc' order = order[1:] else: async_params['sort_dir'] = 'asc' if order: async_params['sort_key'] = order r = self.get(path, async_params=async_params, success=200) return r.json
def volumes_post( self, size, server_id, display_name, display_description=None, snapshot_id=None, imageRef=None, volume_type=None, metadata=None, project=None, success=202, **kwargs ): path = path4url("volumes") volume = dict(size=int(size), server_id=server_id, display_name=display_name) if display_description is not None: volume["display_description"] = display_description if snapshot_id is not None: volume["snapshot_id"] = snapshot_id if imageRef is not None: volume["imageRef"] = imageRef if volume_type is not None: volume["volume_type"] = volume_type if metadata is not None: volume["metadata"] = metadata if project is not None: volume["project"] = project return self.post(path, json=dict(volume=volume), success=success, **kwargs)
def volumes_put( self, volume_id, display_description=None, display_name=None, delete_on_termination=None, metadata=None, success=200, **kwargs): """PUT endpoint_url/volumes/volume_id :param volume_id: (str) :param display_description: (str) :param display_name: (str) :param metadata: (dict) {metakey: metavalue, ...} """ path = utils.path4url('volumes', volume_id) volume = dict() if display_description is not None: volume['display_description'] = display_description if display_name is not None: volume['display_name'] = display_name if delete_on_termination is not None: volume['delete_on_termination'] = bool(delete_on_termination) if metadata is not None: volume['metadata'] = metadata return self.put( path, json=dict(volume=volume), success=success, **kwargs)
def container_put( self, quota=None, versioning=None, project_id=None, metadata=None, *args, **kwargs): """ Full Pithos+ PUT at container level --- request headers --- :param quota: (integer) Size limit in KB :param versioning: (string) 'auto' or other string supported by server :param metadata: (dict) Optional user defined metadata in the form { 'name1': 'value1', 'name2': 'value2', ... } :returns: ConnectionResponse """ self._assert_container() self.request_header_prefices_to_quote = ['x-container-meta-', ] self.set_header('X-Container-Policy-Quota', quota) self.set_header('X-Container-Policy-Versioning', versioning) if project_id is not None: self.set_header('X-Container-Policy-Project', project_id) if metadata: for metaname, metaval in metadata.items(): self.set_header('X-Container-Meta-' + metaname, metaval) self._quote_header_keys( self.headers, ('x-container-policy-', 'x-container-meta-')) path = path4url(self.account, self.container) success = kwargs.pop('success', (201, 202)) return self.put(path, *args, success=success, **kwargs)
def snapshots_post( self, volume_id, force=None, display_name=None, display_description=None, success=202, **kwargs): """POST endpoint_url/snapshots :param volume_id: (str) :param force: (boolean) :param display_name: (str) :param display_description: (str) """ path = utils.path4url('snapshots') snapshot = dict(volume_id=volume_id) if force is not None: snapshot['force'] = bool(force) if display_name is not None: snapshot['display_name'] = display_name if display_description is not None: snapshot['display_description'] = display_description return self.post( path, json=dict(snapshot=snapshot), success=success, **kwargs)
def account_head( self, until=None, if_modified_since=None, if_unmodified_since=None, *args, **kwargs): """ Full Pithos+ HEAD at account level --- request parameters --- :param until: (string) optional timestamp --- request headers --- :param if_modified_since: (string) Retrieve if account has changed since provided timestamp :param if_unmodified_since: (string) Retrieve if account has not change since provided timestamp :returns: ConnectionResponse """ self._assert_account() path = path4url(self.account) self.set_param('until', until, iff=until) self.set_header('If-Modified-Since', if_modified_since) self.set_header('If-Unmodified-Since', if_unmodified_since) success = kwargs.pop('success', 204) return self.head(path, *args, success=success, **kwargs)
def volumes_post( self, size, display_name, server_id=None, display_description=None, snapshot_id=None, imageRef=None, volume_type=None, metadata=None, project=None, success=202, **kwargs): path = path4url('volumes') volume = dict(size=int(size), display_name=display_name) if server_id is not None: volume['server_id'] = server_id if display_description is not None: volume['display_description'] = display_description if snapshot_id is not None: volume['snapshot_id'] = snapshot_id if imageRef is not None: volume['imageRef'] = imageRef if volume_type is not None: volume['volume_type'] = volume_type if metadata is not None: volume['metadata'] = metadata if project is not None: volume['project'] = project return self.post( path, json=dict(volume=volume), success=success, **kwargs)
def container_post( self, update=True, format='json', quota=None, versioning=None, project_id=None, metadata=None, content_type=None, content_length=None, transfer_encoding=None, *args, **kwargs): """ Full Pithos+ POST at container level --- request params --- :param update: (bool) if True, Do not replace metadata/groups :param format: (string) json (default) or xml --- request headers --- :param quota: (integer) Size limit in KB :param versioning: (string) 'auto' or other string supported by server :param metadata: (dict) Optional user defined metadata in the form { 'name1': 'value1', 'name2': 'value2', ... } :param content_type: (string) set a custom content type :param content_length: (string) set a custrom content length :param transfer_encoding: (string) set a custom transfer encoding :returns: ConnectionResponse """ self._assert_container() self.request_header_prefices_to_quote = ['x-container-meta-', ] self.set_param('update', '', iff=update) self.set_param('format', format, iff=format) self.set_header('X-Container-Policy-Quota', quota) self.set_header('X-Container-Policy-Versioning', versioning) if project_id is not None: self.set_header('X-Container-Policy-Project', project_id) if metadata: for metaname, metaval in metadata.items(): self.set_header('X-Container-Meta-' + metaname, metaval) self.set_header('Content-Type', content_type) self.set_header('Content-Length', content_length) self.set_header('Transfer-Encoding', transfer_encoding) self._quote_header_keys( self.headers, ('x-container-policy-', 'x-container-meta-')) path = path4url(self.account, self.container) success = kwargs.pop('success', 202) return self.post(path, *args, success=success, **kwargs)
def images_metadata_delete(self, image_id, key, success=204, **kwargs): """DEL ETE base_url/images/<image_id>/metadata/key :returns: request response """ path = path4url('images', image_id, 'metadata', key) return self.delete(path, success=success, **kwargs)
def floating_ips_post(self, json_data, ip='', success=200, **kwargs): path = path4url('os-floating-ips', ip or '') if json_data is not None: json_data = json.dumps(json_data) self.set_header('Content-Type', 'application/json') self.set_header('Content-Length', len(json_data)) return self.post(path, data=json_data, success=success, **kwargs)
def images_delete(self, image_id='', success=204, **kwargs): """DEL ETE base_url/images/<image_id> :returns: request response """ path = path4url('images', image_id) return self.delete(path, success=success, **kwargs)
def images_metadata_get(self, image_id, key=None, success=200, **kwargs): """GET base_url/<image_id>/metadata[/key] :returns: request response """ path = path4url('images', image_id, 'metadata', key or '') return self.get(path, success=success, **kwargs)
def servers_metadata_delete(self, server_id, key, success=204, **kwargs): """DEL ETE base_url/servers/<server_id>/metadata[/key] :returns: request response """ path = path4url('servers', server_id, 'metadata', key) return self.delete(path, success=success, **kwargs)
def servers_metadata_get(self, server_id, key=None, success=200, **kwargs): """GET base_url/servers/<server_id>/metadata[/key] :returns: request response """ path = path4url('servers', server_id, 'metadata', key or '') return self.get(path, success=success, **kwargs)
def servers_post( self, security_group=None, user_data=None, availability_zone=None, json_data=None, success=202, **kwargs): """POST base_url/servers :param json_data: a json-formated dict that will be send as data :param security_group: (str) :param user_data: Use to pass configuration information or scripts upon launch. Must be Base64 encoded. :param availability_zone: (str) :returns: request response """ self.set_param('security_group', security_group, iff=security_group) self.set_param('user_data', user_data, iff=user_data) self.set_param( 'availability_zone', availability_zone, iff=availability_zone) if json_data: json_data = json.dumps(json_data) self.set_header('Content-Type', 'application/json') self.set_header('Content-Length', len(json_data)) path = path4url('servers') return self.post(path, data=json_data, success=success, **kwargs)
def object_get( self, obj, format='json', hashmap=False, version=None, data_range=None, if_range=False, if_etag_match=None, if_etag_not_match=None, if_modified_since=None, if_unmodified_since=None, *args, **kwargs): """ Full Pithos+ GET at object level --- request parameters --- :param format: (string) json (default) or xml :param hashmap: (bool) Optional request for hashmap :param version: (string) optional version identified --- request headers --- :param data_range: (string) Optional range of data to retrieve :param if_range: (bool) :param if_etag_match: (string) if provided, return only results with etag matching with this :param if_etag_not_match: (string) if provided, return only results with etag not matching with this :param if_modified_since: (string) Retrieve if account has changed since provided timestamp :param if_unmodified_since: (string) Retrieve if account has not changed since provided timestamp :returns: ConnectionResponse """ self._assert_container() self.set_param('format', format, iff=format) self.set_param('hashmap', hashmap, iff=hashmap) self.set_param('version', version, iff=version) self.set_header('Range', data_range) self.set_header('If-Range', '', if_range and data_range) self.set_header('If-Match', if_etag_match, ) self.set_header('If-None-Match', if_etag_not_match) self.set_header('If-Modified-Since', if_modified_since) self.set_header('If-Unmodified-Since', if_unmodified_since) path = path4url(self.account, self.container, obj) success = kwargs.pop('success', 200) return self.get(path, *args, success=success, **kwargs)
def volumes_get(self, detail=None, volume_id=None, success=200, **kwargs): """GET endpoint_url/volumes[/<detail> | /<volume_id>] :param detail: (boolean) :param volume_id: (str) """ path = utils.path4url( 'volumes', 'detail' if detail else volume_id or '') return self.get(path, success=success, **kwargs)
def reassign_network(self, network_id, project_id, **kwargs): """POST endpoint_url/networks/<network_id>/action :returns: request response """ path = path4url('networks', network_id, 'action') req = {'reassign': {'project': project_id}} r = self.post(path, json=req, success=200, **kwargs) return r.headers
def test_path4url(self): utf = u'\u03a6\u03bf\u03cd\u03c4\u03c3\u03bf\u03c2'.encode('utf-8') for expected, args in ( ('', ('')), ('/path1/path2', ('path1', 'path2')), ('/1/number/0.28', (1, 'number', 0.28)), ('/1/n/u/m/b/er/X', ('//1//', '//n//u///m////b/er/', 'X//')), ('/p1/%s/p2' % utf.decode('utf-8'), ('p1', utf, 'p2'))): self.assertEqual(utils.path4url(*args), expected)
def keypairs_delete(self, key_name, success=200, **kwargs): """DELETE endpoint_url/os-keypairs/[<key_name>] :param key_name: (str) the name of the key :returns: request response """ path = path4url('os-keypairs', key_name) return self.delete(path, success=success, **kwargs)
def replace_object_meta(self, metapairs): """ :param metapairs: (dict) key:val metadata """ self._assert_container() path = path4url(self.account, self.container) for key, val in metapairs.items(): self.set_header('X-Object-Meta-' + key, val) self.post(path, success=202)
def list_shared(self, member): """ :param member: (str) sharers account :returns: (list) images shared by member """ path = path4url('shared-images', member) r = self.get(path, success=200) return r.json['shared_images']
def remove_member(self, image_id, member): """ :param image_id: (str) :param member: (str) user to deprive from current user's images """ path = path4url('images', image_id, 'members', member) r = self.delete(path, success=204) return r.headers
def replace_account_meta(self, metapairs): """ :param metapais: (dict) key:val metadata pairs """ self._assert_account() path = path4url(self.account) for key, val in metapairs.items(): self.set_header('X-Account-Meta-' + key, val) self.post(path, success=202)
def list_members(self, image_id): """ :param image_id: (str) :returns: (list) users who can use current user's images """ path = path4url('images', image_id, 'members') r = self.get(path, success=200) return r.json['members']
def keypairs_get(self, key_name=None, success=200, **kwargs): """GET endpoint_url/os-keypairs/[<key_name>] :param key_name: (str) the name of the key :returns: request response """ path = path4url('os-keypairs', key_name or '') return self.get(path, success=success, **kwargs)
def account_get( self, limit=None, marker=None, format='json', show_only_shared=False, public=False, until=None, if_modified_since=None, if_unmodified_since=None, *args, **kwargs): """ Full Pithos+ GET at account level --- request parameters --- :param limit: (integer) The amount of results requested (server will use default value if None) :param marker: string Return containers with name lexicographically after marker :param format: (string) reply format can be json or xml (default: json) :param shared: (bool) If true, only shared containers will be included in results :param until: (string) optional timestamp --- request headers --- :param if_modified_since: (string) Retrieve if account has changed since provided timestamp :param if_unmodified_since: (string) Retrieve if account has not changed since provided timestamp :returns: ConnectionResponse """ self._assert_account() self.response_headers = ['Last-Modified', ] self.response_header_prefices = ['X-Account-', ] self.set_param('limit', limit, iff=limit) self.set_param('marker', marker, iff=marker) self.set_param('format', format, iff=format) self.set_param('shared', iff=show_only_shared) self.set_param('public', iff=public) self.set_param('until', until, iff=until) self.set_header('If-Modified-Since', if_modified_since) self.set_header('If-Unmodified-Since', if_unmodified_since) path = path4url(self.account) success = kwargs.pop('success', (200, 204)) return self.get(path, *args, success=success, **kwargs)
def add_member(self, image_id, member): """ :param image_id: (str) :param member: (str) user to allow access to current user's images """ path = path4url('images', image_id, 'members', member) self.set_header('Content-Length', 0) r = self.put(path, success=204) return r.headers
def set_members(self, image_id, members): """ :param image_id: (str) :param members: (list) user to deprive from current user's images """ path = path4url('images', image_id, 'members') req = {'memberships': [{'member_id': member} for member in members]} r = self.put(path, json=req, success=204) return r.headers
def get_meta(self, image_id): """ :param image_id: (string) :returns: (list) image metadata (key:val) """ path = path4url('images', image_id) r = self.head(path, success=200) return _format_image_headers(r.headers)
def snapshots_put( self, snapshot_id, display_description=None, display_name=None, success=200, **kwargs): """PUT endpoint_url/snapshots/spapshot_id :param snapshot_id: (str) :param display_description: (str) :param display_name: (str) """ path = utils.path4url('snapshots', snapshot_id) snapshot = dict() if display_description is not None: snapshot['display_description'] = display_description if display_name is not None: snapshot['display_name'] = display_name return self.put( path, json=dict(snapshot=snapshot), success=success, **kwargs)
def flavors_get( self, flavor_id='', detail=False, changes_since=None, minDisk=None, minRam=None, marker=None, limit=None, success=200, **kwargs): """GET endpoint_url[/flavor_id][/command] :param flavor_id: ignored if detail :param detail: (bool) --- Parameters --- :param changes_since: when the flavor last changed :param minDisk: minimum disk space in GB filter :param minRam: minimum RAM filter :param marker: UUID of the flavor at which to set a marker :param limit: limit the number of returned values :returns: request response """ if not flavor_id: self.set_param('changes-since', changes_since, iff=changes_since) self.set_param('minDisk', minDisk, iff=minDisk) self.set_param('minRam', minRam, iff=minRam) self.set_param('marker', marker, iff=marker) self.set_param('limit', limit, iff=limit) path = path4url('flavors', 'detail' if detail else (flavor_id or '')) return self.get(path, success=success, **kwargs)
def container_put(self, quota=None, versioning=None, project_id=None, metadata=None, *args, **kwargs): """ Full Pithos+ PUT at container level --- request headers --- :param quota: (integer) Size limit in KB :param versioning: (string) 'auto' or other string supported by server :param metadata: (dict) Optional user defined metadata in the form { 'name1': 'value1', 'name2': 'value2', ... } :returns: ConnectionResponse """ self._assert_container() self.request_header_prefices_to_quote = [ 'x-container-meta-', ] self.set_header('X-Container-Policy-Quota', quota) self.set_header('X-Container-Policy-Versioning', versioning) if project_id is not None: self.set_header('X-Container-Policy-Project', project_id) if metadata: for metaname, metaval in metadata.items(): self.set_header('X-Container-Meta-' + metaname, metaval) self._quote_header_keys(self.headers, ('x-container-policy-', 'x-container-meta-')) path = path4url(self.account, self.container) success = kwargs.pop('success', (201, 202)) return self.put(path, *args, success=success, **kwargs)
def servers_put( self, server_id, server_name=None, json_data=None, success=204, **kwargs): """PUT endpoint_url/servers/<server_id> :param json_data: a json-formated dict that will be send as data :param success: success code (iterable of) codes :raises ClientError: if returned code not in success list :returns: request response """ self.set_param('server', server_name, iff=server_name) if json_data: json_data = json.dumps(json_data) self.set_header('Content-Type', 'application/json') self.set_header('Content-Length', len(json_data)) path = path4url('servers', server_id) return self.put(path, data=json_data, success=success, **kwargs)
def object_delete(self, object, until=None, delimiter=None, *args, **kwargs): """ Full Pithos+ DELETE at object level --- request parameters --- :param until: (string) Optional timestamp :returns: ConnectionResponse """ self._assert_container() self.set_param('until', until, iff=until) self.set_param('delimiter', delimiter, iff=delimiter) path = path4url(self.account, self.container, object) success = kwargs.pop('success', 204) return self.delete(path, *args, success=success, **kwargs)
def floatingips_post(self, json_data, **kwargs): return self.post(path4url('floatingips'), json=json_data, **kwargs)
def floatingips_put(self, floatingip_id, json_data, **kwargs): return self.put(path4url('floatingips', floatingip_id), json=json_data, **kwargs)
def object_post(self, obj, format='json', update=True, if_etag_match=None, if_etag_not_match=None, content_length=None, content_type=None, content_range=None, transfer_encoding=None, content_encoding=None, content_disposition=None, source_object=None, source_account=None, source_version=None, object_bytes=None, manifest=None, permissions={}, public=None, metadata={}, *args, **kwargs): """ Full Pithos+ POST at object level --- request parameters --- :param format: (string) json (default) or xml :param update: (bool) Do not replace metadata --- request headers --- :param if_etag_match: (string) if provided, return only results with etag matching with this :param if_etag_not_match: (string) if provided, return only results with etag not matching with this :param content_length: (string) The size of the data written :param content_type: (string) The MIME content type of the object :param content_range: (string) The range of data supplied :param transfer_encoding: (string) Set to chunked to specify incremental uploading (if used, Content-Length is ignored) :param content_encoding: (string) The encoding of the object :param content_disposition: (string) Object presentation style :param source_object: (string) Update with data from the object at path /<container>/<object> :param source_account: (string) The source account to update from :param source_version: (string) The source version to copy from :param object_bytes: (integer) The updated objects final size :param manifest: (string) Object parts prefix as /<container>/<object> :param permissions: (dict) Object permissions in the form (all fields are optional) { 'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...] } :param public: (bool) If true, Object is published, False, unpublished :param metadata: (dict) Optional user defined metadata in the form {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} :returns: ConnectionResponse """ self._assert_container() self.response_headers = ['ETag', 'X-Object-Version'] self.request_header_prefices_to_quote = [ 'x-object-meta-', ] self.set_param('format', format, iff=format) self.set_param('update', '', iff=update) self.set_header('If-Match', if_etag_match) self.set_header('If-None-Match', if_etag_not_match) self.set_header('Content-Length', content_length, iff=not transfer_encoding) self.set_header('Content-Type', content_type) self.set_header('Content-Range', content_range) self.set_header('Transfer-Encoding', transfer_encoding) self.set_header('Content-Encoding', content_encoding) self.set_header('Content-Disposition', content_disposition) self.set_header('X-Source-Object', source_object) self.set_header('X-Source-Account', source_account) self.set_header('X-Source-Version', source_version) self.set_header('X-Object-Bytes', object_bytes) self.set_header('X-Object-Manifest', manifest) perms = ';'.join([ '%s=%s' % (k, ','.join(v)) for k, v in permissions.items() if (v) ]) if (permissions) else '' self.set_header('X-Object-Sharing', perms, iff=permissions) self.set_header('X-Object-Public', public, public is not None) for key, val in metadata.items(): self.set_header('X-Object-Meta-' + key, val) self._quote_header_keys(self.headers, ('x-object-meta-', )) path = path4url(self.account, self.container, obj) success = kwargs.pop('success', (202, 204)) return self.post(path, *args, success=success, **kwargs)
def object_move(self, object, format='json', ignore_content_type=False, if_etag_match=None, if_etag_not_match=None, destination=None, destination_account=None, content_type=None, content_encoding=None, content_disposition=None, permissions={}, public=None, metadata={}, *args, **kwargs): """ Full Pithos+ COPY at object level --- request parameters --- :param format: (string) json (default) or xml :param ignore_content_type: (bool) Ignore the supplied Content-Type --- request headers --- :param if_etag_match: (string) if provided, return only results with etag matching with this :param if_etag_not_match: (string) if provided, return only results with etag not matching with this :param destination: (string) The destination path in the form /<container>/<object> :param destination_account: (string) The destination account to copy to :param content_type: (string) The MIME content type of the object :param content_encoding: (string) The encoding of the object :param content_disposition: (string) Object presentation style :param source_version: (string) The source version to copy from :param permissions: (dict) Object permissions in the form (all fields are optional) { 'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...] } :param public: (bool) If true, Object is published, False, unpublished :param metadata: (dict) Optional user defined metadata in the form {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} :returns: ConnectionResponse """ self._assert_container() self.response_headers = [ 'If-Match', 'If-None-Match', 'Destination', 'Destination-Account', 'Content-Type', 'Content-Encoding', 'Content-Disposition', 'X-Source-Version', ] self.response_header_prefices = [ 'X-Object-', ] self.request_header_prefices_to_quote = [ 'x-object-meta-', 'Destination' ] self.set_param('format', format, iff=format) self.set_param('ignore_content_type', iff=ignore_content_type) self.set_header('If-Match', if_etag_match) self.set_header('If-None-Match', if_etag_not_match) self.set_header('Destination', destination) self.set_header('Destination-Account', destination_account) self.set_header('Content-Type', content_type) self.set_header('Content-Encoding', content_encoding) self.set_header('Content-Disposition', content_disposition) perms = ';'.join([ '%s=%s' % (k, ','.join(v)) for k, v in permissions.items() if (v) ]) if (permissions) else '' self.set_header('X-Object-Sharing', perms, iff=permissions) self.set_header('X-Object-Public', public, public is not None) if metadata: for key, val in metadata.items(): self.set_header('X-Object-Meta-' + key, val) self._unquote_header_keys(self.headers, 'x-object-meta-') path = path4url(self.account, self.container, object) success = kwargs.pop('success', 201) return self.move(path, *args, success=success, **kwargs)
def volumes_action_post(self, volume_id, json_data, success=200, **kwargs): path = path4url('volumes', volume_id, 'action') return self.post(path, json=json_data, success=success, **kwargs)
def ports_get(self, port_id=None, **kwargs): if port_id: return self.get(path4url('ports', port_id), **kwargs) return self.get(path4url('ports'), **kwargs)
def ports_put(self, port_id, json_data=None, **kwargs): return self.put(path4url('ports', port_id), json=json_data, **kwargs)
def floatingips_delete(self, floatingip_id, **kwargs): return self.delete(path4url('floatingips', floatingip_id), **kwargs)
def container_get(self, limit=None, marker=None, prefix=None, delimiter=None, path=None, format='json', meta=[], show_only_shared=False, public=False, until=None, if_modified_since=None, if_unmodified_since=None, *args, **kwargs): """ Full Pithos+ GET at container level --- request parameters --- :param limit: (integer) The amount of results requested (server will use default value if None) :param marker: (string) Return containers with name lexicographically after marker :param prefix: (string) Return objects starting with prefix :param delimiter: (string) Return objects up to the delimiter :param path: (string) assume prefix = path and delimiter = / (overwrites prefix and delimiter) :param format: (string) reply format can be json or xml (default:json) :param meta: (list) Return objects that satisfy the key queries in the specified comma separated list (use <key>, !<key> for existence queries, <key><op><value> for value queries, where <op> can be one of =, !=, <=, >=, <, >) :param show_only_shared: (bool) If true, only shared containers will be included in results :param until: (string) optional timestamp --- request headers --- :param if_modified_since: (string) Retrieve if account has changed since provided timestamp :param if_unmodified_since: (string) Retrieve if account has not changed since provided timestamp :returns: ConnectionResponse """ self._assert_container() self.response_headers = [ 'Last-Modified', ] self.response_header_prefices = [ 'X-Container-', ] self.set_param('limit', limit, iff=limit) self.set_param('marker', marker, iff=marker) if not path: self.set_param('prefix', prefix, iff=prefix) self.set_param('delimiter', delimiter, iff=delimiter) else: self.set_param('path', path) self.set_param('format', format, iff=format) self.set_param('shared', iff=show_only_shared) self.set_param('public', iff=public) if meta: self.set_param('meta', ','.join(meta)) self.set_param('until', until, iff=until) self.set_header('If-Modified-Since', if_modified_since) self.set_header('If-Unmodified-Since', if_unmodified_since) path = path4url(self.account, self.container) success = kwargs.pop('success', 200) return self.get(path, *args, success=success, **kwargs)
def volume_attachment_delete(self, server_id, attachment_id, **kwargs): path = path4url('servers', server_id, 'os-volume_attachments', attachment_id) success = kwargs.pop('success', 202) return self.delete(path, success=success, **kwargs)
def volume_attachment_post(self, server_id, volume_id, **kwargs): path = path4url('servers', server_id, 'os-volume_attachments') data = dict(volumeAttachment=dict(volumeId=volume_id)) success = kwargs.pop('success', 202) return self.post(path, json=data, success=success, **kwargs)
def servers_diagnostics_get(self, server_id, **kwargs): """GET endpoint_url/servers/<server_id>/diagnostics""" path = path4url('servers', server_id, 'diagnostics') return self.get(path, success=200, **kwargs)
def servers_stats_get(self, server_id, **kwargs): """GET endpoint_url/servers/<server_id>/stats""" path = path4url('servers', server_id, 'stats') return self.get(path, success=200, **kwargs)
def floatingips_get(self, floatingip_id=None, **kwargs): return self.get(path4url('floatingips', floatingip_id or ''), **kwargs)
def snapshots_delete(self, snapshot_id, success=202, **kwargs): """DEL ETE endpoint_url/snapshots/snapshot_id :param snapshot_id: (str) """ path = utils.path4url('snapshots', snapshot_id) return self.delete(path, success=success, **kwargs)
def ports_delete(self, port_id, **kwargs): return self.delete(path4url('ports', port_id), **kwargs)
def list_ports(self, detail=None): path = path4url('ports', 'detail' if detail else '') r = self.get(path, success=200) return r.json['ports']
def ports_post(self, json_data=None, **kwargs): return self.post(path4url('ports'), json=json_data, **kwargs)
def object_put(self, obj, format='json', hashmap=False, delimiter=None, if_etag_match=None, if_etag_not_match=None, etag=None, content_length=None, content_type=None, transfer_encoding=None, copy_from=None, move_from=None, source_account=None, source_version=None, content_encoding=None, content_disposition=None, manifest=None, permissions=None, public=None, metadata=None, *args, **kwargs): """ Full Pithos+ PUT at object level --- request parameters --- :param format: (string) json (default) or xml :param hashmap: (bool) Optional hashmap provided instead of data --- request headers --- :param if_etag_match: (string) if provided, return only results with etag matching with this :param if_etag_not_match: (string) if provided, return only results with etag not matching with this :param etag: (string) The MD5 hash of the object (optional to check written data) :param content_length: (integer) The size of the data written :param content_type: (string) The MIME content type of the object :param transfer_encoding: (string) Set to chunked to specify incremental uploading (if used, Content-Length is ignored) :param copy_from: (string) The source path in the form /<container>/<object> :param move_from: (string) The source path in the form /<container>/<object> :param source_account: (string) The source account to copy/move from :param source_version: (string) The source version to copy from :param conent_encoding: (string) The encoding of the object :param content_disposition: (string) Presentation style of the object :param manifest: (string) Object parts prefix in /<container>/<object> form :param permissions: (dict) Object permissions in the form (all fields are optional) { 'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...] } :param public: (bool) If true, Object is published, False, unpublished :param metadata: (dict) Optional user defined metadata in the form {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} :returns: ConnectionResponse """ self._assert_container() self.response_headers = [ 'ETag', 'X-Object-Version', ] self.request_headers_to_quote = [ 'x-copy-from', 'x-move-from', ] self.request_header_prefices_to_quote = [ 'x-object-meta-', ] self.set_param('format', format, iff=format) self.set_param('hashmap', hashmap, iff=hashmap) self.set_param('delimiter', delimiter, iff=delimiter) self.set_header('If-Match', if_etag_match) self.set_header('If-None-Match', if_etag_not_match) self.set_header('ETag', etag) self.set_header('Content-Length', content_length) self.set_header('Content-Type', content_type) self.set_header('Transfer-Encoding', transfer_encoding) self.set_header('X-Copy-From', copy_from) self.set_header('X-Move-From', move_from) self.set_header('X-Source-Account', source_account) self.set_header('X-Source-Version', source_version) self.set_header('Content-Encoding', content_encoding) self.set_header('Content-Disposition', content_disposition) self.set_header('X-Object-Manifest', manifest) if permissions: perms = None if permissions: for perm_type, perm_list in permissions.items(): if not perms: perms = '' # Remove permissions if perm_list: perms += ';' if perms else '' perms += '%s=%s' % (perm_type, ','.join(perm_list)) self.set_header('X-Object-Sharing', perms) self.set_header('X-Object-Public', public, public is not None) if metadata: for key, val in metadata.items(): self.set_header('X-Object-Meta-' + key, val) self._quote_header_keys(self.headers, ('x-object-meta-', )) path = path4url(self.account, self.container, obj) success = kwargs.pop('success', 201) return self.put(path, *args, success=success, **kwargs)
def subnets_delete(self, subnet_id, **kwargs): return self.delete(path4url('subnets', subnet_id), **kwargs)
def volumes_delete(self, volume_id, success=202, **kwargs): """DEL ETE endpoint_url/volumes/volume_id :param volume_id: (str) """ return self.delete( utils.path4url('volumes', volume_id), success=success, **kwargs)
def container_post(self, update=True, format='json', quota=None, versioning=None, project_id=None, metadata=None, content_type=None, content_length=None, transfer_encoding=None, *args, **kwargs): """ Full Pithos+ POST at container level --- request params --- :param update: (bool) if True, Do not replace metadata/groups :param format: (string) json (default) or xml --- request headers --- :param quota: (integer) Size limit in KB :param versioning: (string) 'auto' or other string supported by server :param metadata: (dict) Optional user defined metadata in the form { 'name1': 'value1', 'name2': 'value2', ... } :param content_type: (string) set a custom content type :param content_length: (string) set a custrom content length :param transfer_encoding: (string) set a custom transfer encoding :returns: ConnectionResponse """ self._assert_container() self.request_header_prefices_to_quote = [ 'x-container-meta-', ] self.set_param('update', '', iff=update) self.set_param('format', format, iff=format) self.set_header('X-Container-Policy-Quota', quota) self.set_header('X-Container-Policy-Versioning', versioning) if project_id is not None: self.set_header('X-Container-Policy-Project', project_id) if metadata: for metaname, metaval in metadata.items(): self.set_header('X-Container-Meta-' + metaname, metaval) self.set_header('Content-Type', content_type) self.set_header('Content-Length', content_length) self.set_header('Transfer-Encoding', transfer_encoding) self._quote_header_keys(self.headers, ('x-container-policy-', 'x-container-meta-')) path = path4url(self.account, self.container) success = kwargs.pop('success', 202) return self.post(path, *args, success=success, **kwargs)
def object_get(self, obj, format='json', hashmap=False, version=None, data_range=None, if_range=False, if_etag_match=None, if_etag_not_match=None, if_modified_since=None, if_unmodified_since=None, *args, **kwargs): """ Full Pithos+ GET at object level --- request parameters --- :param format: (string) json (default) or xml :param hashmap: (bool) Optional request for hashmap :param version: (string) optional version identified --- request headers --- :param data_range: (string) Optional range of data to retrieve :param if_range: (bool) :param if_etag_match: (string) if provided, return only results with etag matching with this :param if_etag_not_match: (string) if provided, return only results with etag not matching with this :param if_modified_since: (string) Retrieve if account has changed since provided timestamp :param if_unmodified_since: (string) Retrieve if account has not changed since provided timestamp :returns: ConnectionResponse """ self._assert_container() self.response_headers = [ 'ETag', 'Content-Length', 'Content-Type', 'Last-Modified', 'Content-Encoding', 'Content-Disposition', 'Content-Range', ] self.response_header_prefices = [ 'X-Object-', ] self.set_param('format', format, iff=format) self.set_param('hashmap', hashmap, iff=hashmap) self.set_param('version', version, iff=version) self.set_header('Range', data_range) self.set_header('If-Range', '', if_range and data_range) self.set_header( 'If-Match', if_etag_match, ) self.set_header('If-None-Match', if_etag_not_match) self.set_header('If-Modified-Since', if_modified_since) self.set_header('If-Unmodified-Since', if_unmodified_since) path = path4url(self.account, self.container, obj) success = kwargs.pop('success', 200) r = self.get(path, *args, success=success, **kwargs) self._unquote_header_keys(r.headers, ('x-object-meta-')) return r
def types_get(self, type_id=None, success=200, **kwargs): """GET endpoint_url/types[/<type_id>]""" path = utils.path4url('types', type_id or '') return self.get(path, success=success, **kwargs)
def reassign_floating_ip(self, floating_network_id, project_id): """Change the project where this ip is charged""" path = path4url('floatingips', floating_network_id, 'action') json_data = dict(reassign=dict(project=project_id)) self.post(path, json=json_data, success=200)