pyxs
pyxs Documentation
- Provided by: python-pyxs-doc (Version: 0.4.2~git20190115.97f14313-5)
- Source: python-pyxs
- Report a bug
pyxs Documentation
Using pyxs is easy! The only class you need to import is Client. It provides a simple straightforward API to XenStore content with a bit of Python's syntactic sugar here and there.
Generally, if you just need to fetch or update some XenStore items you can do:
>>> from pyxs import Client >>> with Client() as c: ... c[b"/local/domain/0/name"] = b"Ziggy" ... c[b"/local/domain/0/name"] b'Ziggy'
Using Client without the with statement is possible, albeit, not recommended:
>>> c = Client() >>> c.connect() >>> c[b"/local/domain/0/name"] = b"It works!" >>> c.close()
The reason for preferring a context manager is simple: you don't have to DIY. The context manager will make sure that a started transaction was either rolled back or committed and close the underlying XenStore connection afterwards.
pyxs supports two ways of communicating with XenStore:
Connection type is determined from the arguments passed to Client constructor. For example, the following code creates a Client instance, operating over a Unix socket:
>>> Client(unix_socket_path="/var/run/xenstored/socket_ro")
Client(UnixSocketConnection('/var/run/xenstored/socket_ro'))
>>> Client()
Client(UnixSocketConnection('/var/run/xenstored/socket'))
Use xen_bus_path argument to initialize a Client with XenBusConnection:
>>> Client(xen_bus_path="/dev/xen/xenbus")
Client(XenBusConnection('/dev/xen/xenbus'))
Transactions allow you to operate on an isolated copy of XenStore tree and merge your changes back atomically on commit. Keep in mind, however, that changes made within a transaction become available to other XenStore clients only if and when committed. Here's an example:
>>> with Client() as c: ... c.transaction() ... c[b"/foo/bar"] = b"baz" ... c.commit() # ! ... print(c[b"/foo/bar"]) b'baz'
The line with an exclamation mark is a bit careless, because it ignores the fact that committing a transaction might fail. A more robust way to commit a transaction is by using a loop:
>>> with Client() as c: ... success = False ... while not success: ... c.transaction() ... c[b"/foo/bar"] = b"baz" ... success = c.commit()
You can also abort the current transaction by calling rollback().
When a new path is created or an existing path is modified, XenStore fires an event, notifying all watching clients that a change has been made. pyxs implements watching via the Monitor class. To watch a path create a monitor monitor() and call watch() with a path you want to watch and a unique token. Right after that the monitor will start to accumulate incoming events. You can iterate over them via wait():
>>> with Client() as c: ... m = c.monitor() ... m.watch(b"/foo/bar", b"a unique token") ... next(m.wait()) Event(b"/foo/bar", b"a unique token")
XenStore has a notion of special paths, which start with @ and are reserved for special occasions:
| Path | Description |
| @introduceDomain | Fired when a new domain is introduced to XenStore -- you can also introduce domains yourself with a introduce_domain() call, but in most of the cases, xenstored will do that for you. |
| @releaseDomain | Fired when XenStore is no longer communicating with a domain, see release_domain(). |
Events for both special and ordinary paths are simple two element tuples, where the first element is always event target -- a path which triggered the event and second is a token passed to watch(). A rather unfortunate consequence of this is that you can't get domid of the domain, which triggered @introduceDomain or @releaseDomain from the received event.
pyxs also provides a compatibility interface, which mimics that of xen.lowlevel.xs --- so you don't have to change anything in the code to switch to pyxs:
>>> from pyxs import xs
>>> handle = xs()
>>> handle.read("0", b"/local/domain/0/name")
b'Domain-0'
>>> handle.close()
If unix_socket_path is given or Client was created with no arguments, XenStore is accessed via UnixSocketConnection; otherwise, XenBusConnection is used.
Each client has a Router thread running in the background. The goal of the router is to multiplex requests from different transaction through a single XenStore connection.
Changed in version 0.4.0: The constructor no longer accepts connection argument. If you wan't to force the use of a specific connection class, wrap it in a Router:
from pyxs import Router, Client
from pyxs.connection import XenBusConnection
router = Router(XenBusConnection())
with Client(router=router) as c:
do_something(c)
WARNING:
SEE ALSO:
WARNING:
WARNING:
NOTE:
WARNING:
The monitor shares the router with its parent client. Thus closing the client invalidates the monitor. Closing the monitor, on the other hand, had no effect on the router state.
NOTE:
>>> with Client() as c:
... m = c.monitor():
... m.watch("foo/bar")
... print(next(c.wait()))
Event(...)
NOTE:
Any alteration to the watched path generates an event. This includes path creation, removal, contents change or permission change. An event can also be triggered spuriously.
Changes made in transactions cause an event only if and when committed.
An event is a (path, token) pair, where the first element is event path, i.e. the actual path that was modified, and the second -- a token, passed to watch().
w<domid> write only r<domid> read only b<domid> both read and write n<domid> no access
The goal of the router is to multiplex XenStore connection between multiple clients and monitors.
NOTE:
The following two "hacks" are used to ensure prompt termination.
Does nothing if the router is already started.
After termination the router can no longer send or receive packets. Does nothing if the router was already terminated.
Changed in version 0.4.0: rq_id no longer defaults to 0 and should be provided explicitly.
In case you experience issues using pyxs, do not hesitate to report it to the Bug Tracker on GitHub.
Writing a XenStore client library without having access to a running XenStore instance can be troublesome. Luckily, there is a way to setup a development using VirtualBox.
Only root is allowed to access XenStore, so the tests require sudo:
$ sudo python setup.py test
pyxs strives to work across a range of Python versions. Use tox to run the tests on all supported versions:
$ cat tox.ini [tox] envlist = py26,py27,py34,py35,pypy [testenv] commands = python setup.py test $ sudo tox
pyxs follows Pocoo style guide. Please read it before you start implementing your changes.
Here you can see the full list of changes between each pyxs release.
Bugfix release, released on May 11th, 2016
Released on March 6th, 2016
| Old name | New name |
| ls | list |
| rm | delete |
| get_permissions | get_perms |
| set_permissions | set_perms |
| transaction_start | transaction |
| transaction_end | commit and rollback |
Released on November 29th 2012
Released on September 12th 2011
Released on August 18th 2011
Initial release, released on July 16th 2011
Sergei Lebedev, Fedor Gogolev
2011-2022, Selectel