[Libguestfs] [PATCH 2/2] v2v: -o rhv-upload: Use Unix domain socket to access imageio (RHBZ#1588088).
Tomáš Golembiovský
tgolembi at redhat.com
Thu Jun 21 21:26:38 UTC 2018
On Thu, 21 Jun 2018 13:35:26 +0100
"Richard W.M. Jones" <rjones at redhat.com> wrote:
> In the case where virt-v2v runs on the same server as the imageio
> daemon that we are talking to, it may be possible to optimize access
> using a Unix domain socket.
>
> This is only an optimization. If it fails or if we're not running on
> the same server it will fall back to the usual HTTPS over TCP
> connection.
> ---
> v2v/rhv-upload-plugin.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
> index 419008517..0c5eec7d3 100644
> --- a/v2v/rhv-upload-plugin.py
> +++ b/v2v/rhv-upload-plugin.py
> @@ -19,11 +19,12 @@
> import builtins
> import json
> import logging
> +import socket
> import ssl
> import sys
> import time
>
> -from http.client import HTTPSConnection
> +from http.client import HTTPSConnection, HTTPConnection
> from urllib.parse import urlparse
>
> import ovirtsdk4 as sdk
> @@ -117,6 +118,25 @@ def open(readonly):
> if time.time() > endt:
> raise RuntimeError("timed out waiting for disk to become unlocked")
>
> + # Get the current host. If it fails, don't worry.
> + host = None
> + try:
> + with builtin_open("/etc/vdsm/vdsm.id") as f:
> + vdsm_id = f.readline().strip()
> +
> + hosts_service = connection.system_service().hosts_service()
> + hosts = hosts_service.list(
> + search="hw_id=%s" % vdsm_id,
> + case_sensitive=False,
> + )
> + if len(hosts) > 0:
> + host = hosts[0]
> + debug("host.id = %r" % host.id)
> + else:
> + debug("could not retrieve host with hw_id=%s" % vdsm_id)
> + except:
> + pass
> +
> # Get a reference to the transfer service.
> transfers_service = system_service.image_transfers_service()
>
> @@ -124,6 +144,7 @@ def open(readonly):
> transfer = transfers_service.add(
> types.ImageTransfer(
> disk = types.Disk(id = disk.id),
> + host = types.Host(id = host.id) if host else None,
proper check is 'host is not None'
> inactivity_timeout = 3600,
> )
> )
> @@ -170,6 +191,7 @@ def open(readonly):
> can_flush = False
> can_trim = False
> can_zero = False
> + unix_socket = None
>
> http.putrequest("OPTIONS", destination_url.path)
> http.putheader("Authorization", transfer.signed_ticket)
> @@ -184,6 +206,7 @@ def open(readonly):
> can_flush = "flush" in j['features']
> can_trim = "trim" in j['features']
> can_zero = "zero" in j['features']
> + unix_socket = j.get('unix_socket')
>
> # Old imageio servers returned either 405 Method Not Allowed or
> # 204 No Content (with an empty body). If we see that we leave
> @@ -198,6 +221,15 @@ def open(readonly):
> debug("imageio features: flush=%r trim=%r zero=%r unix_socket=%r" %
> (can_flush, can_trim, can_zero, unix_socket))
>
> + # If we are connected to the local host and the host features
> + # a unix_socket then we can reconnect to that.
> + if host and unix_socket:
proper check is 'host is not None and unix_socket is not None'
> + try:
> + http = UnixHTTPConnection(unix_socket)
> + debug("optimizing connection using unix socket %r" % unix_socket)
> + except:
> + pass
> +
> # Save everything we need to make requests in the handle.
> return {
> 'can_flush': can_flush,
> @@ -451,3 +483,30 @@ def close(h):
> raise
>
> connection.close()
> +
> +# Modify http.client to work over a Unix domain socket.
> +# Derived from uhttplib written by Erik van Zijst under an MIT license.
> +# (https://pypi.org/project/uhttplib/)
> +# Ported to Python 3 by Irit Goihman.
> +
> +class UnsupportedError(Exception):
> + pass
> +
> +class _UnixMixin(object):
> + def set_tunnel(self, host, port=None, headers=None):
> + raise UnsupportedError("tunneling is not supported")
> +
> +class UnixHTTPConnection(_UnixMixin, HTTPConnection):
> + def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
> + self.path = path
> + HTTPConnection.__init__(self, "localhost", timeout=timeout)
> +
> + def connect(self):
> + self.sock = _create_unix_socket(self.timeout)
> + self.sock.connect(self.path)
> +
> +def _create_unix_socket(timeout):
> + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
> + if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
> + sock.settimeout(timeout)
> + return sock
> --
> 2.16.2
>
--
Tomáš Golembiovský <tgolembi at redhat.com>
More information about the Libguestfs
mailing list