[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 10/14] Basic qemu NIC hotplug support



Implement basic NIC hotplug support using the 'host_net_add' and
'pci_add' qemu monitor commands.

For now, we don't support 'bridge' or 'network' types.

Also, if pci_add fails, we currently fail to remove the backend
which we added.

Finally, NIC hot-unplug support is missing.

* src/qemu_driver.c: add qemudDomainAttachNetDevice()

* src/qemu_conf.[ch]: export qemuBuildNicStr(), qemuBuildHostNetStr()
  and qemuAssignNames()

* src/libvirt_private.syms: export virDomainNetTypeToString()
---
 src/libvirt_private.syms |    1 +
 src/qemu_conf.c          |    6 ++--
 src/qemu_conf.h          |   18 ++++++++++
 src/qemu_driver.c        |   80 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 59c78d5..0caa590 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -91,6 +91,7 @@ virDomainLifecycleTypeFromString;
 virDomainLifecycleTypeToString;
 virDomainLoadAllConfigs;
 virDomainNetDefFree;
+virDomainNetTypeToString;
 virDomainObjFree;
 virDomainObjListFree;
 virDomainRemoveInactive;
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 6d876cb..f483a51 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -830,7 +830,7 @@ qemuNetTypeToHostNet(int type)
     }
 }
 
-static int
+int
 qemuAssignNetNames(virDomainDefPtr def,
                    virDomainNetDefPtr net)
 {
@@ -872,7 +872,7 @@ qemuAssignNetNames(virDomainDefPtr def,
     return 0;
 }
 
-static int
+int
 qemuBuildNicStr(virConnectPtr conn,
                 virDomainNetDefPtr net,
                 const char *prefix,
@@ -899,7 +899,7 @@ qemuBuildNicStr(virConnectPtr conn,
     return 0;
 }
 
-static int
+int
 qemuBuildHostNetStr(virConnectPtr conn,
                     virDomainNetDefPtr net,
                     const char *prefix,
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index 1b2d061..50d7c0a 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -145,6 +145,24 @@ int         qemudBuildCommandLine       (virConnectPtr conn,
                                          int *ntapfds,
                                          const char *migrateFrom);
 
+int         qemuBuildHostNetStr         (virConnectPtr conn,
+                                         virDomainNetDefPtr net,
+                                         const char *prefix,
+                                         char type_sep,
+                                         int vlan,
+                                         int tapfd,
+                                         char **str);
+
+int         qemuBuildNicStr             (virConnectPtr conn,
+                                         virDomainNetDefPtr net,
+                                         const char *prefix,
+                                         char type_sep,
+                                         int vlan,
+                                         char **str);
+
+int         qemuAssignNetNames          (virDomainDefPtr def,
+                                         virDomainNetDefPtr net);
+
 virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
                                      virCapsPtr caps,
                                      const char **progenv,
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index cbc185c..cde789e 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4492,6 +4492,84 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
     return 0;
 }
 
+static int qemudDomainAttachNetDevice(virConnectPtr conn,
+                                      virDomainObjPtr vm,
+                                      virDomainDeviceDefPtr dev,
+                                      unsigned int qemuCmdFlags)
+{
+    virDomainNetDefPtr net = dev->data.net;
+    char *cmd, *reply;
+    int i;
+
+    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) {
+        qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, _("%s"),
+                         "installed qemu version does not support host_net_add");
+        return -1;
+    }
+
+    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+        net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+        qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+                         _("network device type '%s' cannot be attached"),
+                         virDomainNetTypeToString(net->type));
+        return -1;
+    }
+
+    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) &&
+        qemuAssignNetNames(vm->def, net) < 0) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    /* Choose a vlan value greater than all other values since
+     * older versions did not store the value in the state file.
+     */
+    net->vlan = vm->def->nnets;
+    for (i = 0; i < vm->def->nnets; i++)
+        if (vm->def->nets[i]->vlan >= net->vlan)
+            net->vlan = vm->def->nets[i]->vlan;
+
+    if (qemuBuildHostNetStr(conn, net,
+                            "host_net_add ", ' ', net->vlan, -1, &cmd) < 0)
+        return -1;
+
+    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
+        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         _("failed to add network backend with '%s'"), cmd);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+
+    if (qemuBuildNicStr(conn, net,
+                        "pci_add pci_addr=auto ", ' ', net->vlan, &cmd) < 0) {
+        /* FIXME: try and remove the backend again */
+        return -1;
+    }
+
+    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
+        /* FIXME: try and remove the backend again */
+        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         _("failed to add NIC with '%s'"), cmd);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+
+    vm->def->nets[vm->def->nnets++] = net;
+
+    return 0;
+}
+
 static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                        virDomainObjPtr vm,
                                        virDomainDeviceDefPtr dev)
@@ -4617,6 +4695,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
                              virDomainDiskDeviceTypeToString(dev->data.disk->device));
             goto cleanup;
         }
+    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+        ret = qemudDomainAttachNetDevice(dom->conn, vm, dev, qemuCmdFlags);
     } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
                dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
                dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-- 
1.6.2.5


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]