blob: eb4e8b3125d0209de3ac0fde49be131743199f6f [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.Port;
57import org.onosproject.net.PortNumber;
Brian Stanke11f6d532016-07-05 16:17:59 -040058import org.onosproject.net.intent.Intent;
59import org.onosproject.net.intent.IntentData;
60import org.onosproject.net.intent.IntentState;
61import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070062import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050063import org.onosproject.store.serializers.KryoNamespaces;
64import org.onosproject.store.service.ConsistentMap;
65import org.onosproject.store.service.DistributedSet;
66import org.onosproject.store.service.MapEvent;
67import org.onosproject.store.service.MapEventListener;
68import org.onosproject.store.service.Serializer;
69import org.onosproject.store.service.SetEvent;
70import org.onosproject.store.service.SetEventListener;
71import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040072import org.onosproject.store.service.WallClockTimestamp;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070073import org.slf4j.Logger;
74
Brian Stanke0e5c94e2016-03-08 11:20:04 -050075import java.util.HashSet;
76import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070077import java.util.Set;
78
Brian Stanke0e5c94e2016-03-08 11:20:04 -050079import static com.google.common.base.Preconditions.checkNotNull;
80import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081import static org.slf4j.LoggerFactory.getLogger;
82
83/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050084 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070085 */
86@Component(immediate = true)
87@Service
88public class DistributedVirtualNetworkStore
89 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
90 implements VirtualNetworkStore {
91
92 private final Logger log = getLogger(getClass());
93
Brian Stanke0e5c94e2016-03-08 11:20:04 -050094 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070096
Brian Stanke0e5c94e2016-03-08 11:20:04 -050097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070099
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500100 private IdGenerator idGenerator;
101
102 // Track tenants by ID
103 private DistributedSet<TenantId> tenantIdSet;
104
105 // Listener for tenant events
106 private final SetEventListener<TenantId> setListener = new InternalSetListener();
107
108 // Track virtual networks by network Id
109 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
110 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
111
112 // Listener for virtual network events
113 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
114
115 // Track virtual network IDs by tenant Id
116 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
117 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
118
119 // Track virtual devices by device Id
120 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
121 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
122
123 // Track device IDs by network Id
124 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
125 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
126
Brian Stanke7a81b532016-06-14 15:43:51 -0400127 // Track virtual hosts by host Id
128 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
129 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
130
131 // Track host IDs by network Id
132 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
133 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
134
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500135 // Track virtual links by network Id
136 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
137 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
138
139 // Track virtual ports by network Id
140 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
141 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
142
Brian Stanke11f6d532016-07-05 16:17:59 -0400143 // Track intent key to intent data
144 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
145 private Map<Key, IntentData> intentKeyIntentDataMap;
146
147 // Track intent ID to TunnelIds
148 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
149 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
150
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500151 private static final Serializer SERIALIZER = Serializer
152 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
153 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700154 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500155 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500156 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500157 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500158 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400159 .register(VirtualHost.class)
160 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500161 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500162 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500163 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500164 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500165 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400166 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400167 .register(IntentData.class)
168 .register(VirtualNetworkIntent.class)
169 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700170 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400171 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500172
173 /**
174 * Distributed network store service activate method.
175 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700176 @Activate
177 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500178 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
179
180 tenantIdSet = storageService.<TenantId>setBuilder()
181 .withSerializer(SERIALIZER)
182 .withName("onos-tenantId")
183 .withRelaxedReadConsistency()
184 .build()
185 .asDistributedSet();
186 tenantIdSet.addListener(setListener);
187
188 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
189 .withSerializer(SERIALIZER)
190 .withName("onos-networkId-virtualnetwork")
191 .withRelaxedReadConsistency()
192 .build();
193 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
194 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
195
196 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
197 .withSerializer(SERIALIZER)
198 .withName("onos-tenantId-networkIds")
199 .withRelaxedReadConsistency()
200 .build();
201 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
202
203 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
204 .withSerializer(SERIALIZER)
205 .withName("onos-deviceId-virtualdevice")
206 .withRelaxedReadConsistency()
207 .build();
208 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
209
210 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
211 .withSerializer(SERIALIZER)
212 .withName("onos-networkId-deviceIds")
213 .withRelaxedReadConsistency()
214 .build();
215 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
216
Brian Stanke7a81b532016-06-14 15:43:51 -0400217 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
218 .withSerializer(SERIALIZER)
219 .withName("onos-hostId-virtualhost")
220 .withRelaxedReadConsistency()
221 .build();
222 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
223
224 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
225 .withSerializer(SERIALIZER)
226 .withName("onos-networkId-hostIds")
227 .withRelaxedReadConsistency()
228 .build();
229 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
230
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500231 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
232 .withSerializer(SERIALIZER)
233 .withName("onos-networkId-virtuallinks")
234 .withRelaxedReadConsistency()
235 .build();
236 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
237
238 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
239 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400240 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500241 .withRelaxedReadConsistency()
242 .build();
243 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
244
Brian Stanke11f6d532016-07-05 16:17:59 -0400245 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
246 .withSerializer(SERIALIZER)
247 .withName("onos-intentKey-tunnelIds")
248 .withRelaxedReadConsistency()
249 .build();
250 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
251
252 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
253 .withSerializer(SERIALIZER)
254 .withName("onos-intentKey-intentData")
255 .withRelaxedReadConsistency()
256 .build();
257 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
258
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700259 log.info("Started");
260 }
261
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500262 /**
263 * Distributed network store service deactivate method.
264 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700265 @Deactivate
266 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500267 tenantIdSet.removeListener(setListener);
268 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700269 log.info("Stopped");
270 }
271
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500272 /**
273 * This method is used for Junit tests to set the CoreService instance, which
274 * is required to set the IdGenerator instance.
275 *
276 * @param coreService core service instance
277 */
278 public void setCoreService(CoreService coreService) {
279 this.coreService = coreService;
280 }
281
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700282 @Override
283 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500284 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 }
286
287 @Override
288 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500289 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700290 }
291
292 @Override
293 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500294 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700295 }
296
297 @Override
298 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500299
300 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
301 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
302 //TODO update both maps in one transaction.
303 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500304
305 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
306 if (networkIdSet == null) {
307 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500308 }
Brian Stanke5df14472016-03-11 19:34:38 -0500309 networkIdSet.add(virtualNetwork.id());
310 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
311
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500312 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700313 }
314
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500315 /**
316 * Returns a new network identifier from a virtual network block of identifiers.
317 *
318 * @return NetworkId network identifier
319 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700320 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900321 NetworkId networkId;
322 do {
323 networkId = NetworkId.networkId(idGenerator.getNewId());
324 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700325
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900326 return networkId;
327 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700328
329 @Override
330 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500331 // Make sure that the virtual network exists before attempting to remove it.
332 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500333 //TODO update both maps in one transaction.
334
335 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500336 if (virtualNetwork == null) {
337 return;
338 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500339 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500340
Brian Stanke5df14472016-03-11 19:34:38 -0500341 Set<NetworkId> networkIdSet = new HashSet<>();
342 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
343 if (networkId1.id().equals(networkId.id())) {
344 networkIdSet.add(networkId1);
345 }
346 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500347
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500348 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
349 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700350 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500351 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700352 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500353 }
354 });
355 }
356 }
357
358 /**
359 * Returns if the network identifier exists.
360 *
361 * @param networkId network identifier
362 * @return true if the network identifier exists, false otherwise.
363 */
364 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400365 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500366 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700367 }
368
369 @Override
370 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500371 checkState(networkExists(networkId), "The network has not been added.");
372 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
373 if (deviceIdSet == null) {
374 deviceIdSet = new HashSet<>();
375 }
376 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
377 //TODO update both maps in one transaction.
378 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
379 deviceIdSet.add(deviceId);
380 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
381 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700382 }
383
384 @Override
385 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500386 checkState(networkExists(networkId), "The network has not been added.");
387 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500388
389 Set<DeviceId> deviceIdSet = new HashSet<>();
390 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
391 if (deviceId1.equals(deviceId)) {
392 deviceIdSet.add(deviceId1);
393 }
394 });
395
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500396 if (deviceIdSet != null) {
397 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
398 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700399 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500400 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700401 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500402 }
403 });
404
Brian Stanke5df14472016-03-11 19:34:38 -0500405 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500406 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400407 //TODO remove virtual links and ports when removing the virtual device
408 }
409
410 @Override
411 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
412 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
413 checkState(networkExists(networkId), "The network has not been added.");
414 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
415 if (hostIdSet == null) {
416 hostIdSet = new HashSet<>();
417 }
418 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
419 //TODO update both maps in one transaction.
420 hostIdVirtualHostMap.put(hostId, virtualhost);
421 hostIdSet.add(hostId);
422 networkIdHostIdSetMap.put(networkId, hostIdSet);
423 return virtualhost;
424 }
425
426 @Override
427 public void removeHost(NetworkId networkId, HostId hostId) {
428 checkState(networkExists(networkId), "The network has not been added.");
429 //TODO update both maps in one transaction.
430
431 Set<HostId> hostIdSet = new HashSet<>();
432 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
433 if (hostId1.equals(hostId)) {
434 hostIdSet.add(hostId1);
435 }
436 });
437
438 if (hostIdSet != null) {
439 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
440 if (existingHostIds == null || existingHostIds.isEmpty()) {
441 return new HashSet<>();
442 } else {
443 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
444 }
445 });
446
447 hostIdVirtualHostMap.remove(hostId);
448 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700449 }
450
451 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400452 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
453 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500454 checkState(networkExists(networkId), "The network has not been added.");
455 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
456 if (virtualLinkSet == null) {
457 virtualLinkSet = new HashSet<>();
458 }
Brian Stanke9a108972016-04-11 15:25:17 -0400459 // validate that the link does not already exist in this network
460 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
461
462 VirtualLink virtualLink = DefaultVirtualLink.builder()
463 .networkId(networkId)
464 .src(src)
465 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400466 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400467 .tunnelId(realizedBy)
468 .build();
469
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500470 virtualLinkSet.add(virtualLink);
471 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
472 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700473 }
474
475 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400476 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400477 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
478 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
479 if (virtualLinkSet == null) {
480 virtualLinkSet = new HashSet<>();
481 }
482 virtualLinkSet.remove(virtualLink);
483
484 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
485 .networkId(virtualLink.networkId())
486 .src(virtualLink.src())
487 .dst(virtualLink.dst())
488 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400489 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400490 .build();
491
492 virtualLinkSet.add(newVirtualLink);
493 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
494 }
495
496 @Override
497 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500498 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500499
Brian Stanke9a108972016-04-11 15:25:17 -0400500 final VirtualLink virtualLink = getLink(networkId, src, dst);
501 if (virtualLink == null) {
502 return null;
503 }
Brian Stanke5df14472016-03-11 19:34:38 -0500504 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400505 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500506
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500507 if (virtualLinkSet != null) {
508 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
509 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700510 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500511 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700512 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500513 }
514 });
515 }
Brian Stanke9a108972016-04-11 15:25:17 -0400516 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700517 }
518
519 @Override
520 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port 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);
523 if (virtualPortSet == null) {
524 virtualPortSet = new HashSet<>();
525 }
526 Device device = deviceIdVirtualDeviceMap.get(deviceId);
527 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
528 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
529 virtualPortSet.add(virtualPort);
530 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
531 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700532 }
533
534 @Override
535 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500536 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500537
538 Set<VirtualPort> virtualPortSet = new HashSet<>();
539 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
540 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
541 virtualPortSet.add(port);
542 }
543 });
544
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500545 if (virtualPortSet != null) {
546 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
547 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700548 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500549 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700550 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500551 }
552 });
553 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700554 }
555
556 @Override
557 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500558 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
559 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
560 if (networkIdSet != null) {
561 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
562 }
563 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700564 }
565
566 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400567 public VirtualNetwork getNetwork(NetworkId networkId) {
568 return networkIdVirtualNetworkMap.get(networkId);
569 }
570
571 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700572 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500573 checkState(networkExists(networkId), "The network has not been added.");
574 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
575 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
576 if (deviceIdSet != null) {
577 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
578 }
579 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700580 }
581
582 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400583 public Set<VirtualHost> getHosts(NetworkId networkId) {
584 checkState(networkExists(networkId), "The network has not been added.");
585 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
586 Set<VirtualHost> virtualHostSet = new HashSet<>();
587 if (hostIdSet != null) {
588 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
589 }
590 return ImmutableSet.copyOf(virtualHostSet);
591 }
592
593 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700594 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500595 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500596 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
597 if (virtualLinkSet == null) {
598 virtualLinkSet = new HashSet<>();
599 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500600 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700601 }
602
Brian Stanke612cebf2016-05-02 10:21:33 -0400603 @Override
604 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400605 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
606 if (virtualLinkSet == null) {
607 return null;
608 }
609
610 VirtualLink virtualLink = null;
611 for (VirtualLink link : virtualLinkSet) {
612 if (link.src().equals(src) && link.dst().equals(dst)) {
613 virtualLink = link;
614 break;
615 }
616 }
617 return virtualLink;
618 }
619
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700620 @Override
621 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500622 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500623 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
624 if (virtualPortSet == null) {
625 virtualPortSet = new HashSet<>();
626 }
627
Brian Stanke612cebf2016-05-02 10:21:33 -0400628 if (deviceId == null) {
629 return ImmutableSet.copyOf(virtualPortSet);
630 }
631
Brian Stanke5df14472016-03-11 19:34:38 -0500632 Set<VirtualPort> portSet = new HashSet<>();
633 virtualPortSet.forEach(virtualPort -> {
634 if (virtualPort.element().id().equals(deviceId)) {
635 portSet.add(virtualPort);
636 }
637 });
638 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500639 }
640
Brian Stanke11f6d532016-07-05 16:17:59 -0400641 @Override
642 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
643 checkNotNull(intent, "Intent cannot be null");
644 IntentData intentData = removeIntent(intent.key());
645 if (intentData == null) {
646 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
647 } else {
648 intentData = new IntentData(intent, state, intentData.version());
649 }
650 intentKeyIntentDataMap.put(intent.key(), intentData);
651 }
652
653 @Override
654 public IntentData removeIntent(Key intentKey) {
655 checkNotNull(intentKey, "Intent key cannot be null");
656 return intentKeyIntentDataMap.remove(intentKey);
657 }
658
659 @Override
660 public void addTunnelId(Intent intent, TunnelId tunnelId) {
661 // Add the tunnelId to the intent key set map
662 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
663 if (tunnelIdSet == null) {
664 tunnelIdSet = new HashSet<>();
665 }
666 tunnelIdSet.add(tunnelId);
667 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
668 }
669
670 @Override
671 public Set<TunnelId> getTunnelIds(Intent intent) {
672 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
673 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
674 }
675
676 @Override
677 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
678 Set<TunnelId> tunnelIdSet = new HashSet<>();
679 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
680 if (tunnelId1.equals(tunnelId)) {
681 tunnelIdSet.add(tunnelId);
682 }
683 });
684
685 if (!tunnelIdSet.isEmpty()) {
686 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
687 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
688 return new HashSet<>();
689 } else {
690 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
691 }
692 });
693 }
694 }
695
696 @Override
697 public Set<Intent> getIntents() {
698 Set<Intent> intents = new HashSet<>();
699 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
700 return ImmutableSet.copyOf(intents);
701 }
702
703 @Override
704 public Intent getIntent(Key key) {
705 IntentData intentData = intentKeyIntentDataMap.get(key);
706 return intentData == null ? null : intentData.intent();
707 }
708
709 @Override
710 public Set<IntentData> getIntentData() {
711 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
712 }
713
714 @Override
715 public IntentData getIntentData(Key key) {
716 IntentData intentData = intentKeyIntentDataMap.get(key);
717 return intentData == null ? null : new IntentData(intentData);
718 }
719
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500720 /**
721 * Listener class to map listener set events to the virtual network events.
722 */
723 private class InternalSetListener implements SetEventListener<TenantId> {
724 @Override
725 public void event(SetEvent<TenantId> event) {
726 VirtualNetworkEvent.Type type = null;
727 switch (event.type()) {
728 case ADD:
729 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
730 break;
731 case REMOVE:
732 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
733 break;
734 default:
735 log.error("Unsupported event type: " + event.type());
736 }
737 notifyDelegate(new VirtualNetworkEvent(type, null));
738 }
739 }
740
741 /**
742 * Listener class to map listener map events to the virtual network events.
743 */
744 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
745 @Override
746 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
747 NetworkId networkId = checkNotNull(event.key());
748 VirtualNetworkEvent.Type type = null;
749 switch (event.type()) {
750 case INSERT:
751 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
752 break;
753 case UPDATE:
754 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
755 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
756 } else {
757 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
758 }
759 break;
760 case REMOVE:
761 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
762 break;
763 default:
764 log.error("Unsupported event type: " + event.type());
765 }
766 notifyDelegate(new VirtualNetworkEvent(type, networkId));
767 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700768 }
769}