-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TEST]: Improvement: Switch: New interaction approach
- Loading branch information
Yuliia Miroshnychenko
committed
Jan 16, 2025
1 parent
a148a07
commit 44345ce
Showing
23 changed files
with
2,152 additions
and
1,034 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
...tional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/KildaProperties.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.openkilda.functionaltests.helpers | ||
|
||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.beans.factory.annotation.Qualifier | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class KildaProperties { | ||
|
||
public static int DISCOVERY_EXHAUSTED_INTERVAL | ||
public static int ANTIFLAP_MIN | ||
public static int ANTIFLAP_COOLDOWN | ||
public static int DISCOVERY_TIMEOUT | ||
public static double BURST_COEFFICIENT | ||
public static String TOPO_DISCO_TOPIC | ||
public static Properties PRODUCER_PROPS | ||
|
||
@Autowired | ||
KildaProperties( @Value('${discovery.exhausted.interval}') int discoveryExhaustedInterval, | ||
@Value('${antiflap.min}') int antiflapMin, | ||
@Value('${antiflap.cooldown}') int antiflapCooldown, | ||
@Value('${discovery.timeout}') int discoveryTimeout, | ||
@Value('${burst.coefficient}') double burstCoefficient, | ||
@Autowired @Qualifier("kafkaProducerProperties") Properties producerProps, | ||
@Value("#{kafkaTopicsConfig.getTopoDiscoTopic()}") String topoDiscoTopic) { | ||
|
||
DISCOVERY_EXHAUSTED_INTERVAL = discoveryExhaustedInterval | ||
ANTIFLAP_MIN = antiflapMin | ||
ANTIFLAP_COOLDOWN = antiflapCooldown | ||
DISCOVERY_TIMEOUT = discoveryTimeout | ||
BURST_COEFFICIENT = burstCoefficient | ||
TOPO_DISCO_TOPIC = topoDiscoTopic | ||
PRODUCER_PROPS = producerProps | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
...-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/SwitchFactory.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.openkilda.functionaltests.helpers.factory | ||
|
||
import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE | ||
|
||
import org.openkilda.functionaltests.helpers.model.SwitchExtended | ||
import org.openkilda.functionaltests.model.cleanup.CleanupManager | ||
import org.openkilda.testing.model.topology.TopologyDefinition | ||
import org.openkilda.testing.model.topology.TopologyDefinition.Switch | ||
import org.openkilda.testing.service.database.Database | ||
import org.openkilda.testing.service.lockkeeper.LockKeeperService | ||
import org.openkilda.testing.service.northbound.NorthboundService | ||
import org.openkilda.testing.service.northbound.NorthboundServiceV2 | ||
|
||
import groovy.util.logging.Slf4j | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.beans.factory.annotation.Qualifier | ||
import org.springframework.context.annotation.Scope | ||
import org.springframework.stereotype.Component | ||
|
||
@Slf4j | ||
@Component | ||
@Scope(SCOPE_PROTOTYPE) | ||
class SwitchFactory { | ||
|
||
@Autowired @Qualifier("islandNb") | ||
NorthboundService northbound | ||
@Autowired @Qualifier("islandNbV2") | ||
NorthboundServiceV2 northboundV2 | ||
@Autowired | ||
TopologyDefinition topology | ||
@Autowired | ||
Database database | ||
@Autowired | ||
LockKeeperService lockKeeper | ||
@Autowired | ||
CleanupManager cleanupManager | ||
|
||
SwitchExtended get(Switch sw) { | ||
List<Integer> islPorts = [] | ||
topology.getRelatedIsls(sw).each { | ||
it?.srcSwitch?.dpId != sw.dpId ?: islPorts.add(it.srcPort) | ||
it?.dstSwitch?.dpId != sw.dpId ?: islPorts.add(it.dstPort) | ||
} | ||
List<Integer> traffGen = topology.traffGens.findAll{ it.switchConnected.dpId == sw.dpId }.switchPort | ||
return new SwitchExtended(sw, islPorts, traffGen, | ||
northbound, northboundV2, database, lockKeeper, cleanupManager) | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
...nctional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/LagPort.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package org.openkilda.functionaltests.helpers.model | ||
|
||
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.DELETE_LAG_LOGICAL_PORT | ||
|
||
import org.openkilda.functionaltests.model.cleanup.CleanupManager | ||
import org.openkilda.model.SwitchId | ||
import org.openkilda.northbound.dto.v2.switches.LagPortRequest | ||
import org.openkilda.testing.service.northbound.NorthboundServiceV2 | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import groovy.transform.EqualsAndHashCode | ||
import groovy.transform.ToString | ||
import groovy.util.logging.Slf4j | ||
|
||
@Slf4j | ||
@EqualsAndHashCode(excludes = 'northboundV2, cleanupManager') | ||
@ToString(includeNames = true, excludes = 'northboundV2, cleanupManager') | ||
class LagPort { | ||
|
||
SwitchId switchId | ||
Set<Integer> portNumbers | ||
int logicalPortNumber | ||
boolean lacpReply | ||
|
||
@JsonIgnore | ||
NorthboundServiceV2 northboundV2 | ||
@JsonIgnore | ||
CleanupManager cleanupManager | ||
|
||
LagPort(SwitchId switchId, | ||
Set<Integer> portNumbers, | ||
NorthboundServiceV2 northboundV2, | ||
CleanupManager cleanupManager) { | ||
this.switchId = switchId | ||
this.portNumbers = portNumbers | ||
this.northboundV2 = northboundV2 | ||
this.cleanupManager = cleanupManager | ||
} | ||
|
||
LagPort(SwitchId switchId, | ||
int logicalPortNumber, | ||
List<Integer> portNumbers, | ||
boolean lacpReply, | ||
NorthboundServiceV2 northboundV2, | ||
CleanupManager cleanupManager) { | ||
this.switchId = switchId | ||
this.logicalPortNumber = logicalPortNumber | ||
this.lacpReply = lacpReply | ||
this.portNumbers = portNumbers | ||
this.northboundV2 = northboundV2 | ||
this.cleanupManager = cleanupManager | ||
} | ||
|
||
|
||
LagPort create(boolean lacpReply = null) { | ||
def lagDetails = northboundV2.createLagLogicalPort(switchId, new LagPortRequest(portNumbers , lacpReply)) | ||
cleanupManager.addAction(DELETE_LAG_LOGICAL_PORT, { northboundV2.deleteLagLogicalPort(switchId, lagDetails.logicalPortNumber) }) | ||
new LagPort(switchId, lagDetails.logicalPortNumber, lagDetails.portNumbers, lagDetails.lacpReply, northboundV2, cleanupManager) | ||
} | ||
|
||
LagPort update(LagPortRequest updateRequest) { | ||
def lagDetails = northboundV2.updateLagLogicalPort(switchId, logicalPortNumber, updateRequest) | ||
new LagPort(switchId, lagDetails.logicalPortNumber, lagDetails.portNumbers, lagDetails.lacpReply, northboundV2, cleanupManager) | ||
} | ||
|
||
LagPort delete() { | ||
def lagDetails = northboundV2.deleteLagLogicalPort(switchId, logicalPortNumber) | ||
new LagPort(switchId, lagDetails.logicalPortNumber, lagDetails.portNumbers, lagDetails.lacpReply, northboundV2, cleanupManager) | ||
} | ||
} |
130 changes: 130 additions & 0 deletions
130
...nal-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/PortExtended.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package org.openkilda.functionaltests.helpers.model | ||
|
||
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.PORT_UP | ||
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.RESTORE_ISL | ||
import static org.openkilda.functionaltests.model.cleanup.CleanupAfter.TEST | ||
import static org.openkilda.testing.Constants.WAIT_OFFSET | ||
|
||
import org.openkilda.functionaltests.helpers.KildaProperties | ||
import org.openkilda.functionaltests.helpers.Wrappers | ||
import org.openkilda.functionaltests.helpers.thread.PortBlinker | ||
import org.openkilda.functionaltests.model.cleanup.CleanupAfter | ||
import org.openkilda.functionaltests.model.cleanup.CleanupManager | ||
import org.openkilda.messaging.info.switches.PortDescription | ||
import org.openkilda.model.SwitchId | ||
import org.openkilda.northbound.dto.v2.switches.PortPropertiesDto | ||
import org.openkilda.testing.model.topology.TopologyDefinition.Switch | ||
import org.openkilda.testing.service.northbound.NorthboundService | ||
import org.openkilda.testing.service.northbound.NorthboundServiceV2 | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import groovy.transform.EqualsAndHashCode | ||
import groovy.transform.ToString | ||
import groovy.util.logging.Slf4j | ||
|
||
@Slf4j | ||
@EqualsAndHashCode(excludes = 'northbound, northboundV2, cleanupManager') | ||
@ToString(includeNames = true, excludes = 'northbound, northboundV2, cleanupManager') | ||
class PortExtended { | ||
|
||
Switch sw | ||
Integer port | ||
|
||
@JsonIgnore | ||
NorthboundService northbound | ||
@JsonIgnore | ||
NorthboundServiceV2 northboundV2 | ||
@JsonIgnore | ||
CleanupManager cleanupManager | ||
|
||
Map<Tuple2<SwitchId, Integer>, Long> history = [:] | ||
|
||
PortExtended(Switch sw, | ||
Integer portNumber, | ||
NorthboundService northbound, | ||
NorthboundServiceV2 northboundV2, | ||
CleanupManager cleanupManager) { | ||
this.sw = sw | ||
this.port = portNumber | ||
this.northbound = northbound | ||
this.northboundV2 = northboundV2 | ||
this.cleanupManager = cleanupManager | ||
} | ||
|
||
def up() { | ||
def swPort = new Tuple2(sw.dpId, port) | ||
def lastEvent = history.get(swPort) | ||
if (lastEvent) { | ||
Wrappers.silent { //Don't fail hard on this check. In rare cases we may miss the history entry | ||
waitForStabilization(lastEvent) | ||
} | ||
history.remove(swPort) | ||
} | ||
northbound.portUp(sw.dpId, port) | ||
} | ||
|
||
def safeUp() { | ||
if (northbound.getPort(sw.dpId, port).getState().first() != "LIVE") { | ||
up() | ||
} | ||
Wrappers.wait(WAIT_OFFSET) { | ||
assert northbound.getActiveLinks().findAll { | ||
it.source.switchId == sw.dpId && it.source.portNo == port || | ||
it.destination.switchId == sw.dpId && it.destination.portNo == port | ||
}.size() == 2 | ||
} | ||
} | ||
|
||
def down(CleanupAfter cleanupAfter = TEST, boolean isNotInScopeOfIslBreak = true) { | ||
if (isNotInScopeOfIslBreak) { | ||
cleanupManager.addAction(PORT_UP, { safeUp() }, cleanupAfter) | ||
} | ||
def response = northbound.portDown(sw.dpId, port) | ||
sleep(KildaProperties.ANTIFLAP_MIN * 1000) | ||
history.put(new Tuple2(sw.dpId, port), System.currentTimeMillis()) | ||
response | ||
} | ||
|
||
/** | ||
* Wait till the current port is in a stable state (deactivated antiflap) by analyzing its history. | ||
*/ | ||
void waitForStabilization(Long since = 0) { | ||
// '* 2' it takes more time on a hardware env for link via 'a-switch' | ||
Wrappers.wait(KildaProperties.ANTIFLAP_COOLDOWN + WAIT_OFFSET * 2) { | ||
def history = northboundV2.getPortHistory(sw.dpId, port, since, null) | ||
|
||
if (!history.empty) { | ||
def antiflapEvents = history.collect { PortHistoryEvent.valueOf(it.event) }.findAll { | ||
it in [PortHistoryEvent.ANTI_FLAP_ACTIVATED, PortHistoryEvent.ANTI_FLAP_DEACTIVATED] | ||
} | ||
|
||
if (!antiflapEvents.empty) { | ||
assert antiflapEvents.last() == PortHistoryEvent.ANTI_FLAP_DEACTIVATED | ||
} else { | ||
false | ||
} | ||
} else { | ||
false | ||
} | ||
} | ||
} | ||
|
||
def setDiscovery(boolean expectedStatus) { | ||
if (!expectedStatus) { | ||
cleanupManager.addAction(RESTORE_ISL, { setDiscovery(true) }) | ||
} | ||
return northboundV2.updatePortProperties(sw.dpId, port, new PortPropertiesDto(discoveryEnabled: expectedStatus)) | ||
} | ||
|
||
PortBlinker getBlinker(long interval, Properties producerProps) { | ||
new PortBlinker(KildaProperties.PRODUCER_PROPS, KildaProperties.TOPO_DISCO_TOPIC, sw, port, interval) | ||
} | ||
|
||
static def closeBlinker(PortBlinker blinker) { | ||
blinker?.isRunning() && blinker.stop(true) | ||
} | ||
|
||
PortDescription retrieveDetails() { | ||
northbound.getPort(sw.dpId, port) | ||
} | ||
} |
Oops, something went wrong.