blob: e911000d8af2720cbfcdbc0374848520ed231983 [file] [log] [blame]
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05301/*
2 * Copyright 2017-present Open Networking Laboratory
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 */
janani bf41dec32017-03-24 18:44:07 +053016package org.onosproject.l3vpn.netl3vpn.impl;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Bharat saraswalcdfda202017-03-24 23:40:50 +053023import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.LeadershipEvent;
25import org.onosproject.cluster.LeadershipEventListener;
26import org.onosproject.cluster.LeadershipService;
27import org.onosproject.cluster.NodeId;
janani b35f6cbc2017-03-24 21:56:58 +053028import org.onosproject.config.DynamicConfigEvent;
29import org.onosproject.config.DynamicConfigListener;
30import org.onosproject.config.DynamicConfigService;
Bharat saraswalcdfda202017-03-24 23:40:50 +053031import org.onosproject.core.ApplicationId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053032import org.onosproject.core.CoreService;
janani b35f6cbc2017-03-24 21:56:58 +053033import org.onosproject.core.IdGenerator;
34import org.onosproject.l3vpn.netl3vpn.AccessInfo;
35import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
36import org.onosproject.l3vpn.netl3vpn.BgpInfo;
37import org.onosproject.l3vpn.netl3vpn.DeviceInfo;
38import org.onosproject.l3vpn.netl3vpn.FullMeshVpnConfig;
39import org.onosproject.l3vpn.netl3vpn.HubSpokeVpnConfig;
40import org.onosproject.l3vpn.netl3vpn.InterfaceInfo;
41import org.onosproject.l3vpn.netl3vpn.NetL3VpnException;
42import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
43import org.onosproject.l3vpn.netl3vpn.VpnConfig;
44import org.onosproject.l3vpn.netl3vpn.VpnInstance;
45import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
46import org.onosproject.l3vpn.netl3vpn.VpnType;
47import org.onosproject.net.Device;
48import org.onosproject.net.DeviceId;
49import org.onosproject.net.Port;
50import org.onosproject.net.device.DeviceService;
51import org.onosproject.net.driver.DriverService;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053052import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev20130715.IetfInetTypes;
janani b35f6cbc2017-03-24 21:56:58 +053053import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.device.Interfaces;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053054import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.IetfL3VpnSvc;
janani b35f6cbc2017-03-24 21:56:58 +053055import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.DefaultL3VpnSvc;
56import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.L3VpnSvc;
57import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.VpnAttachment;
58import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.AttachmentFlavor;
59import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.attachmentflavor.DefaultVpnId;
60import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.Sites;
61import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.VpnServices;
62import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.Site;
63import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.SiteNetworkAccesses;
64import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.sitenetworkaccesses.SiteNetworkAccess;
65import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.vpnservices.VpnSvc;
66import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.Bearer;
67import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.DefaultBearer;
68import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.DefaultRequestedType;
69import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.RequestedType;
70import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
71import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.RoutingProtocols;
72import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.routingprotocols.RoutingProtocol;
73import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.NetworkInstances;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053074import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.IetfYangTypes;
75import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.L3VpnSvcExt;
janani b35f6cbc2017-03-24 21:56:58 +053076import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.DefaultAugmentedL3VpnBearer;
77import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.requestedtype.DefaultAugmentedL3VpnRequestedType;
78import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.RequestedTypeChoice;
79import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultDot1Qcase;
80import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultPhysicalCase;
81import org.onosproject.yang.model.DataNode;
82import org.onosproject.yang.model.DefaultModelObjectData;
83import org.onosproject.yang.model.ModelConverter;
84import org.onosproject.yang.model.ModelObject;
85import org.onosproject.yang.model.ModelObjectData;
86import org.onosproject.yang.model.ModelObjectId;
87import org.onosproject.yang.model.NodeKey;
88import org.onosproject.yang.model.ResourceData;
89import org.onosproject.yang.model.ResourceId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053090import org.onosproject.yang.model.YangModel;
91import org.onosproject.yang.model.YangModuleId;
92import org.onosproject.yang.runtime.DefaultAppModuleInfo;
93import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
94import org.onosproject.yang.runtime.ModelRegistrationParam;
95import org.onosproject.yang.runtime.YangModelRegistry;
96import org.slf4j.Logger;
97import org.slf4j.LoggerFactory;
98
99import java.util.Iterator;
janani b35f6cbc2017-03-24 21:56:58 +0530100import java.util.List;
101import java.util.Map;
102import java.util.concurrent.ExecutorService;
103import java.util.concurrent.Executors;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530104
janani b35f6cbc2017-03-24 21:56:58 +0530105import static org.onlab.util.Tools.groupedThreads;
106import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
107import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530108import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
janani b35f6cbc2017-03-24 21:56:58 +0530109import static org.onosproject.l3vpn.netl3vpn.impl.BgpConstructionUtil.createBgpInfo;
110import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.createInstance;
111import static org.onosproject.l3vpn.netl3vpn.impl.IntConstructionUtil.createInterface;
112import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.BEARER_NULL;
113import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.CONS_HUNDRED;
114import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.DEVICE_INFO_NULL;
115import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.EVENT_NOT_SUPPORTED;
116import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT;
117import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT_EXCEEDED;
118import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.INT_INFO_NULL;
119import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP_INT_INFO_NULL;
120import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MG_MT_ADD;
121import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.PORT_NAME;
122import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_ROLE_NULL;
123import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_VPN_MISMATCH;
124import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_ATTACHMENT_NULL;
125import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_POLICY_NOT_SUPPORTED;
126import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_TYPE_UNSUPPORTED;
127import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getBgpCreateConfigObj;
128import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntCreateModObj;
129import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntNotAvailable;
130import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getMgmtIpUnAvailErr;
131import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForL3VpnSvc;
132import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForSites;
133import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getResourceData;
134import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getRole;
135import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnCreateModObj;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530136import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.getYangModel;
137
138/**
139 * The IETF net l3vpn manager implementation.
janani bf41dec32017-03-24 18:44:07 +0530140 * // TODO: Implementation of the manager class.
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530141 */
142@Component(immediate = true)
143public class NetL3vpnManager {
144
145 private static final String APP_ID = "org.onosproject.app.l3vpn";
janani b35f6cbc2017-03-24 21:56:58 +0530146 private static final String L3_VPN_ID_TOPIC = "l3vpn-id";
147 private static final String ONOS_NET_L3VPN = "onos/netl3vpn";
148 private static final String EVENT_HANDLER = "event-handler-%d";
149
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530150 private final Logger log = LoggerFactory.getLogger(getClass());
151
152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected CoreService coreService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
janani b35f6cbc2017-03-24 21:56:58 +0530156 protected DriverService driverService;
157
158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
159 protected DeviceService deviceService;
160
161 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530162 protected YangModelRegistry modelRegistry;
163
janani b35f6cbc2017-03-24 21:56:58 +0530164 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
165 protected ModelConverter modelConverter;
166
167 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
168 protected DynamicConfigService configService;
169
170 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
171 protected NetL3VpnStore l3VpnStore;
172
Bharat saraswalcdfda202017-03-24 23:40:50 +0530173 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
174 protected LeadershipService leadershipService;
175
176 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
177 protected ClusterService clusterService;
178
janani b35f6cbc2017-03-24 21:56:58 +0530179 protected IdGenerator l3VpnIdGen;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530180 private NodeId localNodeId;
181 private ApplicationId appId;
janani b35f6cbc2017-03-24 21:56:58 +0530182
janani b36b1d772017-03-27 15:01:28 +0530183 private final DynamicConfigListener configListener = new
184 InternalConfigListener();
janani b35f6cbc2017-03-24 21:56:58 +0530185
Bharat saraswalcdfda202017-03-24 23:40:50 +0530186 private final InternalLeadershipListener leadershipEventListener =
187 new InternalLeadershipListener();
188
janani b35f6cbc2017-03-24 21:56:58 +0530189 private ModelRegistrationParam regParam;
190
191 private ExecutorService executor = Executors.newSingleThreadExecutor(
192 groupedThreads(ONOS_NET_L3VPN, EVENT_HANDLER, log));
193
194 private ResourceId id;
195 private ResourceId module;
196 private ResourceId sites;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530197 private boolean isElectedLeader = false;
198 private boolean isActivatedLeader = false;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530199
200 @Activate
201 protected void activate() {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530202 appId = coreService.registerApplication(APP_ID);
janani b35f6cbc2017-03-24 21:56:58 +0530203 l3VpnIdGen = coreService.getIdGenerator(L3_VPN_ID_TOPIC);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530204
205 localNodeId = clusterService.getLocalNode().id();
206
207 leadershipService.addListener(leadershipEventListener);
208 leadershipService.runForLeadership(appId.name());
209
janani b35f6cbc2017-03-24 21:56:58 +0530210 registerModel();
211 getResourceId();
212 configService.addListener(configListener);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530213 log.info("Started");
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530214 }
215
216 @Deactivate
217 protected void deactivate() {
218 modelRegistry.unregisterModel(regParam);
janani b35f6cbc2017-03-24 21:56:58 +0530219 configService.removeListener(configListener);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530220
221 leadershipService.withdraw(appId.name());
222 leadershipService.removeListener(leadershipEventListener);
223
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530224 log.info("Stopped");
225 }
226
227 private void registerModel() {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530228 YangModel model = getYangModel(IetfInetTypes.class);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530229 Iterator<YangModuleId> it = model.getYangModulesId().iterator();
230
231 //Create model registration param.
232 ModelRegistrationParam.Builder b =
233 DefaultModelRegistrationParam.builder().setYangModel(model);
234
235 YangModuleId id;
236 while (it.hasNext()) {
237 id = it.next();
238 switch (id.moduleName()) {
239 case "ietf-inet-types":
240 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
241 IetfInetTypes.class, null));
242 break;
243 case "ietf-l3vpn-svc":
244 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
245 IetfL3VpnSvc.class, null));
246 break;
247 case "ietf-yang-types":
248 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
249 IetfYangTypes.class, null));
250 break;
251 case "l3vpn-svc-ext":
252 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
253 L3VpnSvcExt.class, null));
254 break;
255 default:
256 break;
257 }
258 }
259 regParam = b.build();
260 modelRegistry.registerModel(regParam);
261 }
janani b35f6cbc2017-03-24 21:56:58 +0530262
263 /**
264 * Returns id as string. If the id is not in the freed list a new id is
265 * generated else the id from the freed list is used.
266 *
267 * @return id
268 */
269 private String getIdFromGen() {
270 Long value;
271 Iterable<Long> freeIds = l3VpnStore.getFreedIdList();
272 Iterator<Long> it = freeIds.iterator();
273 if (it.hasNext()) {
274 value = it.next();
275 l3VpnStore.removeIdFromFreeList(value);
276 } else {
277 value = l3VpnIdGen.getNewId();
278 }
279 if (value > ID_LIMIT) {
280 throw new RuntimeException(ID_LIMIT_EXCEEDED);
281 }
282 return CONS_HUNDRED + String.valueOf(value);
283 }
284
285 /**
286 * Returns the resource id, after constructing model object id and
287 * converting it.
288 */
289 private void getResourceId() {
290
291 ModelObjectId moduleId = ModelObjectId.builder().build();
292 module = getResourceVal(moduleId);
293
294 ModelObjectId svcId = getModIdForL3VpnSvc();
295 id = getResourceVal(svcId);
296
297 ModelObjectId sitesId = getModIdForSites();
298 sites = getResourceVal(sitesId);
299 }
300
301 /**
302 * Returns resource id from model converter.
303 *
304 * @param modelId model object id
305 * @return resource id
306 */
307 private ResourceId getResourceVal(ModelObjectId modelId) {
308 DefaultModelObjectData.Builder data = DefaultModelObjectData.builder()
Thomas Vachuskad17bc732017-03-24 11:46:55 -0700309 .identifier(modelId);
janani b35f6cbc2017-03-24 21:56:58 +0530310 ResourceData resData = modelConverter.createDataNode(data.build());
Bharat saraswalcdfda202017-03-24 23:40:50 +0530311 //TODO: change this when yang runtime manager implements model
312 // converter api.
313 return null;
janani b35f6cbc2017-03-24 21:56:58 +0530314 }
315
316 /**
317 * Processes create request from the store, by taking the root object.
318 * The root object is then used for l3VPN processing.
319 *
320 * @param storeId store resource id
321 */
322 private void processCreateFromStore(ResourceId storeId) {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530323 if (isElectedLeader && isActivatedLeader) {
324 List<ModelObject> objects = getModelObjects(storeId, module);
325 for (ModelObject obj : objects) {
326 if (obj instanceof DefaultL3VpnSvc) {
327 DefaultL3VpnSvc l3VpnSvc = (DefaultL3VpnSvc) obj;
328 createGlobalConfig(l3VpnSvc);
329 }
janani b35f6cbc2017-03-24 21:56:58 +0530330 }
331 }
332 }
333
334 /**
Bharat saraswalcdfda202017-03-24 23:40:50 +0530335 * Processes delete request from the store, by taking the root object.
336 * The root object is then used for l3VPN processing.
337 *
338 * @param storeId store resource id
339 */
340 private void processDeleteFromStore(ResourceId storeId) {
341 if (isElectedLeader && isActivatedLeader) {
342 //TODO: add delete logic here.
343 }
344 }
345
346 /**
janani b35f6cbc2017-03-24 21:56:58 +0530347 * Returns model objects of the store. The data node is read from the
348 * config store. This returns the resource id's node. So the node's
349 * parent resource id is taken and the data node is given to model
350 * converter.
351 *
352 * @param storeId store resource id
353 * @param appId parent resource id
354 * @return model objects
355 */
356 public List<ModelObject> getModelObjects(ResourceId storeId,
357 ResourceId appId) {
358 DataNode dataNode = configService.readNode(storeId, null);
359 ResourceData data = getResourceData(dataNode, appId);
360 ModelObjectData modelData = modelConverter.createModel(data);
361 return modelData.modelObjects();
362 }
363
364 /**
365 * Returns true if the event resource id points to the root level node
366 * only and event is for addition and deletion; false otherwise.
367 *
368 * @param event config event
369 * @return true if event is supported; false otherwise
370 */
371 public boolean isSupported(DynamicConfigEvent event) {
372 ResourceId rsId = event.subject();
373 List<NodeKey> storeKeys = rsId.nodeKeys();
374 List<NodeKey> regKeys = id.nodeKeys();
375 if (storeKeys != null) {
376 if (storeKeys.size() == 1) {
377 return storeKeys.get(0).equals(regKeys.get(1)) &&
378 (event.type() == NODE_ADDED ||
379 event.type() == NODE_DELETED);
380 }
381 }
382 return false;
383 }
384
385 /***
386 * Creation of all configuration in standard device model.
387 *
388 * @param l3VpnSvc l3VPN service object
389 */
390 void createGlobalConfig(L3VpnSvc l3VpnSvc) {
391 if (l3VpnSvc.vpnServices() != null) {
392 createVpnServices(l3VpnSvc.vpnServices());
393 }
394 if (l3VpnSvc.sites() != null) {
395 createInterfaceConfig(l3VpnSvc.sites());
396 }
397 }
398
399 /**
400 * Creates the VPN instances from the VPN services object, if only that
401 * VPN instance is not already created.
402 *
403 * @param vpnSvcs VPN services object
404 */
405 private void createVpnServices(VpnServices vpnSvcs) {
406 if (vpnSvcs != null && vpnSvcs.vpnSvc() != null) {
407 List<VpnSvc> svcList = vpnSvcs.vpnSvc();
408 for (VpnSvc svc : svcList) {
409 String vpnName = svc.vpnId().string();
410 l3VpnStore.addVpnInsIfAbsent(vpnName, new VpnInstance(vpnName));
411 }
412 }
413 }
414
415 /**
416 * Creates interface configuration from the site network access if
417 * available.
418 *
419 * @param sites sites object
420 */
421 private void createInterfaceConfig(Sites sites) {
422 if (sites.site() != null) {
423 List<Site> sitesList = sites.site();
424 for (Site site : sitesList) {
425 if (site.siteNetworkAccesses() != null) {
426 SiteNetworkAccesses accesses = site.siteNetworkAccesses();
427 List<SiteNetworkAccess> accessList =
428 accesses.siteNetworkAccess();
429 for (SiteNetworkAccess access : accessList) {
430 createFromAccess(access, site.siteId().string());
431 }
432 }
433 }
434 }
435 }
436
437 /**
438 * Creates the interface and VPN related configurations from the access
439 * and site id value.
440 *
441 * @param access site network access
442 * @param siteId site id
443 */
444 private void createFromAccess(SiteNetworkAccess access, String siteId) {
445 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
446 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
447 String accessId = access.siteNetworkAccessId().string();
448 AccessInfo info = new AccessInfo(siteId, accessId);
449
450 if (intMap.get(info) == null) {
451 VpnSiteRole siteRole = getSiteRole(access.vpnAttachment());
452 VpnInstance instance = insMap.get(siteRole.name());
453 if (instance == null) {
454 throw new NetL3VpnException(SITE_VPN_MISMATCH);
455 }
456 buildFromAccess(instance, info, access, siteRole);
457 }
458 }
459
460 /**
461 * Returns the VPN site role from the VPN attachment.
462 *
463 * @param attach VPN attachment
464 * @return VPN site role
465 */
466 private VpnSiteRole getSiteRole(VpnAttachment attach) {
467 if (attach == null || attach.attachmentFlavor() == null) {
468 throw new NetL3VpnException(VPN_ATTACHMENT_NULL);
469 }
470 AttachmentFlavor flavor = attach.attachmentFlavor();
471 if (!(flavor instanceof DefaultVpnId)) {
472 throw new NetL3VpnException(VPN_POLICY_NOT_SUPPORTED);
473 }
474 DefaultVpnId vpnId = (DefaultVpnId) flavor;
475 if (vpnId.siteRole() == null) {
476 throw new NetL3VpnException(SITE_ROLE_NULL);
477 }
478 VpnType role = getRole(vpnId.siteRole());
479 VpnSiteRole vpnRole = new VpnSiteRole(
480 String.valueOf(vpnId.vpnId()), role);
481 return vpnRole;
482 }
483
484 /**
485 * Builds the required details for device standard model from the site
486 * network access info available.
487 *
488 * @param instance VPN instance
489 * @param info access info
490 * @param access network access
491 * @param role VPN site role
492 */
493 private void buildFromAccess(VpnInstance instance, AccessInfo info,
494 SiteNetworkAccess access, VpnSiteRole role) {
495 Bearer bearer = access.bearer();
496 if (bearer == null) {
497 throw new NetL3VpnException(BEARER_NULL);
498 }
499
500 RequestedType reqType = bearer.requestedType();
501 IpConnection connect = access.ipConnection();
502 RoutingProtocols pro = access.routingProtocols();
503
504 if (reqType == null || connect == null) {
505 throw new NetL3VpnException(IP_INT_INFO_NULL);
506 }
507 buildDeviceDetails(instance, info, role, bearer, connect,
508 reqType, pro);
509 }
510
511 /**
512 * Builds the device details such as, VPN instance value if it is for
513 * the first time, interface values and BGP info if available in service.
514 *
515 * @param instance VPN instance
516 * @param accInfo access info
517 * @param role VPN site role
518 * @param bearer bearer object
519 * @param connect ip connect object
520 * @param reqType requested type
521 * @param pro routing protocol
522 */
523 private void buildDeviceDetails(VpnInstance instance, AccessInfo accInfo,
524 VpnSiteRole role, Bearer bearer,
525 IpConnection connect, RequestedType reqType,
526 RoutingProtocols pro) {
527 Map<AccessInfo, InterfaceInfo> interMap = l3VpnStore.getInterfaceInfo();
528 InterfaceInfo intInfo = interMap.get(accInfo);
529 if (intInfo != null) {
530 return;
531 }
532
533 DeviceInfo info = buildDevVpnIns(bearer, instance, role, connect);
534 String portName = getInterfaceName(info, reqType);
535 buildDevVpnInt(info, instance, connect, portName, accInfo);
536
537 if (pro != null && pro.routingProtocol() != null) {
538 buildBgpInfo(pro.routingProtocol(), info,
539 role.name(), connect, accInfo);
540 }
541 InterfaceInfo interInfo = new InterfaceInfo(info, portName,
542 instance.vpnName());
543 l3VpnStore.addInterfaceInfo(accInfo, interInfo);
544 }
545
546 /**
547 * Builds device VPN instance with the service objects. It returns
548 *
549 * @param bearer bearer object
550 * @param ins VPN instance
551 * @param role VPN site role
552 * @param connect ip connection
553 * @return return
554 */
555 private DeviceInfo buildDevVpnIns(Bearer bearer, VpnInstance ins,
556 VpnSiteRole role, IpConnection connect) {
557 DefaultAugmentedL3VpnBearer augBearer = ((DefaultBearer) bearer)
558 .augmentation(DefaultAugmentedL3VpnBearer.class);
559 DeviceId id = getDeviceId(augBearer);
560 Map<DeviceId, DeviceInfo> devices = ins.devInfo();
561 DeviceInfo info = null;
562 if (devices != null) {
563 info = devices.get(id);
564 }
565 if (info == null) {
566 info = createVpnInstance(id, role, ins, connect);
567 }
568 return info;
569 }
570
571 /**
572 * Returns the device id from the bearer augment attachment of service.
573 * If the attachment in augment is not available it throws error.
574 *
575 * @param attach augmented bearer
576 * @return device id
577 */
578 private DeviceId getDeviceId(DefaultAugmentedL3VpnBearer attach) {
579 if (attach == null || attach.bearerAttachment() == null ||
580 attach.bearerAttachment().peMgmtIp() == null ||
581 attach.bearerAttachment().peMgmtIp().string() == null) {
582 throw new NetL3VpnException(DEVICE_INFO_NULL);
583 }
584 String ip = attach.bearerAttachment().peMgmtIp().string();
585 return getId(ip);
586 }
587
588 /**
589 * Returns the device id whose management ip address matches with the ip
590 * received.
591 *
592 * @param ip ip address
593 * @return device id
594 */
595 public DeviceId getId(String ip) {
596 for (Device device : deviceService.getAvailableDevices()) {
597 String val = device.annotations().value(MG_MT_ADD);
598 if (ip.equals(val)) {
599 return device.id();
600 }
601 }
602 throw new NetL3VpnException(getMgmtIpUnAvailErr(ip));
603 }
604
605 /**
606 * Creates the VPN instance by constructing standard device model of
607 * instances. It adds the RD and RT values to the VPN instance.
608 *
609 * @param id device id
610 * @param role VPN site role
611 * @param inst VPN instance
612 * @param ip ip connection
613 * @return device info
614 */
615 private DeviceInfo createVpnInstance(DeviceId id, VpnSiteRole role,
616 VpnInstance inst, IpConnection ip) {
617 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
618 generateRdRt(inst, role);
619 DeviceInfo info = new DeviceInfo(id);
620 inst.addDevInfo(id, info);
621
622 NetworkInstances instances = createInstance(inst, role, ip);
623 ModelObjectData devMod = getVpnCreateModObj(intMap, instances,
624 id.toString());
625 ModelObjectData driMod = info.processCreateInstance(driverService,
626 devMod);
627 ResourceData resData = modelConverter.createDataNode(driMod);
628 addToStore(resData);
janani b36b1d772017-03-27 15:01:28 +0530629 l3VpnStore.addVpnIns(inst.vpnName(), inst);
janani b35f6cbc2017-03-24 21:56:58 +0530630 return info;
631 }
632
633 /**
634 * Adds the resource data that is received from the driver, after
635 * converting from the model object data.
636 *
637 * @param resData resource data
638 */
639 private void addToStore(ResourceData resData) {
640 if (resData != null && resData.dataNodes() != null) {
641 List<DataNode> dataNodes = resData.dataNodes();
642 for (DataNode node : dataNodes) {
643 configService.createNodeRecursive(resData.resourceId(), node);
644 }
645 }
646 }
647
648 /**
649 * Generates RD and RT value for the VPN instance for the first time VPN
650 * instance creation.
651 *
652 * @param ins VPN instance
653 * @param role VPN site role
654 */
655 private void generateRdRt(VpnInstance ins, VpnSiteRole role) {
656 ins.type(role.role());
657 VpnConfig config = ins.vpnConfig();
658 String rd = null;
659 if (config == null) {
660 rd = getIdFromGen();
661 }
662 switch (ins.type()) {
663 case ANY_TO_ANY:
664 if (config == null) {
665 config = new FullMeshVpnConfig(rd);
666 config.rd(rd);
667 }
668 break;
669
670 case HUB:
671 case SPOKE:
672 if (config == null) {
673 config = new HubSpokeVpnConfig();
674 config.rd(rd);
675 }
676 createImpRtVal((HubSpokeVpnConfig) config, ins.type());
677 createExpRtVal((HubSpokeVpnConfig) config, ins.type());
678 break;
679
680 default:
681 throw new NetL3VpnException(VPN_TYPE_UNSUPPORTED);
682 }
683 ins.vpnConfig(config);
684 }
685
686 /**
687 * Creates import RT value for HUB and SPOKE, according to the type, if
688 * the values are not present.
689 *
690 * @param config VPN config
691 * @param type VPN type
692 */
693 private void createImpRtVal(HubSpokeVpnConfig config, VpnType type) {
694 if (type == HUB) {
695 if (config.hubImpRt() != null) {
696 return;
697 }
698 setHubImpRt(config);
699 } else {
700 if (config.spokeImpRt() != null) {
701 return;
702 }
703 config.spokeImpRt(config.rd());
704 }
705 }
706
707 /**
708 * Sets the HUB import RT, from the spoke export RT. If it is not
709 * available a new ID is generated.
710 *
711 * @param config VPN config
712 */
713 public void setHubImpRt(HubSpokeVpnConfig config) {
714 String hubImp;
715 if (config.spokeExpRt() != null) {
716 hubImp = config.spokeExpRt();
717 } else {
718 hubImp = getIdFromGen();
719 }
720 config.hubImpRt(hubImp);
721 }
722
723 /**
724 * Creates export RT value for HUB and SPOKE, according to the type, if
725 * the values are not present.
726 *
727 * @param config VPN config
728 * @param type VPN type
729 */
730 private void createExpRtVal(HubSpokeVpnConfig config, VpnType type) {
731 if (type == HUB) {
732 if (config.hubExpRt() != null) {
733 return;
734 }
735 config.hubExpRt(config.rd());
736 } else {
737 if (config.spokeExpRt() != null) {
738 return;
739 }
740 setSpokeExpRt(config);
741 }
742 }
743
744 /**
745 * Sets the SPOKE export RT, from the hub import RT. If it is not
746 * available a new ID is generated.
747 *
748 * @param config VPN config
749 */
750 public void setSpokeExpRt(HubSpokeVpnConfig config) {
751 String spokeExp;
752 if (config.hubImpRt() != null) {
753 spokeExp = config.hubImpRt();
754 } else {
755 spokeExp = getIdFromGen();
756 }
757 config.spokeExpRt(spokeExp);
758 }
759
760 /**
761 * Returns the interface name from the requested type service object.
762 *
763 * @param info device info
764 * @param reqType requested type
765 * @return interface name
766 */
767 private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
768 DefaultAugmentedL3VpnRequestedType req =
769 ((DefaultRequestedType) reqType).augmentation(
770 DefaultAugmentedL3VpnRequestedType.class);
771 if (req == null || req.requestedTypeProfile() == null ||
772 req.requestedTypeProfile().requestedTypeChoice() == null) {
773 throw new NetL3VpnException(INT_INFO_NULL);
774 }
775 RequestedTypeChoice reqChoice = req.requestedTypeProfile()
776 .requestedTypeChoice();
777 return getNameFromChoice(reqChoice, info.deviceId());
778 }
779
780 /**
781 * Returns the interface name from the type choice provided.
782 *
783 * @param choice service choice
784 * @param id device id
785 * @return interface name
786 */
787 private String getNameFromChoice(RequestedTypeChoice choice, DeviceId id) {
788 if (choice == null) {
789 throw new NetL3VpnException(INT_INFO_NULL);
790 }
791 String intName;
792 if (choice instanceof DefaultDot1Qcase) {
793 if (((DefaultDot1Qcase) choice).dot1q() == null ||
794 ((DefaultDot1Qcase) choice).dot1q()
795 .physicalIf() == null) {
796 throw new NetL3VpnException(INT_INFO_NULL);
797 }
798 intName = ((DefaultDot1Qcase) choice).dot1q().physicalIf();
799 } else {
800 if (((DefaultPhysicalCase) choice).physical() == null ||
801 ((DefaultPhysicalCase) choice).physical()
802 .physicalIf() == null) {
803 throw new NetL3VpnException(INT_INFO_NULL);
804 }
805 intName = ((DefaultPhysicalCase) choice).physical().physicalIf();
806 }
807 return getPortName(intName, id);
808 }
809
810 /**
811 * Returns the port name when it the port is available in the device.
812 *
813 * @param intName interface name
814 * @param id device id
815 * @return port name
816 */
817 private String getPortName(String intName, DeviceId id) {
818 List<Port> ports = deviceService.getPorts(id);
819 for (Port port : ports) {
820 String pName = port.annotations().value(PORT_NAME);
821 if (pName.equals(intName)) {
822 return intName;
823 }
824 }
825 throw new NetL3VpnException(getIntNotAvailable(intName));
826 }
827
828 /**
829 * Builds the interface for the device binding with the VPN instance.
830 *
831 * @param info device info
832 * @param ins VPN instance
833 * @param connect IP connection
834 * @param pName port name
835 * @param access access info
836 */
837 private void buildDevVpnInt(DeviceInfo info, VpnInstance ins,
838 IpConnection connect, String pName,
839 AccessInfo access) {
840 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
841 info.addAccessInfo(access);
842 info.addIfName(pName);
843 Interfaces interfaces = createInterface(pName, ins.vpnName(),
844 connect);
845 ModelObjectData devMod = getIntCreateModObj(
846 intMap, interfaces, info.deviceId().toString());
847 ModelObjectData driMod = info.processCreateInterface(driverService,
848 devMod);
849 ResourceData resData = modelConverter.createDataNode(driMod);
850 addToStore(resData);
851 }
852
853 /**
854 * Builds the BGP information from the routes that are given from the
855 * service.
856 *
857 * @param routes routing protocol
858 * @param info device info
859 * @param name VPN name
860 * @param connect IP connection
861 * @param access access info
862 */
863 private void buildBgpInfo(List<RoutingProtocol> routes, DeviceInfo info,
864 String name, IpConnection connect,
865 AccessInfo access) {
866 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
867 BgpInfo intBgp = createBgpInfo(routes, info, name, connect, access);
868 if (intBgp != null) {
869 intBgp.vpnName(name);
870 BgpDriverInfo config = getBgpCreateConfigObj(
871 bgpMap, info.deviceId().toString());
872 ModelObjectData driData = info.processCreateBgpInfo(
873 driverService, intBgp, config);
874 l3VpnStore.addBgpInfo(info.bgpInfo(), info.deviceId());
875 ResourceData resData = modelConverter.createDataNode(driData);
876 addToStore(resData);
877 }
878 }
879
880 /**
881 * Representation of internal listener, listening for dynamic config event.
882 */
883 private class InternalConfigListener implements DynamicConfigListener {
884
885 @Override
886 public boolean isRelevant(DynamicConfigEvent event) {
887 return isSupported(event);
888 }
889
890 @Override
891 public void event(DynamicConfigEvent event) {
892 executor.execute(() -> {
893 try {
894 ResourceId rsId = event.subject();
895 switch (event.type()) {
896 case NODE_ADDED:
897 processCreateFromStore(rsId);
898 break;
899
900 case NODE_DELETED:
901 //TODO: To be committed.
902 break;
903
904 default:
905 throw new NetL3VpnException(EVENT_NOT_SUPPORTED);
906 }
907 } catch (Exception e) {
908 log.warn("Failed to process {}", event, e);
909 }
910 });
911 }
912 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530913
914 /**
915 * Signals that the leadership has changed.
916 *
917 * @param isLeader true if this instance is now the leader, otherwise false
918 */
919 private void leaderChanged(boolean isLeader) {
920 log.debug("Leader changed: {}", isLeader);
921
922 if (!isLeader) {
923 isElectedLeader = false;
924 isActivatedLeader = false;
925 // Nothing to do
926 return;
927 }
928 isActivatedLeader = false;
929 isElectedLeader = true;
930 }
931
932 /**
933 * A listener for leadership events.
934 */
935 private class InternalLeadershipListener implements LeadershipEventListener {
936
937 @Override
938 public boolean isRelevant(LeadershipEvent event) {
939 return event.subject().topic().equals(appId.name());
940 }
941
942 @Override
943 public void event(LeadershipEvent event) {
944 switch (event.type()) {
945 case LEADER_CHANGED:
946 case LEADER_AND_CANDIDATES_CHANGED:
947 if (localNodeId.equals(event.subject().leaderNodeId())) {
948 log.info("Net l3vpn manager gained leadership");
949 leaderChanged(true);
950 } else {
951 log.info("Net l3vpn manager leader changed. New " +
952 "leader is {}", event.subject()
953 .leaderNodeId());
954 leaderChanged(false);
955 }
956 default:
957 break;
958 }
959 }
960 }
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530961}