Open Kilda Java Documentation
TopologyEventsBasicTest.java
Go to the documentation of this file.
1 /* Copyright 2018 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.atdd;
17 
18 import static org.hamcrest.Matchers.equalTo;
19 import static org.hamcrest.Matchers.hasItems;
20 import static org.hamcrest.Matchers.hasProperty;
21 import static org.hamcrest.Matchers.is;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertThat;
24 import static org.junit.Assert.assertTrue;
25 
26 import org.openkilda.LinksUtils;
34 
35 import cucumber.api.PendingException;
36 import cucumber.api.java.en.Then;
37 import cucumber.api.java.en.When;
38 import net.jodah.failsafe.Failsafe;
39 import net.jodah.failsafe.RetryPolicy;
40 import org.apache.commons.lang.StringUtils;
41 import org.apache.commons.lang.math.NumberUtils;
42 import org.junit.Before;
43 
44 import java.util.Comparator;
45 import java.util.List;
46 import java.util.concurrent.TimeUnit;
47 import java.util.stream.Collectors;
48 import java.util.stream.IntStream;
49 
50 
55 
56  private LinkDto manipulatedLink;
57 
58  @Before
59  public void setUp() {
60  manipulatedLink = null;
61  }
62 
63  @When("^multiple links exist between all switches$")
64  public void multipleLinksExistBetweenAllSwitches() throws Exception {
65  List<String> switchIds = IntStream.range(1, 6)
67  .collect(Collectors.toList());
68  assertTrue("Switches should have multiple links",
69  getSwitchesWithoutMultipleLinks(switchIds).isEmpty());
70  }
71 
72  private List<String> getSwitchesWithoutMultipleLinks(List<String> switches) throws Exception {
73  List<LinkDto> links = LinksUtils.dumpLinks();
74 
75  return switches.stream()
76  .filter(sw -> isSwitchHasLessThanTwoLinks(sw, links))
77  .collect(Collectors.toList());
78  }
79 
80  @When("^a link is dropped in the middle$")
81  public void linkIsDroppedInTheMiddle() throws Exception {
82  List<LinkDto> links = LinksUtils.dumpLinks();
83  manipulatedLink = getMiddleLink(links);
84 
85  PathDto node = manipulatedLink.getPath().get(0);
86  assertTrue(LinksUtils.islFail(getSwitchName(node.getSwitchId()), String.valueOf(node.getPortNo())));
87  }
88 
89  @Then("^the link will have no health checks$")
90  public void the_link_will_have_no_health_checks() throws Exception {
91  List<LinkDto> links = LinksUtils.dumpLinks();
92  List<LinkDto> cutLinks = links.stream()
93  .filter(isl -> isl.getState() != LinkStatus.DISCOVERED)
94  .collect(Collectors.toList());
95 
96  assertFalse("Link should be cut", cutLinks.isEmpty());
97  assertThat("Only one link should be cut", cutLinks.size(), is(1));
98  }
99 
100  @Then("^the link disappears from the topology engine in (\\d+) seconds\\.$")
101  public void theLinkDisappearsFromTheTopologyEngine(int timeout) throws Exception {
102  List<LinkDto> cutLinks = Failsafe.with(new RetryPolicy()
103  .withDelay(2, TimeUnit.SECONDS)
104  .withMaxDuration(timeout, TimeUnit.SECONDS)
105  .retryIf(links -> links instanceof List && ((List) links).isEmpty()))
106  .get(() -> LinksUtils.dumpLinks().stream()
107  .filter(isl -> isl.getState() != LinkStatus.DISCOVERED)
108  .collect(Collectors.toList())
109  );
110 
111  assertFalse("Link should be cut", cutLinks.isEmpty());
112  assertThat("Only one link should be cut", cutLinks,
113  hasItems(hasProperty("path", equalTo(manipulatedLink.getPath()))));
114  }
115 
116  @When("^a link is added in the middle$")
117  public void linkIsAddedInTheMiddle() throws Exception {
118  List<LinkDto> links = LinksUtils.dumpLinks();
119  LinkDto middleLink = getMiddleLink(links);
120 
121  String srcSwitch = getSwitchName(middleLink.getPath().get(0).getSwitchId());
122  String dstSwitch = getSwitchName(middleLink.getPath().get(1).getSwitchId());
123  assertTrue("Link is not added", LinksUtils.addLink(srcSwitch, dstSwitch));
124  TimeUnit.SECONDS.sleep(2);
125  }
126 
127  @Then("^the link will have health checks$")
128  public void the_link_will_have_health_checks() throws Exception {
129  // Write code here that turns the phrase above into concrete actions
130  throw new PendingException();
131  }
132 
133  @Then("^the link appears in the topology engine\\.$")
134  public void theLinkAppearsInTheTopologyEngine() throws Exception {
135  List<LinkDto> links = LinksUtils.dumpLinks();
136  assertThat("Amount of links should be 18 (initial 16 and 2 newly created)", links.size(), is(18));
137  }
138 
139  @When("^a switch is dropped in the middle$")
140  public void switchIsDroppedInTheMiddle() throws Exception {
141  List<SwitchDto> switches = SwitchesUtils.dumpSwitches();
142  SwitchDto middleSwitch = getMiddleSwitch(switches);
143  assertTrue("Should successfully knockout switch",
144  SwitchesUtils.knockoutSwitch(getSwitchName(middleSwitch.getSwitchId())));
145 
146  TimeUnit.SECONDS.sleep(1);
147  List<SwitchDto> updatedSwitches = SwitchesUtils.dumpSwitches();
148  SwitchDto deactivatedSwitch = updatedSwitches.stream()
149  .filter(sw -> sw.getSwitchId().equals(middleSwitch.getSwitchId()))
150  .findFirst().orElseThrow(() -> new IllegalStateException("Switch should exist"));
151  assertThat(deactivatedSwitch.getState(), is(SwitchState.DEACTIVATED));
152  }
153 
154  @Then("^all links through the dropped switch will have no health checks$")
156  // Write code here that turns the phrase above into concrete actions
157  throw new PendingException();
158  }
159 
160  @Then("^the links disappear from the topology engine\\.$")
161  public void theLinksDisappearFromTheTopologyEngine() throws Exception {
162  //todo check whether we need to wait until links will disappear or
163  // we might delete them instantly when switch goes down
164  TimeUnit.SECONDS.sleep(15);
165  final SwitchDto middleSwitch = getMiddleSwitch(SwitchesUtils.dumpSwitches());
166  final List<LinkDto> links = LinksUtils.dumpLinks();
167 
168  List<LinkDto> switchLinks = links.stream()
169  .filter(isl -> isLinkBelongToSwitch(middleSwitch.getSwitchId(), isl))
170  .filter(isl -> isl.getState() == LinkStatus.DISCOVERED)
171  .collect(Collectors.toList());
172  assertTrue("Switch shouldn't have any active links", switchLinks.isEmpty());
173  }
174 
175  @Then("^the switch disappears from the topology engine\\.$")
176  public void theSwitchDisappearsFromTheTopologyEngine() throws Exception {
177  List<SwitchDto> switches = SwitchesUtils.dumpSwitches();
178  SwitchDto middleSwitch = getMiddleSwitch(switches);
179 
180  //right now switch doesn't disappear in neo4j - we just update status
181  assertThat(middleSwitch.getState(), is(SwitchState.DEACTIVATED));
182  }
183 
184  @When("^a switch is added at the edge$")
185  public void switchIsAddedAtTheEdge() throws Exception {
186  assertTrue("Should add switch to mininet topology",
187  SwitchesUtils.addSwitch("01010001", "DEADBEEF01010001"));
188  TimeUnit.SECONDS.sleep(1);
189  }
190 
191  @When("^links are added between the new switch and its neighbor$")
192  public void linksAreAddedBetweenTheNewSwitchAndItsNeighbor() throws Exception {
193  List<LinkDto> links = LinksUtils.dumpLinks();
194  List<SwitchDto> switches = SwitchesUtils.dumpSwitches();
195 
196  SwitchDto switchWithoutLinks = switches.stream()
197  .filter(sw -> links.stream()
198  .anyMatch(isl -> isLinkBelongToSwitch(sw.getSwitchId(), isl)))
199  .findAny()
200  .orElseThrow(() -> new IllegalStateException("At least one switch should exist"));
201 
202  SwitchDto latestConnectedSwitch = switches.stream()
203  .sorted(Comparator.comparing(SwitchDto::getSwitchId).reversed())
204  .findFirst().get();
205 
206  assertTrue(LinksUtils.addLink(getSwitchName(switchWithoutLinks.getSwitchId()),
207  getSwitchName(latestConnectedSwitch.getSwitchId())));
208  assertTrue(LinksUtils.addLink(getSwitchName(switchWithoutLinks.getSwitchId()),
209  getSwitchName(latestConnectedSwitch.getSwitchId())));
210  TimeUnit.SECONDS.sleep(1);
211  }
212 
213  @Then("^all links through the added switch will have health checks$")
214  public void allLinksThroughTheAddedSwitchWillHaveHealthChecks() throws Exception {
215  // Write code here that turns the phrase above into concrete actions
216  throw new PendingException();
217  }
218 
219  @Then("^now amount of switches is (\\d+)\\.$")
220  public void theSwitchAppearsInTheTopologyEngine(int switches) throws Exception {
221  List<SwitchDto> switchList = SwitchesUtils.dumpSwitches();
222  List<SwitchDto> activeSwitches = switchList.stream()
223  .filter(sw -> SwitchState.ACTIVATED.getType().equals(sw.getState()))
224  .collect(Collectors.toList());
225 
226  assertThat("Switch should disappear from neo4j", activeSwitches.size(), is(switches));
227  }
228 
229  private boolean isSwitchHasLessThanTwoLinks(String switchId, List<LinkDto> links) {
230  int inputsAmount = 0;
231  int outputsAmount = 0;
232  for (LinkDto isl : links) {
233  for (PathDto node : isl.getPath()) {
234  if (switchId.equalsIgnoreCase(node.getSwitchId())) {
235  if (node.getSeqId() == 0) {
236  outputsAmount++;
237  } else if (node.getSeqId() == 1) {
238  inputsAmount++;
239  }
240  }
241  }
242  }
243 
244  //check whether switch has more than one link in both direction (sequence id 0 and 1)
245  return inputsAmount <= NumberUtils.INTEGER_ONE && outputsAmount <= NumberUtils.INTEGER_ONE;
246  }
247 
248  private LinkDto getMiddleLink(List<LinkDto> links) {
249  return links.stream()
250  .sorted(Comparator.comparing((isl) -> isl.getPath().get(0).getSwitchId()))
251  .collect(Collectors.toList())
252  .get((links.size() / 2) + 1);
253  }
254 
255  private SwitchDto getMiddleSwitch(List<SwitchDto> switches) {
256  return switches.stream()
257  .sorted(Comparator.comparing(SwitchDto::getSwitchId))
258  .collect(Collectors.toList())
259  .get(switches.size() / 2);
260  }
261 
262  private String getSwitchName(String switchId) {
263  return switchId.replaceAll("(\\A.*?:.*?:.*?:.*?:)|[:]", StringUtils.EMPTY);
264  }
265 
266  private boolean isLinkBelongToSwitch(String switchId, LinkDto isl) {
267  return switchId.equalsIgnoreCase(isl.getPath().get(0).getSwitchId())
268  || switchId.equalsIgnoreCase(isl.getPath().get(1).getSwitchId());
269  }
270 }
static List< SwitchDto > dumpSwitches()
static boolean addSwitch(String switchName, String dpid)
static boolean knockoutSwitch(String switchName)
net
Definition: plan-b.py:46