2012-02-10 21:09:00 +00:00
|
|
|
/*
|
2013-10-05 19:41:44 +00:00
|
|
|
* Copyright (C) 2013 Red Hat, Inc.
|
2012-02-10 21:09:00 +00:00
|
|
|
* Copyright (C) 2012 Nicira, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2012-02-10 21:09:00 +00:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Dan Wendlandt <dan@nicira.com>
|
|
|
|
* Kyle Mestery <kmestery@cisco.com>
|
|
|
|
* Ansis Atteka <aatteka@nicira.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "virnetdevopenvswitch.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-02-10 21:09:00 +00:00
|
|
|
#include "virmacaddr.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
util: don't fail if no PortData is found while getting migrateData
Introduced by f6a2f97e
Problem Description:
After multiple times of migrating a domain, which has an ovs interface with no portData set,
with non-shared disk, nbd ports got overflowed.
The steps to reproduce the problem:
1 define and start a domain with its network configured as:
<interface type='bridge'>
<source bridge='br0'/>
<virtualport type='openvswitch'>
</virtualport>
<model type='virtio'/>
<driver name='vhost' queues='4'/>
</interface>
2 do not set the network's portData.
3 migrate(ToURI2) it with flag 91(1011011), which means:
VIR_MIGRATE_LIVE
VIR_MIGRATE_PEER2PEER
VIR_MIGRATE_PERSIST_DEST
VIR_MIGRATE_UNDEFINE_SOURCE
VIR_MIGRATE_NON_SHARED_DISK
4 migrate success, but we got an error log in libvirtd.log:
error : virCommandWait:2423 : internal error: Child process (ovs-vsctl --timeout=5 get Interface
vnet1 external_ids:PortData) unexpected exit status 1: ovs-vsctl: no key "PortData" in Interface
record "vnet1" column external_ids
5 migrate it back, migrate it , migrate it back, .......
6 nbd port got overflowed.
The reasons for the problem is :
1 virNetDevOpenvswitchGetMigrateData() takes it as wrong if no portData is available for the ovs
interface of a domain. (We think it's not appropriate, as portData is just OPTIONAL)
2 in func qemuMigrationBakeCookie(), it fails in qemuMigrationCookieAddNetwork(), and returns with -1.
qemuMigrationCookieAddNBD() is not called thereafter, and mig->nbd is still NULL.
3 However, qemuMigrationRun() just *WARN* if qemuMigrationBakeCookie() fails, migration still successes.
cookie is NULL, it's not baked on the src side.
4 On the destination side, it would alloc a port first and then free the nbd port in COOKIE.
But the cookie is NULL due to qemuMigrationCookieAddNetwork() failure at src side. thus the nbd port
is not freed.
In this patch, we add "--if-exists" option to make ovs-vsctl not raise error if there's no portData available.
Further more, because portData may be NULL in the cookie at the dest side, check it before setting portData.
Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Signed-off-by: Zhang Bo <oscar.zhangbo@huawei.com>
2015-03-05 02:01:50 +00:00
|
|
|
#include "virlog.h"
|
2012-02-10 21:09:00 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
util: don't fail if no PortData is found while getting migrateData
Introduced by f6a2f97e
Problem Description:
After multiple times of migrating a domain, which has an ovs interface with no portData set,
with non-shared disk, nbd ports got overflowed.
The steps to reproduce the problem:
1 define and start a domain with its network configured as:
<interface type='bridge'>
<source bridge='br0'/>
<virtualport type='openvswitch'>
</virtualport>
<model type='virtio'/>
<driver name='vhost' queues='4'/>
</interface>
2 do not set the network's portData.
3 migrate(ToURI2) it with flag 91(1011011), which means:
VIR_MIGRATE_LIVE
VIR_MIGRATE_PEER2PEER
VIR_MIGRATE_PERSIST_DEST
VIR_MIGRATE_UNDEFINE_SOURCE
VIR_MIGRATE_NON_SHARED_DISK
4 migrate success, but we got an error log in libvirtd.log:
error : virCommandWait:2423 : internal error: Child process (ovs-vsctl --timeout=5 get Interface
vnet1 external_ids:PortData) unexpected exit status 1: ovs-vsctl: no key "PortData" in Interface
record "vnet1" column external_ids
5 migrate it back, migrate it , migrate it back, .......
6 nbd port got overflowed.
The reasons for the problem is :
1 virNetDevOpenvswitchGetMigrateData() takes it as wrong if no portData is available for the ovs
interface of a domain. (We think it's not appropriate, as portData is just OPTIONAL)
2 in func qemuMigrationBakeCookie(), it fails in qemuMigrationCookieAddNetwork(), and returns with -1.
qemuMigrationCookieAddNBD() is not called thereafter, and mig->nbd is still NULL.
3 However, qemuMigrationRun() just *WARN* if qemuMigrationBakeCookie() fails, migration still successes.
cookie is NULL, it's not baked on the src side.
4 On the destination side, it would alloc a port first and then free the nbd port in COOKIE.
But the cookie is NULL due to qemuMigrationCookieAddNetwork() failure at src side. thus the nbd port
is not freed.
In this patch, we add "--if-exists" option to make ovs-vsctl not raise error if there's no portData available.
Further more, because portData may be NULL in the cookie at the dest side, check it before setting portData.
Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Signed-off-by: Zhang Bo <oscar.zhangbo@huawei.com>
2015-03-05 02:01:50 +00:00
|
|
|
VIR_LOG_INIT("util.netdevopenvswitch");
|
|
|
|
|
2012-02-10 21:09:00 +00:00
|
|
|
/**
|
|
|
|
* virNetDevOpenvswitchAddPort:
|
|
|
|
* @brname: the bridge name
|
|
|
|
* @ifname: the network interface name
|
|
|
|
* @macaddr: the mac address of the virtual interface
|
2012-03-07 07:15:36 +00:00
|
|
|
* @vmuuid: the Domain UUID that has this interface
|
2012-02-10 21:09:00 +00:00
|
|
|
* @ovsport: the ovs specific fields
|
|
|
|
*
|
|
|
|
* Add an interface to the OVS bridge
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of failure.
|
|
|
|
*/
|
|
|
|
int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
|
2013-10-05 19:41:44 +00:00
|
|
|
const virMacAddr *macaddr,
|
2012-03-07 07:15:36 +00:00
|
|
|
const unsigned char *vmuuid,
|
2012-08-17 04:04:54 +00:00
|
|
|
virNetDevVPortProfilePtr ovsport,
|
|
|
|
virNetDevVlanPtr virtVlan)
|
2012-02-10 21:09:00 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i = 0;
|
2012-02-10 21:09:00 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
char macaddrstr[VIR_MAC_STRING_BUFLEN];
|
2012-03-07 07:15:36 +00:00
|
|
|
char ifuuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
char vmuuidstr[VIR_UUID_STRING_BUFLEN];
|
2012-02-10 21:09:00 +00:00
|
|
|
char *attachedmac_ex_id = NULL;
|
|
|
|
char *ifaceid_ex_id = NULL;
|
|
|
|
char *profile_ex_id = NULL;
|
2012-03-07 07:15:36 +00:00
|
|
|
char *vmid_ex_id = NULL;
|
2012-08-29 18:44:36 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2012-02-10 21:09:00 +00:00
|
|
|
|
|
|
|
virMacAddrFormat(macaddr, macaddrstr);
|
2012-07-25 01:14:41 +00:00
|
|
|
virUUIDFormat(ovsport->interfaceID, ifuuidstr);
|
2012-03-07 07:15:36 +00:00
|
|
|
virUUIDFormat(vmuuid, vmuuidstr);
|
2012-02-10 21:09:00 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
|
|
|
|
macaddrstr) < 0)
|
2013-07-04 10:17:18 +00:00
|
|
|
goto cleanup;
|
2012-02-10 21:09:00 +00:00
|
|
|
if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
|
2012-03-07 07:15:36 +00:00
|
|
|
ifuuidstr) < 0)
|
2013-07-04 10:17:18 +00:00
|
|
|
goto cleanup;
|
2012-03-07 07:15:36 +00:00
|
|
|
if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"",
|
|
|
|
vmuuidstr) < 0)
|
2013-07-04 10:17:18 +00:00
|
|
|
goto cleanup;
|
2012-07-25 01:14:41 +00:00
|
|
|
if (ovsport->profileID[0] != '\0') {
|
2012-02-10 21:09:00 +00:00
|
|
|
if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
|
2012-07-25 01:14:41 +00:00
|
|
|
ovsport->profileID) < 0)
|
2013-07-04 10:17:18 +00:00
|
|
|
goto cleanup;
|
2012-02-10 21:09:00 +00:00
|
|
|
}
|
2012-08-29 18:44:36 +00:00
|
|
|
|
2013-06-25 15:42:13 +00:00
|
|
|
cmd = virCommandNew(OVSVSCTL);
|
|
|
|
|
2014-07-14 10:37:50 +00:00
|
|
|
virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port",
|
|
|
|
ifname, "--", "add-port", brname, ifname, NULL);
|
2013-06-25 15:42:13 +00:00
|
|
|
|
2012-08-29 18:44:36 +00:00
|
|
|
if (virtVlan && virtVlan->nTags > 0) {
|
2012-08-17 04:04:54 +00:00
|
|
|
|
2013-06-25 15:42:13 +00:00
|
|
|
switch (virtVlan->nativeMode) {
|
|
|
|
case VIR_NATIVE_VLAN_MODE_TAGGED:
|
|
|
|
virCommandAddArg(cmd, "vlan_mode=native-tagged");
|
|
|
|
virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag);
|
|
|
|
break;
|
|
|
|
case VIR_NATIVE_VLAN_MODE_UNTAGGED:
|
|
|
|
virCommandAddArg(cmd, "vlan_mode=native-untagged");
|
|
|
|
virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag);
|
|
|
|
break;
|
|
|
|
case VIR_NATIVE_VLAN_MODE_DEFAULT:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-08-30 07:18:02 +00:00
|
|
|
if (virtVlan->trunk) {
|
2012-08-29 18:44:36 +00:00
|
|
|
virBufferAddLit(&buf, "trunk=");
|
2012-08-17 04:04:54 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Trunk ports have at least one VLAN. Do the first one
|
|
|
|
* outside the "for" loop so we can put a "," at the
|
|
|
|
* start of the for loop if there are more than one VLANs
|
|
|
|
* on this trunk port.
|
|
|
|
*/
|
2012-08-29 18:44:36 +00:00
|
|
|
virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);
|
2012-08-17 04:04:54 +00:00
|
|
|
|
|
|
|
for (i = 1; i < virtVlan->nTags; i++) {
|
2012-08-29 18:44:36 +00:00
|
|
|
virBufferAddLit(&buf, ",");
|
|
|
|
virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);
|
2012-08-17 04:04:54 +00:00
|
|
|
}
|
2013-06-25 15:42:13 +00:00
|
|
|
|
2014-06-27 08:40:15 +00:00
|
|
|
if (virBufferCheckError(&buf) < 0)
|
2013-07-04 10:17:18 +00:00
|
|
|
goto cleanup;
|
2013-06-25 15:42:13 +00:00
|
|
|
virCommandAddArg(cmd, virBufferCurrentContent(&buf));
|
2012-08-29 02:56:04 +00:00
|
|
|
} else if (virtVlan->nTags) {
|
2013-06-25 15:42:13 +00:00
|
|
|
virCommandAddArgFormat(cmd, "tag=%d", virtVlan->tag[0]);
|
2012-08-17 04:04:54 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-10 21:09:00 +00:00
|
|
|
|
2012-07-25 01:14:41 +00:00
|
|
|
if (ovsport->profileID[0] == '\0') {
|
2012-08-30 20:38:06 +00:00
|
|
|
virCommandAddArgList(cmd,
|
2012-02-10 21:09:00 +00:00
|
|
|
"--", "set", "Interface", ifname, attachedmac_ex_id,
|
|
|
|
"--", "set", "Interface", ifname, ifaceid_ex_id,
|
2012-03-07 07:15:36 +00:00
|
|
|
"--", "set", "Interface", ifname, vmid_ex_id,
|
2012-02-10 21:09:00 +00:00
|
|
|
"--", "set", "Interface", ifname,
|
|
|
|
"external-ids:iface-status=active",
|
|
|
|
NULL);
|
|
|
|
} else {
|
2012-08-30 20:38:06 +00:00
|
|
|
virCommandAddArgList(cmd,
|
2012-02-10 21:09:00 +00:00
|
|
|
"--", "set", "Interface", ifname, attachedmac_ex_id,
|
|
|
|
"--", "set", "Interface", ifname, ifaceid_ex_id,
|
2012-03-07 07:15:36 +00:00
|
|
|
"--", "set", "Interface", ifname, vmid_ex_id,
|
2012-02-10 21:09:00 +00:00
|
|
|
"--", "set", "Interface", ifname, profile_ex_id,
|
|
|
|
"--", "set", "Interface", ifname,
|
|
|
|
"external-ids:iface-status=active",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0) {
|
2014-11-28 08:37:42 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to add port %s to OVS bridge %s"),
|
|
|
|
ifname, brname);
|
2012-02-10 21:09:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-03-08 18:31:06 +00:00
|
|
|
ret = 0;
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-08-29 18:44:36 +00:00
|
|
|
virBufferFreeAndReset(&buf);
|
2012-03-08 18:31:06 +00:00
|
|
|
VIR_FREE(attachedmac_ex_id);
|
|
|
|
VIR_FREE(ifaceid_ex_id);
|
2012-03-07 07:15:36 +00:00
|
|
|
VIR_FREE(vmid_ex_id);
|
2012-03-08 18:31:06 +00:00
|
|
|
VIR_FREE(profile_ex_id);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
2012-02-10 21:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virNetDevOpenvswitchRemovePort:
|
|
|
|
* @ifname: the network interface name
|
|
|
|
*
|
|
|
|
* Deletes an interface from a OVS bridge
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of failure.
|
|
|
|
*/
|
|
|
|
int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const char *ifname)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
|
|
|
|
cmd = virCommandNew(OVSVSCTL);
|
2012-09-04 19:26:29 +00:00
|
|
|
virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port", ifname, NULL);
|
2012-02-10 21:09:00 +00:00
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0) {
|
2014-11-28 08:37:42 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to delete port %s from OVS"), ifname);
|
2012-02-10 21:09:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-10-01 15:18:21 +00:00
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-10-01 15:18:21 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virNetDevOpenvswitchGetMigrateData:
|
|
|
|
* @migrate: a pointer to store the data into, allocated by this function
|
|
|
|
* @ifname: name of the interface for which data is being migrated
|
|
|
|
*
|
|
|
|
* Allocates data to be migrated specific to Open vSwitch
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of failure
|
|
|
|
*/
|
|
|
|
int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
|
|
|
|
{
|
|
|
|
virCommandPtr cmd = NULL;
|
2016-01-27 09:35:17 +00:00
|
|
|
size_t len;
|
2012-10-01 15:18:21 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
util: don't fail if no PortData is found while getting migrateData
Introduced by f6a2f97e
Problem Description:
After multiple times of migrating a domain, which has an ovs interface with no portData set,
with non-shared disk, nbd ports got overflowed.
The steps to reproduce the problem:
1 define and start a domain with its network configured as:
<interface type='bridge'>
<source bridge='br0'/>
<virtualport type='openvswitch'>
</virtualport>
<model type='virtio'/>
<driver name='vhost' queues='4'/>
</interface>
2 do not set the network's portData.
3 migrate(ToURI2) it with flag 91(1011011), which means:
VIR_MIGRATE_LIVE
VIR_MIGRATE_PEER2PEER
VIR_MIGRATE_PERSIST_DEST
VIR_MIGRATE_UNDEFINE_SOURCE
VIR_MIGRATE_NON_SHARED_DISK
4 migrate success, but we got an error log in libvirtd.log:
error : virCommandWait:2423 : internal error: Child process (ovs-vsctl --timeout=5 get Interface
vnet1 external_ids:PortData) unexpected exit status 1: ovs-vsctl: no key "PortData" in Interface
record "vnet1" column external_ids
5 migrate it back, migrate it , migrate it back, .......
6 nbd port got overflowed.
The reasons for the problem is :
1 virNetDevOpenvswitchGetMigrateData() takes it as wrong if no portData is available for the ovs
interface of a domain. (We think it's not appropriate, as portData is just OPTIONAL)
2 in func qemuMigrationBakeCookie(), it fails in qemuMigrationCookieAddNetwork(), and returns with -1.
qemuMigrationCookieAddNBD() is not called thereafter, and mig->nbd is still NULL.
3 However, qemuMigrationRun() just *WARN* if qemuMigrationBakeCookie() fails, migration still successes.
cookie is NULL, it's not baked on the src side.
4 On the destination side, it would alloc a port first and then free the nbd port in COOKIE.
But the cookie is NULL due to qemuMigrationCookieAddNetwork() failure at src side. thus the nbd port
is not freed.
In this patch, we add "--if-exists" option to make ovs-vsctl not raise error if there's no portData available.
Further more, because portData may be NULL in the cookie at the dest side, check it before setting portData.
Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Signed-off-by: Zhang Bo <oscar.zhangbo@huawei.com>
2015-03-05 02:01:50 +00:00
|
|
|
cmd = virCommandNewArgList(OVSVSCTL, "--timeout=5", "--if-exists", "get", "Interface",
|
2012-10-01 15:18:21 +00:00
|
|
|
ifname, "external_ids:PortData", NULL);
|
|
|
|
|
|
|
|
virCommandSetOutputBuffer(cmd, migrate);
|
|
|
|
|
|
|
|
/* Run the command */
|
|
|
|
if (virCommandRun(cmd, NULL) < 0) {
|
2014-11-28 08:37:42 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to run command to get OVS port data for "
|
|
|
|
"interface %s"), ifname);
|
2012-10-01 15:18:21 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-01-26 18:25:17 +00:00
|
|
|
/* Wipeout the newline, if it exists */
|
2016-01-27 09:35:17 +00:00
|
|
|
len = strlen(*migrate);
|
|
|
|
if (len > 0)
|
|
|
|
(*migrate)[len - 1] = '\0';
|
2016-01-26 18:25:17 +00:00
|
|
|
|
2012-02-10 21:09:00 +00:00
|
|
|
ret = 0;
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-01-23 22:04:47 +00:00
|
|
|
virCommandFree(cmd);
|
2012-10-01 15:18:21 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2012-02-10 21:09:00 +00:00
|
|
|
|
2012-10-01 15:18:21 +00:00
|
|
|
/**
|
|
|
|
* virNetDevOpenvswitchSetMigrateData:
|
|
|
|
* @migrate: the data which was transferred during migration
|
|
|
|
* @ifname: the name of the interface the data is associated with
|
|
|
|
*
|
|
|
|
* Repopulates OVS per-port data on destination host
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of failure
|
|
|
|
*/
|
|
|
|
int virNetDevOpenvswitchSetMigrateData(char *migrate, const char *ifname)
|
|
|
|
{
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
util: don't fail if no PortData is found while getting migrateData
Introduced by f6a2f97e
Problem Description:
After multiple times of migrating a domain, which has an ovs interface with no portData set,
with non-shared disk, nbd ports got overflowed.
The steps to reproduce the problem:
1 define and start a domain with its network configured as:
<interface type='bridge'>
<source bridge='br0'/>
<virtualport type='openvswitch'>
</virtualport>
<model type='virtio'/>
<driver name='vhost' queues='4'/>
</interface>
2 do not set the network's portData.
3 migrate(ToURI2) it with flag 91(1011011), which means:
VIR_MIGRATE_LIVE
VIR_MIGRATE_PEER2PEER
VIR_MIGRATE_PERSIST_DEST
VIR_MIGRATE_UNDEFINE_SOURCE
VIR_MIGRATE_NON_SHARED_DISK
4 migrate success, but we got an error log in libvirtd.log:
error : virCommandWait:2423 : internal error: Child process (ovs-vsctl --timeout=5 get Interface
vnet1 external_ids:PortData) unexpected exit status 1: ovs-vsctl: no key "PortData" in Interface
record "vnet1" column external_ids
5 migrate it back, migrate it , migrate it back, .......
6 nbd port got overflowed.
The reasons for the problem is :
1 virNetDevOpenvswitchGetMigrateData() takes it as wrong if no portData is available for the ovs
interface of a domain. (We think it's not appropriate, as portData is just OPTIONAL)
2 in func qemuMigrationBakeCookie(), it fails in qemuMigrationCookieAddNetwork(), and returns with -1.
qemuMigrationCookieAddNBD() is not called thereafter, and mig->nbd is still NULL.
3 However, qemuMigrationRun() just *WARN* if qemuMigrationBakeCookie() fails, migration still successes.
cookie is NULL, it's not baked on the src side.
4 On the destination side, it would alloc a port first and then free the nbd port in COOKIE.
But the cookie is NULL due to qemuMigrationCookieAddNetwork() failure at src side. thus the nbd port
is not freed.
In this patch, we add "--if-exists" option to make ovs-vsctl not raise error if there's no portData available.
Further more, because portData may be NULL in the cookie at the dest side, check it before setting portData.
Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
Signed-off-by: Zhang Bo <oscar.zhangbo@huawei.com>
2015-03-05 02:01:50 +00:00
|
|
|
if (!migrate) {
|
|
|
|
VIR_DEBUG("No OVS port data for interface %s", ifname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-01 15:18:21 +00:00
|
|
|
cmd = virCommandNewArgList(OVSVSCTL, "--timeout=5", "set",
|
|
|
|
"Interface", ifname, NULL);
|
|
|
|
virCommandAddArgFormat(cmd, "external_ids:PortData=%s", migrate);
|
|
|
|
|
|
|
|
/* Run the command */
|
|
|
|
if (virCommandRun(cmd, NULL) < 0) {
|
2014-11-28 08:37:42 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to run command to set OVS port data for "
|
|
|
|
"interface %s"), ifname);
|
2012-10-01 15:18:21 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-01-23 22:04:47 +00:00
|
|
|
virCommandFree(cmd);
|
2012-10-01 15:18:21 +00:00
|
|
|
return ret;
|
2012-02-10 21:09:00 +00:00
|
|
|
}
|