Introduce a new virNetworPort object that will present an attachment to a virtual network from a VM.
Signed-off-by: Daniel P. Berrangé <berra...@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 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list