[libvirt] [PATCHv7 3/4] domifaddr: Implement the API for qemu

Daniel P. Berrange berrange at redhat.com
Tue Jan 13 15:01:28 UTC 2015


On Mon, Jan 05, 2015 at 10:54:35PM +0530, Nehal J Wani wrote:
> By querying the qemu guest agent with the QMP command
> "guest-network-get-interfaces" and converting the received JSON
> output to structured objects.
> 
> Although "ifconfig" is deprecated, IP aliases created by "ifconfig"
> are supported by this API. The legacy syntax of an IP alias is:
> "<ifname>:<alias-name>". Since we want all aliases to be clubbed
> under parent interface, simply stripping ":<alias-name>" suffices.
> Note that IP aliases formed by "ip" aren't visible to "ifconfig",
> and aliases created by "ip" do not have any specific name. But
> we are lucky, as qemu guest agent detects aliases created by both.
> 
> src/qemu/qemu_agent.h:
>   * Define qemuAgentGetInterfaces
> 
> src/qemu/qemu_agent.c:
>   * Implement qemuAgentGetInterface
> 
> src/qemu/qemu_driver.c:
>   * New function qemuGetDHCPInterfaces
>   * New function qemuDomainInterfaceAddresses
> 
> src/remote_protocol-sructs:
>   * Define new structs
> 
> tests/qemuagenttest.c:
>   * Add new test: testQemuAgentGetInterfaces
>     Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)
> 
> Signed-off-by: Nehal J Wani <nehaljw.kkd1 at gmail.com>
> ---
>  These are very minor changes, and rest of the patches in the series haven't
>  been reviewed yet. Hence sending fix in the same version. :)
>  src/qemu/qemu_agent.c  | 202 +++++++++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_agent.h  |   4 +
>  src/qemu/qemu_driver.c | 159 ++++++++++++++++++++++++++++++++++++++
>  tests/qemuagenttest.c  | 188 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 553 insertions(+)

> +static int
> +qemuDomainInterfaceAddresses(virDomainPtr dom,
> +                             virDomainInterfacePtr **ifaces,
> +                             unsigned int flags)
> +{
> +    virQEMUDriverPtr driver = dom->conn->privateData;
> +    qemuDomainObjPrivatePtr priv = NULL;
> +    virDomainObjPtr vm = NULL;
> +    int ret = -1;
> +
> +    /* We won't allow agent interaction in default behavior */
> +    if (flags == 0)
> +        flags = VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE;
> +
> +    virCheckFlags(VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE |
> +                  VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT, -1);

[snip]

> +    if (flags & VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE) {
> +        ret = qemuGetDHCPInterfaces(dom, vm, ifaces);
> +        if (ret > 0)
> +            goto cleanup;
> +    }
> +
> +    if (flags & VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT) {

On second thoughts, I'm not convinced this logic is the right
approach.  With this, if you don't specify any flags, no code
runs at all. Also, if qemuGetDHCPInterfaces raises a fatal
error we loose the error report & run the agent code instead
which kind of sucks.

I think we want todo something like

  bool tryLeases;
  bool tryAgent;

  if (flags) {
    tryLease =  (flags & VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE);
    tryAgent = (flags & VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT);
  } else {
    tryLease == ...if guest has any NICs on libvirt virtual network...
    tryAgent = priv->agent != NULL;
  }


  if (tryLease) {
      return qemuGetDHCPInterfaces(...);
  }
  if (tryAgent) {
      ...agent code...
  }

  virReportError("No IP address data source found");


> +        if (priv->agentError) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("QEMU guest agent is not "
> +                             "available due to an error"));
> +            goto cleanup;
> +        }
> +
> +        if (!priv->agent) {
> +            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> +                           _("QEMU guest agent is not configured"));
> +            goto cleanup;
> +        }
> +
> +        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
> +            goto cleanup;
> +
> +        qemuDomainObjEnterAgent(vm);
> +        ret = qemuAgentGetInterfaces(priv->agent, ifaces);
> +        qemuDomainObjExitAgent(vm);
> +
> +        qemuDomainObjEndJob(driver, vm);
> +    }
> +
> + cleanup:
> +    if (vm)
> +        virObjectUnlock(vm);
> +    return ret;
> +}
> +
> +static int
> +qemuGetDHCPInterfaces(virDomainPtr dom,
> +                      virDomainObjPtr vm,
> +                      virDomainInterfacePtr **ifaces)
> +{
> +    int rv = -1;
> +    int n_leases = 0;
> +    size_t i, j;
> +    size_t ifaces_count = 0;
> +    virNetworkPtr network;
> +    char macaddr[VIR_MAC_STRING_BUFLEN];
> +    virDomainInterfacePtr iface = NULL;
> +    virNetworkDHCPLeasePtr *leases = NULL;
> +    virDomainInterfacePtr *ifaces_ret = NULL;
> +
> +    if (dom->conn->networkDriver &&
> +        dom->conn->networkDriver->networkGetDHCPLeases) {
> +
> +        for (i = 0; i < vm->def->nnets; i++) {
> +            virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
> +            network = virNetworkLookupByName(dom->conn,
> +                                             vm->def->nets[i]->data.network.name);

You need to check  nets[i]->type == VIR_DOMAIN_NET_NETWORK before
calling this.


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list