blob: 91eba1d87ec0ec8972edb9035d12d3aadd22f611 [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.vpninstance.impl;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.google.common.collect.Sets;
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053021import org.onlab.util.KryoNamespace;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.core.CoreService;
24import org.onosproject.evpnopenflow.rsc.DefaultVpnInstance;
25import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
26import org.onosproject.evpnopenflow.rsc.VpnInstance;
27import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
28import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigService;
29import org.onosproject.evpnopenflow.rsc.vpninstance.VpnInstanceService;
Ray Milkeya95193c2017-08-10 15:35:36 -070030import org.onosproject.evpnrouteservice.EvpnInstanceName;
Ray Milkeya95193c2017-08-10 15:35:36 -070031import org.onosproject.evpnrouteservice.RouteDistinguisher;
32import org.onosproject.evpnrouteservice.VpnRouteTarget;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070033import org.onosproject.routeservice.RouteAdminService;
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053034import org.onosproject.store.serializers.KryoNamespaces;
35import org.onosproject.store.service.EventuallyConsistentMap;
36import org.onosproject.store.service.StorageService;
37import org.onosproject.store.service.WallClockTimestamp;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070038import org.osgi.service.component.annotations.Activate;
39import org.osgi.service.component.annotations.Component;
40import org.osgi.service.component.annotations.Deactivate;
41import org.osgi.service.component.annotations.Reference;
42import org.osgi.service.component.annotations.ReferenceCardinality;
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
46import java.util.Collection;
47import java.util.Collections;
48import java.util.HashMap;
49import java.util.HashSet;
50import java.util.Map;
51import java.util.Set;
52
53import static com.google.common.base.Preconditions.checkNotNull;
54import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
55import static org.onosproject.evpnopenflow.rsc.EvpnConstants.COMMA;
56import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
57import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DESCRIPTION;
58import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_INSTANCE_START;
59import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_INSTANCE_STOP;
60import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID;
61import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INSTANCE_ID;
62import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IPV4_FAMILY;
63import static org.onosproject.evpnopenflow.rsc.EvpnConstants.JSON_NOT_NULL;
64import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
65import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_DISTINGUISHERS;
66import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
67import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
68import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
69import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_CREATION_FAILED;
70import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_DELETE_FAILED;
71import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_ID_NOT_NULL;
72import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_IS_NOT_EXIST;
73import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_NAME;
74import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_NOT_NULL;
75import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_STORE;
76import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_UPDATE_FAILED;
77
78
79/**
80 * Provides implementation of the VpnInstance APIs.
81 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082@Component(immediate = true, service = VpnInstanceService.class)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053083public class VpnInstanceManager implements VpnInstanceService {
84
85 private final Logger log = LoggerFactory.getLogger(getClass());
86
87 protected EventuallyConsistentMap<VpnInstanceId, VpnInstance> vpnInstanceStore;
88 protected ApplicationId appId;
89
Ray Milkeyd84f89b2018-08-17 14:54:17 -070090 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053091 protected StorageService storageService;
92
Ray Milkeyd84f89b2018-08-17 14:54:17 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053094 protected RouteAdminService routeService;
95
Ray Milkeyd84f89b2018-08-17 14:54:17 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053097 protected CoreService coreService;
98
Ray Milkeyd84f89b2018-08-17 14:54:17 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530100 protected VpnAfConfigService vpnAfConfigService;
101
102 @Activate
103 public void activate() {
104 appId = coreService.registerApplication(APP_ID);
105 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
106 .register(KryoNamespaces.API).register(VpnInstance.class)
107 .register(VpnInstanceId.class);
108 vpnInstanceStore = storageService
109 .<VpnInstanceId, VpnInstance>eventuallyConsistentMapBuilder()
110 .withName(VPN_INSTANCE_STORE).withSerializer(serializer)
111 .withTimestampProvider((k, v) -> new WallClockTimestamp())
112 .build();
113 log.info(EVPN_VPN_INSTANCE_START);
114 }
115
116 @Deactivate
117 public void deactivate() {
118 vpnInstanceStore.destroy();
119 log.info(EVPN_VPN_INSTANCE_STOP);
120 }
121
122 @Override
123 public boolean exists(VpnInstanceId vpnInstanceId) {
124 checkNotNull(vpnInstanceId, VPN_INSTANCE_ID_NOT_NULL);
125 return vpnInstanceStore.containsKey(vpnInstanceId);
126 }
127
128 @Override
129 public VpnInstance getInstance(VpnInstanceId vpnInstanceId) {
130 checkNotNull(vpnInstanceId, VPN_INSTANCE_ID_NOT_NULL);
131 return vpnInstanceStore.get(vpnInstanceId);
132 }
133
134 @Override
135 public Collection<VpnInstance> getInstances() {
136 return Collections.unmodifiableCollection(vpnInstanceStore.values());
137 }
138
139 @Override
140 public boolean createInstances(Iterable<VpnInstance> vpnInstances) {
141 checkNotNull(vpnInstances, VPN_INSTANCE_NOT_NULL);
142 for (VpnInstance vpnInstance : vpnInstances) {
143 log.info(INSTANCE_ID, vpnInstance.id().toString());
144 vpnInstanceStore.put(vpnInstance.id(), vpnInstance);
145 if (!vpnInstanceStore.containsKey(vpnInstance.id())) {
146 log.info(VPN_INSTANCE_CREATION_FAILED,
147 vpnInstance.id().toString());
148 return false;
149 }
150 }
151 return true;
152 }
153
154 @Override
155 public boolean updateInstances(Iterable<VpnInstance> vpnInstances) {
156 checkNotNull(vpnInstances, VPN_INSTANCE_NOT_NULL);
157 for (VpnInstance vpnInstance : vpnInstances) {
158 if (!vpnInstanceStore.containsKey(vpnInstance.id())) {
159 log.info(VPN_INSTANCE_IS_NOT_EXIST,
160 vpnInstance.id().toString());
161 return false;
162 }
163 vpnInstanceStore.put(vpnInstance.id(), vpnInstance);
164 if (!vpnInstance.equals(vpnInstanceStore.get(vpnInstance.id()))) {
165 log.info(VPN_INSTANCE_UPDATE_FAILED,
166 vpnInstance.id().toString());
167 return false;
168 }
169 }
170 return true;
171 }
172
173 @Override
174 public boolean removeInstances(Iterable<VpnInstanceId> vpnInstanceIds) {
175 checkNotNull(vpnInstanceIds, VPN_INSTANCE_ID_NOT_NULL);
176 for (VpnInstanceId vpnInstanceId : vpnInstanceIds) {
177 vpnInstanceStore.remove(vpnInstanceId);
178 if (vpnInstanceStore.containsKey(vpnInstanceId)) {
179 log.info(VPN_INSTANCE_DELETE_FAILED, vpnInstanceId.toString());
180 return false;
181 }
182 }
183 return true;
184 }
185
186 @Override
187 public void processGluonConfig(String action, String key, JsonNode value) {
188 Collection<VpnInstance> vpnInstances;
189 switch (action) {
190 case DELETE:
191 String[] list = key.split(SLASH);
192 VpnInstanceId vpnInstanceId = VpnInstanceId
193 .vpnInstanceId(list[list.length - 1]);
194 Set<VpnInstanceId> vpnInstanceIds
195 = Sets.newHashSet(vpnInstanceId);
196 removeInstances(vpnInstanceIds);
197 break;
198 case SET:
199 checkNotNull(value, RESPONSE_NOT_NULL);
200 vpnInstances = changeJsonToSub(value);
201 createInstances(vpnInstances);
202 break;
203 case UPDATE:
204 checkNotNull(value, RESPONSE_NOT_NULL);
205 vpnInstances = changeJsonToSub(value);
206 updateInstances(vpnInstances);
207 break;
208 default:
209 log.info("Invalid action is received while processing VPN " +
210 "instance configuration");
211 }
212 }
213
214 @Override
215 public void updateImpExpRouteTargets(String routeTargetType,
216 Set<VpnRouteTarget> exportRouteTargets,
217 Set<VpnRouteTarget> importRouteTargets,
218 VpnRouteTarget vpnRouteTarget) {
219 switch (routeTargetType) {
220 case "export_extcommunity":
221 exportRouteTargets.add(vpnRouteTarget);
222 break;
223 case "import_extcommunity":
224 importRouteTargets.add(vpnRouteTarget);
225 break;
226 case "both":
227 exportRouteTargets.add(vpnRouteTarget);
228 importRouteTargets.add(vpnRouteTarget);
229 break;
230 default:
231 log.info("Invalid route target type has received");
232 break;
233 }
234 }
235
236 /**
237 * Returns a collection of vpnInstances from subnetNodes.
238 *
239 * @param vpnInstanceNodes the vpnInstance json node
240 * @return returns the collection of vpn instances
241 */
242 private Collection<VpnInstance> changeJsonToSub(JsonNode vpnInstanceNodes) {
243 checkNotNull(vpnInstanceNodes, JSON_NOT_NULL);
244
245 Set<VpnRouteTarget> exportRouteTargets = new HashSet<>();
246 Set<VpnRouteTarget> importRouteTargets = new HashSet<>();
247 Set<VpnRouteTarget> configRouteTargets = new HashSet<>();
248
249 Map<VpnInstanceId, VpnInstance> vpnInstanceMap = new HashMap<>();
250 VpnInstanceId id = VpnInstanceId
251 .vpnInstanceId(vpnInstanceNodes.get(ID).asText());
252 EvpnInstanceName name = EvpnInstanceName
253 .evpnName(vpnInstanceNodes.get(VPN_INSTANCE_NAME).asText());
254 String description = vpnInstanceNodes.get(DESCRIPTION).asText();
255 RouteDistinguisher routeDistinguisher = RouteDistinguisher
256 .routeDistinguisher(vpnInstanceNodes.get(ROUTE_DISTINGUISHERS)
257 .asText());
258 String routeTargets = vpnInstanceNodes.get(IPV4_FAMILY).asText();
259 String[] list = routeTargets.split(COMMA);
260
261 for (String routeTarget : list) {
262 // Converting route target string into route target object and
263 // then storing into configuration route target set.
264 VpnRouteTarget vpnRouteTarget
265 = VpnRouteTarget.routeTarget(routeTarget);
266 configRouteTargets.add(vpnRouteTarget);
267 VpnAfConfig vpnAfConfig
268 = vpnAfConfigService.getVpnAfConfig(vpnRouteTarget);
269 if (vpnAfConfig == null) {
270 log.info("Not able to find vpn af config for the give vpn " +
271 "route target");
272 break;
273 }
274 updateImpExpRouteTargets(vpnAfConfig.routeTargetType(),
275 exportRouteTargets,
276 importRouteTargets,
277 vpnRouteTarget);
278 }
279
280 VpnInstance vpnInstance = new DefaultVpnInstance(id, name, description,
281 routeDistinguisher,
282 exportRouteTargets,
283 importRouteTargets,
284 configRouteTargets);
285 vpnInstanceMap.put(id, vpnInstance);
286 return Collections.unmodifiableCollection(vpnInstanceMap.values());
287 }
Ray Milkey69ec8712017-08-08 13:00:43 -0700288}