<!--
SPDX-FileCopyrightText: Red Hat, Inc.
SPDX-License-Identifier: GPL-2.0-or-later
-->

# UNIX socket support

## Use cases

- Importing VM disk using virt-v2v: improves transferring multiple disks
  concurrently using less resources.
- Backup vendors: improves backup/restore solution scalability.

## An example flow:

### 1. Select a running host from the data center

A user program selects a running host for image transfers using the API.
The transfers can be distributed over all hosts in a data center to
distribute the I/O.


### 2. Find the host uuid

Currently the host uuid used in engine side is not kept on the host, but
we can find it using the host hardware uuid at /etc/vdsm/vdsm.id.

    with 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_uuid=%s' % vdsm_id,
        case_sensitive=False,
    )


### 3. Start an image transfer using the found host uuid

After finding the host uuid we can start an image transfer on that
specific host.

    transfers_service = system_service.image_transfers_service()
    transfer = transfers_service.add(
        types.ImageTransfer(
            disk=types.Disk(id='123'),
            host=types.Host(id=hosts[0].id)
        )
    )


### 4. Find the unix socket address using OPTIONS on the transfer_url

The first request to the server should be OPTIONS /images/ticket-uuid
(to find the features supported by the server, e.g. "zero").
This will also expose the unix socket address.

    OPTIONS /images/ticket-uuid
    ..
    {
        "features": ["zero", "flush"],
        "unix_socket": "\0/org/ovirt/imageio"
    }

### 5. Transfer the data using the unix socket

The user program needs to use a modified httplib.HTTPConnection to
connect using socket address. Then it can use standard HTTPConnection
APIs to perform the transfers.

Here is an example of UnixHTTPConnection class:

    import socket
    import six
    from six.moves import http_client


    class UnixHTTPConnection(http_client.HTTPConnection):
        """
        HTTP connection over unix domain socket.
        """

        def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
            self.path = path
            extra = {}
            if six.PY2:
                extra['strict'] = True
            http_client.HTTPConnection.__init__(
                self, "localhost", timeout=timeout, **extra)

        def connect(self):
            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                self.sock.settimeout(self.timeout)
            self.sock.connect(self.path)

See upload example for more info:
https://github.com/oVirt/ovirt-engine-sdk/blob/master/sdk/examples/upload_disk.py
