Skip to content

Commit

Permalink
Merge pull request #5742 from telstra/test/improvement-switches-relat…
Browse files Browse the repository at this point in the history
…ions-dump-verification

[TEST]: Improvement: Verification of switches and relations dump after WFM restarting
  • Loading branch information
IvanChupin authored Oct 22, 2024
2 parents 3aed73b + 561111d commit 3395883
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<Long> getDefaultCookies(Switch sw) {
def swProps = northbound.get().getSwitchProperties(sw.dpId)
def multiTableRules = []
Expand Down
Original file line number Diff line number Diff line change
@@ -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<SwitchFeature> 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
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"() {
Expand All @@ -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) {
Expand Down Expand Up @@ -172,4 +184,19 @@ class StormLcmSpec extends HealthCheckSpecification {
assert northbound.getAllLinks().every {it.state == IslChangeType.DISCOVERED}
}
}

private def collectRelationsDetails(List relationsDump) {
List<String> 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()]]
}
}
}

0 comments on commit 3395883

Please sign in to comment.