blob: a9b5ac0f0cbc12545df821e44d88365096d02622 [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 Stanke7a81b532016-06-14 15:43:51 -040026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050029import org.onlab.util.KryoNamespace;
30import org.onosproject.core.CoreService;
31import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.tunnel.TunnelId;
33import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040034import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050035import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070036import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050037import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070038import org.onosproject.incubator.net.virtual.NetworkId;
39import org.onosproject.incubator.net.virtual.TenantId;
40import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040041import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070042import org.onosproject.incubator.net.virtual.VirtualLink;
43import org.onosproject.incubator.net.virtual.VirtualNetwork;
44import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050045import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070046import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
47import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
48import org.onosproject.incubator.net.virtual.VirtualPort;
49import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050050import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070051import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040052import org.onosproject.net.HostId;
53import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040054import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070055import org.onosproject.net.Port;
56import org.onosproject.net.PortNumber;
57import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050058import org.onosproject.store.serializers.KryoNamespaces;
59import org.onosproject.store.service.ConsistentMap;
60import org.onosproject.store.service.DistributedSet;
61import org.onosproject.store.service.MapEvent;
62import org.onosproject.store.service.MapEventListener;
63import org.onosproject.store.service.Serializer;
64import org.onosproject.store.service.SetEvent;
65import org.onosproject.store.service.SetEventListener;
66import org.onosproject.store.service.StorageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070067import org.slf4j.Logger;
68
Brian Stanke0e5c94e2016-03-08 11:20:04 -050069import java.util.HashSet;
70import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070071import java.util.Set;
72
Brian Stanke0e5c94e2016-03-08 11:20:04 -050073import static com.google.common.base.Preconditions.checkNotNull;
74import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070075import static org.slf4j.LoggerFactory.getLogger;
76
77/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050078 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070079 */
80@Component(immediate = true)
81@Service
82public class DistributedVirtualNetworkStore
83 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
84 implements VirtualNetworkStore {
85
86 private final Logger log = getLogger(getClass());
87
Brian Stanke0e5c94e2016-03-08 11:20:04 -050088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070090
Brian Stanke0e5c94e2016-03-08 11:20:04 -050091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070093
Brian Stanke0e5c94e2016-03-08 11:20:04 -050094 private IdGenerator idGenerator;
95
96 // Track tenants by ID
97 private DistributedSet<TenantId> tenantIdSet;
98
99 // Listener for tenant events
100 private final SetEventListener<TenantId> setListener = new InternalSetListener();
101
102 // Track virtual networks by network Id
103 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
104 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
105
106 // Listener for virtual network events
107 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
108
109 // Track virtual network IDs by tenant Id
110 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
111 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
112
113 // Track virtual devices by device Id
114 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
115 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
116
117 // Track device IDs by network Id
118 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
119 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
120
Brian Stanke7a81b532016-06-14 15:43:51 -0400121 // Track virtual hosts by host Id
122 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
123 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
124
125 // Track host IDs by network Id
126 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
127 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
128
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500129 // Track virtual links by network Id
130 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
131 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
132
133 // Track virtual ports by network Id
134 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
135 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
136
137 private static final Serializer SERIALIZER = Serializer
138 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
139 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700140 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500141 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500142 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500143 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500144 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400145 .register(VirtualHost.class)
146 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500147 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500148 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500149 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500150 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500151 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400152 .register(TunnelId.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700153 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
154 .build("VirtualNetworkStore"));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500155
156 /**
157 * Distributed network store service activate method.
158 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700159 @Activate
160 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500161 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
162
163 tenantIdSet = storageService.<TenantId>setBuilder()
164 .withSerializer(SERIALIZER)
165 .withName("onos-tenantId")
166 .withRelaxedReadConsistency()
167 .build()
168 .asDistributedSet();
169 tenantIdSet.addListener(setListener);
170
171 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
172 .withSerializer(SERIALIZER)
173 .withName("onos-networkId-virtualnetwork")
174 .withRelaxedReadConsistency()
175 .build();
176 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
177 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
178
179 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
180 .withSerializer(SERIALIZER)
181 .withName("onos-tenantId-networkIds")
182 .withRelaxedReadConsistency()
183 .build();
184 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
185
186 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
187 .withSerializer(SERIALIZER)
188 .withName("onos-deviceId-virtualdevice")
189 .withRelaxedReadConsistency()
190 .build();
191 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
192
193 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
194 .withSerializer(SERIALIZER)
195 .withName("onos-networkId-deviceIds")
196 .withRelaxedReadConsistency()
197 .build();
198 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
199
Brian Stanke7a81b532016-06-14 15:43:51 -0400200 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
201 .withSerializer(SERIALIZER)
202 .withName("onos-hostId-virtualhost")
203 .withRelaxedReadConsistency()
204 .build();
205 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
206
207 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
208 .withSerializer(SERIALIZER)
209 .withName("onos-networkId-hostIds")
210 .withRelaxedReadConsistency()
211 .build();
212 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
213
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500214 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
215 .withSerializer(SERIALIZER)
216 .withName("onos-networkId-virtuallinks")
217 .withRelaxedReadConsistency()
218 .build();
219 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
220
221 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
222 .withSerializer(SERIALIZER)
223 .withName("onos-networkId-virtualportss")
224 .withRelaxedReadConsistency()
225 .build();
226 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
227
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700228 log.info("Started");
229 }
230
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500231 /**
232 * Distributed network store service deactivate method.
233 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700234 @Deactivate
235 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500236 tenantIdSet.removeListener(setListener);
237 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700238 log.info("Stopped");
239 }
240
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500241 /**
242 * This method is used for Junit tests to set the CoreService instance, which
243 * is required to set the IdGenerator instance.
244 *
245 * @param coreService core service instance
246 */
247 public void setCoreService(CoreService coreService) {
248 this.coreService = coreService;
249 }
250
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700251 @Override
252 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500253 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700254 }
255
256 @Override
257 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500258 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700259 }
260
261 @Override
262 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500263 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700264 }
265
266 @Override
267 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500268
269 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
270 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
271 //TODO update both maps in one transaction.
272 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500273
274 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
275 if (networkIdSet == null) {
276 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500277 }
Brian Stanke5df14472016-03-11 19:34:38 -0500278 networkIdSet.add(virtualNetwork.id());
279 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
280
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500281 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700282 }
283
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500284 /**
285 * Returns a new network identifier from a virtual network block of identifiers.
286 *
287 * @return NetworkId network identifier
288 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700289 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900290 NetworkId networkId;
291 do {
292 networkId = NetworkId.networkId(idGenerator.getNewId());
293 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700294
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900295 return networkId;
296 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700297
298 @Override
299 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500300 // Make sure that the virtual network exists before attempting to remove it.
301 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500302 //TODO update both maps in one transaction.
303
304 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500305 if (virtualNetwork == null) {
306 return;
307 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500308 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500309
Brian Stanke5df14472016-03-11 19:34:38 -0500310 Set<NetworkId> networkIdSet = new HashSet<>();
311 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
312 if (networkId1.id().equals(networkId.id())) {
313 networkIdSet.add(networkId1);
314 }
315 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500316
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500317 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
318 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700319 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500320 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700321 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500322 }
323 });
324 }
325 }
326
327 /**
328 * Returns if the network identifier exists.
329 *
330 * @param networkId network identifier
331 * @return true if the network identifier exists, false otherwise.
332 */
333 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400334 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500335 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700336 }
337
338 @Override
339 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500340 checkState(networkExists(networkId), "The network has not been added.");
341 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
342 if (deviceIdSet == null) {
343 deviceIdSet = new HashSet<>();
344 }
345 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
346 //TODO update both maps in one transaction.
347 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
348 deviceIdSet.add(deviceId);
349 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
350 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700351 }
352
353 @Override
354 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500355 checkState(networkExists(networkId), "The network has not been added.");
356 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500357
358 Set<DeviceId> deviceIdSet = new HashSet<>();
359 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
360 if (deviceId1.equals(deviceId)) {
361 deviceIdSet.add(deviceId1);
362 }
363 });
364
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500365 if (deviceIdSet != null) {
366 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
367 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700368 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500369 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700370 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500371 }
372 });
373
Brian Stanke5df14472016-03-11 19:34:38 -0500374 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500375 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400376 //TODO remove virtual links and ports when removing the virtual device
377 }
378
379 @Override
380 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
381 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
382 checkState(networkExists(networkId), "The network has not been added.");
383 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
384 if (hostIdSet == null) {
385 hostIdSet = new HashSet<>();
386 }
387 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
388 //TODO update both maps in one transaction.
389 hostIdVirtualHostMap.put(hostId, virtualhost);
390 hostIdSet.add(hostId);
391 networkIdHostIdSetMap.put(networkId, hostIdSet);
392 return virtualhost;
393 }
394
395 @Override
396 public void removeHost(NetworkId networkId, HostId hostId) {
397 checkState(networkExists(networkId), "The network has not been added.");
398 //TODO update both maps in one transaction.
399
400 Set<HostId> hostIdSet = new HashSet<>();
401 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
402 if (hostId1.equals(hostId)) {
403 hostIdSet.add(hostId1);
404 }
405 });
406
407 if (hostIdSet != null) {
408 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
409 if (existingHostIds == null || existingHostIds.isEmpty()) {
410 return new HashSet<>();
411 } else {
412 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
413 }
414 });
415
416 hostIdVirtualHostMap.remove(hostId);
417 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700418 }
419
420 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400421 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
422 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500423 checkState(networkExists(networkId), "The network has not been added.");
424 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
425 if (virtualLinkSet == null) {
426 virtualLinkSet = new HashSet<>();
427 }
Brian Stanke9a108972016-04-11 15:25:17 -0400428 // validate that the link does not already exist in this network
429 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
430
431 VirtualLink virtualLink = DefaultVirtualLink.builder()
432 .networkId(networkId)
433 .src(src)
434 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400435 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400436 .tunnelId(realizedBy)
437 .build();
438
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500439 virtualLinkSet.add(virtualLink);
440 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
441 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700442 }
443
444 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400445 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400446 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
447 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
448 if (virtualLinkSet == null) {
449 virtualLinkSet = new HashSet<>();
450 }
451 virtualLinkSet.remove(virtualLink);
452
453 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
454 .networkId(virtualLink.networkId())
455 .src(virtualLink.src())
456 .dst(virtualLink.dst())
457 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400458 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400459 .build();
460
461 virtualLinkSet.add(newVirtualLink);
462 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
463 }
464
465 @Override
466 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500467 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500468
Brian Stanke9a108972016-04-11 15:25:17 -0400469 final VirtualLink virtualLink = getLink(networkId, src, dst);
470 if (virtualLink == null) {
471 return null;
472 }
Brian Stanke5df14472016-03-11 19:34:38 -0500473 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400474 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500475
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500476 if (virtualLinkSet != null) {
477 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
478 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700479 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500480 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700481 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500482 }
483 });
484 }
Brian Stanke9a108972016-04-11 15:25:17 -0400485 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700486 }
487
488 @Override
489 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500490 checkState(networkExists(networkId), "The network has not been added.");
491 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
492 if (virtualPortSet == null) {
493 virtualPortSet = new HashSet<>();
494 }
495 Device device = deviceIdVirtualDeviceMap.get(deviceId);
496 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
497 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
498 virtualPortSet.add(virtualPort);
499 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
500 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700501 }
502
503 @Override
504 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
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
507 Set<VirtualPort> virtualPortSet = new HashSet<>();
508 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
509 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
510 virtualPortSet.add(port);
511 }
512 });
513
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500514 if (virtualPortSet != null) {
515 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
516 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700517 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500518 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700519 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500520 }
521 });
522 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700523 }
524
525 @Override
526 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500527 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
528 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
529 if (networkIdSet != null) {
530 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
531 }
532 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700533 }
534
535 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400536 public VirtualNetwork getNetwork(NetworkId networkId) {
537 return networkIdVirtualNetworkMap.get(networkId);
538 }
539
540 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700541 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500542 checkState(networkExists(networkId), "The network has not been added.");
543 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
544 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
545 if (deviceIdSet != null) {
546 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
547 }
548 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700549 }
550
551 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400552 public Set<VirtualHost> getHosts(NetworkId networkId) {
553 checkState(networkExists(networkId), "The network has not been added.");
554 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
555 Set<VirtualHost> virtualHostSet = new HashSet<>();
556 if (hostIdSet != null) {
557 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
558 }
559 return ImmutableSet.copyOf(virtualHostSet);
560 }
561
562 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700563 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500564 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500565 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
566 if (virtualLinkSet == null) {
567 virtualLinkSet = new HashSet<>();
568 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500569 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700570 }
571
Brian Stanke612cebf2016-05-02 10:21:33 -0400572 @Override
573 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400574 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
575 if (virtualLinkSet == null) {
576 return null;
577 }
578
579 VirtualLink virtualLink = null;
580 for (VirtualLink link : virtualLinkSet) {
581 if (link.src().equals(src) && link.dst().equals(dst)) {
582 virtualLink = link;
583 break;
584 }
585 }
586 return virtualLink;
587 }
588
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700589 @Override
590 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500591 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500592 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
593 if (virtualPortSet == null) {
594 virtualPortSet = new HashSet<>();
595 }
596
Brian Stanke612cebf2016-05-02 10:21:33 -0400597 if (deviceId == null) {
598 return ImmutableSet.copyOf(virtualPortSet);
599 }
600
Brian Stanke5df14472016-03-11 19:34:38 -0500601 Set<VirtualPort> portSet = new HashSet<>();
602 virtualPortSet.forEach(virtualPort -> {
603 if (virtualPort.element().id().equals(deviceId)) {
604 portSet.add(virtualPort);
605 }
606 });
607 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500608 }
609
610 /**
611 * Listener class to map listener set events to the virtual network events.
612 */
613 private class InternalSetListener implements SetEventListener<TenantId> {
614 @Override
615 public void event(SetEvent<TenantId> event) {
616 VirtualNetworkEvent.Type type = null;
617 switch (event.type()) {
618 case ADD:
619 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
620 break;
621 case REMOVE:
622 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
623 break;
624 default:
625 log.error("Unsupported event type: " + event.type());
626 }
627 notifyDelegate(new VirtualNetworkEvent(type, null));
628 }
629 }
630
631 /**
632 * Listener class to map listener map events to the virtual network events.
633 */
634 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
635 @Override
636 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
637 NetworkId networkId = checkNotNull(event.key());
638 VirtualNetworkEvent.Type type = null;
639 switch (event.type()) {
640 case INSERT:
641 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
642 break;
643 case UPDATE:
644 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
645 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
646 } else {
647 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
648 }
649 break;
650 case REMOVE:
651 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
652 break;
653 default:
654 log.error("Unsupported event type: " + event.type());
655 }
656 notifyDelegate(new VirtualNetworkEvent(type, networkId));
657 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700658 }
659}