Skip to content

Commit

Permalink
Update wire-protocol.md to have working Python3 code examples (#6058)
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.
  • Loading branch information
lindig authored Oct 16, 2024
2 parents e650ca0 + 9507369 commit 1683f8f
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 1683f8f

Please sign in to comment.