From 803cef98bc31a090b876f1774648e317401c806a Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
Date: Thu, 3 Mar 2011 10:01:39 +0900
Subject: [PATCH 5/5] libvirt/qemu - allow modification nics of inactive domain
This patch allows --persistent modification of nics with inactive
domains in qemu.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
---
src/conf/domain_conf.c | 24 +++++++++++++++++++++
src/conf/domain_conf.h | 3 ++
src/libvirt_private.syms | 2 +
src/qemu/qemu_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4730683..8ef143c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4928,6 +4928,30 @@ 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..d7d973e 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);
+int 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 5e63a12..35b4e30 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -249,6 +249,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 4df6bf9..9f14880 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4111,6 +4111,21 @@ static int qemuDomainFindDiskByName(virDomainDefPtr vmdef, const
char *name)
}
return -1;
}
+
+static int qemuDomainFindNetByName(virDomainDefPtr vmdef,
+ const unsigned char *mac)
+{
+ virDomainNetDefPtr net;
+ int i;
+
+ for (i = 0; i < vmdef->nnets; i++) {
+ net = vmdef->nets[i];
+ /* For now, only MAC can be the key */
+ if (STREQ((char*)net->mac, (char*)mac))
+ return i;
+ }
+ return -1;
+}
/*
* Attach a device given by XML, the change will be persistent
* and domain XML definition file is updated.
@@ -4119,6 +4134,7 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
virDomainDeviceDefPtr newdev)
{
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
/* At first, check device confliction */
switch(newdev->type) {
@@ -4138,6 +4154,23 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
return -1;
newdev->data.disk = NULL;
break;
+ case VIR_DOMAIN_DEVICE_NET:
+ net =
newdev->data.net;
+ if (qemuDomainFindNetByName(vmdef, net->mac) >= 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("target %s already exists."), net->mac);
+ return -1;
+ }
+
+ if (virDomainNetInsert(vmdef, net)) {
+ virReportOOMError();
+ return -1;
+ }
+ /* always PCI ? */
+ if (qemuDomainAssignPCIAddresses(vmdef) < 0)
+ return -1;
+
newdev->data.net = NULL;
+ break;
default:
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("Sorry, the device is not suppored for now"));
@@ -4152,6 +4185,7 @@ static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef,
{
int x;
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
switch(device->type) {
case VIR_DOMAIN_DEVICE_DISK:
@@ -4164,6 +4198,23 @@ 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);
+ if (x < 0) {
+ 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.4.1