Introduce a new virNetworPort object that will present an attachment to
a virtual network from a VM.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
include/libvirt/libvirt-network.h | 49 +++++
include/libvirt/virterror.h | 3 +
src/datatypes.c | 60 +++++
src/datatypes.h | 41 ++++
src/driver-network.h | 27 +++
src/libvirt-network.c | 351 ++++++++++++++++++++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 14 ++
src/util/virerror.c | 9 +
9 files changed, 556 insertions(+)
diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h
index 5115251fbe..08b91e6021 100644
--- a/include/libvirt/libvirt-network.h
+++ b/include/libvirt/libvirt-network.h
@@ -46,6 +46,22 @@ typedef struct _virNetwork virNetwork;
*/
typedef virNetwork *virNetworkPtr;
+/**
+ * virNetworkPort:
+ *
+ * a virNetworkPort is a private structure representing a virtual network
+ * port
+ */
+typedef struct _virNetworkPort virNetworkPort;
+
+/**
+ * virNetworkPortPtr:
+ *
+ * a virNetworkPortPtr is pointer to a virNetworkPort private structure,
+ * this is the type used to reference a virtual network port in the API.
+ */
+typedef virNetworkPort *virNetworkPortPtr;
+
/*
* Get connection from network.
*/
@@ -333,4 +349,37 @@ int virConnectNetworkEventRegisterAny(virConnectPtr conn,
int virConnectNetworkEventDeregisterAny(virConnectPtr conn,
int callbackID);
+virNetworkPortPtr virNetworkPortLookupByUUID(virNetworkPtr net,
+ const unsigned char *uuid);
+
+virNetworkPortPtr virNetworkPortLookupByUUIDString(virNetworkPtr net,
+ const char *uuidstr);
+
+typedef enum {
+ VIR_NETWORK_PORT_CREATE_RECLAIM = (1 << 0), /* reclaim existing used resources
*/
+} virNetworkPortCreateFlags;
+
+virNetworkPortPtr virNetworkPortCreateXML(virNetworkPtr net,
+ const char *xmldesc,
+ unsigned int flags);
+
+virNetworkPtr virNetworkPortGetNetwork(virNetworkPortPtr port);
+
+char *virNetworkPortGetXMLDesc(virNetworkPortPtr port,
+ unsigned int flags);
+
+int virNetworkPortGetUUID(virNetworkPortPtr port,
+ unsigned char *uuid);
+int virNetworkPortGetUUIDString(virNetworkPortPtr port,
+ char *buf);
+
+int virNetworkPortDelete(virNetworkPortPtr port,
+ unsigned int flags);
+
+int virNetworkListAllPorts(virNetworkPtr network,
+ virNetworkPortPtr **ports,
+ unsigned int flags);
+
+int virNetworkPortFree(virNetworkPortPtr port);
+
#endif /* LIBVIRT_NETWORK_H */
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index fbbe2d5624..3db8067391 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -321,6 +321,9 @@ typedef enum {
VIR_ERR_DEVICE_MISSING = 99, /* fail to find the desired device */
VIR_ERR_INVALID_NWFILTER_BINDING = 100, /* invalid nwfilter binding */
VIR_ERR_NO_NWFILTER_BINDING = 101, /* no nwfilter binding */
+ VIR_ERR_INVALID_NETWORK_PORT = 102, /* invalid network port object */
+ VIR_ERR_NETWORK_PORT_EXIST = 103, /* the network port already exist */
+ VIR_ERR_NO_NETWORK_PORT = 104, /* network port not found */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_NUMBER_LAST
diff --git a/src/datatypes.c b/src/datatypes.c
index caf035f178..30c98d62a5 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -39,6 +39,7 @@ virClassPtr virDomainClass;
virClassPtr virDomainSnapshotClass;
virClassPtr virInterfaceClass;
virClassPtr virNetworkClass;
+virClassPtr virNetworkPortClass;
virClassPtr virNodeDeviceClass;
virClassPtr virNWFilterClass;
virClassPtr virNWFilterBindingClass;
@@ -53,6 +54,7 @@ static void virDomainDispose(void *obj);
static void virDomainSnapshotDispose(void *obj);
static void virInterfaceDispose(void *obj);
static void virNetworkDispose(void *obj);
+static void virNetworkPortDispose(void *obj);
static void virNodeDeviceDispose(void *obj);
static void virNWFilterDispose(void *obj);
static void virNWFilterBindingDispose(void *obj);
@@ -89,6 +91,7 @@ virDataTypesOnceInit(void)
DECLARE_CLASS(virDomainSnapshot);
DECLARE_CLASS(virInterface);
DECLARE_CLASS(virNetwork);
+ DECLARE_CLASS(virNetworkPort);
DECLARE_CLASS(virNodeDevice);
DECLARE_CLASS(virNWFilter);
DECLARE_CLASS(virNWFilterBinding);
@@ -385,6 +388,63 @@ virNetworkDispose(void *obj)
}
+/**
+ * virGetNetworkPort:
+ * @net: the network object
+ * @uuid: pointer to the uuid
+ *
+ * Allocates a new network port object. When the object is no longer needed,
+ * virObjectUnref() must be called in order to not leak data.
+ *
+ * Returns a pointer to the network port object, or NULL on error.
+ */
+virNetworkPortPtr
+virGetNetworkPort(virNetworkPtr net, const unsigned char *uuid)
+{
+ virNetworkPortPtr ret = NULL;
+
+ if (virDataTypesInitialize() < 0)
+ return NULL;
+
+ virCheckNetworkGoto(net, error);
+ virCheckNonNullArgGoto(uuid, error);
+
+ if (!(ret = virObjectNew(virNetworkPortClass)))
+ goto error;
+
+ ret->net = virObjectRef(net);
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+ return ret;
+
+ error:
+ virObjectUnref(ret);
+ return NULL;
+}
+
+/**
+ * virNetworkPortDispose:
+ * @obj: the network port to release
+ *
+ * Unconditionally release all memory associated with a network port.
+ * The network port object must not be used once this method returns.
+ *
+ * It will also unreference the associated network object,
+ * which may also be released if its ref count hits zero.
+ */
+static void
+virNetworkPortDispose(void *obj)
+{
+ virNetworkPortPtr port = obj;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(port->uuid, uuidstr);
+ VIR_DEBUG("release network port %p %s", port, uuidstr);
+
+ virObjectUnref(port->net);
+}
+
+
/**
* virGetInterface:
* @conn: the hypervisor connection
diff --git a/src/datatypes.h b/src/datatypes.h
index 529b340587..94e814e7a3 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -34,6 +34,7 @@ extern virClassPtr virDomainClass;
extern virClassPtr virDomainSnapshotClass;
extern virClassPtr virInterfaceClass;
extern virClassPtr virNetworkClass;
+extern virClassPtr virNetworkPortClass;
extern virClassPtr virNodeDeviceClass;
extern virClassPtr virNWFilterClass;
extern virClassPtr virNWFilterBindingClass;
@@ -116,6 +117,33 @@ extern virClassPtr virAdmClientClass;
} \
} while (0)
+# define virCheckNetworkPortReturn(obj, retval) \
+ do { \
+ virNetworkPortPtr _port = (obj); \
+ if (!virObjectIsClass(_port, virNetworkPortClass) || \
+ !virObjectIsClass(_port->net, virNetworkClass)) { \
+ virReportErrorHelper(VIR_FROM_NETWORK, \
+ VIR_ERR_INVALID_NETWORK_PORT, \
+ __FILE__, __FUNCTION__, __LINE__, \
+ __FUNCTION__); \
+ virDispatchError(NULL); \
+ return retval; \
+ } \
+ } while (0)
+
+# define virCheckNetworkPortGoto(obj, label) \
+ do { \
+ virNetworkPortPtr _port = (obj); \
+ if (!virObjectIsClass(_port, virNetworkPortClass) || \
+ !virObjectIsClass(_port->net, virNetworkClass)) { \
+ virReportErrorHelper(VIR_FROM_NETWORK, \
+ VIR_ERR_INVALID_NETWORK_PORT, \
+ __FILE__, __FUNCTION__, __LINE__, \
+ __FUNCTION__); \
+ goto label; \
+ } \
+ } while (0)
+
# define virCheckInterfaceReturn(obj, retval) \
do { \
virInterfacePtr _iface = (obj); \
@@ -573,6 +601,17 @@ struct _virNetwork {
unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
};
+/**
+* _virNetworkPort:
+*
+* Internal structure associated to a network port
+*/
+struct _virNetworkPort {
+ virObject parent;
+ virNetworkPtr net; /* pointer back to the connection */
+ unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
+};
+
/**
* _virInterface:
*
@@ -716,6 +755,8 @@ virDomainPtr virGetDomain(virConnectPtr conn,
virNetworkPtr virGetNetwork(virConnectPtr conn,
const char *name,
const unsigned char *uuid);
+virNetworkPortPtr virGetNetworkPort(virNetworkPtr net,
+ const unsigned char *uuid);
virInterfacePtr virGetInterface(virConnectPtr conn,
const char *name,
const char *mac);
diff --git a/src/driver-network.h b/src/driver-network.h
index 2715c7bfec..11c2e0df15 100644
--- a/src/driver-network.h
+++ b/src/driver-network.h
@@ -118,6 +118,28 @@ typedef int
virNetworkDHCPLeasePtr **leases,
unsigned int flags);
+typedef virNetworkPortPtr
+(*virDrvNetworkPortLookupByUUID)(virNetworkPtr net,
+ const unsigned char *uuid);
+
+typedef virNetworkPortPtr
+(*virDrvNetworkPortCreateXML)(virNetworkPtr net,
+ const char *xmldesc,
+ unsigned int flags);
+
+typedef char *
+(*virDrvNetworkPortGetXMLDesc)(virNetworkPortPtr port,
+ unsigned int flags);
+
+typedef int
+(*virDrvNetworkPortDelete)(virNetworkPortPtr port,
+ unsigned int flags);
+
+typedef int
+(*virDrvNetworkListAllPorts)(virNetworkPtr network,
+ virNetworkPortPtr **ports,
+ unsigned int flags);
+
typedef struct _virNetworkDriver virNetworkDriver;
typedef virNetworkDriver *virNetworkDriverPtr;
@@ -151,6 +173,11 @@ struct _virNetworkDriver {
virDrvNetworkIsActive networkIsActive;
virDrvNetworkIsPersistent networkIsPersistent;
virDrvNetworkGetDHCPLeases networkGetDHCPLeases;
+ virDrvNetworkPortLookupByUUID networkPortLookupByUUID;
+ virDrvNetworkPortCreateXML networkPortCreateXML;
+ virDrvNetworkPortGetXMLDesc networkPortGetXMLDesc;
+ virDrvNetworkPortDelete networkPortDelete;
+ virDrvNetworkListAllPorts networkListAllPorts;
};
diff --git a/src/libvirt-network.c b/src/libvirt-network.c
index 9f9e0ddaf8..a6546a68e9 100644
--- a/src/libvirt-network.c
+++ b/src/libvirt-network.c
@@ -1246,3 +1246,354 @@ virNetworkDHCPLeaseFree(virNetworkDHCPLeasePtr lease)
VIR_FREE(lease->clientid);
VIR_FREE(lease);
}
+
+
+/**
+ * virNetworkPortLookupByUUID:
+ * @net: pointer to the network object
+ * @uuid: the raw UUID for the network port
+ *
+ * Try to lookup a port on the given network based on its UUID.
+ *
+ * virNetworkPortFree should be used to free the resources after the
+ * network port object is no longer needed.
+ *
+ * Returns a new network port object or NULL in case of failure. If the
+ * network port cannot be found, then VIR_ERR_NO_NETWORK_PORT error is raised.
+ */
+virNetworkPortPtr
+virNetworkPortLookupByUUID(virNetworkPtr net,
+ const unsigned char *uuid)
+{
+ VIR_UUID_DEBUG(net, uuid);
+
+ virResetLastError();
+
+ virCheckNetworkReturn(net, NULL);
+ virCheckNonNullArgGoto(uuid, error);
+
+ if (net->conn->networkDriver &&
net->conn->networkDriver->networkPortLookupByUUID) {
+ virNetworkPortPtr ret;
+ ret = net->conn->networkDriver->networkPortLookupByUUID(net, uuid);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(net->conn);
+ return NULL;
+}
+
+
+/**
+ * virNetworkPortLookupByUUIDString:
+ * @net: pointer to the network object
+ * @uuidstr: the string UUID for the port
+ *
+ * Try to lookup a port on the given network based on its UUID.
+ *
+ * Returns a new network port object or NULL in case of failure. If the
+ * network port cannot be found, then VIR_ERR_NO_NETWORK_PORT error is raised.
+ */
+virNetworkPortPtr
+virNetworkPortLookupByUUIDString(virNetworkPtr net,
+ const char *uuidstr)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ VIR_DEBUG("net=%p, uuidstr=%s", net, NULLSTR(uuidstr));
+
+ virResetLastError();
+
+ virCheckNetworkReturn(net, NULL);
+ virCheckNonNullArgGoto(uuidstr, error);
+
+ if (virUUIDParse(uuidstr, uuid) < 0) {
+ virReportInvalidArg(uuidstr,
+ _("uuidstr in %s must be a valid UUID"),
+ __FUNCTION__);
+ goto error;
+ }
+
+ return virNetworkPortLookupByUUID(net, &uuid[0]);
+
+ error:
+ virDispatchError(net->conn);
+ return NULL;
+}
+
+/**
+ * virNetworkPortCreateXML:
+ * @net: pointer to the network object
+ * @xmldesc: an XML description of the port
+ * @flags: currently unused, pass 0
+ *
+ * Create a new network port, based on an XML description
+ * similar to the one returned by virNetworkPortGetXMLDesc()
+ *
+ * virNetworkPortFree should be used to free the resources after the
+ * network port object is no longer needed.
+ *
+ * Returns a new network port object or NULL in case of failure
+ */
+virNetworkPortPtr
+virNetworkPortCreateXML(virNetworkPtr net,
+ const char *xmldesc,
+ unsigned int flags)
+{
+ VIR_DEBUG("net=%p, xmldesc=%s, flags=0x%x", net, NULLSTR(xmldesc), flags);
+
+ virResetLastError();
+
+ virCheckNetworkReturn(net, NULL);
+ virCheckNonNullArgGoto(xmldesc, error);
+ virCheckReadOnlyGoto(net->conn->flags, error);
+
+ if (net->conn->networkDriver &&
net->conn->networkDriver->networkPortCreateXML) {
+ virNetworkPortPtr ret;
+ ret = net->conn->networkDriver->networkPortCreateXML(net, xmldesc,
flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(net->conn);
+ return NULL;
+}
+
+/**
+ * virNetworkPortGetNetwork:
+ * @port: pointer to a network port
+ *
+ * Provides the network pointer associated with a port. The
+ * reference counter on the connection is not increased by this
+ * call.
+ *
+ * Returns the virNetworkPtr or NULL in case of failure.
+ */
+virNetworkPtr
+virNetworkPortGetNetwork(virNetworkPortPtr port)
+{
+ VIR_DEBUG("port=%p", port);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, NULL);
+
+ return port->net;
+}
+
+
+/**
+ * virNetworkPortGetXMLDesc:
+ * @port: a network port object
+ * @flags: currently unused, pass 0
+ *
+ * Provide an XML description of the network port. The description may be reused
+ * later to recreate the port with virNetworkPortCreateXML().
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+char *
+virNetworkPortGetXMLDesc(virNetworkPortPtr port,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("port=%p, flags=0x%x", port, flags);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, NULL);
+ conn = port->net->conn;
+
+ if (conn->networkDriver &&
conn->networkDriver->networkPortGetXMLDesc) {
+ char *ret;
+ ret = conn->networkDriver->networkPortGetXMLDesc(port, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virNetworkPortGetUUID:
+ * @port: a network port object
+ * @uuid: pointer to a VIR_UUID_BUFLEN bytes array
+ *
+ * Get the UUID for a network port
+ *
+ * Returns -1 in case of error, 0 in case of success
+ */
+int
+virNetworkPortGetUUID(virNetworkPortPtr port,
+ unsigned char *uuid)
+{
+ VIR_DEBUG("port=%p, uuid=%p", port, uuid);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, -1);
+ virCheckNonNullArgGoto(uuid, error);
+
+ memcpy(uuid, &port->uuid[0], VIR_UUID_BUFLEN);
+
+ return 0;
+
+ error:
+ virDispatchError(port->net->conn);
+ return -1;
+}
+
+
+/**
+ * virNetworkPortGetUUIDString:
+ * @port: a network port object
+ * @buf: pointer to a VIR_UUID_STRING_BUFLEN bytes array
+ *
+ * Get the UUID for a network as string. For more information about
+ * UUID see RFC4122.
+ *
+ * Returns -1 in case of error, 0 in case of success
+ */
+int
+virNetworkPortGetUUIDString(virNetworkPortPtr port,
+ char *buf)
+{
+ VIR_DEBUG("port=%p, buf=%p", port, buf);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, -1);
+ virCheckNonNullArgGoto(buf, error);
+
+ virUUIDFormat(port->uuid, buf);
+ return 0;
+
+ error:
+ virDispatchError(port->net->conn);
+ return -1;
+}
+
+/**
+ * virNetworkPortDelete:
+ * @port: a port object
+ * @flags: currently unused, pass 0
+ *
+ * Delete the network port. This does not free the
+ * associated virNetworkPortPtr object. It is the
+ * caller's responsibility to ensure the port is not
+ * still in use by a virtual machine before deleting
+ * port.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNetworkPortDelete(virNetworkPortPtr port,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("port=%p, flags=0x%x", port, flags);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, -1);
+ conn = port->net->conn;
+
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ if (conn->networkDriver && conn->networkDriver->networkPortDelete)
{
+ int ret;
+ ret = conn->networkDriver->networkPortDelete(port, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virNetworkListAllPorts:
+ * @network: pointer to a network object
+ * @ports: Pointer to a variable to store the array containing network port
+ * objects or NULL if the list is not required (just returns number
+ * of ports).
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Collect the list of network ports, and allocate an array to store those
+ * objects.
+ *
+ * Returns the number of network ports found or -1 and sets @ports to
+ * NULL in case of error. On success, the array stored into @ports is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier. The caller is responsible
+ * for calling virNetworkPortFree() on each array element, then calling
+ * free() on @ports.
+ */
+int
+virNetworkListAllPorts(virNetworkPtr network,
+ virNetworkPortPtr **ports,
+ unsigned int flags)
+{
+ VIR_DEBUG("network=%p, ports=%p, flags=0x%x", network, ports, flags);
+
+ virResetLastError();
+
+ virCheckNetworkReturn(network, -1);
+
+ if (network->conn->networkDriver &&
+ network->conn->networkDriver->networkListAllPorts) {
+ int ret;
+ ret = network->conn->networkDriver->networkListAllPorts(network, ports,
flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(network->conn);
+ return -1;
+}
+
+
+/**
+ * virNetworkPortFree:
+ * @port: a network port object
+ *
+ * Free the network port object.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNetworkPortFree(virNetworkPortPtr port)
+{
+ VIR_DEBUG("port=%p", port);
+
+ virResetLastError();
+
+ virCheckNetworkPortReturn(port, -1);
+
+ virObjectUnref(port);
+ return 0;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 92e0994612..5a7d19f6d7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1235,6 +1235,7 @@ virGetDomain;
virGetDomainSnapshot;
virGetInterface;
virGetNetwork;
+virGetNetworkPort;
virGetNodeDevice;
virGetNWFilter;
virGetNWFilterBinding;
@@ -1244,6 +1245,7 @@ virGetStorageVol;
virGetStream;
virInterfaceClass;
virNetworkClass;
+virNetworkPortClass;
virNewConnectCloseCallbackData;
virNodeDeviceClass;
virNWFilterClass;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 042b4df043..3a18277eb9 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -814,4 +814,18 @@ LIBVIRT_4.10.0 {
virDomainSetIOThreadParams;
} LIBVIRT_4.5.0;
+LIBVIRT_5.0.0 {
+ global:
+ virNetworkListAllPorts;
+ virNetworkPortLookupByUUID;
+ virNetworkPortLookupByUUIDString;
+ virNetworkPortCreateXML;
+ virNetworkPortGetNetwork;
+ virNetworkPortGetXMLDesc;
+ virNetworkPortGetUUID;
+ virNetworkPortGetUUIDString;
+ virNetworkPortDelete;
+ virNetworkPortFree;
+} LIBVIRT_4.10.0;
+
# .... define new API here using predicted next version number ....
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 61b47d2be0..c195a72c74 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1213,6 +1213,15 @@ const virErrorMsgTuple virErrorMsgStrings[VIR_ERR_NUMBER_LAST] = {
[VIR_ERR_NO_NWFILTER_BINDING] = {
N_("Network filter binding not found"),
N_("Network filter binding not found: %s") },
+ [VIR_ERR_INVALID_NETWORK_PORT] = {
+ N_("Invalid network port pointer"),
+ N_("Invalid network port pointer: %s") },
+ [VIR_ERR_NETWORK_PORT_EXIST] = {
+ N_("this network port exists already"),
+ N_("network port %s exists already") },
+ [VIR_ERR_NO_NETWORK_PORT] = {
+ N_("network port not found"),
+ N_("network port not found: %s") },
};
--
2.19.2