mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 09:17:52 +03:00
802.1Qbg: use pre-associate state at beginning of inc. migr
This patch introduces the usage of the pre-associate state of the IEEE 802.1Qbg standard on incoming VM migration on the target host. It is in response to bugzilla entry 632750. https://bugzilla.redhat.com/show_bug.cgi?id=632750 For being able to differentiate the exact reason as to why a macvtap device is being created, either due to a VM creation or an incoming VM migration, I needed to pass that reason as a parameter from wherever qemudStartVMDaemon is being called in order to determine whether to send an ASSOCIATE (VM creation) or a PRE-ASSOCIATE (incoming VM migration) towards lldpad. I am also fixing a problem with the virsh domainxml-to-native call on the way. Gerhard successfully tested the patch with a recent blade network 802.1Qbg-compliant switch. The patch should not have any side-effects on the 802.1Qbh support in libvirt, but Roopa (cc'ed) may want to verify this.
This commit is contained in:
parent
d7e2b2b4eb
commit
c2b38277b3
@ -1,5 +1,9 @@
|
||||
#
|
||||
|
||||
# macvtap.h
|
||||
openMacvtapTap;
|
||||
delMacvtap;
|
||||
openMacvtapTap;
|
||||
virVMOperationTypeFromString;
|
||||
virVMOperationTypeToString;
|
||||
vpAssociatePortProfileId;
|
||||
vpDisassociatePortProfileId;
|
||||
|
@ -1642,7 +1642,8 @@ qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
unsigned long long qemuCmdFlags,
|
||||
const unsigned char *vmuuid)
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmop)
|
||||
{
|
||||
int rc;
|
||||
#if WITH_MACVTAP
|
||||
@ -1656,7 +1657,8 @@ qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
|
||||
rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
|
||||
net->data.direct.mode, vnet_hdr, vmuuid,
|
||||
&net->data.direct.virtPortProfile, &res_ifname);
|
||||
&net->data.direct.virtPortProfile, &res_ifname,
|
||||
vmop);
|
||||
if (rc >= 0) {
|
||||
VIR_FREE(net->ifname);
|
||||
net->ifname = res_ifname;
|
||||
@ -3953,7 +3955,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
||||
int **vmfds,
|
||||
int *nvmfds,
|
||||
const char *migrateFrom,
|
||||
virDomainSnapshotObjPtr current_snapshot)
|
||||
virDomainSnapshotObjPtr current_snapshot,
|
||||
enum virVMOperationType vmop)
|
||||
{
|
||||
int i;
|
||||
char memory[50];
|
||||
@ -4796,7 +4799,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
||||
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
int tapfd = qemudPhysIfaceConnect(conn, driver, net,
|
||||
qemuCmdFlags,
|
||||
def->uuid);
|
||||
def->uuid,
|
||||
vmop);
|
||||
if (tapfd < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
# include "cpu_conf.h"
|
||||
# include "driver.h"
|
||||
# include "bitmap.h"
|
||||
# include "macvtap.h"
|
||||
|
||||
# define qemudDebug(fmt, ...) do {} while(0)
|
||||
|
||||
@ -238,7 +239,8 @@ int qemudBuildCommandLine (virConnectPtr conn,
|
||||
int **vmfds,
|
||||
int *nvmfds,
|
||||
const char *migrateFrom,
|
||||
virDomainSnapshotObjPtr current_snapshot)
|
||||
virDomainSnapshotObjPtr current_snapshot,
|
||||
enum virVMOperationType vmop)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
|
||||
/* With vlan == -1, use netdev syntax, else old hostnet */
|
||||
@ -317,7 +319,8 @@ int qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
unsigned long long qemuCmdFlags,
|
||||
const unsigned char *vmuuid);
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmop);
|
||||
|
||||
int qemudProbeMachineTypes (const char *binary,
|
||||
virCapsGuestMachinePtr **machines,
|
||||
|
@ -163,7 +163,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
||||
const char *migrateFrom,
|
||||
bool start_paused,
|
||||
int stdin_fd,
|
||||
const char *stdin_path);
|
||||
const char *stdin_path,
|
||||
enum virVMOperationType vmop);
|
||||
|
||||
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
@ -3864,7 +3865,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
||||
const char *migrateFrom,
|
||||
bool start_paused,
|
||||
int stdin_fd,
|
||||
const char *stdin_path) {
|
||||
const char *stdin_path,
|
||||
enum virVMOperationType vmop) {
|
||||
const char **argv = NULL, **tmp;
|
||||
const char **progenv = NULL;
|
||||
int i, ret, runflags;
|
||||
@ -4065,7 +4067,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
||||
if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
|
||||
priv->monJSON, qemuCmdFlags, &argv, &progenv,
|
||||
&vmfds, &nvmfds, migrateFrom,
|
||||
vm->current_snapshot) < 0)
|
||||
vm->current_snapshot, vmop) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
|
||||
@ -4879,7 +4881,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
|
||||
|
||||
if (qemudStartVMDaemon(conn, driver, vm, NULL,
|
||||
(flags & VIR_DOMAIN_START_PAUSED) != 0,
|
||||
-1, NULL) < 0) {
|
||||
-1, NULL, VIR_VM_OP_CREATE) < 0) {
|
||||
qemuDomainStartAudit(vm, "booted", false);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
@ -7015,7 +7017,8 @@ qemudDomainSaveImageStartVM(virConnectPtr conn,
|
||||
}
|
||||
|
||||
/* Set the migration source and start it up. */
|
||||
ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path);
|
||||
ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path,
|
||||
VIR_VM_OP_RESTORE);
|
||||
|
||||
if (intermediate_pid != -1) {
|
||||
/* Wait for intermediate process to exit */
|
||||
@ -7334,14 +7337,15 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
|
||||
if (!def)
|
||||
goto cleanup;
|
||||
|
||||
/* Since we're just exporting args, we can't do bridge/network
|
||||
* setups, since libvirt will normally create TAP devices
|
||||
/* Since we're just exporting args, we can't do bridge/network/direct
|
||||
* setups, since libvirt will normally create TAP/macvtap devices
|
||||
* directly. We convert those configs into generic 'ethernet'
|
||||
* config and assume the user has suitable 'ifup-qemu' scripts
|
||||
*/
|
||||
for (i = 0 ; i < def->nnets ; i++) {
|
||||
virDomainNetDefPtr net = def->nets[i];
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
|
||||
net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
VIR_FREE(net->data.network.name);
|
||||
|
||||
memset(net, 0, sizeof *net);
|
||||
@ -7397,7 +7401,8 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
|
||||
&monConfig, 0, qemuCmdFlags,
|
||||
&retargv, &retenv,
|
||||
NULL, NULL, /* Don't want it to create TAP devices */
|
||||
NULL, NULL) < 0) {
|
||||
NULL, NULL,
|
||||
VIR_VM_OP_NO_OP) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -7484,7 +7489,8 @@ static int qemudDomainObjStart(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1, NULL);
|
||||
ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1, NULL,
|
||||
VIR_VM_OP_CREATE);
|
||||
qemuDomainStartAudit(vm, "booted", ret >= 0);
|
||||
if (ret >= 0) {
|
||||
virDomainEventPtr event =
|
||||
@ -8327,7 +8333,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
|
||||
|
||||
if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
|
||||
qemuCmdFlags,
|
||||
vm->def->uuid)) < 0)
|
||||
vm->def->uuid,
|
||||
VIR_VM_OP_CREATE)) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -11001,7 +11008,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
|
||||
* -incoming unix:/path/to/file or exec:nc -U /path/to/file
|
||||
*/
|
||||
internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, true,
|
||||
-1, NULL);
|
||||
-1, NULL, VIR_VM_OP_MIGRATE_IN_START);
|
||||
VIR_FREE(migrateFrom);
|
||||
if (internalret < 0) {
|
||||
qemuDomainStartAudit(vm, "migrated", false);
|
||||
@ -11247,7 +11254,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
|
||||
*/
|
||||
snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port);
|
||||
if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, true,
|
||||
-1, NULL) < 0) {
|
||||
-1, NULL, VIR_VM_OP_MIGRATE_IN_START) < 0) {
|
||||
qemuDomainStartAudit(vm, "migrated", false);
|
||||
/* Note that we don't set an error here because qemudStartVMDaemon
|
||||
* should have already done that.
|
||||
@ -11862,6 +11869,41 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
qemudVPAssociatePortProfiles(virDomainDefPtr def) {
|
||||
int i;
|
||||
int last_good_net = -1;
|
||||
virDomainNetDefPtr net;
|
||||
|
||||
for (i = 0; i < def->nnets; i++) {
|
||||
net = def->nets[i];
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
if (vpAssociatePortProfileId(net->ifname,
|
||||
net->mac,
|
||||
net->data.direct.linkdev,
|
||||
&net->data.direct.virtPortProfile,
|
||||
def->uuid,
|
||||
VIR_VM_OP_MIGRATE_IN_FINISH) != 0)
|
||||
goto err_exit;
|
||||
}
|
||||
last_good_net = i;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_exit:
|
||||
for (i = 0; i < last_good_net; i++) {
|
||||
net = def->nets[i];
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
vpDisassociatePortProfileId(net->ifname,
|
||||
net->mac,
|
||||
net->data.direct.linkdev,
|
||||
&net->data.direct.virtPortProfile,
|
||||
VIR_VM_OP_MIGRATE_IN_FINISH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish is the third and final step, and it runs on the destination host. */
|
||||
static virDomainPtr
|
||||
qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
@ -11922,6 +11964,8 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qemudVPAssociatePortProfiles(vm->def);
|
||||
|
||||
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
||||
if (vm->persistent)
|
||||
newVM = 0;
|
||||
@ -12814,7 +12858,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
||||
goto endjob;
|
||||
|
||||
rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL,
|
||||
false, -1, NULL);
|
||||
false, -1, NULL, VIR_VM_OP_CREATE);
|
||||
qemuDomainStartAudit(vm, "from-snapshot", rc >= 0);
|
||||
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
|
||||
goto endjob;
|
||||
|
@ -77,9 +77,21 @@
|
||||
# define LLDPAD_PID_FILE "/var/run/lldpad.pid"
|
||||
|
||||
|
||||
VIR_ENUM_IMPL(virVMOperation, VIR_VM_OP_LAST,
|
||||
"create",
|
||||
"save",
|
||||
"restore",
|
||||
"destroy",
|
||||
"migrate out",
|
||||
"migrate in start",
|
||||
"migrate in finish",
|
||||
"no-op")
|
||||
|
||||
|
||||
enum virVirtualPortOp {
|
||||
ASSOCIATE = 0x1,
|
||||
DISASSOCIATE = 0x2,
|
||||
PREASSOCIATE = 0x3,
|
||||
};
|
||||
|
||||
|
||||
@ -551,7 +563,8 @@ openMacvtapTap(const char *tgifname,
|
||||
int vnet_hdr,
|
||||
const unsigned char *vmuuid,
|
||||
virVirtualPortProfileParamsPtr virtPortProfile,
|
||||
char **res_ifname)
|
||||
char **res_ifname,
|
||||
enum virVMOperationType vmOp)
|
||||
{
|
||||
const char *type = "macvtap";
|
||||
int c, rc;
|
||||
@ -563,6 +576,8 @@ openMacvtapTap(const char *tgifname,
|
||||
|
||||
*res_ifname = NULL;
|
||||
|
||||
VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp));
|
||||
|
||||
if (tgifname) {
|
||||
if(ifaceGetIndex(false, tgifname, &ifindex) == 0) {
|
||||
if (STRPREFIX(tgifname,
|
||||
@ -601,7 +616,7 @@ create_name:
|
||||
macaddress,
|
||||
linkdev,
|
||||
virtPortProfile,
|
||||
vmuuid) != 0) {
|
||||
vmuuid, vmOp) != 0) {
|
||||
rc = -1;
|
||||
goto link_del_exit;
|
||||
}
|
||||
@ -634,7 +649,8 @@ disassociate_exit:
|
||||
vpDisassociatePortProfileId(cr_ifname,
|
||||
macaddress,
|
||||
linkdev,
|
||||
virtPortProfile);
|
||||
virtPortProfile,
|
||||
vmOp);
|
||||
|
||||
link_del_exit:
|
||||
link_del(cr_ifname);
|
||||
@ -662,7 +678,8 @@ delMacvtap(const char *ifname,
|
||||
if (ifname) {
|
||||
vpDisassociatePortProfileId(ifname, macaddr,
|
||||
linkdev,
|
||||
virtPortProfile);
|
||||
virtPortProfile,
|
||||
VIR_VM_OP_DESTROY);
|
||||
link_del(ifname);
|
||||
}
|
||||
}
|
||||
@ -1320,6 +1337,9 @@ doPortProfileOp8021Qbg(const char *ifname,
|
||||
portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
|
||||
|
||||
switch (virtPortOp) {
|
||||
case PREASSOCIATE:
|
||||
op = PORT_REQUEST_PREASSOCIATE;
|
||||
break;
|
||||
case ASSOCIATE:
|
||||
op = PORT_REQUEST_ASSOCIATE;
|
||||
break;
|
||||
@ -1484,6 +1504,7 @@ err_exit:
|
||||
* @macvtap_ifname: The name of the macvtap device
|
||||
* @virtPort: pointer to the object holding port profile parameters
|
||||
* @vmuuid : the UUID of the virtual machine
|
||||
* @vmOp : The VM operation (i.e., create, no-op)
|
||||
*
|
||||
* Associate a port on a swtich with a profile. This function
|
||||
* may notify a kernel driver or an external daemon to run
|
||||
@ -1499,13 +1520,19 @@ vpAssociatePortProfileId(const char *macvtap_ifname,
|
||||
const unsigned char *macvtap_macaddr,
|
||||
const char *linkdev,
|
||||
const virVirtualPortProfileParamsPtr virtPort,
|
||||
const unsigned char *vmuuid)
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmOp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
|
||||
virtPort, macvtap_ifname);
|
||||
|
||||
VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp));
|
||||
|
||||
if (vmOp == VIR_VM_OP_NO_OP)
|
||||
return 0;
|
||||
|
||||
switch (virtPort->virtPortType) {
|
||||
case VIR_VIRTUALPORT_NONE:
|
||||
case VIR_VIRTUALPORT_TYPE_LAST:
|
||||
@ -1513,10 +1540,16 @@ vpAssociatePortProfileId(const char *macvtap_ifname,
|
||||
|
||||
case VIR_VIRTUALPORT_8021QBG:
|
||||
rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
|
||||
virtPort, ASSOCIATE);
|
||||
virtPort,
|
||||
(vmOp == VIR_VM_OP_MIGRATE_IN_START)
|
||||
? PREASSOCIATE
|
||||
: ASSOCIATE);
|
||||
break;
|
||||
|
||||
case VIR_VIRTUALPORT_8021QBH:
|
||||
/* avoid associating twice */
|
||||
if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
|
||||
break;
|
||||
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
|
||||
vmuuid,
|
||||
ASSOCIATE);
|
||||
@ -1542,13 +1575,16 @@ int
|
||||
vpDisassociatePortProfileId(const char *macvtap_ifname,
|
||||
const unsigned char *macvtap_macaddr,
|
||||
const char *linkdev,
|
||||
const virVirtualPortProfileParamsPtr virtPort)
|
||||
const virVirtualPortProfileParamsPtr virtPort,
|
||||
enum virVMOperationType vmOp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
|
||||
virtPort, macvtap_ifname);
|
||||
|
||||
VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp));
|
||||
|
||||
switch (virtPort->virtPortType) {
|
||||
case VIR_VIRTUALPORT_NONE:
|
||||
case VIR_VIRTUALPORT_TYPE_LAST:
|
||||
@ -1560,6 +1596,9 @@ vpDisassociatePortProfileId(const char *macvtap_ifname,
|
||||
break;
|
||||
|
||||
case VIR_VIRTUALPORT_8021QBH:
|
||||
/* avoid disassociating twice */
|
||||
if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
|
||||
break;
|
||||
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
|
||||
NULL,
|
||||
DISASSOCIATE);
|
||||
|
@ -62,6 +62,19 @@ struct _virVirtualPortProfileParams {
|
||||
|
||||
# include "internal.h"
|
||||
|
||||
enum virVMOperationType {
|
||||
VIR_VM_OP_CREATE,
|
||||
VIR_VM_OP_SAVE,
|
||||
VIR_VM_OP_RESTORE,
|
||||
VIR_VM_OP_DESTROY,
|
||||
VIR_VM_OP_MIGRATE_OUT,
|
||||
VIR_VM_OP_MIGRATE_IN_START,
|
||||
VIR_VM_OP_MIGRATE_IN_FINISH,
|
||||
VIR_VM_OP_NO_OP,
|
||||
|
||||
VIR_VM_OP_LAST
|
||||
};
|
||||
|
||||
int openMacvtapTap(const char *ifname,
|
||||
const unsigned char *macaddress,
|
||||
const char *linkdev,
|
||||
@ -69,7 +82,8 @@ int openMacvtapTap(const char *ifname,
|
||||
int vnet_hdr,
|
||||
const unsigned char *vmuuid,
|
||||
virVirtualPortProfileParamsPtr virtPortProfile,
|
||||
char **res_ifname);
|
||||
char **res_ifname,
|
||||
enum virVMOperationType vmop);
|
||||
|
||||
void delMacvtap(const char *ifname,
|
||||
const unsigned char *macaddress,
|
||||
@ -86,13 +100,16 @@ int vpAssociatePortProfileId(const char *macvtap_ifname,
|
||||
const unsigned char *macvtap_macaddr,
|
||||
const char *linkdev,
|
||||
const virVirtualPortProfileParamsPtr virtPort,
|
||||
const unsigned char *vmuuid);
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmOp);
|
||||
|
||||
int vpDisassociatePortProfileId(const char *macvtap_ifname,
|
||||
const unsigned char *macvtap_macaddr,
|
||||
const char *linkdev,
|
||||
const virVirtualPortProfileParamsPtr virtPort);
|
||||
const virVirtualPortProfileParamsPtr virtPort,
|
||||
enum virVMOperationType vmOp);
|
||||
|
||||
VIR_ENUM_DECL(virVirtualPort)
|
||||
VIR_ENUM_DECL(virVMOperation)
|
||||
|
||||
#endif /* __UTIL_MACVTAP_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user