[PATCH 0/2] lxc: Implement lxcDomainInterfaceAddresses() function

It is not able to retrieve IP addresses from LXC domains. This method was not implemented before. LXC uses the same operations to retrieve this information, but QEMU has their own functions to process this data. This series turn them into global functions, moving them into domain conf methods, to make them available for other drivers. The only source that LXC does not support is agent which is a specific source from QEMU. Julio Faracco (2): qemu: Converting DHCP and ARP functions to domain conf lxc: Add support to lxcDomainInterfaceAddresses() function src/conf/domain_conf.c | 134 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 + src/lxc/lxc_driver.c | 44 +++++++++++++ src/qemu/qemu_driver.c | 137 +-------------------------------------- 5 files changed, 184 insertions(+), 135 deletions(-) -- 2.20.1

QEMU driver has two functions: qemuGetDHCPInterfaces() and qemuARPGetInterfaces() that are being used inside only one single function. They can be turned into generic functions that other drivers can use. This commit move both from QEMU driver tree to domain conf tree. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/conf/domain_conf.c | 134 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 137 +-------------------------------------- 4 files changed, 140 insertions(+), 135 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f920d1dc39..707d58e1a4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -57,6 +57,7 @@ #include "virnetdev.h" #include "virnetdevtap.h" #include "virnetdevmacvlan.h" +#include "virarptable.h" #include "virhostdev.h" #include "virmdev.h" #include "virdomainsnapshotobjlist.h" @@ -17267,6 +17268,139 @@ virDomainNetUpdate(virDomainDefPtr def, } +int +virDomainNetDHCPInterfaces(virDomainDefPtr def, + virDomainInterfacePtr **ifaces) +{ + g_autoptr(virConnect) conn = NULL; + virDomainInterfacePtr *ifaces_ret = NULL; + size_t ifaces_count = 0; + size_t i; + + if (!(conn = virGetConnectNetwork())) + return -1; + + for (i = 0; i < def->nnets; i++) { + g_autoptr(virNetwork) network = NULL; + char macaddr[VIR_MAC_STRING_BUFLEN]; + virNetworkDHCPLeasePtr *leases = NULL; + int n_leases = 0; + virDomainInterfacePtr iface = NULL; + size_t j; + + if (def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK) + continue; + + virMacAddrFormat(&(def->nets[i]->mac), macaddr); + + network = virNetworkLookupByName(conn, + def->nets[i]->data.network.name); + if (!network) + goto error; + + if ((n_leases = virNetworkGetDHCPLeases(network, macaddr, + &leases, 0)) < 0) + goto error; + + if (n_leases) { + ifaces_ret = g_renew(typeof(*ifaces_ret), ifaces_ret, ifaces_count + 1); + ifaces_ret[ifaces_count] = g_new0(typeof(**ifaces_ret), 1); + iface = ifaces_ret[ifaces_count]; + ifaces_count++; + + /* Assuming each lease corresponds to a separate IP */ + iface->naddrs = n_leases; + iface->addrs = g_new0(typeof(*iface->addrs), iface->naddrs); + iface->name = g_strdup(def->nets[i]->ifname); + iface->hwaddr = g_strdup(macaddr); + } + + for (j = 0; j < n_leases; j++) { + virNetworkDHCPLeasePtr lease = leases[j]; + virDomainIPAddressPtr ip_addr = &iface->addrs[j]; + + ip_addr->addr = g_strdup(lease->ipaddr); + ip_addr->type = lease->type; + ip_addr->prefix = lease->prefix; + + virNetworkDHCPLeaseFree(lease); + } + + VIR_FREE(leases); + } + + *ifaces = g_steal_pointer(&ifaces_ret); + return ifaces_count; + + error: + if (ifaces_ret) { + for (i = 0; i < ifaces_count; i++) + virDomainInterfaceFree(ifaces_ret[i]); + } + VIR_FREE(ifaces_ret); + + return -1; +} + + +int +virDomainNetARPInterfaces(virDomainDefPtr def, + virDomainInterfacePtr **ifaces) +{ + size_t i, j; + size_t ifaces_count = 0; + int ret = -1; + char macaddr[VIR_MAC_STRING_BUFLEN]; + virDomainInterfacePtr *ifaces_ret = NULL; + virDomainInterfacePtr iface = NULL; + virArpTablePtr table; + + table = virArpTableGet(); + if (!table) + goto cleanup; + + for (i = 0; i < def->nnets; i++) { + virMacAddrFormat(&(def->nets[i]->mac), macaddr); + for (j = 0; j < table->n; j++) { + virArpTableEntry entry = table->t[j]; + + if (STREQ(entry.mac, macaddr)) { + if (VIR_ALLOC(iface) < 0) + goto cleanup; + + iface->name = g_strdup(def->nets[i]->ifname); + + iface->hwaddr = g_strdup(macaddr); + + if (VIR_ALLOC(iface->addrs) < 0) + goto cleanup; + iface->naddrs = 1; + + iface->addrs->addr = g_strdup(entry.ipaddr); + + if (VIR_APPEND_ELEMENT(ifaces_ret, ifaces_count, iface) < 0) + goto cleanup; + } + } + } + + *ifaces = g_steal_pointer(&ifaces_ret); + ret = ifaces_count; + + cleanup: + virArpTableFree(table); + virDomainInterfaceFree(iface); + + if (ifaces_ret) { + for (i = 0; i < ifaces_count; i++) + virDomainInterfaceFree(ifaces_ret[i]); + } + VIR_FREE(ifaces_ret); + + return ret; +} + + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ae89fa498..9ae8411f6c 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3186,6 +3186,8 @@ virDomainNetDefPtr virDomainNetFindByName(virDomainDefPtr def, const char *ifnam bool virDomainHasNet(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetUpdate(virDomainDefPtr def, size_t netidx, virDomainNetDefPtr newnet); +int virDomainNetDHCPInterfaces(virDomainDefPtr def, virDomainInterfacePtr **ifaces); +int virDomainNetARPInterfaces(virDomainDefPtr def, virDomainInterfacePtr **ifaces); virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i); void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b63feb4054..3cfeebb220 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -524,6 +524,8 @@ virDomainNetTypeFromString; virDomainNetTypeSharesHostView; virDomainNetTypeToString; virDomainNetUpdate; +virDomainNetDHCPInterfaces; +virDomainNetARPInterfaces; virDomainNostateReasonTypeFromString; virDomainNostateReasonTypeToString; virDomainObjAssignDef; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2f66d7cd9a..0a1dc414ae 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -22040,139 +22040,6 @@ qemuDomainGetFSInfo(virDomainPtr dom, } -static int -qemuGetDHCPInterfaces(virDomainObjPtr vm, - virDomainInterfacePtr **ifaces) -{ - g_autoptr(virConnect) conn = NULL; - virDomainInterfacePtr *ifaces_ret = NULL; - size_t ifaces_count = 0; - size_t i; - - if (!(conn = virGetConnectNetwork())) - return -1; - - for (i = 0; i < vm->def->nnets; i++) { - g_autoptr(virNetwork) network = NULL; - char macaddr[VIR_MAC_STRING_BUFLEN]; - virNetworkDHCPLeasePtr *leases = NULL; - int n_leases = 0; - virDomainInterfacePtr iface = NULL; - size_t j; - - if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK) - continue; - - virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr); - - network = virNetworkLookupByName(conn, - vm->def->nets[i]->data.network.name); - if (!network) - goto error; - - if ((n_leases = virNetworkGetDHCPLeases(network, macaddr, - &leases, 0)) < 0) - goto error; - - if (n_leases) { - ifaces_ret = g_renew(typeof(*ifaces_ret), ifaces_ret, ifaces_count + 1); - ifaces_ret[ifaces_count] = g_new0(typeof(**ifaces_ret), 1); - iface = ifaces_ret[ifaces_count]; - ifaces_count++; - - /* Assuming each lease corresponds to a separate IP */ - iface->naddrs = n_leases; - iface->addrs = g_new0(typeof(*iface->addrs), iface->naddrs); - iface->name = g_strdup(vm->def->nets[i]->ifname); - iface->hwaddr = g_strdup(macaddr); - } - - for (j = 0; j < n_leases; j++) { - virNetworkDHCPLeasePtr lease = leases[j]; - virDomainIPAddressPtr ip_addr = &iface->addrs[j]; - - ip_addr->addr = g_strdup(lease->ipaddr); - ip_addr->type = lease->type; - ip_addr->prefix = lease->prefix; - - virNetworkDHCPLeaseFree(lease); - } - - VIR_FREE(leases); - } - - *ifaces = g_steal_pointer(&ifaces_ret); - return ifaces_count; - - error: - if (ifaces_ret) { - for (i = 0; i < ifaces_count; i++) - virDomainInterfaceFree(ifaces_ret[i]); - } - VIR_FREE(ifaces_ret); - - return -1; -} - - -static int -qemuARPGetInterfaces(virDomainObjPtr vm, - virDomainInterfacePtr **ifaces) -{ - size_t i, j; - size_t ifaces_count = 0; - int ret = -1; - char macaddr[VIR_MAC_STRING_BUFLEN]; - virDomainInterfacePtr *ifaces_ret = NULL; - virDomainInterfacePtr iface = NULL; - virArpTablePtr table; - - table = virArpTableGet(); - if (!table) - goto cleanup; - - for (i = 0; i < vm->def->nnets; i++) { - virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr); - for (j = 0; j < table->n; j++) { - virArpTableEntry entry = table->t[j]; - - if (STREQ(entry.mac, macaddr)) { - if (VIR_ALLOC(iface) < 0) - goto cleanup; - - iface->name = g_strdup(vm->def->nets[i]->ifname); - - iface->hwaddr = g_strdup(macaddr); - - if (VIR_ALLOC(iface->addrs) < 0) - goto cleanup; - iface->naddrs = 1; - - iface->addrs->addr = g_strdup(entry.ipaddr); - - if (VIR_APPEND_ELEMENT(ifaces_ret, ifaces_count, iface) < 0) - goto cleanup; - } - } - } - - *ifaces = g_steal_pointer(&ifaces_ret); - ret = ifaces_count; - - cleanup: - virArpTableFree(table); - virDomainInterfaceFree(iface); - - if (ifaces_ret) { - for (i = 0; i < ifaces_count; i++) - virDomainInterfaceFree(ifaces_ret[i]); - } - VIR_FREE(ifaces_ret); - - return ret; -} - - static int qemuDomainInterfaceAddresses(virDomainPtr dom, virDomainInterfacePtr **ifaces, @@ -22197,7 +22064,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom, switch (source) { case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE: - ret = qemuGetDHCPInterfaces(vm, ifaces); + ret = virDomainNetDHCPInterfaces(vm->def, ifaces); break; case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT: @@ -22217,7 +22084,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom, break; case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP: - ret = qemuARPGetInterfaces(vm, ifaces); + ret = virDomainNetARPInterfaces(vm->def, ifaces); break; default: -- 2.20.1

On 1/21/20 4:37 AM, Julio Faracco wrote:
QEMU driver has two functions: qemuGetDHCPInterfaces() and qemuARPGetInterfaces() that are being used inside only one single function. They can be turned into generic functions that other drivers can use. This commit move both from QEMU driver tree to domain conf tree.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/conf/domain_conf.c | 134 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 137 +-------------------------------------- 4 files changed, 140 insertions(+), 135 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b63feb4054..3cfeebb220 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -524,6 +524,8 @@ virDomainNetTypeFromString; virDomainNetTypeSharesHostView; virDomainNetTypeToString; virDomainNetUpdate; +virDomainNetDHCPInterfaces; +virDomainNetARPInterfaces;
Not ordered properly. 'make syntax-check' would have caught this.
virDomainNostateReasonTypeFromString; virDomainNostateReasonTypeToString; virDomainObjAssignDef;
Michal

LXC driver is not able to retrieve IP addresses from domains. This function was not implemented yet. It can be done using DHCP lease and ARP table. Different from QEMU, LXC does not have an agent to fetch this info, but other sources can be used. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index bf1f8f8190..62bf2f8e85 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1740,6 +1740,49 @@ static int lxcConnectGetVersion(virConnectPtr conn, unsigned long *version) } +static int +lxcDomainInterfaceAddresses(virDomainPtr dom, + virDomainInterfacePtr **ifaces, + unsigned int source, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT, -1); + + if (!(vm = lxcDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto cleanup; + + switch (source) { + case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE: + ret = virDomainNetDHCPInterfaces(vm->def, ifaces); + break; + + case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP: + ret = virDomainNetARPInterfaces(vm->def, ifaces); + break; + + default: + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, + _("Unknown IP address data source %d"), + source); + break; + } + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + + static char *lxcConnectGetHostname(virConnectPtr conn) { if (virConnectGetHostnameEnsureACL(conn) < 0) @@ -5515,6 +5558,7 @@ static virHypervisorDriver lxcHypervisorDriver = { .domainGetMetadata = lxcDomainGetMetadata, /* 1.1.3 */ .domainGetCPUStats = lxcDomainGetCPUStats, /* 1.2.2 */ .domainGetHostname = lxcDomainGetHostname, /* 6.0.0 */ + .domainInterfaceAddresses = lxcDomainInterfaceAddresses, /* 6.1.0 */ .nodeGetMemoryParameters = lxcNodeGetMemoryParameters, /* 0.10.2 */ .nodeSetMemoryParameters = lxcNodeSetMemoryParameters, /* 0.10.2 */ .domainSendProcessSignal = lxcDomainSendProcessSignal, /* 1.0.1 */ -- 2.20.1

On 1/21/20 4:37 AM, Julio Faracco wrote:
LXC driver is not able to retrieve IP addresses from domains. This function was not implemented yet. It can be done using DHCP lease and ARP table. Different from QEMU, LXC does not have an agent to fetch this info, but other sources can be used.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index bf1f8f8190..62bf2f8e85 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1740,6 +1740,49 @@ static int lxcConnectGetVersion(virConnectPtr conn, unsigned long *version) }
+static int +lxcDomainInterfaceAddresses(virDomainPtr dom, + virDomainInterfacePtr **ifaces, + unsigned int source, + unsigned int flags) +{ + virDomainObjPtr vm = NULL; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT, -1);
Ooops, this is not a flag rather than a source value. s/.../0/. Michal

On 1/21/20 4:37 AM, Julio Faracco wrote:
It is not able to retrieve IP addresses from LXC domains. This method was not implemented before. LXC uses the same operations to retrieve this information, but QEMU has their own functions to process this data. This series turn them into global functions, moving them into domain conf methods, to make them available for other drivers. The only source that LXC does not support is agent which is a specific source from QEMU.
Julio Faracco (2): qemu: Converting DHCP and ARP functions to domain conf lxc: Add support to lxcDomainInterfaceAddresses() function
src/conf/domain_conf.c | 134 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 + src/lxc/lxc_driver.c | 44 +++++++++++++ src/qemu/qemu_driver.c | 137 +-------------------------------------- 5 files changed, 184 insertions(+), 135 deletions(-)
Fixed, and pushed. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
Julio Faracco
-
Michal Privoznik