|
|
d0ea73 |
From db7e06935bfd20e02110549371a5174e68a45cf0 Mon Sep 17 00:00:00 2001
|
|
|
d0ea73 |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
d0ea73 |
Date: Mon, 18 Jun 2018 15:34:37 +0100
|
|
|
d0ea73 |
Subject: [PATCH] v2v: -o rhv-upload: Use Unix domain socket to access imageio
|
|
|
d0ea73 |
(RHBZ#1588088).
|
|
|
d0ea73 |
|
|
|
d0ea73 |
In the case where virt-v2v runs on the same server as the imageio
|
|
|
d0ea73 |
daemon that we are talking to, it may be possible to optimize access
|
|
|
d0ea73 |
using a Unix domain socket.
|
|
|
d0ea73 |
|
|
|
d0ea73 |
This is only an optimization. If it fails or if we're not running on
|
|
|
d0ea73 |
the same server it will fall back to the usual HTTPS over TCP
|
|
|
d0ea73 |
connection.
|
|
|
d0ea73 |
|
|
|
d0ea73 |
Thanks: Nir Soffer, Daniel Erez.
|
|
|
d0ea73 |
(cherry picked from commit b7a2e6270d53200d2df471c36a1fb2b46db8bbac)
|
|
|
d0ea73 |
---
|
|
|
d0ea73 |
v2v/rhv-upload-plugin.py | 61 ++++++++++++++++++++++++++++++++++++++--
|
|
|
d0ea73 |
1 file changed, 58 insertions(+), 3 deletions(-)
|
|
|
d0ea73 |
|
|
|
d0ea73 |
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
index f215eaecf..8805e3552 100644
|
|
|
d0ea73 |
--- a/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
+++ b/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
@@ -19,11 +19,12 @@
|
|
|
d0ea73 |
import builtins
|
|
|
d0ea73 |
import json
|
|
|
d0ea73 |
import logging
|
|
|
d0ea73 |
+import socket
|
|
|
d0ea73 |
import ssl
|
|
|
d0ea73 |
import sys
|
|
|
d0ea73 |
import time
|
|
|
d0ea73 |
|
|
|
d0ea73 |
-from http.client import HTTPSConnection
|
|
|
d0ea73 |
+from http.client import HTTPSConnection, HTTPConnection
|
|
|
d0ea73 |
from urllib.parse import urlparse
|
|
|
d0ea73 |
|
|
|
d0ea73 |
import ovirtsdk4 as sdk
|
|
|
d0ea73 |
@@ -56,6 +57,28 @@ def debug(s):
|
|
|
d0ea73 |
print(s, file=sys.stderr)
|
|
|
d0ea73 |
sys.stderr.flush()
|
|
|
d0ea73 |
|
|
|
d0ea73 |
+def find_host(connection):
|
|
|
d0ea73 |
+ """Return the current host object or None."""
|
|
|
d0ea73 |
+ try:
|
|
|
d0ea73 |
+ with builtins.open("/etc/vdsm/vdsm.id") as f:
|
|
|
d0ea73 |
+ vdsm_id = f.readline().strip()
|
|
|
d0ea73 |
+ except Exception as e:
|
|
|
d0ea73 |
+ return None
|
|
|
d0ea73 |
+ debug("hw_id = %r" % vdsm_id)
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ hosts_service = connection.system_service().hosts_service()
|
|
|
d0ea73 |
+ hosts = hosts_service.list(
|
|
|
d0ea73 |
+ search="hw_id=%s" % vdsm_id,
|
|
|
d0ea73 |
+ case_sensitive=False,
|
|
|
d0ea73 |
+ )
|
|
|
d0ea73 |
+ if len(hosts) == 0:
|
|
|
d0ea73 |
+ return None
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ host = hosts[0]
|
|
|
d0ea73 |
+ debug("host.id = %r" % host.id)
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ return types.Host(id = host.id)
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
def open(readonly):
|
|
|
d0ea73 |
# Parse out the username from the output_conn URL.
|
|
|
d0ea73 |
parsed = urlparse(params['output_conn'])
|
|
|
d0ea73 |
@@ -121,9 +144,11 @@ def open(readonly):
|
|
|
d0ea73 |
transfers_service = system_service.image_transfers_service()
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Create a new image transfer.
|
|
|
d0ea73 |
+ host = find_host(connection)
|
|
|
d0ea73 |
transfer = transfers_service.add(
|
|
|
d0ea73 |
types.ImageTransfer(
|
|
|
d0ea73 |
disk = types.Disk(id = disk.id),
|
|
|
d0ea73 |
+ host = host,
|
|
|
d0ea73 |
inactivity_timeout = 3600,
|
|
|
d0ea73 |
)
|
|
|
d0ea73 |
)
|
|
|
d0ea73 |
@@ -170,6 +195,7 @@ def open(readonly):
|
|
|
d0ea73 |
can_flush = False
|
|
|
d0ea73 |
can_trim = False
|
|
|
d0ea73 |
can_zero = False
|
|
|
d0ea73 |
+ unix_socket = None
|
|
|
d0ea73 |
|
|
|
d0ea73 |
http.putrequest("OPTIONS", destination_url.path)
|
|
|
d0ea73 |
http.putheader("Authorization", transfer.signed_ticket)
|
|
|
d0ea73 |
@@ -186,6 +212,7 @@ def open(readonly):
|
|
|
d0ea73 |
can_flush = "flush" in j['features']
|
|
|
d0ea73 |
can_trim = "trim" in j['features']
|
|
|
d0ea73 |
can_zero = "zero" in j['features']
|
|
|
d0ea73 |
+ unix_socket = j.get('unix_socket')
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Old imageio servers returned either 405 Method Not Allowed or
|
|
|
d0ea73 |
# 204 No Content (with an empty body). If we see that we leave
|
|
|
d0ea73 |
@@ -197,8 +224,17 @@ def open(readonly):
|
|
|
d0ea73 |
raise RuntimeError("could not use OPTIONS request: %d: %s" %
|
|
|
d0ea73 |
(r.status, r.reason))
|
|
|
d0ea73 |
|
|
|
d0ea73 |
- debug("imageio features: flush=%r trim=%r zero=%r" %
|
|
|
d0ea73 |
- (can_flush, can_trim, can_zero))
|
|
|
d0ea73 |
+ debug("imageio features: flush=%r trim=%r zero=%r unix_socket=%r" %
|
|
|
d0ea73 |
+ (can_flush, can_trim, can_zero, unix_socket))
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ # If we are connected to imageio on the local host and the
|
|
|
d0ea73 |
+ # transfer features a unix_socket then we can reconnect to that.
|
|
|
d0ea73 |
+ if host is not None and unix_socket is not None:
|
|
|
d0ea73 |
+ try:
|
|
|
d0ea73 |
+ http = UnixHTTPConnection(unix_socket)
|
|
|
d0ea73 |
+ debug("optimizing connection using unix socket %r" % unix_socket)
|
|
|
d0ea73 |
+ except:
|
|
|
d0ea73 |
+ pass
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Save everything we need to make requests in the handle.
|
|
|
d0ea73 |
return {
|
|
|
d0ea73 |
@@ -463,3 +499,22 @@ def close(h):
|
|
|
d0ea73 |
raise
|
|
|
d0ea73 |
|
|
|
d0ea73 |
connection.close()
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+# Modify http.client.HTTPConnection to work over a Unix domain socket.
|
|
|
d0ea73 |
+# Derived from uhttplib written by Erik van Zijst under an MIT license.
|
|
|
d0ea73 |
+# (https://pypi.org/project/uhttplib/)
|
|
|
d0ea73 |
+# Ported to Python 3 by Irit Goihman.
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+class UnsupportedError(Exception):
|
|
|
d0ea73 |
+ pass
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+class UnixHTTPConnection(HTTPConnection):
|
|
|
d0ea73 |
+ def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
|
|
|
d0ea73 |
+ self.path = path
|
|
|
d0ea73 |
+ HTTPConnection.__init__(self, "localhost", timeout=timeout)
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ def connect(self):
|
|
|
d0ea73 |
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
|
d0ea73 |
+ if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
|
|
|
d0ea73 |
+ self.sock.settimeout(timeout)
|
|
|
d0ea73 |
+ self.sock.connect(self.path)
|
|
|
d0ea73 |
--
|
|
|
6b9fda |
2.21.0
|
|
|
d0ea73 |
|