[libvirt] [PATCH v2 2/4] libxl: channels support

Joao Martins joao.m.martins at oracle.com
Sun Sep 25 18:55:26 UTC 2016


On 09/24/2016 12:15 AM, Joao Martins wrote:
> On September 23, 2016 11:12:00 PM GMT+01:00, Jim Fehlig <jfehlig at suse.com> wrote:
>> On 09/22/2016 01:53 PM, Joao Martins wrote:
>>> Allow libxl to handle channel element which creates a Xen
>>> console visible to the guest as a low-bandwitdh communication
>>> channel. If type is PTY we also fetch the tty after boot using
>>> libxl_channel_getinfo to fetch the tty path. On socket case,
>>> we autogenerate a path if not specified in the XML. Path
>> autogenerated
>>> is slightly different from qemu driver: qemu stores also on
>>> "channels/target" but it creates then a directory per domain with
>>> each channel target name. libxl doesn't appear to have a clear
>>> definition of private files associated with each domain, so for
>>> simplicity we do it slightly different. On qemu each autogenerated
>>> channel goes like:
>>>
>>> channels/target/<domain-name>/<target name>
>>>
>>> Whereas for libxl:
>>>
>>> channels/target/<domain-name>-<target name>
>>>
>>> Should note that if path is not specified it won't persist,
>>> existing only on live XML, unless user had initially specified it.
>>> Since support for libxl channels only came on Xen >= 4.5 we therefore
>>> need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
>>>
>>> After this patch and having a qemu guest agent:
>>>  $ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
>>>  <channel type='unix'>
>>>    <source mode='bind' path='/tmp/channel'/>
>>>    <target type='xen' name='org.qemu.guest_agent.0'/>
>>>  </channel>
>>>
>>>  $ virsh create domain.xml
>>>  $ echo '{"execute":"guest-network-get-interfaces"}' | socat
>>>  stdio,ignoreeof  unix-connect:/tmp/channel
>>>
>>>  {"execute":"guest-network-get-interfaces"}
>>>  {"return": [{"name": "lo", "ip-addresses": [{"ip-address-type":
>> "ipv4",
>>>  "ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
>>>  "ip-address": "::1", "prefix": 128}], "hardware-address":
>>>  "00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
>>>  [{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix":
>> 24},
>>>  {"ip-address-type": "ipv6", "ip-address":
>> "fe80::216:3eff:fe40:88eb",
>>>  "prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
>>>  "sit0"}]}
>>>
>>> Signed-off-by: Joao Martins <joao.m.martins at oracle.com>
>>> ---
>>> Since v1:
>>> * Autogenerated paths, and updated commit message explaning it the
>> different
>>> naming. Despite per domain name being slightly different, parent
>>> directory is same across both drivers.
>>> * Remove the switch case from target type xen and rework the function
>> structure
>>> a bit.
>>> ---
>>>  src/libxl/libxl_conf.c   | 120
>> ++++++++++++++++++++++++++++++++++++++++++++++-
>>>  src/libxl/libxl_conf.h   |   4 +-
>>>  src/libxl/libxl_domain.c |  44 ++++++++++++++++-
>>>  src/libxl/libxl_driver.c |   7 +++
>>>  4 files changed, 171 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
>>> index 306e441..824f2d2 100644
>>> --- a/src/libxl/libxl_conf.c
>>> +++ b/src/libxl/libxl_conf.c
>>> @@ -88,6 +88,7 @@ libxlDriverConfigDispose(void *obj)
>>>      VIR_FREE(cfg->saveDir);
>>>      VIR_FREE(cfg->autoDumpDir);
>>>      VIR_FREE(cfg->lockManagerName);
>>> +    VIR_FREE(cfg->channelDir);
>>>      virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
>>>  }
>>>  
>>> @@ -1339,6 +1340,8 @@ libxlDriverConfigNew(void)
>>>          goto error;
>>>      if (VIR_STRDUP(cfg->autoDumpDir, LIBXL_DUMP_DIR) < 0)
>>>          goto error;
>>> +    if (VIR_STRDUP(cfg->channelDir, LIBXL_CHANNEL_DIR) < 0)
>>> +        goto error;
>>>  
>>>      if (virAsprintf(&log_file, "%s/libxl-driver.log", cfg->logDir) <
>> 0)
>>>          goto error;
>>> @@ -1490,6 +1493,114 @@ int
>> libxlDriverConfigLoadFile(libxlDriverConfigPtr cfg,
>>>  
>>>  }
>>>  
>>> +#ifdef LIBXL_HAVE_DEVICE_CHANNEL
>>> +static int
>>> +libxlPrepareChannel(virDomainChrDefPtr channel,
>>> +                    const char *channelDir,
>>> +                    const char *domainName)
>>> +{
>>> +    if (channel->targetType ==
>> VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN &&
>>> +        channel->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
>>> +        !channel->source.data.nix.path) {
>>> +        if (virAsprintf(&channel->source.data.nix.path,
>>> +                        "%s/%s-%s", channelDir, domainName,
>>> +                        channel->target.name ? channel->target.name
>>> +                        : "unknown.sock") < 0)
>>> +            return -1;
>>> +
>>> +        channel->source.data.nix.listen = true;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int
>>> +libxlMakeChannel(virDomainChrDefPtr l_channel,
>>> +                 libxl_device_channel *x_channel)
>>> +{
>>> +    int ret = -1;
>>
>> Similar to the other libxlMake* functions, ret could be dropped simply
>> return -1
>> when encountering failure.
> 
> Ok, will change that.
> 
>>> +
>>> +    libxl_device_channel_init(x_channel);
>>> +
>>> +    if (l_channel->targetType !=
>> VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN) {
>>> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
>>> +                       _("channel target type not supported"));
>>> +        return ret;
>>> +    }
>>> +
>>> +    switch (l_channel->source.type) {
>>> +    case VIR_DOMAIN_CHR_TYPE_PTY:
>>> +        x_channel->connection = LIBXL_CHANNEL_CONNECTION_PTY;
>>> +        break;
>>> +    case VIR_DOMAIN_CHR_TYPE_UNIX:
>>> +        x_channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
>>> +        if (VIR_STRDUP(x_channel->u.socket.path,
>>> +                       l_channel->source.data.nix.path) < 0)
>>> +            return ret;
>>> +        break;
>>> +    default:
>>> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
>>> +                       _("channel source type not supported"));
>>> +        break;
>>> +    }
>>> +
>>> +    if (!l_channel->target.name) {
>>> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
>>> +                       _("channel target name missing"));
>>> +        return ret;
>>> +    }
>>> +
>>> +    if (VIR_STRDUP(x_channel->name, l_channel->target.name) < 0)
>>> +        return ret;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int
>>> +libxlMakeChannelList(libxlDriverPrivatePtr driver,
>>> +                     virDomainDefPtr def,
>>> +                     libxl_domain_config *d_config)
>>> +{
>>> +    virDomainChrDefPtr *l_channels = def->channels;
>>> +    size_t nchannels = def->nchannels;
>>> +    libxl_device_channel *x_channels;
>>> +    libxlDriverConfigPtr cfg;
>>> +    size_t i, nvchannels = 0;
>>> +
>>> +    if (VIR_ALLOC_N(x_channels, nchannels) < 0)
>>> +        return -1;
>>> +
>>> +    cfg = libxlDriverConfigGet(driver);
>>> +
>>> +    for (i = 0; i < nchannels; i++) {
>>> +        if (l_channels[i]->deviceType !=
>> VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL)
>>> +            continue;
>>> +
>>> +        if (libxlPrepareChannel(l_channels[i], cfg->channelDir,
>> def->name) < 0)
>>> +            goto error;
>>> +
>>> +        if (libxlMakeChannel(l_channels[i], &x_channels[nvchannels])
>> < 0)
>>> +            goto error;
>>> +
>>> +        nvchannels++;
>>> +    }
>>> +
>>> +    VIR_SHRINK_N(x_channels, nchannels, nchannels - nvchannels);
>>> +    d_config->channels = x_channels;
>>> +    d_config->num_channels = nvchannels;
>>> +    virObjectUnref(cfg);
>>> +
>>> +    return 0;
>>> +
>>> + error:
>>> +    for (i = 0; i < nchannels; i++)
>>> +        libxl_device_channel_dispose(&x_channels[i]);
>>> +    VIR_FREE(x_channels);
>>> +    virObjectUnref(cfg);
>>> +    return -1;
>>> +}
>>> +#endif
>>> +
>>>  #ifdef LIBXL_HAVE_PVUSB
>>>  int
>>>  libxlMakeUSBController(virDomainControllerDefPtr controller,
>>> @@ -1828,11 +1939,13 @@ libxlDriverNodeGetInfo(libxlDriverPrivatePtr
>> driver, virNodeInfoPtr info)
>>>  }
>>>  
>>>  int
>>> -libxlBuildDomainConfig(virPortAllocatorPtr graphicsports,
>>> +libxlBuildDomainConfig(libxlDriverPrivatePtr driver,
>>>                         virDomainDefPtr def,
>>>                         libxl_ctx *ctx,
>>>                         libxl_domain_config *d_config)
>>>  {
>>> +    virPortAllocatorPtr graphicsports =
>> driver->reservedGraphicsPorts;
>>> +
>>
>> Spurious change?
> 
> This (and the other two below) was intended, as I needed
>  channelDir. and instead of having yet another argument, I
>  passed driver instead as graphics port was using it too.
> 
> But I could use the macro directly, or add another argument if you prefer.

Hmm, I can just avoid passing driver and have cfg->channelDir added as an
argument. I just noticed that I am unnecessarily doing libxlDriverConfigGet
twice and perhaps if a third argument is added in the future then probably
consider having driver be passed as an argument?

Joao




More information about the libvir-list mailing list