Open simondeziel opened 3 weeks ago
Related issues #579 and #581.
Here's a toy PoC:
#!/usr/bin/python3
"""Basic interaction with the LXD API over the Unix socket."""
# Python implementation of:
# $ curl -s --unix /var/snap/lxd/common/lxd/unix.socket http://unix.socket/1.0 | jq -r '.metadata.environment'
#{
# "addresses": [],
# "architectures": [
# "x86_64",
# "i686"
# ],
#...
#}
# Heavily inspired from snapd's api-client.py:
# https://github.com/snapcore/snapd/blob/master/tests/main/theme-install/api-client/bin/api-client.py
import http.client
import json
import socket
import sys
# This class is a subclass of http.client.HTTPConnection that connects to a Unix socket instead of a TCP socket.
class UnixSocketHTTPConnection(http.client.HTTPConnection):
def __init__(self, socket_path):
super().__init__("pylxd")
self._socket_path = socket_path
def connect(self):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(self._socket_path)
self.sock = s
# This function connects to the Unix socket and requests the environment part of the metadata returned by LXD.
# Returns the environment content of the metadata, or an empty string if an error occurs.
def main():
# Try to connect to the Unix socket and request the environment part of the metadata returned by LXD.
# If an exception occurs, print an error message and return an empty string.
try:
conn = UnixSocketHTTPConnection("/var/snap/lxd/common/lxd/unix.socket")
conn.request("GET", "/1.0")
response = conn.getresponse()
body = response.read().decode()
except FileNotFoundError:
print("missing socket", file=sys.stderr)
return ""
except http.client.HTTPException as e:
print("HTTP exception:", e, file=sys.stderr)
return ""
finally:
conn.close()
# If the response status is not 200, print an error message and return an empty string.
if response.status != 200:
print("HTTP error:", response.status, file=sys.stderr)
return ""
# If the response body is missing or empty, print an error message and return an empty string.
if not body:
print("Missing/empty body", file=sys.stderr)
return ""
# Try to parse the response body as JSON, and extract the environment part of the metadata returned by LXD.
try:
data = json.loads(body)
except json.JSONDecodeError as e:
print("JSON decode exception:", e, file=sys.stderr)
return ""
if "metadata" in data:
return data["metadata"].get("environment", "")
return ""
if __name__ == "__main__":
print(main())
The
requests_unixsocket
is abandoned and we have very little hope that https://github.com/msabramo/requests-unixsocket/pull/72 will ever be merged.cloud-init
folks have found a way to talk to/dev/lxd/sock
usingrequests
(without usingrequests_unixsocket
) to implement the LXD datasource. This could be taken as a source of inspiration for our replacement implementation.