From 3307d7228ea3c47884d626584db646d23a5a22ce Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa(a)bluextal.(none)>
Date: Wed, 23 Feb 2011 17:25:07 +0900
Subject: [PATCH 2/2] libvirt/qemu : allow persistent modification of netifs via
A(De)ttachDeviceFlags
This patch allows virsh attach/detach-interface --persistent...
with qemu. Xen supports this behavior now.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
---
src/conf/domain_conf.c | 25 ++++++++++++++++++++
src/conf/domain_conf.h | 3 ++
src/libvirt_private.syms | 2 +
src/qemu/qemu_driver.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b97c1f0..dcbf756 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4924,6 +4924,31 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i)
}
}
+int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net)
+{
+ if (VIR_REALLOC_N(def->nets, def->nnets) < 0)
+ return -1;
+ def->nets[def->nnets] = net;
+ def->nnets++;
+ return 0;
+}
+
+void virDomainNetRemove(virDomainDefPtr def, size_t i)
+{
+ if (def->nnets > 1) {
+ memmove(def->nets + i,
+ def->nets + i + 1,
+ sizeof(*def->nets) * (def->nnets - (i + 1)));
+ def->nnets--;
+ if (VIR_REALLOC_N(def->nets, def->nnets) < 0) {
+ /* ignore harmless */
+ }
+ } else {
+ VIR_FREE(def->nets);
+ def->nnets = 0;
+ }
+}
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 30aeccc..396dfbc 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1270,6 +1270,9 @@ int virDomainDiskDefAssignAddress(virCapsPtr caps,
virDomainDiskDefPtr def);
void virDomainDiskRemove(virDomainDefPtr def, size_t i);
+void virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
+void virDomainNetRemove(virDomainDefPtr def, size_t i);
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller);
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 797a670..eef5266 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -245,6 +245,8 @@ virDomainDiskIoTypeToString;
virDomainDiskRemove;
virDomainDiskTypeFromString;
virDomainDiskTypeToString;
+virDomainNetInsert;
+virDomainNetRemove;
virDomainFSDefFree;
virDomainFindByID;
virDomainFindByName;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 703f86a..ab697cd 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4094,6 +4094,22 @@ static int qemuDomainFindDiskByName(virDomainDefPtr vmdef, const
char *name)
}
return -1;
}
+
+static int qemuDomainFindNetByName(virDomainDefPtr vmdef,
+ const unsigned char *mac, const char *ifname)
+{
+ virDomainNetDefPtr net;
+ int i;
+
+ for (i = 0; i < vmdef->nnets; i++) {
+ net = vmdef->nets[i];
+ if (!strcmp((char*)net->mac, (char*)mac))
+ return i;
+ if (ifname && !strcmp((char*)net->ifname, (char*)ifname))
+ return i;
+ }
+ return -1;
+}
/*
* Attach a device given by XML, the change will be persistent
* and domain XML definition file is updated.
@@ -4102,6 +4118,7 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
virDomainDeviceDefPtr newdev)
{
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
/* At first, check device confliction */
switch(newdev->type) {
@@ -4128,6 +4145,22 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
}
newdev->data.disk = NULL;
break;
+ case VIR_DOMAIN_DEVICE_NET:
+ net =
newdev->data.net;
+ if (qemuDomainFindNetByName(vmdef, net->mac, net->ifname) >= 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("target %s already exists."), disk->dst);
+ return -1;
+ }
+
+ if (virDomainNetInsert(vmdef, net)) {
+ virReportOOMError();
+ return -1;
+ }
+ /* always PCI ? */
+ qemuDomainAssignPCIAddresses(vmdef);
+
newdev->data.net = NULL;
+ break;
default:
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("Sorry, the device is not suppored for now"));
@@ -4142,6 +4175,7 @@ static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef,
{
int x;
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
switch(device->type) {
case VIR_DOMAIN_DEVICE_DISK:
@@ -4154,6 +4188,29 @@ static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef,
}
virDomainDiskRemove(vmdef, x);
break;
+ case VIR_DOMAIN_DEVICE_NET:
+ net =
device->data.net;
+ /* need to find mac address */
+ if (net->ifname == NULL && strlen((char*)net->mac) == 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("interface mac or name must be specified."));
+ return -1;
+ }
+ net =
device->data.net;
+ x = qemuDomainFindNetByName(vmdef, net->mac, net->ifname);
+ if (x < 0) {
+ if (net->ifname)
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("interface mac: %s name: %s doesn't exist."),
+ net->mac, net->ifname);
+ else
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("interface mac: %s doesn't exist."),
+ net->mac);
+ return -1;
+ }
+ virDomainNetRemove(vmdef, x);
+ break;
default:
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("Sorry, the device is not suppored for now"));
--
1.7.1