Skip to content

Commit

Permalink
Update wire-protocol.md to have working Python3 code examples
Browse files Browse the repository at this point in the history
The document was updated in f785993 to use
Python 3, however the examples were left unchanged.

In Python 3, `xmlrpclib` does not exist, it has been replaced by the `xmlrpc`
module (specifically in this case `xmlrpclib.Server` has been replaced by
`xmlrpc.client.ServerProxy`).

Additionally, the `python-jsonrpc` package has not been ported to Python 3, and
as such is unavailable. There is no direct replacement, however a combination of
the `jsonrpcclient` package and the `requests` packages provide a reasonable
solution.

This commit updates the examples appropriately so they function in Python 3.

Signed-off-by: Alex Brett <[email protected]>
  • Loading branch information
alexbrett committed Oct 16, 2024
1 parent e650ca0 commit 9507369
Showing 1 changed file with 44 additions and 27 deletions.
71 changes: 44 additions & 27 deletions ocaml/doc/wire-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,12 +469,21 @@ $ python3

### Using the XML-RPC Protocol

Import the library `xmlrpclib` and create a
Import the library `xmlrpc.client` and create a
python object referencing the remote server as shown below:

```python
>>> import xmlrpclib
>>> xen = xmlrpclib.Server("https://localhost:443")
>>> import xmlrpc.client
>>> xen = xmlrpc.client.ServerProxy("https://localhost:443")
```

Note that you may need to disable SSL certificate validation to establish the
connection, this can be done as follows:

```python
>>> import ssl
>>> ctx = ssl._create_unverified_context()
>>> xen = xmlrpc.client.ServerProxy("https://localhost:443", context=ctx)
```

Acquire a session reference by logging in with a username and password; the
Expand Down Expand Up @@ -555,27 +564,38 @@ To retrieve all the VM records in a single call:

### Using the JSON-RPC Protocol

For this example we are making use of the package `python-jsonrpc` due to its
simplicity, although other packages can also be used.
For this example we are making use of the package `jsonrpcclient` and the
`requests` library due to their simplicity, although other packages can also be
used.

First, import the library `pyjsonrpc` and create the object referencing the
remote server as follows:
First, import the `requests` and `jsonrpcclient` libraries:

```python
>>> import pyjsonrpc
>>> client = pyjsonrpc.HttpClient(url = "https://localhost/jsonrpc:443")
>>> import requests
>>> import jsonrpcclient
```

Acquire a session reference by logging in with a username and password; the
library `pyjsonrpc` returns the response's `result` member, which is the session
reference:
Now we construct a utility method to make using these libraries easier:

```python
>>> def jsonrpccall(method, params):
... r = requests.post("https://localhost:443/jsonrpc",
... json=jsonrpcclient.request(method, params=params),
... verify=False)
... p = jsonrpcclient.parse(r.json())
... if isinstance(p, jsonrpcclient.Ok):
... return p.result
... raise Exception(p.message, p.data)
```

Acquire a session reference by logging in with a username and password:

```python
>>> session = client.call("session.login_with_password",
... "user", "passwd", "version", "originator")
>>> session = jsonrpccall("session.login_with_password",
... ("user", "password", "version", "originator"))
```

`pyjsonrpc` uses the JSON-RPC protocol v2.0, so this is what the serialized
`jsonrpcclient` uses the JSON-RPC protocol v2.0, so this is what the serialized
request looks like:

```json
Expand All @@ -591,7 +611,7 @@ Next, the user may acquire a list of all the VMs known to the system (note the
call takes the session reference as the only parameter):

```python
>>> all_vms = client.call("VM.get_all", session)
>>> all_vms = jsonrpccall("VM.get_all", (session,))
>>> all_vms
['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ]
```
Expand All @@ -603,22 +623,19 @@ find the subset of template VMs using a command like the following:

```python
>>> all_templates = filter(
... lambda x: client.call("VM.get_is_a_template", session, x),
all_vms)
... lambda x: jsonrpccall("VM.get_is_a_template", (session, x)),
... all_vms)
```

Once a reference to a VM has been acquired, a lifecycle operation may be invoked:

```python
>>> from pyjsonrpc import JsonRpcError
>>> try:
... client.call("VM.start", session, all_templates[0], False, False)
... except JsonRpcError as e:
... e.message
... e.data
... jsonrpccall("VM.start", (session, next(all_templates), False, False))
... except Exception as e:
... e
...
'VM_IS_TEMPLATE'
[ 'OpaqueRef:1', 'start' ]
Exception('VM_IS_TEMPLATE', ['OpaqueRef:1', 'start'])
```

In this case the `start` message has been rejected because the VM is
Expand All @@ -629,7 +646,7 @@ Rather than querying fields individually, whole _records_ may be returned at onc
To retrieve the record of a single object as a python dictionary:

```python
>>> record = client.call("VM.get_record", session, all_templates[0])
>>> record = jsonrpccall("VM.get_record", (session, next(all_templates)))
>>> record['power_state']
'Halted'
>>> record['name_label']
Expand All @@ -639,7 +656,7 @@ To retrieve the record of a single object as a python dictionary:
To retrieve all the VM records in a single call:

```python
>>> records = client.call("VM.get_all_records", session)
>>> records = jsonrpccall("VM.get_all_records", (session,))
>>> records.keys()
['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ]
>>> records['OpaqueRef:1']['name_label']
Expand Down

0 comments on commit 9507369

Please sign in to comment.