On Thu, 21 Jun 2018 13:35:26 +0100 "Richard W.M. Jones" <rjones@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@redhat.com>