blob: 29c4d66001d649451fc4dea50b0bfd47142b52fb [file] [log] [blame]
Mohammad Shahid4c30ea32017-08-09 18:02:10 +05301/*
2 * Copyright 2017-present Open Networking Foundation
3 *
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 */
16
17package org.onosproject.evpnopenflow.rsc.baseport.impl;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.google.common.collect.Sets;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.MacAddress;
29import org.onlab.util.KryoNamespace;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.evpnopenflow.rsc.BasePort;
33import org.onosproject.evpnopenflow.rsc.BasePortId;
34import org.onosproject.evpnopenflow.rsc.DefaultBasePort;
35import org.onosproject.evpnopenflow.rsc.baseport.BasePortEvent;
36import org.onosproject.evpnopenflow.rsc.baseport.BasePortListener;
37import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
38import org.onosproject.net.DeviceId;
39import org.onosproject.net.Host;
40import org.onosproject.store.serializers.KryoNamespaces;
41import org.onosproject.store.service.EventuallyConsistentMap;
42import org.onosproject.store.service.MultiValuedTimestamp;
43import org.onosproject.store.service.StorageService;
44import org.onosproject.store.service.WallClockTimestamp;
45import org.onosproject.vtnrsc.AllowedAddressPair;
46import org.onosproject.vtnrsc.BindingHostId;
47import org.onosproject.vtnrsc.DefaultFloatingIp;
48import org.onosproject.vtnrsc.FixedIp;
49import org.onosproject.vtnrsc.FloatingIp;
50import org.onosproject.vtnrsc.FloatingIpId;
51import org.onosproject.vtnrsc.RouterId;
52import org.onosproject.vtnrsc.SecurityGroup;
53import org.onosproject.vtnrsc.SubnetId;
54import org.onosproject.vtnrsc.TenantId;
55import org.onosproject.vtnrsc.TenantNetwork;
56import org.onosproject.vtnrsc.TenantNetworkId;
57import org.onosproject.vtnrsc.TenantRouter;
58import org.slf4j.Logger;
59import org.slf4j.LoggerFactory;
60
61import java.util.ArrayList;
62import java.util.Collection;
63import java.util.Collections;
64import java.util.HashMap;
65import java.util.List;
66import java.util.Map;
67import java.util.Set;
68import java.util.UUID;
69import java.util.stream.Collectors;
70
71import static com.google.common.base.Preconditions.checkNotNull;
72import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
73import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BASE_PORT_STORE;
74import static org.onosproject.evpnopenflow.rsc.EvpnConstants.LISTENER_NOT_NULL;
75import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
76
77/**
78 * Provides implementation of the BasePort APIs.
79 */
80@Component(immediate = true)
81@Service
82public class BasePortManager implements BasePortService {
83
84 private final Set<BasePortListener> listeners = Sets
85 .newCopyOnWriteArraySet();
86 private final Logger log = LoggerFactory.getLogger(getClass());
87 private static final String BASEPORT_ID_NULL = "BasePort ID cannot be " +
88 "null";
89 private static final String BASEPORT_NOT_NULL = "BasePort cannot be " +
90 "null";
91 private static final String TENANTID_NOT_NULL = "TenantId cannot be null";
92 private static final String NETWORKID_NOT_NULL = "NetworkId cannot be null";
93 private static final String DEVICEID_NOT_NULL = "DeviceId cannot be null";
94 private static final String FIXEDIP_NOT_NULL = "FixedIp cannot be null";
95 private static final String MAC_NOT_NULL = "Mac address cannot be null";
96 private static final String IP_NOT_NULL = "Ip cannot be null";
97 private static final String EVENT_NOT_NULL = "event cannot be null";
98 private static final String SET = "set";
99 private static final String UPDATE = "update";
100 private static final String DELETE = "delete";
101 private static final String SLASH = "/";
102 private static final String PROTON_BASE_PORT = "Port";
103 private static final String JSON_NOT_NULL = "JsonNode can not be null";
104
105 protected EventuallyConsistentMap<BasePortId, BasePort> vPortStore;
106 protected ApplicationId appId;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected StorageService storageService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected CoreService coreService;
113
114 @Activate
115 public void activate() {
116
117 appId = coreService.registerApplication(APP_ID);
118
119 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
120 .register(KryoNamespaces.API)
121 .register(MultiValuedTimestamp.class)
122 .register(TenantNetworkId.class)
123 .register(Host.class)
124 .register(TenantNetwork.class)
125 .register(TenantNetworkId.class)
126 .register(TenantId.class)
127 .register(SubnetId.class)
128 .register(BasePortId.class)
129 .register(BasePort.State.class)
130 .register(AllowedAddressPair.class)
131 .register(FixedIp.class)
132 .register(FloatingIp.class)
133 .register(FloatingIpId.class)
134 .register(FloatingIp.Status.class)
135 .register(UUID.class)
136 .register(DefaultFloatingIp.class)
137 .register(BindingHostId.class)
138 .register(SecurityGroup.class)
139 .register(IpAddress.class)
140 .register(DefaultBasePort.class)
141 .register(RouterId.class)
142 .register(TenantRouter.class)
143 .register(BasePort.class);
144 vPortStore = storageService
145 .<BasePortId, BasePort>eventuallyConsistentMapBuilder()
146 .withName(BASE_PORT_STORE).withSerializer(serializer)
147 .withTimestampProvider((k, v) -> new WallClockTimestamp())
148 .build();
149 log.info("Started");
150 }
151
152 @Deactivate
153 public void deactivate() {
154 vPortStore.destroy();
155 log.info("Stoppped");
156 }
157
158 @Override
159 public boolean exists(BasePortId vPortId) {
160 checkNotNull(vPortId, BASEPORT_ID_NULL);
161 return vPortStore.containsKey(vPortId);
162 }
163
164 @Override
165 public BasePort getPort(BasePortId vPortId) {
166 checkNotNull(vPortId, BASEPORT_ID_NULL);
167 return vPortStore.get(vPortId);
168 }
169
170 @Override
171 public BasePort getPort(FixedIp fixedIP) {
172 checkNotNull(fixedIP, FIXEDIP_NOT_NULL);
173 List<BasePort> vPorts = new ArrayList<>();
174 vPortStore.values().forEach(p -> {
175 for (FixedIp fixedIp : p.fixedIps()) {
176 if (fixedIp.equals(fixedIP)) {
177 vPorts.add(p);
178 break;
179 }
180 }
181 });
182 if (vPorts.size() == 0) {
183 return null;
184 }
185 return vPorts.get(0);
186 }
187
188 @Override
189 public BasePort getPort(MacAddress mac) {
190 checkNotNull(mac, MAC_NOT_NULL);
191 List<BasePort> vPorts = new ArrayList<>();
192 vPortStore.values().forEach(p -> {
193 if (p.macAddress().equals(mac)) {
194 vPorts.add(p);
195 }
196 });
197 if (vPorts.size() == 0) {
198 return null;
199 }
200 return vPorts.get(0);
201 }
202
203 @Override
204 public BasePort getPort(TenantNetworkId networkId, IpAddress ip) {
205 checkNotNull(networkId, NETWORKID_NOT_NULL);
206 checkNotNull(ip, IP_NOT_NULL);
207 List<BasePort> vPorts = new ArrayList<>();
208 vPortStore.values().stream().filter(p -> p.networkId().equals(networkId))
209 .forEach(p -> {
210 for (FixedIp fixedIp : p.fixedIps()) {
211 if (fixedIp.ip().equals(ip)) {
212 vPorts.add(p);
213 break;
214 }
215 }
216 });
217 if (vPorts.size() == 0) {
218 return null;
219 }
220 return vPorts.get(0);
221 }
222
223 @Override
224 public Collection<BasePort> getPorts() {
225 return Collections.unmodifiableCollection(vPortStore.values());
226 }
227
228 @Override
229 public Collection<BasePort> getPorts(TenantNetworkId networkId) {
230 checkNotNull(networkId, NETWORKID_NOT_NULL);
231 return vPortStore.values().stream().filter(d -> d.networkId().equals(networkId))
232 .collect(Collectors.toList());
233 }
234
235 @Override
236 public Collection<BasePort> getPorts(TenantId tenantId) {
237 checkNotNull(tenantId, TENANTID_NOT_NULL);
238 return vPortStore.values().stream().filter(d -> d.tenantId().equals(tenantId))
239 .collect(Collectors.toList());
240 }
241
242 @Override
243 public Collection<BasePort> getPorts(DeviceId deviceId) {
244 checkNotNull(deviceId, DEVICEID_NOT_NULL);
245 return vPortStore.values().stream().filter(d -> d.deviceId().equals(deviceId))
246 .collect(Collectors.toList());
247 }
248
249 @Override
250 public boolean createPorts(Iterable<BasePort> vPorts) {
251 checkNotNull(vPorts, BASEPORT_NOT_NULL);
252 for (BasePort vPort : vPorts) {
253 log.info("vPortId is {} ", vPort.portId().toString());
254 vPortStore.put(vPort.portId(), vPort);
255 if (!vPortStore.containsKey(vPort.portId())) {
256 log.info("The basePort is created failed whose identifier is" +
257 " {} ",
258 vPort.portId().toString());
259 return false;
260 }
261 }
262 return true;
263 }
264
265 @Override
266 public boolean updatePorts(Iterable<BasePort> vPorts) {
267 checkNotNull(vPorts, BASEPORT_NOT_NULL);
268 for (BasePort vPort : vPorts) {
269 vPortStore.put(vPort.portId(), vPort);
270 if (!vPortStore.containsKey(vPort.portId())) {
271 log.info("The basePort is not exist whose identifier is {}",
272 vPort.portId().toString());
273 return false;
274 }
275
276 vPortStore.put(vPort.portId(), vPort);
277
278 if (!vPort.equals(vPortStore.get(vPort.portId()))) {
279 log.info("The basePort is updated failed whose identifier " +
280 "is {}",
281 vPort.portId().toString());
282 return false;
283 }
284 }
285 return true;
286 }
287
288 @Override
289 public boolean removePorts(Iterable<BasePortId> vPortIds) {
290 checkNotNull(vPortIds, BASEPORT_ID_NULL);
291 for (BasePortId vPortId : vPortIds) {
292 vPortStore.remove(vPortId);
293 if (vPortStore.containsKey(vPortId)) {
294 log.info("The basePort is removed failed whose identifier is" +
295 " {}",
296 vPortId.toString());
297 return false;
298 }
299 }
300 return true;
301 }
302
303 /**
304 * Returns a collection of basePorts from subnetNodes.
305 *
306 * @param vPortNodes the basePort json node
307 * @return BasePort collection of vpn ports
308 */
309 private Collection<BasePort> changeJsonToSub(JsonNode vPortNodes) {
310 checkNotNull(vPortNodes, JSON_NOT_NULL);
311 Set<FixedIp> fixedIps = null;
312 TenantNetworkId tenantNetworkId = null;
313 Map<BasePortId, BasePort> vportMap = new HashMap<>();
314 Map<String, String> strMap = new HashMap<>();
315 BasePortId basePortId = BasePortId.portId(vPortNodes.get("id").asText());
316 String name = vPortNodes.get("name").asText();
317 TenantId tenantId = TenantId
318 .tenantId(vPortNodes.get("tenant_id").asText());
319 Boolean adminStateUp = vPortNodes.get("admin_state_up").asBoolean();
320 String state = vPortNodes.get("status").asText();
321 MacAddress macAddress = MacAddress
322 .valueOf(vPortNodes.get("mac_address").asText());
323 DeviceId deviceId = DeviceId
324 .deviceId(vPortNodes.get("device_id").asText());
325 String deviceOwner = vPortNodes.get("device_owner").asText();
326 BindingHostId bindingHostId = BindingHostId
327 .bindingHostId(vPortNodes.get("host_id").asText());
328 String bindingVnicType = vPortNodes.get("vnic_type").asText();
329 String bindingVifType = vPortNodes.get("vif_type").asText();
330 String bindingVifDetails = vPortNodes.get("vif_details").asText();
331 strMap.put("name", name);
332 strMap.put("deviceOwner", deviceOwner);
333 strMap.put("bindingVnicType", bindingVnicType);
334 strMap.put("bindingVifType", bindingVifType);
335 strMap.put("bindingVifDetails", bindingVifDetails);
336 BasePort prevBasePort = getPort(basePortId);
337 if (prevBasePort != null) {
338 fixedIps = prevBasePort.fixedIps();
339 tenantNetworkId = prevBasePort.networkId();
340 }
341 BasePort vPort = new DefaultBasePort(basePortId,
342 tenantNetworkId,
343 adminStateUp,
344 strMap, state,
345 macAddress, tenantId,
346 deviceId, fixedIps,
347 bindingHostId,
348 null,
349 null);
350 vportMap.put(basePortId, vPort);
351
352 return Collections.unmodifiableCollection(vportMap.values());
353 }
354
355 /**
356 * Returns BasePort State.
357 *
358 * @param state the base port state
359 * @return the basePort state
360 */
361 private BasePort.State isState(String state) {
362 if (state.equals("ACTIVE")) {
363 return BasePort.State.ACTIVE;
364 } else {
365 return BasePort.State.DOWN;
366 }
367
368 }
369
370 /**
371 * process Etcd response for port information.
372 *
373 * @param action can be either update or delete
374 * @param key can contain the id and also target information
375 * @param value content of the port configuration
376 */
377 @Override
378 public void processGluonConfig(String action, String key, JsonNode value) {
379 Collection<BasePort> basePorts;
380 switch (action) {
381 case DELETE:
382 String[] list = key.split(SLASH);
383 BasePortId basePortId
384 = BasePortId.portId(list[list.length - 1]);
385 Set<BasePortId> basePortIds = Sets.newHashSet(basePortId);
386 removePorts(basePortIds);
387 break;
388 case SET:
389 checkNotNull(value, RESPONSE_NOT_NULL);
390 basePorts = changeJsonToSub(value);
391 createPorts(basePorts);
392 break;
393 case UPDATE:
394 checkNotNull(value, RESPONSE_NOT_NULL);
395 basePorts = changeJsonToSub(value);
396 updatePorts(basePorts);
397 break;
398 default:
399 log.info("Invalid action is received while processing VPN " +
400 "port configuration");
401 }
402 }
403
404 private void parseEtcdResponse(JsonNode jsonNode,
405 String key,
406 String action) {
407 JsonNode modifyValue = null;
408 if (action.equals(SET)) {
409 modifyValue = jsonNode.get(key);
410 }
411 String[] list = key.split(SLASH);
412 String target = list[list.length - 2];
413 if (target.equals(PROTON_BASE_PORT)) {
414 processGluonConfig(action, key, modifyValue);
415 }
416 }
417
418 @Override
419 public void addListener(BasePortListener listener) {
420 checkNotNull(listener, LISTENER_NOT_NULL);
421 listeners.add(listener);
422 }
423
424 @Override
425 public void removeListener(BasePortListener listener) {
426 checkNotNull(listener, LISTENER_NOT_NULL);
427 listeners.remove(listener);
428 }
429
430 /**
431 * Notifies specify event to all listeners.
432 *
433 * @param event vpn af config event
434 */
435 private void notifyListeners(BasePortEvent event) {
436 checkNotNull(event, EVENT_NOT_NULL);
437 listeners.forEach(listener -> listener.event(event));
438 }
439}