Open Kilda Java Documentation
TopologyDefinition.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.testing.model.topology;
17 
18 import static java.util.Collections.emptyList;
19 import static java.util.Collections.unmodifiableList;
20 import static java.util.stream.Collectors.toList;
21 import static java.util.stream.Collectors.toSet;
22 
24 
25 import com.fasterxml.jackson.annotation.JsonCreator;
26 import com.fasterxml.jackson.annotation.JsonIdentityInfo;
27 import com.fasterxml.jackson.annotation.JsonProperty;
28 import com.fasterxml.jackson.annotation.ObjectIdGenerators;
29 import com.google.common.base.Preconditions;
30 import com.google.common.collect.ImmutableRangeSet;
31 import com.google.common.collect.Range;
32 import com.google.common.collect.RangeSet;
33 import lombok.NonNull;
34 import lombok.Value;
35 import lombok.experimental.NonFinal;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Set;
40 import java.util.stream.Collectors;
41 import java.util.stream.IntStream;
42 
48 @Value
49 @NonFinal
50 public class TopologyDefinition {
51 
52  @NonNull
53  private List<Switch> switches;
54  @NonNull
55  private List<Isl> isls;
56  @NonNull
57  private List<TraffGen> traffGens;
58  @NonNull
59  private TraffGenConfig traffGenConfig;
60 
64  @JsonCreator
65  public static TopologyDefinition factory(
66  @JsonProperty("switches") List<Switch> switches,
67  @JsonProperty("isls") List<Isl> isls,
68  @JsonProperty("traffgens") List<TraffGen> traffGens,
69  @JsonProperty("traffgen_config") TraffGenConfig traffGenConfig) {
70 
71  Preconditions.checkArgument(
72  switches.size() == switches.stream().map(Switch::getDpId).distinct().count(),
73  "Switches must have no duplicates");
74  Preconditions.checkArgument(
75  isls.size() == isls.stream().distinct().count(), "Isls must have no duplicates");
76  Preconditions.checkArgument(
77  traffGens.size() == traffGens.stream().map(TraffGen::getName).distinct().count(),
78  "TraffGens must have no duplicates");
79 
80  return new TopologyDefinition(
81  unmodifiableList(switches),
82  unmodifiableList(isls),
83  unmodifiableList(traffGens),
84  traffGenConfig);
85  }
86 
90  public List<Switch> getActiveSwitches() {
91  return switches.stream()
92  .filter(Switch::isActive)
93  .collect(toList());
94  }
95 
99  public Set<SwitchId> getSkippedSwitchIds() {
100  return switches.stream()
101  .filter(sw -> sw.getStatus() == Status.Skip)
102  .map(Switch::getDpId)
103  .collect(toSet());
104  }
105 
109  public List<Isl> getIslsForActiveSwitches() {
110  return isls.stream()
111  .filter(isl -> isl.getDstSwitch() != null
112  && isl.getSrcSwitch().isActive() && isl.getDstSwitch().isActive())
113  .collect(toList());
114  }
115 
120  public List<Isl> getNotConnectedIsls() {
121  return isls.stream()
122  .filter(isl -> isl.getSrcSwitch() != null && isl.getSrcSwitch().isActive()
123  && isl.getDstSwitch() == null)
124  .collect(toList());
125  }
126 
130  public List<Integer> getAllowedPortsForSwitch(Switch sw) {
131  List<Integer> allPorts = new ArrayList<>(sw.getAllPorts());
132  allPorts.removeAll(getIslsForActiveSwitches().stream().filter(isl ->
133  isl.getSrcSwitch().getDpId().equals(sw.getDpId())).map(Isl::getSrcPort).collect(Collectors.toList()));
134  allPorts.removeAll(getIslsForActiveSwitches().stream().filter(isl ->
135  isl.getDstSwitch().getDpId().equals(sw.getDpId())).map(Isl::getDstPort).collect(Collectors.toList()));
136  return allPorts;
137  }
138 
139  @Value
140  @NonFinal
141  @JsonIdentityInfo(property = "name", generator = ObjectIdGenerators.PropertyGenerator.class)
142  public static class Switch {
143 
144  private static int DEFAULT_MAX_PORT = 20;
145 
146  private String name;
147  @NonNull
148  private SwitchId dpId;
149  @NonNull
150  private String ofVersion;
151  @NonNull
152  private Status status;
153  @NonNull
154  private List<OutPort> outPorts;
155  private Integer maxPort;
156 
160  @JsonCreator
161  public static Switch factory(
162  @JsonProperty("name") String name,
163  @JsonProperty("dp_id") SwitchId dpId,
164  @JsonProperty("of_version") String ofVersion,
165  @JsonProperty("status") Status status,
166  @JsonProperty("out_ports") List<OutPort> outPorts,
167  @JsonProperty("max_port") Integer maxPort) {
168  if (outPorts == null) {
169  outPorts = emptyList();
170  }
171  if (maxPort == null) {
172  maxPort = DEFAULT_MAX_PORT;
173  }
174 
175  return new Switch(name, dpId, ofVersion, status, outPorts, maxPort);
176  }
177 
178  public boolean isActive() {
179  return status == Status.Active;
180  }
181 
185  public List<Integer> getAllPorts() {
186  return IntStream.rangeClosed(1, maxPort).boxed().collect(toList());
187  }
188  }
189 
190  @Value
191  @NonFinal
192  public static class OutPort {
193 
194  private int port;
195  @NonNull
196  private RangeSet<Integer> vlanRange;
197 
198  @JsonCreator
199  public static OutPort factory(
200  @JsonProperty("port") int port,
201  @JsonProperty("vlan_range") String vlanRange) {
202 
203  return new OutPort(port, parseVlanRange(vlanRange));
204  }
205 
206  private static RangeSet<Integer> parseVlanRange(String vlanRangeAsStr) {
207  String[] splitRanges = vlanRangeAsStr.split(",");
208  if (splitRanges.length == 0) {
209  throw new IllegalArgumentException("Vlan range must be non-empty.");
210  }
211 
212  ImmutableRangeSet.Builder<Integer> resultVlanRange = ImmutableRangeSet.builder();
213  for (String range : splitRanges) {
214  String[] boundaries = range.split("\\.\\.");
215  if (boundaries.length == 0 || boundaries.length > 2) {
216  throw new IllegalArgumentException("Range " + range + " is not valid.");
217  }
218 
219  int lowerBound = Integer.parseInt(boundaries[0].trim());
220  if (boundaries.length == 2) {
221  int upperBound = Integer.parseInt(boundaries[1].trim());
222  resultVlanRange.add(Range.closed(lowerBound, upperBound));
223  } else {
224  resultVlanRange.add(Range.closed(lowerBound, lowerBound));
225  }
226  }
227 
228  return resultVlanRange.build();
229  }
230  }
231 
232  @Value
233  @NonFinal
234  public static class Isl {
235 
236  @NonNull
237  private Switch srcSwitch;
238  private int srcPort;
239  private Switch dstSwitch;
240  private int dstPort;
241  private long maxBandwidth;
242  private ASwitch aswitch;
243 
244  @JsonCreator
245  public static Isl factory(
246  @JsonProperty("src_switch") Switch srcSwitch,
247  @JsonProperty("src_port") int srcPort,
248  @JsonProperty("dst_switch") Switch dstSwitch,
249  @JsonProperty("dst_port") int dstPort,
250  @JsonProperty("max_bandwidth") long maxBandwidth,
251  @JsonProperty("a_switch") ASwitch aswitch) {
252  return new Isl(srcSwitch, srcPort, dstSwitch, dstPort, maxBandwidth, aswitch);
253  }
254  }
255 
256  @Value
257  @NonFinal
258  public static class ASwitch {
259 
260  @NonNull
261  private Integer inPort;
262  private Integer outPort;
263 
264  @JsonCreator
265  public static ASwitch factory(
266  @JsonProperty("in_port") Integer inPort,
267  @JsonProperty("out_port") Integer outPort) {
268  return new ASwitch(inPort, outPort);
269  }
270  }
271 
272  @Value
273  @NonFinal
274  public static class TraffGen {
275 
276  @NonNull
277  private String name;
278  @NonNull
279  private String controlEndpoint;
280  @NonNull
281  private String ifaceName;
282  @NonNull
283  private Switch switchConnected;
284  private int switchPort;
285  @NonNull
286  private Status status;
287 
288  @JsonCreator
289  public static TraffGen factory(
290  @JsonProperty("name") String name,
291  @JsonProperty("iface") String ifaceName,
292  @JsonProperty("control_endpoint") String controlEndpoint,
293  @JsonProperty("switch") Switch switchConnected,
294  @JsonProperty("switch_port") int switchPort,
295  @JsonProperty("status") Status status) {
296  return new TraffGen(name, controlEndpoint, ifaceName, switchConnected, switchPort, status);
297  }
298 
299  public boolean isActive() {
300  return status == Status.Active;
301  }
302  }
303 
307  public List<TraffGen> getActiveTraffGens() {
308  return traffGens.stream()
309  .filter(TraffGen::isActive)
310  .filter(traffGen -> traffGen.getSwitchConnected().isActive())
311  .collect(Collectors.toList());
312  }
313 
314  @Value
315  @NonFinal
316  public static class TraffGenConfig {
317 
318  @NonNull
319  private String addressPoolBase;
320  private int addressPoolPrefixLen;
321 
322  @JsonCreator
323  public static TraffGenConfig factory(
324  @JsonProperty("address_pool_base") String addressPoolBase,
325  @JsonProperty("address_pool_prefix_len") int addressPoolPrefixLen) {
326  return new TraffGenConfig(addressPoolBase, addressPoolPrefixLen);
327  }
328  }
329 
330  public enum Status {
333  Skip
334  }
335 }
static TopologyDefinition factory( @JsonProperty("switches") List< Switch > switches, @JsonProperty("isls") List< Isl > isls, @JsonProperty("traffgens") List< TraffGen > traffGens, @JsonProperty("traffgen_config") TraffGenConfig traffGenConfig)
name
Definition: setup.py:24
def status()
Definition: rest.py:593