Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/functional-networking.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas ${{ matrix.openstack_version }}
enable_plugin networking-bgpvpn https://github.com/openstack/networking-bgpvpn.git ${{ matrix.openstack_version }}
Q_ML2_PLUGIN_EXT_DRIVERS=qos,port_security,dns_domain_keywords
BGP_SCHEDULER_DRIVER=neutron_dynamic_routing.services.bgp.scheduler.bgp_dragent_scheduler.StaticScheduler

[[post-config|\$NEUTRON_CONF]]
[oslo_policy]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,94 +119,81 @@ func TestBGPAgentRUD(t *testing.T) {
// Create a BGP Speaker
bgpSpeaker, err := spk.CreateBGPSpeaker(t, client)
th.AssertNoErr(t, err)

// List BGP Speaker-Agent associations
pages, err := agents.ListDRAgentHostingBGPSpeakers(client, bgpSpeaker.ID).AllPages(context.TODO())
th.AssertNoErr(t, err)
bgpAgents, err := agents.ExtractAgents(pages)
th.AssertNoErr(t, err)
th.AssertIntGreaterOrEqual(t, len(bgpAgents), 1)

// List the BGP Agents that accommodate the BGP Speaker
err = tools.WaitForTimeout(
func(ctx context.Context) (bool, error) {
flag := true
for _, agt := range bgpAgents {
t.Logf("BGP Speaker %s has been scheduled to agent %s", bgpSpeaker.ID, agt.ID)
bgpAgent, err := agents.Get(ctx, client, agt.ID).Extract()
th.AssertNoErr(t, err)
numOfSpeakers := int(bgpAgent.Configurations["bgp_speakers"].(float64))
flag = flag && (numOfSpeakers == 1)
}
return flag, nil
}, timeout)
bgpAgentsForSpeaker, err := agents.ExtractAgents(pages)
th.AssertNoErr(t, err)

// List the BGP speakers on the first agent
bgpAgent, err := agents.Get(context.TODO(), client, bgpAgents[0].ID).Extract()
th.AssertNoErr(t, err)
agentConf := bgpAgent.Configurations
numOfSpeakers := int(agentConf["bgp_speakers"].(float64))
t.Logf("Agent %s has %d speaker(s)", bgpAgents[0].ID, numOfSpeakers)
// If there are no associations, we can assume the static scheduler is in
// effect and we must manually associate/disassociate the speaker from the
// agent.
//
// https://docs.openstack.org/neutron-dynamic-routing/latest/admin/agent-scheduler.html
doManualAssignment := len(bgpAgentsForSpeaker) == 0
var agentID string

pages, err = agents.ListBGPSpeakers(client, bgpAgents[0].ID).AllPages(context.TODO())
th.AssertNoErr(t, err)
allSpeakers, err := agents.ExtractBGPSpeakers(pages)
th.AssertNoErr(t, err)
out := "Speakers:"
for _, speaker := range allSpeakers {
out += " " + speaker.ID
if doManualAssignment {
// If using manual assignment, schedule a BGP Speaker to an agent
agentID = allAgents[0].ID
opts := agents.ScheduleBGPSpeakerOpts{
SpeakerID: bgpSpeaker.ID,
}
err = agents.ScheduleBGPSpeaker(context.TODO(), client, agentID, opts).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Successfully scheduled speaker %s to agent %s", bgpSpeaker.ID, agentID)
} else {
// If using automatic assignment, pick the first agent that the speaker
// was assigned to (it may be assigned to many, depending on how many
// nodes there are)
agentID = bgpAgentsForSpeaker[0].ID
}
t.Log(out)

// Remove the BGP Speaker from the first agent
err = agents.RemoveBGPSpeaker(context.TODO(), client, bgpAgents[0].ID, bgpSpeaker.ID).ExtractErr()
// Wait for the association to complete.
pages, err = agents.ListDRAgentHostingBGPSpeakers(client, bgpSpeaker.ID).AllPages(context.TODO())
th.AssertNoErr(t, err)
bgpAgentsForSpeaker, err = agents.ExtractAgents(pages)
th.AssertNoErr(t, err)
t.Logf("BGP Speaker %s has been removed from agent %s", bgpSpeaker.ID, bgpAgents[0].ID)
err = tools.WaitForTimeout(
func(ctx context.Context) (bool, error) {
bgpAgent, err := agents.Get(ctx, client, bgpAgents[0].ID).Extract()
bgpAgent, err := agents.Get(ctx, client, agentID).Extract()
th.AssertNoErr(t, err)
agentConf := bgpAgent.Configurations
numOfSpeakers := int(agentConf["bgp_speakers"].(float64))
t.Logf("Agent %s has %d speaker(s)", bgpAgent.ID, numOfSpeakers)
return numOfSpeakers == 0, nil
t.Logf("Agent %s has %d speaker(s)", agentID, numOfSpeakers)
return 1 == numOfSpeakers, nil
}, timeout)
th.AssertNoErr(t, err)

// Remove all BGP Speakers from the agent
pages, err = agents.ListBGPSpeakers(client, bgpAgents[0].ID).AllPages(context.TODO())
// Disassociate the BGP Speaker from the agent.
err = agents.RemoveBGPSpeaker(context.TODO(), client, bgpAgentsForSpeaker[0].ID, bgpSpeaker.ID).ExtractErr()
th.AssertNoErr(t, err)
allSpeakers, err = agents.ExtractBGPSpeakers(pages)
th.AssertNoErr(t, err)
for _, speaker := range allSpeakers {
th.AssertNoErr(t, agents.RemoveBGPSpeaker(context.TODO(), client, bgpAgents[0].ID, speaker.ID).ExtractErr())
}
t.Logf("BGP Speaker %s has been removed from agent %s", bgpSpeaker.ID, bgpAgentsForSpeaker[0].ID)

// Schedule a BGP Speaker to an agent
opts := agents.ScheduleBGPSpeakerOpts{
SpeakerID: bgpSpeaker.ID,
// Only validate the disassociation if we know the static scheduler is in
// effect as it'll simply be recreated if we're using the chance scheduler
// and running in a single node deployment.
if doManualAssignment {
err = tools.WaitForTimeout(
func(ctx context.Context) (bool, error) {
bgpAgent, err := agents.Get(ctx, client, bgpAgentsForSpeaker[0].ID).Extract()
th.AssertNoErr(t, err)
agentConf := bgpAgent.Configurations
numOfSpeakers := int(agentConf["bgp_speakers"].(float64))
t.Logf("Agent %s has %d speaker(s)", bgpAgent.ID, numOfSpeakers)
return numOfSpeakers == 0, nil
}, timeout)
th.AssertNoErr(t, err)
}
err = agents.ScheduleBGPSpeaker(context.TODO(), client, bgpAgents[0].ID, opts).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Successfully scheduled speaker %s to agent %s", bgpSpeaker.ID, bgpAgents[0].ID)

err = tools.WaitForTimeout(
func(ctx context.Context) (bool, error) {
bgpAgent, err := agents.Get(ctx, client, bgpAgents[0].ID).Extract()
th.AssertNoErr(t, err)
agentConf := bgpAgent.Configurations
numOfSpeakers := int(agentConf["bgp_speakers"].(float64))
t.Logf("Agent %s has %d speaker(s)", bgpAgent.ID, numOfSpeakers)
return 1 == numOfSpeakers, nil
}, timeout)
th.AssertNoErr(t, err)

// Delete the BGP Speaker
err = speakers.Delete(context.TODO(), client, bgpSpeaker.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Successfully deleted the BGP Speaker, %s", bgpSpeaker.ID)
err = tools.WaitForTimeout(
func(ctx context.Context) (bool, error) {
bgpAgent, err := agents.Get(ctx, client, bgpAgents[0].ID).Extract()
bgpAgent, err := agents.Get(ctx, client, agentID).Extract()
th.AssertNoErr(t, err)
agentConf := bgpAgent.Configurations
numOfSpeakers := int(agentConf["bgp_speakers"].(float64))
Expand Down
Loading