On Thu, Feb 24, 2011 at 01:08:40PM +0900, KAMEZAWA Hiroyuki wrote:
>From b06da6d9b4ee996046af72a81c89b90852372e53 Mon Sep 17 00:00:00
2001
From: KAMEZAWA Hiroyuki <kamezawa(a)bluextal.(none)>
Date: Thu, 24 Feb 2011 13:08:54 +0900
Subject: [PATCH 2/2] libvirt/qemu : support attach/detach-interface --persistent with
qemu
Now, virsh attach/detach-interface have --persistent option for
updating inactive domain but it's only supported in Xen.
This patch adds support for qemu.
Changelog v1->v2:
- fixed TABs
- fixed header file, type of a function
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
---
src/conf/domain_conf.c | 50 ++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 3 ++
src/libvirt_private.syms | 2 +
src/qemu/qemu_driver.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b97c1f0..660573b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4924,6 +4924,56 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i)
}
}
+int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net)
Function duplicated.
+{
+ 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)
Function duplicated.
+{
+ 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 virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net)
Function duplicated.
+{
+ 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)
Function duplicated.
+{
+ 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);
prototype mismatch: int c file this function returns int.
+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 e75478a..00a240b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4097,6 +4097,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.
@@ -4105,6 +4121,7 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
virDomainDeviceDefPtr newdev)
{
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
/* At first, check device confliction */
switch(newdev->type) {
@@ -4131,6 +4148,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);
disk->dst -> net->mac or something else about net device.
+ 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"));
@@ -4145,6 +4178,7 @@ static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef,
{
int x;
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
switch(device->type) {
case VIR_DOMAIN_DEVICE_DISK:
@@ -4157,6 +4191,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
--
Thanks,
Hu Tao