/* * libvirt-interface.c: entry points for virInterfacePtr APIs * * Copyright (C) 2006-2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include #include "datatypes.h" #include "virlog.h" VIR_LOG_INIT("libvirt.interface"); #define VIR_FROM_THIS VIR_FROM_INTERFACE /** * virInterfaceGetConnect: * @iface: pointer to an interface * * Provides the connection pointer associated with an interface. The * reference counter on the connection is not increased by this * call. * * Returns the virConnectPtr or NULL in case of failure. */ virConnectPtr virInterfaceGetConnect(virInterfacePtr iface) { VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, NULL); return iface->conn; } /** * virConnectListAllInterfaces: * @conn: Pointer to the hypervisor connection. * @ifaces: Pointer to a variable to store the array containing the interface * objects or NULL if the list is not required (just returns number * of interfaces). * @flags: bitwise-OR of virConnectListAllInterfacesFlags. * * Collect the list of interfaces, and allocate an array to store those * objects. This API solves the race inherent between virConnectListInterfaces * and virConnectListDefinedInterfaces. * * Normally, all interfaces are returned; however, @flags can be used to * filter the results for a smaller list of targeted interfaces. The valid * flags are divided into groups, where each group contains bits that * describe mutually exclusive attributes of a interface, and where all bits * within a group describe all possible interfaces. * * The only group of @flags is VIR_CONNECT_LIST_INTERFACES_ACTIVE (up) and * VIR_CONNECT_LIST_INTERFACES_INACTIVE (down) to filter the interfaces by state. * * Returns the number of interfaces found or -1 and sets @ifaces to NULL in case * of error. On success, the array stored into @ifaces 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 * virStorageInterfaceFree() on each array element, then calling free() on @ifaces. */ int virConnectListAllInterfaces(virConnectPtr conn, virInterfacePtr **ifaces, unsigned int flags) { VIR_DEBUG("conn=%p, ifaces=%p, flags=0x%x", conn, ifaces, flags); virResetLastError(); if (ifaces) *ifaces = NULL; virCheckConnectReturn(conn, -1); if (conn->interfaceDriver && conn->interfaceDriver->connectListAllInterfaces) { int ret; ret = conn->interfaceDriver->connectListAllInterfaces(conn, ifaces, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virConnectNumOfInterfaces: * @conn: pointer to the hypervisor connection * * Provides the number of active interfaces on the physical host. * * Returns the number of active interfaces found or -1 in case of error */ int virConnectNumOfInterfaces(virConnectPtr conn) { VIR_DEBUG("conn=%p", conn); virResetLastError(); virCheckConnectReturn(conn, -1); if (conn->interfaceDriver && conn->interfaceDriver->connectNumOfInterfaces) { int ret; ret = conn->interfaceDriver->connectNumOfInterfaces(conn); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virConnectListInterfaces: * @conn: pointer to the hypervisor connection * @names: array to collect the list of names of interfaces * @maxnames: size of @names * * Collect the list of active physical host interfaces, * and store their names in @names * * For more control over the results, see virConnectListAllInterfaces(). * * Returns the number of interfaces found or -1 in case of error. Note that * this command is inherently racy; a interface can be started between a call * to virConnectNumOfInterfaces() and this call; you are only guaranteed that * all currently active interfaces were listed if the return is less than * @maxnames. The client must call free() on each returned name. */ int virConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames) { VIR_DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); virResetLastError(); virCheckConnectReturn(conn, -1); virCheckNonNullArgGoto(names, error); virCheckNonNegativeArgGoto(maxnames, error); if (conn->interfaceDriver && conn->interfaceDriver->connectListInterfaces) { int ret; ret = conn->interfaceDriver->connectListInterfaces(conn, names, maxnames); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virConnectNumOfDefinedInterfaces: * @conn: pointer to the hypervisor connection * * Provides the number of defined (inactive) interfaces on the physical host. * * Returns the number of defined interface found or -1 in case of error */ int virConnectNumOfDefinedInterfaces(virConnectPtr conn) { VIR_DEBUG("conn=%p", conn); virResetLastError(); virCheckConnectReturn(conn, -1); if (conn->interfaceDriver && conn->interfaceDriver->connectNumOfDefinedInterfaces) { int ret; ret = conn->interfaceDriver->connectNumOfDefinedInterfaces(conn); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virConnectListDefinedInterfaces: * @conn: pointer to the hypervisor connection * @names: array to collect the list of names of interfaces * @maxnames: size of @names * * Collect the list of defined (inactive) physical host interfaces, * and store their names in @names. * * For more control over the results, see virConnectListAllInterfaces(). * * Returns the number of names provided in the array or -1 in case of error. * Note that this command is inherently racy; a interface can be defined between * a call to virConnectNumOfDefinedInterfaces() and this call; you are only * guaranteed that all currently defined interfaces were listed if the return * is less than @maxnames. The client must call free() on each returned name. */ int virConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int maxnames) { VIR_DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); virResetLastError(); virCheckConnectReturn(conn, -1); virCheckNonNullArgGoto(names, error); virCheckNonNegativeArgGoto(maxnames, error); if (conn->interfaceDriver && conn->interfaceDriver->connectListDefinedInterfaces) { int ret; ret = conn->interfaceDriver->connectListDefinedInterfaces(conn, names, maxnames); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virInterfaceLookupByName: * @conn: pointer to the hypervisor connection * @name: name for the interface * * Try to lookup an interface on the given hypervisor based on its name. * * virInterfaceFree should be used to free the resources after the * interface object is no longer needed. * * Returns a new interface object or NULL in case of failure. If the * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. */ virInterfacePtr virInterfaceLookupByName(virConnectPtr conn, const char *name) { VIR_DEBUG("conn=%p, name=%s", conn, NULLSTR(name)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(name, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByName) { virInterfacePtr ret; ret = conn->interfaceDriver->interfaceLookupByName(conn, name); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; } /** * virInterfaceLookupByMACString: * @conn: pointer to the hypervisor connection * @macstr: the MAC for the interface (null-terminated ASCII format) * * Try to lookup an interface on the given hypervisor based on its MAC. * * virInterfaceFree should be used to free the resources after the * interface object is no longer needed. * * Returns a new interface object or NULL in case of failure. If the * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. */ virInterfacePtr virInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) { VIR_DEBUG("conn=%p, macstr=%s", conn, NULLSTR(macstr)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(macstr, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByMACString) { virInterfacePtr ret; ret = conn->interfaceDriver->interfaceLookupByMACString(conn, macstr); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; } /** * virInterfaceGetName: * @iface: an interface object * * Get the public name for that interface * * Returns a pointer to the name or NULL, the string need not be deallocated * its lifetime will be the same as the interface object. */ const char * virInterfaceGetName(virInterfacePtr iface) { VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, NULL); return iface->name; } /** * virInterfaceGetMACString: * @iface: an interface object * * Get the MAC for an interface as string. For more information about * MAC see RFC4122. * * Returns a pointer to the MAC address (in null-terminated ASCII * format) or NULL, the string need not be deallocated its lifetime * will be the same as the interface object. */ const char * virInterfaceGetMACString(virInterfacePtr iface) { VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, NULL); return iface->mac; } /** * virInterfaceGetXMLDesc: * @iface: an interface object * @flags: bitwise-OR of extraction flags. Current valid bits: * * VIR_INTERFACE_XML_INACTIVE - return the static configuration, * suitable for use redefining the * interface via virInterfaceDefineXML() * * Provide an XML description of the interface. If * VIR_INTERFACE_XML_INACTIVE is set, the description may be reused * later to redefine the interface with virInterfaceDefineXML(). If it * is not set, the ip address and netmask will be the current live * setting of the interface, not the settings from the config files. * * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case * of error. The caller must free() the returned value. */ char * virInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags) { virConnectPtr conn; VIR_DEBUG("iface=%p, flags=0x%x", iface, flags); virResetLastError(); virCheckInterfaceReturn(iface, NULL); conn = iface->conn; if (conn->interfaceDriver && conn->interfaceDriver->interfaceGetXMLDesc) { char *ret; ret = conn->interfaceDriver->interfaceGetXMLDesc(iface, flags); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(iface->conn); return NULL; } /** * virInterfaceDefineXML: * @conn: pointer to the hypervisor connection * @xml: the XML description for the interface, preferably in UTF-8 * @flags: extra flags; not used yet, so callers should always pass 0 * * Define an inactive persistent physical host interface or modify an existing * persistent one from the XML description. * * Normally this change in the interface configuration is immediately * permanent/persistent, but if virInterfaceChangeBegin() has been * previously called (i.e. if an interface config transaction is * open), the new interface definition will only become permanent if * virInterfaceChangeCommit() is called prior to the next reboot of * the system running libvirtd. Prior to that time, it can be * explicitly removed using virInterfaceChangeRollback(), or will be * automatically removed during the next reboot of the system running * libvirtd. * * virInterfaceFree should be used to free the resources after the * interface object is no longer needed. * * Returns NULL in case of error, a pointer to the interface otherwise */ virInterfacePtr virInterfaceDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) { VIR_DEBUG("conn=%p, xml=%s, flags=0x%x", conn, NULLSTR(xml), flags); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckReadOnlyGoto(conn->flags, error); virCheckNonNullArgGoto(xml, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceDefineXML) { virInterfacePtr ret; ret = conn->interfaceDriver->interfaceDefineXML(conn, xml, flags); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; } /** * virInterfaceUndefine: * @iface: pointer to a defined interface * * Undefine an interface, ie remove it from the config. * This does not free the associated virInterfacePtr object. * * Normally this change in the interface configuration is * permanent/persistent, but if virInterfaceChangeBegin() has been * previously called (i.e. if an interface config transaction is * open), the removal of the interface definition will only become * permanent if virInterfaceChangeCommit() is called prior to the next * reboot of the system running libvirtd. Prior to that time, the * definition can be explicitly restored using * virInterfaceChangeRollback(), or will be automatically restored * during the next reboot of the system running libvirtd. * * Returns 0 in case of success, -1 in case of error */ int virInterfaceUndefine(virInterfacePtr iface) { virConnectPtr conn; VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, -1); conn = iface->conn; virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceUndefine) { int ret; ret = conn->interfaceDriver->interfaceUndefine(iface); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(iface->conn); return -1; } /** * virInterfaceCreate: * @iface: pointer to a defined interface * @flags: extra flags; not used yet, so callers should always pass 0 * * Activate an interface (i.e. call "ifup"). * * If there was an open network config transaction at the time this * interface was defined (that is, if virInterfaceChangeBegin() had * been called), the interface will be brought back down (and then * undefined) if virInterfaceChangeRollback() is called. * * Returns 0 in case of success, -1 in case of error */ int virInterfaceCreate(virInterfacePtr iface, unsigned int flags) { virConnectPtr conn; VIR_DEBUG("iface=%p, flags=0x%x", iface, flags); virResetLastError(); virCheckInterfaceReturn(iface, -1); conn = iface->conn; virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceCreate) { int ret; ret = conn->interfaceDriver->interfaceCreate(iface, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(iface->conn); return -1; } /** * virInterfaceDestroy: * @iface: an interface object * @flags: extra flags; not used yet, so callers should always pass 0 * * deactivate an interface (ie call "ifdown") * This does not remove the interface from the config, and * does not free the associated virInterfacePtr object. * * If there is an open network config transaction at the time this * interface is destroyed (that is, if virInterfaceChangeBegin() had * been called), and if the interface is later undefined and then * virInterfaceChangeRollback() is called, the restoral of the * interface definition will also bring the interface back up. * * Returns 0 in case of success and -1 in case of failure. */ int virInterfaceDestroy(virInterfacePtr iface, unsigned int flags) { virConnectPtr conn; VIR_DEBUG("iface=%p, flags=0x%x", iface, flags); virResetLastError(); virCheckInterfaceReturn(iface, -1); conn = iface->conn; virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceDestroy) { int ret; ret = conn->interfaceDriver->interfaceDestroy(iface, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(iface->conn); return -1; } /** * virInterfaceRef: * @iface: the interface to hold a reference on * * Increment the reference count on the interface. For each * additional call to this method, there shall be a corresponding * call to virInterfaceFree to release the reference count, once * the caller no longer needs the reference to this object. * * This method is typically useful for applications where multiple * threads are using a connection, and it is required that the * connection remain open until all threads have finished using * it. ie, each new thread using an interface would increment * the reference count. * * Returns 0 in case of success, -1 in case of failure. */ int virInterfaceRef(virInterfacePtr iface) { VIR_DEBUG("iface=%p refs=%d", iface, iface ? iface->parent.u.s.refs : 0); virResetLastError(); virCheckInterfaceReturn(iface, -1); virObjectRef(iface); return 0; } /** * virInterfaceFree: * @iface: an interface object * * Free the interface object. The interface itself is unaltered. * The data structure is freed and should not be used thereafter. * * Returns 0 in case of success and -1 in case of failure. */ int virInterfaceFree(virInterfacePtr iface) { VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, -1); virObjectUnref(iface); return 0; } /** * virInterfaceChangeBegin: * @conn: pointer to hypervisor connection * @flags: extra flags; not used yet, so callers should always pass 0 * * This function creates a restore point to which one can return * later by calling virInterfaceChangeRollback(). This function should * be called before any transaction with interface configuration. * Once it is known that a new configuration works, it can be committed via * virInterfaceChangeCommit(), which frees the restore point. * * If virInterfaceChangeBegin() is called when a transaction is * already opened, this function will fail, and a * VIR_ERR_INVALID_OPERATION will be logged. * * Returns 0 in case of success and -1 in case of failure. */ int virInterfaceChangeBegin(virConnectPtr conn, unsigned int flags) { VIR_DEBUG("conn=%p, flags=0x%x", conn, flags); virResetLastError(); virCheckConnectReturn(conn, -1); virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceChangeBegin) { int ret; ret = conn->interfaceDriver->interfaceChangeBegin(conn, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virInterfaceChangeCommit: * @conn: pointer to hypervisor connection * @flags: extra flags; not used yet, so callers should always pass 0 * * This commits the changes made to interfaces and frees the restore point * created by virInterfaceChangeBegin(). * * If virInterfaceChangeCommit() is called when a transaction is not * opened, this function will fail, and a VIR_ERR_INVALID_OPERATION * will be logged. * * Returns 0 in case of success and -1 in case of failure. */ int virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags) { VIR_DEBUG("conn=%p, flags=0x%x", conn, flags); virResetLastError(); virCheckConnectReturn(conn, -1); virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceChangeCommit) { int ret; ret = conn->interfaceDriver->interfaceChangeCommit(conn, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virInterfaceChangeRollback: * @conn: pointer to hypervisor connection * @flags: extra flags; not used yet, so callers should always pass 0 * * This cancels changes made to interfaces settings by restoring previous * state created by virInterfaceChangeBegin(). * * If virInterfaceChangeRollback() is called when a transaction is not * opened, this function will fail, and a VIR_ERR_INVALID_OPERATION * will be logged. * * Returns 0 in case of success and -1 in case of failure. */ int virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags) { VIR_DEBUG("conn=%p, flags=0x%x", conn, flags); virResetLastError(); virCheckConnectReturn(conn, -1); virCheckReadOnlyGoto(conn->flags, error); if (conn->interfaceDriver && conn->interfaceDriver->interfaceChangeRollback) { int ret; ret = conn->interfaceDriver->interfaceChangeRollback(conn, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return -1; } /** * virInterfaceIsActive: * @iface: pointer to the interface object * * Determine if the interface is currently running * * Returns 1 if running, 0 if inactive, -1 on error */ int virInterfaceIsActive(virInterfacePtr iface) { VIR_DEBUG("iface=%p", iface); virResetLastError(); virCheckInterfaceReturn(iface, -1); if (iface->conn->interfaceDriver->interfaceIsActive) { int ret; ret = iface->conn->interfaceDriver->interfaceIsActive(iface); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(iface->conn); return -1; }