blob: 9007c2141335f88b4a68d842e3c6f9b58047baeb [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 Stanke11f6d532016-07-05 16:17:59 -040045import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050046import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070047import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
48import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
49import org.onosproject.incubator.net.virtual.VirtualPort;
50import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050051import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070052import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040053import org.onosproject.net.HostId;
54import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040055import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070056import org.onosproject.net.PortNumber;
Brian Stanke11f6d532016-07-05 16:17:59 -040057import org.onosproject.net.intent.Intent;
58import org.onosproject.net.intent.IntentData;
59import org.onosproject.net.intent.IntentState;
60import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070061import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050062import org.onosproject.store.serializers.KryoNamespaces;
63import org.onosproject.store.service.ConsistentMap;
64import org.onosproject.store.service.DistributedSet;
65import org.onosproject.store.service.MapEvent;
66import org.onosproject.store.service.MapEventListener;
67import org.onosproject.store.service.Serializer;
68import org.onosproject.store.service.SetEvent;
69import org.onosproject.store.service.SetEventListener;
70import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040071import org.onosproject.store.service.WallClockTimestamp;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import org.slf4j.Logger;
73
Brian Stanke0e5c94e2016-03-08 11:20:04 -050074import java.util.HashSet;
75import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076import java.util.Set;
77
Brian Stanke0e5c94e2016-03-08 11:20:04 -050078import static com.google.common.base.Preconditions.checkNotNull;
79import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070080import static org.slf4j.LoggerFactory.getLogger;
81
82/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050083 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070084 */
85@Component(immediate = true)
86@Service
87public class DistributedVirtualNetworkStore
88 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
89 implements VirtualNetworkStore {
90
91 private final Logger log = getLogger(getClass());
92
Brian Stanke0e5c94e2016-03-08 11:20:04 -050093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070095
Brian Stanke0e5c94e2016-03-08 11:20:04 -050096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070098
Brian Stanke0e5c94e2016-03-08 11:20:04 -050099 private IdGenerator idGenerator;
100
101 // Track tenants by ID
102 private DistributedSet<TenantId> tenantIdSet;
103
104 // Listener for tenant events
105 private final SetEventListener<TenantId> setListener = new InternalSetListener();
106
107 // Track virtual networks by network Id
108 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
109 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
110
111 // Listener for virtual network events
112 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
113
114 // Track virtual network IDs by tenant Id
115 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
116 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
117
118 // Track virtual devices by device Id
119 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
120 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
121
122 // Track device IDs by network Id
123 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
124 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
125
Brian Stanke7a81b532016-06-14 15:43:51 -0400126 // Track virtual hosts by host Id
127 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
128 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
129
130 // Track host IDs by network Id
131 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
132 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
133
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500134 // Track virtual links by network Id
135 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
136 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
137
138 // Track virtual ports by network Id
139 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
140 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
141
Brian Stanke11f6d532016-07-05 16:17:59 -0400142 // Track intent key to intent data
143 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
144 private Map<Key, IntentData> intentKeyIntentDataMap;
145
146 // Track intent ID to TunnelIds
147 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
148 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
149
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500150 private static final Serializer SERIALIZER = Serializer
151 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
152 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700153 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500154 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500155 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500156 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500157 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400158 .register(VirtualHost.class)
159 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500160 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500161 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500162 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500163 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500164 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400165 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400166 .register(IntentData.class)
167 .register(VirtualNetworkIntent.class)
168 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700169 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400170 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500171
172 /**
173 * Distributed network store service activate method.
174 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700175 @Activate
176 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500177 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
178
179 tenantIdSet = storageService.<TenantId>setBuilder()
180 .withSerializer(SERIALIZER)
181 .withName("onos-tenantId")
182 .withRelaxedReadConsistency()
183 .build()
184 .asDistributedSet();
185 tenantIdSet.addListener(setListener);
186
187 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
188 .withSerializer(SERIALIZER)
189 .withName("onos-networkId-virtualnetwork")
190 .withRelaxedReadConsistency()
191 .build();
192 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
193 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
194
195 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
196 .withSerializer(SERIALIZER)
197 .withName("onos-tenantId-networkIds")
198 .withRelaxedReadConsistency()
199 .build();
200 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
201
202 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
203 .withSerializer(SERIALIZER)
204 .withName("onos-deviceId-virtualdevice")
205 .withRelaxedReadConsistency()
206 .build();
207 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
208
209 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
210 .withSerializer(SERIALIZER)
211 .withName("onos-networkId-deviceIds")
212 .withRelaxedReadConsistency()
213 .build();
214 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
215
Brian Stanke7a81b532016-06-14 15:43:51 -0400216 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
217 .withSerializer(SERIALIZER)
218 .withName("onos-hostId-virtualhost")
219 .withRelaxedReadConsistency()
220 .build();
221 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
222
223 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
224 .withSerializer(SERIALIZER)
225 .withName("onos-networkId-hostIds")
226 .withRelaxedReadConsistency()
227 .build();
228 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
229
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500230 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
231 .withSerializer(SERIALIZER)
232 .withName("onos-networkId-virtuallinks")
233 .withRelaxedReadConsistency()
234 .build();
235 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
236
237 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
238 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400239 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500240 .withRelaxedReadConsistency()
241 .build();
242 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
243
Brian Stanke11f6d532016-07-05 16:17:59 -0400244 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
245 .withSerializer(SERIALIZER)
246 .withName("onos-intentKey-tunnelIds")
247 .withRelaxedReadConsistency()
248 .build();
249 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
250
251 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
252 .withSerializer(SERIALIZER)
253 .withName("onos-intentKey-intentData")
254 .withRelaxedReadConsistency()
255 .build();
256 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
257
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700258 log.info("Started");
259 }
260
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500261 /**
262 * Distributed network store service deactivate method.
263 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700264 @Deactivate
265 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500266 tenantIdSet.removeListener(setListener);
267 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700268 log.info("Stopped");
269 }
270
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500271 /**
272 * This method is used for Junit tests to set the CoreService instance, which
273 * is required to set the IdGenerator instance.
274 *
275 * @param coreService core service instance
276 */
277 public void setCoreService(CoreService coreService) {
278 this.coreService = coreService;
279 }
280
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700281 @Override
282 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500283 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700284 }
285
286 @Override
287 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500288 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700289 }
290
291 @Override
292 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500293 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700294 }
295
296 @Override
297 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500298
299 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
300 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
301 //TODO update both maps in one transaction.
302 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500303
304 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
305 if (networkIdSet == null) {
306 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500307 }
Brian Stanke5df14472016-03-11 19:34:38 -0500308 networkIdSet.add(virtualNetwork.id());
309 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
310
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500311 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700312 }
313
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500314 /**
315 * Returns a new network identifier from a virtual network block of identifiers.
316 *
317 * @return NetworkId network identifier
318 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700319 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900320 NetworkId networkId;
321 do {
322 networkId = NetworkId.networkId(idGenerator.getNewId());
323 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700324
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900325 return networkId;
326 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700327
328 @Override
329 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500330 // Make sure that the virtual network exists before attempting to remove it.
331 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500332 //TODO update both maps in one transaction.
333
334 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500335 if (virtualNetwork == null) {
336 return;
337 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500338 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500339
Brian Stanke5df14472016-03-11 19:34:38 -0500340 Set<NetworkId> networkIdSet = new HashSet<>();
341 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
342 if (networkId1.id().equals(networkId.id())) {
343 networkIdSet.add(networkId1);
344 }
345 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500346
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500347 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
348 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700349 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500350 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700351 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500352 }
353 });
354 }
355 }
356
357 /**
358 * Returns if the network identifier exists.
359 *
360 * @param networkId network identifier
361 * @return true if the network identifier exists, false otherwise.
362 */
363 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400364 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500365 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700366 }
367
368 @Override
369 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500370 checkState(networkExists(networkId), "The network has not been added.");
371 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
372 if (deviceIdSet == null) {
373 deviceIdSet = new HashSet<>();
374 }
375 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
376 //TODO update both maps in one transaction.
377 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
378 deviceIdSet.add(deviceId);
379 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
380 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700381 }
382
383 @Override
384 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500385 checkState(networkExists(networkId), "The network has not been added.");
386 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500387
388 Set<DeviceId> deviceIdSet = new HashSet<>();
389 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
390 if (deviceId1.equals(deviceId)) {
391 deviceIdSet.add(deviceId1);
392 }
393 });
394
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500395 if (deviceIdSet != null) {
396 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
397 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700398 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500399 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700400 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500401 }
402 });
403
Brian Stanke5df14472016-03-11 19:34:38 -0500404 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500405 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400406 //TODO remove virtual links and ports when removing the virtual device
407 }
408
409 @Override
410 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
411 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
412 checkState(networkExists(networkId), "The network has not been added.");
413 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
414 if (hostIdSet == null) {
415 hostIdSet = new HashSet<>();
416 }
417 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
418 //TODO update both maps in one transaction.
419 hostIdVirtualHostMap.put(hostId, virtualhost);
420 hostIdSet.add(hostId);
421 networkIdHostIdSetMap.put(networkId, hostIdSet);
422 return virtualhost;
423 }
424
425 @Override
426 public void removeHost(NetworkId networkId, HostId hostId) {
427 checkState(networkExists(networkId), "The network has not been added.");
428 //TODO update both maps in one transaction.
429
430 Set<HostId> hostIdSet = new HashSet<>();
431 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
432 if (hostId1.equals(hostId)) {
433 hostIdSet.add(hostId1);
434 }
435 });
436
437 if (hostIdSet != null) {
438 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
439 if (existingHostIds == null || existingHostIds.isEmpty()) {
440 return new HashSet<>();
441 } else {
442 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
443 }
444 });
445
446 hostIdVirtualHostMap.remove(hostId);
447 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700448 }
449
450 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400451 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
452 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500453 checkState(networkExists(networkId), "The network has not been added.");
454 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
455 if (virtualLinkSet == null) {
456 virtualLinkSet = new HashSet<>();
457 }
Brian Stanke9a108972016-04-11 15:25:17 -0400458 // validate that the link does not already exist in this network
459 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
460
461 VirtualLink virtualLink = DefaultVirtualLink.builder()
462 .networkId(networkId)
463 .src(src)
464 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400465 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400466 .tunnelId(realizedBy)
467 .build();
468
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500469 virtualLinkSet.add(virtualLink);
470 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
471 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700472 }
473
474 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400475 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400476 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
477 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
478 if (virtualLinkSet == null) {
479 virtualLinkSet = new HashSet<>();
480 }
481 virtualLinkSet.remove(virtualLink);
482
483 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
484 .networkId(virtualLink.networkId())
485 .src(virtualLink.src())
486 .dst(virtualLink.dst())
487 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400488 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400489 .build();
490
491 virtualLinkSet.add(newVirtualLink);
492 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
493 }
494
495 @Override
496 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500497 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500498
Brian Stanke9a108972016-04-11 15:25:17 -0400499 final VirtualLink virtualLink = getLink(networkId, src, dst);
500 if (virtualLink == null) {
501 return null;
502 }
Brian Stanke5df14472016-03-11 19:34:38 -0500503 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400504 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500505
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500506 if (virtualLinkSet != null) {
507 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
508 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700509 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500510 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700511 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500512 }
513 });
514 }
Brian Stanke9a108972016-04-11 15:25:17 -0400515 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700516 }
517
518 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700519 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
520 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500521 checkState(networkExists(networkId), "The network has not been added.");
522 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700523
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500524 if (virtualPortSet == null) {
525 virtualPortSet = new HashSet<>();
526 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700527
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500528 Device device = deviceIdVirtualDeviceMap.get(deviceId);
529 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700530
531 boolean exist = virtualPortSet.stream().anyMatch(
532 p -> p.element().id().equals(deviceId) &&
533 p.number().equals(portNumber));
534 checkState(!exist, "The requested Port Number is already in use");
535
536 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
537 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500538 virtualPortSet.add(virtualPort);
539 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
540 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700541 }
542
543 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700544 public void bindPort(NetworkId networkId, DeviceId deviceId,
545 PortNumber portNumber, ConnectPoint realizedBy) {
546
547 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
548 .get(networkId);
549
550 VirtualPort vPort = virtualPortSet.stream().filter(
551 p -> p.element().id().equals(deviceId) &&
552 p.number().equals(portNumber)).findFirst().get();
553 checkNotNull(vPort, "The virtual port has not been added.");
554
555 Device device = deviceIdVirtualDeviceMap.get(deviceId);
556 checkNotNull(device, "The device has not been created for deviceId: "
557 + deviceId);
558
559 virtualPortSet.remove(vPort);
560 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
561 virtualPortSet.add(vPort);
562 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
563 }
564
565 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700566 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500567 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500568
569 Set<VirtualPort> virtualPortSet = new HashSet<>();
570 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
571 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
572 virtualPortSet.add(port);
573 }
574 });
575
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500576 if (virtualPortSet != null) {
577 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
578 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700579 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500580 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700581 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500582 }
583 });
584 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700585 }
586
587 @Override
588 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500589 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
590 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
591 if (networkIdSet != null) {
592 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
593 }
594 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700595 }
596
597 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400598 public VirtualNetwork getNetwork(NetworkId networkId) {
599 return networkIdVirtualNetworkMap.get(networkId);
600 }
601
602 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700603 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500604 checkState(networkExists(networkId), "The network has not been added.");
605 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
606 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
607 if (deviceIdSet != null) {
608 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
609 }
610 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700611 }
612
613 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400614 public Set<VirtualHost> getHosts(NetworkId networkId) {
615 checkState(networkExists(networkId), "The network has not been added.");
616 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
617 Set<VirtualHost> virtualHostSet = new HashSet<>();
618 if (hostIdSet != null) {
619 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
620 }
621 return ImmutableSet.copyOf(virtualHostSet);
622 }
623
624 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700625 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500626 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500627 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
628 if (virtualLinkSet == null) {
629 virtualLinkSet = new HashSet<>();
630 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500631 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700632 }
633
Brian Stanke612cebf2016-05-02 10:21:33 -0400634 @Override
635 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400636 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
637 if (virtualLinkSet == null) {
638 return null;
639 }
640
641 VirtualLink virtualLink = null;
642 for (VirtualLink link : virtualLinkSet) {
643 if (link.src().equals(src) && link.dst().equals(dst)) {
644 virtualLink = link;
645 break;
646 }
647 }
648 return virtualLink;
649 }
650
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700651 @Override
652 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500653 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500654 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
655 if (virtualPortSet == null) {
656 virtualPortSet = new HashSet<>();
657 }
658
Brian Stanke612cebf2016-05-02 10:21:33 -0400659 if (deviceId == null) {
660 return ImmutableSet.copyOf(virtualPortSet);
661 }
662
Brian Stanke5df14472016-03-11 19:34:38 -0500663 Set<VirtualPort> portSet = new HashSet<>();
664 virtualPortSet.forEach(virtualPort -> {
665 if (virtualPort.element().id().equals(deviceId)) {
666 portSet.add(virtualPort);
667 }
668 });
669 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500670 }
671
Brian Stanke11f6d532016-07-05 16:17:59 -0400672 @Override
673 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
674 checkNotNull(intent, "Intent cannot be null");
675 IntentData intentData = removeIntent(intent.key());
676 if (intentData == null) {
677 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
678 } else {
679 intentData = new IntentData(intent, state, intentData.version());
680 }
681 intentKeyIntentDataMap.put(intent.key(), intentData);
682 }
683
684 @Override
685 public IntentData removeIntent(Key intentKey) {
686 checkNotNull(intentKey, "Intent key cannot be null");
687 return intentKeyIntentDataMap.remove(intentKey);
688 }
689
690 @Override
691 public void addTunnelId(Intent intent, TunnelId tunnelId) {
692 // Add the tunnelId to the intent key set map
693 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
694 if (tunnelIdSet == null) {
695 tunnelIdSet = new HashSet<>();
696 }
697 tunnelIdSet.add(tunnelId);
698 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
699 }
700
701 @Override
702 public Set<TunnelId> getTunnelIds(Intent intent) {
703 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
704 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
705 }
706
707 @Override
708 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
709 Set<TunnelId> tunnelIdSet = new HashSet<>();
710 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
711 if (tunnelId1.equals(tunnelId)) {
712 tunnelIdSet.add(tunnelId);
713 }
714 });
715
716 if (!tunnelIdSet.isEmpty()) {
717 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
718 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
719 return new HashSet<>();
720 } else {
721 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
722 }
723 });
724 }
725 }
726
727 @Override
728 public Set<Intent> getIntents() {
729 Set<Intent> intents = new HashSet<>();
730 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
731 return ImmutableSet.copyOf(intents);
732 }
733
734 @Override
735 public Intent getIntent(Key key) {
736 IntentData intentData = intentKeyIntentDataMap.get(key);
737 return intentData == null ? null : intentData.intent();
738 }
739
740 @Override
741 public Set<IntentData> getIntentData() {
742 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
743 }
744
745 @Override
746 public IntentData getIntentData(Key key) {
747 IntentData intentData = intentKeyIntentDataMap.get(key);
748 return intentData == null ? null : new IntentData(intentData);
749 }
750
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500751 /**
752 * Listener class to map listener set events to the virtual network events.
753 */
754 private class InternalSetListener implements SetEventListener<TenantId> {
755 @Override
756 public void event(SetEvent<TenantId> event) {
757 VirtualNetworkEvent.Type type = null;
758 switch (event.type()) {
759 case ADD:
760 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
761 break;
762 case REMOVE:
763 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
764 break;
765 default:
766 log.error("Unsupported event type: " + event.type());
767 }
768 notifyDelegate(new VirtualNetworkEvent(type, null));
769 }
770 }
771
772 /**
773 * Listener class to map listener map events to the virtual network events.
774 */
775 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
776 @Override
777 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
778 NetworkId networkId = checkNotNull(event.key());
779 VirtualNetworkEvent.Type type = null;
780 switch (event.type()) {
781 case INSERT:
782 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
783 break;
784 case UPDATE:
785 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
786 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
787 } else {
788 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
789 }
790 break;
791 case REMOVE:
792 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
793 break;
794 default:
795 log.error("Unsupported event type: " + event.type());
796 }
797 notifyDelegate(new VirtualNetworkEvent(type, networkId));
798 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700799 }
800}