blob: f4eedc40a4938441b03a1cbaa7a5ece4cf67a9b8 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.incubator.store.virtual.impl;
17
Brian Stanke0e5c94e2016-03-08 11:20:04 -050018import com.google.common.collect.ImmutableSet;
19import com.google.common.collect.Sets;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070025import org.apache.felix.scr.annotations.Service;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050026import org.onlab.util.KryoNamespace;
27import org.onosproject.core.CoreService;
28import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070029import org.onosproject.incubator.net.tunnel.TunnelId;
30import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050031import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050033import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070034import org.onosproject.incubator.net.virtual.NetworkId;
35import org.onosproject.incubator.net.virtual.TenantId;
36import org.onosproject.incubator.net.virtual.VirtualDevice;
37import org.onosproject.incubator.net.virtual.VirtualLink;
38import org.onosproject.incubator.net.virtual.VirtualNetwork;
39import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050040import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070041import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
42import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
43import org.onosproject.incubator.net.virtual.VirtualPort;
44import org.onosproject.net.ConnectPoint;
Brian Stanke5df14472016-03-11 19:34:38 -050045import org.onosproject.net.DefaultDevice;
46import org.onosproject.net.DefaultPort;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050047import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070048import org.onosproject.net.DeviceId;
49import org.onosproject.net.Port;
50import org.onosproject.net.PortNumber;
51import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050052import org.onosproject.store.serializers.KryoNamespaces;
53import org.onosproject.store.service.ConsistentMap;
54import org.onosproject.store.service.DistributedSet;
55import org.onosproject.store.service.MapEvent;
56import org.onosproject.store.service.MapEventListener;
57import org.onosproject.store.service.Serializer;
58import org.onosproject.store.service.SetEvent;
59import org.onosproject.store.service.SetEventListener;
60import org.onosproject.store.service.StorageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070061import org.slf4j.Logger;
62
Brian Stanke0e5c94e2016-03-08 11:20:04 -050063import java.util.HashSet;
64import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070065import java.util.Set;
66
Brian Stanke0e5c94e2016-03-08 11:20:04 -050067import static com.google.common.base.Preconditions.checkNotNull;
68import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070069import static org.slf4j.LoggerFactory.getLogger;
70
71/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050072 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070073 */
74@Component(immediate = true)
75@Service
76public class DistributedVirtualNetworkStore
77 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
78 implements VirtualNetworkStore {
79
80 private final Logger log = getLogger(getClass());
81
Brian Stanke0e5c94e2016-03-08 11:20:04 -050082 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070084
Brian Stanke0e5c94e2016-03-08 11:20:04 -050085 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070087
Brian Stanke0e5c94e2016-03-08 11:20:04 -050088 private IdGenerator idGenerator;
89
90 // Track tenants by ID
91 private DistributedSet<TenantId> tenantIdSet;
92
93 // Listener for tenant events
94 private final SetEventListener<TenantId> setListener = new InternalSetListener();
95
96 // Track virtual networks by network Id
97 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
98 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
99
100 // Listener for virtual network events
101 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
102
103 // Track virtual network IDs by tenant Id
104 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
105 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
106
107 // Track virtual devices by device Id
108 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
109 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
110
111 // Track device IDs by network Id
112 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
113 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
114
115 // Track virtual links by network Id
116 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
117 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
118
119 // Track virtual ports by network Id
120 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
121 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
122
123 private static final Serializer SERIALIZER = Serializer
124 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
125 .register(TenantId.class)
126 .register(NetworkId.class).register(DeviceId.class)
127 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500128 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500129 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500130 .register(DefaultVirtualDevice.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500131 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500132 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500133 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500134 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500135 .register(DeviceId.class)
136 .register(Device.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500137 .register(DefaultDevice.class)
138 .register(DefaultPort.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400139 .register(TunnelId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500140 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID).build());
141
142 /**
143 * Distributed network store service activate method.
144 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700145 @Activate
146 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500147 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
148
149 tenantIdSet = storageService.<TenantId>setBuilder()
150 .withSerializer(SERIALIZER)
151 .withName("onos-tenantId")
152 .withRelaxedReadConsistency()
153 .build()
154 .asDistributedSet();
155 tenantIdSet.addListener(setListener);
156
157 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
158 .withSerializer(SERIALIZER)
159 .withName("onos-networkId-virtualnetwork")
160 .withRelaxedReadConsistency()
161 .build();
162 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
163 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
164
165 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
166 .withSerializer(SERIALIZER)
167 .withName("onos-tenantId-networkIds")
168 .withRelaxedReadConsistency()
169 .build();
170 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
171
172 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
173 .withSerializer(SERIALIZER)
174 .withName("onos-deviceId-virtualdevice")
175 .withRelaxedReadConsistency()
176 .build();
177 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
178
179 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
180 .withSerializer(SERIALIZER)
181 .withName("onos-networkId-deviceIds")
182 .withRelaxedReadConsistency()
183 .build();
184 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
185
186 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
187 .withSerializer(SERIALIZER)
188 .withName("onos-networkId-virtuallinks")
189 .withRelaxedReadConsistency()
190 .build();
191 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
192
193 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
194 .withSerializer(SERIALIZER)
195 .withName("onos-networkId-virtualportss")
196 .withRelaxedReadConsistency()
197 .build();
198 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
199
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700200 log.info("Started");
201 }
202
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500203 /**
204 * Distributed network store service deactivate method.
205 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700206 @Deactivate
207 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500208 tenantIdSet.removeListener(setListener);
209 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700210 log.info("Stopped");
211 }
212
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500213 /**
214 * This method is used for Junit tests to set the CoreService instance, which
215 * is required to set the IdGenerator instance.
216 *
217 * @param coreService core service instance
218 */
219 public void setCoreService(CoreService coreService) {
220 this.coreService = coreService;
221 }
222
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700223 @Override
224 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500225 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700226 }
227
228 @Override
229 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500230 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700231 }
232
233 @Override
234 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500235 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700236 }
237
238 @Override
239 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500240
241 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
242 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
243 //TODO update both maps in one transaction.
244 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500245
246 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
247 if (networkIdSet == null) {
248 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500249 }
Brian Stanke5df14472016-03-11 19:34:38 -0500250 networkIdSet.add(virtualNetwork.id());
251 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
252
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500253 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700254 }
255
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500256 /**
257 * Returns a new network identifier from a virtual network block of identifiers.
258 *
259 * @return NetworkId network identifier
260 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700261 private NetworkId genNetworkId() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500262 return NetworkId.networkId(idGenerator.getNewId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700263 }
264
265
266 @Override
267 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500268 // Make sure that the virtual network exists before attempting to remove it.
269 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500270 //TODO update both maps in one transaction.
271
272 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500273 if (virtualNetwork == null) {
274 return;
275 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500276 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500277
Brian Stanke5df14472016-03-11 19:34:38 -0500278 Set<NetworkId> networkIdSet = new HashSet<>();
279 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
280 if (networkId1.id().equals(networkId.id())) {
281 networkIdSet.add(networkId1);
282 }
283 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500284
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500285 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
286 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
Brian Stanke5df14472016-03-11 19:34:38 -0500287 return new HashSet<NetworkId>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500288 } else {
Brian Stanke5df14472016-03-11 19:34:38 -0500289 return new HashSet<NetworkId>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500290 }
291 });
292 }
293 }
294
295 /**
296 * Returns if the network identifier exists.
297 *
298 * @param networkId network identifier
299 * @return true if the network identifier exists, false otherwise.
300 */
301 private boolean networkExists(NetworkId networkId) {
302 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700303 }
304
305 @Override
306 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500307 checkState(networkExists(networkId), "The network has not been added.");
308 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
309 if (deviceIdSet == null) {
310 deviceIdSet = new HashSet<>();
311 }
312 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
313 //TODO update both maps in one transaction.
314 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
315 deviceIdSet.add(deviceId);
316 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
317 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700318 }
319
320 @Override
321 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500322 checkState(networkExists(networkId), "The network has not been added.");
323 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500324
325 Set<DeviceId> deviceIdSet = new HashSet<>();
326 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
327 if (deviceId1.equals(deviceId)) {
328 deviceIdSet.add(deviceId1);
329 }
330 });
331
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500332 if (deviceIdSet != null) {
333 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
334 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
Brian Stanke5df14472016-03-11 19:34:38 -0500335 return new HashSet<DeviceId>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500336 } else {
Brian Stanke5df14472016-03-11 19:34:38 -0500337 return new HashSet<DeviceId>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500338 }
339 });
340
Brian Stanke5df14472016-03-11 19:34:38 -0500341 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500342 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700343 }
344
345 @Override
346 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500347 checkState(networkExists(networkId), "The network has not been added.");
348 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
349 if (virtualLinkSet == null) {
350 virtualLinkSet = new HashSet<>();
351 }
Brian Stanke9a108972016-04-11 15:25:17 -0400352 // validate that the link does not already exist in this network
353 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
354
355 VirtualLink virtualLink = DefaultVirtualLink.builder()
356 .networkId(networkId)
357 .src(src)
358 .dst(dst)
359 .tunnelId(realizedBy)
360 .build();
361
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500362 virtualLinkSet.add(virtualLink);
363 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
364 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700365 }
366
367 @Override
Brian Stanke9a108972016-04-11 15:25:17 -0400368 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId) {
369 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
370 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
371 if (virtualLinkSet == null) {
372 virtualLinkSet = new HashSet<>();
373 }
374 virtualLinkSet.remove(virtualLink);
375
376 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
377 .networkId(virtualLink.networkId())
378 .src(virtualLink.src())
379 .dst(virtualLink.dst())
380 .tunnelId(tunnelId)
381 .build();
382
383 virtualLinkSet.add(newVirtualLink);
384 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
385 }
386
387 @Override
388 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500389 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500390
Brian Stanke9a108972016-04-11 15:25:17 -0400391 final VirtualLink virtualLink = getLink(networkId, src, dst);
392 if (virtualLink == null) {
393 return null;
394 }
Brian Stanke5df14472016-03-11 19:34:38 -0500395 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400396 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500397
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500398 if (virtualLinkSet != null) {
399 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
400 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
Brian Stanke5df14472016-03-11 19:34:38 -0500401 return new HashSet<VirtualLink>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500402 } else {
Brian Stanke5df14472016-03-11 19:34:38 -0500403 return new HashSet<VirtualLink>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500404 }
405 });
406 }
Brian Stanke9a108972016-04-11 15:25:17 -0400407 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700408 }
409
410 @Override
411 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500412 checkState(networkExists(networkId), "The network has not been added.");
413 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
414 if (virtualPortSet == null) {
415 virtualPortSet = new HashSet<>();
416 }
417 Device device = deviceIdVirtualDeviceMap.get(deviceId);
418 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
419 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
420 virtualPortSet.add(virtualPort);
421 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
422 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700423 }
424
425 @Override
426 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500427 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500428
429 Set<VirtualPort> virtualPortSet = new HashSet<>();
430 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
431 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
432 virtualPortSet.add(port);
433 }
434 });
435
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500436 if (virtualPortSet != null) {
437 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
438 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
Brian Stanke5df14472016-03-11 19:34:38 -0500439 return new HashSet<VirtualPort>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500440 } else {
Brian Stanke5df14472016-03-11 19:34:38 -0500441 return new HashSet<VirtualPort>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500442 }
443 });
444 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700445 }
446
447 @Override
448 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500449 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
450 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
451 if (networkIdSet != null) {
452 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
453 }
454 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700455 }
456
457 @Override
458 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500459 checkState(networkExists(networkId), "The network has not been added.");
460 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
461 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
462 if (deviceIdSet != null) {
463 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
464 }
465 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700466 }
467
468 @Override
469 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500470 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500471 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
472 if (virtualLinkSet == null) {
473 virtualLinkSet = new HashSet<>();
474 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500475 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700476 }
477
Brian Stanke9a108972016-04-11 15:25:17 -0400478 /**
479 * Returns the virtual link matching the network identifier, source connect point,
480 * and destination connect point.
481 *
482 * @param networkId network identifier
483 * @param src source connect point
484 * @param dst destination connect point
485 * @return virtual link
486 */
487 private VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
488 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
489 if (virtualLinkSet == null) {
490 return null;
491 }
492
493 VirtualLink virtualLink = null;
494 for (VirtualLink link : virtualLinkSet) {
495 if (link.src().equals(src) && link.dst().equals(dst)) {
496 virtualLink = link;
497 break;
498 }
499 }
500 return virtualLink;
501 }
502
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700503 @Override
504 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500505 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500506 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
507 if (virtualPortSet == null) {
508 virtualPortSet = new HashSet<>();
509 }
510
511 Set<VirtualPort> portSet = new HashSet<>();
512 virtualPortSet.forEach(virtualPort -> {
513 if (virtualPort.element().id().equals(deviceId)) {
514 portSet.add(virtualPort);
515 }
516 });
517 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500518 }
519
520 /**
521 * Listener class to map listener set events to the virtual network events.
522 */
523 private class InternalSetListener implements SetEventListener<TenantId> {
524 @Override
525 public void event(SetEvent<TenantId> event) {
526 VirtualNetworkEvent.Type type = null;
527 switch (event.type()) {
528 case ADD:
529 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
530 break;
531 case REMOVE:
532 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
533 break;
534 default:
535 log.error("Unsupported event type: " + event.type());
536 }
537 notifyDelegate(new VirtualNetworkEvent(type, null));
538 }
539 }
540
541 /**
542 * Listener class to map listener map events to the virtual network events.
543 */
544 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
545 @Override
546 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
547 NetworkId networkId = checkNotNull(event.key());
548 VirtualNetworkEvent.Type type = null;
549 switch (event.type()) {
550 case INSERT:
551 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
552 break;
553 case UPDATE:
554 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
555 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
556 } else {
557 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
558 }
559 break;
560 case REMOVE:
561 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
562 break;
563 default:
564 log.error("Unsupported event type: " + event.type());
565 }
566 notifyDelegate(new VirtualNetworkEvent(type, networkId));
567 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700568 }
569}