Notice
This document is for a development version of Ceph.
Librados (Python)
The rados
module is a thin Python wrapper for librados
.
Installation
To install Python libraries for Ceph, see Getting librados for Python.
Getting Started
You can create your own Ceph client using Python. The following tutorial will
show you how to import the Ceph Python module, connect to a Ceph cluster, and
perform object operations as a client.admin
user.
Note
To use the Ceph Python bindings, you must have access to a running Ceph cluster. To set one up quickly, see Getting Started.
First, create a Python source file for your Ceph client.
vim client.py
Import the Module
To use the rados
module, import it into your source file.
1 import rados
Configure a Cluster Handle
Before connecting to the Ceph Storage Cluster, create a cluster handle. By
default, the cluster handle assumes a cluster named ceph
(i.e., the default
for deployment tools, and our Getting Started guides too), and a
client.admin
user name. You may change these defaults to suit your needs.
To connect to the Ceph Storage Cluster, your application needs to know where to find the Ceph Monitor. Provide this information to your application by specifying the path to your Ceph configuration file, which contains the location of the initial Ceph monitors.
1 import rados, sys
2
3 #Create Handle Examples.
4 cluster = rados.Rados(conffile='ceph.conf')
5 cluster = rados.Rados(conffile=sys.argv[1])
6 cluster = rados.Rados(conffile = 'ceph.conf', conf = dict (keyring = '/path/to/keyring'))
Ensure that the conffile
argument provides the path and file name of your
Ceph configuration file. You may use the sys
module to avoid hard-coding the
Ceph configuration path and file name.
Your Python client also requires a client keyring. For this example, we use the
client.admin
key by default. If you would like to specify the keyring when
creating the cluster handle, you may use the conf
argument. Alternatively,
you may specify the keyring path in your Ceph configuration file. For example,
you may add something like the following line to your Ceph configuration file:
keyring = /path/to/ceph.client.admin.keyring
For additional details on modifying your configuration via Python, see Configuration.
Connect to the Cluster
Once you have a cluster handle configured, you may connect to the cluster. With a connection to the cluster, you may execute methods that return information about the cluster.
1 import rados, sys
2
3 cluster = rados.Rados(conffile='ceph.conf')
4 print("\nlibrados version: {}".format(str(cluster.version())))
5 print("Will attempt to connect to: {}".format(str(cluster.conf_get('mon host'))))
6
7 cluster.connect()
8 print("\nCluster ID: {}".format(cluster.get_fsid()))
9
10 print("\n\nCluster Statistics")
11 print("==================")
12 cluster_stats = cluster.get_cluster_stats()
13
14 for key, value in cluster_stats.items():
15 print(key, value)
By default, Ceph authentication is on
. Your application will need to know
the location of the keyring. The python-ceph
module doesn’t have the default
location, so you need to specify the keyring path. The easiest way to specify
the keyring is to add it to the Ceph configuration file. The following Ceph
configuration file example uses the client.admin
keyring.
1 [global]
2 # ... elided configuration
3 keyring = /path/to/keyring/ceph.client.admin.keyring
Manage Pools
When connected to the cluster, the Rados
API allows you to manage pools. You
can list pools, check for the existence of a pool, create a pool and delete a
pool.
1 print("\n\nPool Operations")
2 print("===============")
3
4 print("\nAvailable Pools")
5 print("----------------")
6 pools = cluster.list_pools()
7
8 for pool in pools:
9 print(pool)
10
11 print("\nCreate 'test' Pool")
12 print("------------------")
13 cluster.create_pool('test')
14
15 print("\nPool named 'test' exists: {}".format(str(cluster.pool_exists('test'))))
16 print("\nVerify 'test' Pool Exists")
17 print("-------------------------")
18 pools = cluster.list_pools()
19
20 for pool in pools:
21 print(pool)
22
23 print("\nDelete 'test' Pool")
24 print("------------------")
25 cluster.delete_pool('test')
26 print("\nPool named 'test' exists: {}".format(str(cluster.pool_exists('test'))))
Input/Output Context
Reading from and writing to the Ceph Storage Cluster requires an input/output
context (ioctx). You can create an ioctx with the open_ioctx()
or
open_ioctx2()
method of the Rados
class. The ioctx_name
parameter
is the name of the pool and pool_id
is the ID of the pool you wish to use.
1 ioctx = cluster.open_ioctx('data')
or
1 ioctx = cluster.open_ioctx2(pool_id)
Once you have an I/O context, you can read/write objects, extended attributes, and perform a number of other operations. After you complete operations, ensure that you close the connection. For example:
1 print("\nClosing the connection.")
2 ioctx.close()
Writing, Reading and Removing Objects
Once you create an I/O context, you can write objects to the cluster. If you write to an object that doesn’t exist, Ceph creates it. If you write to an object that exists, Ceph overwrites it (except when you specify a range, and then it only overwrites the range). You may read objects (and object ranges) from the cluster. You may also remove objects from the cluster. For example:
1print("\nWriting object 'hw' with contents 'Hello World!' to pool 'data'.")
2ioctx.write_full("hw", "Hello World!")
3
4print("\n\nContents of object 'hw'\n------------------------\n")
5print(ioctx.read("hw"))
6
7print("\nRemoving object 'hw'")
8ioctx.remove_object("hw")
Writing and Reading XATTRS
Once you create an object, you can write extended attributes (XATTRs) to the object and read XATTRs from the object. For example:
1print("\n\nWriting XATTR 'lang' with value 'en_US' to object 'hw'")
2ioctx.set_xattr("hw", "lang", "en_US")
3
4print("\n\nGetting XATTR 'lang' from object 'hw'\n")
5print(ioctx.get_xattr("hw", "lang"))
Listing Objects
If you want to examine the list of objects in a pool, you may retrieve the list of objects and iterate over them with the object iterator. For example:
1object_iterator = ioctx.list_objects()
2
3while True :
4
5 try :
6 rados_object = object_iterator.__next__()
7 print("Object contents = {}".format(rados_object.read()))
8
9 except StopIteration :
10 break
11
12# Or alternatively
13[print("Object contents = {}".format(obj.read())) for obj in ioctx.list_objects()]
The Object
class provides a file-like interface to an object, allowing
you to read and write content and extended attributes. Object operations using
the I/O context provide additional functionality and asynchronous capabilities.
Cluster Handle API
The Rados
class provides an interface into the Ceph Storage Daemon.
Configuration
The Rados
class provides methods for getting and setting configuration
values, reading the Ceph configuration file, and parsing arguments. You
do not need to be connected to the Ceph Storage Cluster to invoke the following
methods. See Storage Cluster Configuration for details on settings.
- Rados.conf_get(option)
Rados.conf_get(self, unicode option: str) -> Optional[str]
Get the value of a configuration option
- Parameters
option (
str
) -- which option to read- Return type
Optional
[str
]- Returns
value of the option or None
- Raises
TypeError
- Rados.conf_set(option, val)
Rados.conf_set(self, unicode option: str, unicode val: str)
Set the value of a configuration option
- Parameters
option (
str
) -- which option to setoption -- value of the option
- Raises
TypeError
,ObjectNotFound
- Rados.conf_read_file(path=None)
Rados.conf_read_file(self, unicode path: Optional[str] = None)
Configure the cluster handle using a Ceph config file.
- Parameters
path (
Optional
[str
]) -- path to the config file
- Rados.conf_parse_argv(args)
Rados.conf_parse_argv(self, args: Sequence[str])
Parse known arguments from args, and remove; returned args contain only those unknown to ceph
- Rados.version()
Rados.version(self) -> Version
Get the version number of the
librados
C library.- Return type
Version
- Returns
a tuple of
(major, minor, extra)
components of the librados version
Connection Management
Once you configure your cluster handle, you may connect to the cluster, check
the cluster fsid
, retrieve cluster statistics, and disconnect (shutdown)
from the cluster. You may also assert that the cluster handle is in a particular
state (e.g., “configuring”, “connecting”, etc.).
- Rados.connect(timeout=0)
Rados.connect(self, int timeout: int = 0)
Connect to the cluster. Use shutdown() to release resources.
- Parameters
timeout (
int
) -- Any supplied timeout value is currently ignored.
- Rados.shutdown()
Rados.shutdown(self)
Disconnects from the cluster. Call this explicitly when a Rados.connect()ed object is no longer used.
- Rados.get_fsid()
Rados.get_fsid(self) -> str
Get the fsid of the cluster as a hexadecimal string.
- Raises
Error
- Return type
str
- Returns
cluster fsid
- Rados.get_cluster_stats()
Rados.get_cluster_stats(self) -> Dict[str, int]
Read usage info about the cluster
This tells you total space, space used, space available, and number of objects. These are not updated immediately when data is written, they are eventually consistent. :rtype:
Dict
[str
,int
] :returns: contains the following keys:kb
(int) - total spacekb_used
(int) - space usedkb_avail
(int) - free space availablenum_objects
(int) - number of objects
Pool Operations
To use pool operation methods, you must connect to the Ceph Storage Cluster first. You may list the available pools, create a pool, check to see if a pool exists, and delete a pool.
- Rados.list_pools()
Rados.list_pools(self) -> List[str]
Gets a list of pool names.
- Return type
List
[str
]- Returns
list of pool names.
- Rados.create_pool(pool_name, crush_rule=None, auid=None)
Rados.create_pool(self, unicode pool_name: str, int crush_rule: Optional[int] = None, int auid: Optional[int] = None)
Create a pool: - with default settings: if crush_rule=None and auid=None - with a specific CRUSH rule: crush_rule given - with a specific auid: auid given - with a specific CRUSH rule and auid: crush_rule and auid given
- Parameters
pool_name (
str
) -- name of the pool to createcrush_rule (
Optional
[int
]) -- rule to use for placement in the new poolauid (
Optional
[int
]) -- id of the owner of the new pool
- Raises
TypeError
,Error
- Rados.pool_exists(pool_name)
Rados.pool_exists(self, unicode pool_name: str) -> bool
Checks if a given pool exists.
- Parameters
pool_name (
str
) -- name of the pool to check- Raises
TypeError
,Error
- Return type
bool
- Returns
whether the pool exists, false otherwise.
- Rados.delete_pool(pool_name)
Rados.delete_pool(self, unicode pool_name: str)
Delete a pool and all data inside it.
The pool is removed from the cluster immediately, but the actual data is deleted in the background.
- Parameters
pool_name (
str
) -- name of the pool to delete- Raises
TypeError
,Error
CLI Commands
The Ceph CLI command is internally using the following librados Python binding methods.
In order to send a command, choose the correct method and choose the correct target.
- Rados.mon_command(cmd, inbuf, timeout=0, target=None)
Send a command to the mon.
mon_command[_target](cmd, inbuf, outbuf, outbuflen, outs, outslen)
- Parameters
cmd (
str
) -- JSON formatted string.inbuf (
bytes
) -- optional string.timeout (
int
) -- This parameter is ignored.target (
Union
[str
,int
,None
]) -- name or rank of a specific mon. Optional
- Return type
Tuple
[int
,bytes
,str
]- Returns
(int ret, string outbuf, string outs)
Example:
>>> import json >>> c = Rados(conffile='/etc/ceph/ceph.conf') >>> c.connect() >>> cmd = json.dumps({"prefix": "osd safe-to-destroy", "ids": ["2"], "format": "json"}) >>> c.mon_command(cmd, b'')
- Rados.osd_command(osdid, cmd, inbuf, timeout=0)
osd_command(osdid, cmd, inbuf, outbuf, outbuflen, outs, outslen)
- Return type
Tuple
[int
,bytes
,str
]- Returns
(int ret, string outbuf, string outs)
- Rados.mgr_command(cmd, inbuf, timeout=0, target=None)
- Return type
Tuple
[int
,str
,bytes
]- Returns
(int ret, string outbuf, string outs)
- Rados.pg_command(pgid, cmd, inbuf, timeout=0)
pg_command(pgid, cmd, inbuf, outbuf, outbuflen, outs, outslen)
- Return type
Tuple
[int
,bytes
,str
]- Returns
(int ret, string outbuf, string outs)
Input/Output Context API
To write data to and read data from the Ceph Object Store, you must create
an Input/Output context (ioctx). The Rados class provides open_ioctx()
and open_ioctx2() methods. The remaining ioctx
operations involve
invoking methods of the Ioctx and other classes.
- Rados.open_ioctx(ioctx_name)
Rados.open_ioctx(self, unicode ioctx_name: str) -> Ioctx
Create an io context
The io context allows you to perform operations within a particular pool.
- Parameters
ioctx_name (
str
) -- name of the pool- Raises
TypeError
,Error
- Return type
Ioctx
- Returns
Rados Ioctx object
- Ioctx.require_ioctx_open()
Ioctx.require_ioctx_open(self)
Checks if the rados.Ioctx object state is ‘open’
- Raises
IoctxStateError
- Ioctx.get_stats()
Ioctx.get_stats(self) -> Dict[str, int]
Get pool usage statistics
- Return type
Dict
[str
,int
]- Returns
dict contains the following keys:
num_bytes
(int) - size of pool in bytesnum_kb
(int) - size of pool in kbytesnum_objects
(int) - number of objects in the poolnum_object_clones
(int) - number of object clonesnum_object_copies
(int) - number of object copiesnum_objects_missing_on_primary
(int) - number of objectsmissing on primary
num_objects_unfound
(int) - number of unfound objectsnum_objects_degraded
(int) - number of degraded objectsnum_rd
(int) - bytes readnum_rd_kb
(int) - kbytes readnum_wr
(int) - bytes writtennum_wr_kb
(int) - kbytes written
- Ioctx.get_last_version()
Ioctx.get_last_version(self) -> int
Return the version of the last object read or written to.
This exposes the internal version number of the last object read or written via this io context
- Return type
int
- Returns
version of the last object used
- Ioctx.close()
Ioctx.close(self)
Close a rados.Ioctx object.
This just tells librados that you no longer need to use the io context. It may not be freed immediately if there are pending asynchronous requests on it, but you should not use an io context again after calling this function on it.
Object Operations
The Ceph Storage Cluster stores data as objects. You can read and write objects synchronously or asynchronously. You can read and write from offsets. An object has a name (or key) and data.
- Ioctx.aio_write(object_name, to_write, offset=0, oncomplete=None, onsafe=None)
Ioctx.aio_write(self, unicode object_name: str, bytes to_write: bytes, int offset: int = 0, oncomplete: Optional[Callable[[Completion], None]] = None, onsafe: Optional[Callable[[Completion], None]] = None) -> Completion
Write data to an object asynchronously
Queues the write and returns.
- Parameters
object_name (
str
) -- name of the objectto_write (
bytes
) -- data to writeoffset (
int
) -- byte offset in the object to begin writing atoncomplete (
Optional
[Callable
[[Completion
],None
]]) -- what to do when the write is safe and complete in memory on all replicasonsafe (
Optional
[Callable
[[Completion
],None
]]) -- what to do when the write is safe and complete on storage on all replicas
- Raises
Error
- Return type
Completion
- Returns
completion object
- Ioctx.aio_write_full(object_name, to_write, oncomplete=None, onsafe=None)
Ioctx.aio_write_full(self, unicode object_name: str, bytes to_write: bytes, oncomplete: Optional[Callable] = None, onsafe: Optional[Callable] = None) -> Completion
Asynchronously write an entire object
The object is filled with the provided data. If the object exists, it is atomically truncated and then written. Queues the write and returns.
- Parameters
object_name (
str
) -- name of the objectto_write (
bytes
) -- data to writeoncomplete (
Optional
[Callable
]) -- what to do when the write is safe and complete in memory on all replicasonsafe (
Optional
[Callable
]) -- what to do when the write is safe and complete on storage on all replicas
- Raises
Error
- Return type
Completion
- Returns
completion object
- Ioctx.aio_append(object_name, to_append, oncomplete=None, onsafe=None)
Ioctx.aio_append(self, unicode object_name: str, bytes to_append: bytes, oncomplete: Optional[Callable] = None, onsafe: Optional[Callable] = None) -> Completion
Asynchronously append data to an object
Queues the write and returns.
- Parameters
object_name (
str
) -- name of the objectto_append (
bytes
) -- data to appendoffset -- byte offset in the object to begin writing at
oncomplete (
Optional
[Callable
]) -- what to do when the write is safe and complete in memory on all replicasonsafe (
Optional
[Callable
]) -- what to do when the write is safe and complete on storage on all replicas
- Raises
Error
- Return type
Completion
- Returns
completion object
- Ioctx.write(key, data, offset=0)
Ioctx.write(self, unicode key: str, bytes data: bytes, int offset: int = 0)
Write data to an object synchronously
- Parameters
key (
str
) -- name of the objectdata (
bytes
) -- data to writeoffset (
int
) -- byte offset in the object to begin writing at
- Raises
TypeError
- Raises
LogicError
- Returns
int - 0 on success
- Ioctx.write_full(key, data)
Ioctx.write_full(self, unicode key: str, bytes data: bytes)
Write an entire object synchronously.
The object is filled with the provided data. If the object exists, it is atomically truncated and then written.
- Parameters
key (
str
) -- name of the objectdata (
bytes
) -- data to write
- Raises
TypeError
- Raises
Error
- Returns
int - 0 on success
- Ioctx.aio_flush()
Ioctx.aio_flush(self)
Block until all pending writes in an io context are safe
- Raises
Error
- Ioctx.set_locator_key(loc_key)
Ioctx.set_locator_key(self, unicode loc_key: str)
Set the key for mapping objects to pgs within an io context.
The key is used instead of the object name to determine which placement groups an object is put in. This affects all subsequent operations of the io context - until a different locator key is set, all objects in this io context will be placed in the same pg.
- Parameters
loc_key (
str
) -- the key to use as the object locator, or NULL to discard any previously set key- Raises
TypeError
- Ioctx.aio_read(object_name, length, offset, oncomplete=None)
Ioctx.aio_read(self, unicode object_name: str, int length: int, int offset: int, oncomplete: Optional[Callable] = None) -> Completion
Asynchronously read data from an object
oncomplete will be called with the returned read value as well as the completion:
oncomplete(completion, data_read)
- Parameters
object_name (
str
) -- name of the object to read fromlength (
int
) -- the number of bytes to readoffset (
int
) -- byte offset in the object to begin reading fromoncomplete (
Optional
[Callable
]) -- what to do when the read is complete
- Raises
Error
- Return type
Completion
- Returns
completion object
- Ioctx.read(key, length=8192, offset=0)
Ioctx.read(self, unicode key: str, int length: int = 8192, int offset: int = 0) -> bytes
Read data from an object synchronously
- Parameters
key (
str
) -- name of the objectlength (
int
) -- the number of bytes to read (default=8192)offset (
int
) -- byte offset in the object to begin reading at
- Raises
TypeError
- Raises
Error
- Return type
bytes
- Returns
data read from object
- Ioctx.stat(key)
Ioctx.stat(self, unicode key: str) -> Tuple[int, time.struct_time]
Get object stats (size/mtime)
- Parameters
key (
str
) -- the name of the object to get stats from- Raises
TypeError
- Raises
Error
- Return type
Tuple
[int
,struct_time
]- Returns
(size,timestamp)
- Ioctx.trunc(key, size)
Ioctx.trunc(self, unicode key: str, int size: int) -> int
Resize an object
If this enlarges the object, the new area is logically filled with zeroes. If this shrinks the object, the excess data is removed.
- Parameters
key (
str
) -- the name of the object to resizesize (
int
) -- the new size of the object in bytes
- Raises
TypeError
- Raises
Error
- Return type
int
- Returns
0 on success, otherwise raises error
- Ioctx.remove_object(key)
Ioctx.remove_object(self, unicode key: str) -> bool
Delete an object
This does not delete any snapshots of the object.
- Parameters
key (
str
) -- the name of the object to delete- Raises
TypeError
- Raises
Error
- Return type
bool
- Returns
True on success
Object Extended Attributes
You may set extended attributes (XATTRs) on an object. You can retrieve a list of objects or XATTRs and iterate over them.
- Ioctx.set_xattr(key, xattr_name, xattr_value)
Ioctx.set_xattr(self, unicode key: str, unicode xattr_name: str, bytes xattr_value: bytes) -> bool
Set an extended attribute on an object.
- Parameters
key (
str
) -- the name of the object to set xattr toxattr_name (
str
) -- which extended attribute to setxattr_value (
bytes
) -- the value of the extended attribute
- Raises
TypeError
- Raises
Error
- Return type
bool
- Returns
True on success, otherwise raise an error
- Ioctx.get_xattrs(oid)
Ioctx.get_xattrs(self, unicode oid: str) -> XattrIterator
Start iterating over xattrs on an object.
- Parameters
oid (
str
) -- the name of the object to get xattrs from- Raises
TypeError
- Raises
Error
- Return type
XattrIterator
- Returns
XattrIterator
- XattrIterator.__next__()
Get the next xattr on the object
- Raises
StopIteration
- Returns
pair - of name and value of the next Xattr
- Ioctx.get_xattr(key, xattr_name)
Ioctx.get_xattr(self, unicode key: str, unicode xattr_name: str) -> bytes
Get the value of an extended attribute on an object.
- Parameters
key (
str
) -- the name of the object to get xattr fromxattr_name (
str
) -- which extended attribute to read
- Raises
TypeError
- Raises
Error
- Return type
bytes
- Returns
value of the xattr
- Ioctx.rm_xattr(key, xattr_name)
Ioctx.rm_xattr(self, unicode key: str, unicode xattr_name: str) -> bool
Removes an extended attribute on from an object.
- Parameters
key (
str
) -- the name of the object to remove xattr fromxattr_name (
str
) -- which extended attribute to remove
- Raises
TypeError
- Raises
Error
- Return type
bool
- Returns
True on success, otherwise raise an error
Object Interface
From an I/O context, you can retrieve a list of objects from a pool and iterate over them. The object interface provide makes each object look like a file, and you may perform synchronous operations on the objects. For asynchronous operations, you should use the I/O context methods.
- Ioctx.list_objects()
Ioctx.list_objects(self) -> ObjectIterator
Get ObjectIterator on rados.Ioctx object.
- Return type
ObjectIterator
- Returns
ObjectIterator
- ObjectIterator.__next__()
Get the next object name and locator in the pool
- Raises
StopIteration
- Returns
next rados.Ioctx Object
- Object.read(length=1024 * 1024)
- Object.write(string_to_write)
- Object.get_xattrs()
- Object.get_xattr(xattr_name)
- Object.set_xattr(xattr_name, xattr_value)
- Object.rm_xattr(xattr_name)
- Object.stat()
- Object.remove()
Brought to you by the Ceph Foundation
The Ceph Documentation is a community resource funded and hosted by the non-profit Ceph Foundation. If you would like to support this and our other efforts, please consider joining now.