blob: d3390a60e3cfa33ffc4ccd164e9eb990f0be0db7 [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;
Claudine Chiu7f872a72016-12-16 13:51:39 -050077import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050078import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070079
Brian Stanke0e5c94e2016-03-08 11:20:04 -050080import static com.google.common.base.Preconditions.checkNotNull;
81import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070082import static org.slf4j.LoggerFactory.getLogger;
83
84/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050085 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070086 */
87@Component(immediate = true)
88@Service
89public class DistributedVirtualNetworkStore
90 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
91 implements VirtualNetworkStore {
92
93 private final Logger log = getLogger(getClass());
94
Brian Stanke0e5c94e2016-03-08 11:20:04 -050095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070097
Brian Stanke0e5c94e2016-03-08 11:20:04 -050098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700100
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500101 private IdGenerator idGenerator;
102
103 // Track tenants by ID
104 private DistributedSet<TenantId> tenantIdSet;
105
106 // Listener for tenant events
107 private final SetEventListener<TenantId> setListener = new InternalSetListener();
108
109 // Track virtual networks by network Id
110 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
111 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
112
113 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500114 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
115 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
116 VirtualNetworkEvent.Type eventType =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900117 mapEventType.equals(MapEvent.Type.INSERT)
118 ? VirtualNetworkEvent.Type.NETWORK_ADDED :
119 mapEventType.equals(MapEvent.Type.UPDATE)
120 ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
121 mapEventType.equals(MapEvent.Type.REMOVE)
122 ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
Claudine Chiu945828d2016-11-21 12:47:07 -0500123 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
124 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500125
sangyun-han3c3e99e2017-02-08 15:30:53 +0900126 // Listener for virtual device events
127 private final MapEventListener<DeviceId, VirtualDevice> virtualDeviceMapListener =
128 new InternalMapListener<>((mapEventType, virtualDevice) -> {
129 VirtualNetworkEvent.Type eventType =
130 mapEventType.equals(MapEvent.Type.INSERT)
131 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
132 mapEventType.equals(MapEvent.Type.UPDATE)
133 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
134 mapEventType.equals(MapEvent.Type.REMOVE)
135 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
136 return eventType == null ? null :
137 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
138 });
139
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500140 // Track virtual network IDs by tenant Id
141 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
142 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
143
144 // Track virtual devices by device Id
145 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
146 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
147
148 // Track device IDs by network Id
149 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
150 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
151
Brian Stanke7a81b532016-06-14 15:43:51 -0400152 // Track virtual hosts by host Id
153 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
154 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
155
156 // Track host IDs by network Id
157 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
158 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
159
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500160 // Track virtual links by network Id
161 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
162 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
163
164 // Track virtual ports by network Id
165 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
166 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
167
Brian Stanke11f6d532016-07-05 16:17:59 -0400168 // Track intent key to intent data
169 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
170 private Map<Key, IntentData> intentKeyIntentDataMap;
171
172 // Track intent ID to TunnelIds
173 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
174 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
175
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500176 private static final Serializer SERIALIZER = Serializer
177 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
178 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700179 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500180 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500181 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500182 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500183 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400184 .register(VirtualHost.class)
185 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500186 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500187 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500188 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500189 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500190 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400191 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400192 .register(IntentData.class)
193 .register(VirtualNetworkIntent.class)
194 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700195 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400196 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500197
198 /**
199 * Distributed network store service activate method.
200 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700201 @Activate
202 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500203 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
204
205 tenantIdSet = storageService.<TenantId>setBuilder()
206 .withSerializer(SERIALIZER)
207 .withName("onos-tenantId")
208 .withRelaxedReadConsistency()
209 .build()
210 .asDistributedSet();
211 tenantIdSet.addListener(setListener);
212
213 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
214 .withSerializer(SERIALIZER)
215 .withName("onos-networkId-virtualnetwork")
216 .withRelaxedReadConsistency()
217 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500218 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500219 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
220
221 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
222 .withSerializer(SERIALIZER)
223 .withName("onos-tenantId-networkIds")
224 .withRelaxedReadConsistency()
225 .build();
226 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
227
228 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
229 .withSerializer(SERIALIZER)
230 .withName("onos-deviceId-virtualdevice")
231 .withRelaxedReadConsistency()
232 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500233 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500234 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
235
236 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
237 .withSerializer(SERIALIZER)
238 .withName("onos-networkId-deviceIds")
239 .withRelaxedReadConsistency()
240 .build();
241 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
242
Brian Stanke7a81b532016-06-14 15:43:51 -0400243 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
244 .withSerializer(SERIALIZER)
245 .withName("onos-hostId-virtualhost")
246 .withRelaxedReadConsistency()
247 .build();
248 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
249
250 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
251 .withSerializer(SERIALIZER)
252 .withName("onos-networkId-hostIds")
253 .withRelaxedReadConsistency()
254 .build();
255 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
256
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500257 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
258 .withSerializer(SERIALIZER)
259 .withName("onos-networkId-virtuallinks")
260 .withRelaxedReadConsistency()
261 .build();
262 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
263
264 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
265 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400266 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500267 .withRelaxedReadConsistency()
268 .build();
269 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
270
Brian Stanke11f6d532016-07-05 16:17:59 -0400271 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
272 .withSerializer(SERIALIZER)
273 .withName("onos-intentKey-tunnelIds")
274 .withRelaxedReadConsistency()
275 .build();
276 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
277
278 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
279 .withSerializer(SERIALIZER)
280 .withName("onos-intentKey-intentData")
281 .withRelaxedReadConsistency()
282 .build();
283 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
284
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 log.info("Started");
286 }
287
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500288 /**
289 * Distributed network store service deactivate method.
290 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700291 @Deactivate
292 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500293 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500294 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
295 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700296 log.info("Stopped");
297 }
298
299 @Override
300 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500301 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700302 }
303
304 @Override
305 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500306 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700307 }
308
309 @Override
310 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500311 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700312 }
313
314 @Override
315 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500316
317 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
318 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
319 //TODO update both maps in one transaction.
320 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500321
322 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
323 if (networkIdSet == null) {
324 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500325 }
Brian Stanke5df14472016-03-11 19:34:38 -0500326 networkIdSet.add(virtualNetwork.id());
327 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
328
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500329 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700330 }
331
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500332 /**
333 * Returns a new network identifier from a virtual network block of identifiers.
334 *
335 * @return NetworkId network identifier
336 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700337 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900338 NetworkId networkId;
339 do {
340 networkId = NetworkId.networkId(idGenerator.getNewId());
341 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700342
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900343 return networkId;
344 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700345
346 @Override
347 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500348 // Make sure that the virtual network exists before attempting to remove it.
349 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500350 //TODO update both maps in one transaction.
351
352 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500353 if (virtualNetwork == null) {
354 return;
355 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500356 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500357
Brian Stanke5df14472016-03-11 19:34:38 -0500358 Set<NetworkId> networkIdSet = new HashSet<>();
359 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
360 if (networkId1.id().equals(networkId.id())) {
361 networkIdSet.add(networkId1);
362 }
363 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500364
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500365 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
366 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700367 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500368 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700369 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500370 }
371 });
372 }
373 }
374
375 /**
376 * Returns if the network identifier exists.
377 *
378 * @param networkId network identifier
379 * @return true if the network identifier exists, false otherwise.
380 */
381 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400382 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500383 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700384 }
385
386 @Override
387 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500388 checkState(networkExists(networkId), "The network has not been added.");
389 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
390 if (deviceIdSet == null) {
391 deviceIdSet = new HashSet<>();
392 }
393 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
394 //TODO update both maps in one transaction.
395 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
396 deviceIdSet.add(deviceId);
397 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
398 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700399 }
400
401 @Override
402 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500403 checkState(networkExists(networkId), "The network has not been added.");
404 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500405
406 Set<DeviceId> deviceIdSet = new HashSet<>();
407 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
408 if (deviceId1.equals(deviceId)) {
409 deviceIdSet.add(deviceId1);
410 }
411 });
412
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500413 if (deviceIdSet != null) {
414 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
415 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700416 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500417 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700418 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500419 }
420 });
421
Brian Stanke5df14472016-03-11 19:34:38 -0500422 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500423 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400424 //TODO remove virtual links and ports when removing the virtual device
425 }
426
427 @Override
428 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
429 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
430 checkState(networkExists(networkId), "The network has not been added.");
431 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
432 if (hostIdSet == null) {
433 hostIdSet = new HashSet<>();
434 }
435 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
436 //TODO update both maps in one transaction.
437 hostIdVirtualHostMap.put(hostId, virtualhost);
438 hostIdSet.add(hostId);
439 networkIdHostIdSetMap.put(networkId, hostIdSet);
440 return virtualhost;
441 }
442
443 @Override
444 public void removeHost(NetworkId networkId, HostId hostId) {
445 checkState(networkExists(networkId), "The network has not been added.");
446 //TODO update both maps in one transaction.
447
448 Set<HostId> hostIdSet = new HashSet<>();
449 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
450 if (hostId1.equals(hostId)) {
451 hostIdSet.add(hostId1);
452 }
453 });
454
455 if (hostIdSet != null) {
456 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
457 if (existingHostIds == null || existingHostIds.isEmpty()) {
458 return new HashSet<>();
459 } else {
460 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
461 }
462 });
463
464 hostIdVirtualHostMap.remove(hostId);
465 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700466 }
467
468 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400469 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
470 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500471 checkState(networkExists(networkId), "The network has not been added.");
472 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
473 if (virtualLinkSet == null) {
474 virtualLinkSet = new HashSet<>();
475 }
Brian Stanke9a108972016-04-11 15:25:17 -0400476 // validate that the link does not already exist in this network
477 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
478
479 VirtualLink virtualLink = DefaultVirtualLink.builder()
480 .networkId(networkId)
481 .src(src)
482 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400483 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400484 .tunnelId(realizedBy)
485 .build();
486
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500487 virtualLinkSet.add(virtualLink);
488 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
489 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700490 }
491
492 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400493 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400494 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
495 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
496 if (virtualLinkSet == null) {
497 virtualLinkSet = new HashSet<>();
498 }
499 virtualLinkSet.remove(virtualLink);
500
501 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
502 .networkId(virtualLink.networkId())
503 .src(virtualLink.src())
504 .dst(virtualLink.dst())
505 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400506 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400507 .build();
508
509 virtualLinkSet.add(newVirtualLink);
510 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
511 }
512
513 @Override
514 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500515 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500516
Brian Stanke9a108972016-04-11 15:25:17 -0400517 final VirtualLink virtualLink = getLink(networkId, src, dst);
518 if (virtualLink == null) {
519 return null;
520 }
Brian Stanke5df14472016-03-11 19:34:38 -0500521 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400522 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500523
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500524 if (virtualLinkSet != null) {
525 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
526 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700527 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500528 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700529 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500530 }
531 });
532 }
Brian Stanke9a108972016-04-11 15:25:17 -0400533 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700534 }
535
536 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700537 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
538 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500539 checkState(networkExists(networkId), "The network has not been added.");
540 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700541
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500542 if (virtualPortSet == null) {
543 virtualPortSet = new HashSet<>();
544 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700545
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500546 Device device = deviceIdVirtualDeviceMap.get(deviceId);
547 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700548
549 boolean exist = virtualPortSet.stream().anyMatch(
550 p -> p.element().id().equals(deviceId) &&
551 p.number().equals(portNumber));
552 checkState(!exist, "The requested Port Number is already in use");
553
554 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
555 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500556 virtualPortSet.add(virtualPort);
557 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500558 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
559 networkId, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500560 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700561 }
562
563 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700564 public void bindPort(NetworkId networkId, DeviceId deviceId,
565 PortNumber portNumber, ConnectPoint realizedBy) {
566
567 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
568 .get(networkId);
569
570 VirtualPort vPort = virtualPortSet.stream().filter(
571 p -> p.element().id().equals(deviceId) &&
572 p.number().equals(portNumber)).findFirst().get();
573 checkNotNull(vPort, "The virtual port has not been added.");
574
575 Device device = deviceIdVirtualDeviceMap.get(deviceId);
576 checkNotNull(device, "The device has not been created for deviceId: "
577 + deviceId);
578
579 virtualPortSet.remove(vPort);
580 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
581 virtualPortSet.add(vPort);
582 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500583 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
584 networkId, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700585 }
586
587 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700588 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500589 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500590
591 Set<VirtualPort> virtualPortSet = new HashSet<>();
592 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
593 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
594 virtualPortSet.add(port);
595 }
596 });
597
Claudine Chiu7f872a72016-12-16 13:51:39 -0500598 if (!virtualPortSet.isEmpty()) {
599 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500600 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
601 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700602 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500603 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500604 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700605 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500606 }
607 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500608 if (portRemoved.get()) {
609 virtualPortSet.forEach(virtualPort -> notifyDelegate(
610 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
611 networkId, virtualPort)
612 ));
613 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500614 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700615 }
616
617 @Override
618 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500619 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
620 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
621 if (networkIdSet != null) {
622 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
623 }
624 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700625 }
626
627 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400628 public VirtualNetwork getNetwork(NetworkId networkId) {
629 return networkIdVirtualNetworkMap.get(networkId);
630 }
631
632 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700633 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500634 checkState(networkExists(networkId), "The network has not been added.");
635 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
636 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
637 if (deviceIdSet != null) {
638 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
639 }
640 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700641 }
642
643 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400644 public Set<VirtualHost> getHosts(NetworkId networkId) {
645 checkState(networkExists(networkId), "The network has not been added.");
646 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
647 Set<VirtualHost> virtualHostSet = new HashSet<>();
648 if (hostIdSet != null) {
649 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
650 }
651 return ImmutableSet.copyOf(virtualHostSet);
652 }
653
654 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700655 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500656 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500657 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
658 if (virtualLinkSet == null) {
659 virtualLinkSet = new HashSet<>();
660 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500661 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700662 }
663
Brian Stanke612cebf2016-05-02 10:21:33 -0400664 @Override
665 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400666 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
667 if (virtualLinkSet == null) {
668 return null;
669 }
670
671 VirtualLink virtualLink = null;
672 for (VirtualLink link : virtualLinkSet) {
673 if (link.src().equals(src) && link.dst().equals(dst)) {
674 virtualLink = link;
675 break;
676 }
677 }
678 return virtualLink;
679 }
680
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700681 @Override
682 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500683 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500684 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
685 if (virtualPortSet == null) {
686 virtualPortSet = new HashSet<>();
687 }
688
Brian Stanke612cebf2016-05-02 10:21:33 -0400689 if (deviceId == null) {
690 return ImmutableSet.copyOf(virtualPortSet);
691 }
692
Brian Stanke5df14472016-03-11 19:34:38 -0500693 Set<VirtualPort> portSet = new HashSet<>();
694 virtualPortSet.forEach(virtualPort -> {
695 if (virtualPort.element().id().equals(deviceId)) {
696 portSet.add(virtualPort);
697 }
698 });
699 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500700 }
701
Brian Stanke11f6d532016-07-05 16:17:59 -0400702 @Override
703 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
704 checkNotNull(intent, "Intent cannot be null");
705 IntentData intentData = removeIntent(intent.key());
706 if (intentData == null) {
707 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
708 } else {
709 intentData = new IntentData(intent, state, intentData.version());
710 }
711 intentKeyIntentDataMap.put(intent.key(), intentData);
712 }
713
714 @Override
715 public IntentData removeIntent(Key intentKey) {
716 checkNotNull(intentKey, "Intent key cannot be null");
717 return intentKeyIntentDataMap.remove(intentKey);
718 }
719
720 @Override
721 public void addTunnelId(Intent intent, TunnelId tunnelId) {
722 // Add the tunnelId to the intent key set map
723 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
724 if (tunnelIdSet == null) {
725 tunnelIdSet = new HashSet<>();
726 }
727 tunnelIdSet.add(tunnelId);
728 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
729 }
730
731 @Override
732 public Set<TunnelId> getTunnelIds(Intent intent) {
733 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
734 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
735 }
736
737 @Override
738 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
739 Set<TunnelId> tunnelIdSet = new HashSet<>();
740 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
741 if (tunnelId1.equals(tunnelId)) {
742 tunnelIdSet.add(tunnelId);
743 }
744 });
745
746 if (!tunnelIdSet.isEmpty()) {
747 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
748 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
749 return new HashSet<>();
750 } else {
751 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
752 }
753 });
754 }
755 }
756
757 @Override
758 public Set<Intent> getIntents() {
759 Set<Intent> intents = new HashSet<>();
760 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
761 return ImmutableSet.copyOf(intents);
762 }
763
764 @Override
765 public Intent getIntent(Key key) {
766 IntentData intentData = intentKeyIntentDataMap.get(key);
767 return intentData == null ? null : intentData.intent();
768 }
769
770 @Override
771 public Set<IntentData> getIntentData() {
772 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
773 }
774
775 @Override
776 public IntentData getIntentData(Key key) {
777 IntentData intentData = intentKeyIntentDataMap.get(key);
778 return intentData == null ? null : new IntentData(intentData);
779 }
780
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500781 /**
782 * Listener class to map listener set events to the virtual network events.
783 */
784 private class InternalSetListener implements SetEventListener<TenantId> {
785 @Override
786 public void event(SetEvent<TenantId> event) {
787 VirtualNetworkEvent.Type type = null;
788 switch (event.type()) {
789 case ADD:
790 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
791 break;
792 case REMOVE:
793 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
794 break;
795 default:
796 log.error("Unsupported event type: " + event.type());
797 }
798 notifyDelegate(new VirtualNetworkEvent(type, null));
799 }
800 }
801
802 /**
803 * Listener class to map listener map events to the virtual network events.
804 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500805 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
806
807 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
808
809 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
810 this.createEvent = createEvent;
811 }
812
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500813 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500814 public void event(MapEvent<K, V> event) {
815 checkNotNull(event.key());
816 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500817 switch (event.type()) {
818 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500819 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500820 break;
821 case UPDATE:
822 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500823 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500824 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500825 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500826 }
827 break;
828 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500829 if (event.oldValue() != null) {
830 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
831 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500832 break;
833 default:
834 log.error("Unsupported event type: " + event.type());
835 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500836 if (vnetEvent != null) {
837 notifyDelegate(vnetEvent);
838 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500839 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700840 }
841}