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