[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