File libvirt.suse-netcontrol.patch of Package libvirt

From: Olaf Hering <olaf@aepfle.de>
Date: Wed, 21 Feb 2018 10:03:54 +0000
Subject: suse-netcontrol

---
 meson.build                             | 11 +-
 meson_options.txt                       |  1 +
 src/interface/interface_backend_netcf.c | 59 ++++++++-
 src/interface/interface_driver.c        |  9 +-
 src/interface/meson.build               |  3 +-
 tools/virsh.c                           |  2 +
 6 files changed, 80 insertions(+), 5 deletions(-)

--- a/meson.build
+++ b/meson.build
@@ -1116,24 +1116,30 @@ libxml_dep = dependency('libxml-2.0', version: '>=' + libxml_version)
 libm_dep = cc.find_library('m')
 
 netcf_version = '0.1.8'
 if not get_option('netcf').disabled()
   netcf_dep = dependency('netcf', version: '>=' + netcf_version, required: get_option('netcf'))
   if netcf_dep.found()
     conf.set('WITH_NETCF', 1)
   endif
 else
   netcf_dep = dependency('', required: false)
 endif
 
+netcontrol_version = '0.2.0'
+netcontrol_dep = dependency('netcontrol', version: '>=' + netcontrol_version, required: get_option('netcontrol'))
+if netcontrol_dep.found()
+  conf.set('WITH_NETCONTROL', 1)
+endif
+
 have_gnu_gettext_tools = false
 if not get_option('nls').disabled()
   have_gettext = cc.has_function('gettext')
   if not have_gettext
     intl_dep = cc.find_library('intl', required: false)
     have_gettext = intl_dep.found()
   else
     intl_dep = dependency('', required: false)
   endif
   if not have_gettext and get_option('nls').enabled()
     error('gettext() is required to build libvirt')
   endif
@@ -1477,28 +1483,28 @@ if not get_option('driver_esx').disabled() and curl_dep.found()
   conf.set('WITH_ESX', 1)
   conf.set('WITH_VMX', 1)
 elif get_option('driver_esx').enabled()
   error('Curl is required for the ESX driver')
 endif
 
 if not get_option('driver_hyperv').disabled() and openwsman_dep.found()
   conf.set('WITH_HYPERV', 1)
 elif get_option('driver_hyperv').enabled()
   error('openwsman is required for the Hyper-V driver')
 endif
 
-if not get_option('driver_interface').disabled() and conf.has('WITH_LIBVIRTD') and (udev_dep.found() or conf.has('WITH_NETCF'))
+if not get_option('driver_interface').disabled() and conf.has('WITH_LIBVIRTD') and (udev_dep.found() or conf.has('WITH_NETCF') or netcontrol_dep.found())
   conf.set('WITH_INTERFACE', 1)
 elif get_option('driver_interface').enabled()
-  error('Requested the Interface driver without netcf or udev and libvirtd support')
+  error('Requested the Interface driver without netcf, netcontrol or udev and libvirtd support')
 endif
 
 if not get_option('driver_libxl').disabled() and conf.has('WITH_LIBVIRTD')
   libxl_version = '4.9.0'
   libxl_dep = dependency('xenlight', version: '>=' + libxl_version, required: get_option('driver_libxl'))
 
   if libxl_dep.found()
     libxl_firmware_dir = libxl_dep.get_variable(pkgconfig : 'xenfirmwaredir', default_value: '')
     libxl_execbin = libxl_dep.get_variable(pkgconfig : 'libexec_bin', default_value: '')
     if libxl_firmware_dir != ''
       conf.set_quoted('LIBXL_FIRMWARE_DIR', libxl_firmware_dir)
     endif
@@ -2254,24 +2260,25 @@ libs_summary = {
   'json-c': json_c_dep,
   'libbsd': libbsd_dep,
   'libiscsi': libiscsi_dep,
   'libkvm': libkvm_dep,
   'libnbd': libnbd_dep,
   'libnl': libnl_dep,
   'libparted': libparted_dep,
   'libpcap': libpcap_dep,
   'libssh': libssh_dep,
   'libssh2': libssh2_dep,
   'libutil': libutil_dep,
   'netcf': netcf_dep,
+  'netcontrol': netcontrol_dep,
   'NLS': have_gnu_gettext_tools,
   'numactl': numactl_dep,
   'openwsman': openwsman_dep,
   'parallels-sdk': parallels_sdk_dep,
   'pciaccess': pciaccess_dep,
   'polkit': conf.has('WITH_POLKIT'),
   'rbd': rbd_dep,
   'readline': readline_dep,
   'sanlock': sanlock_dep,
   'sasl': sasl_dep,
   'selinux': selinux_dep,
   'udev': udev_dep,
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -26,24 +26,25 @@ option('bash_completion_dir', type: 'string', value: '', description: 'directory
 option('blkid', type: 'feature', value: 'auto', description: 'blkid support')
 option('capng', type: 'feature', value: 'auto', description: 'cap-ng support')
 option('curl', type: 'feature', value: 'auto', description: 'curl support')
 option('fuse', type: 'feature', value: 'auto', description: 'fuse support')
 option('glusterfs', type: 'feature', value: 'auto', description: 'glusterfs support')
 option('json_c', type: 'feature', value: 'auto', description: 'JSON-C support')
 option('libiscsi', type: 'feature', value: 'auto', description: 'libiscsi support')
 option('libnl', type: 'feature', value: 'auto', description: 'libnl support')
 option('libpcap', type: 'feature', value: 'auto', description: 'libpcap support')
 option('libssh', type: 'feature', value: 'auto', description: 'libssh support')
 option('libssh2', type: 'feature', value: 'auto', description: 'libssh2 support')
 option('netcf', type: 'feature', value: 'auto', description: 'netcf support')
+option('netcontrol', type: 'feature', value: 'auto', description: 'netcontrol support')
 option('nls', type: 'feature', value: 'auto', description: 'nls support')
 option('numactl', type: 'feature', value: 'auto', description: 'numactl support')
 option('openwsman', type: 'feature', value: 'auto', description: 'openwsman support')
 option('pciaccess', type: 'feature', value: 'auto', description: 'pciaccess support')
 option('polkit', type: 'feature', value: 'auto', description: 'use PolicyKit for UNIX socket access checks')
 option('readline', type: 'feature', value: 'auto', description: 'readline support')
 option('sanlock', type: 'feature', value: 'auto', description: 'sanlock support')
 option('sasl', type: 'feature', value: 'auto', description: 'sasl support')
 option('selinux', type: 'feature', value: 'auto', description: 'selinux support')
 option('selinux_mount', type: 'string', value: '', description: 'set SELinux mount point')
 option('sshconfdir', type: 'string', value: '', description: 'directory for SSH client configuration')
 # dep:pciaccess
--- a/src/interface/interface_backend_netcf.c
+++ b/src/interface/interface_backend_netcf.c
@@ -12,25 +12,30 @@
  * 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
  * <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 
-#include <netcf.h>
+#ifdef WITH_NETCONTROL
+# include <netcontrol/netcf.h>
+# include <netcontrol/logger.h>
+#else
+# include <netcf.h>
+#endif
 
 #include "virerror.h"
 #include "datatypes.h"
 #include "interface_driver.h"
 #include "interface_conf.h"
 #include "viralloc.h"
 #include "virlog.h"
 #include "virpidfile.h"
 #include "viraccessapicheck.h"
 #include "virinterfaceobj.h"
 #include "virutil.h"
 
@@ -61,24 +66,55 @@ static int
 virNetcfDriverStateOnceInit(void)
 {
     if (!VIR_CLASS_NEW(virNetcfDriverState, virClassForObjectLockable()))
         return -1;
 
     return 0;
 }
 
 VIR_ONCE_GLOBAL_INIT(virNetcfDriverState);
 
 static virNetcfDriverStatePtr driver;
 
+#ifdef WITH_NETCONTROL
+static void
+interface_nc_log_driver(const char *category ATTRIBUTE_UNUSED,
+                        int         priority,
+                        const char *func,
+                        const char *file,
+                        long long   line,
+                        const char *msg,
+                        size_t      len  ATTRIBUTE_UNUSED)
+{
+    int vp;
+
+    switch (priority) {
+        case NC_LOG_FATAL:
+        case NC_LOG_ERROR:
+            vp = VIR_LOG_ERROR;
+            break;
+        case NC_LOG_WARN:
+            vp = VIR_LOG_WARN;
+            break;
+        case NC_LOG_INFO:
+            vp = VIR_LOG_INFO;
+            break;
+        case NC_LOG_DEBUG:
+        default:
+            vp = VIR_LOG_DEBUG;
+            break;
+    }
+    virLogMessage(&virLogSelf, vp, file, line, func, 0, "%s", msg);
+}
+#endif
 
 static void
 virNetcfDriverStateDispose(void *obj)
 {
     virNetcfDriverStatePtr _driver = obj;
 
     if (_driver->netcf)
         ncf_close(_driver->netcf);
 
     if (_driver->lockFD != -1)
         virPidFileRelease(_driver->stateDir, "driver", _driver->lockFD);
 
@@ -117,24 +153,28 @@ netcfStateInitialize(bool privileged,
     }
 
     if (g_mkdir_with_parents(driver->stateDir, S_IRWXU) < 0) {
         virReportSystemError(errno, _("cannot create state directory '%1$s'"),
                              driver->stateDir);
         goto error;
     }
 
     if ((driver->lockFD =
          virPidFileAcquire(driver->stateDir, "driver", getpid())) < 0)
         goto error;
 
+#ifdef WITH_NETCONTROL
+    nc_logger_redirect_to(interface_nc_log_driver);
+#endif
+
     /* open netcf */
     if (ncf_init(&driver->netcf, NULL) != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to initialize netcf"));
         goto error;
     }
     return VIR_DRV_STATE_INIT_COMPLETE;
 
  error:
     g_clear_pointer(&driver, virObjectUnref);
     return VIR_DRV_STATE_INIT_ERROR;
 }
@@ -1062,24 +1102,25 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo)
        goto cleanup;
 
     if (netcfInterfaceObjIsActive(iface, &active) < 0)
         goto cleanup;
 
     ret = active ? 1 : 0;
 
  cleanup:
     ncf_if_free(iface);
     return ret;
 }
 
+#ifdef HAVE_NETCF_TRANSACTIONS
 static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
 {
     int ret = -1;
 
     virCheckFlags(0, -1); /* currently flags must be 0 */
 
     if (virInterfaceChangeBeginEnsureACL(conn) < 0)
         return -1;
 
     VIR_WITH_OBJECT_LOCK_GUARD(driver) {
         ret = ncf_change_begin(driver->netcf, 0);
         if (ret < 0) {
@@ -1133,43 +1174,46 @@ static int netcfInterfaceChangeRollback(virConnectPtr conn, unsigned int flags)
         if (ret < 0) {
             const char *errmsg, *details;
             int errcode = ncf_error(driver->netcf, &errmsg, &details);
             virReportError(netcf_to_vir_err(errcode),
                            _("failed to rollback transaction: %1$s%2$s%3$s"),
                            errmsg, details ? " - " : "",
                            NULLSTR_EMPTY(details));
         }
     }
 
     return ret;
 }
+#endif /* HAVE_NETCF_TRANSACTIONS */
 
 static virInterfaceDriver interfaceDriver = {
     .name = INTERFACE_DRIVER_NAME,
     .connectNumOfInterfaces = netcfConnectNumOfInterfaces, /* 0.7.0 */
     .connectListInterfaces = netcfConnectListInterfaces, /* 0.7.0 */
     .connectNumOfDefinedInterfaces = netcfConnectNumOfDefinedInterfaces, /* 0.7.0 */
     .connectListDefinedInterfaces = netcfConnectListDefinedInterfaces, /* 0.7.0 */
     .connectListAllInterfaces = netcfConnectListAllInterfaces, /* 0.10.2 */
     .interfaceLookupByName = netcfInterfaceLookupByName, /* 0.7.0 */
     .interfaceLookupByMACString = netcfInterfaceLookupByMACString, /* 0.7.0 */
     .interfaceGetXMLDesc = netcfInterfaceGetXMLDesc, /* 0.7.0 */
     .interfaceDefineXML = netcfInterfaceDefineXML, /* 0.7.0 */
     .interfaceUndefine = netcfInterfaceUndefine, /* 0.7.0 */
     .interfaceCreate = netcfInterfaceCreate, /* 0.7.0 */
     .interfaceDestroy = netcfInterfaceDestroy, /* 0.7.0 */
     .interfaceIsActive = netcfInterfaceIsActive, /* 0.7.3 */
+#ifdef HAVE_NETCF_TRANSACTIONS
     .interfaceChangeBegin = netcfInterfaceChangeBegin, /* 0.9.2 */
     .interfaceChangeCommit = netcfInterfaceChangeCommit, /* 0.9.2 */
     .interfaceChangeRollback = netcfInterfaceChangeRollback, /* 0.9.2 */
+#endif /* HAVE_NETCF_TRANSACTIONS */
 };
 
 
 static virHypervisorDriver interfaceHypervisorDriver = {
     .name = "interface",
     .connectOpen = netcfConnectOpen, /* 4.1.0 */
     .connectClose = netcfConnectClose, /* 4.1.0 */
     .connectIsEncrypted = netcfConnectIsEncrypted, /* 4.1.0 */
     .connectIsSecure = netcfConnectIsSecure, /* 4.1.0 */
     .connectIsAlive = netcfConnectIsAlive, /* 4.1.0 */
 };
 
@@ -1182,20 +1226,33 @@ static virConnectDriver interfaceConnectDriver = {
 };
 
 
 static virStateDriver interfaceStateDriver = {
     .name = INTERFACE_DRIVER_NAME,
     .stateInitialize = netcfStateInitialize,
     .stateCleanup = netcfStateCleanup,
     .stateReload = netcfStateReload,
 };
 
 int netcfIfaceRegister(void)
 {
+    struct netcf *netcf;
+
+    /* Initialization of libnetcontrol will fail if NetworkManager is enabled.
+     * Skip registration if ncf_init fails.
+     * TODO: finer-grained check?  E.g. is_nm_enabled()
+     */
+    if (ncf_init(&netcf, NULL) != 0) {
+        VIR_INFO("Failed to initialize libnetcontrol.  Management of interface devices is disabled");
+        return 0;
+    }
+
+    ncf_close(netcf);
+
     if (virRegisterConnectDriver(&interfaceConnectDriver, false) < 0)
         return -1;
     if (virSetSharedInterfaceDriver(&interfaceDriver) < 0)
         return -1;
     if (virRegisterStateDriver(&interfaceStateDriver) < 0)
         return -1;
     return 0;
 }
--- a/src/interface/interface_driver.c
+++ b/src/interface/interface_driver.c
@@ -21,19 +21,26 @@
 #include <config.h>
 
 #include "interface_driver.h"
 
 int
 interfaceRegister(void)
 {
 #ifdef WITH_NETCF
     /* Attempt to load the netcf based backend first */
     if (netcfIfaceRegister() == 0)
         return 0;
 #endif /* WITH_NETCF */
+#ifdef WITH_NETCONTROL
+    /* Attempt to load the netcontrol based backend, which is a slightly
+       patched netcf backend */
+    if (netcfIfaceRegister() == 0)
+        return 0;
+#endif /* WITH_NETCONTROL */
 #if WITH_UDEV
-    /* If there's no netcf or it failed to load, register the udev backend */
+    /* If there's no netcf or netcontrol, or it failed to load, register the
+       udev backend */
     if (udevIfaceRegister() == 0)
         return 0;
 #endif /* WITH_UDEV */
     return -1;
 }
--- a/src/interface/meson.build
+++ b/src/interface/meson.build
@@ -1,37 +1,38 @@
 interface_driver_sources = [
   'interface_driver.c',
 ]
 
-if conf.has('WITH_NETCF')
+if conf.has('WITH_NETCF') or conf.has('WITH_NETCONTROL')
   interface_driver_sources += 'interface_backend_netcf.c'
 endif
 
 if conf.has('WITH_UDEV')
   interface_driver_sources += 'interface_backend_udev.c'
 endif
 
 driver_source_files += files(interface_driver_sources)
 stateful_driver_source_files += files(interface_driver_sources)
 
 if conf.has('WITH_INTERFACE')
   virt_modules += {
     'name': 'virt_driver_interface',
     'sources': [
       files(interface_driver_sources),
     ],
     'deps': [
       access_dep,
       libnl_dep,
       netcf_dep,
+      netcontrol_dep,
       udev_dep,
     ],
     'link_args': [
       libvirt_no_undefined,
     ],
   }
 
   virt_daemons += {
     'name': 'virtinterfaced',
     'c_args': [
       '-DDAEMON_NAME="virtinterfaced"',
       '-DMODULE_NAME="interface"',
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -529,24 +529,26 @@ virshShowVersion(vshControl *ctl G_GNUC_UNUSED)
     vshPrint(ctl, " Remote");
 #endif
 #ifdef WITH_NETWORK
     vshPrint(ctl, " Network");
 #endif
 #ifdef WITH_BRIDGE
     vshPrint(ctl, " Bridging");
 #endif
 #if defined(WITH_INTERFACE)
     vshPrint(ctl, " Interface");
 # if defined(WITH_NETCF)
     vshPrint(ctl, " netcf");
+# elif defined(WITH_NETCONTROL)
+    vshPrint(ctl, " netcontrol");
 # elif defined(WITH_UDEV)
     vshPrint(ctl, " udev");
 # endif
 #endif
 #ifdef WITH_NWFILTER
     vshPrint(ctl, " Nwfilter");
 #endif
     vshPrint(ctl, "\n");
 
     vshPrint(ctl, "%s", _(" Storage:"));
 #ifdef WITH_STORAGE_DIR
     vshPrint(ctl, " Dir");
openSUSE Build Service is sponsored by