From 561111d6be76880ddeaa18b94a104bab16cd5b3a Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Tue, 8 Oct 2024 16:32:02 +0200 Subject: [PATCH 01/21] [TEST]: Improvement: Verification of switches and relations dump after WFM restarting --- .../helpers/SwitchHelper.groovy | 5 ++ .../helpers/model/SwitchDbData.groovy | 76 +++++++++++++++++++ .../spec/xresilience/StormLcmSpec.groovy | 63 ++++++++++----- 3 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchDbData.groovy diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy index 924c5c1b3c..ac978992c3 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy @@ -1,6 +1,7 @@ package org.openkilda.functionaltests.helpers import groovy.transform.Memoized +import org.openkilda.functionaltests.helpers.model.SwitchDbData import org.openkilda.functionaltests.model.cleanup.CleanupAfter import org.openkilda.functionaltests.model.cleanup.CleanupManager import org.openkilda.messaging.command.switches.DeleteRulesAction @@ -209,6 +210,10 @@ class SwitchHelper { database.get().getSwitch(sw.dpId).features } + static List dumpAllSwitches() { + database.get().dumpAllSwitches().collect { new SwitchDbData((it.data))} + } + static List getDefaultCookies(Switch sw) { def swProps = northbound.get().getSwitchProperties(sw.dpId) def multiTableRules = [] diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchDbData.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchDbData.groovy new file mode 100644 index 0000000000..04a606a7bf --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchDbData.groovy @@ -0,0 +1,76 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.model.Switch.SwitchData +import org.openkilda.model.SwitchFeature +import org.openkilda.model.SwitchId +import org.openkilda.model.SwitchStatus + +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString + +import java.time.Instant + +@ToString +@EqualsAndHashCode(excludes = "timeModified") +class SwitchDbData { + + SwitchId switchId + SwitchStatus status + IpSocketAddress socketAddress + String hostname + String controller + String description + String version + String manufacturer + String hardware + String software + String serialNumber + String dataPath + Set features + boolean underMaintenance + Instant timeCreated + Instant timeModified + String pop + double latitude + double longitude + String street + String city + String country + + SwitchDbData(SwitchData switchData) { + this.switchId = switchData.switchId + this.status = switchData.status + this.socketAddress = new IpSocketAddress(switchData.socketAddress.address, switchData.socketAddress.port) + this.hostname = switchData.hostname + this.controller = switchData.controller + this.description = switchData.description + this.version = switchData.ofVersion + this.manufacturer = switchData.ofDescriptionManufacturer + this.hardware = switchData.ofDescriptionHardware + this.software = switchData.ofDescriptionSoftware + this.serialNumber = switchData.ofDescriptionSerialNumber + this.dataPath = switchData.ofDescriptionDatapath + this.features = switchData.features + this.underMaintenance = switchData.underMaintenance + this.timeCreated = switchData.timeCreate + this.timeModified = switchData.timeModify + this.pop = switchData.pop + this.latitude = switchData.latitude + this.longitude = switchData.longitude + this.street = switchData.street + this.city = switchData.city + this.country = switchData.country + } + + @ToString + @EqualsAndHashCode(excludes = "port") + class IpSocketAddress { + String address + int port + + IpSocketAddress(String address, int port) { + this.address = address + this.port = port + } + } +} diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/StormLcmSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/StormLcmSpec.groovy index 8a7aebd0c6..2f90a41a07 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/StormLcmSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/StormLcmSpec.groovy @@ -1,13 +1,13 @@ package org.openkilda.functionaltests.spec.xresilience -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs +import static org.assertj.core.api.Assertions.assertThat import static org.openkilda.functionaltests.extension.tags.Tag.LOW_PRIORITY import static org.openkilda.functionaltests.extension.tags.Tag.VIRTUAL +import static org.openkilda.testing.Constants.STATS_LOGGING_TIMEOUT import static org.openkilda.testing.Constants.SWITCHES_ACTIVATION_TIME import static org.openkilda.testing.Constants.TOPOLOGY_DISCOVERING_TIME import static org.openkilda.testing.Constants.WAIT_OFFSET import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMode.RW -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags @@ -62,6 +62,20 @@ class StormLcmSpec extends HealthCheckSpecification { wfmManipulator = new WfmManipulator(dockerHost) } + def cleanupSpec() { + Wrappers.wait(SWITCHES_ACTIVATION_TIME) { + assert northbound.getAllSwitches().findAll { + it.switchId in topology.switches.dpId && it.state == SwitchChangeType.ACTIVATED + }.size() == topology.activeSwitches.size() + } + + Wrappers.wait(TOPOLOGY_DISCOVERING_TIME) { + assert northbound.getAllLinks().findAll { + it.source.switchId in topology.switches.dpId && it.state == IslChangeType.DISCOVERED + }.size() == topology.islsForActiveSwitches.size() * 2 + } + } + @Tags(LOW_PRIORITY) // note: it takes ~15 minutes to run this test def "System survives Storm topologies restart"() { @@ -82,27 +96,25 @@ class StormLcmSpec extends HealthCheckSpecification { flows.each { flow -> flow.validateAndCollectDiscrepancies().isEmpty() } and: "Database dump" - //unstable for parallel runs even when isolated. why? -// def relationsDump = database.dumpAllRelations() - def switchesDump = database.dumpAllSwitches() + def initialSwitchesDump = switchHelper.dumpAllSwitches() + def initialGraphRelations + Wrappers.wait(STATS_LOGGING_TIMEOUT) { + initialGraphRelations = database.dumpAllRelations() + // waiting for both switch_properties and flow_stats "has" relations + assert database.dumpAllRelations().findAll { it.label == "has" }.size() == flowsAmount + topology.activeSwitches.size() + } + def initialRelationsDump = collectRelationsDetails(initialGraphRelations) when: "Storm topologies are restarted" wfmManipulator.restartWfm() then: "Database nodes and relations are unchanged" - def newRelation = database.dumpAllRelations() - def newSwitches = database.dumpAllSwitches() - expect newSwitches, sameBeanAs(switchesDump).ignoring("data.timeModify") - .ignoring("data.socketAddress.port") -// expect newRelation, sameBeanAs(relationsDump).ignoring("properties.time_modify") -// .ignoring("properties.latency") -// .ignoring("properties.time_create") -// .ignoring("properties.switch_address_port") -// .ignoring("properties.connected_at") -// .ignoring("properties.master") -// .ignoring("inVertex") -// .ignoring("outVertex") -// .ignoring("id") + def newSwitchesDump = switchHelper.dumpAllSwitches() + assertThat(newSwitchesDump).containsExactlyInAnyOrder(*initialSwitchesDump) + + def graphRelationsAfterWfmRestarting = database.dumpAllRelations() + def newRelationsDump = collectRelationsDetails(graphRelationsAfterWfmRestarting) + assertThat(newRelationsDump).containsExactlyInAnyOrder(*initialRelationsDump) and: "Topology is recovered after storm topology restarting" Wrappers.wait(TOPOLOGY_DISCOVERING_TIME) { @@ -172,4 +184,19 @@ class StormLcmSpec extends HealthCheckSpecification { assert northbound.getAllLinks().every {it.state == IslChangeType.DISCOVERED} } } + + private def collectRelationsDetails(List relationsDump) { + List propertiesFieldsToIgnore = ["time_modify", "latency", "time_create", + "switch_address_port", "connected_at", "master"] + relationsDump.collect { + //there is no need to ignore inVertex, outVertex, id as ONLY label and properties fields are used + [(it.label + "_data"): [it.properties().collectEntries { + if (it?.key in propertiesFieldsToIgnore) { + [:] + } else { + [(it?.key): it?.value] + } + }.findAll()]] + } + } } From b953a40b0f022ea9e1194117974156fe53066100 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Thu, 12 Sep 2024 16:16:02 +0200 Subject: [PATCH 02/21] [TEST]: Improvement: Verification of flows on the switch --- .../helpers/SwitchHelper.groovy | 2 +- .../helpers/model/SwitchPairs.groovy | 5 ++ .../spec/switches/SwitchesFlowsV2Spec.groovy | 76 +++++++++++++------ 3 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy index 924c5c1b3c..584fc2f5e8 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy @@ -409,7 +409,7 @@ class SwitchHelper { return northboundV2.get().getSwitchFlows(new SwitchId(sw.getDpId().getId()), portIds) } - static List "get used ports" (SwitchId switchId) { + static List getUsedPorts(SwitchId switchId) { return northboundV2.get().getSwitchFlows(switchId, []).flowsByPort.keySet().asList() } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchPairs.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchPairs.groovy index 4ce3ec3403..10a9eff4d2 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchPairs.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchPairs.groovy @@ -128,6 +128,11 @@ class SwitchPairs { return this } + SwitchPair specificPair(Switch source, Switch destination) { + switchPairs = switchPairs.findAll { it.src == source && it.dst == destination } + return switchPairs.first() + } + SwitchPairs includeSourceSwitch(Switch sw) { switchPairs = switchPairs.findAll { it.src == sw } return this diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy index 92ccaaa502..1c39f4415e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy @@ -52,21 +52,34 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { def setupSpec() { /* Topology used to test features in this spec looks like this: - 2 subflows of Y-flow subflow 1 + usual flow + 2 subflows of Y-flow subflow 1 + usual flow use the same src and dst 🡾 🡾 (Shared SW)☴☴☴(switch flow goes through)☴☴☴☴☴☴☴☴☴☴☴☴=============(Endpoint1 SW) 🡽 \-----(SW protected path goes through)---/ \------------(Endpoint2 SW) usual flow 🡹 🡹 - usual flow protected path subflow 2 + usual flow protected path subflow 2 ends on the switch that is not used by other flows */ - switchTriplet = switchTriplets.all(true, false).getSwitchTriplets().find { - it.shared != it.ep1 && it.pathsEp1.min{ it.size() }?.size() > 2 - && it.pathsEp1.unique(false) { a, b -> a.intersect(b) == [] ? 1 : 0 }.size() >= 2 + switchTriplet = switchTriplets.all(true, false).nonNeighbouring().getSwitchTriplets().find { + def yPoints = topologyHelper.findPotentialYPoints(it) + yPoints[0] != it.shared } assumeTrue(switchTriplet != null, "Couldn't find appropriate switch triplet") - switchPair = switchPairs.all() - .includeSwitch(switchTriplet.getShared()) - .includeSwitch(switchTriplet.getEp1()).random() + + yFlow = yFlowFactory.getRandom(switchTriplet, false, [], CLASS) + def yFlowPath = yFlow.retrieveAllEntityPaths() + def subFlow1Path = yFlowPath.subFlowPaths.first() + def subFlow2Path = yFlowPath.subFlowPaths.last() + // sub-flow1 shares switches with regular flow + yFlowSubFlow1Id = subFlow1Path.path.forward.getInvolvedSwitches().size() > subFlow2Path.path.forward.getInvolvedSwitches().size() ? + subFlow2Path.flowId : subFlow1Path.flowId + + //sub-flow2 ends on the switch that is not used by the sub-flow1 and regular flow + yFlowSubFlow2Id = yFlow.subFlows.find { it.flowId != yFlowSubFlow1Id }.flowId + def flowDstSwitch = topology.activeSwitches.find { + it.dpId == yFlow.subFlows.find { it.flowId == yFlowSubFlow1Id }.endpoint.switchId + } + + switchPair = switchPairs.all().specificPair(switchTriplet.shared, flowDstSwitch) flow = flowFactory.getBuilder(switchPair, false) .withProtectedPath(true) .build().create(UP, CLASS) @@ -74,29 +87,48 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() switchFlowGoesThrough = topology.activeSwitches.find { it.dpId == flowPathInfo.flowPath.path.forward.transitInvolvedSwitches.first() } switchProtectedPathGoesThrough = topology.activeSwitches.find { it.dpId == flowPathInfo.flowPath.protectedPath.forward.transitInvolvedSwitches.first() } - - yFlow = yFlowFactory.getRandom(switchTriplet, true, [], CLASS) - yFlowSubFlow1Id = yFlow.subFlows.first().flowId - yFlowSubFlow2Id = yFlow.subFlows.last().flowId } @Tags([SMOKE]) - def "System allows to get flows on particular ports on switch"() { + def "System allows to get flows on particular ports on switch(several flows on the same port)"() { given: "Y-Flow subflow which starts on switch" and: "List of the ports that subflow uses on switch, received from flow path" def usedPortsList = yFlow.retrieveAllEntityPaths().subFlowPaths.find { it.flowId == yFlowSubFlow2Id } .collect { (it.path.forward.getNodes().nodes + it?.protectedPath?.forward?.getNodes()?.nodes) - .findAll { it?.switchId == switchTriplet.getShared().getDpId() }.portNo + .findAll { it?.switchId == switchTriplet.shared.dpId }.portNo }.flatten() + def sharedEpPort = yFlow.sharedEndpoint.portNumber + when: "Get all flows on the switch ports used by subflow under test" - def response = switchHelper.getFlowsV2(switchTriplet.getShared(), usedPortsList) + def response = switchHelper.getFlowsV2(switchTriplet.shared, usedPortsList) then: "Each port in response has information about subflow" response.flowsByPort.every { usedPortsList.contains(it.key) && it.value*.flowId.contains(yFlowSubFlow2Id) } + + and: "Used port on shared endpoint shows both sub-flows" + response.flowsByPort.get(sharedEpPort).flowId.sort() == [yFlowSubFlow1Id, yFlowSubFlow2Id].sort() + } + + @Tags([SMOKE]) + def "System allows to get flows on particular ports on switch"() { + given: "Y-Flow subflow which ends on switch that is not in the path of another sub-flow or regular flow" + and: "List of the ports that subflow uses on switch, received from flow path" + def switchWithOnlyOneSubFlow = switchPair.dst == switchTriplet.ep1 ? switchTriplet.ep2 : switchTriplet.ep1 + + def usedPortsList = yFlow.retrieveAllEntityPaths().subFlowPaths.find { it.flowId == yFlowSubFlow2Id } + .collect { it.path.forward.retrieveNodes().findAll { it.switchId == switchWithOnlyOneSubFlow.dpId }.portNo }.flatten() + + when: "Get all flows on the switch ports used by subflow under test" + def response = switchHelper.getFlowsV2(switchWithOnlyOneSubFlow, usedPortsList) + + then: "Each port in response has information about the subflow" + response.flowsByPort.every { + usedPortsList.contains(it.key) && it.value.flowId.unique() == [yFlowSubFlow2Id] + } } def "System allows to get a flow that #switchRole switch"() { @@ -105,8 +137,7 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { def flows = switchHelper.getFlowsV2(switchUnderTest, []) then: "The created flows (including both y-flow subflows) are in the response list from the switch" - flows.flowsByPort.collectMany { it.value }*.flowId - .containsAll([flowId, yFlowSubFlow1Id, yFlowSubFlow2Id]) + flows.flowsByPort.collectMany { it.value.flowId }.unique().sort() == [flowId, yFlowSubFlow1Id, yFlowSubFlow2Id].sort() where: switchRole | switchUnderTest @@ -121,22 +152,21 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { def flows = switchHelper.getFlowsV2(switchProtectedPathGoesThrough, []) then: "The flow's protected path is in the response list from the switch" - flows.flowsByPort.collectMany { it.value }*.flowId - .contains(flowId) + flows.flowsByPort.collectMany { it.value.flowId }.unique() == [flowId] } @Tags([LOW_PRIORITY]) def "Mirror sink endpoint port is not listed in list of the ports used"() { given: "Switch with flow on it and a free port" def switchUnderTest = switchPair.getDst() - def usedPortsList = switchHelper."get used ports"(switchUnderTest.getDpId()) + def usedPortsList = switchHelper.getUsedPorts(switchUnderTest.dpId) def freePort = (new ArrayList<>(1..1000).asList() - usedPortsList - topology.getBusyPortsForSwitch(switchUnderTest)).first() when: "Create mirror point on switch with sink pointing to free port" flow.createMirrorPoint( - switchUnderTest.getDpId(), freePort, randomVlan(), + switchUnderTest.dpId, freePort, randomVlan(), FlowPathDirection.REVERSE ) @@ -147,8 +177,8 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { @Tags([LOW_PRIORITY]) def "Empty list is returned if none of requested ports is busy with any flow"() { given: "Switch with flow on it and ports this flow uses" - def switchUnderTest = switchPair.getDst() - def usedPortsList = switchHelper."get used ports"(switchUnderTest.getDpId()) + def switchUnderTest = switchPair.dst + def usedPortsList = switchHelper.getUsedPorts(switchUnderTest.dpId) when: "Request flows on several unused ports" def unusedPortsList = new ArrayList<>(1..1000).asList() - usedPortsList From 628bc01ba7a80b780efeefaf73604513f4faa1d1 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Fri, 6 Sep 2024 12:14:14 +0200 Subject: [PATCH 03/21] [TEST]: Improvement: Regular Flow: Getting Isls --- .../helpers/model/FlowEntityPath.groovy | 28 ++++- .../helpers/model/FlowPathModel.groovy | 9 -- .../spec/flows/AutoRerouteSpec.groovy | 28 ++--- .../spec/flows/BandwidthSpec.groovy | 18 +-- .../spec/flows/FlowAffinitySpec.groovy | 12 +- .../spec/flows/FlowCrudSpec.groovy | 16 +-- .../spec/flows/FlowCrudV1Spec.groovy | 6 +- .../spec/flows/FlowDiversitySpec.groovy | 26 ++-- .../spec/flows/FlowLoopSpec.groovy | 2 +- .../spec/flows/FlowMonitoringSpec.groovy | 6 +- .../spec/flows/FlowPingSpec.groovy | 2 +- .../spec/flows/IntentionalRerouteSpec.groovy | 24 ++-- .../spec/flows/MaxLatencySpec.groovy | 28 ++--- .../spec/flows/MultiRerouteSpec.groovy | 6 +- .../spec/flows/PartialUpdateSpec.groovy | 4 +- .../spec/flows/PinnedFlowSpec.groovy | 14 +-- .../spec/flows/ProtectedPathSpec.groovy | 116 +++++++++--------- .../spec/flows/ProtectedPathV1Spec.groovy | 6 +- .../spec/flows/QinQFlowSpec.groovy | 4 +- .../spec/flows/SwapEndpointSpec.groovy | 12 +- .../spec/flows/VxlanFlowSpec.groovy | 2 +- .../flows/yflows/YFlowDiversitySpec.groovy | 2 +- .../spec/links/LinkMaintenanceSpec.groovy | 12 +- .../spec/links/LinkSpec.groovy | 18 +-- .../spec/links/UnstableIslSpec.groovy | 4 +- .../spec/network/PathCheckSpec.groovy | 2 +- .../spec/network/PathComputationSpec.groovy | 10 +- .../spec/stats/FlowStatSpec.groovy | 6 +- .../spec/switches/FlowRulesSpec.groovy | 2 +- .../spec/switches/MetersSpec.groovy | 2 +- .../spec/switches/SwitchFailuresSpec.groovy | 4 +- .../switches/SwitchMaintenanceSpec.groovy | 12 +- .../spec/switches/SwitchSyncSpec.groovy | 4 +- .../spec/switches/SwitchValidationSpec.groovy | 4 +- .../switches/SwitchValidationV2Spec.groovy | 6 +- .../spec/toggles/FeatureTogglesV2Spec.groovy | 8 +- .../spec/xresilience/ContentionSpec.groovy | 8 +- .../spec/xresilience/RetriesSpec.groovy | 24 ++-- 38 files changed, 252 insertions(+), 245 deletions(-) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowEntityPath.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowEntityPath.groovy index 1dfe04c6e8..020eb4bdbd 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowEntityPath.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowEntityPath.groovy @@ -5,6 +5,7 @@ import org.openkilda.messaging.info.event.PathNode import org.openkilda.messaging.payload.flow.FlowPathPayload import org.openkilda.model.SwitchId import org.openkilda.testing.model.topology.TopologyDefinition +import org.openkilda.testing.model.topology.TopologyDefinition.Isl import groovy.transform.Canonical import groovy.transform.EqualsAndHashCode @@ -49,11 +50,28 @@ class FlowEntityPath { } List getPathNodes(Direction direction = Direction.FORWARD, boolean isProtected = false) { - if (direction == Direction.FORWARD) { - isProtected ? flowPath.protectedPath.forward.nodes.toPathNode() : flowPath.path.forward.nodes.toPathNode() - } else { - isProtected ? flowPath.protectedPath.reverse.nodes.toPathNode() : flowPath.path.reverse.nodes.toPathNode() - } + PathModel path = isProtected ? flowPath.protectedPath : flowPath.path + getPathInvolvedNodes(path, direction) + } + + List getMainPathInvolvedIsls(Direction direction = Direction.FORWARD) { + getPathInvolvedIsls(flowPath.path, direction) + } + + List getProtectedPathInvolvedIsls(Direction direction = Direction.FORWARD) { + getPathInvolvedIsls(flowPath.protectedPath, direction) + } + + List getInvolvedIsls(Direction direction = Direction.FORWARD) { + flowPath.getInvolvedIsls(direction) + } + + private List getPathInvolvedIsls(PathModel path, Direction direction) { + direction == Direction.FORWARD ? path.forward.getInvolvedIsls() : path.reverse.getInvolvedIsls() + } + + private List getPathInvolvedNodes(PathModel path, Direction direction) { + direction == Direction.FORWARD ? path.forward.nodes.toPathNode() : path.reverse.nodes.toPathNode() } } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowPathModel.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowPathModel.groovy index d5d22ccfbd..036436358c 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowPathModel.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowPathModel.groovy @@ -24,13 +24,4 @@ class FlowPathModel { direction == Direction.FORWARD ? (path.forward.getInvolvedIsls() + protectedPath?.forward?.getInvolvedIsls()).findAll() : (path.reverse.getInvolvedIsls() + protectedPath?.reverse?.getInvolvedIsls()).findAll() } - - List getMainPathInvolvedIsls(Direction direction = Direction.FORWARD) { - direction == Direction.FORWARD ? path.forward.getInvolvedIsls() : path.reverse.getInvolvedIsls() - } - - List getProtectedPathInvolvedIsls(Direction direction = Direction.FORWARD) { - direction == Direction.FORWARD ? protectedPath.forward.getInvolvedIsls() : protectedPath.reverse.getInvolvedIsls() - } - } \ No newline at end of file diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy index 50b96068f3..87fd777d09 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy @@ -61,7 +61,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { def initialPath = flow.retrieveAllEntityPaths() when: "Fail a flow ISL (bring switch port down)" - def flowIsls = initialPath.flowPath.getInvolvedIsls() + def flowIsls = initialPath.getInvolvedIsls() List altFlowIsls = availablePaths.findAll { !it.containsAll(flowIsls) }.flatten().unique() as List def islToFail = flowIsls.find { !(it in altFlowIsls) && !(it.reversed in altFlowIsls) } islHelper.breakIsl(islToFail) @@ -87,7 +87,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { .withStrictBandwidth(true).build() .create() def initialPath = flow.retrieveAllEntityPaths() - def flowIsls = initialPath.flowPath.getInvolvedIsls(Direction.FORWARD) + initialPath.flowPath.getInvolvedIsls(Direction.REVERSE) + def flowIsls = initialPath.getInvolvedIsls(Direction.FORWARD) + initialPath.getInvolvedIsls(Direction.REVERSE) and: "Alt path ISLs have not enough bandwidth to host the flow" def altIsls = topology.getRelatedIsls(switchPair.src) + topology.getRelatedIsls(switchPair.dst) @@ -209,7 +209,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { .create() def initialPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialPath.getInvolvedIsls() List> altFlowIsls = availablePaths.findAll { !it.containsAll(initialFlowIsls) } List broughtDownIsls = altFlowIsls.collectMany { isls -> @@ -281,7 +281,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { } } when: "Bring all ports up on the source switch that are involved in the alternative paths" - islHelper.restoreIsls(broughtDownIsls.findAll {it.srcPort != initialPath.flowPath.getInvolvedIsls().first().srcPort}) + islHelper.restoreIsls(broughtDownIsls.findAll {it.srcPort != initialPath.getInvolvedIsls().first().srcPort}) then: "The flow goes to 'Up' status" and: "The flow was rerouted" @@ -300,7 +300,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(switchPair) def initialPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialPath.getInvolvedIsls() and: "Make the current flow path less preferable than others" allFlowPaths.findAll { it != initialFlowIsls }.each { islHelper.makePathIslsMorePreferable(it, initialFlowIsls) } @@ -328,7 +328,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(switchPair) def initialPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialPath.getInvolvedIsls() and: "Make the current flow path less preferable than others" allFlowPathsIsls.findAll { it != initialFlowIsls }.each { islHelper.makePathIslsMorePreferable(it, initialFlowIsls) } @@ -364,7 +364,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(switchPair) def initialPath = flow.retrieveAllEntityPaths() - def flowIsls = initialPath.flowPath.getInvolvedIsls() + def flowIsls = initialPath.getInvolvedIsls() and: "Make the current flow path less preferable than others" allFlowPathsIsls.findAll { it != flowIsls }.each { islHelper.makePathIslsMorePreferable(it, flowIsls) } @@ -426,7 +426,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(switchPair) def initialPath = flow.retrieveAllEntityPaths() - assert initialPath.flowPath.getInvolvedIsls() == expectedFlowIsls + assert initialPath.getInvolvedIsls() == expectedFlowIsls //All alternative paths for both flows are unavailable def untouchableIsls = expectedFlowIsls.collectMany { [it, it.reversed] } @@ -435,7 +435,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { .unique { [it, it.reversed].sort() } islHelper.breakIsls(islsToBreak) //move the flow to DOWN status - def flowIslToBreak = initialPath.flowPath.getInvolvedIsls().first() + def flowIslToBreak = initialPath.getInvolvedIsls().first() islHelper.breakIsl(flowIslToBreak) when: "Generate switchUp event on switch which is not related to the flow" @@ -487,7 +487,7 @@ class AutoRerouteSpec extends HealthCheckSpecification { and: "A flow over these switches that uses one of the desired paths that have common ISL" availablePathsIsls.findAll { it != mainIsls }.each { islHelper.makePathIslsMorePreferable(mainIsls, it) } def flow = flowFactory.getRandom(swPair) - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls and: "A potential 'backup' path that shares common isl has the preferred cost (will be preferred during reroute)" northbound.deleteLinkProps(northbound.getLinkProps(topology.isls)) @@ -522,7 +522,7 @@ triggering one more reroute of the current path" } and: "New flow path avoids both main and backup paths as well as broken ISLs" - def actualIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def actualIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() [commonIsl, commonIsl.reversed, mainPathUniqueIsl, mainPathUniqueIsl.reversed].each { assert !actualIsls.contains(it) } @@ -599,7 +599,7 @@ class AutoRerouteIsolatedSpec extends HealthCheckSpecification { and: "First flow without transit switches" def firstFlow = flowFactory.getRandom(switchPair1) def initialFirstFlowPath = firstFlow.retrieveAllEntityPaths() - assert initialFirstFlowPath.flowPath.getInvolvedIsls() == firstFlowMainPath.getInvolvedIsls() + assert initialFirstFlowPath.getInvolvedIsls() == firstFlowMainPath.getInvolvedIsls() and: "Second flow with transit switch" def secondFlow = flowFactory.getRandom(switchPair2) @@ -607,7 +607,7 @@ class AutoRerouteIsolatedSpec extends HealthCheckSpecification { def initialSecondFlowPath = secondFlow.retrieveAllEntityPaths() when: "Disconnect the src switch of the first flow from the controller" - def islToBreak = initialFirstFlowPath.flowPath.getInvolvedIsls().first() + def islToBreak = initialFirstFlowPath.getInvolvedIsls().first() def blockData = switchHelper.knockoutSwitch(switchPair1.src, RW) and: "Mark the switch as ACTIVE in db" // just to reproduce #3131 @@ -696,7 +696,7 @@ Failed to find path with requested bandwidth= ignored" def initialPath = flow.retrieveAllEntityPaths() and: "Alt path ISLs have not enough bandwidth to host the flow" - def initialFlowIsls = initialPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialPath.getInvolvedIsls() def altIsls = topology.getRelatedIsls(topologyHelper.getSwitch(flow.getSource().getSwitchId())) - initialFlowIsls List busyEndpoints = flow.occupiedEndpoints() altIsls.each {isl -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/BandwidthSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/BandwidthSpec.groovy index e0f80e6aa8..ae83157897 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/BandwidthSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/BandwidthSpec.groovy @@ -39,7 +39,7 @@ class BandwidthSpec extends HealthCheckSpecification { then: "Available bandwidth on ISLs is changed in accordance with flow maximum bandwidth" def linksAfterFlowCreate = northbound.getAllLinks() - def involvedIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def involvedIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() checkBandwidth(involvedIsls, linksBeforeFlowCreate, linksAfterFlowCreate, -flow.maximumBandwidth) when: "Update the flow with a valid bandwidth" @@ -52,7 +52,7 @@ class BandwidthSpec extends HealthCheckSpecification { and: "Available bandwidth on ISLs is changed in accordance with new flow maximum bandwidth" def linksBeforeFlowUpdate = linksAfterFlowCreate def linksAfterFlowUpdate = northbound.getAllLinks() - def involvedIslsAfterUpdating = updatedFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def involvedIslsAfterUpdating = updatedFlow.retrieveAllEntityPaths().getInvolvedIsls() involvedIslsAfterUpdating.sort() == involvedIsls.sort() checkBandwidth(involvedIslsAfterUpdating, linksBeforeFlowUpdate, linksAfterFlowUpdate, @@ -85,7 +85,7 @@ class BandwidthSpec extends HealthCheckSpecification { when: "Create a flow to reduce available bandwidth on links of the expected preferable path" def flow1 = flowFactory.getBuilder(switchPair).withBandwidth(minAvailableBandwidth - 100).build().create() - def flow1PathIsls = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flow1PathIsls = flow1.retrieveAllEntityPaths().getInvolvedIsls() then: "The flow is really built through the expected preferable path" flow1PathIsls == preferablePathIsls @@ -95,7 +95,7 @@ class BandwidthSpec extends HealthCheckSpecification { .withBandwidth(101).build().create() then: "The flow is built through longer path where available bandwidth is enough" - def flow2PathIsls = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flow2PathIsls = flow2.retrieveAllEntityPaths().getInvolvedIsls() islHelper.getCost(flow2PathIsls) > islHelper.getCost(flow1PathIsls) } @@ -165,7 +165,7 @@ class BandwidthSpec extends HealthCheckSpecification { then: "Available bandwidth on ISLs is not changed in accordance with flow maximum bandwidth" def linksAfterFlowCreate = northbound.getAllLinks() - def involvedIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def involvedIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() checkBandwidth(involvedIsls, linksBeforeFlowCreate, linksAfterFlowCreate) when: "Update the flow with a bandwidth that exceeds available bandwidth on ISL (ignore_bandwidth = true)" @@ -176,7 +176,7 @@ class BandwidthSpec extends HealthCheckSpecification { and: "Available bandwidth on ISLs is not changed in accordance with new flow maximum bandwidth" def linksAfterFlowUpdate = northbound.getAllLinks() - def involvedIslsAfterUpdating = updatedFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def involvedIslsAfterUpdating = updatedFlow.retrieveAllEntityPaths().getInvolvedIsls() involvedIslsAfterUpdating == involvedIsls checkBandwidth(involvedIslsAfterUpdating, linksBeforeFlowCreate, linksAfterFlowUpdate) @@ -204,7 +204,7 @@ class BandwidthSpec extends HealthCheckSpecification { then: "Only one link is involved in flow path" def initialFlowPath = flow.retrieveAllEntityPaths() - def involvedIsls = initialFlowPath.flowPath.getInvolvedIsls() + def involvedIsls = initialFlowPath.getInvolvedIsls() involvedIsls.size() == 1 involvedIsls == preferablePathIsls @@ -236,7 +236,7 @@ class BandwidthSpec extends HealthCheckSpecification { then: "Available bandwidth on ISLs is not changed in accordance with flow maximum bandwidth" def linksAfterFlowCreate = northbound.getAllLinks() def initialPath = flow.retrieveAllEntityPaths() - checkBandwidth(initialPath.flowPath.getInvolvedIsls(), linksBeforeFlowCreate, linksAfterFlowCreate) + checkBandwidth(initialPath.getInvolvedIsls(), linksBeforeFlowCreate, linksAfterFlowCreate) when: "Update the flow (ignore_bandwidth = false)" flow.update(flow.tap { it.ignoreBandwidth = false }) @@ -255,7 +255,7 @@ class BandwidthSpec extends HealthCheckSpecification { def linksAfterFlowUpdate = northbound.getAllLinks() def flowPathAfterUpdate = flow.retrieveAllEntityPaths() flowPathAfterUpdate == initialPath - checkBandwidth(flowPathAfterUpdate.flowPath.getInvolvedIsls(), linksBeforeFlowCreate, linksAfterFlowUpdate) + checkBandwidth(flowPathAfterUpdate.getInvolvedIsls(), linksBeforeFlowCreate, linksAfterFlowUpdate) } @Tags([LOW_PRIORITY]) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowAffinitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowAffinitySpec.groovy index eb0cd6c6ac..592bf9cbf9 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowAffinitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowAffinitySpec.groovy @@ -108,7 +108,7 @@ class FlowAffinitySpec extends HealthCheckSpecification { .each { islHelper.makePathIslsMorePreferable(flowExpectedPath, it) } def flow = flowFactory.getRandom(swPair1) def initialFlowPath = flow.retrieveAllEntityPaths() - assert initialFlowPath.flowPath.getInvolvedIsls() == flowExpectedPath + assert initialFlowPath.getInvolvedIsls() == flowExpectedPath northbound.deleteLinkProps(northbound.getLinkProps(topology.isls)) and: "Potential affinity flow, which optimal path is diverse from the main flow, but it has a not optimal closer path" @@ -121,7 +121,7 @@ class FlowAffinitySpec extends HealthCheckSpecification { affinityFlow.create() then: "Most optimal, but 'uncommon' to the main flow path is NOT picked, but path with least uncommon ISLs is chosen" - def actualAffinityPathIsls = affinityFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def actualAffinityPathIsls = affinityFlow.retrieveAllEntityPaths().getInvolvedIsls() assert actualAffinityPathIsls != uncommonFlowPathIsls leastUncommonPaths2.find { it.getInvolvedIsls() == actualAffinityPathIsls} @@ -143,8 +143,8 @@ class FlowAffinitySpec extends HealthCheckSpecification { .create() then: "Affinity flow path has no overlapping ISLs with the first flow" - assert affinityFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() - .intersect(flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls()).isEmpty() + assert affinityFlow.retrieveAllEntityPaths().getInvolvedIsls() + .intersect(flow.retrieveAllEntityPaths().getInvolvedIsls()).isEmpty() } def "Affinity flow on the same endpoints #willOrNot take the same path if main path cost #exceedsOrNot affinity penalty"() { @@ -155,7 +155,7 @@ class FlowAffinitySpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(swPair) and: "Isl which is taken by the main flow weighs more/less than the neighboring ISL, taking into account affinity penalty" - def flowIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flowIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() assert flowIsls.size() == 1 islHelper.updateIslsCost([flowIsls[0]], mainIslCost) @@ -163,7 +163,7 @@ class FlowAffinitySpec extends HealthCheckSpecification { def affinityFlow = flowFactory.getBuilder(swPair, false, flow.occupiedEndpoints()) .withAffinityFlow(flow.flowId).build() .create() - def affinityFlowIsls = affinityFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def affinityFlowIsls = affinityFlow.retrieveAllEntityPaths().getInvolvedIsls() then: "It takes/doesn't take the path of the main flow" (flowIsls.sort() == affinityFlowIsls.sort()) == expectSamePaths diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy index 032dfd6584..d23b83c432 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy @@ -432,8 +432,8 @@ class FlowCrudSpec extends HealthCheckSpecification { then: "The flow is built through one of the long paths" def fullFlowPath = flow.retrieveAllEntityPaths() - def forwardIsls = fullFlowPath.flowPath.getInvolvedIsls(Direction.FORWARD) - def reverseIsls = fullFlowPath.flowPath.getInvolvedIsls(Direction.REVERSE) + def forwardIsls = fullFlowPath.getInvolvedIsls(Direction.FORWARD) + def reverseIsls = fullFlowPath.getInvolvedIsls(Direction.REVERSE) assert forwardIsls.intersect(modifiedIsls).isEmpty() assert forwardIsls.size() > shortestIslCountPath @@ -962,7 +962,7 @@ types .* or update switch properties and add needed encapsulation type./).matche def flow = flowFactory.getRandom(switchPair) when: "Make the current path less preferable than alternatives" - def initialFlowIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialFlowIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() }.findAll { !it.containsAll(initialFlowIsls) } .each { islHelper.makePathIslsMorePreferable(it, initialFlowIsls) } @@ -975,7 +975,7 @@ types .* or update switch properties and add needed encapsulation type./).matche def newFlowPath wait(rerouteDelay + WAIT_OFFSET) { newFlowPath = flow.retrieveAllEntityPaths() - assert newFlowPath.flowPath.getInvolvedIsls() != initialFlowIsls + assert newFlowPath.getInvolvedIsls() != initialFlowIsls } and: "Flow is updated" @@ -995,7 +995,7 @@ types .* or update switch properties and add needed encapsulation type./).matche when: "Make the current path less preferable than alternatives" def initialFlowPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialFlowPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialFlowPath.getInvolvedIsls() switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() }.findAll { !it.containsAll(initialFlowIsls) } .each { islHelper.makePathIslsMorePreferable(it, initialFlowIsls) } @@ -1009,7 +1009,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow path is not rebuild" timedLoop(rerouteDelay) { - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialFlowIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialFlowIsls } when: "Update the flow: vlanId on the dst endpoint" @@ -1022,7 +1022,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow path is not rebuild" timedLoop(rerouteDelay) { - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialFlowIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialFlowIsls } when: "Update the flow: port number and vlanId on the src/dst endpoints" @@ -1040,7 +1040,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow path is not rebuild" timedLoop(rerouteDelay + WAIT_OFFSET / 2) { - assert updatedFlow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialFlowIsls + assert updatedFlow.retrieveAllEntityPaths().getInvolvedIsls() == initialFlowIsls } and: "Flow is valid" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudV1Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudV1Spec.groovy index a1db39c3ea..7c38645834 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudV1Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudV1Spec.groovy @@ -449,8 +449,8 @@ class FlowCrudV1Spec extends HealthCheckSpecification { then: "The flow is built through one of the long paths" def fullFlowPath = flow.retrieveAllEntityPaths() - def forwardIsls = fullFlowPath.flowPath.getInvolvedIsls(Direction.FORWARD) - def reverseIsls = fullFlowPath.flowPath.getInvolvedIsls(Direction.REVERSE) + def forwardIsls = fullFlowPath.getInvolvedIsls(Direction.FORWARD) + def reverseIsls = fullFlowPath.getInvolvedIsls(Direction.REVERSE) assert forwardIsls.intersect(modifiedIsls).isEmpty() @@ -522,7 +522,7 @@ Failed to find path with requested bandwidth=$invalidFlow.maximumBandwidth/).mat and: "Flow eventually gets into UP state" flow.waitForBeingInState(UP) - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == flowExpectedPath.getInvolvedIsls() + flow.retrieveAllEntityPaths().getInvolvedIsls() == flowExpectedPath.getInvolvedIsls() and: "All related switches have no discrepancies in rules" switchesId.each { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowDiversitySpec.groovy index 4b97396e0f..c2d9f1ab75 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowDiversitySpec.groovy @@ -77,7 +77,7 @@ class FlowDiversitySpec extends HealthCheckSpecification { and: "All flows have different paths" def allInvolvedIsls = [flow1, flow2, flow3].collectMany { flow -> - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + flow.retrieveAllEntityPaths().getInvolvedIsls() } allInvolvedIsls.unique(false) == allInvolvedIsls @@ -149,7 +149,7 @@ class FlowDiversitySpec extends HealthCheckSpecification { [flow1Path.getPathNodes(), flow2PathUpdated.getPathNodes(), flow3PathUpdated.getPathNodes()].toSet().size() == 3 def allInvolvedIsls = [flow1Path, flow2PathUpdated, flow3PathUpdated].collectMany { path -> - path.flowPath.getInvolvedIsls() + path.getInvolvedIsls() } allInvolvedIsls.unique(false) == allInvolvedIsls } @@ -171,11 +171,11 @@ class FlowDiversitySpec extends HealthCheckSpecification { def (flow1Path, flow2Path, flow3Path) = [flow1, flow2, flow3].collect {flow -> flow.retrieveAllEntityPaths() } - def allInvolvedIsls = [flow1Path, flow2Path, flow3Path].collectMany { path -> path.flowPath.getInvolvedIsls()} + def allInvolvedIsls = [flow1Path, flow2Path, flow3Path].collectMany { path -> path.getInvolvedIsls()} assert allInvolvedIsls.unique(false) == allInvolvedIsls and: "Flow1 path is the most preferable" - def flow1Isls = flow1Path.flowPath.getInvolvedIsls() + def flow1Isls = flow1Path.getInvolvedIsls() switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() }.findAll { !it.containsAll(flow1Isls) } .each { islHelper.makePathIslsMorePreferable(flow1Isls, it) } @@ -185,8 +185,8 @@ class FlowDiversitySpec extends HealthCheckSpecification { then: "The flow became not diverse and rerouted to the more preferable path (path of the first flow)" def flow2PathUpdated = flow2.retrieveAllEntityPaths() - flow2PathUpdated.flowPath.getInvolvedIsls() != flow2Path.flowPath.getInvolvedIsls() - flow2PathUpdated.flowPath.getInvolvedIsls() == flow1Path.flowPath.getInvolvedIsls() + flow2PathUpdated.getInvolvedIsls() != flow2Path.getInvolvedIsls() + flow2PathUpdated.getInvolvedIsls() == flow1Path.getInvolvedIsls() and: "The 'diverse_with' field is removed" !flow2.retrieveDetails().diverseWith @@ -204,8 +204,8 @@ class FlowDiversitySpec extends HealthCheckSpecification { then: "The flow became not diverse and rerouted to the more preferable path (path of the first flow)" def flow3PathUpdated = flow3.retrieveAllEntityPaths() - flow3PathUpdated.flowPath.getInvolvedIsls() != flow3Path.flowPath.getInvolvedIsls() - flow3PathUpdated.flowPath.getInvolvedIsls() == flow1Path.flowPath.getInvolvedIsls() + flow3PathUpdated.getInvolvedIsls() != flow3Path.getInvolvedIsls() + flow3PathUpdated.getInvolvedIsls() == flow1Path.getInvolvedIsls() and: "The 'diverse_with' field is removed" !flow3.retrieveDetails().diverseWith @@ -246,7 +246,7 @@ class FlowDiversitySpec extends HealthCheckSpecification { and: "Create a flow going through these switches" def flow1 = flowFactory.getRandom(switchPair, false) - def initialFlowIsls = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialFlowIsls = flow1.retrieveAllEntityPaths().getInvolvedIsls() and: "Make each alternative path less preferable than the first flow path" def altPaths = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -267,7 +267,7 @@ class FlowDiversitySpec extends HealthCheckSpecification { def flow2Path = flow2.retrieveAllEntityPaths() then: "The flow is built through the most preferable path (path of the first flow)" - flow2Path.flowPath.getInvolvedIsls() == initialFlowIsls + flow2Path.getInvolvedIsls() == initialFlowIsls when: "Create the third flow with diversity enabled" def flow3 = flowFactory.getBuilder(switchPair, false, (flow1.occupiedEndpoints() + flow2.occupiedEndpoints())) @@ -276,8 +276,8 @@ class FlowDiversitySpec extends HealthCheckSpecification { def flow3Path = flow3.retrieveAllEntityPaths() then: "The flow is built through one of alternative paths because they are preferable already" - def involvedIsls = [flow2Path, flow3Path].collectMany {path -> path.flowPath.getInvolvedIsls() } - flow3Path.flowPath.getInvolvedIsls() != flow2Path.flowPath.getInvolvedIsls() + def involvedIsls = [flow2Path, flow3Path].collectMany {path -> path.getInvolvedIsls() } + flow3Path.getInvolvedIsls() != flow2Path.getInvolvedIsls() involvedIsls.unique(false) == involvedIsls } @@ -380,7 +380,7 @@ class FlowDiversitySpec extends HealthCheckSpecification { and: "All flows have different paths" def allInvolvedIsls = [flow1, flow2, flow3].collectMany {flow -> - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + flow.retrieveAllEntityPaths().getInvolvedIsls() } allInvolvedIsls.unique(false) == allInvolvedIsls } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowLoopSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowLoopSpec.groovy index bcf3a4e7f2..9bce1f3d0c 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowLoopSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowLoopSpec.groovy @@ -295,7 +295,7 @@ class FlowLoopSpec extends HealthCheckSpecification { } when: "Fail a flow ISL (bring switch port down)" - def islToFail = flowPath.flowPath.getInvolvedIsls().last() + def islToFail = flowPath.getInvolvedIsls().last() islHelper.breakIsl(islToFail) then: "The flow was rerouted" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowMonitoringSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowMonitoringSpec.groovy index a8619f6fd8..b3042ab772 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowMonitoringSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowMonitoringSpec.groovy @@ -89,7 +89,7 @@ class FlowMonitoringSpec extends HealthCheckSpecification { assert flowStats.of(flow.flowId).get(FLOW_RTT, FORWARD, FLOW_MONITORING).hasNonZeroValues() } - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls when: "Main path does not satisfy SLA(update isl latency via db)" def isl = mainIsls.first() @@ -142,7 +142,7 @@ and flowLatencyMonitoringReactions is disabled in featureToggle"() { wait(flowSlaCheckIntervalSeconds + WAIT_OFFSET * 3) { assert flowStats.of(flow.flowId).get(FLOW_RTT, FORWARD, FLOW_MONITORING).hasNonZeroValues() } - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls when: "Main path does not satisfy SLA(update isl latency via db)" def isl = mainIsls.first() @@ -160,7 +160,7 @@ and flowLatencyMonitoringReactions is disabled in featureToggle"() { !flow.retrieveFlowHistory().getEntriesByType(FlowActionType.REROUTE) and: "Flow path is not changed" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls } def setLatencyForPaths(int mainPathLatency, int alternativePathLatency) { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy index 4383f35066..7774404937 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy @@ -176,7 +176,7 @@ class FlowPingSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(swPair) expectedPingResult.flowId = flow.flowId - assert aswitchPathIsls == flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + assert aswitchPathIsls == flow.retrieveAllEntityPaths().getInvolvedIsls() when: "Break the flow by removing rules from a-switch" def islToBreak = aswitchPathIsls.find { it.aswitch } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/IntentionalRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/IntentionalRerouteSpec.groovy index 5960586119..b3fd8d3ab3 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/IntentionalRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/IntentionalRerouteSpec.groovy @@ -46,7 +46,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .build().create() def initialFlowPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialFlowPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialFlowPath.getInvolvedIsls() when: "Make the current path less preferable than alternatives" def alternativePathsIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -68,7 +68,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == FlowState.UP } !rerouteResponse.rerouted rerouteResponse.path.nodes == initialFlowPath.flowPath.path.forward.nodes.toPathNodeV2() - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialFlowIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == initialFlowIsls } @Tags(ISL_PROPS_DB_RESET) @@ -80,7 +80,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .withEncapsulationType(FlowEncapsulationType.TRANSIT_VLAN) .build().create() def initialPathEntities = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialPathEntities.flowPath.getInvolvedIsls() + def initialFlowIsls = initialPathEntities.getInvolvedIsls() when: "Make one of the alternative paths to be the most preferable among all others" List> availablePathsIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -102,7 +102,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { then: "The flow is successfully rerouted and goes through the preferable path" def newPathEntities = flow.retrieveAllEntityPaths() - def flowNewPathIsls = newPathEntities.flowPath.getInvolvedIsls() + def flowNewPathIsls = newPathEntities.getInvolvedIsls() rerouteResponse.rerouted rerouteResponse.path.nodes == newPathEntities.flowPath.path.forward.nodes.toPathNodeV2() @@ -139,7 +139,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .withBandwidth(0) .withIgnoreBandwidth(true) def flow = flowEntity.build().create() - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == longestPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == longestPathIsls //now make another long path more preferable, for reroute to rebuild the rules on other switches in the future islHelper.updateIslsCost((changedIsls + changedIsls*.reversed) as List, DEFAULT_COST) @@ -187,7 +187,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .build().create() def initialFlowPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialFlowPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialFlowPath.getInvolvedIsls() when: "Make the current path less preferable than alternatives" def alternativePathsIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -211,7 +211,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == FlowState.UP } - def newFlowIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def newFlowIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() newFlowIsls != initialFlowIsls Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == FlowState.UP } @@ -238,7 +238,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .withIgnoreBandwidth(true) .withEncapsulationType(FlowEncapsulationType.VXLAN) .build().create() - def initialFlowIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialFlowIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() def potentialNewPath = availablePathsIsls.findAll { it != initialFlowIsls }.first() availablePathsIsls.findAll { it != potentialNewPath }.each { islHelper.makePathIslsMorePreferable(potentialNewPath, it) } @@ -279,7 +279,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .withBandwidth(10000) .build().create() def initialFlowPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialFlowPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialFlowPath.getInvolvedIsls() when: "Make the current path less preferable than alternatives" def alternativePaths = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -305,7 +305,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { rerouteResponse.path.path == initialFlowPath.flowPath.path.forward.nodes.toPathNode() int seqId = 0 rerouteResponse.path.path.each { assert it.seqId == seqId++ } - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialFlowIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == initialFlowIsls } @Tags([LOW_PRIORITY, ISL_PROPS_DB_RESET]) @@ -316,7 +316,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { .withBandwidth(10000) .build().create() def initialFlowPath = flow.retrieveAllEntityPaths() - def initialFlowIsls = initialFlowPath.flowPath.getInvolvedIsls() + def initialFlowIsls = initialFlowPath.getInvolvedIsls() when: "Make one of the alternative paths to be the most preferable among all others" def availablePathsIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } @@ -337,7 +337,7 @@ class IntentionalRerouteSpec extends HealthCheckSpecification { then: "The flow is successfully rerouted and goes through the preferable path" def newFlowPath = flow.retrieveAllEntityPaths() - def newFlowIsls = newFlowPath.flowPath.getInvolvedIsls() + def newFlowIsls = newFlowPath.getInvolvedIsls() int seqId = 0 rerouteResponse.rerouted diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MaxLatencySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MaxLatencySpec.groovy index ebf6de2b4b..7df7db80a0 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MaxLatencySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MaxLatencySpec.groovy @@ -13,8 +13,6 @@ import org.openkilda.functionaltests.helpers.model.FlowActionType import org.openkilda.functionaltests.helpers.model.PathComputationStrategy import org.openkilda.functionaltests.helpers.model.SwitchPair import org.openkilda.functionaltests.model.cleanup.CleanupAfter -import org.openkilda.functionaltests.model.stats.Direction -import org.openkilda.messaging.info.event.PathNode import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.StatusInfo import org.openkilda.testing.model.topology.TopologyDefinition.Isl @@ -85,8 +83,8 @@ class MaxLatencySpec extends HealthCheckSpecification { then: "Flow is created, main path is the 15 latency path, protected is 10 latency" def flowPath = flow.retrieveAllEntityPaths() - flowPath.flowPath.getMainPathInvolvedIsls() == alternativeIsls - flowPath.flowPath.getProtectedPathInvolvedIsls() == mainIsls + flowPath.getMainPathInvolvedIsls() == alternativeIsls + flowPath.getProtectedPathInvolvedIsls() == mainIsls } @Tags([LOW_PRIORITY]) @@ -126,8 +124,8 @@ class MaxLatencySpec extends HealthCheckSpecification { then: "Flow is created, main path is the 10 latency path, protected is 15 latency" and: "Flow goes to DEGRADED state" def flowPath = flow.retrieveAllEntityPaths() - flowPath.flowPath.getMainPathInvolvedIsls() == mainIsls - flowPath.flowPath.getProtectedPathInvolvedIsls() == alternativeIsls + flowPath.getMainPathInvolvedIsls() == mainIsls + flowPath.getProtectedPathInvolvedIsls() == alternativeIsls } @Tags([LOW_PRIORITY]) @@ -144,7 +142,7 @@ class MaxLatencySpec extends HealthCheckSpecification { .build().create(DEGRADED) then: "Flow is created, flow path is the 15 latency path" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == alternativeIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == alternativeIsls } @Tags([LOW_PRIORITY]) @@ -160,7 +158,7 @@ class MaxLatencySpec extends HealthCheckSpecification { .withPathComputationStrategy(PathComputationStrategy.MAX_LATENCY) .build().create() //flow path is the 10 latency path - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls and: "Update the flow(maxLatency: 10)" def newMaxLatency = 10 @@ -177,7 +175,7 @@ class MaxLatencySpec extends HealthCheckSpecification { for example: reroute can be triggered by blinking/activating any isl (not involved in flow path)*/ assert northboundV2.getFlowHistoryStatuses(flow.flowId).historyStatuses*.statusBecome[0..1] == ["UP", "DEGRADED"] } - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == alternativeIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == alternativeIsls } def "Able to reroute a MAX_LATENCY flow if maxLatencyTier2 > pathLatency > maxLatency"() { @@ -191,7 +189,7 @@ class MaxLatencySpec extends HealthCheckSpecification { .withMaxLatencyTier2(16) .withPathComputationStrategy(PathComputationStrategy.MAX_LATENCY) .build().create() - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls and: "Init auto reroute (bring port down on the src switch)" setLatencyForPaths(10, 15) @@ -209,7 +207,7 @@ class MaxLatencySpec extends HealthCheckSpecification { assert flowInfo.status == DEGRADED assert flowInfo.statusInfo == StatusInfo.BACK_UP_STRATEGY_USED } - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == alternativeIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == alternativeIsls } def "Able to create DEGRADED flow with LATENCY strategy if max_latency_tier_2 > flowPath > max_latency"() { @@ -226,7 +224,7 @@ class MaxLatencySpec extends HealthCheckSpecification { then: "Flow is created in DEGRADED state because flowPath doesn't satisfy max_latency value \ but satisfies max_latency_tier2" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls } @Tags([LOW_PRIORITY]) @@ -243,7 +241,7 @@ but satisfies max_latency_tier2" .build().create() then: "Flow is created in UP" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls } @Tags([LOW_PRIORITY]) @@ -277,7 +275,7 @@ but satisfies max_latency_tier2" .withPathComputationStrategy(PathComputationStrategy.LATENCY) .build().create() - assert flow.retrieveAllEntityPaths().getFlowPath().getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls when: "Break the flow path to init autoReroute" def islToBreak = mainIsls.first() @@ -290,7 +288,7 @@ but satisfies max_latency_tier2" it.statusInfo.contains("No path found.") } } - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainIsls } def setLatencyForPaths(int mainPathLatency, int alternativePathLatency) { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MultiRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MultiRerouteSpec.groovy index 2b9823ccbc..a7d51b18d1 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MultiRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MultiRerouteSpec.groovy @@ -42,7 +42,7 @@ class MultiRerouteSpec extends HealthCheckSpecification { } //ensure all flows are on the same path flows[1..-1].each { - assert it.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == currentPathIsls + assert it.retrieveAllEntityPaths().getInvolvedIsls() == currentPathIsls } when: "Make another path more preferable" @@ -70,7 +70,7 @@ class MultiRerouteSpec extends HealthCheckSpecification { wait(WAIT_OFFSET * 3) { def assertions = new SoftAssertions() flowsOnPrefPath = flows.findAll { - it.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == prefPathIsls + it.retrieveAllEntityPaths().getInvolvedIsls() == prefPathIsls } flowsOnPrefPath.each { flow -> assertions.checkSucceeds { assert flow.retrieveFlowStatus().status == FlowState.UP } @@ -85,7 +85,7 @@ class MultiRerouteSpec extends HealthCheckSpecification { def assertions = new SoftAssertions() restFlows.each { flow -> assertions.checkSucceeds { assert flow.retrieveFlowStatus().status == FlowState.UP } - assertions.checkSucceeds { assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() != prefPathIsls } + assertions.checkSucceeds { assert flow.retrieveAllEntityPaths().getInvolvedIsls() != prefPathIsls } } assertions.verify() } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy index 1f9e34cfc9..0fc34f331b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy @@ -221,8 +221,8 @@ class PartialUpdateSpec extends HealthCheckSpecification { flow2.partialUpdate(updateRequest) then: "Flows use diverse paths" - def flow1InvolvedIsls = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() - def flow2InvolvedIsls = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flow1InvolvedIsls = flow1.retrieveAllEntityPaths().getInvolvedIsls() + def flow2InvolvedIsls = flow2.retrieveAllEntityPaths().getInvolvedIsls() flow1InvolvedIsls.intersect(flow2InvolvedIsls).empty } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy index e26b85c711..2f9412d2b0 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy @@ -96,7 +96,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { .build().create() def allEntityPath = flow.retrieveAllEntityPaths() - def initialPathIsls = allEntityPath.flowPath.getInvolvedIsls() + def initialPathIsls = allEntityPath.getInvolvedIsls() List altPathIsls = allPaths.findAll { it != initialPathIsls }.min { it.size() } def involvedSwitches = allEntityPath.getInvolvedSwitches() @@ -126,7 +126,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { Wrappers.timedLoop(2) { assert flow.retrieveFlowStatus().status == FlowState.DOWN //do not check history here. In parallel environment it may be overriden by 'up' event on another island - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialPathIsls } } islHelper.breakIsls(islsToBreak[1..-1]) @@ -154,7 +154,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { Wrappers.wait(WAIT_OFFSET + discoveryInterval) { islsToBreak[0..-2].each { assert islUtils.getIslInfo(it).get().state == IslChangeType.DISCOVERED } assert flow.retrieveFlowStatus().status == FlowState.DOWN - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialPathIsls } and: "Restore the last ISL" @@ -163,7 +163,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { then: "Flow is marked as UP when the last ISL is restored" Wrappers.wait(WAIT_OFFSET * 2) { assert flow.retrieveFlowStatus().status == FlowState.UP - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialPathIsls } } @@ -174,7 +174,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { def flow = flowFactory.getBuilder(switchPair) .withPinned(true) .build().create() - def initialPathIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialPathIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() when: "Make another path more preferable" def newPathIsls = availablePaths.find { it != initialPathIsls } @@ -188,7 +188,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { affectedFlows == [flow.flowId] Wrappers.timedLoop(4) { assert flow.retrieveFlowStatus().status == FlowState.UP - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialPathIsls } } @@ -199,7 +199,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { def flow = flowFactory.getBuilder(switchPair) .withPinned(true) .build().create() - def initialPathIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialPathIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() when: "Make another path more preferable" def newPath = availablePaths.find { it != initialPathIsls } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathSpec.groovy index aa9a16a8b5..47f1b22bfa 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathSpec.groovy @@ -227,8 +227,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPath = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPath =flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPath = flowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPath = flowPathInfo.getProtectedPathInvolvedIsls() initialMainPath.intersect(initialProtectedPath).isEmpty() and: "Rules for main and protected paths are created" @@ -273,8 +273,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Flow paths are swapped" flow.waitForBeingInState(FlowState.UP) def flowPathInfoAfterSwapping = flow.retrieveAllEntityPaths() - def newMainPath = flowPathInfoAfterSwapping.flowPath.getMainPathInvolvedIsls() - def newProtectedPath = flowPathInfoAfterSwapping.flowPath.getProtectedPathInvolvedIsls() + def newMainPath = flowPathInfoAfterSwapping.getMainPathInvolvedIsls() + def newProtectedPath = flowPathInfoAfterSwapping.getProtectedPathInvolvedIsls() verifyAll { assert newMainPath == initialProtectedPath assert newProtectedPath == initialMainPath @@ -359,13 +359,13 @@ class ProtectedPathSpec extends HealthCheckSpecification { flowPathsInfo.each { assert !it.flowPath.protectedPath.isPathAbsent()} and: "Current paths are not equal to protected paths" - def firstFlowMainPathIsls = flowPathsInfo.first().flowPath.getMainPathInvolvedIsls() - def firstFlowProtectedPathIsls = flowPathsInfo.first().flowPath.getProtectedPathInvolvedIsls() + def firstFlowMainPathIsls = flowPathsInfo.first().getMainPathInvolvedIsls() + def firstFlowProtectedPathIsls = flowPathsInfo.first().getProtectedPathInvolvedIsls() assert firstFlowMainPathIsls.intersect(firstFlowProtectedPathIsls).isEmpty() //check that all other flows use the same paths, so above verification applies to all of them flowPathsInfo.each { flowPathInfo -> - assert flowPathInfo.flowPath.getMainPathInvolvedIsls() == firstFlowMainPathIsls - assert flowPathInfo.flowPath.getProtectedPathInvolvedIsls() == firstFlowProtectedPathIsls + assert flowPathInfo.getMainPathInvolvedIsls() == firstFlowMainPathIsls + assert flowPathInfo.getProtectedPathInvolvedIsls() == firstFlowProtectedPathIsls } and: "Bandwidth is reserved for protected paths on involved ISLs" @@ -388,11 +388,11 @@ class ProtectedPathSpec extends HealthCheckSpecification { assert flow.retrieveFlowStatus().status == FlowState.UP def flowPathInfoAfterRerouting = flow.retrieveAllEntityPaths() - assert flowPathInfoAfterRerouting.flowPath.getMainPathInvolvedIsls() == firstFlowProtectedPathIsls + assert flowPathInfoAfterRerouting.getMainPathInvolvedIsls() == firstFlowProtectedPathIsls if (4 <= uniquePathCount) { // protected path is recalculated due to the main path broken ISl - assert flowPathInfoAfterRerouting.flowPath.getProtectedPathInvolvedIsls() != firstFlowMainPathIsls - assert flowPathInfoAfterRerouting.flowPath.getProtectedPathInvolvedIsls() != firstFlowProtectedPathIsls + assert flowPathInfoAfterRerouting.getProtectedPathInvolvedIsls() != firstFlowMainPathIsls + assert flowPathInfoAfterRerouting.getProtectedPathInvolvedIsls() != firstFlowProtectedPathIsls } } } @@ -403,7 +403,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Path of the flow is not changed" flows.each { flow -> flow.waitForBeingInState(FlowState.UP) - assert flow.retrieveAllEntityPaths().flowPath.getMainPathInvolvedIsls() == firstFlowProtectedPathIsls + assert flow.retrieveAllEntityPaths().getMainPathInvolvedIsls() == firstFlowProtectedPathIsls } where: @@ -422,8 +422,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def initialFlowPath = flow.retrieveAllEntityPaths() and: "Other paths have not enough bandwidth to host the flow in case of reroute" - def originalMainPathIsls = initialFlowPath.flowPath.getMainPathInvolvedIsls() - def originalProtectedPathIsls = initialFlowPath.flowPath.getProtectedPathInvolvedIsls() + def originalMainPathIsls = initialFlowPath.getMainPathInvolvedIsls() + def originalProtectedPathIsls = initialFlowPath.getProtectedPathInvolvedIsls() def usedIsls = originalMainPathIsls + originalProtectedPathIsls def otherIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } .findAll { !it.containsAll(originalMainPathIsls) && !it.containsAll(originalProtectedPathIsls) }.flatten() @@ -438,7 +438,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Main path swaps to protected, flow becomes degraded, main path UP, protected DOWN" Wrappers.wait(WAIT_OFFSET) { def newPath = flow.retrieveAllEntityPaths() - assert newPath.flowPath.getMainPathInvolvedIsls() == originalProtectedPathIsls + assert newPath.getMainPathInvolvedIsls() == originalProtectedPathIsls verifyAll(flow.retrieveDetails()) { status == FlowState.DEGRADED statusDetails.mainPath == "Up" @@ -453,7 +453,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Main path remains the same, flow becomes UP, main path UP, protected UP" Wrappers.wait(WAIT_OFFSET * 2) { def newPath = flow.retrieveAllEntityPaths() - assert newPath.flowPath.getMainPathInvolvedIsls() == originalProtectedPathIsls + assert newPath.getMainPathInvolvedIsls() == originalProtectedPathIsls verifyAll(flow.retrieveDetails()) { status == FlowState.UP statusDetails.mainPath == "Up" @@ -473,8 +473,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def initialFlowPath = flow.retrieveAllEntityPaths() and: "Other paths are not available (ISLs are down)" - def originalMainPathIsls = initialFlowPath.flowPath.getMainPathInvolvedIsls() - def originalProtectedPathIsls = initialFlowPath.flowPath.getProtectedPathInvolvedIsls() + def originalMainPathIsls = initialFlowPath.getMainPathInvolvedIsls() + def originalProtectedPathIsls = initialFlowPath.getProtectedPathInvolvedIsls() def usedIsls = originalMainPathIsls + originalProtectedPathIsls def otherIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls()} .findAll { it != originalMainPathIsls && it != originalProtectedPathIsls }.flatten() @@ -489,7 +489,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Main path swaps to protected, flow becomes degraded, main path UP, protected DOWN" Wrappers.wait(WAIT_OFFSET) { def newPath = flow.retrieveAllEntityPaths() - assert newPath.flowPath.getMainPathInvolvedIsls() == originalProtectedPathIsls + assert newPath.getMainPathInvolvedIsls() == originalProtectedPathIsls verifyAll(flow.retrieveDetails()) { status == FlowState.DEGRADED statusDetails.mainPath == "Up" @@ -504,8 +504,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Main path remains the same (no swap), flow becomes UP, main path remains UP, protected path becomes UP" Wrappers.wait(WAIT_OFFSET) { def newPath = flow.retrieveAllEntityPaths() - assert newPath.flowPath.getMainPathInvolvedIsls() == originalProtectedPathIsls - assert newPath.flowPath.getProtectedPathInvolvedIsls() == originalMainPathIsls + assert newPath.getMainPathInvolvedIsls() == originalProtectedPathIsls + assert newPath.getProtectedPathInvolvedIsls() == originalMainPathIsls verifyAll(flow.retrieveDetails()) { status == FlowState.UP statusDetails.mainPath == "Up" @@ -530,8 +530,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPathIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPathIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPathIsls = flowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPathIsls = flowPathInfo.getProtectedPathInvolvedIsls() assert initialMainPathIsls.intersect(initialProtectedPathIsls).isEmpty() when: "Make the current and protected path less preferable than alternatives" @@ -551,11 +551,11 @@ class ProtectedPathSpec extends HealthCheckSpecification { and: "Path is not changed to protected path" def flowPathInfoAfterRerouting = flow.retrieveAllEntityPaths() - def mainPathIsls = flowPathInfoAfterRerouting.flowPath.getMainPathInvolvedIsls() + def mainPathIsls = flowPathInfoAfterRerouting.getMainPathInvolvedIsls() mainPathIsls != initialMainPathIsls mainPathIsls != initialProtectedPathIsls //protected path is rerouted too, because more preferable path is exist - def newCurrentProtectedPathIsls = flowPathInfoAfterRerouting.flowPath.getProtectedPathInvolvedIsls() + def newCurrentProtectedPathIsls = flowPathInfoAfterRerouting.getProtectedPathInvolvedIsls() newCurrentProtectedPathIsls != initialMainPathIsls newCurrentProtectedPathIsls != initialProtectedPathIsls Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == FlowState.UP } @@ -583,8 +583,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPathIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPathIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPathIsls = flowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPathIsls = flowPathInfo.getProtectedPathInvolvedIsls() assert initialMainPathIsls.intersect(initialProtectedPathIsls).isEmpty() when: "Make the current and protected path less preferable than alternatives" @@ -600,12 +600,12 @@ class ProtectedPathSpec extends HealthCheckSpecification { then: "Flow is switched to protected path" Wrappers.wait(PROTECTED_PATH_INSTALLATION_TIME) { def newPathInfo = flow.retrieveAllEntityPaths() - def newMainPath = newPathInfo.flowPath.getMainPathInvolvedIsls() + def newMainPath = newPathInfo.getMainPathInvolvedIsls() assert flow.retrieveFlowStatus().status == FlowState.UP assert newMainPath != initialMainPathIsls assert newMainPath == initialProtectedPathIsls - def newCurrentProtectedPath = newPathInfo.flowPath.getProtectedPathInvolvedIsls() + def newCurrentProtectedPath = newPathInfo.getProtectedPathInvolvedIsls() if (4 <= uniquePathCount) { assert newCurrentProtectedPath != initialMainPathIsls assert newCurrentProtectedPath != initialProtectedPathIsls @@ -616,7 +616,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { islHelper.restoreIsl(islToBreak) then: "Path of the flow is not changed" - flow.retrieveAllEntityPaths().flowPath.getMainPathInvolvedIsls() == initialProtectedPathIsls + flow.retrieveAllEntityPaths().getMainPathInvolvedIsls() == initialProtectedPathIsls where: flowDescription | bandwidth @@ -635,8 +635,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPath = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPath = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPath = flowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPath = flowPathInfo.getProtectedPathInvolvedIsls() when: "Init intentional reroute" def rerouteResponse = flow.reroute() @@ -645,8 +645,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { !rerouteResponse.rerouted def newFlowPathInfo = flow.retrieveAllEntityPaths() - newFlowPathInfo.flowPath.getMainPathInvolvedIsls() == initialMainPath - newFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() == initialProtectedPath + newFlowPathInfo.getMainPathInvolvedIsls() == initialMainPath + newFlowPathInfo.getProtectedPathInvolvedIsls() == initialProtectedPath } @Tags([LOW_PRIORITY, ISL_PROPS_DB_RESET]) @@ -718,8 +718,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def initialFlowPathInfo = flow.retrieveAllEntityPaths() !initialFlowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPathIsls = initialFlowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPathIsls = initialFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPathIsls = initialFlowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPathIsls = initialFlowPathInfo.getProtectedPathInvolvedIsls() assert initialMainPathIsls.intersect(initialProtectedPathIsls).isEmpty() def protectedIslsInfo = initialProtectedPathIsls.collect { islUtils.getIslInfo(it).get() } @@ -739,17 +739,17 @@ class ProtectedPathSpec extends HealthCheckSpecification { FlowEntityPath newFlowPathInfo Wrappers.wait(PROTECTED_PATH_INSTALLATION_TIME) { newFlowPathInfo = flow.retrieveAllEntityPaths() - assert newFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() != initialProtectedPathIsls + assert newFlowPathInfo.getProtectedPathInvolvedIsls() != initialProtectedPathIsls assert flow.retrieveFlowStatus().status == FlowState.UP } and: "Current path is not changed" - initialMainPathIsls == newFlowPathInfo.flowPath.getMainPathInvolvedIsls() + initialMainPathIsls == newFlowPathInfo.getMainPathInvolvedIsls() and: "Bandwidth is reserved for new protected path on involved ISLs" def allLinks Wrappers.wait(PROTECTED_PATH_INSTALLATION_TIME) { - def newProtectedIsls = newFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def newProtectedIsls = newFlowPathInfo.getProtectedPathInvolvedIsls() allLinks = northbound.getAllLinks() def newProtectedIslsInfo = newProtectedIsls.collect { islUtils.getIslInfo(allLinks, it).get() } @@ -775,7 +775,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { islHelper.restoreIsl(islToBreakProtectedPath) then: "Path is not recalculated again" - flow.retrieveAllEntityPaths().flowPath.getProtectedPathInvolvedIsls()== newFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() + flow.retrieveAllEntityPaths().getProtectedPathInvolvedIsls()== newFlowPathInfo.getProtectedPathInvolvedIsls() } @Tags(ISL_RECOVER_ON_FAIL) @@ -794,7 +794,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { def initialFlowPathInfo = flow.retrieveAllEntityPaths() and: "All alternative paths are unavailable (bring ports down on the source switch)" - def flowPathPortOnSourceSwitch = initialFlowPathInfo.flowPath.getMainPathInvolvedIsls().first().srcPort + def flowPathPortOnSourceSwitch = initialFlowPathInfo.getMainPathInvolvedIsls().first().srcPort def broughtDownIsls = topology.getRelatedIsls(switchPair.getSrc()) .findAll{it.srcSwitch == switchPair.getSrc() && it.srcPort != flowPathPortOnSourceSwitch } islHelper.breakIsls(broughtDownIsls) @@ -831,7 +831,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() when: "All alternative paths are unavailable" - def mainPathIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() + def mainPathIsls = flowPathInfo.getMainPathInvolvedIsls() def untouchableIsls = mainPathIsls.collectMany { [it, it.reversed] } def altPaths = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } .findAll { !it.containsAll(mainPathIsls) } @@ -879,8 +879,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { when: "Main paths breaks" def flowPathInfo = flow.retrieveAllEntityPaths() - def mainPathIsl = flowPathInfo.flowPath.getMainPathInvolvedIsls().first() - def protectedPathIsl = flowPathInfo.flowPath.getProtectedPathInvolvedIsls().first() + def mainPathIsl = flowPathInfo.getMainPathInvolvedIsls().first() + def protectedPathIsl = flowPathInfo.getProtectedPathInvolvedIsls().first() islHelper.breakIsl(mainPathIsl) and: "Protected path breaks when swap is in progress" @@ -895,8 +895,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { Wrappers.timedLoop(3) { //this should be a stable result, all reroutes must finish assert flow.retrieveFlowStatus().status == FlowState.UP def currentPath = flow.retrieveAllEntityPaths() - assert currentPath.flowPath.getMainPathInvolvedIsls().intersect([mainPathIsl, protectedPathIsl]).isEmpty() - assert currentPath.flowPath.getProtectedPathInvolvedIsls().intersect([mainPathIsl, protectedPathIsl]).isEmpty() + assert currentPath.getMainPathInvolvedIsls().intersect([mainPathIsl, protectedPathIsl]).isEmpty() + assert currentPath.getProtectedPathInvolvedIsls().intersect([mainPathIsl, protectedPathIsl]).isEmpty() } } @@ -915,8 +915,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def initialMainPathIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def initialProtectedPathIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def initialMainPathIsls = flowPathInfo.getMainPathInvolvedIsls() + def initialProtectedPathIsls = flowPathInfo.getProtectedPathInvolvedIsls() assert initialMainPathIsls.intersect(initialProtectedPathIsls).isEmpty() when: "Make the current and protected path less preferable than alternatives" @@ -938,12 +938,12 @@ class ProtectedPathSpec extends HealthCheckSpecification { def newMainPath Wrappers.wait(RULES_INSTALLATION_TIME) { flowPathInfoAfterRerouting = flow.retrieveAllEntityPaths() - newMainPath = flowPathInfoAfterRerouting.flowPath.getMainPathInvolvedIsls() + newMainPath = flowPathInfoAfterRerouting.getMainPathInvolvedIsls() newMainPath != initialMainPathIsls && newMainPath != initialProtectedPathIsls } and: "Flow protected path shouldn't be rerouted due to lack of non overlapping path" - flowPathInfoAfterRerouting.flowPath.getProtectedPathInvolvedIsls() == initialProtectedPathIsls + flowPathInfoAfterRerouting.getProtectedPathInvolvedIsls() == initialProtectedPathIsls and: "Flow and both its paths are UP" Wrappers.wait(WAIT_OFFSET) { @@ -974,7 +974,7 @@ class ProtectedPathSpec extends HealthCheckSpecification { } ?: assumeTrue(false, "No suiting switches found") //select paths for further manipulations - def availablePathsIsls = swPair.retrieveAvailablePaths().collect { it.getInvolvedIsls()} + def availablePathsIsls = allPathCandidates.collect { it.getInvolvedIsls()} def mainPath1Isls = availablePathsIsls.first() def mainPath2Isls = availablePathsIsls.find { it != mainPath1Isls } def protectedPathIsls = availablePathsIsls.find { it != mainPath1Isls && it != mainPath2Isls } @@ -1120,14 +1120,14 @@ class ProtectedPathSpec extends HealthCheckSpecification { def flow = flowFactory.getBuilder(switchPair).withProtectedPath(true).build().create() and: "All alternative paths are unavailable (bring ports down on the source switch)" - def flowPathIsl = flow.retrieveAllEntityPaths().flowPath.getMainPathInvolvedIsls() + def flowPathIsl = flow.retrieveAllEntityPaths().getMainPathInvolvedIsls() def broughtDownIsls = topology.getRelatedIsls(switchPair.src) - flowPathIsl islHelper.breakIsls(broughtDownIsls) when: "Break ISL on a protected path (bring port down) for changing the flow state to DEGRADED" def flowPathInfo = flow.retrieveAllEntityPaths() - def protectedIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() - def currentIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() + def protectedIsls = flowPathInfo.getProtectedPathInvolvedIsls() + def currentIsls = flowPathInfo.getMainPathInvolvedIsls() islHelper.breakIsl(protectedIsls[0]) then: "Flow state is changed to DEGRADED" @@ -1257,8 +1257,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { and: "All alternative paths are unavailable (bring ports down on the source switch)" def initialFlowPathInfo = flow.retrieveAllEntityPaths() - def mainPathIsl = initialFlowPathInfo.flowPath.getMainPathInvolvedIsls() - def protectedIslToBreak = initialFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def mainPathIsl = initialFlowPathInfo.getMainPathInvolvedIsls() + def protectedIslToBreak = initialFlowPathInfo.getProtectedPathInvolvedIsls() def broughtDownIsls = topology.getRelatedIsls(switchPair.src) - mainPathIsl.first() - protectedIslToBreak.first() islHelper.breakIsls(broughtDownIsls) @@ -1284,8 +1284,8 @@ class ProtectedPathSpec extends HealthCheckSpecification { and: "Protected path is recalculated only" def newFlowPathInfo = flow.retrieveAllEntityPaths() - newFlowPathInfo.flowPath.getMainPathInvolvedIsls() == mainPathIsl - newFlowPathInfo.flowPath.getProtectedPathInvolvedIsls() == alternativeIsl + newFlowPathInfo.getMainPathInvolvedIsls() == mainPathIsl + newFlowPathInfo.getProtectedPathInvolvedIsls() == alternativeIsl } @Tags(LOW_PRIORITY) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathV1Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathV1Spec.groovy index a9de6059ec..48ee89e87c 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathV1Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ProtectedPathV1Spec.groovy @@ -444,14 +444,14 @@ class ProtectedPathV1Spec extends HealthCheckSpecification { .createV1() and: "All alternative paths are unavailable (bring ports down on the source switch)" - def flowPathIsl = flow.retrieveAllEntityPaths().flowPath.getMainPathInvolvedIsls() + def flowPathIsl = flow.retrieveAllEntityPaths().getMainPathInvolvedIsls() def broughtDownIsls = topology.getRelatedIsls(switchPair.src) - flowPathIsl islHelper.breakIsls(broughtDownIsls) when: "Break ISL on a protected path (bring port down) for changing the flow state to DEGRADED" def flowPathInfo = flow.retrieveAllEntityPaths() - def protectedIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() - def currentIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() + def protectedIsls = flowPathInfo.getProtectedPathInvolvedIsls() + def currentIsls = flowPathInfo.getMainPathInvolvedIsls() islHelper.breakIsl(protectedIsls[0]) then: "Flow state is changed to DEGRADED" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy index f1768001b5..5c98650597 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy @@ -748,7 +748,7 @@ class QinQFlowSpec extends HealthCheckSpecification { def flow = flowEntity.create() when: "Make the current path less preferable than alternatives" - def initialPathIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def initialPathIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() }.findAll { it != initialPathIsls } .each { islHelper.makePathIslsMorePreferable(it, initialPathIsls) } @@ -767,7 +767,7 @@ class QinQFlowSpec extends HealthCheckSpecification { and: "Flow is not rerouted" Wrappers.timedLoop(rerouteDelay + WAIT_OFFSET / 2) { - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == initialPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == initialPathIsls } and: "System allows traffic on the flow" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/SwapEndpointSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/SwapEndpointSpec.groovy index 1516e65ce4..4a86fdea35 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/SwapEndpointSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/SwapEndpointSpec.groovy @@ -750,7 +750,7 @@ switches"() { def flow2 = getSecondFlow(flow1SwitchPair, flow2SwitchPair, flow1).create() and: "Update the first flow so that it consumes all bandwidth on the link" - def flow1Isl = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow1Isl = flow1.retrieveAllEntityPaths().getInvolvedIsls().first() def flow1IslMaxBw = islUtils.getIslInfo(flow1Isl).get().maxBandwidth flow1.update(flow1.tap { it.maximumBandwidth = flow1IslMaxBw }) @@ -760,7 +760,7 @@ switches"() { islHelper.breakIsls(broughtDownIsls) and: "Update max bandwidth for the second flow's link so that it is equal to max bandwidth of the first flow" - def flow2Isl = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow2Isl = flow2.retrieveAllEntityPaths().getInvolvedIsls().first() islHelper.updateLinkMaxBandwidthUsingApi(flow2Isl, flow1IslMaxBw) and: "Break all alternative paths for the second flow" @@ -806,7 +806,7 @@ switches"() { def flow2 = getSecondFlow(flow1SwitchPair, flow2SwitchPair, flow1).create() and: "Update the first flow so that it consumes all bandwidth on the link" - def flow1Isl = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow1Isl = flow1.retrieveAllEntityPaths().getInvolvedIsls().first() def flow1IslMaxBw = islUtils.getIslInfo(flow1Isl).get().maxBandwidth flow1.update(flow1.tap { it.maximumBandwidth = flow1IslMaxBw }) @@ -816,7 +816,7 @@ switches"() { islHelper.breakIsls(broughtDownIsls) and: "Update max bandwidth for the second flow's link so that it is not enough bandwidth for the first flow" - def flow2Isl = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow2Isl = flow2.retrieveAllEntityPaths().getInvolvedIsls().first() islHelper.updateLinkMaxBandwidthUsingApi(flow2Isl, flow1IslMaxBw - 1) and: "Break all alternative paths for the second flow" @@ -855,7 +855,7 @@ switches"() { def flow2 = getSecondFlow(flow1SwitchPair, flow2SwitchPair, flow1).create() and: "Update the first flow so that it consumes all bandwidth on the link" - def flow1Isl = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow1Isl = flow1.retrieveAllEntityPaths().getInvolvedIsls().first() def flow1IslMaxBw = islUtils.getIslInfo(flow1Isl).get().maxBandwidth flow1.update(flow1.tap { it.maximumBandwidth = flow1IslMaxBw }) @@ -865,7 +865,7 @@ switches"() { islHelper.breakIsls(broughtDownIsls) and: "Update max bandwidth for the second flow's link so that it is not enough bandwidth for the first flow" - def flow2Isl = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def flow2Isl = flow2.retrieveAllEntityPaths().getInvolvedIsls().first() islHelper.updateLinkMaxBandwidthUsingApi(flow2Isl, flow1IslMaxBw - 1) and: "Break all alternative paths for the second flow" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy index ae43a9033a..7bb875885c 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy @@ -461,7 +461,7 @@ class VxlanFlowSpec extends HealthCheckSpecification { .build().create() then: "Flow is built through vxlan-enabled path, even though it is not the shortest" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() != noVxlanPathIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() != noVxlanPathIsls } @Tags([LOW_PRIORITY, TOPOLOGY_DEPENDENT]) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy index cee700edab..4aa5c5027d 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy @@ -98,7 +98,7 @@ class YFlowDiversitySpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(swT.shared, swT.ep1, false) def subFlowId = yFlow.subFlows.first().flowId def involvedIslSubFlow = yFlow.retrieveAllEntityPaths().subFlowPaths.find { it.flowId == subFlowId }.getInvolvedIsls() - def involvedIslSimpleFlow = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def involvedIslSimpleFlow = flow.retrieveAllEntityPaths().getInvolvedIsls() assert involvedIslSubFlow == involvedIslSimpleFlow when: "Update Y-Flow to become diverse with simple multiSwitch flow" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkMaintenanceSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkMaintenanceSpec.groovy index 71f123ec57..2445d103ba 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkMaintenanceSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkMaintenanceSpec.groovy @@ -61,7 +61,7 @@ class LinkMaintenanceSpec extends HealthCheckSpecification { assert flow1Path.getPathNodes() == flow2Path.getPathNodes() when: "Set maintenance mode without flows evacuation flag for the first link involved in flow paths" - def isl = flow1Path.flowPath.getInvolvedIsls().first() + def isl = flow1Path.getInvolvedIsls().first() islHelper.setLinkMaintenance(isl, true, false) then: "Flows are not evacuated (rerouted) and have the same paths" @@ -84,8 +84,8 @@ class LinkMaintenanceSpec extends HealthCheckSpecification { } and: "Link under maintenance is not involved in new flow paths" - !flow1PathUpdated.flowPath.getInvolvedIsls().contains(isl) - !flow2PathUpdated.flowPath.getInvolvedIsls().contains(isl) + !flow1PathUpdated.getInvolvedIsls().contains(isl) + !flow2PathUpdated.getInvolvedIsls().contains(isl) } @Tags(ISL_RECOVER_ON_FAIL) @@ -102,7 +102,7 @@ class LinkMaintenanceSpec extends HealthCheckSpecification { assert flow1Path.getPathNodes() == flow2Path.getPathNodes() and: "Make only one alternative path available for both flows" - def flow1ActualIsl = flow1Path.flowPath.getInvolvedIsls().first() + def flow1ActualIsl = flow1Path.getInvolvedIsls().first() def altIsls = topology.getRelatedIsls(switchPair.src) - flow1ActualIsl /* altIsls can have only 1 element (the only one alt ISL). In this case it will be set under maintenance mode, and breaking the other @@ -125,8 +125,8 @@ class LinkMaintenanceSpec extends HealthCheckSpecification { assert flow1PathUpdated != flow1Path assert flow2PathUpdated != flow2Path - assert flow1PathUpdated.flowPath.getInvolvedIsls().contains(islUnderMaintenance) - assert flow2PathUpdated.flowPath.getInvolvedIsls().contains(islUnderMaintenance) + assert flow1PathUpdated.getInvolvedIsls().contains(islUnderMaintenance) + assert flow2PathUpdated.getInvolvedIsls().contains(islUnderMaintenance) } } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkSpec.groovy index 198dde4d2e..c215476c18 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/LinkSpec.groovy @@ -146,7 +146,7 @@ class LinkSpec extends HealthCheckSpecification { busyEndpoints.addAll(flow2.occupiedEndpoints()) and: "Forward flow from source switch to some 'internal' switch" - def islToInternal = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def islToInternal = flow1.retrieveAllEntityPaths().getInvolvedIsls().first() def flow3 = flowFactory.getBuilder(islToInternal.srcSwitch, islToInternal.dstSwitch, false, busyEndpoints) .withPinned(true).build() .create() @@ -165,7 +165,7 @@ class LinkSpec extends HealthCheckSpecification { [flow1, flow2, flow3, flow4].each { assert it.flowId in linkFlows*.id } when: "Get all flows going through the link from some 'internal' switch to destination switch" - def islFromInternal = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls().last() + def islFromInternal = flow1.retrieveAllEntityPaths().getInvolvedIsls().last() linkFlows = northbound.getLinkFlows(islFromInternal.srcSwitch.dpId, islFromInternal.srcPort, islFromInternal.dstSwitch.dpId, islFromInternal.dstPort) @@ -181,7 +181,7 @@ class LinkSpec extends HealthCheckSpecification { Wrappers.wait(rerouteDelay + WAIT_OFFSET) { [flow1, flow2, flow3, flow4].each { flow -> assert flow.retrieveFlowStatus().status == FlowState.DOWN - def isls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def isls = flow.retrieveAllEntityPaths().getInvolvedIsls() assert isls.contains(islToInternal) || isls.contains(islToInternal.reversed) } @@ -368,10 +368,10 @@ class LinkSpec extends HealthCheckSpecification { and: "Create a couple of flows going through these switches" def flow1 = flowFactory.getRandom(switchPair) - def flow1PathIsls = flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flow1PathIsls = flow1.retrieveAllEntityPaths().getInvolvedIsls() def flow2 = flowFactory.getRandom(switchPair, false, FlowState.UP, flow1.occupiedEndpoints()) - def flow2PathIsls = flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def flow2PathIsls = flow2.retrieveAllEntityPaths().getInvolvedIsls() assert flow1PathIsls == preferablePath assert flow2PathIsls == preferablePath @@ -390,8 +390,8 @@ class LinkSpec extends HealthCheckSpecification { response.containsAll([flow1, flow2]*.flowId) Wrappers.wait(PATH_INSTALLATION_TIME + WAIT_OFFSET) { [flow1, flow2].each { flow -> assert flow.retrieveFlowStatus().status == FlowState.UP } - assert flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() != flow1PathIsls - assert flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() != flow2PathIsls + assert flow1.retrieveAllEntityPaths().getInvolvedIsls() != flow1PathIsls + assert flow2.retrieveAllEntityPaths().getInvolvedIsls() != flow2PathIsls } } @@ -641,7 +641,7 @@ class LinkSpec extends HealthCheckSpecification { def switchPair = switchPairs.all().neighbouring().random() def flow = flowFactory.getBuilder(switchPair).withPinned(true).build().create() - def isl = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def isl = flow.retrieveAllEntityPaths().getInvolvedIsls().first() islHelper.breakIsl(isl) when: "Try to delete the link" @@ -662,7 +662,7 @@ class LinkSpec extends HealthCheckSpecification { and: "An active link with flow on it" def flow = flowFactory.getRandom(switchPair) def flowPath = flow.retrieveAllEntityPaths() - def isl = flowPath.flowPath.getInvolvedIsls().first() + def isl = flowPath.getInvolvedIsls().first() when: "Delete the link using force" def response = islHelper.deleteIsl(isl, true) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/UnstableIslSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/UnstableIslSpec.groovy index 24c77e8007..9e4eaaac6e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/UnstableIslSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/links/UnstableIslSpec.groovy @@ -132,7 +132,7 @@ class UnstableIslSpec extends HealthCheckSpecification { then: "Flow is created on the stable path(secondPath)" Wrappers.wait(rerouteDelay + WAIT_OFFSET) { - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == secondPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == secondPathIsls } when: "Mark first path as stable(update the 'time_unstable' field in db)" @@ -148,7 +148,7 @@ class UnstableIslSpec extends HealthCheckSpecification { then: "Flow is rerouted" Wrappers.wait(rerouteDelay + WAIT_OFFSET) { - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == firstPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == firstPathIsls } } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathCheckSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathCheckSpec.groovy index 9a221af26a..58e4f420ca 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathCheckSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathCheckSpec.groovy @@ -133,7 +133,7 @@ class PathCheckSpec extends HealthCheckSpecification { .find { it.retrieveNodes().size() > 4 && it.retrieveNodes().intersect(flowForwardPath).size() > 1 } and: "Involved ISls have been collected" - def flowInvolvedISLs = flowPathDetails.flowPath.getInvolvedIsls(Direction.FORWARD) + def flowInvolvedISLs = flowPathDetails.getInvolvedIsls(Direction.FORWARD) def intersectedPathInvolvedISLs = intersectingPath.getInvolvedIsls() def commonISLs = flowInvolvedISLs.intersect(intersectedPathInvolvedISLs) assert !commonISLs.isEmpty(), "Path for verification has no intersected segment(s) with the flow." diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathComputationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathComputationSpec.groovy index 987abf36a7..5080c99843 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathComputationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/network/PathComputationSpec.groovy @@ -49,14 +49,14 @@ class PathComputationSpec extends HealthCheckSpecification { flow.pathComputationStrategy == COST and: "Flow is actually built on the path with the least cost" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == costEffectivePath + flow.retrieveAllEntityPaths().getInvolvedIsls() == costEffectivePath when: "Update default strategy to LATENCY" kildaConfiguration.updatePathComputationStrategy(LATENCY.toString()) then: "Existing flow remains with COST strategy and on the same path" flow.retrieveDetails().pathComputationStrategy == COST - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == costEffectivePath + flow.retrieveAllEntityPaths().getInvolvedIsls() == costEffectivePath and: "Manual reroute of the flow responds that flow is already on the best path" !flow.reroute().rerouted @@ -73,7 +73,7 @@ class PathComputationSpec extends HealthCheckSpecification { flow2.pathComputationStrategy == LATENCY and: "New flow actually uses path with the least latency (ignoring cost)" - flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == latencyEffectivePath + flow2.retrieveAllEntityPaths().getInvolvedIsls() == latencyEffectivePath } def "Flow path computation strategy can be updated from LATENCY to COST"() { @@ -94,13 +94,13 @@ class PathComputationSpec extends HealthCheckSpecification { .create() then: "Flow is built on the least-latency path" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == latencyEffectivePath + flow.retrieveAllEntityPaths().getInvolvedIsls() == latencyEffectivePath when: "Update flow path strategy to 'Cost'" flow.update(flow.tap{ it.pathComputationStrategy = COST }) then: "Flow path has changed to the least-cost path" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == costEffectivePath + flow.retrieveAllEntityPaths().getInvolvedIsls() == costEffectivePath } def "Target flow path computation strategy is not applied immediately in case flow was updated partially"() { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/FlowStatSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/FlowStatSpec.groovy index 061cdfabfa..0f529dd336 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/FlowStatSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/FlowStatSpec.groovy @@ -133,8 +133,8 @@ class FlowStatSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() assert !flowPathInfo.flowPath.protectedPath.isPathAbsent() - def mainPathIsls = flowPathInfo.flowPath.getMainPathInvolvedIsls() - def protectedPathIsls = flowPathInfo.flowPath.getProtectedPathInvolvedIsls() + def mainPathIsls = flowPathInfo.getMainPathInvolvedIsls() + def protectedPathIsls = flowPathInfo.getProtectedPathInvolvedIsls() when: "Generate traffic on the given flow" def traffExam = traffExamProvider.get() @@ -170,7 +170,7 @@ class FlowStatSpec extends HealthCheckSpecification { Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == UP } def flowPathInfoAfterRerouting = flow.retrieveAllEntityPaths() - def newMainPath = flowPathInfoAfterRerouting.flowPath.getMainPathInvolvedIsls() + def newMainPath = flowPathInfoAfterRerouting.getMainPathInvolvedIsls() newMainPath != mainPathIsls newMainPath != protectedPathIsls diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy index 8088f2b1bb..d24cf6c6c4 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy @@ -589,7 +589,7 @@ class FlowRulesSpec extends HealthCheckSpecification { when: "Break the flow ISL (bring switch port down) to cause flow rerouting" def actualFlowPath = flow.retrieveAllEntityPaths() // Switches may have parallel links, so we need to get involved ISLs. - def islToFail = actualFlowPath.flowPath.getInvolvedIsls().first() + def islToFail = actualFlowPath.getInvolvedIsls().first() islHelper.breakIsl(islToFail) then: "The flow was rerouted after reroute timeout" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy index 3388f3072a..a6eb7ce70d 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy @@ -348,7 +348,7 @@ meters in flow rules at all (#srcSwitch - #dstSwitch flow)"() { !dstSwFlowEgressRule.instructions.goToMeter and: "Intermediate switches don't have meters in flow rules at all" - List flowInvolvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List flowInvolvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List flowInvolvedSwitches[1..-2].findAll { it.ofVersion != "OF_12" }.each { sw -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchFailuresSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchFailuresSpec.groovy index e7f8b2c376..27e2b07eb5 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchFailuresSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchFailuresSpec.groovy @@ -75,7 +75,7 @@ class SwitchFailuresSpec extends HealthCheckSpecification { //depends whether there are alt paths available and: "The flow goes down OR changes path to avoid failed ISL after reroute timeout" Wrappers.wait(rerouteDelay + WAIT_OFFSET) { - def currentIsls = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def currentIsls = flow.retrieveAllEntityPaths().getInvolvedIsls() def pathChanged = !currentIsls.contains(isl) && !currentIsls.contains(isl.reversed) assert pathChanged || (flow.retrieveFlowStatus().status == FlowState.DOWN && flow.retrieveFlowHistory().getEntriesByType(FlowActionType.REROUTE_FAILED).find { @@ -92,7 +92,7 @@ class SwitchFailuresSpec extends HealthCheckSpecification { when: "Current path breaks and reroute starts" switchHelper.shapeSwitchesTraffic([swPair.dst], new TrafficControlData(3000)) - def islToBreak = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def islToBreak = flow.retrieveAllEntityPaths().getInvolvedIsls().first() antiflap.portDown(islToBreak.srcSwitch.dpId, islToBreak.srcPort) and: "Switch reconnects in the middle of reroute" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchMaintenanceSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchMaintenanceSpec.groovy index 5a089ecc35..df7b26082a 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchMaintenanceSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchMaintenanceSpec.groovy @@ -89,15 +89,15 @@ class SwitchMaintenanceSpec extends HealthCheckSpecification { and: "Create a couple of flows going through these switches" def flow1 = flowFactory.getRandom(switchPair) def flow2 = flowFactory.getRandom(switchPair, false, FlowState.UP, flow1.occupiedEndpoints()) - assert flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == pathIsls - assert flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls()== pathIsls + assert flow1.retrieveAllEntityPaths().getInvolvedIsls() == pathIsls + assert flow2.retrieveAllEntityPaths().getInvolvedIsls()== pathIsls when: "Set maintenance mode without flows evacuation flag for some intermediate switch involved in flow paths" switchHelper.setSwitchMaintenance(swId, true, false) then: "Flows are not evacuated (rerouted) and have the same paths" - flow1.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == pathIsls - flow2.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == pathIsls + flow1.retrieveAllEntityPaths().getInvolvedIsls() == pathIsls + flow2.retrieveAllEntityPaths().getInvolvedIsls() == pathIsls when: "Set maintenance mode again with flows evacuation flag for the same switch" northbound.setSwitchMaintenance(swId, true, true) @@ -110,8 +110,8 @@ class SwitchMaintenanceSpec extends HealthCheckSpecification { flow1PathUpdated = flow1.retrieveAllEntityPaths() flow2PathUpdated = flow2.retrieveAllEntityPaths() - assert flow1PathUpdated.flowPath.getInvolvedIsls() != pathIsls - assert flow2PathUpdated.flowPath.getInvolvedIsls()!= pathIsls + assert flow1PathUpdated.getInvolvedIsls() != pathIsls + assert flow2PathUpdated.getInvolvedIsls()!= pathIsls } and: "Switch under maintenance is not involved in new flow paths" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy index 835f2ff2a4..c704d6b4e5 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy @@ -97,7 +97,7 @@ class SwitchSyncSpec extends HealthCheckSpecification { def flow = flowFactory.getRandom(switchPair) and: "Drop all rules an meters from related switches (both default and non-default)" - List involvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def involvedSwitchIds = involvedSwitches*.getDpId() def cookiesMap = involvedSwitches.collectEntries { sw -> @@ -233,7 +233,7 @@ class SwitchSyncSpec extends HealthCheckSpecification { and: "Reproduce situation when switches have missing rules and meters" def flowInfoFromDb = flow.retrieveDetailsFromDB() - List involvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def involvedSwitchIds = involvedSwitches*.getDpId() def transitSwitchIds = involvedSwitches[1..-2]*.dpId diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy index 1b331d108b..6740772dea 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy @@ -152,7 +152,7 @@ class SwitchValidationSpec extends HealthCheckSpecification { when: "Create an intermediate-switch flow" def flow = flowFactory.getRandom(switchPair) def flowPathInfo = flow.retrieveAllEntityPaths() - List involvedSwitches = flowPathInfo.flowPath.getInvolvedIsls() + List involvedSwitches = flowPathInfo.getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List then: "The intermediate switch does not contain any information about meter" @@ -685,7 +685,7 @@ misconfigured" and: "Remove required rules and meters from switches" def flowInfoFromDb = flow.retrieveDetailsFromDB() - List involvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def transitSwitchIds = involvedSwitches[1..-2].dpId def cookiesMap = involvedSwitches.collectEntries { sw -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy index 09160bb5fc..cdd6c78f4d 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy @@ -167,7 +167,7 @@ class SwitchValidationV2Spec extends HealthCheckSpecification { when: "Create an intermediate-switch flow" def flow = flowFactory.getRandom(switchPair) def flowPathInfo = flow.retrieveAllEntityPaths() - def involvedSwitches = flowPathInfo.flowPath.getInvolvedIsls() + def involvedSwitches = flowPathInfo.getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List then: "The intermediate switch does not contain any information about meter" @@ -477,7 +477,7 @@ misconfigured" def flow = flowFactory.getRandom(switchPair) when: "Delete created rules on the transit" - List involvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def transitSw = involvedSwitches[1] switchHelper.deleteSwitchRules(transitSw.dpId, DeleteRulesAction.IGNORE_DEFAULTS) @@ -701,7 +701,7 @@ misconfigured" and: "Remove required rules and meters from switches" def flowInfoFromDb = flow.retrieveDetailsFromDB() - List involvedSwitches = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() + List involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedIsls() .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def transitSwitchIds = involvedSwitches[1..-2]*.dpId def cookiesMap = involvedSwitches.collectEntries { sw -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/toggles/FeatureTogglesV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/toggles/FeatureTogglesV2Spec.groovy index dc2159116f..1ef85189e2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/toggles/FeatureTogglesV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/toggles/FeatureTogglesV2Spec.groovy @@ -139,7 +139,7 @@ feature toggle"() { and: "Init a flow reroute by breaking current path" def flowPathInfo = flow.retrieveAllEntityPaths() - def islToBreak = flowPathInfo.flowPath.getInvolvedIsls().first() + def islToBreak = flowPathInfo.getInvolvedIsls().first() islHelper.breakIsl(islToBreak) then: "Flow is rerouted" @@ -161,7 +161,7 @@ feature toggle"() { and: "Init a flow reroute by breaking a new current path" def newFlowPathInfo = flow.retrieveAllEntityPaths() - def newIslToBreak = newFlowPathInfo.flowPath.getInvolvedIsls().first() + def newIslToBreak = newFlowPathInfo.getInvolvedIsls().first() islHelper.breakIsl(newIslToBreak) then: "Flow is rerouted" @@ -199,7 +199,7 @@ feature toggle"() { and: "Init a flow reroute by breaking current path" def flowPathInfo = flow.retrieveAllEntityPaths() - def islToBreak = flowPathInfo.flowPath.getInvolvedIsls().first() + def islToBreak = flowPathInfo.getInvolvedIsls().first() islHelper.breakIsl(islToBreak) then: "Flow is not rerouted" @@ -249,7 +249,7 @@ feature toggle"() { //you have to break all altPaths to avoid rerouting when flowPath is broken def flowPathInfo = flow.retrieveAllEntityPaths() - def flowInvolvedIsls = flowPathInfo.flowPath.getInvolvedIsls() + def flowInvolvedIsls = flowPathInfo.getInvolvedIsls() def altIsls = topology.getRelatedIsls(switchPair.src) - flowInvolvedIsls.first() islHelper.breakIsls(altIsls) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/ContentionSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/ContentionSpec.groovy index 9ad6c8b952..51e3de34fd 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/ContentionSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/ContentionSpec.groovy @@ -69,9 +69,9 @@ class ContentionSpec extends BaseSpecification { } createTasks*.join() assert createTasks.findAll { it.isError() }.empty - def relatedIsls = flows[0].retrieveAllEntityPaths().flowPath.getInvolvedIsls() + def relatedIsls = flows[0].retrieveAllEntityPaths().getInvolvedIsls() //all flows use same isls - flows[1..-1].each { assert it.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == relatedIsls } + flows[1..-1].each { assert it.retrieveAllEntityPaths().getInvolvedIsls() == relatedIsls } then: "Available bandwidth on related isls is reduced based on bandwidth of created flows" relatedIsls.each { isl -> @@ -106,7 +106,7 @@ class ContentionSpec extends BaseSpecification { def flow = flowFactory.getRandom(swPair) def flowPathInfo = flow.retrieveAllEntityPaths() - def mainPathIsls = flowPathInfo.flowPath.getInvolvedIsls() + def mainPathIsls = flowPathInfo.getInvolvedIsls() def newPathIsls = availablePaths.find { it != mainPathIsls } availablePaths.findAll { it != newPathIsls }.each { islHelper.makePathIslsMorePreferable(newPathIsls, it) } @@ -123,7 +123,7 @@ class ContentionSpec extends BaseSpecification { then: "Flow is Up and path has changed" Wrappers.wait(WAIT_OFFSET) { assert flow.retrieveFlowStatus().status == FlowState.UP - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == newPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == newPathIsls } and: "Related switches have no rule discrepancies" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy index 81a322170c..1025ff6e8b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy @@ -82,7 +82,7 @@ and at least 1 path must remain safe" def availablePathsIsls = switchPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } availablePathsIsls.findAll { it != mainPathIsls }.each { islHelper.makePathIslsMorePreferable(mainPathIsls, it) } def flow = flowFactory.getRandom(switchPair) - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainPathIsls and: "Switch on the preferred failover path will suddenly be unavailable for rules installation when the reroute starts" //select a required failover path beforehand @@ -110,12 +110,12 @@ and at least 1 path must remain safe" assert flow.retrieveFlowStatus().status == UP } def flowPathInfo = flow.retrieveAllEntityPaths() - def flowPathIsls = flowPathInfo.flowPath.getInvolvedIsls() + def flowPathIsls = flowPathInfo.getInvolvedIsls() flowPathIsls != mainPathIsls flowPathIsls != failoverPathIsls !flowPathInfo.getInvolvedSwitches().contains(switchIdToBreak) - !flowPathInfo.flowPath.getInvolvedIsls().contains(islToBreak) - !flowPathInfo.flowPath.getInvolvedIsls().contains(islToBreak.reversed) + !flowPathInfo.getInvolvedIsls().contains(islToBreak) + !flowPathInfo.getInvolvedIsls().contains(islToBreak.reversed) and: "All related switches have no rule anomalies" def switchesToVerify = islHelper.retrieveInvolvedSwitches((mainPathIsls + failoverPathIsls + flowPathIsls).unique()) @@ -156,8 +156,8 @@ and at least 1 path must remain safe" **/ def flow = flowFactory.getBuilder(swPair).withProtectedPath(true).build().create() def flowPathInfo = flow.retrieveAllEntityPaths() - assert flowPathInfo.flowPath.getMainPathInvolvedIsls() == mainPathIsls - assert flowPathInfo.flowPath.getProtectedPathInvolvedIsls() == protectedPathIsls + assert flowPathInfo.getMainPathInvolvedIsls() == mainPathIsls + assert flowPathInfo.getProtectedPathInvolvedIsls() == protectedPathIsls when: "Disconnect dst switch on protected path" def swToManipulate = swPair.dst @@ -183,8 +183,8 @@ and at least 1 path must remain safe" and: "Flow is not rerouted" def flowPathInfoAfterSwap = flow.retrieveAllEntityPaths() - flowPathInfoAfterSwap.flowPath.getMainPathInvolvedIsls() == mainPathIsls - flowPathInfoAfterSwap.flowPath.getProtectedPathInvolvedIsls() == protectedPathIsls + flowPathInfoAfterSwap.getMainPathInvolvedIsls() == mainPathIsls + flowPathInfoAfterSwap.getProtectedPathInvolvedIsls() == protectedPathIsls and: "All involved switches pass switch validation(except dst switch)" @@ -279,7 +279,7 @@ and at least 1 path must remain safe" and: "A flow on the main path" def flow = flowFactory.getRandom(swPair) - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainPathIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == mainPathIsls when: "Make backupPath more preferable than mainPath" islHelper.makePathIslsMorePreferable(backupPathIsls, mainPathIsls) @@ -304,7 +304,7 @@ and at least 1 path must remain safe" } then: "Flow is not rerouted" - flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == mainPathIsls + flow.retrieveAllEntityPaths().getInvolvedIsls() == mainPathIsls and: "All involved switches pass switch validation(except dst switch)" def involvedSwitchIds = islHelper.retrieveInvolvedSwitches(backupPathIsls)[0..-2]*.dpId @@ -363,10 +363,10 @@ class RetriesIsolatedSpec extends HealthCheckSpecification { availablePaths.findAll { it != preferableIsls }.each { islHelper.makePathIslsMorePreferable(preferableIsls, it) } def flow = flowFactory.getRandom(swPair) - assert flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls() == preferableIsls + assert flow.retrieveAllEntityPaths().getInvolvedIsls() == preferableIsls when: "Break current path to trigger a reroute" - def islToBreak = flow.retrieveAllEntityPaths().flowPath.getInvolvedIsls().first() + def islToBreak = flow.retrieveAllEntityPaths().getInvolvedIsls().first() cleanupManager.addAction(RESTORE_ISL, {islHelper.restoreIsl(islToBreak)}) cleanupManager.addAction(RESET_ISLS_COST,{database.resetCosts(topology.isls)}) northbound.portDown(islToBreak.srcSwitch.dpId, islToBreak.srcPort) From bf8df1cadba1d8c9166f4656466a844e0c3d606f Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Fri, 11 Oct 2024 14:42:49 +0200 Subject: [PATCH 04/21] [TEST]: Improvement: HW: Path: Collecting path nodes between switches --- .../openkilda/functionaltests/extension/env/EnvExtension.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/extension/env/EnvExtension.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/extension/env/EnvExtension.groovy index 7cb3ee3647..ba0ff17e33 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/extension/env/EnvExtension.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/extension/env/EnvExtension.groovy @@ -101,6 +101,7 @@ class EnvExtension extends AbstractGlobalExtension implements SpringContextListe log.info("Virtual topology is successfully created") } else if (profile == "hardware") { labService.createHwLab(topology) + collectSwitchesPathsFromDb(topology) log.info("Successfully redirected to hardware topology") } else { throw new RuntimeException("Provided profile '$profile' is unknown. Select one of the following profiles:" + From 015b6cdbb76b6786353656bbd961b99d3c56ab82 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Tue, 17 Sep 2024 16:08:58 +0200 Subject: [PATCH 05/21] [TEST]: Refactoring: Verification of the ping operation --- .../model/ComplexFlowPingResponse.groovy | 49 ++++++ .../helpers/model/FlowExtended.groovy | 23 ++- .../helpers/model/HaFlowExtended.groovy | 10 +- .../model/SubFlowPingDiscrepancies.groovy | 11 ++ .../helpers/model/YFlowExtended.groovy | 6 + .../spec/flows/AutoRerouteSpec.groovy | 6 +- .../spec/flows/ConnectedDevicesSpec.groovy | 5 +- .../spec/flows/FlowCrudSpec.groovy | 15 +- .../spec/flows/FlowPingSpec.groovy | 57 +++---- .../spec/flows/PartialUpdateSpec.groovy | 10 +- .../spec/flows/QinQFlowSpec.groovy | 50 ++---- .../spec/flows/VxlanFlowSpec.groovy | 15 +- .../flows/haflows/HaFlowCreateSpec.groovy | 9 +- .../spec/flows/haflows/HaFlowPingSpec.groovy | 70 ++++++-- .../spec/flows/yflows/YFlowCreateSpec.groovy | 7 +- .../spec/flows/yflows/YFlowPingSpec.groovy | 149 +++++++++++++----- .../spec/switches/LagPortSpec.groovy | 5 +- 17 files changed, 315 insertions(+), 182 deletions(-) create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowPingResponse.groovy create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowPingDiscrepancies.groovy diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowPingResponse.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowPingResponse.groovy new file mode 100644 index 0000000000..fae0f62af4 --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowPingResponse.groovy @@ -0,0 +1,49 @@ +package org.openkilda.functionaltests.helpers.model + +import static org.openkilda.functionaltests.helpers.model.FlowDirection.FORWARD +import static org.openkilda.functionaltests.helpers.model.FlowDirection.REVERSE + +import org.openkilda.northbound.dto.v2.haflows.HaFlowPingResult +import org.openkilda.northbound.dto.v2.yflows.SubFlowPingPayload +import org.openkilda.northbound.dto.v2.yflows.YFlowPingResult + +import groovy.transform.ToString + +@ToString +class ComplexFlowPingResponse { + boolean pingSuccess + String error + List subFlowsDiscrepancies + + ComplexFlowPingResponse(YFlowPingResult pingResponse) { + this.pingSuccess = pingResponse.pingSuccess + this.error = pingResponse.error + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(pingResponse.subFlows) + } + + ComplexFlowPingResponse(HaFlowPingResult pingResponse) { + this.pingSuccess = pingResponse.pingSuccess + this.error = pingResponse.error + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(pingResponse.subFlows) + } + + static private def collectDiscrepanciesPerSubFlow(List subFlowsPingDetails) { + List discrepanciesPerSubFlow = subFlowsPingDetails.collect { subFlowPingDetails -> + verifyPingLogic(subFlowPingDetails, FORWARD) + verifyPingLogic(subFlowPingDetails, REVERSE) + + HashMap discrepancies = [:] + subFlowPingDetails.forward.pingSuccess ?: discrepancies.put(FORWARD, subFlowPingDetails.forward.error) + subFlowPingDetails.reverse.pingSuccess ?: discrepancies.put(REVERSE, subFlowPingDetails.reverse.error) + + return discrepancies.isEmpty() ? null : new SubFlowPingDiscrepancies(subFlowPingDetails.flowId, discrepancies) + }.findAll() + return discrepanciesPerSubFlow + } + + static private void verifyPingLogic(SubFlowPingPayload pingPayload, FlowDirection direction) { + def pingResult = direction == FORWARD ? pingPayload.forward : pingPayload.reverse + assert (pingResult.pingSuccess && !pingResult.error) || (!pingResult.pingSuccess && pingResult.error), + "There is an error in the ping logic for sub-flow ${pingPayload.flowId} $direction: $pingResult" + } +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy index 1d716a1bcf..23a7404b07 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy @@ -4,6 +4,7 @@ import static groovyx.gpars.GParsPool.withPool import static org.openkilda.functionaltests.helpers.FlowNameGenerator.FLOW import static org.openkilda.functionaltests.helpers.SwitchHelper.randomVlan import static org.openkilda.functionaltests.helpers.Wrappers.wait +import static org.openkilda.functionaltests.helpers.model.FlowDirection.* import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.DELETE_FLOW import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.OTHER import static org.openkilda.functionaltests.model.cleanup.CleanupAfter.TEST @@ -416,7 +417,25 @@ class FlowExtended { assert validationResponse.findAll { !it.asExpected } == validationResponse.findAll { !it.discrepancies.isEmpty() }, "There is an error in the logic of flow validation" validationResponse.findAll { !it.discrepancies.isEmpty() } - .collectEntries { [(FlowDirection.getByDirection(it.direction)): it.discrepancies] } + .collectEntries { [(getByDirection(it.direction)): it.discrepancies] } + } + + Map pingAndCollectDiscrepancies(PingInput pingInput = new PingInput()) { + def pingResponse = ping(pingInput) + assert pingResponse.flowId == flowId, "Ping response for an incorrect flow" + verifyPingLogic(pingResponse, FORWARD) + verifyPingLogic(pingResponse, REVERSE) + + Map discrepancies = [:] + pingResponse.forward.pingSuccess ?: discrepancies.put(FORWARD, pingResponse.forward.error) + pingResponse.reverse.pingSuccess ?: discrepancies.put(REVERSE, pingResponse.reverse.error) + return discrepancies + } + + static private void verifyPingLogic(PingOutput pingPayload, FlowDirection direction) { + def pingResult = direction == FORWARD ? pingPayload.forward : pingPayload.reverse + assert (pingResult.pingSuccess && !pingResult.error) || (!pingResult.pingSuccess && pingResult.error), + "There is an error in the ping logic for $pingResult" } FlowReroutePayload sync() { @@ -490,7 +509,7 @@ class FlowExtended { } def getFlowRulesCountBySwitch(FlowDirection direction, int involvedSwitchesCount, boolean isSwitchServer42) { - def flowEndpoint = direction == FlowDirection.FORWARD ? source : destination + def flowEndpoint = direction == FORWARD ? source : destination def swProps = northbound.getSwitchProperties(flowEndpoint.switchId) int count = involvedSwitchesCount - 1; diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy index 3d2fe4a117..3037cb74c7 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy @@ -271,9 +271,15 @@ class HaFlowExtended { return new HaFlowExtended(haFlow, northboundV2, topologyDefinition, cleanupManager) } - HaFlowPingResult ping(int timeoutMillis) { + HaFlowPingResult ping(HaFlowPingPayload haFlowPingPayload = new HaFlowPingPayload(2000)) { log.debug("Ping ha-flow '${haFlowId}'") - northboundV2.pingHaFlow(haFlowId, new HaFlowPingPayload(timeoutMillis)) + northboundV2.pingHaFlow(haFlowId, haFlowPingPayload) + } + + ComplexFlowPingResponse pingAndCollectDiscrepancies(HaFlowPingPayload haFlowPingPayload = new HaFlowPingPayload(2000)) { + def response = ping(haFlowPingPayload) + assert response.haFlowId == haFlowId, "Ping response for an incorrect ha-flow" + new ComplexFlowPingResponse(response) } List occupiedEndpoints() { diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowPingDiscrepancies.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowPingDiscrepancies.groovy new file mode 100644 index 0000000000..68329d6675 --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowPingDiscrepancies.groovy @@ -0,0 +1,11 @@ +package org.openkilda.functionaltests.helpers.model + +import groovy.transform.ToString +import groovy.transform.TupleConstructor + +@TupleConstructor +@ToString +class SubFlowPingDiscrepancies { + String subFlowId + Map flowDiscrepancies +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy index 8ac9f97e00..817a3a4946 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy @@ -275,6 +275,12 @@ class YFlowExtended { northboundV2.pingYFlow(yFlowId, payload) } + ComplexFlowPingResponse pingAndCollectDiscrepancies(YFlowPingPayload payload = new YFlowPingPayload(2000)) { + def response = ping(payload) + assert response.getYFlowId() == yFlowId, "Ping response for an incorrect Y-Flow" + new ComplexFlowPingResponse(response) + } + YFlowRerouteResult reroute() { return northboundV2.rerouteYFlow(yFlowId) } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy index 87fd777d09..a8b89b26b2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/AutoRerouteSpec.groovy @@ -529,11 +529,7 @@ triggering one more reroute of the current path" and: "Flow is pingable" retry(3, 0) { //Was unstable on Jenkins builds. Fresh env problem? - with(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } - true + flow.pingAndCollectDiscrepancies().isEmpty() } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy index fda53732a9..c8b586db38 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy @@ -509,10 +509,7 @@ srcDevices=#newSrcEnabled, dstDevices=#newDstEnabled"() { and: "Flow is valid and pingable" flow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(flow.ping()) { - assert it.forward.pingSuccess - assert it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() and: "Device sends an lldp+arp packet into a flow port on that switch (with a correct flow vlan)" device.sendLldp(lldpData) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy index d23b83c432..d55121d17e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy @@ -899,10 +899,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow is valid and pingable" updatedFlow.validateAndCollectDiscrepancies().isEmpty() - with(updatedFlow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + updatedFlow.pingAndCollectDiscrepancies().isEmpty() and: "The src switch passes switch validation" !switchHelper.synchronizeAndCollectFixedDiscrepancies(srcSwitch.getDpId()).isPresent() @@ -942,10 +939,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow is valid and pingable" updatedFlow.validateAndCollectDiscrepancies().isEmpty() - with(updatedFlow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + updatedFlow.pingAndCollectDiscrepancies().isEmpty() and: "The new and old dst switches pass switch validation" wait(RULES_DELETION_TIME) { @@ -1090,10 +1084,7 @@ types .* or update switch properties and add needed encapsulation type./).matche and: "Flow is valid and pingable" updatedFlow.validateAndCollectDiscrepancies().isEmpty() - with(updatedFlow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + updatedFlow.pingAndCollectDiscrepancies().isEmpty() and: "Involved switches pass switch validation" def involvedSwitches = updatedFlow.retrieveAllEntityPaths().getInvolvedSwitches() diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy index 7774404937..cbf7ae7c59 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowPingSpec.groovy @@ -1,6 +1,6 @@ package org.openkilda.functionaltests.spec.flows -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs + import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.LOW_PRIORITY import static org.openkilda.functionaltests.extension.tags.Tag.SMOKE @@ -9,7 +9,6 @@ import static org.openkilda.testing.Constants.DefaultRule.VERIFICATION_UNICAST_R import static org.openkilda.testing.Constants.DefaultRule.VERIFICATION_UNICAST_VXLAN_RULE_COOKIE import static org.openkilda.testing.Constants.STATS_LOGGING_TIMEOUT import static org.openkilda.testing.Constants.WAIT_OFFSET -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.flow.FlowNotCreatedExpectedError @@ -17,6 +16,7 @@ import org.openkilda.functionaltests.extension.tags.IterationTag import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.factory.FlowFactory +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.FlowEncapsulationType import org.openkilda.functionaltests.helpers.model.Path import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory @@ -174,8 +174,6 @@ class FlowPingSpec extends HealthCheckSpecification { //build a flow def flow = flowFactory.getRandom(swPair) - - expectedPingResult.flowId = flow.flowId assert aswitchPathIsls == flow.retrieveAllEntityPaths().getInvolvedIsls() when: "Break the flow by removing rules from a-switch" @@ -186,57 +184,54 @@ class FlowPingSpec extends HealthCheckSpecification { aSwitchFlows.removeFlows(rulesToRemove) and: "Ping the flow" - def response = flow.ping(data.pingInput) + def discrepancies = flow.pingAndCollectDiscrepancies(data.pingInput) then: "Ping response properly shows that certain direction is unpingable" - expect response, sameBeanAs(expectedPingResult) - .ignoring("forward.latency").ignoring("reverse.latency") + discrepancies == data.expectedDiscrepancy where: data << [ [ breakForward: true, breakReverse: false, - pingInput : new PingInput() + pingInput : new PingInput(), + expectedDiscrepancy: [(FlowDirection.FORWARD): "No ping for reasonable time"] ], [ breakForward: false, breakReverse: true, - pingInput : new PingInput() + pingInput : new PingInput(), + expectedDiscrepancy: [(FlowDirection.REVERSE): "No ping for reasonable time"] ], [ breakForward: true, breakReverse: true, - pingInput : new PingInput() + pingInput : new PingInput(), + expectedDiscrepancy: [(FlowDirection.FORWARD): "No ping for reasonable time", + (FlowDirection.REVERSE): "No ping for reasonable time"] ], [ breakForward: true, breakReverse: false, - pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000) + pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000), + expectedDiscrepancy: [(FlowDirection.FORWARD): "No ping for reasonable time"] ], [ breakForward: false, breakReverse: true, - pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000) + pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000), + expectedDiscrepancy: [(FlowDirection.REVERSE): "No ping for reasonable time"] ], [ breakForward: true, breakReverse: true, - pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000) + pingInput : new PingInput((getDiscoveryInterval() + 1) * 1000), + expectedDiscrepancy: [(FlowDirection.FORWARD): "No ping for reasonable time", + (FlowDirection.REVERSE): "No ping for reasonable time"] ] ] description = "${data.breakForward ? "forward" : ""}${data.breakForward && data.breakReverse ? " and " : ""}" + "${data.breakReverse ? "reverse" : ""} path with ${data.pingInput.timeoutMillis}ms timeout" - - expectedPingResult = new PingOutputBuilder().forward( - new UniFlowPingOutput( - pingSuccess: !data.breakForward, - error: data.breakForward ? "No ping for reasonable time" : null)).reverse( - new UniFlowPingOutput( - pingSuccess: !data.breakReverse, - error: data.breakReverse ? "No ping for reasonable time" : null)) - .error(null) - .build() } def "Unable to ping a single-switch flow"() { @@ -276,11 +271,7 @@ class FlowPingSpec extends HealthCheckSpecification { def flow = flowFactory.getBuilder(switchPair) .withEncapsulationType(FlowEncapsulationType.VXLAN).build() .create() - //make sure that flow is pingable - with(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + assert flow.pingAndCollectDiscrepancies().isEmpty() when: "Break the flow by removing flow rules from the intermediate switch" def intermediateSwId = flow.retrieveAllEntityPaths().getInvolvedSwitches()[1] @@ -291,18 +282,14 @@ class FlowPingSpec extends HealthCheckSpecification { switchHelper.deleteSwitchRules(intermediateSwId, cookie) } - and: "Ping the flow" - def response = flow.ping() - then: "Ping shows that path is broken" - !response.forward.pingSuccess - !response.reverse.pingSuccess + assert flow.pingAndCollectDiscrepancies().keySet() == [FlowDirection.FORWARD, FlowDirection.REVERSE].toSet() } def "Able to turn on periodic pings on a flow"() { when: "Create a flow with periodic pings turned on" def endpointSwitches = switchPairs.all().nonNeighbouring().random() - def flow = flowFactory.getBuilder(endpointSwitches).withPeriodicPing(true).build() + flowFactory.getBuilder(endpointSwitches).withPeriodicPing(true).build() .create() then: "Packet counter on catch ping rules grows due to pings happening" @@ -321,7 +308,7 @@ class FlowPingSpec extends HealthCheckSpecification { def "Unable to create a single-switch flow with periodic pings"() { when: "Try to create a single-switch flow with periodic pings" def singleSwitch = topology.activeSwitches.first() - def flow = flowFactory.getBuilder(singleSwitch, singleSwitch) + flowFactory.getBuilder(singleSwitch, singleSwitch) .withPeriodicPing(true).build() .create() diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy index 0fc34f331b..4804731404 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PartialUpdateSpec.groovy @@ -282,10 +282,7 @@ class PartialUpdateSpec extends HealthCheckSpecification { and: "Flow is valid and pingable" flow.validateAndCollectDiscrepancies().isEmpty() - with(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() and: "The src switch passes switch validation" !switchHelper.synchronizeAndCollectFixedDiscrepancies(srcSwitch.dpId).isPresent() @@ -329,10 +326,7 @@ class PartialUpdateSpec extends HealthCheckSpecification { and: "Flow is valid and pingable" flow.validateAndCollectDiscrepancies().isEmpty() - with(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() and: "The new and old dst switches pass switch validation" Wrappers.wait(RULES_DELETION_TIME) { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy index 5c98650597..13ff85bb40 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy @@ -82,10 +82,7 @@ class QinQFlowSpec extends HealthCheckSpecification { and: "Flow is valid and pingable" qinqFlow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(qinqFlow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + qinqFlow.pingAndCollectDiscrepancies().isEmpty() and: "The flow allows traffic (if applicable)" def traffExam = traffExamProvider.get() @@ -119,10 +116,7 @@ class QinQFlowSpec extends HealthCheckSpecification { and: "Both flows are pingable" [qinqFlow, vlanFlow].each { - verifyAll(it.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + it.pingAndCollectDiscrepancies().isEmpty() } then: "Both flows allow traffic" @@ -178,10 +172,7 @@ class QinQFlowSpec extends HealthCheckSpecification { } [qinqFlow, vlanFlow].each { - verifyAll(it.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + it.pingAndCollectDiscrepancies().isEmpty() } when: "Delete the flows" @@ -366,10 +357,7 @@ class QinQFlowSpec extends HealthCheckSpecification { and: "Flow is valid and pingable" flow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() when: "Delete the flow via APIv1" flow.deleteV1() @@ -465,10 +453,7 @@ class QinQFlowSpec extends HealthCheckSpecification { then: "Both flow are valid and pingable" [flow1, flow2].each { flow -> flow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() } and: "Flows allow traffic" @@ -483,10 +468,7 @@ class QinQFlowSpec extends HealthCheckSpecification { then: "The first flow is still valid and pingable" flow1.validateAndCollectDiscrepancies().isEmpty() - verifyAll(flow1.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow1.pingAndCollectDiscrepancies().isEmpty() and: "The first flow still allows traffic" verifyFlowHasBidirectionalTraffic(exam1, traffExam) @@ -584,10 +566,7 @@ class QinQFlowSpec extends HealthCheckSpecification { and: "Flow is valid and pingable" qinqFlow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(qinqFlow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + qinqFlow.pingAndCollectDiscrepancies().isEmpty() and: "The flow allows traffic (if applicable)" def traffExam = traffExamProvider.get() @@ -621,12 +600,9 @@ class QinQFlowSpec extends HealthCheckSpecification { switchHelper.synchronizeAndCollectFixedDiscrepancies(involvedSwitchesforBothFlows).isEmpty() and: "Both flows are pingable" - [qinqFlow, vlanFlow].each { - verifyAll(it.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } - } + qinqFlow.pingAndCollectDiscrepancies().isEmpty() + vlanFlow.pingAndCollectDiscrepancies().isEmpty() + then: "Both flows allow traffic" if(!trafficDisclaimer) { @@ -664,12 +640,8 @@ class QinQFlowSpec extends HealthCheckSpecification { [qinqFlow, vlanFlow].each { it.validateAndCollectDiscrepancies().isEmpty() } - [qinqFlow, vlanFlow].each { - verifyAll(it.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + it.pingAndCollectDiscrepancies().isEmpty() } when: "Delete the flows" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy index 7bb875885c..93bd4e7b9e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy @@ -105,10 +105,7 @@ class VxlanFlowSpec extends HealthCheckSpecification { } and: "Flow is pingable" - verifyAll(flow.ping()) { - forward.pingSuccess - reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() and: "The flow allows traffic" def traffExam = traffExamProvider.get() @@ -127,10 +124,7 @@ class VxlanFlowSpec extends HealthCheckSpecification { } and: "Flow is pingable" - verifyAll(flow.ping()) { - forward.pingSuccess - reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() when: "Try to update the encapsulation type to #encapsulationUpdate.toString()" def updateEntity = flow.deepCopy().tap { @@ -149,10 +143,7 @@ class VxlanFlowSpec extends HealthCheckSpecification { and: "Flow is pingable (though sometimes we have to wait)" Wrappers.wait(WAIT_OFFSET) { - verifyAll(flow.ping()) { - forward.pingSuccess - reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() } and: "Rules are recreated" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy index 7822cd3508..9ee32c540b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy @@ -56,12 +56,11 @@ class HaFlowCreateSpec extends HealthCheckSpecification { // Ping operation is temporary allowed only for multi switch HA-Flows https://github.com/telstra/open-kilda/issues/5224 //Ping operation is temporary disabled when one of the sub-flows' ends is Y-Point https://github.com/telstra/open-kilda/pull/5381 if (SwitchTriplet.ALL_ENDPOINTS_DIFFERENT(swT) && !isOneSubFlowEndpointYPoint) { - def response = haFlow.ping(2000) + def response = haFlow.pingAndCollectDiscrepancies() + assert response.pingSuccess assert !response.error - response.subFlows.each { - assert it.forward.pingSuccess - assert it.reverse.pingSuccess - } + assert response.subFlowsDiscrepancies.isEmpty() + } and: "HA-Flow has been successfully deleted" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy index 47c8255ebc..a7cf52a17f 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy @@ -3,12 +3,14 @@ package org.openkilda.functionaltests.spec.flows.haflows import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.functionaltests.model.stats.FlowStats import org.openkilda.model.SwitchId +import org.openkilda.model.cookie.Cookie import org.openkilda.northbound.dto.v2.haflows.HaFlowPatchPayload import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value @@ -160,18 +162,20 @@ class HaFlowPingSpec extends HealthCheckSpecification { def haFlow = haFlowFactory.getRandom(switchTriplet) when: "Ping HA-Flow" - def pingResult = haFlow.ping(2000) + def response = haFlow.pingAndCollectDiscrepancies() then: "HA-Flow ping is not successful and the appropriate error message has been returned" - !pingResult.isPingSuccess() - pingResult.haFlowId == haFlow.haFlowId - pingResult.error == "Temporary disabled. HaFlow ${haFlow.haFlowId} has one sub-flow with endpoint switch equals to Y-point switch" + verifyAll { + assert !response.pingSuccess + assert response.error == "Temporary disabled. HaFlow ${haFlow.haFlowId} has one sub-flow with endpoint switch equals to Y-point switch" + assert response.subFlowsDiscrepancies.isEmpty() + } } @Tags([LOW_PRIORITY]) def "Able to ping HA-Flow when neither of the sub-flows end on Y-Point"() { given: "HA-Flow has been created" - def swT = switchTriplets.all(true).findSwitchTripletWithYPointOnSharedEp() + def swT = switchTriplets.all().nonNeighbouring().findSwitchTripletWithYPointOnSharedEp() def haFlow = haFlowFactory.getRandom(swT) and: "Neither of the sub-flows end on Y-Point (ping is disabled for such kind of HA-Flow)" @@ -179,21 +183,63 @@ class HaFlowPingSpec extends HealthCheckSpecification { assert !paths.sharedPath.path.forward.nodes.nodes when: "Ping HA-Flow" - def pingResult = haFlow.ping(2000) + def pingResult = haFlow.ping() then: "HA-Flow ping is successful" pingResult.isPingSuccess() pingResult.haFlowId == haFlow.haFlowId !pingResult.error - and: "Successful ping for both sub-flows in FORWARD direction" - pingResult.subFlows.each {subFlow -> - assert subFlow.forward.pingSuccess && !subFlow.forward.error + when: "Break one sub-flow by removing flow rules from the intermediate switch" + def yFlowPath = haFlow.retrievedAllEntityPaths() + def subFlow1Switch = yFlowPath.subFlowPaths.first().getInvolvedIsls().last().srcSwitch.dpId + def subFlow1Id = yFlowPath.subFlowPaths.first().flowId + def subFlow2Switch = yFlowPath.subFlowPaths.last().getInvolvedIsls().last().srcSwitch.dpId + def rulesToDelete = switchRulesFactory.get(subFlow1Switch).getRules().findAll { + !new Cookie(it.cookie).serviceFlag + }*.cookie + rulesToDelete.each { cookie -> + switchHelper.deleteSwitchRules(subFlow1Switch, cookie) + } + def collectedDiscrepancies = haFlow.pingAndCollectDiscrepancies() + + then: "HA-Flow ping is not successful, and ping for one sub-flow shows that path is broken" + def expectedDiscrepancy = [(FlowDirection.FORWARD): "No ping for reasonable time", + (FlowDirection.REVERSE): "No ping for reasonable time"] + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.subFlowsDiscrepancies + .find { it.subFlowId == subFlow1Id }.flowDiscrepancies == expectedDiscrepancy + assert !collectedDiscrepancies.subFlowsDiscrepancies.find { it.subFlowId != subFlow1Id } + } + + when: "Break another sub-flow by removing flow rules from the intermediate switch(after fixing previous discrepancy)" + switchHelper.synchronize(subFlow1Switch) + rulesToDelete = switchRulesFactory.get(subFlow2Switch).getRules().findAll { + !new Cookie(it.cookie).serviceFlag + }*.cookie + rulesToDelete.each { cookie -> + switchHelper.deleteSwitchRules(subFlow2Switch, cookie) } + collectedDiscrepancies = haFlow.pingAndCollectDiscrepancies() + + then: "HA-Flow ping is not successful, and ping for another sub-flow shows that path is broken" + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.subFlowsDiscrepancies + .find { it.subFlowId != subFlow1Id }.flowDiscrepancies == expectedDiscrepancy + assert !collectedDiscrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFlow1Id } + } + + when: "All required rules have been installed(sync)" + switchHelper.synchronize(subFlow2Switch) + collectedDiscrepancies = haFlow.pingAndCollectDiscrepancies() - and: "Successful ping for both sub-flows in REVERSE direction" - pingResult.subFlows.each {subFlow -> - assert subFlow.reverse.pingSuccess && !subFlow.reverse.error + then: "HA-Flow ping is successful for both sub-flows" + verifyAll { + assert collectedDiscrepancies.pingSuccess + assert !collectedDiscrepancies.error + assert collectedDiscrepancies.subFlowsDiscrepancies.isEmpty() } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy index c91466ccf7..70bcfeb8ed 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy @@ -85,12 +85,9 @@ class YFlowCreateSpec extends HealthCheckSpecification { and: "YFlow is pingable" if (swT.shared != swT.ep1 || swT.shared != swT.ep2) { - def response = yFlow.ping() + def response = yFlow.pingAndCollectDiscrepancies() !response.error - response.subFlows.each { - assert it.forward.pingSuccess - assert it.reverse.pingSuccess - } + response.subFlowsDiscrepancies.isEmpty() } and: "All involved switches pass switch validation" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy index 6399f7d9e6..eb66ccf940 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy @@ -7,13 +7,11 @@ import static org.openkilda.testing.Constants.WAIT_OFFSET import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowDirection +import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.YFlowFactory import org.openkilda.model.SwitchId import org.openkilda.model.cookie.Cookie -import org.openkilda.northbound.dto.v2.yflows.SubFlowPingPayload -import org.openkilda.northbound.dto.v2.yflows.UniSubFlowPingPayload -import org.openkilda.northbound.dto.v2.yflows.YFlowPingPayload -import org.openkilda.northbound.dto.v2.yflows.YFlowPingResult import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value @@ -26,6 +24,10 @@ class YFlowPingSpec extends HealthCheckSpecification { @Shared YFlowFactory yFlowFactory + @Autowired + @Shared + SwitchRulesFactory switchRulesFactory + @Value('${flow.ping.interval}') int pingInterval @@ -55,49 +57,122 @@ class YFlowPingSpec extends HealthCheckSpecification { @Tags([LOW_PRIORITY]) def "Able to ping y-flow when one of subflows is one-switch one (#5019)"() { given: "y-flow which has one-switch subflow" - def switchTriplet = switchTriplets.all(true, true).findSwitchTripletForOneSwitchSubflow() + def switchTriplet = switchTriplets.all().nonNeighbouring().random().tap { + it.ep1 = it.shared + it.pathsEp1 = [] + } assumeTrue(switchTriplet != null, "These cases cannot be covered on given topology:") def yFlow = yFlowFactory.getRandom(switchTriplet) - and: "expected ping response" - def multiSwitchSubFlowId = yFlow.getSubFlows() - .find { it.getEndpoint().getSwitchId().equals(switchTriplet.getEp2().getDpId()) } - .getFlowId() - def expectedResponseSubflowPart = UniSubFlowPingPayload.builder() - .pingSuccess(true) - .build() - def expectedResponse = YFlowPingResult.builder() - .yFlowId(yFlow.yFlowId) - .pingSuccess(false) - .error("One sub flow is one-switch flow") - .subFlows([SubFlowPingPayload.builder() - .flowId(multiSwitchSubFlowId) - .forward(expectedResponseSubflowPart) - .reverse(expectedResponseSubflowPart) - .build()]) - .build() - when: "ping y-flow" - def response = yFlow.ping(new YFlowPingPayload(2000)) - response = 'replace unpredictable latency values from ping response'(response) + def collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() then: "y-flow ping is not successful, but one of subflows ping is successful" - response == expectedResponse + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.error == "One sub flow is one-switch flow" + assert collectedDiscrepancies.subFlowsDiscrepancies.isEmpty() + } + + when: "Break the flow by removing flow rules from the intermediate switch" + String subFlow = yFlow.subFlows.find { it.endpoint.switchId != yFlow.sharedEndpoint.switchId }.flowId + def intermediateSwId = yFlow.retrieveAllEntityPaths().subFlowPaths.find { it.flowId == subFlow } + .getInvolvedIsls().first().dstSwitch.dpId + def rulesToDelete = switchRulesFactory.get(intermediateSwId).getRules().findAll { + !new Cookie(it.cookie).serviceFlag + }*.cookie + rulesToDelete.each { cookie -> + switchHelper.deleteSwitchRules(intermediateSwId, cookie) + } + collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() + + then: "y-flow ping is not successful, and ping for another sub-flow shows that path is broken" + def expectedDiscrepancy = [(FlowDirection.FORWARD): "No ping for reasonable time", + (FlowDirection.REVERSE): "No ping for reasonable time"] + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.error == "One sub flow is one-switch flow" + assert collectedDiscrepancies.subFlowsDiscrepancies + .find { it.subFlowId == subFlow }.flowDiscrepancies == expectedDiscrepancy + } + + when: "All required rules have been installed(sync)" + switchHelper.synchronize(intermediateSwId) + collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() + + then: "y-flow ping is not successful, but one of subflows ping is successful" + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.error == "One sub flow is one-switch flow" + assert collectedDiscrepancies.subFlowsDiscrepancies.isEmpty() + } + } + + @Tags([LOW_PRIORITY]) + def "Able to ping y-flow and detect when path is broken"() { + given: "y-flow has been created" + def switchTriplet = switchTriplets.all().nonNeighbouring().findSwitchTripletWithYPointOnSharedEp() + assumeTrue(switchTriplet != null, "These cases cannot be covered on given topology:") + def yFlow = yFlowFactory.getRandom(switchTriplet) + + and: "ping for y-flow detects no discrepancy" + assert yFlow.ping().pingSuccess + + when: "Break one sub-flow by removing flow rules from the intermediate switch" + def yFlowPath = yFlow.retrieveAllEntityPaths() + def subFlow1Switch = yFlowPath.subFlowPaths.first().getInvolvedIsls().last().srcSwitch.dpId + def subFlow1Id = yFlowPath.subFlowPaths.first().flowId + def subFlow2Switch = yFlowPath.subFlowPaths.last().getInvolvedIsls().last().srcSwitch.dpId + def rulesToDelete = switchRulesFactory.get(subFlow1Switch).getRules().findAll { + !new Cookie(it.cookie).serviceFlag + }*.cookie + rulesToDelete.each { cookie -> + switchHelper.deleteSwitchRules(subFlow1Switch, cookie) + } + def collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() + + then: "y-flow ping is not successful, and ping for one sub-flow shows that path is broken" + def expectedDiscrepancy = [(FlowDirection.FORWARD): "No ping for reasonable time", + (FlowDirection.REVERSE): "No ping for reasonable time"] + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.subFlowsDiscrepancies + .find { it.subFlowId == subFlow1Id }.flowDiscrepancies == expectedDiscrepancy + assert !collectedDiscrepancies.subFlowsDiscrepancies.find { it.subFlowId != subFlow1Id } + } + + when: "Break another sub-flow by removing flow rules from the intermediate switch(after fixing previous discrepancy)" + switchHelper.synchronize(subFlow1Switch) + rulesToDelete = switchRulesFactory.get(subFlow2Switch).getRules().findAll { + !new Cookie(it.cookie).serviceFlag + }*.cookie + rulesToDelete.each { cookie -> + switchHelper.deleteSwitchRules(subFlow2Switch, cookie) + } + collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() + + then: "y-flow ping is not successful, and ping for another sub-flow shows that path is broken" + verifyAll { + assert !collectedDiscrepancies.pingSuccess + assert collectedDiscrepancies.subFlowsDiscrepancies + .find { it.subFlowId != subFlow1Id }.flowDiscrepancies == expectedDiscrepancy + assert !collectedDiscrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFlow1Id } + } + + when: "All required rules have been installed(sync)" + switchHelper.synchronize(subFlow2Switch) + collectedDiscrepancies = yFlow.pingAndCollectDiscrepancies() + + then: "y-flow ping is successful for both sub-flows" + verifyAll { + assert collectedDiscrepancies.pingSuccess + assert !collectedDiscrepancies.error + assert collectedDiscrepancies.subFlowsDiscrepancies.isEmpty() + } } def getPacketCountOfVlanPingRule(SwitchId switchId) { return northbound.getSwitchRules(switchId).flowEntries .findAll { it.cookie == Cookie.VERIFICATION_UNICAST_RULE_COOKIE }[0].packetCount } - - def 'replace unpredictable latency values from ping response'(YFlowPingResult originalResponse) { - //TODO: implement PingResponse model in test package to safely compare expected and actual responses without - //manipulating original response - def subFlowPingPayloadWithZeroLatency = originalResponse.subFlows[0].tap { - it.forward.latency = 0 - it.reverse.latency = 0 - } - originalResponse.subFlows[0] = subFlowPingPayloadWithZeroLatency - return originalResponse - } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/LagPortSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/LagPortSpec.groovy index a27489460b..cd0b36257f 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/LagPortSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/LagPortSpec.groovy @@ -157,10 +157,7 @@ class LagPortSpec extends HealthCheckSpecification { then: "Flow is valid and pingable" flow.validateAndCollectDiscrepancies().isEmpty() - verifyAll(flow.ping()) { - it.forward.pingSuccess - it.reverse.pingSuccess - } + flow.pingAndCollectDiscrepancies().isEmpty() and: "System allows traffic on the flow" def traffExam = traffExamProvider.get() From 1fe31f784e49f81d2b980fcfc4fe924130cfb871 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Wed, 2 Oct 2024 17:37:03 +0200 Subject: [PATCH 06/21] [TEST]: Improvement: Verification of validation response --- .../ComplexFlowValidationResponse.groovy | 51 +++++++++++++++++++ .../helpers/model/FlowDirection.groovy | 2 +- .../helpers/model/HaFlowExtended.groovy | 5 ++ .../SubFlowValidationDiscrepancies.groovy | 13 +++++ .../helpers/model/YFlowExtended.groovy | 5 ++ .../flows/haflows/HaFlowDiversitySpec.groovy | 15 +++--- .../flows/haflows/HaFlowValidationSpec.groovy | 22 ++++---- .../spec/flows/yflows/YFlowCreateSpec.groovy | 4 +- .../flows/yflows/YFlowValidationSpec.groovy | 22 +++----- .../server42/Server42HaFlowRttSpec.groovy | 10 ++-- .../spec/server42/Server42YFlowRttSpec.groovy | 10 ++-- 11 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy new file mode 100644 index 0000000000..330c000d74 --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy @@ -0,0 +1,51 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.northbound.dto.v1.flows.FlowValidationDto +import org.openkilda.northbound.dto.v1.flows.PathDiscrepancyDto +import org.openkilda.northbound.dto.v2.haflows.HaFlowValidationResult +import org.openkilda.northbound.dto.v2.yflows.YFlowValidationResult + +import groovy.transform.ToString + +@ToString +class ComplexFlowValidationResponse { + private static final String COOKIE_ID_IN_RULE_DISCREPANCY_STRING_REGEX = /-?\d{19}/ + + boolean asExpected + List subFlowsDiscrepancies + + ComplexFlowValidationResponse(YFlowValidationResult yFlowValidation) { + this.asExpected = yFlowValidation.asExpected + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(yFlowValidation.subFlowValidationResults) + } + + ComplexFlowValidationResponse(HaFlowValidationResult haFlowValidation) { + this.asExpected = haFlowValidation.asExpected + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(haFlowValidation.subFlowValidationResults) + + } + + private static List collectDiscrepanciesPerSubFlow(List subFlowValidationDetails) { + List discrepanciesPerSubFlow = subFlowValidationDetails.groupBy { it.flowId }.collect { + assert (it.value.direction*.toUpperCase() as Set).size() == it.value.size(), "There is an error in the validation logic $it" + HashMap> discrepancy = [:] + it.value.each { + verifyValidateLogic(it) + it.asExpected ?: discrepancy.put(FlowDirection.getByDirection(it.direction.toLowerCase()), it.discrepancies) + } + discrepancy.isEmpty() ? null : new SubFlowValidationDiscrepancies(subFlowId: it.key, flowDiscrepancies: discrepancy) + + }.findAll() + discrepanciesPerSubFlow + } + + private static void verifyValidateLogic(FlowValidationDto validationDto) { + assert (validationDto.asExpected && validationDto.discrepancies.isEmpty()) || (!validationDto.asExpected && !validationDto.discrepancies.isEmpty()), + "There is an error in the validation logic $validationDto" + } + + Set retrieveAllRulesCookieFromDiscrepancy() { + def rules = subFlowsDiscrepancies.flowDiscrepancies*.values().flatten() + rules.collect { new Long((it =~ COOKIE_ID_IN_RULE_DISCREPANCY_STRING_REGEX)[0]) } + } +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy index b0a8aa120f..c34216929b 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy @@ -22,6 +22,6 @@ enum FlowDirection { return flowDirection } } - throw new IllegalArgumentException("Invalid value for encapsulation type") + throw new IllegalArgumentException("Invalid value for direction") } } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy index 3d2fe4a117..909b235d6a 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy @@ -287,6 +287,11 @@ class HaFlowExtended { northboundV2.validateHaFlow(haFlowId) } + ComplexFlowValidationResponse validateAndCollectDiscrepancy() { + def validationResponse = validate() + new ComplexFlowValidationResponse(validationResponse) + } + HaFlowSyncResult sync() { log.debug("Sync ha-flow '${haFlowId}'") northboundV2.syncHaFlow(haFlowId) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy new file mode 100644 index 0000000000..d0161a4d2b --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy @@ -0,0 +1,13 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.northbound.dto.v1.flows.PathDiscrepancyDto + +import groovy.transform.ToString +import groovy.transform.TupleConstructor + +@TupleConstructor +@ToString +class SubFlowValidationDiscrepancies { + String subFlowId + Map> flowDiscrepancies +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy index 8ac9f97e00..9a3c390563 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy @@ -262,6 +262,11 @@ class YFlowExtended { northboundV2.validateYFlow(yFlowId) } + ComplexFlowValidationResponse validateAndCollectDiscrepancy() { + def validationResponse = validate() + new ComplexFlowValidationResponse(validationResponse) + } + YFlowSyncResult sync() { log.debug("Synchronize Y-Flow '${yFlowId}'") northboundV2.synchronizeYFlow(yFlowId) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy index 57fb1de9ff..8a32903712 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy @@ -72,9 +72,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2, haFlow3].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty() } + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } @@ -127,9 +126,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty()} + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } @@ -181,9 +179,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty()} + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy index c3b48ec87f..d07aa773c6 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy @@ -2,7 +2,6 @@ package org.openkilda.functionaltests.spec.flows.haflows import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW import static org.openkilda.functionaltests.extension.tags.Tag.SMOKE -import static org.openkilda.functionaltests.helpers.model.SwitchRules.missingRuleCookieIds import static org.openkilda.testing.Constants.RULES_DELETION_TIME import org.openkilda.functionaltests.HealthCheckSpecification @@ -39,11 +38,11 @@ class HaFlowValidationSpec extends HealthCheckSpecification { def haFlow = haFlowFactory.getRandom(swT) when: "Validate HA-Flow" - def validationResult = haFlow.validate() + def validationResult = haFlow.validateAndCollectDiscrepancy() then: "HA-Flow is validated successfully" validationResult.asExpected - validationResult.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty() } + validationResult.subFlowsDiscrepancies.isEmpty() } def "HA-Flow validation should fail in case of missing rule on #switchRole switch"() { @@ -59,11 +58,11 @@ class HaFlowValidationSpec extends HealthCheckSpecification { then: "HA-Flow validation returns deleted rule in 'Discrepancies' section" Wrappers.wait(RULES_DELETION_TIME) { - def validationResponse = haFlow.validate() - assert !validationResponse.asExpected - def missingRules = validationResponse.getSubFlowValidationResults().collect { it.getDiscrepancies() }.flatten() + def discrepancies = haFlow.validateAndCollectDiscrepancy() + assert !discrepancies.asExpected + def missingRules = discrepancies.retrieveAllRulesCookieFromDiscrepancy() assert missingRules.size() == 1, "We deleted only one rule" - assert missingRules.get(0).getRule().contains(haFlowRuleToDelete.getCookie().toString()) + assert missingRules.first() == haFlowRuleToDelete.getCookie() } where: @@ -91,11 +90,10 @@ class HaFlowValidationSpec extends HealthCheckSpecification { then: "HA-Flow validation returns rules related to deleted meter in 'Discrepancies' section" Wrappers.wait(RULES_DELETION_TIME) { - def validationResponse = haFlow.validate() - assert !validationResponse.asExpected - def missingMeters = validationResponse.getSubFlowValidationResults().collect { it.getDiscrepancies() }.flatten() - assert missingMeters.size() == expectedDeletedSwitchRules.size() - assert missingRuleCookieIds(missingMeters) == expectedDeletedSwitchRules.collect { it.getCookie() } as Set + def discrepancies = haFlow.validateAndCollectDiscrepancy() + assert !discrepancies.asExpected + def missingMeters = discrepancies.retrieveAllRulesCookieFromDiscrepancy() + assert missingMeters == expectedDeletedSwitchRules.collect { it.getCookie() } as Set } where: diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy index 45dcba9ae8..eb5a358732 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy @@ -73,9 +73,9 @@ class YFlowCreateSpec extends HealthCheckSpecification { def paths = yFlow.retrieveAllEntityPaths() and: "Y-Flow passes flow validation" - with(yFlow.validate()) { + with(yFlow.validateAndCollectDiscrepancy()) { it.asExpected - it.subFlowValidationResults.each { assert it.asExpected } + it.subFlowsDiscrepancies.isEmpty() } and: "Both sub-flows pass flow validation" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy index 97cb481990..05232e81a8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy @@ -6,6 +6,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.yflow.YFlowNotFoundExpectedError import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.YFlowFactory import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.messaging.payload.flow.FlowState @@ -94,25 +95,17 @@ class YFlowValidationSpec extends HealthCheckSpecification { switchHelper.deleteSwitchRules(swIdToManipulate, cookieToDelete) then: "Y-Flow is not valid" - def validateYFlowInfo = yFlow.validate() - !validateYFlowInfo.asExpected + def discrepancies = yFlow.validateAndCollectDiscrepancy() + !discrepancies.asExpected and: "Discrepancies has been detected for broken sub-flow REVERSE direction" - def reverseBrokenSubFlow = validateYFlowInfo.subFlowValidationResults - .find { it.flowId == subFl_1.flowId && it.direction == Direction.REVERSE.name() } - assert !reverseBrokenSubFlow.asExpected && reverseBrokenSubFlow.discrepancies + assert discrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFl_1.flowId }.flowDiscrepancies.get(FlowDirection.REVERSE) and: "No discrepancies has been detected for broken sub-flow FORWARD direction" - def forwardBrokenSubFlow = validateYFlowInfo.subFlowValidationResults - .find { it.flowId == subFl_1.flowId && it.direction == Direction.FORWARD.name() } - assert forwardBrokenSubFlow.asExpected && forwardBrokenSubFlow.discrepancies.empty - + assert !discrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFl_1.flowId }.flowDiscrepancies.get(FlowDirection.FORWARD) and: "No discrepancies has been detected for another sub-flow" - validateYFlowInfo.subFlowValidationResults - .findAll { it.flowId != subFl_1.flowId }.each { - assert it.asExpected && it.discrepancies.empty - } + assert !discrepancies.subFlowsDiscrepancies.find { it.subFlowId != subFl_1.flowId } and: "Simple flow validation detects discrepancies for the subFlow_1 REVERSE direction only" verifyAll(northbound.validateFlow(subFl_1.flowId)) { subFlow1 -> @@ -138,7 +131,8 @@ class YFlowValidationSpec extends HealthCheckSpecification { yFlow.waitForBeingInState(FlowState.UP) then: "Y-Flow/subFlow passes flow validation" - yFlow.validate().asExpected + def discrepanciesAfterSync = yFlow.validateAndCollectDiscrepancy() + discrepanciesAfterSync.asExpected && discrepanciesAfterSync.subFlowsDiscrepancies.isEmpty() yFlow.subFlows.each { northbound.validateFlow(it.flowId).each { direction -> assert direction.asExpected } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy index b094a0b4a7..82cb7623d0 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy @@ -17,6 +17,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet @@ -135,11 +136,10 @@ class Server42HaFlowRttSpec extends HealthCheckSpecification { } and: "Ha-Flow is valid and UP" - haFlow.validate().subFlowValidationResults.each { validationInfo -> - if (validationInfo.direction == "forward") { - assert !validationInfo.asExpected - } else { - assert validationInfo.asExpected + verifyAll(haFlow.validateAndCollectDiscrepancy()) { validationResult -> + assert !validationResult.asExpected + validationResult.subFlowsDiscrepancies.each { + assert it.flowDiscrepancies.get(FlowDirection.FORWARD) && !it.flowDiscrepancies.get(FlowDirection.REVERSE) } } haFlow.retrieveDetails().status == FlowState.UP diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy index b05dee6d74..c9392b2f1e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy @@ -24,6 +24,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.builder.YFlowBuilder +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet @@ -412,13 +413,10 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { } and: "Y-Flow is valid and UP" - verifyAll(yFlow.validate()) { validationResult -> + verifyAll(yFlow.validateAndCollectDiscrepancy()) { validationResult -> assert !validationResult.asExpected - validationResult.getSubFlowValidationResults().findAll { it.direction == "FORWARD" }.each { - assert !it.asExpected - } - validationResult.getSubFlowValidationResults().findAll { it.direction == "REVERSE" }.each { - assert it.asExpected + validationResult.subFlowsDiscrepancies.each { + assert it.flowDiscrepancies.get(FlowDirection.FORWARD) && !it.flowDiscrepancies.get(FlowDirection.REVERSE) } } From 8d78f561ac5d8aeed26bd6003774dba7999ad0da Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Wed, 25 Sep 2024 12:18:55 +0200 Subject: [PATCH 07/21] [TEST]: Improvement: Switch rules/meters comparison --- .../helpers/model/FlowExtended.groovy | 3 +- .../helpers/model/FlowRuleEntity.groovy | 159 ++++++++++++++++++ .../helpers/model/SwitchRules.groovy | 39 +++-- .../spec/flows/FlowCrudSpec.groovy | 6 +- .../spec/flows/FlowSyncSpec.groovy | 8 +- .../spec/flows/MirrorEndpointsSpec.groovy | 23 +-- .../spec/flows/PinnedFlowSpec.groovy | 2 +- .../spec/flows/VxlanFlowSpec.groovy | 6 +- .../spec/flows/haflows/HaFlowSyncSpec.groovy | 4 +- .../spec/server42/Server42IslRttSpec.groovy | 78 ++------- .../spec/switches/DefaultRulesSpec.groovy | 83 ++++----- .../spec/switches/FlowRulesSpec.groovy | 83 +++++---- .../spec/switches/MetersSpec.groovy | 22 +-- 13 files changed, 306 insertions(+), 210 deletions(-) create mode 100644 src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowRuleEntity.groovy diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy index 23a7404b07..f705054a1e 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowExtended.groovy @@ -16,7 +16,6 @@ import static org.openkilda.testing.Constants.WAIT_OFFSET import org.openkilda.functionaltests.model.cleanup.CleanupAfter import org.openkilda.functionaltests.model.cleanup.CleanupManager -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.info.meter.FlowMeterEntries import org.openkilda.messaging.payload.flow.DetectConnectedDevicesPayload import org.openkilda.messaging.payload.flow.FlowCreatePayload @@ -832,7 +831,7 @@ class FlowExtended { * * @param flowInvolvedSwitchesWithRules (map of switch-rules data for further verification) */ - void verifyRulesForProtectedFlowOnSwitches(HashMap> flowInvolvedSwitchesWithRules) { + void verifyRulesForProtectedFlowOnSwitches(HashMap> flowInvolvedSwitchesWithRules) { def flowDBInfo = retrieveDetailsFromDB() long mainForwardCookie = flowDBInfo.forwardPath.cookie.value long mainReverseCookie = flowDBInfo.reversePath.cookie.value diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowRuleEntity.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowRuleEntity.groovy new file mode 100644 index 0000000000..52f60ae53b --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowRuleEntity.groovy @@ -0,0 +1,159 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.messaging.info.rule.FlowApplyActions +import org.openkilda.messaging.info.rule.FlowCopyFieldAction +import org.openkilda.messaging.info.rule.FlowEntry +import org.openkilda.messaging.info.rule.FlowInstructions +import org.openkilda.messaging.info.rule.FlowMatchField +import org.openkilda.messaging.info.rule.FlowSetFieldAction +import org.openkilda.messaging.info.rule.FlowSwapFieldAction + +import groovy.transform.Canonical +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString + +@ToString(includeNames = true) +@Canonical +@EqualsAndHashCode(excludes = 'durationSeconds, durationNanoSeconds, packetCount, byteCount') +class FlowRuleEntity { + long cookie + long durationSeconds + long durationNanoSeconds + long tableId + long packetCount + String version + int priority + long idleTimeout + long hardTimeout + long byteCount + MatchField match + Instruction instructions + String[] flags + + FlowRuleEntity(FlowEntry entry) { + this.cookie = entry.cookie + this.tableId = entry.tableId + this.durationSeconds = entry.durationSeconds + this.durationNanoSeconds = entry.durationNanoSeconds + this.packetCount = entry.packetCount + this.version = entry.version + this.priority = entry.priority + this.idleTimeout = entry.idleTimeout + this.hardTimeout = entry.hardTimeout + this.byteCount = entry.byteCount + this.match = entry.match ? new MatchField(entry.match) : null + this.instructions = entry.instructions ? new Instruction(entry.instructions) : null + this.flags = entry.flags + } + + @ToString(includeNames = true) + @Canonical + class MatchField { + String ethSrc + String ethDst + String ethType + String ipProto + String udpSrc + String udpDst + String inPort + String vlanVid + String tunnelId + String metadataValue + String metadataMask + + MatchField(FlowMatchField matchField) { + this.ethSrc = matchField.ethSrc + this.ethDst = matchField.ethDst + this.ethType = matchField.ethType + this.ipProto = matchField.ipProto + this.udpSrc = matchField.udpSrc + this.udpDst = matchField.udpDst + this.inPort = matchField.inPort + this.vlanVid = matchField.vlanVid + this.tunnelId = matchField.tunnelId + this.metadataValue = matchField.metadataValue + this.metadataMask = matchField.metadataMask + } + } + + @ToString(includeNames = true) + @Canonical + class Instruction { + ApplyActions applyActions + String none + Long goToMeter + Short goToTable + + Instruction(FlowInstructions instructions) { + this.applyActions = instructions.applyActions ? new ApplyActions(instructions.applyActions) : null + this.none = instructions.none + this.goToMeter = instructions.goToMeter + this.goToTable = instructions.goToTable + } + } + + @ToString(includeNames = true) + @Canonical + class ApplyActions { + String flowOutput + List setFieldActions + String pushVlan + String popVlan + String meter + String pushVxlan + String group + FieldActionBase copyFieldAction + FieldActionBase swapFieldAction + + ApplyActions(FlowApplyActions applyActions) { + this.flowOutput = applyActions.flowOutput + this.setFieldActions = applyActions.setFieldActions.collect { new SetFieldAction(it) } + this.pushVlan = applyActions.pushVlan + this.popVlan = applyActions.popVlan + this.meter = applyActions.meter + this.pushVxlan = applyActions.pushVxlan + this.group = applyActions.group + this.copyFieldAction = applyActions.copyFieldAction ? new FieldActionBase(applyActions.copyFieldAction) : null + this.swapFieldAction = applyActions.swapFieldAction ? new FieldActionBase(applyActions.swapFieldAction) : null + + } + + @ToString(includeNames = true) + @Canonical + class SetFieldAction { + String fieldName + String fieldValue + + SetFieldAction(FlowSetFieldAction flowSetFieldAction) { + this.fieldName = flowSetFieldAction.fieldName + this.fieldValue = flowSetFieldAction.fieldValue + } + } + + @ToString(includeNames = true) + @Canonical + class FieldActionBase { + String bits + String srcOffset + String dstOffset + String srcOxm + String dstOxm + + FieldActionBase(FlowCopyFieldAction copyFieldAction) { + this.bits = copyFieldAction.bits + this.srcOffset = copyFieldAction.srcOffset + this.dstOffset = copyFieldAction.dstOffset + this.srcOxm = copyFieldAction.srcOxm + this.dstOxm = copyFieldAction.dstOxm + } + + FieldActionBase(FlowSwapFieldAction swapFieldAction) { + this.bits = swapFieldAction.bits + this.srcOffset = swapFieldAction.srcOffset + this.dstOffset = swapFieldAction.dstOffset + this.srcOxm = swapFieldAction.srcOxm + this.dstOxm = swapFieldAction.dstOxm + } + } + } +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchRules.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchRules.groovy index 095d6716fe..711012e695 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchRules.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchRules.groovy @@ -1,8 +1,6 @@ package org.openkilda.functionaltests.helpers.model import org.openkilda.functionaltests.model.cleanup.CleanupManager -import org.openkilda.messaging.command.switches.DeleteRulesAction -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.model.FlowEncapsulationType import org.openkilda.model.FlowMeter import org.openkilda.model.SwitchId @@ -31,19 +29,18 @@ class SwitchRules { this.switchId = switchId } - List forHaFlow(HaFlowExtended haFlow) { + List forHaFlow(HaFlowExtended haFlow) { def haFlowCookies = (database.getHaFlowCookies(haFlow.haFlowId) + database.getHaSubFlowsCookies(haFlow.subFlows*.haSubFlowId)) .collect {it.getValue()} - def switchRules = northboundService.getSwitchRules(switchId) - return switchRules.getFlowEntries().findAll {haFlowCookies.contains(it.getCookie())} + def switchRules = getRules() + return switchRules.findAll {haFlowCookies.contains(it.getCookie())} } - Set relatedToMeter(FlowMeter flowMeter) { - return northboundService.getSwitchRules(switchId).getFlowEntries() - .findAll {it.getInstructions().getGoToMeter() == flowMeter.getMeterId().getValue()} + Set relatedToMeter(FlowMeter flowMeter) { + return getRules().findAll {it.getInstructions().getGoToMeter() == flowMeter.getMeterId().getValue()} } - void delete(FlowEntry flowEntry) { + void delete(FlowRuleEntity flowEntry) { delete(flowEntry.getCookie()) } @@ -56,10 +53,9 @@ class SwitchRules { return missingRules.collect {new Long((it.getRule() =~ COOKIE_ID_IN_RULE_DISCREPANCY_STRING_REGEX)[0])} } - FlowEntry pingRule(String encapsulationType) { + FlowRuleEntity pingRule(String encapsulationType) { def pingRuleCookie = getPingRuleCookie(encapsulationType) - return northboundService.getSwitchRules(switchId).flowEntries - .find { it.cookie == pingRuleCookie } + return getRules().find { it.cookie == pingRuleCookie } } static long getPingRuleCookie(String encapsulationType) { @@ -72,18 +68,21 @@ class SwitchRules { } } - List getRulesByCookieType(CookieType cookieType) { - northboundService.getSwitchRules(switchId).flowEntries - .findAll { new Cookie(it.cookie).getType() == cookieType } + List getRulesByCookieType(CookieType cookieType) { + getRules().findAll { new Cookie(it.cookie).getType() == cookieType } } - List getServer42FlowRules() { - northboundService.getSwitchRules(switchId).flowEntries - .findAll { new Cookie(it.cookie).getType() in [CookieType.SERVER_42_FLOW_RTT_INPUT, + List getServer42FlowRules() { + getRules().findAll { new Cookie(it.cookie).getType() in [CookieType.SERVER_42_FLOW_RTT_INPUT, CookieType.SERVER_42_FLOW_RTT_INGRESS] } } - List getRules() { - northboundService.getSwitchRules(switchId).flowEntries + List getServer42ISLRules() { + getRules().findAll { (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT] || + it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) } + } + + List getRules() { + northboundService.getSwitchRules(switchId).flowEntries.collect { new FlowRuleEntity(it) } } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy index d55121d17e..1db67384da 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowCrudSpec.groovy @@ -1,6 +1,6 @@ package org.openkilda.functionaltests.spec.flows -import org.openkilda.messaging.info.rule.FlowEntry +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import groovy.util.logging.Slf4j import org.openkilda.functionaltests.HealthCheckSpecification @@ -715,8 +715,8 @@ Failed to find path with requested bandwidth=${IMPOSSIBLY_HIGH_BANDWIDTH}/) and: "Rules for main and protected paths are created" wait(WAIT_OFFSET) { - HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() - .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> + HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() + .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> flow.verifyRulesForProtectedFlowOnSwitches(flowInvolvedSwitchesWithRules) } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowSyncSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowSyncSpec.groovy index 07a4a3aa46..ba815dee4b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowSyncSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/FlowSyncSpec.groovy @@ -10,8 +10,8 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.factory.FlowFactory +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.SwitchId import org.openkilda.model.cookie.Cookie @@ -67,8 +67,8 @@ class FlowSyncSpec extends HealthCheckSpecification { Wrappers.wait(RULES_INSTALLATION_TIME) { def flowRules = getFlowRules(sw) assert flowRules.size() == flowRulesCount - flowRules.each { - assert it.durationSeconds < TimeCategory.minus(new Date(), syncTime).toMilliseconds() / 1000.0 + flowRules.each { rule -> + assert rule.durationSeconds < TimeCategory.minus(new Date(), syncTime).toMilliseconds() / 1000.0 } } } @@ -77,7 +77,7 @@ class FlowSyncSpec extends HealthCheckSpecification { flow.validateAndCollectDiscrepancies().isEmpty() } - List getFlowRules(SwitchId swId) { + List getFlowRules(SwitchId swId) { switchRulesFactory.get(swId).getRules().findAll { def cookie = new Cookie(it.cookie) cookie.type == CookieType.SERVICE_OR_FLOW_SEGMENT && !cookie.serviceFlag }.sort() diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MirrorEndpointsSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MirrorEndpointsSpec.groovy index f0af90a897..110ff9c0a9 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MirrorEndpointsSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/MirrorEndpointsSpec.groovy @@ -1,6 +1,6 @@ package org.openkilda.functionaltests.spec.flows -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs + import static org.junit.jupiter.api.Assumptions.assumeFalse import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.HARDWARE @@ -13,7 +13,6 @@ import static org.openkilda.functionaltests.helpers.SwitchHelper.randomVlan import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.OTHER import static org.openkilda.functionaltests.model.stats.FlowStatsMetric.FLOW_RAW_BYTES import static org.openkilda.testing.Constants.WAIT_OFFSET -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.AbstractExpectedError @@ -28,11 +27,11 @@ import org.openkilda.functionaltests.helpers.factory.FlowFactory import org.openkilda.functionaltests.helpers.model.FlowActionType import org.openkilda.functionaltests.helpers.model.FlowEncapsulationType import org.openkilda.functionaltests.helpers.model.FlowExtended +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.SwitchPair import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.model.cleanup.CleanupManager import org.openkilda.functionaltests.model.stats.FlowStats -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.FlowPathDirection import org.openkilda.model.FlowPathStatus @@ -122,9 +121,13 @@ class MirrorEndpointsSpec extends HealthCheckSpecification { assert mirrorPointsDetails[0].status == FlowPathStatus.ACTIVE.toString().toLowerCase() assert mirrorPointsDetails[0].mirrorPointId == mirrorPointPayload.mirrorPointId } - with(flow.retrieveMirrorPoints()) { - points.size() == 1 - expect points[0], sameBeanAs(mirrorPointPayload) + def flowMirrorDetails = flow.retrieveMirrorPoints() + assert flowMirrorDetails.points.size() == 1 + verifyAll(flowMirrorDetails.points.first()) { + assert mirrorPointId == mirrorPointPayload.mirrorPointId + assert mirrorPointDirection == mirrorPointPayload.mirrorPointDirection + assert mirrorPointSwitchId == mirrorPointPayload.mirrorPointSwitchId + assert sinkEndpoint == mirrorPointPayload.sinkEndpoint } and: "Mirror flow rule has an OF group action and higher prio than flow rule" @@ -864,23 +867,23 @@ flow mirror point cannot be created this flow/).matches(error) } - List getFlowRules(SwitchId swId) { + List getFlowRules(SwitchId swId) { def swRules = switchRulesFactory.get(swId).getRules() swRules.findAll { new FlowSegmentCookie(it.cookie).direction != FlowPathDirection.UNDEFINED } } - static FlowEntry findRule(List rules, FlowPathDirection pathDirection, boolean isMirror) { + static FlowRuleEntity findRule(List rules, FlowPathDirection pathDirection, boolean isMirror) { rules.find { def cookie = new FlowSegmentCookie(it.cookie) cookie.direction == pathDirection && cookie.isMirror() == isMirror } } - static FlowEntry findFlowRule(List rules, FlowPathDirection pathDirection) { + static FlowRuleEntity findFlowRule(List rules, FlowPathDirection pathDirection) { findRule(rules, pathDirection, false) } - static FlowEntry findMirrorRule(List rules, FlowPathDirection pathDirection) { + static FlowRuleEntity findMirrorRule(List rules, FlowPathDirection pathDirection) { findRule(rules, pathDirection, true) } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy index 2f9412d2b0..3e97da3aa4 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/PinnedFlowSpec.groovy @@ -133,7 +133,7 @@ class PinnedFlowSpec extends HealthCheckSpecification { and: "Rules and meters are not changed" def cookiesMapAfterReroute = involvedSwitches.collectEntries { sw -> - [sw.id, northbound.getSwitchRules(sw).flowEntries.findAll { + [sw.id, switchRulesFactory.get(sw).getRules().findAll { !new Cookie(it.cookie).serviceFlag }*.cookie] } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy index 93bd4e7b9e..7635fea239 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/VxlanFlowSpec.groovy @@ -20,10 +20,10 @@ import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.factory.FlowFactory import org.openkilda.functionaltests.helpers.model.FlowEncapsulationType import org.openkilda.functionaltests.helpers.model.Path +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.SwitchPair import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.model.stats.Direction -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.SwitchId import org.openkilda.model.cookie.Cookie @@ -248,8 +248,8 @@ class VxlanFlowSpec extends HealthCheckSpecification { and: "Rules for main and protected paths are created" Wrappers.wait(WAIT_OFFSET) { - HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() - .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> + HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() + .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> flow.verifyRulesForProtectedFlowOnSwitches(flowInvolvedSwitchesWithRules) } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy index 28d1024311..9f5640e9cd 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy @@ -16,9 +16,9 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory -import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.SwitchId @@ -54,7 +54,7 @@ class HaFlowSyncSpec extends HealthCheckSpecification { assert !haFlowRulesToDelete.isEmpty() withPool { - haFlowRulesToDelete.eachParallel { FlowEntry rule -> + haFlowRulesToDelete.eachParallel { FlowRuleEntity rule -> switchRules.delete(rule) } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42IslRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42IslRttSpec.groovy index 5d7008ef24..09632f9a6d 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42IslRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42IslRttSpec.groovy @@ -1,8 +1,7 @@ package org.openkilda.functionaltests.spec.server42 -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs -import static groovyx.gpars.GParsPool.withPool import static org.assertj.core.api.Assertions.assertThat +import static groovyx.gpars.GParsPool.withPool import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.ResourceLockConstants.S42_TOGGLE import static org.openkilda.functionaltests.extension.tags.Tag.HARDWARE @@ -20,11 +19,12 @@ import static org.openkilda.testing.Constants.RULES_DELETION_TIME import static org.openkilda.testing.Constants.RULES_INSTALLATION_TIME import static org.openkilda.testing.Constants.WAIT_OFFSET import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMode.RW -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.SwitchHelper +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity +import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.model.stats.IslStats import org.openkilda.messaging.model.SwitchPropertiesDto.RttState import org.openkilda.model.SwitchFeature @@ -53,6 +53,9 @@ class Server42IslRttSpec extends HealthCheckSpecification { @Shared @Value('${latency.update.interval}') Integer latencyUpdateInterval + @Autowired + @Shared + SwitchRulesFactory switchRulesFactory int islSyncWaitSeconds = 60 //server42.control.rtt.sync.interval.seconds int statsWaitSeconds = 4 @@ -163,10 +166,8 @@ class Server42IslRttSpec extends HealthCheckSpecification { and: "ISL RTT rules are not installed for the new link because it is the same as moved(portNumber)" wait(RULES_INSTALLATION_TIME) { // newIsl.srcSwitch == isl.srcSwitch - assert northbound.getSwitchRules(newIsl.srcSwitch.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - }.size() == (northbound.getLinks(newIsl.srcSwitch.dpId, null, null, null).size() - 1 + 2) + assert switchRulesFactory.get(newIsl.srcSwitch.dpId).getServer42ISLRules().size() == + (northbound.getLinks(newIsl.srcSwitch.dpId, null, null, null).size() - 1 + 2) // -1 = moved link, 2 = SERVER_42_ISL_RTT_TURNING_COOKIE + SERVER_42_ISL_RTT_OUTPUT_COOKIE } @@ -193,12 +194,10 @@ class Server42IslRttSpec extends HealthCheckSpecification { when: "Replug the link back where it was" islUtils.replug(newIsl, true, isl, false, false) islUtils.waitForIslStatus([isl, isl.reversed], DISCOVERED) - def originIslIsUp = true islUtils.waitForIslStatus([newIsl, newIsl.reversed], MOVED) and: "Remove the MOVED ISL" assert northbound.deleteLink(islUtils.toLinkParameters(newIsl)).size() == 2 - def newIslIsRemoved = true then: "Server42 ISL RTT rules are deleted on the dst switch of the moved link" wait(RULES_DELETION_TIME) { checkIslRttRules(newIsl.dstSwitch.dpId, true) } @@ -298,12 +297,9 @@ class Server42IslRttSpec extends HealthCheckSpecification { changeIslRttToggle(true) then: "IslRtt rules are installed on the switch" - def s42IslRttTurningRule + FlowRuleEntity s42IslRttTurningRule wait(RULES_INSTALLATION_TIME) { - def s42IslRttRules = northbound.getSwitchRules(sw.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - } + def s42IslRttRules = switchRulesFactory.get(sw.dpId).getServer42ISLRules() assert s42IslRttRules.size() == (northbound.getLinks(sw.dpId, null, null, null).size() + 2) s42IslRttTurningRule = s42IslRttRules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE } } @@ -317,10 +313,7 @@ class Server42IslRttSpec extends HealthCheckSpecification { then: "SERVER_42_ISL_RTT_OUTPUT_COOKIE and SERVER_42_ISL_RTT_INPUT rules updated according to the changes" and: "SERVER_42_ISL_RTT_TURNING_COOKIE is not changed" wait(RULES_INSTALLATION_TIME) { - def rules = northbound.getSwitchRules(sw.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - } + def rules = switchRulesFactory.get(sw.dpId).getServer42ISLRules() assert rules.size() == northbound.getLinks(sw.dpId, null, null, null).size() + 2 assert rules.findAll { new Cookie(it.cookie).getType() == CookieType.SERVER_42_ISL_RTT_INPUT @@ -328,11 +321,7 @@ class Server42IslRttSpec extends HealthCheckSpecification { assert rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE }.instructions.applyActions.flowOutput == newS42Port.toString() - assert expect(rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE }, sameBeanAs(s42IslRttTurningRule) - .ignoring("byteCount") - .ignoring("packetCount") - .ignoring("durationSeconds") - .ignoring("durationNanoSeconds")) + assert rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE } == s42IslRttTurningRule } when: "server42IslRtt feature toggle is set to false" @@ -358,10 +347,7 @@ class Server42IslRttSpec extends HealthCheckSpecification { then: "SERVER_42_ISL_RTT_OUTPUT_COOKIE and SERVER_42_ISL_RTT_INPUT rules updated according to the changes" and: "SERVER_42_ISL_RTT_TURNING_COOKIE is not changed" wait(RULES_INSTALLATION_TIME) { - def rules = northbound.getSwitchRules(sw.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - } + def rules = switchRulesFactory.get(sw.dpId).getServer42ISLRules() assert rules.size() == northbound.getLinks(sw.dpId, null, null, null).size() + 2 assert rules.findAll { new Cookie(it.cookie).getType() == CookieType.SERVER_42_ISL_RTT_INPUT @@ -369,11 +355,7 @@ class Server42IslRttSpec extends HealthCheckSpecification { assert rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE }.instructions.applyActions.flowOutput == originSwProps.server42Port.toString() - assert expect(rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE }, sameBeanAs(s42IslRttTurningRule) - .ignoring("byteCount") - .ignoring("packetCount") - .ignoring("durationSeconds") - .ignoring("durationNanoSeconds")) + assert rules.find { it.cookie == Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE } == s42IslRttTurningRule } } @@ -478,10 +460,7 @@ class Server42IslRttSpec extends HealthCheckSpecification { wait(RULES_INSTALLATION_TIME) { checkIslRttRules(isl.srcSwitch.dpId, true) } when: "Delete ISL Rtt rules on the src switch" - def rulesToDelete = northbound.getSwitchRules(isl.srcSwitch.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - } + def rulesToDelete = switchRulesFactory.get(isl.srcSwitch.dpId).getServer42ISLRules() withPool { rulesToDelete.eachParallel { switchHelper.deleteSwitchRules(isl.srcSwitch.dpId, it.cookie) } } @@ -510,15 +489,8 @@ class Server42IslRttSpec extends HealthCheckSpecification { and: "ISL Rtt rules are really installed" wait(RULES_INSTALLATION_TIME) { - def installedRules = northbound.getSwitchRules(isl.srcSwitch.dpId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - } - assert expect(installedRules.sort { it.cookie }, sameBeanAs(rulesToDelete.sort { it.cookie }) - .ignoring("byteCount") - .ignoring("packetCount") - .ignoring("durationNanoSeconds") - .ignoring("durationSeconds")) + def installedRules = switchRulesFactory.get(isl.srcSwitch.dpId).getServer42ISLRules() + assertThat(installedRules).containsExactlyInAnyOrder(*rulesToDelete) } and: "ISL Rtt stats are available in both directions" @@ -556,23 +528,9 @@ class Server42IslRttSpec extends HealthCheckSpecification { return originalState } - def revertToOrigin(islRttFeatureStartState, initialSwitchRtt) { - islRttFeatureStartState != null && changeIslRttToggle(islRttFeatureStartState) - initialSwitchRtt.each { sw, state -> changeIslRttSwitch(sw, state) } - initialSwitchRtt.keySet().each { sw -> - wait(RULES_INSTALLATION_TIME) { - assertThat(northbound.getSwitchRules(sw.dpId).flowEntries*.cookie.toArray()).as(sw.dpId.toString()) - .containsExactlyInAnyOrder(*sw.defaultCookies) - } - } - } - void checkIslRttRules(SwitchId switchId, Boolean rulesExist) { def countOfRules = rulesExist ? (northbound.getLinks(switchId, null, null, null).size() + 2) : 0 - assert northbound.getSwitchRules(switchId).flowEntries.findAll { - (it.cookie in [Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE, Cookie.SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || - (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) - }.size() == countOfRules + assert switchRulesFactory.get(switchId).getServer42ISLRules().size() == countOfRules } void checkIslRttStats(Isl isl, Date checkpointTime, Boolean statExist) { diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy index f3773c22c4..ee6878a69f 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy @@ -1,6 +1,5 @@ package org.openkilda.functionaltests.spec.switches -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs import static org.assertj.core.api.Assertions.assertThat import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.HARDWARE @@ -15,13 +14,10 @@ import static org.openkilda.model.cookie.Cookie.SERVER_42_ISL_RTT_TURNING_COOKIE import static org.openkilda.testing.Constants.RULES_DELETION_TIME import static org.openkilda.testing.Constants.RULES_INSTALLATION_TIME import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMode.RW -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.messaging.Message -import org.openkilda.messaging.command.CommandData -import org.openkilda.messaging.command.CommandMessage +import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.messaging.command.switches.DeleteRulesAction import org.openkilda.messaging.command.switches.InstallRulesAction import org.openkilda.messaging.model.SwitchPropertiesDto.RttState @@ -30,10 +26,15 @@ import org.openkilda.model.cookie.Cookie import org.openkilda.model.cookie.CookieBase.CookieType import org.openkilda.testing.model.topology.TopologyDefinition.Switch -import spock.lang.Unroll +import org.springframework.beans.factory.annotation.Autowired +import spock.lang.Shared class DefaultRulesSpec extends HealthCheckSpecification { + @Autowired + @Shared + SwitchRulesFactory switchRulesFactory + def setupSpec() { deleteAnyFlowsLeftoversIssue5480() } @@ -41,7 +42,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { @Tags([TOPOLOGY_DEPENDENT, SMOKE, SMOKE_SWITCHES]) def "Default rules are installed on switches #sw.hwSwString"() { expect: "Default rules are installed on the switch" - def cookies = northbound.getSwitchRules(sw.dpId).flowEntries*.cookie + def cookies = switchRulesFactory.get(sw.dpId).getRules().cookie cookies.sort() == sw.defaultCookies.sort() where: @@ -53,7 +54,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { given: "A switch with no rules installed and not connected to the controller" def sw = topology.activeSwitches.first() switchHelper.deleteSwitchRules(sw.dpId, DeleteRulesAction.DROP_ALL) - wait(RULES_DELETION_TIME) { assert northbound.getSwitchRules(sw.dpId).flowEntries.isEmpty() } + wait(RULES_DELETION_TIME) { assert switchRulesFactory.get(sw.dpId).getRules().isEmpty() } def blockData = switchHelper.knockoutSwitch(sw, RW) when: "Connect the switch to the controller" @@ -61,7 +62,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { then: "Default rules are installed on the switch" wait(RULES_INSTALLATION_TIME) { - assert northbound.getSwitchRules(sw.dpId).flowEntries*.cookie.sort() == sw.defaultCookies.sort() + assert switchRulesFactory.get(sw.dpId).getRules().cookie.sort() == sw.defaultCookies.sort() } } @@ -69,24 +70,23 @@ class DefaultRulesSpec extends HealthCheckSpecification { def "Able to install default rule on #sw.hwSwString [install-action=#data.installRulesAction]"( Map data, Switch sw) { given: "A switch without any rules" - def defaultRules = northbound.getSwitchRules(sw.dpId).flowEntries + def defaultRules = switchRulesFactory.get(sw.dpId).getRules() assertThat(defaultRules*.cookie.sort()).containsExactlyInAnyOrder(*sw.defaultCookies.sort()) switchHelper.deleteSwitchRules(sw.dpId, DeleteRulesAction.DROP_ALL) - wait(RULES_DELETION_TIME) { assert northbound.getSwitchRules(sw.dpId).flowEntries.empty } + wait(RULES_DELETION_TIME) { assert switchRulesFactory.get(sw.dpId).getRules().empty } when: "Install rules on the switch" def installedRules = northbound.installSwitchRules(sw.dpId, data.installRulesAction) then: "The corresponding rules are really installed" - //https://github.com/telstra/open-kilda/issues/3625 -// installedRules.size() == 1 + installedRules.size() == 1 def expectedRules = defaultRules.findAll { it.cookie == data.cookie } wait(RULES_INSTALLATION_TIME) { - compareRules(northbound.getSwitchRules(sw.dpId).flowEntries - .findAll { new Cookie(it.cookie).getType() != CookieType.MULTI_TABLE_ISL_VLAN_EGRESS_RULES }, - expectedRules) + def actualRules = switchRulesFactory.get(sw.dpId).getRules() + .findAll { new Cookie(it.cookie).getType() != CookieType.MULTI_TABLE_ISL_VLAN_EGRESS_RULES } + assertThat(actualRules).containsExactlyInAnyOrder(*expectedRules) } where: @@ -135,11 +135,11 @@ class DefaultRulesSpec extends HealthCheckSpecification { def "Able to install default rule on switch: #sw.hwSwString [install-action=#data.installRulesAction]"( Map data, Switch sw) { given: "A switch without rules" - def defaultRules = northbound.getSwitchRules(sw.dpId).flowEntries + def defaultRules = switchRulesFactory.get(sw.dpId).getRules() assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() switchHelper.deleteSwitchRules(sw.dpId, DeleteRulesAction.DROP_ALL) - wait(RULES_DELETION_TIME) { assert northbound.getSwitchRules(sw.dpId).flowEntries.empty } + wait(RULES_DELETION_TIME) { assert switchRulesFactory.get(sw.dpId).getRules().empty } when: "Install rules on the switch" def installedRules = northbound.installSwitchRules(sw.dpId, data.installRulesAction) @@ -149,7 +149,9 @@ class DefaultRulesSpec extends HealthCheckSpecification { def expectedRules = defaultRules.findAll { it.cookie == data.cookie } wait(RULES_INSTALLATION_TIME) { - compareRules(northbound.getSwitchRules(sw.dpId).flowEntries, expectedRules) + def actualRules = switchRulesFactory.get(sw.dpId).getRules() + assert actualRules.cookie == installedRules + assertThat(actualRules).containsExactlyInAnyOrder(*expectedRules) } where: @@ -185,11 +187,11 @@ class DefaultRulesSpec extends HealthCheckSpecification { @Tags([TOPOLOGY_DEPENDENT, SMOKE, SMOKE_SWITCHES]) def "Able to install default rules on #sw.hwSwString [install-action=INSTALL_DEFAULTS]"() { given: "A switch without any rules" - def defaultRules = northbound.getSwitchRules(sw.dpId).flowEntries + def defaultRules = switchRulesFactory.get(sw.dpId).getRules() assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() switchHelper.deleteSwitchRules(sw.dpId, DeleteRulesAction.DROP_ALL) - wait(RULES_DELETION_TIME) { assert northbound.getSwitchRules(sw.dpId).flowEntries.empty } + wait(RULES_DELETION_TIME) { assert switchRulesFactory.get(sw.dpId).getRules().empty } when: "Install rules on the switch" def installedRules = northbound.installSwitchRules(sw.dpId, InstallRulesAction.INSTALL_DEFAULTS) @@ -197,7 +199,8 @@ class DefaultRulesSpec extends HealthCheckSpecification { then: "The corresponding rules are really installed" installedRules.size() == defaultRules.size() wait(RULES_INSTALLATION_TIME) { - compareRules(northbound.getSwitchRules(sw.dpId).flowEntries, defaultRules) + def actualRules = switchRulesFactory.get(sw.dpId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultRules) } where: @@ -208,16 +211,15 @@ class DefaultRulesSpec extends HealthCheckSpecification { def "Able to delete default rule from #sw.hwSwString[delete-action=#data.deleteRulesAction]"( Map data, Switch sw) { when: "Delete rules from the switch" - def defaultRules = northbound.getSwitchRules(sw.dpId).flowEntries + def defaultRules = switchRulesFactory.get(sw.dpId).getRules() assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() def deletedRules = switchHelper.deleteSwitchRules(sw.dpId, data.deleteRulesAction) then: "The corresponding rules are really deleted" deletedRules.size() == 1 wait(RULES_DELETION_TIME) { - def actualRules = northbound.getSwitchRules(sw.dpId).flowEntries - assert actualRules.findAll { it.cookie in deletedRules }.empty - compareRules(actualRules, defaultRules.findAll { it.cookie != data.cookie }) + def actualRules = switchRulesFactory.get(sw.dpId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultRules.findAll { it.cookie != data.cookie }) } and: "Switch and rules validation shows that corresponding default rule is missing" @@ -267,7 +269,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { when: "Delete rule from the switch" def defaultRules wait(RULES_INSTALLATION_TIME) { - defaultRules = northbound.getSwitchRules(sw.dpId).flowEntries + defaultRules = switchRulesFactory.get(sw.dpId).getRules() assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() } def deletedRules = switchHelper.deleteSwitchRules(sw.dpId, data.deleteRulesAction) @@ -275,9 +277,8 @@ class DefaultRulesSpec extends HealthCheckSpecification { then: "The corresponding rule is really deleted" deletedRules.size() == 1 wait(RULES_DELETION_TIME) { - def actualRules = northbound.getSwitchRules(sw.dpId).flowEntries - assert actualRules.findAll { it.cookie in deletedRules }.empty - compareRules(actualRules, defaultRules.findAll { it.cookie != data.cookie }) + def actualRules = switchRulesFactory.get(sw.dpId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultRules.findAll { it.cookie != data.cookie }) } and: "Switch and rules validation shows that corresponding default rule is missing" @@ -341,7 +342,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { and: "The corresponding rule is really deleted" wait(RULES_DELETION_TIME) { - assert northbound.getSwitchRules(sw.dpId).flowEntries.findAll { it.cookie == SERVER_42_FLOW_RTT_TURNING_COOKIE }.empty + assert switchRulesFactory.get(sw.dpId).getRules().findAll { it.cookie == SERVER_42_FLOW_RTT_TURNING_COOKIE }.empty } and: "Switch and rules validation shows that corresponding rule is missing" @@ -366,7 +367,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { and: "The corresponding rule is really installed" wait(RULES_INSTALLATION_TIME) { - assert !northbound.getSwitchRules(sw.dpId).flowEntries.findAll { it.cookie == SERVER_42_FLOW_RTT_TURNING_COOKIE }.empty + assert !switchRulesFactory.get(sw.dpId).getRules().findAll { it.cookie == SERVER_42_FLOW_RTT_TURNING_COOKIE }.empty } } @@ -385,7 +386,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { it.server42IslRtt = RttState.ENABLED.toString() })) wait(RULES_INSTALLATION_TIME) { - assert northbound.getSwitchRules(sw.dpId).flowEntries.findAll { + assert switchRulesFactory.get(sw.dpId).getRules().findAll { (it.cookie in [SERVER_42_ISL_RTT_TURNING_COOKIE, SERVER_42_ISL_RTT_OUTPUT_COOKIE]) || (new Cookie(it.cookie).getType() in [CookieType.SERVER_42_ISL_RTT_INPUT]) }.size() == northbound.getLinks(sw.dpId, null, null, null).size() + 2 @@ -400,7 +401,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { and: "The corresponding rule is really deleted" wait(RULES_DELETION_TIME) { - assert northbound.getSwitchRules(sw.dpId).flowEntries.findAll { it.cookie == SERVER_42_ISL_RTT_TURNING_COOKIE }.empty + assert switchRulesFactory.get(sw.dpId).getRules().findAll { it.cookie == SERVER_42_ISL_RTT_TURNING_COOKIE }.empty } and: "Switch and rules validation shows that corresponding rule is missing" @@ -425,19 +426,7 @@ class DefaultRulesSpec extends HealthCheckSpecification { and: "The corresponding rule is really installed" wait(RULES_INSTALLATION_TIME) { - assert !northbound.getSwitchRules(sw.dpId).flowEntries.findAll { it.cookie == SERVER_42_ISL_RTT_TURNING_COOKIE }.empty + assert !switchRulesFactory.get(sw.dpId).getRules().findAll { it.cookie == SERVER_42_ISL_RTT_TURNING_COOKIE }.empty } } - - void compareRules(actualRules, expectedRules) { - assert expect(actualRules.sort { it.cookie }, sameBeanAs(expectedRules.sort { it.cookie }) - .ignoring("byteCount") - .ignoring("packetCount") - .ignoring("durationNanoSeconds") - .ignoring("durationSeconds")) - } - - private static Message buildMessage(final CommandData data) { - return new CommandMessage(data, System.currentTimeMillis(), UUID.randomUUID().toString(), null); - } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy index d24cf6c6c4..574b021eaf 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy @@ -1,6 +1,6 @@ package org.openkilda.functionaltests.spec.switches -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs +import static org.assertj.core.api.Assertions.assertThat import static groovyx.gpars.GParsPool.withPool import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.ISL_RECOVER_ON_FAIL @@ -15,7 +15,6 @@ import static org.openkilda.testing.Constants.RULES_DELETION_TIME import static org.openkilda.testing.Constants.RULES_INSTALLATION_TIME import static org.openkilda.testing.Constants.WAIT_OFFSET import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMode.RW -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.SwitchNotFoundExpectedError @@ -25,10 +24,10 @@ import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.factory.FlowFactory import org.openkilda.functionaltests.helpers.model.FlowEncapsulationType import org.openkilda.functionaltests.helpers.model.FlowExtended +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.messaging.command.switches.DeleteRulesAction -import org.openkilda.messaging.info.event.PathNode import org.openkilda.messaging.info.rule.FlowEntry import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.SwitchId @@ -82,8 +81,8 @@ class FlowRulesSpec extends HealthCheckSpecification { def setupSpec() { (srcSwitch, dstSwitch) = topology.getActiveSwitches()[0..1] s42IsEnabledOnSrcSw = switchHelper.getCachedSwProps(srcSwitch.dpId).server42FlowRtt - srcSwDefaultRules = northbound.getSwitchRules(srcSwitch.dpId).flowEntries - dstSwDefaultRules = northbound.getSwitchRules(dstSwitch.dpId).flowEntries + srcSwDefaultRules = switchRulesFactory.get(srcSwitch.dpId).getRules() + dstSwDefaultRules = switchRulesFactory.get(dstSwitch.dpId).getRules() } @Tags([VIRTUAL, SMOKE, SWITCH_RECOVER_ON_FAIL]) @@ -93,7 +92,7 @@ class FlowRulesSpec extends HealthCheckSpecification { def defaultPlusFlowRules = [] Wrappers.wait(RULES_INSTALLATION_TIME) { - defaultPlusFlowRules = northbound.getSwitchRules(srcSwitch.dpId).flowEntries + defaultPlusFlowRules = switchRulesFactory.get(srcSwitch.dpId).getRules() def multiTableFlowRules = multiTableFlowRulesCount + sharedRulesCount assert defaultPlusFlowRules.size() == srcSwDefaultRules.size() + flowRulesCount + multiTableFlowRules } @@ -104,7 +103,8 @@ class FlowRulesSpec extends HealthCheckSpecification { switchHelper.reviveSwitch(srcSwitch, blockData) then: "Previously installed rules are not deleted from the switch" - compareRules(northbound.getSwitchRules(srcSwitch.dpId).flowEntries, defaultPlusFlowRules) + def actualRules = switchRulesFactory.get(srcSwitch.dpId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultPlusFlowRules) } @Tags([SMOKE]) @@ -114,13 +114,14 @@ class FlowRulesSpec extends HealthCheckSpecification { flowFactory.getRandom(srcSwitch, dstSwitch) when: "Delete rules from the switch" - def expectedRules = data.getExpectedRules(srcSwitch, srcSwDefaultRules) + List expectedRules = data.getExpectedRules(srcSwitch, srcSwDefaultRules) def deletedRules = switchHelper.deleteSwitchRules(srcSwitch.dpId, data.deleteRulesAction) then: "The corresponding rules are really deleted" deletedRules.size() == data.rulesDeleted Wrappers.wait(RULES_DELETION_TIME) { - compareRules(northbound.getSwitchRules(srcSwitch.dpId).flowEntries, expectedRules) + def actualRules = switchRulesFactory.get(srcSwitch.dpId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*expectedRules) } where: @@ -138,7 +139,7 @@ class FlowRulesSpec extends HealthCheckSpecification { sharedRulesCount + (s42IsEnabledOnSrcSw ? s42FlowRttInput + s42QinqOuterVlanCount + s42FlowRttIngressForwardCount : 0), getExpectedRules : { sw, defaultRules -> - def noDefaultSwRules = northbound.getSwitchRules(srcSwitch.dpId).flowEntries - defaultRules + List noDefaultSwRules = switchRulesFactory.get(srcSwitch.dpId).getRules() - defaultRules defaultRules + noDefaultSwRules.findAll { Cookie.isIngressRulePassThrough(it.cookie) } + (s42IsEnabledOnSrcSw ? noDefaultSwRules.findAll { new Cookie(it.cookie).getType() == CookieType.SERVER_42_FLOW_RTT_INPUT } : []) @@ -149,7 +150,7 @@ class FlowRulesSpec extends HealthCheckSpecification { rulesDeleted : flowRulesCount + sharedRulesCount + (s42IsEnabledOnSrcSw ? s42QinqOuterVlanCount + s42FlowRttIngressForwardCount : 0), getExpectedRules : { sw, defaultRules -> - def noDefaultSwRules = northbound.getSwitchRules(srcSwitch.dpId).flowEntries - defaultRules + List noDefaultSwRules = switchRulesFactory.get(srcSwitch.dpId).getRules() - defaultRules defaultRules + noDefaultSwRules.findAll { Cookie.isIngressRulePassThrough(it.cookie) } + (s42IsEnabledOnSrcSw ? noDefaultSwRules.findAll { new Cookie(it.cookie).getType() == CookieType.SERVER_42_FLOW_RTT_INPUT } : []) @@ -160,7 +161,7 @@ class FlowRulesSpec extends HealthCheckSpecification { rulesDeleted : srcSwDefaultRules.size() + multiTableFlowRulesCount + (s42IsEnabledOnSrcSw ? s42FlowRttInput : 0), getExpectedRules : { sw, defaultRules -> defaultRules + getFlowRules(sw) + - northbound.getSwitchRules(srcSwitch.dpId).flowEntries.findAll { + switchRulesFactory.get(srcSwitch.dpId).getRules().findAll { Cookie.isIngressRulePassThrough(it.cookie) } } @@ -170,7 +171,7 @@ class FlowRulesSpec extends HealthCheckSpecification { rulesDeleted : srcSwDefaultRules.size() + multiTableFlowRulesCount + (s42IsEnabledOnSrcSw ? s42FlowRttInput : 0), getExpectedRules : { sw, defaultRules -> getFlowRules(sw) - - (s42IsEnabledOnSrcSw ? northbound.getSwitchRules(srcSwitch.dpId).flowEntries.findAll { + (s42IsEnabledOnSrcSw ? switchRulesFactory.get(srcSwitch.dpId).getRules().findAll { new Cookie(it.cookie).getType() == CookieType.SERVER_42_FLOW_RTT_INPUT } : []) } ], @@ -179,7 +180,7 @@ class FlowRulesSpec extends HealthCheckSpecification { rulesDeleted : srcSwDefaultRules.size() + multiTableFlowRulesCount + (s42IsEnabledOnSrcSw ? s42FlowRttInput : 0), getExpectedRules : { sw, defaultRules -> defaultRules + getFlowRules(sw) + - northbound.getSwitchRules(srcSwitch.dpId).flowEntries.findAll { + switchRulesFactory.get(srcSwitch.dpId).getRules().findAll { Cookie.isIngressRulePassThrough(it.cookie) } } @@ -195,7 +196,7 @@ class FlowRulesSpec extends HealthCheckSpecification { when: "Delete switch rules by #data.identifier" //exclude the "SERVER_42_INPUT" rule, this rule has less priority than usual flow rule def ruleToDelete = getFlowRules(data.switch).find { !new Cookie(it.cookie).serviceFlag } - def expectedDeletedRules = northbound.getSwitchRules(data.switch.dpId).flowEntries + def expectedDeletedRules = switchRulesFactory.get(data.switch.dpId).getRules() .findAll { it."$data.identifier" == ruleToDelete."$data.identifier" && !new Cookie(it.cookie).serviceFlag } def deletedRules = switchHelper.deleteSwitchRules(data.switch.dpId, ruleToDelete."$data.identifier") @@ -203,7 +204,7 @@ class FlowRulesSpec extends HealthCheckSpecification { then: "The requested rules are really deleted" deletedRules.size() == expectedDeletedRules.size() Wrappers.wait(RULES_DELETION_TIME) { - def actualRules = northbound.getSwitchRules(data.switch.dpId).flowEntries + def actualRules = switchRulesFactory.get(data.switch.dpId).getRules() assert actualRules.findAll { it.cookie in expectedDeletedRules*.cookie }.empty } @@ -223,7 +224,7 @@ class FlowRulesSpec extends HealthCheckSpecification { assumeTrue(data.description != "priority", "https://github.com/telstra/open-kilda/issues/1701") flowFactory.getRandom(srcSwitch, dstSwitch) - def ingressRule = (northbound.getSwitchRules(srcSwitch.dpId).flowEntries - data.defaultRules).find { + def ingressRule = (switchRulesFactory.get(srcSwitch.dpId).getRules() - data.defaultRules).find { new Cookie(it.cookie).serviceFlag } if (ingressRule) { @@ -235,7 +236,7 @@ class FlowRulesSpec extends HealthCheckSpecification { then: "All rules are kept intact" deletedRules.size() == 0 - northbound.getSwitchRules(data.switch.dpId).flowEntries.size() == data.defaultRules.size() + flowRulesCount + switchRulesFactory.get(data.switch.dpId).getRules().size() == data.defaultRules.size() + flowRulesCount where: data << [[description : "cookie", @@ -256,7 +257,7 @@ class FlowRulesSpec extends HealthCheckSpecification { def "Able to delete switch rules by #data.description"() { given: "A switch with some flow rules installed" flow.create() - def cookiesBefore = northbound.getSwitchRules(data.switch.dpId).flowEntries*.cookie.sort() + def cookiesBefore = switchRulesFactory.get(data.switch.dpId).getRules().cookie.sort() def s42IsEnabled = switchHelper.getCachedSwProps(data.switch.dpId).server42FlowRtt when: "Delete switch rules by #data.description" @@ -270,7 +271,7 @@ class FlowRulesSpec extends HealthCheckSpecification { } deletedRules.size() == amountOfDeletedRules Wrappers.wait(RULES_DELETION_TIME) { - def actualRules = northbound.getSwitchRules(data.switch.dpId).flowEntries + def actualRules = switchRulesFactory.get(data.switch.dpId).getRules() assert actualRules*.cookie.sort() == cookiesBefore - deletedRules assert filterRules(actualRules, data.inPort, data.inVlan, data.outPort).empty } @@ -315,7 +316,7 @@ class FlowRulesSpec extends HealthCheckSpecification { def "Attempt to delete switch rules by supplying non-existing #data.description keeps all rules intact"() { given: "A switch with some flow rules installed" flowFactory.getRandom(srcSwitch, dstSwitch) - def originalRules = northbound.getSwitchRules(data.switch.dpId).flowEntries*.cookie.sort() + def originalRules = switchRulesFactory.get(data.switch.dpId).getRules().cookie.sort() when: "Delete switch rules by non-existing #data.description" def deletedRules = switchHelper.deleteSwitchRules(data.switch.dpId, data.inPort, data.inVlan, @@ -323,7 +324,7 @@ class FlowRulesSpec extends HealthCheckSpecification { then: "All rules are kept intact" deletedRules.size() == 0 - northbound.getSwitchRules(data.switch.dpId).flowEntries*.cookie.sort() == originalRules + switchRulesFactory.get(data.switch.dpId).getRules().cookie.sort() == originalRules where: data << [[description : "inPort", @@ -378,7 +379,7 @@ class FlowRulesSpec extends HealthCheckSpecification { and: "Remove flow rules so that they become 'missing'" def involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedSwitches() def defaultPlusFlowRulesMap = involvedSwitches.collectEntries { switchId -> - [switchId, northbound.getSwitchRules(switchId).flowEntries] + [switchId, switchRulesFactory.get(switchId).getRules()] } def amountOfRulesMap = involvedSwitches.collectEntries { switchId -> @@ -412,7 +413,8 @@ class FlowRulesSpec extends HealthCheckSpecification { involvedSwitches.each { switchId -> assert synchronizedRulesMap[switchId].installedRules.size() == amountOfRulesMap[switchId] Wrappers.wait(RULES_INSTALLATION_TIME) { - compareRules(northbound.getSwitchRules(switchId).flowEntries, defaultPlusFlowRulesMap[switchId]) + def actualRules = switchRulesFactory.get(switchId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultPlusFlowRulesMap[switchId]) } } @@ -457,8 +459,8 @@ class FlowRulesSpec extends HealthCheckSpecification { def flowPathInfo = flow.retrieveAllEntityPaths() - HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() - .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> + HashMap> flowInvolvedSwitchesWithRules = flowPathInfo.getInvolvedSwitches() + .collectEntries{ [(it): switchRulesFactory.get(it).getRules()] } as HashMap> flow.verifyRulesForProtectedFlowOnSwitches(flowInvolvedSwitchesWithRules) def mainFlowPath = flowPathInfo.getPathNodes(Direction.FORWARD, false) @@ -468,7 +470,7 @@ class FlowRulesSpec extends HealthCheckSpecification { !commonNodeIds.contains(it.switchId) })*.switchId.unique() def rulesOnSwitchesBefore = (commonNodeIds + uniqueNodes).collectEntries { - [it, northbound.getSwitchRules(it).flowEntries.sort { it.cookie }] + [it, switchRulesFactory.get(it).getRules().sort { it.cookie }] } and: "Delete flow rules(for main and protected paths) on involved switches for creating missing rules" @@ -513,7 +515,8 @@ class FlowRulesSpec extends HealthCheckSpecification { and: "Synced rules are exactly the same as before delete (ignoring irrelevant fields)" rulesOnSwitchesBefore.each { - compareRules(northbound.getSwitchRules(it.key).flowEntries, it.value) + def actualRules = switchRulesFactory.get(it.key).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*it.value) } } @@ -667,7 +670,7 @@ class FlowRulesSpec extends HealthCheckSpecification { def involvedSwitches = flow.retrieveAllEntityPaths().getInvolvedSwitches() def transitSwitchIds = involvedSwitches[1..-2] def defaultPlusFlowRulesMap = involvedSwitches.collectEntries { switchId -> - [switchId, northbound.getSwitchRules(switchId).flowEntries] + [switchId, switchRulesFactory.get(switchId).getRules()] } def rulesCountMap = involvedSwitches.collectEntries { switchId -> @@ -701,14 +704,15 @@ class FlowRulesSpec extends HealthCheckSpecification { involvedSwitches.each { switchId -> assert synchronizedRulesMap[switchId].installedRules.size() == rulesCountMap[switchId] Wrappers.wait(RULES_INSTALLATION_TIME) { - compareRules(northbound.getSwitchRules(switchId).flowEntries, defaultPlusFlowRulesMap[switchId]) + def actualRules = switchRulesFactory.get(switchId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*defaultPlusFlowRulesMap[switchId]) } } and: "Rules are synced correctly" // ingressRule should contain "pushVxlan" // egressRule should contain "tunnel-id" - with(northbound.getSwitchRules(switchPair.src.dpId).flowEntries) { rules -> + with(switchRulesFactory.get(switchPair.src.dpId).getRules()) { rules -> assert rules.find { it.cookie == flowInfoFromDb.forwardPath.cookie.value }.instructions.applyActions.pushVxlan @@ -717,7 +721,7 @@ class FlowRulesSpec extends HealthCheckSpecification { }.match.tunnelId } - with(northbound.getSwitchRules(switchPair.dst.dpId).flowEntries) { rules -> + with(switchRulesFactory.get(switchPair.dst.dpId).getRules()) { rules -> assert rules.find { it.cookie == flowInfoFromDb.forwardPath.cookie.value }.match.tunnelId @@ -727,7 +731,7 @@ class FlowRulesSpec extends HealthCheckSpecification { } transitSwitchIds.each { swId -> - with(northbound.getSwitchRules(swId).flowEntries) { rules -> + with(switchRulesFactory.get(swId).getRules()) { rules -> assert rules.find { it.cookie == flowInfoFromDb.forwardPath.cookie.value }.match.tunnelId @@ -747,16 +751,7 @@ class FlowRulesSpec extends HealthCheckSpecification { } } - void compareRules(actualRules, expectedRules) { - assert expect(actualRules.sort { it.cookie }, sameBeanAs(expectedRules.sort { it.cookie }) - .ignoring("byteCount") - .ignoring("packetCount") - .ignoring("durationNanoSeconds") - .ignoring("durationSeconds")) - } - - - List filterRules(List rules, inPort, inVlan, outPort) { + List filterRules(List rules, inPort, inVlan, outPort) { if (inPort) { rules = rules.findAll { it.match.inPort == inPort.toString() } } @@ -769,7 +764,7 @@ class FlowRulesSpec extends HealthCheckSpecification { return rules } - List getFlowRules(Switch sw) { + List getFlowRules(Switch sw) { switchRulesFactory.get(sw.dpId).getRules().findAll { !(it.cookie in sw.defaultCookies) }.sort() } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy index a6eb7ce70d..a3b655cee8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/MetersSpec.groovy @@ -1,6 +1,6 @@ package org.openkilda.functionaltests.spec.switches -import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs +import static org.assertj.core.api.Assertions.assertThat import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.HARDWARE import static org.openkilda.functionaltests.extension.tags.Tag.SMOKE @@ -19,7 +19,6 @@ import static org.openkilda.model.cookie.Cookie.LLDP_POST_INGRESS_COOKIE import static org.openkilda.model.cookie.Cookie.LLDP_POST_INGRESS_ONE_SWITCH_COOKIE import static org.openkilda.model.cookie.Cookie.LLDP_POST_INGRESS_VXLAN_COOKIE import static org.openkilda.testing.Constants.WAIT_OFFSET -import static spock.util.matcher.HamcrestSupport.expect import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.MeterExpectedError @@ -27,10 +26,10 @@ import org.openkilda.functionaltests.extension.tags.IterationTag import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.factory.FlowFactory +import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.messaging.info.meter.MeterEntry import org.openkilda.messaging.info.rule.FlowEntry -import org.openkilda.messaging.info.rule.SwitchFlowEntries import org.openkilda.model.SwitchId import org.openkilda.model.cookie.Cookie import org.openkilda.model.cookie.CookieBase.CookieType @@ -521,8 +520,8 @@ meters in flow rules at all (#srcSwitch - #dstSwitch flow)"() { flow.updateFlowBandwidthInDB(newBandwidth) //at this point existing meters do not correspond with the flow //now save some original data for further comparison before resetting meters - Map originalRules = [src.dpId, dst.dpId].collectEntries { - [(it): northbound.getSwitchRules(it)] + Map> originalRules = [src.dpId, dst.dpId].collectEntries { + [(it): switchRulesFactory.get(it).getRules()] } Map> originalMeters = [src.dpId, dst.dpId].collectEntries { [(it): northbound.getAllMeters(it).meterEntries] @@ -558,19 +557,14 @@ meters in flow rules at all (#srcSwitch - #dstSwitch flow)"() { and: "Default meters are unchanged" [src.dpId, dst.dpId].each { SwitchId swId -> - assert expect(northbound.getAllMeters(swId).meterEntries.findAll(defaultMeters).sort(), - sameBeanAs(originalMeters[swId].findAll(defaultMeters).sort()) - .ignoring("timestamp")) + def actualDefaultMeters = northbound.getAllMeters(swId).meterEntries.findAll(defaultMeters) + assertThat(actualDefaultMeters).containsExactlyInAnyOrder(*originalMeters[swId].findAll(defaultMeters)) } and: "Switch rules are unchanged" [src.dpId, dst.dpId].each { SwitchId swId -> - assert expect(northbound.getSwitchRules(swId), sameBeanAs(originalRules[swId]) - .ignoring("timestamp") - .ignoring("flowEntries.durationNanoSeconds") - .ignoring("flowEntries.durationSeconds") - .ignoring("flowEntries.byteCount") - .ignoring("flowEntries.packetCount")) + def actualRules = switchRulesFactory.get(swId).getRules() + assertThat(actualRules).containsExactlyInAnyOrder(*originalRules[swId]) } where: From bc04e304bfc2a456b5999eac7a7c34eeb372f3dd Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Tue, 5 Nov 2024 17:14:51 +0100 Subject: [PATCH 08/21] [TEST]: Improvement: Ha-Flow: Reroute to better path --- .../functionaltests/helpers/IslHelper.groovy | 1 + .../model/cleanup/CleanupManager.groovy | 6 +-- .../HaFlowIntentionalRerouteSpec.groovy | 50 ++++++++++++++----- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/IslHelper.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/IslHelper.groovy index 86924217e7..4d9d2997f5 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/IslHelper.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/IslHelper.groovy @@ -159,6 +159,7 @@ class IslHelper { */ void updateIslsCost(List isls, Integer newCost) { cleanupManager.addAction(DELETE_ISLS_PROPERTIES,{ northbound.deleteLinkProps(northbound.getLinkProps(topology.isls)) }) + cleanupManager.addAction(RESET_ISLS_COST,{ database.resetCosts(topology.isls) }) northbound.updateLinkProps(isls.collectMany { isl -> [islUtils.toLinkProps(isl, ["cost": (newCost).toString()])] }) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/model/cleanup/CleanupManager.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/model/cleanup/CleanupManager.groovy index 86fd78fbba..bbf98b136c 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/model/cleanup/CleanupManager.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/model/cleanup/CleanupManager.groovy @@ -105,12 +105,12 @@ class CleanupManager { exceptions += runActionsAsynchronously(actions[PORT_UP]) exceptions += runActionsAsynchronously(actions[RESTORE_ISL]) exceptions += runActionsAsynchronously(actions[CLEAN_LINK_DELAY]) - if (actions[RESET_ISLS_COST]) { - exceptions += runActionsSynchronously([actions[RESET_ISLS_COST].first()]) - } if (actions[DELETE_ISLS_PROPERTIES]) { exceptions += runActionsSynchronously([actions[DELETE_ISLS_PROPERTIES].first()]) } + if (actions[RESET_ISLS_COST]) { + exceptions += runActionsSynchronously([actions[RESET_ISLS_COST].first()]) + } exceptions += runActionsSynchronously(actions[DELETE_HAFLOW]) exceptions += runActionsAsynchronously(actions[SYNCHRONIZE_SWITCH]) exceptions += runActionsSynchronously(actions[RESET_ISL_PARAMETERS]) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy index 48254eeca8..5830c81c45 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW import static org.openkilda.functionaltests.extension.tags.Tag.ISL_PROPS_DB_RESET import static org.openkilda.functionaltests.helpers.model.FlowEncapsulationType.TRANSIT_VLAN +import static org.openkilda.testing.Constants.DEFAULT_COST import static org.openkilda.testing.Constants.WAIT_OFFSET import org.openkilda.functionaltests.HealthCheckSpecification @@ -14,6 +15,7 @@ import org.openkilda.functionaltests.helpers.IslHelper import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath import org.openkilda.functionaltests.helpers.model.SwitchTriplet +import org.openkilda.messaging.info.event.IslInfoData import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.northbound.dto.v2.flows.FlowPathV2.PathNodeV2 import org.openkilda.northbound.dto.v2.haflows.HaFlowRerouteResult @@ -72,7 +74,10 @@ class HaFlowIntentionalRerouteSpec extends HealthCheckSpecification { @Tags(ISL_PROPS_DB_RESET) def "Able to reroute to a better path if it has enough bandwidth"() { given: "An HA-Flow with alternate paths available" - def swT = switchTriplets.all().findSwitchTripletWithAlternativePaths() + def swT = switchTriplets.all().withAllDifferentEndpoints().withSharedEpEp1Ep2InChain().switchTriplets.shuffled().find { + // shared-ep1 or shared-ep2 should have 2 direct paths(one is used during flow creation, another will be changed to become preferable) + it.pathsEp1.findAll { it.size() == 2 }.size() == 2 || it.pathsEp2.findAll { it.size() == 2 }.size() == 2 + } assumeTrue(swT != null, "No suiting switches found") def haFlow = haFlowFactory.getBuilder(swT).withEncapsulationType(TRANSIT_VLAN) .withBandwidth(10000).build().create() @@ -89,17 +94,13 @@ class HaFlowIntentionalRerouteSpec extends HealthCheckSpecification { when: "Make one of the alternative paths to be the most preferable among all others" def availablePathsIslsEp1 = swT.retrieveAvailablePathsEp1().collect { it.getInvolvedIsls() } def availablePathsIslsEp2 = swT.retrieveAvailablePathsEp2().collect { it.getInvolvedIsls() } - def preferableAltPathForSubFlow1 = availablePathsIslsEp1.find { it != initialIslsSubFlow1 } - def preferableAltPathForSubFlow2 = availablePathsIslsEp2.find { it != initialIslsSubFlow2 } - withPool { - availablePathsIslsEp1.findAll { it != preferableAltPathForSubFlow1 }.eachParallel { - islHelper.makePathIslsMorePreferable(preferableAltPathForSubFlow1, it) - } - availablePathsIslsEp2.findAll { it != preferableAltPathForSubFlow2 }.eachParallel { - islHelper.makePathIslsMorePreferable(preferableAltPathForSubFlow2, it) - } - } + List islToUpdate = (availablePathsIslsEp1 + availablePathsIslsEp2) + .findAll { !(it.intersect(initialIslsSubFlow1) || it.intersect(initialIslsSubFlow2)) }.collect { it.last() }.unique() + islHelper.updateIslsCost(islToUpdate, DEFAULT_COST - 5) + + def preferableAltPathForSubFlow1 = retrievePreferablePathBasedOnCost(availablePathsIslsEp1) + def preferableAltPathForSubFlow2 = retrievePreferablePathBasedOnCost(availablePathsIslsEp2) and: "Make the future path to have exact bandwidth to handle the HA-Flow" def thinIsl = setBandwidthForAlternativesPaths(initialFlowIsls, @@ -107,10 +108,10 @@ class HaFlowIntentionalRerouteSpec extends HealthCheckSpecification { and: "Init a reroute of the HA-Flow" def rerouteResponse = haFlow.reroute() - haFlow.waitForBeingInState(FlowState.UP) then: "The HA-Flow is successfully rerouted and goes through the preferable path" rerouteResponse.rerouted + haFlow.waitForBeingInState(FlowState.UP) def haFlowPathAfterReroute = haFlow.retrievedAllEntityPaths() def actualFlowIslsAfterReroute = haFlowPathAfterReroute.getInvolvedIsls() @@ -218,4 +219,29 @@ class HaFlowIntentionalRerouteSpec extends HealthCheckSpecification { rerouteResult.subFlowPaths.find { it.flowId == subFlowId}.nodes .collect { PathNodeV2.builder().switchId(it.switchId).portNo(it.portNo).segmentLatency(null).build() } } + + private List retrievePreferablePathBasedOnCost(List> availablePathsIsls) { + def pathsCost = collectPathsCost(availablePathsIsls) + def preferablePath = pathsCost.find { it.value == pathsCost.values().min() }.key + // getting rid of any alternative path with the same price + pathsCost.findAll { it.value == pathsCost.values().min() }.findAll { it.key != preferablePath }.each { + islHelper.updateIslsCost([it.key.last()], it.value + 1) + } + return preferablePath + } + + private Map, Integer> collectPathsCost(List> availablePaths) { + List linkDetails = northbound.getAllLinks() + availablePaths.collectEntries { path -> + def pathCost = 0 + path.each { isl -> + pathCost += linkDetails. + find { + ((it.source.switchId == isl.srcSwitch.dpId && it.source.portNo == isl.srcPort) && + (it.destination.switchId == isl.dstSwitch.dpId && it.destination.portNo == isl.dstPort)) + }.cost + } + [(path): pathCost] + } + } } From 5c5cdc6e960e9f0a734c033a6b90c4cf99e3ce5b Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Mon, 21 Oct 2024 16:37:43 +0200 Subject: [PATCH 09/21] [TEST]: Improvement: Flaky test: Reroute with global timeout --- .../spec/xresilience/RetriesSpec.groovy | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy index 1025ff6e8b..09e79e9313 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/xresilience/RetriesSpec.groovy @@ -359,11 +359,15 @@ class RetriesIsolatedSpec extends HealthCheckSpecification { def swPair = switchPairs.all().nonNeighbouring().switchPairs .find { it.src.dpId.toString().contains("03") && it.dst.dpId.toString().contains("07")} def availablePaths = swPair.retrieveAvailablePaths().collect { it.getInvolvedIsls() } - def preferableIsls = availablePaths.find{ it.size() >= 5 } - availablePaths.findAll { it != preferableIsls }.each { islHelper.makePathIslsMorePreferable(preferableIsls, it) } + + def expectedInitialPath = availablePaths.find { it.size() >= 5 } + availablePaths.findAll { it != expectedInitialPath }.each { islHelper.makePathIslsMorePreferable(expectedInitialPath, it) } def flow = flowFactory.getRandom(swPair) - assert flow.retrieveAllEntityPaths().getInvolvedIsls() == preferableIsls + assert expectedInitialPath == flow.retrieveAllEntityPaths().getInvolvedIsls() + + def flowInvolvedSwitches = islHelper.retrieveInvolvedSwitches(expectedInitialPath) + switchHelper.shapeSwitchesTraffic(flowInvolvedSwitches[1..-1], new TrafficControlData(8000)) when: "Break current path to trigger a reroute" def islToBreak = flow.retrieveAllEntityPaths().getInvolvedIsls().first() @@ -372,26 +376,34 @@ class RetriesIsolatedSpec extends HealthCheckSpecification { northbound.portDown(islToBreak.srcSwitch.dpId, islToBreak.srcPort) and: "Connection to src switch is slow in order to simulate a global timeout on reroute operation" - switchHelper.shapeSwitchesTraffic([swPair.src], new TrafficControlData(9200)) + switchHelper.shapeSwitchesTraffic([swPair.src], new TrafficControlData(8500)) then: "After global timeout expect flow reroute to fail and flow to become DOWN" TimeUnit.SECONDS.sleep(globalTimeout) - int eventsAmount + // 1 reroute event: main ISL break -> GlobalTimeout + // 1 reroute event: delay on the src(new path in the scope of triggered reroute) + int rerouteEventsAmount = 2 wait(globalTimeout + WAIT_OFFSET, 1) { //long wait, may be doing some revert actions after global t/o def history = flow.retrieveFlowHistory() def rerouteEvent = history.getEntriesByType(REROUTE).first() assert rerouteEvent.payload.find { it.action == sprintf('Global timeout reached for reroute operation on flow "%s"', flow.flowId) } assert rerouteEvent.payload.last().action == REROUTE_FAILED.payloadLastAction assert flow.retrieveFlowStatus().status == DOWN - eventsAmount = history.entries.size() + assert history.getEntriesByType(REROUTE).size() == rerouteEventsAmount } - and: "Flow remains down and no new history events appear for the next 3 seconds (no retry happens)" - timedLoop(3) { + and: "Flow remains down and no new history events appear for the next 5 seconds (no retry happens)" + timedLoop(5) { assert flow.retrieveFlowStatus().status == DOWN - assert flow.retrieveFlowHistory().entries.size() == eventsAmount + assert flow.retrieveFlowHistory().entries.size() == rerouteEventsAmount + 1 // +1 creation event } + and: "The last reroute event was caused by delay on src for the alternative path" + def rerouteEvents = flow.retrieveFlowHistory().getEntriesByType(REROUTE).last() + rerouteEvents.payload.last().action == REROUTE_FAILED.payloadLastAction + rerouteEvents.payload.last().details.toString().contains( + "No paths of the flow ${flow.flowId} are affected by failure on IslEndpoint") + and: "Src/dst switches are valid" switchHelper.cleanupTrafficShaperRules([swPair.src]) boolean isTrafficShaperRulesCleanedUp = true @@ -400,6 +412,7 @@ class RetriesIsolatedSpec extends HealthCheckSpecification { } cleanup: - !isTrafficShaperRulesCleanedUp && switchHelper.cleanupTrafficShaperRules([swPair.src]) + //should be called here as flow deletion is called before removing delay on the switch in our cleanup manager + !isTrafficShaperRulesCleanedUp && switchHelper.cleanupTrafficShaperRules(flowInvolvedSwitches) } } From 4bc8a9f99faa2c85098748321fe33235cdb244eb Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Wed, 13 Nov 2024 17:33:21 +0100 Subject: [PATCH 10/21] [TEST]: Improvement: Moving factory classes to the appropriate folder, ha-flow deletion --- .../helpers/{ => factory}/HaFlowFactory.groovy | 3 +-- .../helpers/{model => factory}/YFlowFactory.groovy | 6 +++++- .../functionaltests/helpers/model/HaFlowExtended.groovy | 6 ++++-- .../spec/flows/haflows/HaFlowCreateSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowDiversitySpec.groovy | 4 ++-- .../spec/flows/haflows/HaFlowHistorySpec.groovy | 2 +- .../spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowPathSwapSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowPathsSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowPingSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowProtectedSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowRerouteSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowSyncSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowUpdateSpec.groovy | 2 +- .../spec/flows/haflows/HaFlowValidationSpec.groovy | 2 +- .../functionaltests/spec/flows/yflows/SubFlowSpec.groovy | 2 +- .../spec/flows/yflows/YFlowCreateSpec.groovy | 2 +- .../spec/flows/yflows/YFlowDiversitySpec.groovy | 2 +- .../spec/flows/yflows/YFlowPathSwapSpec.groovy | 2 +- .../functionaltests/spec/flows/yflows/YFlowPingSpec.groovy | 2 +- .../spec/flows/yflows/YFlowProtectedSpec.groovy | 2 +- .../spec/flows/yflows/YFlowRerouteSpec.groovy | 3 +-- .../spec/flows/yflows/YFlowUpdateSpec.groovy | 3 +-- .../spec/flows/yflows/YFlowValidationSpec.groovy | 2 +- .../spec/server42/Server42HaFlowRttSpec.groovy | 2 +- .../spec/server42/Server42YFlowRttSpec.groovy | 2 +- .../functionaltests/spec/stats/HaFlowStatSpec.groovy | 2 +- .../functionaltests/spec/stats/YFlowStatSpec.groovy | 2 +- .../spec/switches/SwitchesFlowsV2Spec.groovy | 2 +- 29 files changed, 37 insertions(+), 34 deletions(-) rename src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/{ => factory}/HaFlowFactory.groovy (94%) rename src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/{model => factory}/YFlowFactory.groovy (89%) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/HaFlowFactory.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/HaFlowFactory.groovy similarity index 94% rename from src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/HaFlowFactory.groovy rename to src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/HaFlowFactory.groovy index 3020838957..6c7118394a 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/HaFlowFactory.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/HaFlowFactory.groovy @@ -1,8 +1,7 @@ -package org.openkilda.functionaltests.helpers +package org.openkilda.functionaltests.helpers.factory import org.openkilda.functionaltests.model.cleanup.CleanupManager -import static org.openkilda.testing.Constants.FLOW_CRUD_TIMEOUT import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE import org.openkilda.functionaltests.helpers.builder.HaFlowBuilder diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowFactory.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/YFlowFactory.groovy similarity index 89% rename from src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowFactory.groovy rename to src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/YFlowFactory.groovy index cb52255edf..329dcb5e07 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowFactory.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/factory/YFlowFactory.groovy @@ -1,4 +1,8 @@ -package org.openkilda.functionaltests.helpers.model +package org.openkilda.functionaltests.helpers.factory + +import org.openkilda.functionaltests.helpers.model.SwitchPortVlan +import org.openkilda.functionaltests.helpers.model.SwitchTriplet +import org.openkilda.functionaltests.helpers.model.YFlowExtended import groovy.util.logging.Slf4j import org.openkilda.functionaltests.helpers.builder.YFlowBuilder diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy index 61dcc2d1aa..f3d1f7c79b 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy @@ -304,8 +304,10 @@ class HaFlowExtended { } HaFlow delete() { - Wrappers.wait(WAIT_OFFSET * 2) { - assert !(FlowState.getByValue(northboundV2.getHaFlow(haFlowId)?.status) in [FlowState.IN_PROGRESS, FlowState.DOWN]) + if (haFlowId in northboundV2.getAllHaFlows().haFlowId) { + Wrappers.wait(WAIT_OFFSET * 2) { + assert !(FlowState.getByValue(northboundV2.getHaFlow(haFlowId)?.status) in [FlowState.IN_PROGRESS, FlowState.DOWN]) + } } log.debug("Deleting ha-flow '$haFlowId'") def response = northboundV2.deleteHaFlow(haFlowId) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy index 9ee32c540b..02b4051aef 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy @@ -5,7 +5,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.haflow.HaFlowNotCreatedExpectedError import org.openkilda.functionaltests.error.haflow.HaFlowNotCreatedWithConflictExpectedError import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.builder.HaFlowBuilder import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.testing.service.traffexam.TraffExamService diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy index 52aeb53ad1..0960d22fc8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy @@ -6,10 +6,10 @@ import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.factory.FlowFactory import org.openkilda.functionaltests.helpers.model.HaFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowHistorySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowHistorySpec.groovy index d6d8e500b3..5fb0d815de 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowHistorySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowHistorySpec.groovy @@ -9,7 +9,7 @@ import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMo import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.HistoryMaxCountExpectedError import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.messaging.info.event.IslChangeType diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy index 48254eeca8..618ee29333 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowIntentionalRerouteSpec.groovy @@ -9,7 +9,7 @@ import static org.openkilda.testing.Constants.WAIT_OFFSET import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.IslHelper import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathSwapSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathSwapSpec.groovy index 8ec2ec7f6c..6d972c468b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathSwapSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathSwapSpec.groovy @@ -13,7 +13,7 @@ import static org.openkilda.testing.Constants.STATS_LOGGING_TIMEOUT import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.haflow.HaFlowPathNotSwappedExpectedError import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.model.stats.HaFlowStats import org.openkilda.messaging.payload.flow.FlowState diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathsSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathsSpec.groovy index 0a96d775c9..56dfab28b2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathsSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPathsSpec.groovy @@ -2,7 +2,7 @@ package org.openkilda.functionaltests.spec.flows.haflows import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.model.HaFlowExtended import groovy.util.logging.Slf4j diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy index a7cf52a17f..2c7bafa9ed 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowPingSpec.groovy @@ -2,7 +2,7 @@ package org.openkilda.functionaltests.spec.flows.haflows import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowProtectedSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowProtectedSpec.groovy index 75c7493955..4cbfb7f046 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowProtectedSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowProtectedSpec.groovy @@ -3,7 +3,7 @@ package org.openkilda.functionaltests.spec.flows.haflows import groovy.util.logging.Slf4j import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.northbound.dto.v2.haflows.HaFlowPatchPayload diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy index 1382adc5a8..d0f8b926db 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy @@ -3,7 +3,7 @@ package org.openkilda.functionaltests.spec.flows.haflows import groovy.util.logging.Slf4j import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.model.stats.HaFlowStats import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.FlowStatus diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy index 9f5640e9cd..1f0ab7426f 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowSyncSpec.groovy @@ -14,7 +14,7 @@ import static org.openkilda.testing.service.floodlight.model.FloodlightConnectMo import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowRuleEntity import org.openkilda.functionaltests.helpers.model.HaFlowExtended diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowUpdateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowUpdateSpec.groovy index c55ed680b4..21393ec5af 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowUpdateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowUpdateSpec.groovy @@ -9,7 +9,7 @@ import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.haflow.HaFlowNotUpdatedExpectedError import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.northbound.dto.v2.haflows.HaFlowPatchEndpoint diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy index d07aa773c6..941b365d47 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy @@ -6,7 +6,7 @@ import static org.openkilda.testing.Constants.RULES_DELETION_TIME import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchMetersFactory diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/SubFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/SubFlowSpec.groovy index f3f26c6414..480ff7c671 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/SubFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/SubFlowSpec.groovy @@ -6,7 +6,7 @@ import static org.openkilda.functionaltests.helpers.SwitchHelper.randomVlan import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.flow.FlowNotModifiedExpectedError import org.openkilda.functionaltests.helpers.model.YFlowActionType -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.FlowPathDirection import org.openkilda.northbound.dto.v1.flows.PingInput diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy index f0e656e380..90ec61f562 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy @@ -17,7 +17,7 @@ import org.openkilda.functionaltests.helpers.builder.YFlowBuilder import org.openkilda.functionaltests.helpers.model.FlowActionType import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.helpers.model.YFlowActionType -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.model.SwitchFeature import org.openkilda.northbound.dto.v2.switches.LagPortRequest import org.openkilda.testing.service.traffexam.TraffExamService diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy index 4aa5c5027d..d3d51a1451 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy @@ -8,7 +8,7 @@ import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.model.FlowActionType import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath import org.openkilda.functionaltests.helpers.model.YFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.messaging.payload.flow.FlowPathPayload import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.northbound.dto.v2.yflows.YFlowPatchPayload diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPathSwapSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPathSwapSpec.groovy index 4f23d679b6..62ee7bbaf2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPathSwapSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPathSwapSpec.groovy @@ -4,7 +4,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.yflow.YFlowPathNotSwappedExpectedError import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.functionaltests.model.stats.FlowStats import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.testing.model.topology.TopologyDefinition.Isl diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy index eb66ccf940..1a64302059 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowPingSpec.groovy @@ -9,7 +9,7 @@ import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.model.SwitchId import org.openkilda.model.cookie.Cookie diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowProtectedSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowProtectedSpec.groovy index e1844dfb58..6df3f37526 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowProtectedSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowProtectedSpec.groovy @@ -3,7 +3,7 @@ package org.openkilda.functionaltests.spec.flows.yflows import static org.junit.jupiter.api.Assumptions.assumeTrue import org.openkilda.functionaltests.HealthCheckSpecification -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.northbound.dto.v2.yflows.YFlowPatchPayload import groovy.util.logging.Slf4j diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy index 8c79cb5f56..950561da1f 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy @@ -16,8 +16,7 @@ import org.openkilda.functionaltests.error.yflow.YFlowRerouteExpectedError import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.model.FlowActionType import org.openkilda.functionaltests.helpers.model.YFlowActionType -import org.openkilda.functionaltests.helpers.model.YFlowFactory -import org.openkilda.functionaltests.model.stats.Direction +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.functionaltests.model.stats.FlowStats import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.northbound.dto.v2.yflows.YFlowRerouteResult diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowUpdateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowUpdateSpec.groovy index 9bb5492209..a67ab34ed2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowUpdateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowUpdateSpec.groovy @@ -4,9 +4,8 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.yflow.YFlowNotUpdatedExpectedError import org.openkilda.functionaltests.error.yflow.YFlowNotUpdatedWithConflictExpectedError import org.openkilda.functionaltests.helpers.model.FlowEncapsulationType -import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.helpers.model.YFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.PathComputationStrategy import org.openkilda.model.SwitchId diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy index 05232e81a8..8c5111d8f2 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy @@ -7,7 +7,7 @@ import org.openkilda.functionaltests.error.yflow.YFlowNotFoundExpectedError import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowDirection -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.messaging.payload.flow.FlowState import org.springframework.beans.factory.annotation.Autowired diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy index 82cb7623d0..26a50eabaf 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy @@ -15,7 +15,7 @@ import static org.openkilda.testing.Constants.WAIT_OFFSET import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.HaFlowExtended diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy index c9392b2f1e..667be20996 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy @@ -29,7 +29,7 @@ import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.helpers.model.YFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.functionaltests.model.stats.FlowStats import org.openkilda.messaging.payload.flow.FlowState import org.openkilda.model.SwitchId diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/HaFlowStatSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/HaFlowStatSpec.groovy index 6d9e45cc72..5cdb27b1e3 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/HaFlowStatSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/HaFlowStatSpec.groovy @@ -2,7 +2,7 @@ package org.openkilda.functionaltests.spec.stats import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags -import org.openkilda.functionaltests.helpers.HaFlowFactory +import org.openkilda.functionaltests.helpers.factory.HaFlowFactory import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.model.stats.FlowStats diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/YFlowStatSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/YFlowStatSpec.groovy index 0dd0497224..68407c732b 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/YFlowStatSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/stats/YFlowStatSpec.groovy @@ -18,7 +18,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.model.YFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.functionaltests.model.stats.FlowStats import org.openkilda.functionaltests.model.stats.YFlowStats diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy index 1c39f4415e..5ce60a8dbd 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy @@ -12,7 +12,7 @@ import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.model.SwitchPair import org.openkilda.functionaltests.helpers.model.SwitchTriplet import org.openkilda.functionaltests.helpers.model.YFlowExtended -import org.openkilda.functionaltests.helpers.model.YFlowFactory +import org.openkilda.functionaltests.helpers.factory.YFlowFactory import org.openkilda.model.FlowPathDirection import org.openkilda.testing.model.topology.TopologyDefinition.Switch import org.openkilda.functionaltests.helpers.factory.FlowFactory From 5c41ccb34d983701dd031208112093c3e1ca4ae0 Mon Sep 17 00:00:00 2001 From: Ivan Chupin Date: Thu, 14 Nov 2024 13:19:51 +0000 Subject: [PATCH 11/21] nbworker add feature to reroute y-flow for switch/link evacuation process --- .../java/org/openkilda/model/FlowPath.java | 3 +- .../nbworker/bolts/MessageEncoder.java | 4 +- .../services/FlowOperationsService.java | 20 +++- .../services/FlowOperationsServiceTest.java | 98 ++++++++++++++++++- 4 files changed, 116 insertions(+), 9 deletions(-) diff --git a/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java b/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java index 52cda6ef06..78a9735682 100644 --- a/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java +++ b/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java @@ -88,13 +88,14 @@ public FlowPath(@NonNull PathId pathId, @NonNull Switch srcSwitch, @NonNull Swit long latency, long bandwidth, boolean ignoreBandwidth, FlowPathStatus status, List segments, Set applications, - String sharedBandwidthGroupId, HaFlowPath haFlowPath) { + String sharedBandwidthGroupId, HaFlowPath haFlowPath, Flow flow) { data = FlowPathDataImpl.builder().pathId(pathId).srcSwitch(srcSwitch).destSwitch(destSwitch) .cookie(cookie).meterId(meterId).ingressMirrorGroupId(ingressMirrorGroupId) .latency(latency).bandwidth(bandwidth) .ignoreBandwidth(ignoreBandwidth).status(status) .applications(applications) .sharedBandwidthGroupId(sharedBandwidthGroupId).haFlowPath(haFlowPath) + .flow(flow) .build(); // The reference is used to link path segments back to the path. See {@link #setSegments(List)}. ((FlowPathDataImpl) data).flowPath = this; diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java index 8f8f5a17d0..e5a0ae08c2 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java @@ -17,7 +17,7 @@ import org.openkilda.messaging.Message; import org.openkilda.messaging.MessageData; -import org.openkilda.messaging.command.flow.FlowRerouteRequest; +import org.openkilda.messaging.command.BaseRerouteRequest; import org.openkilda.messaging.command.switches.SwitchValidateRequest; import org.openkilda.messaging.error.ErrorData; import org.openkilda.wfm.CommandContext; @@ -38,7 +38,7 @@ protected void handleInput(Tuple input) throws Exception { CommandContext commandContext = pullContext(input); Message message = wrap(commandContext, payload); - if (payload instanceof FlowRerouteRequest) { + if (payload instanceof BaseRerouteRequest) { getOutput().emit(input.getSourceStreamId(), input, new Values(message)); } else if (payload instanceof SwitchValidateRequest) { getOutput().emit(input.getSourceStreamId(), input, diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java index 8895b7b722..66b1b5d52c 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java @@ -24,6 +24,7 @@ import org.openkilda.messaging.command.flow.FlowRequest; import org.openkilda.messaging.command.flow.FlowRerouteRequest; import org.openkilda.messaging.command.haflow.HaFlowRerouteRequest; +import org.openkilda.messaging.command.yflow.YFlowRerouteRequest; import org.openkilda.messaging.error.ErrorType; import org.openkilda.messaging.error.InvalidFlowException; import org.openkilda.messaging.error.MessageException; @@ -83,6 +84,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import net.jodah.failsafe.RetryPolicy; +import org.apache.commons.lang3.StringUtils; import java.time.Duration; import java.time.Instant; @@ -713,10 +715,20 @@ public List makeRerouteRequests( } } } else { - if (processed.add(flow.getFlowId())) { - FlowRerouteRequest request = new FlowRerouteRequest( - flow.getFlowId(), false, false, affectedIslEndpoints, reason, false); - results.add(request); + if (StringUtils.isNotBlank(flow.getYFlowId())) { + if (yFlowRepository.exists(flow.getYFlowId())) { + if (processed.add(flow.getYFlowId())) { + YFlowRerouteRequest req = new YFlowRerouteRequest(flow.getYFlowId(), affectedIslEndpoints, + reason, false); + results.add(req); + } + } + } else { + if (processed.add(flow.getFlowId())) { + FlowRerouteRequest request = new FlowRerouteRequest( + flow.getFlowId(), false, false, affectedIslEndpoints, reason, false); + results.add(request); + } } } } diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java b/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java index 3bd37ee971..d09a9c4ea0 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java @@ -23,7 +23,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import org.openkilda.messaging.command.BaseRerouteRequest; import org.openkilda.messaging.command.flow.FlowRequest; +import org.openkilda.messaging.command.flow.FlowRerouteRequest; +import org.openkilda.messaging.command.yflow.YFlowRerouteRequest; import org.openkilda.messaging.error.InvalidFlowException; import org.openkilda.messaging.info.InfoData; import org.openkilda.messaging.model.FlowPatch; @@ -39,12 +42,15 @@ import org.openkilda.model.Switch; import org.openkilda.model.SwitchId; import org.openkilda.model.SwitchStatus; +import org.openkilda.model.YFlow; +import org.openkilda.model.YFlow.SharedEndpoint; import org.openkilda.model.cookie.FlowSegmentCookie; import org.openkilda.persistence.inmemory.InMemoryGraphBasedTest; import org.openkilda.persistence.repositories.FlowPathRepository; import org.openkilda.persistence.repositories.FlowRepository; import org.openkilda.persistence.repositories.PathSegmentRepository; import org.openkilda.persistence.repositories.SwitchRepository; +import org.openkilda.persistence.repositories.YFlowRepository; import org.openkilda.wfm.error.FlowNotFoundException; import org.openkilda.wfm.error.SwitchNotFoundException; import org.openkilda.wfm.share.flow.TestFlowBuilder; @@ -71,6 +77,7 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { private static final String FLOW_ID_1 = "flow_1"; private static final String FLOW_ID_2 = "flow_2"; private static final String FLOW_ID_3 = "flow_3"; + private static final String Y_FLOW_ID_1 = "y_flow_1"; private static final PathId FORWARD_PATH_1 = new PathId("forward_path_1"); private static final PathId FORWARD_PATH_2 = new PathId("forward_path_2"); private static final PathId FORWARD_PATH_3 = new PathId("forward_path_3"); @@ -91,6 +98,7 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { private static FlowOperationsService flowOperationsService; private static FlowRepository flowRepository; + private static YFlowRepository yFlowRepository; private static FlowPathRepository flowPathRepository; private static PathSegmentRepository pathSegmentRepository; private static SwitchRepository switchRepository; @@ -103,6 +111,7 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { @BeforeAll public static void setUpOnce() { flowRepository = persistenceManager.getRepositoryFactory().createFlowRepository(); + yFlowRepository = persistenceManager.getRepositoryFactory().createYFlowRepository(); flowPathRepository = persistenceManager.getRepositoryFactory().createFlowPathRepository(); pathSegmentRepository = persistenceManager.getRepositoryFactory().createPathSegmentRepository(); switchRepository = persistenceManager.getRepositoryFactory().createSwitchRepository(); @@ -789,7 +798,7 @@ public void whenFlowWithMaxLatency_patchFlowWithLatencyTier2OnlyTest() } @Test - void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoundException, InvalidFlowException { + public void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoundException, InvalidFlowException { Flow createdFlow = createFlow(FLOW_ID_1, switchA, 1, switchC, 2, FORWARD_PATH_1, REVERSE_PATH_1, switchB, false, 100_500L, 0L); @@ -815,7 +824,7 @@ void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoundExcept } @Test - void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundException, InvalidFlowException { + public void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundException, InvalidFlowException { Flow createdFlow = createFlow(FLOW_ID_1, switchA, 1, switchC, 2, FORWARD_PATH_1, REVERSE_PATH_1, switchB, false, 100_500L, 0L); @@ -839,6 +848,91 @@ void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundExceptio assertEquals(action, carrier.getHistoryHolderList().get(2).getFlowHistoryData().getAction()); } + @Test + public void makeRerouteRequests() { + YFlow yFlow = buildYFlow(Y_FLOW_ID_1, switchA, 1, switchD); + yFlowRepository.add(yFlow); + + Flow ySubflow1 = buildFlow(null, Y_FLOW_ID_1, switchA, 1, 10, + switchB, 2, 11, "subFlow1", yFlow); + FlowPath yFlowForwardPath1 = FlowPath.builder() + .pathId(new PathId("subPath1")) + .srcSwitch(switchA) + .destSwitch(switchB) + .flow(ySubflow1) + .build(); + + Flow ySubflow2 = buildFlow(null, Y_FLOW_ID_1, switchA, 1, 20, + switchC, 2, 22, "subFlow2", yFlow); + FlowPath yFlowForwardPath2 = FlowPath.builder() + .pathId(new PathId("subPath2")) + .srcSwitch(switchA) + .destSwitch(switchB) + .flow(ySubflow2) + .build(); + + Flow flow1 = buildFlow(FLOW_ID_1, null, switchA, 1, 100, switchB, + 2, 111, "regularFlow", null); + FlowPath flowPath1 = FlowPath.builder() + .pathId(new PathId("path1")) + .srcSwitch(switchA) + .destSwitch(switchB) + .flow(flow1) + .build(); + + List flowPaths = Arrays.asList(yFlowForwardPath1, flowPath1, yFlowForwardPath2); + + // 3 flow path: 1 for regular flow and 2 for y-flow + List actualResult = + flowOperationsService.makeRerouteRequests(flowPaths, new HashSet<>(), "Great reason to reroute"); + + Assertions.assertEquals(2, actualResult.size()); + Assertions.assertInstanceOf(YFlowRerouteRequest.class, actualResult.get(0)); + Assertions.assertEquals(Y_FLOW_ID_1, actualResult.get(0).getFlowId()); + Assertions.assertInstanceOf(FlowRerouteRequest.class, actualResult.get(1)); + Assertions.assertEquals(FLOW_ID_1, actualResult.get(1).getFlowId()); + + // y-flow does not exist in the repository + transactionManager.doInTransaction(() -> yFlowRepository.remove(yFlow)); + actualResult = flowOperationsService.makeRerouteRequests(flowPaths, new HashSet<>(), "Great reason to reroute"); + Assertions.assertEquals(1, actualResult.size()); + Assertions.assertInstanceOf(FlowRerouteRequest.class, actualResult.get(0)); + Assertions.assertEquals(FLOW_ID_1, actualResult.get(0).getFlowId()); + } + + private YFlow buildYFlow(String yFlowId, Switch sharedEndpoint, int portNumber, Switch yPoint) { + return YFlow.builder() + .yFlowId(yFlowId) + .sharedEndpoint(new SharedEndpoint(sharedEndpoint.getSwitchId(), portNumber)) + .yPoint(yPoint.getSwitchId()) + .status(FlowStatus.UP) + .build(); + } + + private Flow buildFlow(String flowId, String yflowId, Switch srcSwitch, int srcPort, int srcVlan, Switch destSwitch, + int destPort, int destVlan, String desc, YFlow yflow) { + TestFlowBuilder builder = new TestFlowBuilder() + .yFlow(yflow) + .srcSwitch(srcSwitch) + .srcPort(srcPort) + .srcVlan(srcVlan) + .destSwitch(destSwitch) + .destPort(destPort) + .destVlan(destVlan) + .encapsulationType(FlowEncapsulationType.TRANSIT_VLAN) + .pathComputationStrategy(PathComputationStrategy.COST) + .description(desc) + .status(FlowStatus.UP); + + if (flowId != null) { + builder.flowId(flowId); + } + if (yflowId != null) { + builder.yFlowId(yflowId); + } + return builder.build(); + } + private void assertFlows(Collection actualFlows, String... expectedFlowIds) { assertEquals(expectedFlowIds.length, actualFlows.size()); assertEquals(new HashSet<>(Arrays.asList(expectedFlowIds)), From 3f3822040d36d5ca99c8865efefffa43a982d736 Mon Sep 17 00:00:00 2001 From: Ivan Chupin Date: Thu, 14 Nov 2024 13:23:45 +0000 Subject: [PATCH 12/21] Revert "nbworker add feature to reroute y-flow for switch/link evacuation process" This reverts commit 5c41ccb34d983701dd031208112093c3e1ca4ae0. --- .../java/org/openkilda/model/FlowPath.java | 3 +- .../nbworker/bolts/MessageEncoder.java | 4 +- .../services/FlowOperationsService.java | 20 +--- .../services/FlowOperationsServiceTest.java | 98 +------------------ 4 files changed, 9 insertions(+), 116 deletions(-) diff --git a/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java b/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java index 78a9735682..52cda6ef06 100644 --- a/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java +++ b/src-java/kilda-model/src/main/java/org/openkilda/model/FlowPath.java @@ -88,14 +88,13 @@ public FlowPath(@NonNull PathId pathId, @NonNull Switch srcSwitch, @NonNull Swit long latency, long bandwidth, boolean ignoreBandwidth, FlowPathStatus status, List segments, Set applications, - String sharedBandwidthGroupId, HaFlowPath haFlowPath, Flow flow) { + String sharedBandwidthGroupId, HaFlowPath haFlowPath) { data = FlowPathDataImpl.builder().pathId(pathId).srcSwitch(srcSwitch).destSwitch(destSwitch) .cookie(cookie).meterId(meterId).ingressMirrorGroupId(ingressMirrorGroupId) .latency(latency).bandwidth(bandwidth) .ignoreBandwidth(ignoreBandwidth).status(status) .applications(applications) .sharedBandwidthGroupId(sharedBandwidthGroupId).haFlowPath(haFlowPath) - .flow(flow) .build(); // The reference is used to link path segments back to the path. See {@link #setSegments(List)}. ((FlowPathDataImpl) data).flowPath = this; diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java index e5a0ae08c2..8f8f5a17d0 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/MessageEncoder.java @@ -17,7 +17,7 @@ import org.openkilda.messaging.Message; import org.openkilda.messaging.MessageData; -import org.openkilda.messaging.command.BaseRerouteRequest; +import org.openkilda.messaging.command.flow.FlowRerouteRequest; import org.openkilda.messaging.command.switches.SwitchValidateRequest; import org.openkilda.messaging.error.ErrorData; import org.openkilda.wfm.CommandContext; @@ -38,7 +38,7 @@ protected void handleInput(Tuple input) throws Exception { CommandContext commandContext = pullContext(input); Message message = wrap(commandContext, payload); - if (payload instanceof BaseRerouteRequest) { + if (payload instanceof FlowRerouteRequest) { getOutput().emit(input.getSourceStreamId(), input, new Values(message)); } else if (payload instanceof SwitchValidateRequest) { getOutput().emit(input.getSourceStreamId(), input, diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java index 66b1b5d52c..8895b7b722 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsService.java @@ -24,7 +24,6 @@ import org.openkilda.messaging.command.flow.FlowRequest; import org.openkilda.messaging.command.flow.FlowRerouteRequest; import org.openkilda.messaging.command.haflow.HaFlowRerouteRequest; -import org.openkilda.messaging.command.yflow.YFlowRerouteRequest; import org.openkilda.messaging.error.ErrorType; import org.openkilda.messaging.error.InvalidFlowException; import org.openkilda.messaging.error.MessageException; @@ -84,7 +83,6 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import net.jodah.failsafe.RetryPolicy; -import org.apache.commons.lang3.StringUtils; import java.time.Duration; import java.time.Instant; @@ -715,20 +713,10 @@ public List makeRerouteRequests( } } } else { - if (StringUtils.isNotBlank(flow.getYFlowId())) { - if (yFlowRepository.exists(flow.getYFlowId())) { - if (processed.add(flow.getYFlowId())) { - YFlowRerouteRequest req = new YFlowRerouteRequest(flow.getYFlowId(), affectedIslEndpoints, - reason, false); - results.add(req); - } - } - } else { - if (processed.add(flow.getFlowId())) { - FlowRerouteRequest request = new FlowRerouteRequest( - flow.getFlowId(), false, false, affectedIslEndpoints, reason, false); - results.add(request); - } + if (processed.add(flow.getFlowId())) { + FlowRerouteRequest request = new FlowRerouteRequest( + flow.getFlowId(), false, false, affectedIslEndpoints, reason, false); + results.add(request); } } } diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java b/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java index d09a9c4ea0..3bd37ee971 100644 --- a/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java +++ b/src-java/nbworker-topology/nbworker-storm-topology/src/test/java/org/openkilda/wfm/topology/nbworker/services/FlowOperationsServiceTest.java @@ -23,10 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.openkilda.messaging.command.BaseRerouteRequest; import org.openkilda.messaging.command.flow.FlowRequest; -import org.openkilda.messaging.command.flow.FlowRerouteRequest; -import org.openkilda.messaging.command.yflow.YFlowRerouteRequest; import org.openkilda.messaging.error.InvalidFlowException; import org.openkilda.messaging.info.InfoData; import org.openkilda.messaging.model.FlowPatch; @@ -42,15 +39,12 @@ import org.openkilda.model.Switch; import org.openkilda.model.SwitchId; import org.openkilda.model.SwitchStatus; -import org.openkilda.model.YFlow; -import org.openkilda.model.YFlow.SharedEndpoint; import org.openkilda.model.cookie.FlowSegmentCookie; import org.openkilda.persistence.inmemory.InMemoryGraphBasedTest; import org.openkilda.persistence.repositories.FlowPathRepository; import org.openkilda.persistence.repositories.FlowRepository; import org.openkilda.persistence.repositories.PathSegmentRepository; import org.openkilda.persistence.repositories.SwitchRepository; -import org.openkilda.persistence.repositories.YFlowRepository; import org.openkilda.wfm.error.FlowNotFoundException; import org.openkilda.wfm.error.SwitchNotFoundException; import org.openkilda.wfm.share.flow.TestFlowBuilder; @@ -77,7 +71,6 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { private static final String FLOW_ID_1 = "flow_1"; private static final String FLOW_ID_2 = "flow_2"; private static final String FLOW_ID_3 = "flow_3"; - private static final String Y_FLOW_ID_1 = "y_flow_1"; private static final PathId FORWARD_PATH_1 = new PathId("forward_path_1"); private static final PathId FORWARD_PATH_2 = new PathId("forward_path_2"); private static final PathId FORWARD_PATH_3 = new PathId("forward_path_3"); @@ -98,7 +91,6 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { private static FlowOperationsService flowOperationsService; private static FlowRepository flowRepository; - private static YFlowRepository yFlowRepository; private static FlowPathRepository flowPathRepository; private static PathSegmentRepository pathSegmentRepository; private static SwitchRepository switchRepository; @@ -111,7 +103,6 @@ public class FlowOperationsServiceTest extends InMemoryGraphBasedTest { @BeforeAll public static void setUpOnce() { flowRepository = persistenceManager.getRepositoryFactory().createFlowRepository(); - yFlowRepository = persistenceManager.getRepositoryFactory().createYFlowRepository(); flowPathRepository = persistenceManager.getRepositoryFactory().createFlowPathRepository(); pathSegmentRepository = persistenceManager.getRepositoryFactory().createPathSegmentRepository(); switchRepository = persistenceManager.getRepositoryFactory().createSwitchRepository(); @@ -798,7 +789,7 @@ public void whenFlowWithMaxLatency_patchFlowWithLatencyTier2OnlyTest() } @Test - public void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoundException, InvalidFlowException { + void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoundException, InvalidFlowException { Flow createdFlow = createFlow(FLOW_ID_1, switchA, 1, switchC, 2, FORWARD_PATH_1, REVERSE_PATH_1, switchB, false, 100_500L, 0L); @@ -824,7 +815,7 @@ public void whenPartialUpdate_dumpBeforeAndDumpAfterIsSaved() throws FlowNotFoun } @Test - public void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundException, InvalidFlowException { + void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundException, InvalidFlowException { Flow createdFlow = createFlow(FLOW_ID_1, switchA, 1, switchC, 2, FORWARD_PATH_1, REVERSE_PATH_1, switchB, false, 100_500L, 0L); @@ -848,91 +839,6 @@ public void whenFullUpdateIsRequired_historyActionIsSaved() throws FlowNotFoundE assertEquals(action, carrier.getHistoryHolderList().get(2).getFlowHistoryData().getAction()); } - @Test - public void makeRerouteRequests() { - YFlow yFlow = buildYFlow(Y_FLOW_ID_1, switchA, 1, switchD); - yFlowRepository.add(yFlow); - - Flow ySubflow1 = buildFlow(null, Y_FLOW_ID_1, switchA, 1, 10, - switchB, 2, 11, "subFlow1", yFlow); - FlowPath yFlowForwardPath1 = FlowPath.builder() - .pathId(new PathId("subPath1")) - .srcSwitch(switchA) - .destSwitch(switchB) - .flow(ySubflow1) - .build(); - - Flow ySubflow2 = buildFlow(null, Y_FLOW_ID_1, switchA, 1, 20, - switchC, 2, 22, "subFlow2", yFlow); - FlowPath yFlowForwardPath2 = FlowPath.builder() - .pathId(new PathId("subPath2")) - .srcSwitch(switchA) - .destSwitch(switchB) - .flow(ySubflow2) - .build(); - - Flow flow1 = buildFlow(FLOW_ID_1, null, switchA, 1, 100, switchB, - 2, 111, "regularFlow", null); - FlowPath flowPath1 = FlowPath.builder() - .pathId(new PathId("path1")) - .srcSwitch(switchA) - .destSwitch(switchB) - .flow(flow1) - .build(); - - List flowPaths = Arrays.asList(yFlowForwardPath1, flowPath1, yFlowForwardPath2); - - // 3 flow path: 1 for regular flow and 2 for y-flow - List actualResult = - flowOperationsService.makeRerouteRequests(flowPaths, new HashSet<>(), "Great reason to reroute"); - - Assertions.assertEquals(2, actualResult.size()); - Assertions.assertInstanceOf(YFlowRerouteRequest.class, actualResult.get(0)); - Assertions.assertEquals(Y_FLOW_ID_1, actualResult.get(0).getFlowId()); - Assertions.assertInstanceOf(FlowRerouteRequest.class, actualResult.get(1)); - Assertions.assertEquals(FLOW_ID_1, actualResult.get(1).getFlowId()); - - // y-flow does not exist in the repository - transactionManager.doInTransaction(() -> yFlowRepository.remove(yFlow)); - actualResult = flowOperationsService.makeRerouteRequests(flowPaths, new HashSet<>(), "Great reason to reroute"); - Assertions.assertEquals(1, actualResult.size()); - Assertions.assertInstanceOf(FlowRerouteRequest.class, actualResult.get(0)); - Assertions.assertEquals(FLOW_ID_1, actualResult.get(0).getFlowId()); - } - - private YFlow buildYFlow(String yFlowId, Switch sharedEndpoint, int portNumber, Switch yPoint) { - return YFlow.builder() - .yFlowId(yFlowId) - .sharedEndpoint(new SharedEndpoint(sharedEndpoint.getSwitchId(), portNumber)) - .yPoint(yPoint.getSwitchId()) - .status(FlowStatus.UP) - .build(); - } - - private Flow buildFlow(String flowId, String yflowId, Switch srcSwitch, int srcPort, int srcVlan, Switch destSwitch, - int destPort, int destVlan, String desc, YFlow yflow) { - TestFlowBuilder builder = new TestFlowBuilder() - .yFlow(yflow) - .srcSwitch(srcSwitch) - .srcPort(srcPort) - .srcVlan(srcVlan) - .destSwitch(destSwitch) - .destPort(destPort) - .destVlan(destVlan) - .encapsulationType(FlowEncapsulationType.TRANSIT_VLAN) - .pathComputationStrategy(PathComputationStrategy.COST) - .description(desc) - .status(FlowStatus.UP); - - if (flowId != null) { - builder.flowId(flowId); - } - if (yflowId != null) { - builder.yFlowId(yflowId); - } - return builder.build(); - } - private void assertFlows(Collection actualFlows, String... expectedFlowIds) { assertEquals(expectedFlowIds.length, actualFlows.size()); assertEquals(new HashSet<>(Arrays.asList(expectedFlowIds)), From 5d1939db31936981a2e6dac82678c34afd8b3051 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Mon, 18 Nov 2024 17:13:38 +0100 Subject: [PATCH 13/21] [TEST]: Improvement: SwT: Y-Point selection --- .../helpers/TopologyHelper.groovy | 20 ------------- .../helpers/model/SwitchTriplet.groovy | 28 +++++++++++++++++-- .../helpers/model/SwitchTriplets.groovy | 9 ++---- .../flows/haflows/HaFlowCreateSpec.groovy | 18 ++++++------ .../flows/haflows/HaFlowRerouteSpec.groovy | 2 +- .../spec/flows/yflows/YFlowCreateSpec.groovy | 22 +++++++-------- .../spec/flows/yflows/YFlowRerouteSpec.groovy | 2 +- .../spec/switches/SwitchesFlowsV2Spec.groovy | 4 +-- 8 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/TopologyHelper.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/TopologyHelper.groovy index 78dfabd139..d628727f24 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/TopologyHelper.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/TopologyHelper.groovy @@ -84,26 +84,6 @@ class TopologyHelper { } } - @Memoized - List findPotentialYPoints(SwitchTriplet swT) { - def sortedEp1Paths = swT.pathsEp1.sort { it.size() } - def potentialEp1Paths = sortedEp1Paths.takeWhile { it.size() == sortedEp1Paths[0].size() } - def potentialEp2Paths = potentialEp1Paths.collect { potentialEp1Path -> - def sortedEp2Paths = swT.pathsEp2.sort { - it.size() - it.intersect(potentialEp1Path).size() - } - [path1: potentialEp1Path, - potentialPaths2: sortedEp2Paths.takeWhile {it.size() == sortedEp2Paths[0].size() }] - } - return potentialEp2Paths.collectMany {path1WithPath2 -> - path1WithPath2.potentialPaths2.collect { List potentialPath2 -> - def switches = path1WithPath2.path1.switchId - .intersect(potentialPath2.switchId) - switches ? switches[-1] : null - } - }.findAll().unique() - } - List> getDbPathsNodes(SwitchId src, SwitchId dst) { database.getPaths(src, dst)*.path } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplet.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplet.groovy index 3e6bce2790..d86387ff7f 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplet.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplet.groovy @@ -3,11 +3,13 @@ package org.openkilda.functionaltests.helpers.model import static org.openkilda.functionaltests.helpers.TopologyHelper.convertToPathNodePayload import org.openkilda.messaging.info.event.PathNode +import org.openkilda.model.SwitchId import org.openkilda.testing.model.topology.TopologyDefinition import org.openkilda.testing.model.topology.TopologyDefinition.Switch import com.fasterxml.jackson.annotation.JsonIgnore import groovy.transform.EqualsAndHashCode +import groovy.transform.Memoized import groovy.transform.TupleConstructor @TupleConstructor @@ -20,7 +22,7 @@ class SwitchTriplet { List> pathsEp2 @JsonIgnore - TopologyDefinition topologyDefinition + TopologyDefinition topology @JsonIgnore SwitchTriplet getReversed() { @@ -75,14 +77,34 @@ class SwitchTriplet { areEp1Ep2AndEp1OrEp2AndShEpNeighbour } + @Memoized + List findPotentialYPoints() { + def sortedEp1Paths = pathsEp1.sort { it.size() } + def potentialEp1Paths = sortedEp1Paths.takeWhile { it.size() == sortedEp1Paths[0].size() } + def potentialEp2Paths = potentialEp1Paths.collect { potentialEp1Path -> + def sortedEp2Paths = pathsEp2.sort { + it.size() - it.intersect(potentialEp1Path).size() + } + [path1: potentialEp1Path, + potentialPaths2: sortedEp2Paths.takeWhile {it.size() == sortedEp2Paths[0].size() }] + } + return potentialEp2Paths.collectMany {path1WithPath2 -> + path1WithPath2.potentialPaths2.collect { List potentialPath2 -> + def switches = path1WithPath2.path1.switchId + .intersect(potentialPath2.switchId) + switches ? switches[-1] : null + } + }.findAll().unique() + } + List retrieveAvailablePathsEp1(){ convertToPathNodePayload(pathsEp1).collect{ - new Path(it, topologyDefinition) + new Path(it, topology) } } List retrieveAvailablePathsEp2(){ convertToPathNodePayload(pathsEp2).collect{ - new Path(it, topologyDefinition) + new Path(it, topology) } } } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplets.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplets.groovy index 0a79d305ea..0317e0e4c3 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplets.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SwitchTriplets.groovy @@ -2,7 +2,6 @@ package org.openkilda.functionaltests.helpers.model import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE -import org.openkilda.functionaltests.helpers.TopologyHelper import org.openkilda.messaging.info.event.PathNode import org.openkilda.model.SwitchId import org.openkilda.testing.model.topology.TopologyDefinition @@ -29,8 +28,6 @@ import org.springframework.stereotype.Component class SwitchTriplets { List switchTriplets @Autowired - TopologyHelper topologyHelper - @Autowired TopologyDefinition topology SwitchTriplets(List switchTriplets) { @@ -147,7 +144,7 @@ class SwitchTriplets { .unique(false) { a, b -> a.intersect(b) == [] ? 1 : 0 } def ep2paths = it.pathsEp2.findAll { path -> !path.any { node -> node.switchId == it.ep1.dpId } } .unique(false) { a, b -> a.intersect(b) == [] ? 1 : 0 } - def yPoints = topologyHelper.findPotentialYPoints(it) + def yPoints = it.findPotentialYPoints() yPoints.size() == 1 && (isYPointOnSharedEp ? yPoints[0] == it.shared.dpId : yPoints[0] != it.shared.dpId) && yPoints[0] != it.ep1.dpId && yPoints[0] != it.ep2.dpId && ep1paths.size() >= 2 && ep2paths.size() >= 2 @@ -184,7 +181,7 @@ class SwitchTriplets { SwitchTriplet findSwitchTripletWithYPointOnSharedEp() { return switchTriplets.find { - topologyHelper.findPotentialYPoints(it).size() == 1 && it.getShared().getDpId() == topologyHelper.findPotentialYPoints(it).get(0) + it.findPotentialYPoints().size() == 1 && it.shared.dpId == it.findPotentialYPoints().get(0) } } @@ -227,7 +224,7 @@ class SwitchTriplets { ep2: ep2, pathsEp1: retrievePairPathNode(shared.dpId, ep1.dpId), pathsEp2: retrievePairPathNode(shared.dpId, ep2.dpId), - topologyDefinition: topology) + topology: topology) } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy index 02b4051aef..b5c5ebf943 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowCreateSpec.groovy @@ -164,12 +164,12 @@ and ${haFlowInvalidRequest.subFlows[1].endpointInnerVlan}./).matches(exc) //se = shared endpoint, ep = subflow endpoint, yp = y-point [name : "se is wb and se!=yp", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId }], [name : "se is non-wb and se!=yp", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId }], [name : "ep on wb and different eps", //ep1 is not the same sw as ep2 @@ -178,37 +178,37 @@ and ${haFlowInvalidRequest.subFlows[1].endpointInnerVlan}./).matches(exc) condition: { SwitchTriplet swT -> !swT.ep1.wb5164 && swT.ep1 != swT.ep2 }], [name : "se+yp on wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] == swT.shared.dpId }], [name : "se+yp on non-wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] == swT.shared.dpId }], [name : "yp on wb and yp!=se!=ep", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId && yPoints[0] != swT.ep1.dpId && yPoints[0] != swT.ep2.dpId }], [name : "yp on non-wb and yp!=se!=ep", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId && yPoints[0] != swT.ep1.dpId && yPoints[0] != swT.ep2.dpId }], [name : "ep+yp on wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && (yPoints[0] == swT.ep1.dpId || yPoints[0] == swT.ep2.dpId) }], [name : "ep+yp on non-wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && (yPoints[0] == swT.ep1.dpId || yPoints[0] == swT.ep2.dpId) }], [name : "yp==se", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() yPoints.size() == 1 && yPoints[0] == swT.shared.dpId && swT.shared != swT.ep1 && swT.shared != swT.ep2 }] ] diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy index d0f8b926db..dd6c183ca8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy @@ -167,7 +167,7 @@ class HaFlowRerouteSpec extends HealthCheckSpecification { def "HA-flow goes to 'Down' status when ISl of the HA-flow fails and there is no alt path to reroute"() { given: "An HA-flow without alternative paths" def swT = switchTriplets.all().withAllDifferentEndpoints().switchTriplets.find { - def yPoints = topologyHelper.findPotentialYPoints(it) + def yPoints = it.findPotentialYPoints() yPoints.size() == 1 && yPoints[0] != it.shared.dpId } assumeTrue(swT != null, "These cases cannot be covered on given topology:") diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy index 90ec61f562..b73732082c 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy @@ -384,8 +384,8 @@ source: switchId="${flowParams.yFlow.sharedEndpoint.switchId}" port=${flowParams def slowestLinkSwitchIds = [slowestLinkOnTheWest.getSrcSwitchId(), slowestLinkOnTheWest.getDestSwitchId()] def switchTriplet = switchTriplets.all(true, false).getSwitchTriplets() .find { - def yPoints = topologyHelper.findPotentialYPoints(it) - slowestLinkSwitchIds.contains(it.shared.getDpId()) && + def yPoints = it.findPotentialYPoints() + slowestLinkSwitchIds.contains(it.shared.dpId) && !slowestLinkSwitchIds.intersect(yPoints).isEmpty() } assumeTrue(switchTriplet != null, "No suiting switches found.") @@ -456,12 +456,12 @@ source: switchId="${flowParams.yFlow.sharedEndpoint.switchId}" port=${flowParams //se = shared endpoint, ep = subflow endpoint, yp = y-point [name : "se is wb and se!=yp", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId }], [name : "se is non-wb and se!=yp", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId }], [name : "ep on wb and different eps", //ep1 is not the same sw as ep2 @@ -470,37 +470,37 @@ source: switchId="${flowParams.yFlow.sharedEndpoint.switchId}" port=${flowParams condition: { SwitchTriplet swT -> !swT.ep1.wb5164 && swT.ep1 != swT.ep2 }], [name : "se+yp on wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] == swT.shared.dpId }], [name : "se+yp on non-wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] == swT.shared.dpId }], [name : "yp on wb and yp!=se!=ep", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId && yPoints[0] != swT.ep1.dpId && yPoints[0] != swT.ep2.dpId }], [name : "yp on non-wb and yp!=se!=ep", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && yPoints[0] != swT.shared.dpId && yPoints[0] != swT.ep1.dpId && yPoints[0] != swT.ep2.dpId }], [name : "ep+yp on wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() swT.shared.wb5164 && yPoints.size() == 1 && (yPoints[0] == swT.ep1.dpId || yPoints[0] == swT.ep2.dpId) }], [name : "ep+yp on non-wb", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() !swT.shared.wb5164 && yPoints.size() == 1 && (yPoints[0] == swT.ep1.dpId || yPoints[0] == swT.ep2.dpId) }], [name : "yp==se", condition: { SwitchTriplet swT -> - def yPoints = topologyHelper.findPotentialYPoints(swT) + def yPoints = swT.findPotentialYPoints() yPoints.size() == 1 && yPoints[0] == swT.shared.dpId && swT.shared != swT.ep1 && swT.shared != swT.ep2 }] ] diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy index 950561da1f..955ac2b561 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowRerouteSpec.groovy @@ -50,7 +50,7 @@ class YFlowRerouteSpec extends HealthCheckSpecification { def "Valid y-flow can be rerouted"() { given: "A qinq y-flow" def swT = switchTriplets.all().withAllDifferentEndpoints().withoutWBSwitch().getSwitchTriplets().find { - def yPoints = topologyHelper.findPotentialYPoints(it) + def yPoints = it.findPotentialYPoints() yPoints.size() == 1 && yPoints[0] != it.shared.dpId } assumeTrue(swT != null, "These cases cannot be covered on given topology:") diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy index 5ce60a8dbd..97b129f0fb 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchesFlowsV2Spec.groovy @@ -60,8 +60,8 @@ class SwitchesFlowsV2Spec extends HealthCheckSpecification { usual flow protected path subflow 2 ends on the switch that is not used by other flows */ switchTriplet = switchTriplets.all(true, false).nonNeighbouring().getSwitchTriplets().find { - def yPoints = topologyHelper.findPotentialYPoints(it) - yPoints[0] != it.shared + def yPoints = it.findPotentialYPoints() + yPoints[0] != it.shared.dpId } assumeTrue(switchTriplet != null, "Couldn't find appropriate switch triplet") From 509476349232af5bb2000f5d0aa52cf312ee52b9 Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Mon, 4 Nov 2024 18:27:17 +0100 Subject: [PATCH 14/21] [TEST]: Flaky tests: Hardware environment issue --- .../spec/flows/ConnectedDevicesSpec.groovy | 5 ++++- .../spec/flows/haflows/HaFlowRerouteSpec.groovy | 2 +- .../spec/flows/yflows/YFlowDiversitySpec.groovy | 1 - .../spec/server42/Server42YFlowRttSpec.groovy | 13 +++++++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy index c8b586db38..6409ed1541 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/ConnectedDevicesSpec.groovy @@ -857,7 +857,10 @@ srcDevices=#newSrcEnabled, dstDevices=#newDstEnabled"() { "Devices+VXLAN problem https://github.com/telstra/open-kilda/issues/3199") given: "Two switches connected to traffgen" - def switchPair = switchPairs.all().neighbouring().withTraffgensOnBothEnds().random() + def swPairs = switchPairs.all().neighbouring().withTraffgensOnBothEnds() + // there is an issue with physical switch (lldp traffic) + profile == "virtual" ?: swPairs.excludeSwitches(topology.activeSwitches.findAll { it.dpId.toString().contains("40") }) + def switchPair = switchPairs.random() and: "A QinQ flow with enabled connected devices on src has been created" def flow = flowFactory.getBuilder(switchPair) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy index d0f8b926db..028dd3ccfe 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowRerouteSpec.groovy @@ -45,7 +45,7 @@ class HaFlowRerouteSpec extends HealthCheckSpecification { @Autowired Provider traffExamProvider - @Tags([TOPOLOGY_DEPENDENT, ISL_RECOVER_ON_FAIL]) + @Tags([ISL_RECOVER_ON_FAIL]) @Issue("https://github.com/telstra/open-kilda/issues/5647 (hardware)") def "Valid HA-flow can be rerouted"() { given: "An HA-flow" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy index d3d51a1451..5cb171462c 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowDiversitySpec.groovy @@ -34,7 +34,6 @@ class YFlowDiversitySpec extends HealthCheckSpecification { given: "Switches with three not overlapping paths at least" def swT = switchTriplets.all(false, false).withAllDifferentEndpoints() .withAtLeastNNonOverlappingPaths(4).random() - println("[" + swT.shared.dpId + "] " + swT.ep1.dpId + "---" + swT.ep2.dpId ) assumeTrue(swT != null, "Unable to find suitable switches") when: "Create three Y-Flows with diversity enabled" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy index 667be20996..a69713fd00 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy @@ -13,6 +13,7 @@ import static org.openkilda.functionaltests.model.stats.Direction.REVERSE import static org.openkilda.functionaltests.model.stats.FlowStatsMetric.FLOW_RTT import static org.openkilda.functionaltests.model.stats.Origin.FLOW_MONITORING import static org.openkilda.functionaltests.model.stats.Origin.SERVER_42 +import static org.openkilda.testing.Constants.DEFAULT_COST import static org.openkilda.testing.Constants.PROTECTED_PATH_INSTALLATION_TIME import static org.openkilda.testing.Constants.RULES_DELETION_TIME import static org.openkilda.testing.Constants.RULES_INSTALLATION_TIME @@ -76,7 +77,6 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { .withSharedEpInTheMiddleOfTheChain().random() switchTripletWithYPointOnSubFlowEnd = switchTriplets.all().withAllDifferentEndpoints().withS42Support() .withSharedEpEp1Ep2InChain().random() - } @Tags(TOPOLOGY_DEPENDENT) @@ -86,6 +86,7 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { def swT = isSharedEndpointYPoint ? switchTripletWithYPointOnSharedEp : switchTripletWithYPointOnSubFlowEnd assert swT, "There is no switch triplet for the further Y-Flow creation" + isSharedEndpointYPoint ?: makeBothYFlowSubFlowsHaveTheLongestSharedPath(swT) when: "Set server42FlowRtt toggle to true" !featureToggles.getFeatureToggles().server42FlowRtt && featureToggles.server42FlowRtt(true) @@ -146,6 +147,7 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { assumeTrue((topology.getActiveServer42Switches().size() >= 3), "Unable to find active server42") def swT = isSharedEndpointYPoint ? switchTripletWithYPointOnSharedEp : switchTripletWithYPointOnSubFlowEnd + isSharedEndpointYPoint ?: makeBothYFlowSubFlowsHaveTheLongestSharedPath(swT) and: "server42FlowRtt feature enabled globally and on src/dst switch" !featureToggles.getFeatureToggles().server42FlowRtt && featureToggles.server42FlowRtt(true) @@ -157,7 +159,6 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { def yFlow = yFlowFactory.getRandom(swT) assert isSharedEndpointYPoint ? yFlow.sharedEndpoint.switchId == yFlow.yPoint : yFlow.sharedEndpoint.switchId != yFlow.yPoint - then: "Involved switches pass switch validation" List involvedSwitches = yFlow.retrieveAllEntityPaths().getInvolvedSwitches() Wrappers.wait(RULES_INSTALLATION_TIME) { @@ -373,6 +374,7 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { assumeTrue((topology.getActiveServer42Switches().size() >= 3), "Unable to find active server42") def swT = isSharedEndpointYPoint ? switchTripletWithYPointOnSharedEp : switchTripletWithYPointOnSubFlowEnd + isSharedEndpointYPoint ?: makeBothYFlowSubFlowsHaveTheLongestSharedPath(swT) and: "server42FlowRtt feature enabled globally and switch ON for appropriate switches(swT)" !featureToggles.getFeatureToggles().server42FlowRtt && featureToggles.server42FlowRtt(true) @@ -561,6 +563,7 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { assumeTrue((topology.getActiveServer42Switches().size() >= 3), "Unable to find active server42") def swT = isSharedEndpointYPoint ? switchTripletWithYPointOnSharedEp : switchTripletWithYPointOnSubFlowEnd + isSharedEndpointYPoint ?: makeBothYFlowSubFlowsHaveTheLongestSharedPath(swT) def statsWaitSeconds = 4 and: "server42FlowRtt toggle is turned off" @@ -660,4 +663,10 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { isSharedEndpointYPoint << [true, false] } + private void makeBothYFlowSubFlowsHaveTheLongestSharedPath(SwitchTriplet swT) { + def pathToManipulate = swT.pathsEp1[0].size() > swT.pathsEp2[0].size() + ? swT.retrieveAvailablePathsEp2().first() : swT.retrieveAvailablePathsEp1().first() + islHelper.updateIslsCost(pathToManipulate.getInvolvedIsls(), DEFAULT_COST - 5) + } + } From ba008e823f97bf8be97121aca1614789f43f8bba Mon Sep 17 00:00:00 2001 From: Yuliia Miroshnychenko Date: Wed, 27 Nov 2024 11:51:24 +0100 Subject: [PATCH 15/21] [TEST]: Improvement: Switch default cookies --- .../helpers/SwitchHelper.groovy | 108 +++++++++--------- .../spec/flows/QinQFlowSpec.groovy | 32 ++++-- .../spec/switches/DefaultRulesSpec.groovy | 19 +-- .../spec/switches/FlowRulesSpec.groovy | 3 +- .../spec/switches/SwitchSyncSpec.groovy | 6 +- .../spec/switches/SwitchValidationSpec.groovy | 3 +- .../switches/SwitchValidationV2Spec.groovy | 3 +- 7 files changed, 92 insertions(+), 82 deletions(-) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy index bef1cab3a7..0d2d7f3a3f 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/SwitchHelper.groovy @@ -226,74 +226,69 @@ class SwitchHelper { MULTITABLE_POST_INGRESS_DROP_COOKIE, MULTITABLE_EGRESS_PASS_THROUGH_COOKIE, MULTITABLE_TRANSIT_DROP_COOKIE, LLDP_POST_INGRESS_COOKIE, LLDP_POST_INGRESS_ONE_SWITCH_COOKIE, ARP_POST_INGRESS_COOKIE, ARP_POST_INGRESS_ONE_SWITCH_COOKIE] - if (sw.features.contains(NOVIFLOW_PUSH_POP_VXLAN) || sw.features.contains(KILDA_OVS_PUSH_POP_MATCH_VXLAN)) { + def unifiedCookies = [DROP_RULE_COOKIE, VERIFICATION_BROADCAST_RULE_COOKIE, + VERIFICATION_UNICAST_RULE_COOKIE, DROP_VERIFICATION_LOOP_RULE_COOKIE] + + + boolean isVxlanSupported = sw.features.contains(NOVIFLOW_PUSH_POP_VXLAN) || sw.features.contains(KILDA_OVS_PUSH_POP_MATCH_VXLAN) + + if (isVxlanSupported) { multiTableRules.addAll([LLDP_POST_INGRESS_VXLAN_COOKIE, ARP_POST_INGRESS_VXLAN_COOKIE]) + vxlanRules << VERIFICATION_UNICAST_VXLAN_RULE_COOKIE + } + + if (swProps.switchLldp) { + devicesRules.addAll([LLDP_INPUT_PRE_DROP_COOKIE, LLDP_TRANSIT_COOKIE, LLDP_INGRESS_COOKIE]) + } + if (swProps.switchArp) { + devicesRules.addAll([ARP_INPUT_PRE_DROP_COOKIE, ARP_TRANSIT_COOKIE, ARP_INGRESS_COOKIE]) } - northbound.get().getLinks(sw.dpId, null, null, null).each { - if (sw.features.contains(NOVIFLOW_PUSH_POP_VXLAN) || sw.features.contains(KILDA_OVS_PUSH_POP_MATCH_VXLAN)) { + + northbound.get().getSwitchFlows(sw.dpId).each { flow -> + [flow.source, flow.destination].findAll { ep -> ep.datapath == sw.dpId }.each { ep -> + multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_INGRESS_RULES, ep.portNumber).getValue()) + if (swProps.switchLldp || ep.detectConnectedDevices.lldp) { + devicesRules.add(new PortColourCookie(CookieType.LLDP_INPUT_CUSTOMER_TYPE, ep.portNumber).getValue()) + } + if (swProps.switchArp || ep.detectConnectedDevices.arp) { + devicesRules.add(new PortColourCookie(CookieType.ARP_INPUT_CUSTOMER_TYPE, ep.portNumber).getValue()) + } + } + } + + def relatedLinks = northbound.get().getLinks(sw.dpId, null, null, null) + relatedLinks.each { + if (isVxlanSupported) { multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_ISL_VXLAN_EGRESS_RULES, it.source.portNo).getValue()) multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_ISL_VXLAN_TRANSIT_RULES, it.source.portNo).getValue()) } multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_ISL_VLAN_EGRESS_RULES, it.source.portNo).getValue()) multiTableRules.add(new PortColourCookie(CookieType.PING_INPUT, it.source.portNo).getValue()) } - northbound.get().getSwitchFlows(sw.dpId).each { - if (it.source.datapath.equals(sw.dpId)) { - multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_INGRESS_RULES, it.source.portNumber).getValue()) - if (swProps.switchLldp || it.source.detectConnectedDevices.lldp) { - devicesRules.add(new PortColourCookie(CookieType.LLDP_INPUT_CUSTOMER_TYPE, it.source.portNumber).getValue()) - } - if (swProps.switchArp || it.source.detectConnectedDevices.arp) { - devicesRules.add(new PortColourCookie(CookieType.ARP_INPUT_CUSTOMER_TYPE, it.source.portNumber).getValue()) - } - } - if (it.destination.datapath.equals(sw.dpId)) { - multiTableRules.add(new PortColourCookie(CookieType.MULTI_TABLE_INGRESS_RULES, it.destination.portNumber).getValue()) - if (swProps.switchLldp || it.destination.detectConnectedDevices.lldp) { - devicesRules.add(new PortColourCookie(CookieType.LLDP_INPUT_CUSTOMER_TYPE, it.destination.portNumber).getValue()) - } - if (swProps.switchArp || it.destination.detectConnectedDevices.arp) { - devicesRules.add(new PortColourCookie(CookieType.ARP_INPUT_CUSTOMER_TYPE, it.destination.portNumber).getValue()) - } + + if ((toggles.server42IslRtt && doesSwSupportS42(swProps) && + swProps.server42IslRtt in ["ENABLED", "AUTO"] && !sw.features.contains(SwitchFeature.NOVIFLOW_COPY_FIELD))) { + devicesRules.add(SERVER_42_ISL_RTT_TURNING_COOKIE) + devicesRules.add(SERVER_42_ISL_RTT_OUTPUT_COOKIE) + relatedLinks.each { + devicesRules.add(new PortColourCookie(CookieType.SERVER_42_ISL_RTT_INPUT, it.source.portNo).getValue()) } } - if (swProps.switchLldp) { - devicesRules.addAll([LLDP_INPUT_PRE_DROP_COOKIE, LLDP_TRANSIT_COOKIE, LLDP_INGRESS_COOKIE]) - } - if (swProps.switchArp) { - devicesRules.addAll([ARP_INPUT_PRE_DROP_COOKIE, ARP_TRANSIT_COOKIE, ARP_INGRESS_COOKIE]) - } + if (swProps.server42FlowRtt) { server42Rules << SERVER_42_FLOW_RTT_OUTPUT_VLAN_COOKIE - if (sw.features.contains(NOVIFLOW_PUSH_POP_VXLAN) || sw.features.contains(KILDA_OVS_PUSH_POP_MATCH_VXLAN)) { + if (isVxlanSupported) { server42Rules << SERVER_42_FLOW_RTT_OUTPUT_VXLAN_COOKIE } } if (toggles.server42FlowRtt) { - if (sw.features.contains(SwitchFeature.NOVIFLOW_SWAP_ETH_SRC_ETH_DST) || - sw.features.contains(SwitchFeature.KILDA_OVS_SWAP_FIELD)) { + if (sw.features.contains(SwitchFeature.NOVIFLOW_SWAP_ETH_SRC_ETH_DST) || sw.features.contains(SwitchFeature.KILDA_OVS_SWAP_FIELD)) { server42Rules << SERVER_42_FLOW_RTT_TURNING_COOKIE server42Rules << SERVER_42_FLOW_RTT_VXLAN_TURNING_COOKIE } } - if (toggles.server42IslRtt && - swProps.server42Port != null && swProps.server42MacAddress != null && swProps.server42Vlan != null && - ("ENABLED".equals(swProps.server42IslRtt) || - "AUTO".equals(swProps.server42IslRtt) && - !sw.features.contains(SwitchFeature.NOVIFLOW_COPY_FIELD))) { - devicesRules.add(SERVER_42_ISL_RTT_TURNING_COOKIE) - devicesRules.add(SERVER_42_ISL_RTT_OUTPUT_COOKIE) - northbound.get().getLinks(sw.dpId, null, null, null).each { - devicesRules.add(new PortColourCookie(CookieType.SERVER_42_ISL_RTT_INPUT, it.source.portNo).getValue()) - } - } - if (sw.features.contains(NOVIFLOW_PUSH_POP_VXLAN) || sw.features.contains(KILDA_OVS_PUSH_POP_MATCH_VXLAN)) { - vxlanRules << VERIFICATION_UNICAST_VXLAN_RULE_COOKIE - } - def lacpPorts = northboundV2.get().getLagLogicalPort(sw.dpId).findAll { - it.lacpReply - } + def lacpPorts = northboundV2.get().getLagLogicalPort(sw.dpId).findAll { it.lacpReply } if (!lacpPorts.isEmpty()) { lacpRules << new ServiceCookie(ServiceCookieTag.DROP_SLOW_PROTOCOLS_LOOP_COOKIE).getValue() lacpPorts.each { @@ -301,23 +296,22 @@ class SwitchHelper { } } if (sw.noviflow && !sw.wb5164) { - return ([DROP_RULE_COOKIE, VERIFICATION_BROADCAST_RULE_COOKIE, - VERIFICATION_UNICAST_RULE_COOKIE, DROP_VERIFICATION_LOOP_RULE_COOKIE, - CATCH_BFD_RULE_COOKIE, ROUND_TRIP_LATENCY_RULE_COOKIE] - + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) + return ([CATCH_BFD_RULE_COOKIE, ROUND_TRIP_LATENCY_RULE_COOKIE] + + unifiedCookies + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) } else if ((sw.noviflow || sw.nbFormat().manufacturer == "E") && sw.wb5164) { - return ([DROP_RULE_COOKIE, VERIFICATION_BROADCAST_RULE_COOKIE, - VERIFICATION_UNICAST_RULE_COOKIE, DROP_VERIFICATION_LOOP_RULE_COOKIE, CATCH_BFD_RULE_COOKIE] - + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) + return ([CATCH_BFD_RULE_COOKIE] + + unifiedCookies + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) } else if (sw.ofVersion == "OF_12") { return [VERIFICATION_BROADCAST_RULE_COOKIE] } else { - return ([DROP_RULE_COOKIE, VERIFICATION_BROADCAST_RULE_COOKIE, - VERIFICATION_UNICAST_RULE_COOKIE, DROP_VERIFICATION_LOOP_RULE_COOKIE] - + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) + return (unifiedCookies + vxlanRules + multiTableRules + devicesRules + server42Rules + lacpRules) } } + static boolean doesSwSupportS42(SwitchPropertiesDto swProps) { + swProps.server42Port != null && swProps.server42MacAddress != null && swProps.server42Vlan != null + } + static List getDefaultMeters(Switch sw) { if (sw.ofVersion == "OF_12") { return [] diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy index 13ff85bb40..f7f33e6b24 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/QinQFlowSpec.groovy @@ -182,9 +182,10 @@ class QinQFlowSpec extends HealthCheckSpecification { def allSwitches = topology.activeSwitches involvedSwitchesforBothFlows.each { swId -> def sw = allSwitches.find { item -> item.dpId == swId } + def defaultCookies = sw.defaultCookies Wrappers.wait(RULES_INSTALLATION_TIME, 1) { assertThat(switchRulesFactory.get(swId).getRules()*.cookie.toArray()).as(swId.toString()) - .containsExactlyInAnyOrder(*sw.defaultCookies) + .containsExactlyInAnyOrder(*defaultCookies) } } @@ -206,6 +207,9 @@ class QinQFlowSpec extends HealthCheckSpecification { def "System allows to create a single switch QinQ flow\ [srcVlan:#srcVlanId, srcInnerVlan:#srcInnerVlanId, dstVlan:#dstVlanId, dstInnerVlan:#dstInnerVlanId, sw:#swPair.src.hwSwString]#trafficDisclaimer"() { + given: "Switch default cookies before flow creation have been collected" + def defaultCookies = swPair.src.defaultCookies + when: "Create a single switch QinQ flow" def qinqFlow = flowFactory.getBuilder(swPair) .withSourceVlan(srcVlanId) @@ -256,7 +260,7 @@ class QinQFlowSpec extends HealthCheckSpecification { then: "Flow rules are deleted" Wrappers.wait(RULES_INSTALLATION_TIME, 1) { assertThat(switchRulesFactory.get(swPair.src.dpId).getRules()*.cookie.toArray()) - .containsExactlyInAnyOrder(*swPair.src.defaultCookies) + .containsExactlyInAnyOrder(*defaultCookies) } switchRulesFactory.get(swPair.src.dpId).getRules().findAll { new Cookie(it.cookie).getType() == CookieType.SHARED_OF_FLOW @@ -319,6 +323,8 @@ class QinQFlowSpec extends HealthCheckSpecification { def "System allow to create/update/delete a protected QinQ flow via APIv1"() { given: "Two switches with enabled multi table mode" def swP = switchPairs.all().withAtLeastNNonOverlappingPaths(2).random() + def srcDefaultCookies = swP.src.defaultCookies + def dstDefaultCookies = swP.dst.defaultCookies when: "Create a QinQ flow" def flowEntity = flowFactory.getBuilder(swP) @@ -363,11 +369,12 @@ class QinQFlowSpec extends HealthCheckSpecification { flow.deleteV1() then: "Flows rules are deleted" - [swP.src, swP.dst].each { sw -> - Wrappers.wait(RULES_INSTALLATION_TIME, 1) { - assertThat(switchRulesFactory.get(sw.dpId).getRules()*.cookie.toArray()) - .containsExactlyInAnyOrder(*sw.defaultCookies) - } + Wrappers.wait(RULES_INSTALLATION_TIME, 1) { + assertThat(switchRulesFactory.get(swP.src.dpId).getRules()*.cookie.toArray()) + .containsExactlyInAnyOrder(*srcDefaultCookies) + assertThat(switchRulesFactory.get(swP.dst.dpId).getRules()*.cookie.toArray()) + .containsExactlyInAnyOrder(*dstDefaultCookies) + } and: "Shared rule of flow is deleted" @@ -478,9 +485,10 @@ class QinQFlowSpec extends HealthCheckSpecification { (srcVlanId: #srcVlanId, srcInnerVlanId: #srcInnerVlanId, dstVlanId: #dstVlanId, dstInnerVlanId: #dstInnerVlanId)"() { given: "A switch with enabled multiTable mode" def sw = topology.activeSwitches[0] + def defaultCookies = sw.defaultCookies when: "Create a single switch QinQ flow" - def qinqFlow = flowFactory.getBuilder(sw, sw) + def qinqFlow = flowFactory.getBuilder(sw, sw, false) .withSourceVlan(srcVlanId) .withSourceInnerVlan(srcInnerVlanId) .withDestinationVlan(dstVlanId) @@ -514,10 +522,9 @@ class QinQFlowSpec extends HealthCheckSpecification { qinqFlow.delete() then: "Flow rules are deleted" - def singleSw = topology.getActiveSwitches().find { it.dpId == sw.dpId } Wrappers.wait(RULES_INSTALLATION_TIME, 1) { - assertThat(switchRulesFactory.get(singleSw.dpId).getRules()*.cookie.toArray()).as(singleSw.dpId.toString()) - .containsExactlyInAnyOrder(*singleSw.defaultCookies) + assertThat(switchRulesFactory.get(sw.dpId).getRules()*.cookie.toArray()).as(sw.dpId.toString()) + .containsExactlyInAnyOrder(*defaultCookies) } where: @@ -650,9 +657,10 @@ class QinQFlowSpec extends HealthCheckSpecification { then: "Flows rules are deleted" involvedSwitchesforBothFlows.each { swId -> def sw = topology.getActiveSwitches().find { it.dpId == swId } + def defaultCookies = sw.defaultCookies Wrappers.wait(RULES_INSTALLATION_TIME, 1) { assertThat(switchRulesFactory.get(swId).getRules()*.cookie.toArray()).as(swId.toString()) - .containsExactlyInAnyOrder(*sw.defaultCookies) + .containsExactlyInAnyOrder(*defaultCookies) } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy index ee6878a69f..5334bab26a 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/DefaultRulesSpec.groovy @@ -212,7 +212,8 @@ class DefaultRulesSpec extends HealthCheckSpecification { Map data, Switch sw) { when: "Delete rules from the switch" def defaultRules = switchRulesFactory.get(sw.dpId).getRules() - assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() + def expectedDefaultCookies = sw.defaultCookies + assert defaultRules*.cookie.sort() == expectedDefaultCookies.sort() def deletedRules = switchHelper.deleteSwitchRules(sw.dpId, data.deleteRulesAction) then: "The corresponding rules are really deleted" @@ -226,13 +227,13 @@ class DefaultRulesSpec extends HealthCheckSpecification { verifyAll(northbound.validateSwitchRules(sw.dpId)) { missingRules == deletedRules excessRules.empty - properRules.sort() == sw.defaultCookies.findAll { it != data.cookie }.sort() + properRules.sort() == expectedDefaultCookies.findAll { it != data.cookie }.sort() } verifyAll(switchHelper.validateAndCollectFoundDiscrepancies(sw.dpId).get()) { rules.missing*.getCookie() == deletedRules rules.misconfigured.empty rules.excess.empty - rules.proper*.getCookie().sort() == sw.defaultCookies.findAll { it != data.cookie }.sort() + rules.proper*.getCookie().sort() == expectedDefaultCookies.findAll { it != data.cookie }.sort() } where: @@ -268,9 +269,10 @@ class DefaultRulesSpec extends HealthCheckSpecification { def "Able to delete default rule from #sw.hwSwString [delete-action=#data.deleteRulesAction]"(Map data, Switch sw) { when: "Delete rule from the switch" def defaultRules + def expectedDefaultCookies = sw.defaultCookies wait(RULES_INSTALLATION_TIME) { defaultRules = switchRulesFactory.get(sw.dpId).getRules() - assert defaultRules*.cookie.sort() == sw.defaultCookies.sort() + assert defaultRules*.cookie.sort() == expectedDefaultCookies.sort() } def deletedRules = switchHelper.deleteSwitchRules(sw.dpId, data.deleteRulesAction) @@ -285,13 +287,13 @@ class DefaultRulesSpec extends HealthCheckSpecification { verifyAll(northbound.validateSwitchRules(sw.dpId)) { missingRules == deletedRules excessRules.empty - properRules.sort() == sw.defaultCookies.findAll { it != data.cookie }.sort() + properRules.sort() == expectedDefaultCookies.findAll { it != data.cookie }.sort() } verifyAll(switchHelper.validateAndCollectFoundDiscrepancies(sw.dpId).get()) { rules.missing*.getCookie() == deletedRules rules.misconfigured.empty rules.excess.empty - rules.proper*.getCookie().sort() == sw.defaultCookies.findAll { it != data.cookie }.sort() + rules.proper*.getCookie().sort() == expectedDefaultCookies.findAll { it != data.cookie }.sort() } where: @@ -346,16 +348,17 @@ class DefaultRulesSpec extends HealthCheckSpecification { } and: "Switch and rules validation shows that corresponding rule is missing" + def defaultCookiesWithoutMissingS42Rule = sw.defaultCookies.findAll { it != SERVER_42_FLOW_RTT_TURNING_COOKIE }.sort() verifyAll(northbound.validateSwitchRules(sw.dpId)) { missingRules == [SERVER_42_FLOW_RTT_TURNING_COOKIE] excessRules.empty - properRules.sort() == sw.defaultCookies.findAll { it != SERVER_42_FLOW_RTT_TURNING_COOKIE }.sort() + properRules.sort() == defaultCookiesWithoutMissingS42Rule } verifyAll(switchHelper.validateAndCollectFoundDiscrepancies(sw.dpId).get()) { rules.missing*.getCookie() == [SERVER_42_FLOW_RTT_TURNING_COOKIE] rules.misconfigured.empty rules.excess.empty - rules.proper*.getCookie().sort() == sw.defaultCookies.findAll { it != SERVER_42_FLOW_RTT_TURNING_COOKIE }.sort() + rules.proper*.getCookie().sort() == defaultCookiesWithoutMissingS42Rule } when: "Install the server42 turning rule" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy index 574b021eaf..9597875b32 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/FlowRulesSpec.groovy @@ -765,6 +765,7 @@ class FlowRulesSpec extends HealthCheckSpecification { } List getFlowRules(Switch sw) { - switchRulesFactory.get(sw.dpId).getRules().findAll { !(it.cookie in sw.defaultCookies) }.sort() + def defaultCookies = sw.defaultCookies + switchRulesFactory.get(sw.dpId).getRules().findAll { !(it.cookie in defaultCookies) }.sort() } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy index c704d6b4e5..d6ba5bb4bc 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchSyncSpec.groovy @@ -101,8 +101,9 @@ class SwitchSyncSpec extends HealthCheckSpecification { .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def involvedSwitchIds = involvedSwitches*.getDpId() def cookiesMap = involvedSwitches.collectEntries { sw -> + def defaultCookies = sw.defaultCookies [sw.dpId, northbound.getSwitchRules(sw.dpId).flowEntries.findAll { - !(it.cookie in sw.defaultCookies) + !(it.cookie in defaultCookies) }*.cookie] } Map> metersMap = involvedSwitches.collectEntries { sw -> @@ -238,8 +239,9 @@ class SwitchSyncSpec extends HealthCheckSpecification { def involvedSwitchIds = involvedSwitches*.getDpId() def transitSwitchIds = involvedSwitches[1..-2]*.dpId def cookiesMap = involvedSwitches.collectEntries { sw -> + def defaultCookies = sw.defaultCookies [sw.dpId, northbound.getSwitchRules(sw.dpId).flowEntries.findAll { - !(it.cookie in sw.defaultCookies) && !new Cookie(it.cookie).serviceFlag + !(it.cookie in defaultCookies) && !new Cookie(it.cookie).serviceFlag }*.cookie] } def metersMap = involvedSwitches.collectEntries { sw -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy index 6740772dea..62b27796e6 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationSpec.groovy @@ -689,8 +689,9 @@ misconfigured" .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def transitSwitchIds = involvedSwitches[1..-2].dpId def cookiesMap = involvedSwitches.collectEntries { sw -> + def defaultCookies = sw.defaultCookies [sw.dpId, switchRulesFactory.get(sw.dpId).getRules().findAll { - !(it.cookie in sw.defaultCookies) && !new Cookie(it.cookie).serviceFlag + !(it.cookie in defaultCookies) && !new Cookie(it.cookie).serviceFlag }*.cookie] } def metersMap = involvedSwitches.collectEntries { sw -> diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy index cdd6c78f4d..883d4981a8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/switches/SwitchValidationV2Spec.groovy @@ -705,8 +705,9 @@ misconfigured" .collect { [it.srcSwitch, it.dstSwitch] }.flatten().unique() as List def transitSwitchIds = involvedSwitches[1..-2]*.dpId def cookiesMap = involvedSwitches.collectEntries { sw -> + def defaultCookies = sw.defaultCookies [sw.dpId, switchRulesFactory.get(sw.dpId).getRules().findAll { - !(it.cookie in sw.defaultCookies) && !new Cookie(it.cookie).serviceFlag + !(it.cookie in defaultCookies) && !new Cookie(it.cookie).serviceFlag }*.cookie] } def metersMap = involvedSwitches.collectEntries { sw -> From 8cc02082d426e8d12f7b891c904daffe73a2f8f4 Mon Sep 17 00:00:00 2001 From: Ivan Chupin Date: Wed, 27 Nov 2024 11:21:31 +0000 Subject: [PATCH 16/21] added context menu fix to copy some cell values for datatable components , fix column width for columns in flow list page, switch list page, isl list page. added missing styles to angular.json for perfectmemory lib. Switch detail -> flows table fix, added copy to clipboard feature for switch columns --- src-gui/ui/angular.json | 2 + .../flow-datatables.component.html | 52 +- .../flow-datatables.component.ts | 751 ++++++++++-------- .../isl/datatable/datatable.component.ts | 10 +- .../switch-datatable.component.html | 7 +- .../switch-datatable.component.ts | 6 +- .../switch-flows/switch-flows.component.html | 34 +- .../switch-flows/switch-flows.component.ts | 20 +- src-gui/ui/src/styles.css | 2 +- 9 files changed, 468 insertions(+), 416 deletions(-) diff --git a/src-gui/ui/angular.json b/src-gui/ui/angular.json index 4aff44dde5..7853b49f45 100644 --- a/src-gui/ui/angular.json +++ b/src-gui/ui/angular.json @@ -26,6 +26,8 @@ "src/assets" ], "styles": [ + "@angular/cdk/overlay-prebuilt.css", + "node_modules/@perfectmemory/ngx-contextmenu/src/assets/stylesheets/base.scss", "node_modules/bootstrap/dist/css/bootstrap.min.css", "node_modules/font-awesome/css/font-awesome.css", "node_modules/datatables.net-dt/css/jquery.dataTables.css", diff --git a/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.html b/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.html index d4674df305..b02047a76b 100644 --- a/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.html +++ b/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.html @@ -26,9 +26,7 @@ - - Src Switch ID Src Port @@ -51,9 +49,7 @@ - - Dst Switch ID Dst Port @@ -68,8 +64,6 @@ - - @@ -96,26 +90,6 @@ - - - - - Created - - - - - - - - - type @@ -130,7 +104,7 @@ - + {{row.flowid || "-"}} @@ -138,46 +112,40 @@ - + {{row.y_flow_id || "-"}} - + Copy to Clipboard - - {{row.source_switch_name || "-"}} + + {{row.source_switch || "-"}} - + Copy to Clipboard - {{row.source_switch || "-"}} {{row.src_port || "-"}} {{row.src_vlan || "-"}} - - {{row.target_switch_name || "-"}} + + {{row.target_switch || "-"}} - + Copy to Clipboard - {{row.target_switch || "-"}} {{row.dst_port || "-"}} {{row.dst_vlan || "-"}} {{row.maximum_bandwidth / 1000 || "-"}} {{ row.status || row.state || "-"}} {{row.description || "-"}} - {{row['created'] | date:'yyyy/MM/dd H:mm:s'}} - - {{ descrepancyString(row) }} + {{ descrepancyString(row) }} - - diff --git a/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.ts b/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.ts index 24262433d5..8df016fd88 100644 --- a/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.ts +++ b/src-gui/ui/src/app/modules/flows/flow-datatables/flow-datatables.component.ts @@ -1,390 +1,441 @@ -import { Component, OnInit, Input, ViewChild, OnChanges, SimpleChange, EventEmitter, SimpleChanges, Renderer2, AfterViewInit, OnDestroy, Output } from '@angular/core'; -import { DataTableDirective } from 'angular-datatables'; -import { LoaderService } from 'src/app/common/services/loader.service'; -import { Subject } from 'rxjs'; -import { Flow } from 'src/app/common/data-models/flow'; -import { Router } from '@angular/router'; -import { CommonService } from 'src/app/common/services/common.service'; -import { FormBuilder } from '@angular/forms'; -import { ClipboardService } from 'ngx-clipboard'; -import { FlowReRouteModalComponent } from 'src/app/common/components/flow-re-route-modal/flow-re-route-modal.component'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { FlowsService } from 'src/app/common/services/flows.service'; +import { + Component, + OnInit, + Input, + ViewChild, + OnChanges, + SimpleChange, + EventEmitter, + SimpleChanges, + Renderer2, + AfterViewInit, + OnDestroy, + Output +} from '@angular/core'; +import {DataTableDirective} from 'angular-datatables'; +import {LoaderService} from 'src/app/common/services/loader.service'; +import {Subject} from 'rxjs'; +import {Flow} from 'src/app/common/data-models/flow'; +import {Router} from '@angular/router'; +import {CommonService} from 'src/app/common/services/common.service'; +import {FormBuilder} from '@angular/forms'; +import {ClipboardService} from 'ngx-clipboard'; +import {FlowReRouteModalComponent} from 'src/app/common/components/flow-re-route-modal/flow-re-route-modal.component'; +import {NgbModal, NgbModalRef} from '@ng-bootstrap/ng-bootstrap'; +import {FlowsService} from 'src/app/common/services/flows.service'; + declare var jQuery: any; -import { MessageObj } from 'src/app/common/constants/constants'; +import {MessageObj} from 'src/app/common/constants/constants'; @Component({ - selector: 'app-flow-datatables', - templateUrl: './flow-datatables.component.html', - styleUrls: ['./flow-datatables.component.css'] + selector: 'app-flow-datatables', + templateUrl: './flow-datatables.component.html', + styleUrls: ['./flow-datatables.component.css'] }) export class FlowDatatablesComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { - @ViewChild(DataTableDirective, { static: true }) datatableElement: DataTableDirective; - @Input() data = []; - @Input() srcSwitch: string; - @Input() dstSwitch: string; - @Input() filterFlag: string; - @Input() textSearch: any; - @Output() refresh = new EventEmitter(); - @Output() enableReroute = new EventEmitter(); - - - typeFilter = ''; - dtOptions = {}; - reRouteFlowIndex = {}; - reRouteList: any = []; - checkedFlow = []; - selectAll = false; - dtTrigger: Subject = new Subject(); - - wrapperHide = true; - expandedSrcSwitchName = false; - expandedSrcSwitchPort = false; - expandedSrcSwitchVlan = false; - - expandedTargetSwitchName = false; - expandedTargetSwitchPort = false; - expandedTargetSwitchVlan = false; - - expandedBandwidth = false; - expandedFlowId = false; - expandedYFlowId = false; - expandedState = false; - expandedStatus = false; - expandedDescription = false; - expandedCreated = false; - storeLinkSetting = false; - loadFilter = false; - hasDownFLows = false; - activeStatus: any = ''; - clipBoardItems = []; - - constructor(private loaderService: LoaderService, private renderer: Renderer2, private router: Router, - public commonService: CommonService, - private flowService: FlowsService, - private clipboardService: ClipboardService, - private modalService: NgbModal, - private formBuilder: FormBuilder) { - this.wrapperHide = false; - const storeSetting = localStorage.getItem('haslinkStoreSetting') || false; - this.storeLinkSetting = storeSetting && storeSetting == '1' ? true : false; - } - ngOnInit() { - const ref = this; - this.dtOptions = { - pageLength: 10, - deferRender: true, - info: true, - dom: 'tpli', - 'aLengthMenu': [[10, 20, 35, 50, -1], [10, 20, 35, 50, 'All']], - retrieve: true, - autoWidth: false, - colResize: false, - stateSave: false, - 'order': [], - language: { - searchPlaceholder: 'Search' - }, - buttons: { - buttons: [ - { extend: 'csv', text: 'Export', className: 'btn btn-dark' } - ] - }, - drawCallback: function() { - if (jQuery('#flowDataTable tbody tr').length < 10) { - jQuery('#flowDataTable_next').addClass('disabled'); - } else { - jQuery('#flowDataTable_next').removeClass('disabled'); - } - }, - 'aoColumns': [ - { sWidth: '7%' , 'bSortable': false}, - { sWidth: '15%' }, - { sWidth: '10%' }, - { sWidth: '13%', 'sType': 'name', 'bSortable': true }, - { sWidth: '8%' }, - { sWidth: '8%' }, - { sWidth: '9%' }, - { sWidth: '13%', 'sType': 'name', 'bSortable': true }, - { sWidth: '8%' }, - { sWidth: '8%' }, - { sWidth: '9%' }, - { sWidth: '10%' }, - { sWidth: '10%' }, - { sWidth: '10%' }, - { sWidth: '10%' }, - { sWidth: '1%' , 'bSortable': false}, - { sWidth: '10%' , 'bSortable': false}, - - ], - columnDefs: [ - { - 'targets': [ 0], - 'visible': ref.commonService.hasPermission('fw_permission_reroute'), - 'searchable': false - }, - { - 'targets': [ 3], - 'visible': false, - 'searchable': true - }, - { - 'targets': [ 7 ], - 'visible': false, - 'searchable': true - }, - { 'targets': [14], 'visible': false}, - ], - initComplete: function( settings, json ) { - setTimeout(function() { - ref.loaderService.hide(); - ref.wrapperHide = true; - }, ref.data.length / 2); - } - }; - } - - ngOnChanges(change: SimpleChanges) { - const ref = this; - if ( typeof(change.data) != 'undefined' && change.data) { - if (typeof(change.data) !== 'undefined' && change.data.currentValue) { - this.data = change.data.currentValue; - this.data.forEach(function(d) { - if (d.status == 'DOWN' || d.status == 'DEGRADED') { - ref.hasDownFLows = true; - ref.checkedFlow[d.flowid] = false; - } - }); - this.clipBoardItems = this.data; - } + @ViewChild(DataTableDirective, {static: true}) datatableElement: DataTableDirective; + @Input() data = []; + @Input() srcSwitch: string; + @Input() dstSwitch: string; + @Input() filterFlag: string; + @Input() textSearch: any; + @Output() refresh = new EventEmitter(); + @Output() enableReroute = new EventEmitter(); + + + typeFilter = ''; + dtOptions = {}; + reRouteFlowIndex = {}; + reRouteList: any = []; + checkedFlow = []; + selectAll = false; + dtTrigger: Subject = new Subject(); + + wrapperHide = true; + expandedSrcSwitchName = false; + expandedSrcSwitchPort = false; + expandedSrcSwitchVlan = false; + + expandedTargetSwitchName = false; + expandedTargetSwitchPort = false; + expandedTargetSwitchVlan = false; + + expandedBandwidth = false; + expandedFlowId = false; + expandedYFlowId = false; + expandedState = false; + expandedStatus = false; + expandedDescription = false; + expandedCreated = false; + storeLinkSetting = false; + loadFilter = false; + hasDownFLows = false; + activeStatus: any = ''; + clipBoardItems = []; + + constructor(private loaderService: LoaderService, private renderer: Renderer2, private router: Router, + public commonService: CommonService, + private flowService: FlowsService, + private clipboardService: ClipboardService, + private modalService: NgbModal, + private formBuilder: FormBuilder) { + this.wrapperHide = false; + const storeSetting = localStorage.getItem('haslinkStoreSetting') || false; + this.storeLinkSetting = storeSetting && storeSetting == '1' ? true : false; } - if (typeof(change.textSearch) !== 'undefined' && change.textSearch.currentValue) { - this.fulltextSearch(change.textSearch.currentValue); + + ngOnInit() { + const ref = this; + this.dtOptions = { + pageLength: 10, + deferRender: true, + info: true, + dom: 'tpli', + 'aLengthMenu': [[10, 20, 35, 50, -1], [10, 20, 35, 50, 'All']], + retrieve: true, + autoWidth: false, + colResize: false, + stateSave: false, + scrollX: true, + 'order': [], + language: { + searchPlaceholder: 'Search' + }, + buttons: { + buttons: [ + {extend: 'csv', text: 'Export', className: 'btn btn-dark'} + ] + }, + drawCallback: function () { + if (jQuery('#flowDataTable tbody tr').length < 10) { + jQuery('#flowDataTable_next').addClass('disabled'); + } else { + jQuery('#flowDataTable_next').removeClass('disabled'); + } + }, + columnDefs: [ + { + 'targets': [0], + 'visible': ref.commonService.hasPermission('fw_permission_reroute'), + 'searchable': false, + 'bSortable': false, + 'sWidth':'70px' + }, + { + 'targets': [1], + 'sWidth':'200px' + }, + { + 'targets': [2], + 'sWidth':'200px' + }, + { + 'targets': [3], + 'sType': 'name', + 'sWidth':'180px' + }, + { + 'targets': [4], + 'sWidth':'110px' + }, + { + 'targets': [5], + 'sWidth':'110px' + }, + { + 'targets': [6], + 'sType': 'name', + 'sWidth':'180px' + }, + { + 'targets': [7], + 'sWidth':'110px' + }, + { + 'targets': [8], + 'sWidth':'110px' + }, + { + 'targets': [9], + 'sWidth':'165px' + }, + { + 'targets': [10], + 'sWidth':'100px' + }, + { + 'targets': [11], + 'sWidth':'200px' + }, + { + 'targets': [12], + 'sWidth':'170px' + }, + { + 'targets': [13], + 'searchable': false, + 'bSortable': false, + 'sWidth':'90px' + }, + ], + initComplete: function (settings, json) { + setTimeout(function () { + ref.loaderService.hide(); + ref.wrapperHide = true; + }, ref.data.length / 2); + } + }; } - if (typeof(change.srcSwitch) !== 'undefined' && change.srcSwitch.currentValue) { - this.expandedSrcSwitchName = true; - } else { - this.expandedSrcSwitchName = false; + + ngOnChanges(change: SimpleChanges) { + const ref = this; + if (typeof (change.data) != 'undefined' && change.data) { + if (typeof (change.data) !== 'undefined' && change.data.currentValue) { + this.data = change.data.currentValue; + this.data.forEach(function (d) { + if (d.status == 'DOWN' || d.status == 'DEGRADED') { + ref.hasDownFLows = true; + ref.checkedFlow[d.flowid] = false; + } + }); + this.clipBoardItems = this.data; + } + } + if (typeof (change.textSearch) !== 'undefined' && change.textSearch.currentValue) { + this.fulltextSearch(change.textSearch.currentValue); + } + if (typeof (change.srcSwitch) !== 'undefined' && change.srcSwitch.currentValue) { + this.expandedSrcSwitchName = true; + } else { + this.expandedSrcSwitchName = false; + } + if (typeof (change.dstSwitch) != 'undefined' && change.dstSwitch.currentValue) { + this.expandedTargetSwitchName = true; + } else { + this.expandedTargetSwitchName = false; + } + + this.triggerSearch(); } - if (typeof(change.dstSwitch) != 'undefined' && change.dstSwitch.currentValue) { - this.expandedTargetSwitchName = true; - } else { - this.expandedTargetSwitchName = false; + + loadFilters() { + this.loadFilter = !this.loadFilter; } - this.triggerSearch(); - } - loadFilters() { - this.loadFilter = ! this.loadFilter; - } + fulltextSearch(value: any) { + if (this.dtTrigger) { + this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => { + dtInstance.search(value) + .draw(); + }); + } + } - fulltextSearch(value: any) { - if (this.dtTrigger) { + ngAfterViewInit() { + this.dtTrigger.next(); this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => { - dtInstance.search(value) - .draw(); - }); - } - } - - ngAfterViewInit() { - this.dtTrigger.next(); - this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => { - dtInstance.columns().every(function () { - const that = this; - $('input[type="search"]', this.header()).on('keyup change', function () { - if (that.search() !== this['value']) { - that - .search(this['value']) - .draw(); - } + dtInstance.columns().every(function () { + const that = this; + $('input[type="search"]', this.header()).on('keyup change', function () { + if (that.search() !== this['value']) { + that + .search(this['value']) + .draw(); + } + }); + }); }); - }); - }); - } - - toggleSearch(e, inputContainer) { - - this[inputContainer] = !this[inputContainer]; - if (this[inputContainer]) { - setTimeout(() => { - this.renderer.selectRootElement('#' + inputContainer).focus(); - }); - } else { - setTimeout(() => { - this.renderer.selectRootElement('#' + inputContainer).value = ''; - jQuery('#' + inputContainer).trigger('change'); - }); } - event.stopPropagation(); - } - - stopPropagationmethod(e) { - event.stopPropagation(); - if (e.key === 'Enter') { - return false; - } - } - - triggerSearch() { - setTimeout(() => { - jQuery('#expandedSrcSwitchName').trigger('change'); - jQuery('#expandedTargetSwitchName').trigger('change'); - }, 1000); - } - - showFlow(flowObj: Flow) { - localStorage.setItem('filterFlag', this.filterFlag); - this.router.navigate(['/flows/details/' + flowObj.flowid]); - } - - - ngOnDestroy(): void { - this.dtTrigger.unsubscribe(); - } - - descrepancyString(row) { - const text = []; - if (row.hasOwnProperty('controller-flow')) { - if (row['controller-flow']) { - text.push('controller:true'); + + toggleSearch(e, inputContainer) { + + this[inputContainer] = !this[inputContainer]; + if (this[inputContainer]) { + setTimeout(() => { + this.renderer.selectRootElement('#' + inputContainer).focus(); + }); } else { - text.push('controller:false'); + setTimeout(() => { + this.renderer.selectRootElement('#' + inputContainer).value = ''; + jQuery('#' + inputContainer).trigger('change'); + }); } - } else { - text.push('controller:false'); + event.stopPropagation(); } - if (row.hasOwnProperty('inventory-flow')) { - if (row['inventory-flow']) { - text.push('inventory:true'); - } else { - text.push('inventory:false'); - } - } else { - text.push('inventory:false'); + stopPropagationmethod(e) { + event.stopPropagation(); + if (e.key === 'Enter') { + return false; + } } - return text.join(', '); - } + triggerSearch() { + setTimeout(() => { + jQuery('#expandedSrcSwitchName').trigger('change'); + jQuery('#expandedTargetSwitchName').trigger('change'); + }, 1000); + } + showFlow(flowObj: Flow) { + localStorage.setItem('filterFlag', this.filterFlag); + this.router.navigate(['/flows/details/' + flowObj.flowid]); + } - copyToClip(event, copyItem, index) { - copyItem = this.clipBoardItems[index][copyItem]; - this.clipboardService.copyFromContent(copyItem); - } - /* Re-routing down flows ***/ + ngOnDestroy(): void { + this.dtTrigger.unsubscribe(); + } - loadFlowReRouteModal() { - const modelRef = this.modalService.open(FlowReRouteModalComponent, { size: 'lg', windowClass: 'modal-isl slideInUp', backdrop: 'static', keyboard: false }); - modelRef.componentInstance.title = MessageObj.re_routing_flows; - modelRef.componentInstance.reRouteIndex = this.reRouteFlowIndex; - modelRef.componentInstance.responseData = this.reRouteList; - modelRef.result.then(() => { - this.refreshList(); - }); -} + descrepancyString(row) { + const text = []; + if (row.hasOwnProperty('controller-flow')) { + if (row['controller-flow']) { + text.push('controller:true'); + } else { + text.push('controller:false'); + } + } else { + text.push('controller:false'); + } -refreshList() { - this.refresh.emit(); -} + if (row.hasOwnProperty('inventory-flow')) { + if (row['inventory-flow']) { + text.push('inventory:true'); + } else { + text.push('inventory:false'); + } + } else { + text.push('inventory:false'); + } -enableRerouteFlow(flag) { - this.enableReroute.emit({flag: flag}); -} + return text.join(', '); + } -selectAllFlows(e) { - this.selectAll = !this.selectAll; - if (this.checkedFlow && Object.keys(this.checkedFlow).length) { - Object.keys(this.checkedFlow).forEach((k, i) => { this.checkedFlow[k] = this.selectAll; }); - } - this.enableRerouteFlow(this.selectAll); -} -toggleSelection(flow) { - let re_routeFlag = false; - this.checkedFlow[flow.flowid] = !this.checkedFlow[flow.flowid]; - if (this.checkedFlow && Object.keys(this.checkedFlow).length) { - let selectAll = true; - Object.keys(this.checkedFlow).forEach((k, i) => { - if (!this.checkedFlow[k]) { - selectAll = false; - return false; - } else { - re_routeFlag = true; - } - }); - this.selectAll = selectAll; - } - this.enableRerouteFlow(re_routeFlag); + copyToClip(event, copyItem, index) { + copyItem = this.clipBoardItems[index][copyItem]; + this.clipboardService.copyFromContent(copyItem); + } -} + /* Re-routing down flows ***/ -reRouteFlows() { - this.reRouteFlowIndex = {}; - const selectedFlows = []; - Object.keys(this.checkedFlow).forEach((k, i) => { - if (this.checkedFlow[k]) { - selectedFlows.push(k); + loadFlowReRouteModal() { + const modelRef = this.modalService.open(FlowReRouteModalComponent, { + size: 'lg', + windowClass: 'modal-isl slideInUp', + backdrop: 'static', + keyboard: false + }); + modelRef.componentInstance.title = MessageObj.re_routing_flows; + modelRef.componentInstance.reRouteIndex = this.reRouteFlowIndex; + modelRef.componentInstance.responseData = this.reRouteList; + modelRef.result.then(() => { + this.refreshList(); + }); + } + + refreshList() { + this.refresh.emit(); + } + + enableRerouteFlow(flag) { + this.enableReroute.emit({flag: flag}); } - }); - if (selectedFlows && selectedFlows.length) { - this.loadFlowReRouteModal(); - const flowID = selectedFlows.pop(); - this.reRouteFlowIndex[flowID] = {type: 'info'}; - this.reRouteFlow(flowID, selectedFlows); - } -} -reRouteFlow(flowID, flowList) { - const self = this; - if (flowID) { - this.reRouteList.push(flowID); - this.reRouteFlowIndex[flowID]['progress'] = 10; - this.reRouteFlowIndex[flowID]['interval'] = setInterval(() => { - if (this.reRouteFlowIndex[flowID]['progress'] <= 90) { - this.reRouteFlowIndex[flowID]['progress'] = this.reRouteFlowIndex[flowID]['progress'] + 10; + selectAllFlows(e) { + this.selectAll = !this.selectAll; + if (this.checkedFlow && Object.keys(this.checkedFlow).length) { + Object.keys(this.checkedFlow).forEach((k, i) => { + this.checkedFlow[k] = this.selectAll; + }); } - }, 300); - this.flowService.getReRoutedPath(flowID).subscribe(function(data: any) { - if (data && typeof(data.rerouted) !== 'undefined' && data.rerouted) { - clearInterval( self.reRouteFlowIndex[flowID]['interval']); - self.reRouteFlowIndex[flowID]['type'] = 'success'; - self.reRouteFlowIndex[flowID]['progress'] = 100; - self.reRouteFlowIndex[flowID]['message'] = MessageObj.flow_rerouted; - } else { - clearInterval(self.reRouteFlowIndex[flowID]['interval']); - self.reRouteFlowIndex[flowID]['type'] = 'success'; - self.reRouteFlowIndex[flowID]['progress'] = 100; - self.reRouteFlowIndex[flowID]['message'] = MessageObj.flow_on_best_route; - } - if (flowList && flowList.length) { - const flow_id = flowList.pop(); - self.reRouteFlowIndex[flow_id] = {type: 'info'}; - self.reRouteFlow(flow_id, flowList); - } else { - return; - } + this.enableRerouteFlow(this.selectAll); + } - }, function(error) { - clearInterval(self.reRouteFlowIndex[flowID]['interval']); - self.reRouteFlowIndex[flowID]['type'] = 'danger'; - self.reRouteFlowIndex[flowID]['progress'] = 100; - self.reRouteFlowIndex[flowID]['message'] = error.error['error-auxiliary-message']; - self.reRouteFlowIndex[flowID]['description'] = error.error['error-description']; - if (flowList && flowList.length) { - const flow_id = flowList.pop(); - self.reRouteFlowIndex[flow_id] = {type: 'info'}; - self.reRouteFlow(flow_id, flowList); - } else { - return; + toggleSelection(flow) { + let re_routeFlag = false; + this.checkedFlow[flow.flowid] = !this.checkedFlow[flow.flowid]; + if (this.checkedFlow && Object.keys(this.checkedFlow).length) { + let selectAll = true; + Object.keys(this.checkedFlow).forEach((k, i) => { + if (!this.checkedFlow[k]) { + selectAll = false; + return false; + } else { + re_routeFlag = true; + } + }); + this.selectAll = selectAll; + } + this.enableRerouteFlow(re_routeFlag); + + } + + reRouteFlows() { + this.reRouteFlowIndex = {}; + const selectedFlows = []; + Object.keys(this.checkedFlow).forEach((k, i) => { + if (this.checkedFlow[k]) { + selectedFlows.push(k); } - }); + }); + if (selectedFlows && selectedFlows.length) { + this.loadFlowReRouteModal(); + const flowID = selectedFlows.pop(); + this.reRouteFlowIndex[flowID] = {type: 'info'}; + this.reRouteFlow(flowID, selectedFlows); + } } -} + reRouteFlow(flowID, flowList) { + const self = this; + if (flowID) { + this.reRouteList.push(flowID); + this.reRouteFlowIndex[flowID]['progress'] = 10; + this.reRouteFlowIndex[flowID]['interval'] = setInterval(() => { + if (this.reRouteFlowIndex[flowID]['progress'] <= 90) { + this.reRouteFlowIndex[flowID]['progress'] = this.reRouteFlowIndex[flowID]['progress'] + 10; + } + }, 300); + this.flowService.getReRoutedPath(flowID).subscribe(function (data: any) { + if (data && typeof (data.rerouted) !== 'undefined' && data.rerouted) { + clearInterval(self.reRouteFlowIndex[flowID]['interval']); + self.reRouteFlowIndex[flowID]['type'] = 'success'; + self.reRouteFlowIndex[flowID]['progress'] = 100; + self.reRouteFlowIndex[flowID]['message'] = MessageObj.flow_rerouted; + } else { + clearInterval(self.reRouteFlowIndex[flowID]['interval']); + self.reRouteFlowIndex[flowID]['type'] = 'success'; + self.reRouteFlowIndex[flowID]['progress'] = 100; + self.reRouteFlowIndex[flowID]['message'] = MessageObj.flow_on_best_route; + } + if (flowList && flowList.length) { + const flow_id = flowList.pop(); + self.reRouteFlowIndex[flow_id] = {type: 'info'}; + self.reRouteFlow(flow_id, flowList); + } else { + return; + } + + }, function (error) { + clearInterval(self.reRouteFlowIndex[flowID]['interval']); + self.reRouteFlowIndex[flowID]['type'] = 'danger'; + self.reRouteFlowIndex[flowID]['progress'] = 100; + self.reRouteFlowIndex[flowID]['message'] = error.error['error-auxiliary-message']; + self.reRouteFlowIndex[flowID]['description'] = error.error['error-description']; + if (flowList && flowList.length) { + const flow_id = flowList.pop(); + self.reRouteFlowIndex[flow_id] = {type: 'info'}; + self.reRouteFlow(flow_id, flowList); + } else { + return; + } + }); + } + + } - /** End re-routing down flows *** */ + /** End re-routing down flows *** */ } diff --git a/src-gui/ui/src/app/modules/isl/datatable/datatable.component.ts b/src-gui/ui/src/app/modules/isl/datatable/datatable.component.ts index 9ebfa33aa4..31f50528e2 100644 --- a/src-gui/ui/src/app/modules/isl/datatable/datatable.component.ts +++ b/src-gui/ui/src/app/modules/isl/datatable/datatable.component.ts @@ -134,19 +134,19 @@ export class DatatableComponent implements OnDestroy, OnInit, AfterViewInit, OnC jQuery('#isl-list-table_next').removeClass('disabled'); } }, 'aoColumns': [ - { sWidth: '14%', 'sType': 'name', 'bSortable': true }, + { sWidth: '20%', 'sType': 'name', 'bSortable': true }, { sWidth: '8%' }, { sWidth: '8%' }, - { sWidth: '14%' }, + { sWidth: '19%' }, { sWidth: '8%' }, { sWidth: '8%' }, { sWidth: '7%' }, { sWidth: '12%' }, - { sWidth: '12%' }, - { sWidth: '12%' }, - { sWidth: '12%' }, { sWidth: '8%' }, { sWidth: '8%' }, + { sWidth: '8%' }, + { sWidth: '9%' }, + { sWidth: '8%' }, { sWidth: '8%' } ], 'columnDefs': [ diff --git a/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.html b/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.html index bd385b2ef7..778a732181 100644 --- a/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.html +++ b/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.html @@ -114,8 +114,13 @@ {{ checkValue(row.address) }} - + {{ checkValue(row.hostname) }} + + + Copy to Clipboard + + diff --git a/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.ts b/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.ts index 4060d282e4..3256f2fb28 100644 --- a/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.ts +++ b/src-gui/ui/src/app/modules/switches/switch-datatable/switch-datatable.component.ts @@ -86,14 +86,14 @@ export class SwitchDatatableComponent implements OnInit, OnChanges, OnDestroy, A } }, 'aoColumns': [ - {sWidth: '10%'}, + {sWidth: '16%'}, {sWidth: '10%', 'sType': 'name', 'bSortable': true}, {sWidth: '10%'}, {sWidth: '10%'}, + {sWidth: '10%'}, // no {sWidth: '10%'}, {sWidth: '10%'}, - {sWidth: '15%'}, - {sWidth: '25%'}, + {sWidth: '20%'}, {sWidth: '10%'} ], language: { diff --git a/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.html b/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.html index 3fb35ab7d5..d649a89fbc 100644 --- a/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.html +++ b/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.html @@ -90,22 +90,38 @@ - - {{row.flowid || "-"}} - + + {{row.flowid || "-"}} + + + Copy to Clipboard + + - + {{row.source_switch_name || "-"}} - + + + Copy to Clipboard + + + + + {{row.source_switch || "-"}} - {{row.source_switch || "-"}} {{row.src_port || "-"}} {{row.src_vlan || "-"}} - + {{row.target_switch_name || "-"}} - + + + Copy to Clipboard + + - {{row.target_switch || "-"}} + + {{row.target_switch || "-"}} + {{row.dst_port || "-"}} {{row.dst_vlan || "-"}} {{row.maximum_bandwidth / 1000 || "-"}} diff --git a/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.ts b/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.ts index 44d3c71c18..ac9d35417c 100644 --- a/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.ts +++ b/src-gui/ui/src/app/modules/switches/switch-flows/switch-flows.component.ts @@ -8,6 +8,7 @@ import { MessageObj } from 'src/app/common/constants/constants'; import { FlowsService } from 'src/app/common/services/flows.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ToastrService } from 'ngx-toastr'; +import {ClipboardService} from "ngx-clipboard"; declare var jQuery: any; @Component({ @@ -46,6 +47,8 @@ export class SwitchFlowsComponent implements OnDestroy, OnInit, OnChanges, After expandedState = false; expandedStatus = false; expandedDescription = false; + clipBoardItems = []; + constructor( private renderer: Renderer2, private loaderService: LoaderService, @@ -53,6 +56,7 @@ export class SwitchFlowsComponent implements OnDestroy, OnInit, OnChanges, After private route: ActivatedRoute, private flowService: FlowsService, private toaster: ToastrService, + private clipboardService: ClipboardService, private modalService: NgbModal ) { } @@ -90,17 +94,17 @@ export class SwitchFlowsComponent implements OnDestroy, OnInit, OnChanges, After }, 'aoColumns': [ { sWidth: '5%' , 'bSortable': false}, - { sWidth: '10%' }, - { sWidth: '13%', 'sType': 'name', 'bSortable': true }, + { sWidth: '14%' }, + { sWidth: '14%', 'sType': 'name', 'bSortable': true }, { sWidth: '8%' }, { sWidth: '8%' }, { sWidth: '9%' }, - { sWidth: '13%', 'sType': 'name', 'bSortable': true }, + { sWidth: '14%', 'sType': 'name', 'bSortable': true }, { sWidth: '8%' }, { sWidth: '8%' }, { sWidth: '9%' }, - { sWidth: '10%' }, - { sWidth: '10%' }, + { sWidth: '8%' }, + { sWidth: '8%' }, { sWidth: '10%' }, { sWidth: '1%' , 'bSortable': false}, ], @@ -190,6 +194,7 @@ export class SwitchFlowsComponent implements OnDestroy, OnInit, OnChanges, After this.data.forEach(function(d) { ref.switchFlow[d.flowid] = false; }); + this.clipBoardItems = this.data; } } } @@ -371,4 +376,9 @@ refreshList() { } + copyToClip(event, copyItem, index) { + copyItem = this.clipBoardItems[index][copyItem]; + this.clipboardService.copyFromContent(copyItem); + } + } diff --git a/src-gui/ui/src/styles.css b/src-gui/ui/src/styles.css index 91301300a8..aa7d8f5e8e 100644 --- a/src-gui/ui/src/styles.css +++ b/src-gui/ui/src/styles.css @@ -252,7 +252,7 @@ h1 { table.dataTable.no-footer { border-right: 1px solid #ccc; font-size: 13px; - margin: 15px 0; + margin: 0 0; float: left; width: 100%; table-layout: fixed; From 4d85c7be667a719e3a9defe5dda4ea7d85bcc67a Mon Sep 17 00:00:00 2001 From: Ivan Chupin Date: Thu, 14 Nov 2024 13:32:01 +0000 Subject: [PATCH 17/21] nbworker add feature to reroute y-flow for switch/link evacuation process added evacuate y-flow button that replace evacuate toggle, slightly fix evacuate button logic. add new info message in toastrService regarding flow evacuation. --- .../ui/src/app/common/constants/constants.ts | 2 + .../isl/isl-detail/isl-detail.component.html | 15 +-- .../isl/isl-detail/isl-detail.component.ts | 19 ++-- .../switch-detail.component.html | 10 +- .../switch-detail/switch-detail.component.ts | 19 ++-- .../java/org/openkilda/model/FlowPath.java | 3 +- .../nbworker/bolts/MessageEncoder.java | 4 +- .../services/FlowOperationsService.java | 20 +++- .../services/FlowOperationsServiceTest.java | 98 ++++++++++++++++++- 9 files changed, 139 insertions(+), 51 deletions(-) diff --git a/src-gui/ui/src/app/common/constants/constants.ts b/src-gui/ui/src/app/common/constants/constants.ts index 614a080582..d2206f23ea 100644 --- a/src-gui/ui/src/app/common/constants/constants.ts +++ b/src-gui/ui/src/app/common/constants/constants.ts @@ -36,6 +36,8 @@ export const MessageObj = { bfd_flag_updated: 'BFD flag updated successfully!', flows_evacuated: 'All flows are evacuated successfully!', error_flows_evacuated: 'Error in evacuating flows!', + info_cannot_evacuate_flows_from_switch: 'Can not evacuate flows while switch is not under maintenance.', + info_cannot_evacuate_flows_from_isl: 'Can not evacuate flows while ISL is not under maintenance.', reverse_graph_no_data: 'Backward graph API did not return data.', forward_graph_no_data: 'Forward graph API did not return data.', updating_isl_bandwidth: 'Updating ISL max bandwidth', diff --git a/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.html b/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.html index 9c89bf5045..86f7d6fb12 100644 --- a/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.html +++ b/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.html @@ -242,18 +242,13 @@
- +
-
- - -
+  
diff --git a/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.ts b/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.ts index 4a42520b02..ac81ea4115 100644 --- a/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.ts +++ b/src-gui/ui/src/app/modules/isl/isl-detail/isl-detail.component.ts @@ -42,7 +42,6 @@ export class IslDetailComponent implements OnInit, AfterViewInit, OnDestroy { state = ''; bfd_session_status = ''; enable_bfd = false; - evacuate = false; under_maintenance = false; loadingData = true; isBFDEdit: any = false; @@ -187,7 +186,6 @@ export class IslDetailComponent implements OnInit, AfterViewInit, OnDestroy { this.bfd_session_status = retrievedObject.bfd_session_status; this.available_bandwidth = retrievedObject.available_bandwidth; this.under_maintenance = retrievedObject.under_maintenance; - this.evacuate = retrievedObject.evacuate; this.enable_bfd = retrievedObject.enable_bfd; this.clipBoardItems = Object.assign(this.clipBoardItems, { sourceSwitchName: retrievedObject.source_switch_name, @@ -413,14 +411,13 @@ export class IslDetailComponent implements OnInit, AfterViewInit, OnDestroy { } evacuateIsl(e) { + if (!this.under_maintenance) { + this.toastr.info(MessageObj.info_cannot_evacuate_flows_from_isl, 'Can not evacuate'); + return; + } const modalRef = this.modalService.open(ModalconfirmationComponent); modalRef.componentInstance.title = 'Confirmation'; - this.evacuate = e.target.checked; - if (this.evacuate) { - modalRef.componentInstance.content = 'Are you sure you want to evacuate all flows?'; - } else { - modalRef.componentInstance.content = 'Are you sure ?'; - } + modalRef.componentInstance.content = 'Are you sure you want to evacuate all flows?'; modalRef.result.then((response) => { if (response && response == true) { const data = { @@ -429,7 +426,7 @@ export class IslDetailComponent implements OnInit, AfterViewInit, OnDestroy { dst_switch: this.dst_switch, dst_port: this.dst_port, under_maintenance: this.under_maintenance, - evacuate: e.target.checked + evacuate: true }; this.islListService.islUnderMaintenance(data).subscribe(response => { this.toastr.success(MessageObj.flows_evacuated, 'Success'); @@ -437,11 +434,7 @@ export class IslDetailComponent implements OnInit, AfterViewInit, OnDestroy { }, error => { this.toastr.error(MessageObj.error_flows_evacuated, 'Error'); }); - } else { - this.evacuate = false; } - }, error => { - this.evacuate = false; }); } diff --git a/src-gui/ui/src/app/modules/switches/switch-detail/switch-detail.component.html b/src-gui/ui/src/app/modules/switches/switch-detail/switch-detail.component.html index 96af9adcb3..24e78b6f0a 100644 --- a/src-gui/ui/src/app/modules/switches/switch-detail/switch-detail.component.html +++ b/src-gui/ui/src/app/modules/switches/switch-detail/switch-detail.component.html @@ -108,12 +108,10 @@