blob: 67c623716c7b0ad31389027b5d47a0cb1c52ef64 [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;
janani b176905a2017-03-28 17:36:18 +053023import org.onlab.util.AbstractAccumulator;
24import org.onlab.util.Accumulator;
Bharat saraswalcdfda202017-03-24 23:40:50 +053025import org.onosproject.cluster.ClusterService;
26import org.onosproject.cluster.LeadershipEvent;
27import org.onosproject.cluster.LeadershipEventListener;
28import org.onosproject.cluster.LeadershipService;
29import org.onosproject.cluster.NodeId;
janani b35f6cbc2017-03-24 21:56:58 +053030import org.onosproject.config.DynamicConfigEvent;
31import org.onosproject.config.DynamicConfigListener;
32import org.onosproject.config.DynamicConfigService;
janani b176905a2017-03-28 17:36:18 +053033import org.onosproject.config.FailedException;
34import org.onosproject.config.Filter;
Bharat saraswalcdfda202017-03-24 23:40:50 +053035import org.onosproject.core.ApplicationId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053036import org.onosproject.core.CoreService;
janani b35f6cbc2017-03-24 21:56:58 +053037import org.onosproject.core.IdGenerator;
38import org.onosproject.l3vpn.netl3vpn.AccessInfo;
39import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
40import org.onosproject.l3vpn.netl3vpn.BgpInfo;
41import org.onosproject.l3vpn.netl3vpn.DeviceInfo;
42import org.onosproject.l3vpn.netl3vpn.FullMeshVpnConfig;
43import org.onosproject.l3vpn.netl3vpn.HubSpokeVpnConfig;
44import org.onosproject.l3vpn.netl3vpn.InterfaceInfo;
45import org.onosproject.l3vpn.netl3vpn.NetL3VpnException;
46import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
47import org.onosproject.l3vpn.netl3vpn.VpnConfig;
48import org.onosproject.l3vpn.netl3vpn.VpnInstance;
49import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
50import org.onosproject.l3vpn.netl3vpn.VpnType;
51import org.onosproject.net.Device;
52import org.onosproject.net.DeviceId;
53import org.onosproject.net.Port;
54import org.onosproject.net.device.DeviceService;
55import org.onosproject.net.driver.DriverService;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053056import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev20130715.IetfInetTypes;
janani b35f6cbc2017-03-24 21:56:58 +053057import 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 +053058import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.IetfL3VpnSvc;
janani b35f6cbc2017-03-24 21:56:58 +053059import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.DefaultL3VpnSvc;
60import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.L3VpnSvc;
61import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.VpnAttachment;
62import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.AttachmentFlavor;
63import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.attachmentflavor.DefaultVpnId;
janani b176905a2017-03-28 17:36:18 +053064import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.DefaultSites;
janani b35f6cbc2017-03-24 21:56:58 +053065import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.Sites;
66import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.VpnServices;
67import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.Site;
68import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.SiteNetworkAccesses;
69import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.sitenetworkaccesses.SiteNetworkAccess;
70import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.vpnservices.VpnSvc;
71import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.Bearer;
72import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.DefaultBearer;
73import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.DefaultRequestedType;
74import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.RequestedType;
75import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
76import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.RoutingProtocols;
77import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.routingprotocols.RoutingProtocol;
78import 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 +053079import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.IetfYangTypes;
80import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.L3VpnSvcExt;
janani b35f6cbc2017-03-24 21:56:58 +053081import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.DefaultAugmentedL3VpnBearer;
82import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.requestedtype.DefaultAugmentedL3VpnRequestedType;
83import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.RequestedTypeChoice;
84import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultDot1Qcase;
85import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultPhysicalCase;
86import org.onosproject.yang.model.DataNode;
87import org.onosproject.yang.model.DefaultModelObjectData;
88import org.onosproject.yang.model.ModelConverter;
89import org.onosproject.yang.model.ModelObject;
90import org.onosproject.yang.model.ModelObjectData;
91import org.onosproject.yang.model.ModelObjectId;
92import org.onosproject.yang.model.NodeKey;
93import org.onosproject.yang.model.ResourceData;
94import org.onosproject.yang.model.ResourceId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053095import org.onosproject.yang.model.YangModel;
96import org.onosproject.yang.model.YangModuleId;
97import org.onosproject.yang.runtime.DefaultAppModuleInfo;
98import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
99import org.onosproject.yang.runtime.ModelRegistrationParam;
100import org.onosproject.yang.runtime.YangModelRegistry;
101import org.slf4j.Logger;
102import org.slf4j.LoggerFactory;
103
104import java.util.Iterator;
janani b35f6cbc2017-03-24 21:56:58 +0530105import java.util.List;
106import java.util.Map;
janani b176905a2017-03-28 17:36:18 +0530107import java.util.Timer;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530108
janani b176905a2017-03-28 17:36:18 +0530109import static com.google.common.base.Preconditions.checkNotNull;
janani b35f6cbc2017-03-24 21:56:58 +0530110import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
111import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530112import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
janani b35f6cbc2017-03-24 21:56:58 +0530113import static org.onosproject.l3vpn.netl3vpn.impl.BgpConstructionUtil.createBgpInfo;
114import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.createInstance;
janani b176905a2017-03-28 17:36:18 +0530115import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.deleteInstance;
janani b35f6cbc2017-03-24 21:56:58 +0530116import static org.onosproject.l3vpn.netl3vpn.impl.IntConstructionUtil.createInterface;
117import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.BEARER_NULL;
118import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.CONS_HUNDRED;
119import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.DEVICE_INFO_NULL;
janani b176905a2017-03-28 17:36:18 +0530120import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.EVENT_NULL;
janani b35f6cbc2017-03-24 21:56:58 +0530121import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT;
122import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT_EXCEEDED;
123import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.INT_INFO_NULL;
janani b176905a2017-03-28 17:36:18 +0530124import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP;
janani b35f6cbc2017-03-24 21:56:58 +0530125import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP_INT_INFO_NULL;
janani b176905a2017-03-28 17:36:18 +0530126import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_BATCH_MS;
127import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_EVENTS;
128import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_IDLE_MS;
janani b35f6cbc2017-03-24 21:56:58 +0530129import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.PORT_NAME;
130import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_ROLE_NULL;
131import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_VPN_MISMATCH;
janani b176905a2017-03-28 17:36:18 +0530132import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.TIMER;
133import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.UNKNOWN_EVENT;
janani b35f6cbc2017-03-24 21:56:58 +0530134import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_ATTACHMENT_NULL;
135import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_POLICY_NOT_SUPPORTED;
136import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_TYPE_UNSUPPORTED;
137import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getBgpCreateConfigObj;
138import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntCreateModObj;
139import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntNotAvailable;
140import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getMgmtIpUnAvailErr;
141import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForL3VpnSvc;
142import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForSites;
143import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getResourceData;
144import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getRole;
janani bd821b182017-03-30 16:34:49 +0530145import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnBgpDelModObj;
janani b35f6cbc2017-03-24 21:56:58 +0530146import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnCreateModObj;
janani bd821b182017-03-30 16:34:49 +0530147import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnDelModObj;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530148import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.getYangModel;
149
150/**
151 * The IETF net l3vpn manager implementation.
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530152 */
153@Component(immediate = true)
janani bd821b182017-03-30 16:34:49 +0530154public class NetL3VpnManager {
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530155
156 private static final String APP_ID = "org.onosproject.app.l3vpn";
janani b35f6cbc2017-03-24 21:56:58 +0530157 private static final String L3_VPN_ID_TOPIC = "l3vpn-id";
janani b35f6cbc2017-03-24 21:56:58 +0530158
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530159 private final Logger log = LoggerFactory.getLogger(getClass());
160
janani b176905a2017-03-28 17:36:18 +0530161 private final DynamicConfigListener configListener =
162 new InternalConfigListener();
163
164 private final Accumulator<DynamicConfigEvent> accumulator =
165 new InternalEventAccumulator();
166
167 private final InternalLeadershipListener leadershipEventListener =
168 new InternalLeadershipListener();
169
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530170 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
171 protected CoreService coreService;
172
173 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
janani b35f6cbc2017-03-24 21:56:58 +0530174 protected DriverService driverService;
175
176 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
177 protected DeviceService deviceService;
178
179 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530180 protected YangModelRegistry modelRegistry;
181
janani b35f6cbc2017-03-24 21:56:58 +0530182 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
183 protected ModelConverter modelConverter;
184
185 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
186 protected DynamicConfigService configService;
187
188 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
189 protected NetL3VpnStore l3VpnStore;
190
Bharat saraswalcdfda202017-03-24 23:40:50 +0530191 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
192 protected LeadershipService leadershipService;
193
194 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
195 protected ClusterService clusterService;
196
janani b35f6cbc2017-03-24 21:56:58 +0530197 protected IdGenerator l3VpnIdGen;
janani b176905a2017-03-28 17:36:18 +0530198
Bharat saraswalcdfda202017-03-24 23:40:50 +0530199 private NodeId localNodeId;
janani b176905a2017-03-28 17:36:18 +0530200
Bharat saraswalcdfda202017-03-24 23:40:50 +0530201 private ApplicationId appId;
janani b35f6cbc2017-03-24 21:56:58 +0530202
janani b35f6cbc2017-03-24 21:56:58 +0530203 private ModelRegistrationParam regParam;
204
janani b35f6cbc2017-03-24 21:56:58 +0530205 private ResourceId id;
janani b176905a2017-03-28 17:36:18 +0530206
janani b35f6cbc2017-03-24 21:56:58 +0530207 private ResourceId module;
janani b176905a2017-03-28 17:36:18 +0530208
janani b35f6cbc2017-03-24 21:56:58 +0530209 private ResourceId sites;
janani b176905a2017-03-28 17:36:18 +0530210
Bharat saraswalcdfda202017-03-24 23:40:50 +0530211 private boolean isElectedLeader = false;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530212
213 @Activate
214 protected void activate() {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530215 appId = coreService.registerApplication(APP_ID);
janani b35f6cbc2017-03-24 21:56:58 +0530216 l3VpnIdGen = coreService.getIdGenerator(L3_VPN_ID_TOPIC);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530217
218 localNodeId = clusterService.getLocalNode().id();
219
220 leadershipService.addListener(leadershipEventListener);
221 leadershipService.runForLeadership(appId.name());
222
janani b35f6cbc2017-03-24 21:56:58 +0530223 registerModel();
224 getResourceId();
225 configService.addListener(configListener);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530226 log.info("Started");
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530227 }
228
229 @Deactivate
230 protected void deactivate() {
231 modelRegistry.unregisterModel(regParam);
janani b35f6cbc2017-03-24 21:56:58 +0530232 configService.removeListener(configListener);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530233
234 leadershipService.withdraw(appId.name());
235 leadershipService.removeListener(leadershipEventListener);
236
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530237 log.info("Stopped");
238 }
239
240 private void registerModel() {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530241 YangModel model = getYangModel(IetfInetTypes.class);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530242 Iterator<YangModuleId> it = model.getYangModulesId().iterator();
243
244 //Create model registration param.
245 ModelRegistrationParam.Builder b =
246 DefaultModelRegistrationParam.builder().setYangModel(model);
247
248 YangModuleId id;
249 while (it.hasNext()) {
250 id = it.next();
251 switch (id.moduleName()) {
252 case "ietf-inet-types":
253 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
254 IetfInetTypes.class, null));
255 break;
256 case "ietf-l3vpn-svc":
257 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
258 IetfL3VpnSvc.class, null));
259 break;
260 case "ietf-yang-types":
261 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
262 IetfYangTypes.class, null));
263 break;
264 case "l3vpn-svc-ext":
265 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
266 L3VpnSvcExt.class, null));
267 break;
268 default:
269 break;
270 }
271 }
272 regParam = b.build();
273 modelRegistry.registerModel(regParam);
274 }
janani b35f6cbc2017-03-24 21:56:58 +0530275
276 /**
277 * Returns id as string. If the id is not in the freed list a new id is
278 * generated else the id from the freed list is used.
279 *
280 * @return id
281 */
282 private String getIdFromGen() {
283 Long value;
284 Iterable<Long> freeIds = l3VpnStore.getFreedIdList();
285 Iterator<Long> it = freeIds.iterator();
286 if (it.hasNext()) {
287 value = it.next();
288 l3VpnStore.removeIdFromFreeList(value);
289 } else {
290 value = l3VpnIdGen.getNewId();
291 }
292 if (value > ID_LIMIT) {
293 throw new RuntimeException(ID_LIMIT_EXCEEDED);
294 }
295 return CONS_HUNDRED + String.valueOf(value);
296 }
297
298 /**
299 * Returns the resource id, after constructing model object id and
300 * converting it.
301 */
302 private void getResourceId() {
303
304 ModelObjectId moduleId = ModelObjectId.builder().build();
305 module = getResourceVal(moduleId);
306
307 ModelObjectId svcId = getModIdForL3VpnSvc();
308 id = getResourceVal(svcId);
309
310 ModelObjectId sitesId = getModIdForSites();
311 sites = getResourceVal(sitesId);
312 }
313
314 /**
315 * Returns resource id from model converter.
316 *
317 * @param modelId model object id
318 * @return resource id
319 */
320 private ResourceId getResourceVal(ModelObjectId modelId) {
321 DefaultModelObjectData.Builder data = DefaultModelObjectData.builder()
Thomas Vachuskad17bc732017-03-24 11:46:55 -0700322 .identifier(modelId);
janani b35f6cbc2017-03-24 21:56:58 +0530323 ResourceData resData = modelConverter.createDataNode(data.build());
janani b176905a2017-03-28 17:36:18 +0530324 return resData.resourceId();
janani b35f6cbc2017-03-24 21:56:58 +0530325 }
326
327 /**
328 * Processes create request from the store, by taking the root object.
329 * The root object is then used for l3VPN processing.
330 *
331 * @param storeId store resource id
janani b176905a2017-03-28 17:36:18 +0530332 * @param node data node
janani b35f6cbc2017-03-24 21:56:58 +0530333 */
janani b176905a2017-03-28 17:36:18 +0530334 private void processCreateFromStore(ResourceId storeId, DataNode node) {
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530335 if (isElectedLeader) {
janani b176905a2017-03-28 17:36:18 +0530336 List<NodeKey> keys = storeId.nodeKeys();
337 List<ModelObject> objects = null;
338 if (keys.size() == 1) {
339 objects = getModelObjects(node, module);
340 } else if (keys.size() == 2) {
341 objects = getModelObjects(node, id);
342 }
343 if (objects != null) {
344 for (ModelObject obj : objects) {
345 if (obj instanceof DefaultL3VpnSvc) {
346 DefaultL3VpnSvc l3VpnSvc = (DefaultL3VpnSvc) obj;
347 createGlobalConfig(l3VpnSvc);
348 } else if (obj instanceof DefaultSites) {
349 DefaultSites sites = (DefaultSites) obj;
350 createInterfaceConfig(sites);
351 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530352 }
janani b35f6cbc2017-03-24 21:56:58 +0530353 }
354 }
355 }
356
357 /**
Bharat saraswalcdfda202017-03-24 23:40:50 +0530358 * Processes delete request from the store, by taking the root object.
janani b176905a2017-03-28 17:36:18 +0530359 * The root object would have got deleted from store. So all the
360 * configurations are removed.
Bharat saraswalcdfda202017-03-24 23:40:50 +0530361 *
janani b176905a2017-03-28 17:36:18 +0530362 * @param dataNode data node
Bharat saraswalcdfda202017-03-24 23:40:50 +0530363 */
janani b176905a2017-03-28 17:36:18 +0530364 private void processDeleteFromStore(DataNode dataNode) {
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530365 if (isElectedLeader) {
janani b176905a2017-03-28 17:36:18 +0530366 if (dataNode == null) {
367 //TODO: Delete for inner nodes.
368 deleteGlobalConfig(null);
369 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530370 }
371 }
372
373 /**
janani b176905a2017-03-28 17:36:18 +0530374 * Returns model objects of the store. The data node read from store
375 * gives the particular node. So the node's parent resource id is taken
376 * and the data node is given to model converter.
janani b35f6cbc2017-03-24 21:56:58 +0530377 *
janani b176905a2017-03-28 17:36:18 +0530378 * @param dataNode data node from store
379 * @param appId parent resource id
janani b35f6cbc2017-03-24 21:56:58 +0530380 * @return model objects
381 */
janani b176905a2017-03-28 17:36:18 +0530382 public List<ModelObject> getModelObjects(DataNode dataNode,
janani b35f6cbc2017-03-24 21:56:58 +0530383 ResourceId appId) {
janani b35f6cbc2017-03-24 21:56:58 +0530384 ResourceData data = getResourceData(dataNode, appId);
385 ModelObjectData modelData = modelConverter.createModel(data);
386 return modelData.modelObjects();
387 }
388
389 /**
390 * Returns true if the event resource id points to the root level node
391 * only and event is for addition and deletion; false otherwise.
392 *
393 * @param event config event
394 * @return true if event is supported; false otherwise
395 */
396 public boolean isSupported(DynamicConfigEvent event) {
397 ResourceId rsId = event.subject();
398 List<NodeKey> storeKeys = rsId.nodeKeys();
399 List<NodeKey> regKeys = id.nodeKeys();
janani b176905a2017-03-28 17:36:18 +0530400 List<NodeKey> sitesKeys = sites.nodeKeys();
janani b35f6cbc2017-03-24 21:56:58 +0530401 if (storeKeys != null) {
janani b176905a2017-03-28 17:36:18 +0530402 int storeSize = storeKeys.size();
403 if (storeSize == 1) {
janani b35f6cbc2017-03-24 21:56:58 +0530404 return storeKeys.get(0).equals(regKeys.get(1)) &&
405 (event.type() == NODE_ADDED ||
406 event.type() == NODE_DELETED);
janani b176905a2017-03-28 17:36:18 +0530407 } else if (storeSize == 2) {
408 return (storeKeys.get(0).equals(sitesKeys.get(1))) &&
409 storeKeys.get(1).equals(sitesKeys.get(2)) &&
410 (event.type() == NODE_ADDED ||
411 event.type() == NODE_DELETED);
janani b35f6cbc2017-03-24 21:56:58 +0530412 }
413 }
414 return false;
415 }
416
417 /***
janani b176905a2017-03-28 17:36:18 +0530418 * Creates all configuration in the standard device model.
janani b35f6cbc2017-03-24 21:56:58 +0530419 *
420 * @param l3VpnSvc l3VPN service object
421 */
422 void createGlobalConfig(L3VpnSvc l3VpnSvc) {
423 if (l3VpnSvc.vpnServices() != null) {
424 createVpnServices(l3VpnSvc.vpnServices());
425 }
426 if (l3VpnSvc.sites() != null) {
427 createInterfaceConfig(l3VpnSvc.sites());
428 }
429 }
430
431 /**
432 * Creates the VPN instances from the VPN services object, if only that
433 * VPN instance is not already created.
434 *
435 * @param vpnSvcs VPN services object
436 */
437 private void createVpnServices(VpnServices vpnSvcs) {
438 if (vpnSvcs != null && vpnSvcs.vpnSvc() != null) {
439 List<VpnSvc> svcList = vpnSvcs.vpnSvc();
440 for (VpnSvc svc : svcList) {
441 String vpnName = svc.vpnId().string();
442 l3VpnStore.addVpnInsIfAbsent(vpnName, new VpnInstance(vpnName));
443 }
444 }
445 }
446
447 /**
448 * Creates interface configuration from the site network access if
449 * available.
450 *
451 * @param sites sites object
452 */
453 private void createInterfaceConfig(Sites sites) {
454 if (sites.site() != null) {
455 List<Site> sitesList = sites.site();
456 for (Site site : sitesList) {
457 if (site.siteNetworkAccesses() != null) {
458 SiteNetworkAccesses accesses = site.siteNetworkAccesses();
459 List<SiteNetworkAccess> accessList =
460 accesses.siteNetworkAccess();
461 for (SiteNetworkAccess access : accessList) {
462 createFromAccess(access, site.siteId().string());
463 }
464 }
465 }
466 }
467 }
468
469 /**
470 * Creates the interface and VPN related configurations from the access
471 * and site id value.
472 *
473 * @param access site network access
474 * @param siteId site id
475 */
476 private void createFromAccess(SiteNetworkAccess access, String siteId) {
477 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
478 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
479 String accessId = access.siteNetworkAccessId().string();
480 AccessInfo info = new AccessInfo(siteId, accessId);
481
482 if (intMap.get(info) == null) {
483 VpnSiteRole siteRole = getSiteRole(access.vpnAttachment());
484 VpnInstance instance = insMap.get(siteRole.name());
485 if (instance == null) {
486 throw new NetL3VpnException(SITE_VPN_MISMATCH);
487 }
488 buildFromAccess(instance, info, access, siteRole);
489 }
490 }
491
492 /**
493 * Returns the VPN site role from the VPN attachment.
494 *
495 * @param attach VPN attachment
496 * @return VPN site role
497 */
498 private VpnSiteRole getSiteRole(VpnAttachment attach) {
499 if (attach == null || attach.attachmentFlavor() == null) {
500 throw new NetL3VpnException(VPN_ATTACHMENT_NULL);
501 }
502 AttachmentFlavor flavor = attach.attachmentFlavor();
503 if (!(flavor instanceof DefaultVpnId)) {
504 throw new NetL3VpnException(VPN_POLICY_NOT_SUPPORTED);
505 }
506 DefaultVpnId vpnId = (DefaultVpnId) flavor;
507 if (vpnId.siteRole() == null) {
508 throw new NetL3VpnException(SITE_ROLE_NULL);
509 }
510 VpnType role = getRole(vpnId.siteRole());
janani b176905a2017-03-28 17:36:18 +0530511 return new VpnSiteRole(String.valueOf(vpnId.vpnId()), role);
janani b35f6cbc2017-03-24 21:56:58 +0530512 }
513
514 /**
515 * Builds the required details for device standard model from the site
516 * network access info available.
517 *
518 * @param instance VPN instance
519 * @param info access info
520 * @param access network access
521 * @param role VPN site role
522 */
523 private void buildFromAccess(VpnInstance instance, AccessInfo info,
524 SiteNetworkAccess access, VpnSiteRole role) {
525 Bearer bearer = access.bearer();
526 if (bearer == null) {
527 throw new NetL3VpnException(BEARER_NULL);
528 }
529
530 RequestedType reqType = bearer.requestedType();
531 IpConnection connect = access.ipConnection();
532 RoutingProtocols pro = access.routingProtocols();
533
534 if (reqType == null || connect == null) {
535 throw new NetL3VpnException(IP_INT_INFO_NULL);
536 }
537 buildDeviceDetails(instance, info, role, bearer, connect,
538 reqType, pro);
539 }
540
541 /**
542 * Builds the device details such as, VPN instance value if it is for
543 * the first time, interface values and BGP info if available in service.
544 *
545 * @param instance VPN instance
546 * @param accInfo access info
547 * @param role VPN site role
548 * @param bearer bearer object
549 * @param connect ip connect object
550 * @param reqType requested type
551 * @param pro routing protocol
552 */
553 private void buildDeviceDetails(VpnInstance instance, AccessInfo accInfo,
554 VpnSiteRole role, Bearer bearer,
555 IpConnection connect, RequestedType reqType,
556 RoutingProtocols pro) {
557 Map<AccessInfo, InterfaceInfo> interMap = l3VpnStore.getInterfaceInfo();
558 InterfaceInfo intInfo = interMap.get(accInfo);
559 if (intInfo != null) {
560 return;
561 }
562
563 DeviceInfo info = buildDevVpnIns(bearer, instance, role, connect);
564 String portName = getInterfaceName(info, reqType);
565 buildDevVpnInt(info, instance, connect, portName, accInfo);
566
567 if (pro != null && pro.routingProtocol() != null) {
568 buildBgpInfo(pro.routingProtocol(), info,
569 role.name(), connect, accInfo);
570 }
571 InterfaceInfo interInfo = new InterfaceInfo(info, portName,
572 instance.vpnName());
573 l3VpnStore.addInterfaceInfo(accInfo, interInfo);
janani bd821b182017-03-30 16:34:49 +0530574 l3VpnStore.addVpnIns(instance.vpnName(), instance);
janani b35f6cbc2017-03-24 21:56:58 +0530575 }
576
577 /**
578 * Builds device VPN instance with the service objects. It returns
579 *
580 * @param bearer bearer object
581 * @param ins VPN instance
582 * @param role VPN site role
583 * @param connect ip connection
584 * @return return
585 */
586 private DeviceInfo buildDevVpnIns(Bearer bearer, VpnInstance ins,
587 VpnSiteRole role, IpConnection connect) {
588 DefaultAugmentedL3VpnBearer augBearer = ((DefaultBearer) bearer)
589 .augmentation(DefaultAugmentedL3VpnBearer.class);
590 DeviceId id = getDeviceId(augBearer);
591 Map<DeviceId, DeviceInfo> devices = ins.devInfo();
592 DeviceInfo info = null;
593 if (devices != null) {
594 info = devices.get(id);
595 }
596 if (info == null) {
597 info = createVpnInstance(id, role, ins, connect);
598 }
599 return info;
600 }
601
602 /**
603 * Returns the device id from the bearer augment attachment of service.
604 * If the attachment in augment is not available it throws error.
605 *
606 * @param attach augmented bearer
607 * @return device id
608 */
609 private DeviceId getDeviceId(DefaultAugmentedL3VpnBearer attach) {
610 if (attach == null || attach.bearerAttachment() == null ||
611 attach.bearerAttachment().peMgmtIp() == null ||
612 attach.bearerAttachment().peMgmtIp().string() == null) {
613 throw new NetL3VpnException(DEVICE_INFO_NULL);
614 }
615 String ip = attach.bearerAttachment().peMgmtIp().string();
616 return getId(ip);
617 }
618
619 /**
620 * Returns the device id whose management ip address matches with the ip
621 * received.
622 *
623 * @param ip ip address
624 * @return device id
625 */
626 public DeviceId getId(String ip) {
627 for (Device device : deviceService.getAvailableDevices()) {
janani b176905a2017-03-28 17:36:18 +0530628 String val = device.annotations().value(IP);
janani b35f6cbc2017-03-24 21:56:58 +0530629 if (ip.equals(val)) {
630 return device.id();
631 }
632 }
633 throw new NetL3VpnException(getMgmtIpUnAvailErr(ip));
634 }
635
636 /**
637 * Creates the VPN instance by constructing standard device model of
638 * instances. It adds the RD and RT values to the VPN instance.
639 *
640 * @param id device id
641 * @param role VPN site role
642 * @param inst VPN instance
643 * @param ip ip connection
644 * @return device info
645 */
646 private DeviceInfo createVpnInstance(DeviceId id, VpnSiteRole role,
647 VpnInstance inst, IpConnection ip) {
648 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
649 generateRdRt(inst, role);
650 DeviceInfo info = new DeviceInfo(id);
janani b35f6cbc2017-03-24 21:56:58 +0530651
652 NetworkInstances instances = createInstance(inst, role, ip);
653 ModelObjectData devMod = getVpnCreateModObj(intMap, instances,
654 id.toString());
655 ModelObjectData driMod = info.processCreateInstance(driverService,
656 devMod);
657 ResourceData resData = modelConverter.createDataNode(driMod);
658 addToStore(resData);
janani b36b1d772017-03-27 15:01:28 +0530659 l3VpnStore.addVpnIns(inst.vpnName(), inst);
janani bd821b182017-03-30 16:34:49 +0530660 inst.addDevInfo(id, info);
janani b35f6cbc2017-03-24 21:56:58 +0530661 return info;
662 }
663
664 /**
665 * Adds the resource data that is received from the driver, after
666 * converting from the model object data.
667 *
668 * @param resData resource data
669 */
670 private void addToStore(ResourceData resData) {
671 if (resData != null && resData.dataNodes() != null) {
672 List<DataNode> dataNodes = resData.dataNodes();
673 for (DataNode node : dataNodes) {
674 configService.createNodeRecursive(resData.resourceId(), node);
675 }
676 }
677 }
678
679 /**
680 * Generates RD and RT value for the VPN instance for the first time VPN
681 * instance creation.
682 *
683 * @param ins VPN instance
684 * @param role VPN site role
685 */
686 private void generateRdRt(VpnInstance ins, VpnSiteRole role) {
687 ins.type(role.role());
688 VpnConfig config = ins.vpnConfig();
689 String rd = null;
690 if (config == null) {
691 rd = getIdFromGen();
692 }
693 switch (ins.type()) {
694 case ANY_TO_ANY:
695 if (config == null) {
696 config = new FullMeshVpnConfig(rd);
697 config.rd(rd);
698 }
699 break;
700
701 case HUB:
702 case SPOKE:
703 if (config == null) {
704 config = new HubSpokeVpnConfig();
705 config.rd(rd);
706 }
707 createImpRtVal((HubSpokeVpnConfig) config, ins.type());
708 createExpRtVal((HubSpokeVpnConfig) config, ins.type());
709 break;
710
711 default:
712 throw new NetL3VpnException(VPN_TYPE_UNSUPPORTED);
713 }
714 ins.vpnConfig(config);
715 }
716
717 /**
718 * Creates import RT value for HUB and SPOKE, according to the type, if
719 * the values are not present.
720 *
721 * @param config VPN config
722 * @param type VPN type
723 */
724 private void createImpRtVal(HubSpokeVpnConfig config, VpnType type) {
725 if (type == HUB) {
726 if (config.hubImpRt() != null) {
727 return;
728 }
729 setHubImpRt(config);
730 } else {
731 if (config.spokeImpRt() != null) {
732 return;
733 }
734 config.spokeImpRt(config.rd());
735 }
736 }
737
738 /**
739 * Sets the HUB import RT, from the spoke export RT. If it is not
740 * available a new ID is generated.
741 *
742 * @param config VPN config
743 */
744 public void setHubImpRt(HubSpokeVpnConfig config) {
745 String hubImp;
746 if (config.spokeExpRt() != null) {
747 hubImp = config.spokeExpRt();
748 } else {
749 hubImp = getIdFromGen();
750 }
751 config.hubImpRt(hubImp);
752 }
753
754 /**
755 * Creates export RT value for HUB and SPOKE, according to the type, if
756 * the values are not present.
757 *
758 * @param config VPN config
759 * @param type VPN type
760 */
761 private void createExpRtVal(HubSpokeVpnConfig config, VpnType type) {
762 if (type == HUB) {
763 if (config.hubExpRt() != null) {
764 return;
765 }
766 config.hubExpRt(config.rd());
767 } else {
768 if (config.spokeExpRt() != null) {
769 return;
770 }
771 setSpokeExpRt(config);
772 }
773 }
774
775 /**
776 * Sets the SPOKE export RT, from the hub import RT. If it is not
777 * available a new ID is generated.
778 *
779 * @param config VPN config
780 */
781 public void setSpokeExpRt(HubSpokeVpnConfig config) {
782 String spokeExp;
783 if (config.hubImpRt() != null) {
784 spokeExp = config.hubImpRt();
785 } else {
786 spokeExp = getIdFromGen();
787 }
788 config.spokeExpRt(spokeExp);
789 }
790
791 /**
792 * Returns the interface name from the requested type service object.
793 *
794 * @param info device info
795 * @param reqType requested type
796 * @return interface name
797 */
798 private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
799 DefaultAugmentedL3VpnRequestedType req =
800 ((DefaultRequestedType) reqType).augmentation(
801 DefaultAugmentedL3VpnRequestedType.class);
802 if (req == null || req.requestedTypeProfile() == null ||
803 req.requestedTypeProfile().requestedTypeChoice() == null) {
804 throw new NetL3VpnException(INT_INFO_NULL);
805 }
806 RequestedTypeChoice reqChoice = req.requestedTypeProfile()
807 .requestedTypeChoice();
808 return getNameFromChoice(reqChoice, info.deviceId());
809 }
810
811 /**
812 * Returns the interface name from the type choice provided.
813 *
814 * @param choice service choice
815 * @param id device id
816 * @return interface name
817 */
818 private String getNameFromChoice(RequestedTypeChoice choice, DeviceId id) {
819 if (choice == null) {
820 throw new NetL3VpnException(INT_INFO_NULL);
821 }
822 String intName;
823 if (choice instanceof DefaultDot1Qcase) {
824 if (((DefaultDot1Qcase) choice).dot1q() == null ||
825 ((DefaultDot1Qcase) choice).dot1q()
826 .physicalIf() == null) {
827 throw new NetL3VpnException(INT_INFO_NULL);
828 }
829 intName = ((DefaultDot1Qcase) choice).dot1q().physicalIf();
830 } else {
831 if (((DefaultPhysicalCase) choice).physical() == null ||
832 ((DefaultPhysicalCase) choice).physical()
833 .physicalIf() == null) {
834 throw new NetL3VpnException(INT_INFO_NULL);
835 }
836 intName = ((DefaultPhysicalCase) choice).physical().physicalIf();
837 }
838 return getPortName(intName, id);
839 }
840
841 /**
842 * Returns the port name when it the port is available in the device.
843 *
844 * @param intName interface name
845 * @param id device id
846 * @return port name
847 */
848 private String getPortName(String intName, DeviceId id) {
849 List<Port> ports = deviceService.getPorts(id);
850 for (Port port : ports) {
851 String pName = port.annotations().value(PORT_NAME);
852 if (pName.equals(intName)) {
853 return intName;
854 }
855 }
856 throw new NetL3VpnException(getIntNotAvailable(intName));
857 }
858
859 /**
860 * Builds the interface for the device binding with the VPN instance.
861 *
862 * @param info device info
863 * @param ins VPN instance
864 * @param connect IP connection
865 * @param pName port name
866 * @param access access info
867 */
868 private void buildDevVpnInt(DeviceInfo info, VpnInstance ins,
869 IpConnection connect, String pName,
870 AccessInfo access) {
871 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
872 info.addAccessInfo(access);
873 info.addIfName(pName);
874 Interfaces interfaces = createInterface(pName, ins.vpnName(),
875 connect);
876 ModelObjectData devMod = getIntCreateModObj(
janani bd821b182017-03-30 16:34:49 +0530877 info.ifNames(), interfaces, info.deviceId().toString());
janani b35f6cbc2017-03-24 21:56:58 +0530878 ModelObjectData driMod = info.processCreateInterface(driverService,
879 devMod);
880 ResourceData resData = modelConverter.createDataNode(driMod);
881 addToStore(resData);
882 }
883
884 /**
885 * Builds the BGP information from the routes that are given from the
886 * service.
887 *
888 * @param routes routing protocol
889 * @param info device info
890 * @param name VPN name
891 * @param connect IP connection
892 * @param access access info
893 */
894 private void buildBgpInfo(List<RoutingProtocol> routes, DeviceInfo info,
895 String name, IpConnection connect,
896 AccessInfo access) {
897 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
898 BgpInfo intBgp = createBgpInfo(routes, info, name, connect, access);
899 if (intBgp != null) {
900 intBgp.vpnName(name);
901 BgpDriverInfo config = getBgpCreateConfigObj(
janani bd821b182017-03-30 16:34:49 +0530902 bgpMap, info.deviceId().toString(), info.bgpInfo(), intBgp);
janani b35f6cbc2017-03-24 21:56:58 +0530903 ModelObjectData driData = info.processCreateBgpInfo(
904 driverService, intBgp, config);
905 l3VpnStore.addBgpInfo(info.bgpInfo(), info.deviceId());
906 ResourceData resData = modelConverter.createDataNode(driData);
907 addToStore(resData);
908 }
909 }
910
911 /**
janani b176905a2017-03-28 17:36:18 +0530912 * Creates all configuration in the standard device model.
913 *
914 * @param l3VpnSvc l3 VPN service
915 */
916 void deleteGlobalConfig(L3VpnSvc l3VpnSvc) {
917 deleteGlobalVpn(l3VpnSvc);
918 //TODO: Site and access deletion needs to be added.
919 }
920
921 /**
922 * Deletes the global VPN from the device model and delete from the device.
923 *
924 * @param l3VpnSvc L3 VPN service
925 */
926 private void deleteGlobalVpn(L3VpnSvc l3VpnSvc) {
927 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
928 //TODO: check for VPN delete deleting interface from store.
929 if (l3VpnSvc == null || l3VpnSvc.vpnServices() == null ||
930 l3VpnSvc.vpnServices().vpnSvc() == null) {
931 for (Map.Entry<String, VpnInstance> vpnMap : insMap.entrySet()) {
932 deleteVpnInstance(vpnMap.getValue(), false);
933 }
934 return;
935 }
936 List<VpnSvc> vpnList = l3VpnSvc.vpnServices().vpnSvc();
937 for (Map.Entry<String, VpnInstance> vpnMap : insMap.entrySet()) {
938 boolean isPresent = isVpnPresent(vpnMap.getKey(), vpnList);
939 if (!isPresent) {
940 deleteVpnInstance(vpnMap.getValue(), false);
941 }
942 }
943 }
944
945 /**
946 * Returns true if the VPN in the distributed map is also present in the
947 * service; false otherwise.
948 *
949 * @param vpnName VPN name from store
950 * @param vpnList VPN list from service
951 * @return true if VPN available; false otherwise
952 */
953 private boolean isVpnPresent(String vpnName, List<VpnSvc> vpnList) {
954 for (VpnSvc svc : vpnList) {
955 if (svc.vpnId().string().equals(vpnName)) {
956 return true;
957 }
958 }
959 return false;
960 }
961
962 /**
963 * Deletes the VPN instance by constructing standard device model of
964 * instances.
965 *
966 * @param instance VPN instance
967 * @param isIntDeleted if interface already removed.
968 */
969 private void deleteVpnInstance(VpnInstance instance, boolean isIntDeleted) {
970 Map<DeviceId, DeviceInfo> devices = instance.devInfo();
janani bd821b182017-03-30 16:34:49 +0530971 if (devices != null) {
972 for (Map.Entry<DeviceId, DeviceInfo> device : devices.entrySet()) {
973 NetworkInstances ins = deleteInstance(instance.vpnName());
974 DeviceInfo dev = device.getValue();
975 if (!isIntDeleted) {
976 remVpnBgp(dev);
977 remInterfaceFromMap(dev);
978 }
979 Map<AccessInfo, InterfaceInfo> intMap =
980 l3VpnStore.getInterfaceInfo();
981 String id = dev.deviceId().toString();
982 ModelObjectData devMod = getVpnDelModObj(intMap, ins, id);
983 ModelObjectData driMod = dev.processDeleteInstance(
984 driverService, devMod);
985 ResourceData resData = modelConverter.createDataNode(driMod);
986 deleteFromStore(resData);
janani b176905a2017-03-28 17:36:18 +0530987 }
janani bd821b182017-03-30 16:34:49 +0530988 l3VpnStore.removeVpnInstance(instance.vpnName());
janani b176905a2017-03-28 17:36:18 +0530989 }
janani bd821b182017-03-30 16:34:49 +0530990 }
991
992 /**
993 * Removes the BGP information for that complete VPN instance.
994 *
995 * @param dev device info
996 */
997 private void remVpnBgp(DeviceInfo dev) {
998 BgpInfo devBgp = dev.bgpInfo();
999 if (devBgp != null) {
1000 l3VpnStore.removeBgpInfo(devBgp);
1001 BgpInfo delInfo = new BgpInfo();
1002 delInfo.vpnName(devBgp.vpnName());
1003 String id = dev.deviceId().toString();
1004 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
1005 BgpDriverInfo driConfig = getVpnBgpDelModObj(bgpMap, id);
1006 ModelObjectData driData = dev.processDeleteBgpInfo(
1007 driverService, delInfo, driConfig);
1008 ResourceData resData = modelConverter.createDataNode(driData);
1009 deleteFromStore(resData);
1010 l3VpnStore.removeBgpInfo(devBgp);
1011 }
janani b176905a2017-03-28 17:36:18 +05301012 }
1013
1014 /**
1015 * Deletes the resource data that is received from the driver, after
1016 * converting from the model object data.
1017 *
1018 * @param resData resource data
1019 */
1020 private void deleteFromStore(ResourceData resData) {
1021 if (resData != null) {
janani bd821b182017-03-30 16:34:49 +05301022 configService.deleteNodeRecursive(resData.resourceId());
janani b176905a2017-03-28 17:36:18 +05301023 }
1024 }
1025
1026 /**
1027 * Removes the interface from the app distributed map, if the driver
1028 * interfaces are already removed from the store.
1029 *
1030 * @param deviceInfo device info
1031 */
1032 private void remInterfaceFromMap(DeviceInfo deviceInfo) {
1033 List<AccessInfo> accesses = deviceInfo.accesses();
janani bd821b182017-03-30 16:34:49 +05301034 if (accesses != null) {
1035 for (AccessInfo access : accesses) {
1036 l3VpnStore.removeInterfaceInfo(access);
1037 }
janani b176905a2017-03-28 17:36:18 +05301038 }
1039 deviceInfo.ifNames(null);
1040 deviceInfo.accesses(null);
1041 }
1042
1043 /**
1044 * Signals that the leadership has changed.
1045 *
1046 * @param isLeader true if this instance is now the leader, otherwise false
1047 */
1048 private void leaderChanged(boolean isLeader) {
1049 log.debug("Leader changed: {}", isLeader);
1050 isElectedLeader = isLeader;
1051 }
1052
1053 /**
janani b35f6cbc2017-03-24 21:56:58 +05301054 * Representation of internal listener, listening for dynamic config event.
1055 */
1056 private class InternalConfigListener implements DynamicConfigListener {
1057
1058 @Override
1059 public boolean isRelevant(DynamicConfigEvent event) {
1060 return isSupported(event);
1061 }
1062
1063 @Override
1064 public void event(DynamicConfigEvent event) {
janani b176905a2017-03-28 17:36:18 +05301065 accumulator.add(event);
janani b35f6cbc2017-03-24 21:56:58 +05301066 }
1067 }
Bharat saraswalcdfda202017-03-24 23:40:50 +05301068
1069 /**
janani b176905a2017-03-28 17:36:18 +05301070 * Accumulates events to allow processing after a desired number of
1071 * events were accumulated.
Bharat saraswalcdfda202017-03-24 23:40:50 +05301072 */
janani b176905a2017-03-28 17:36:18 +05301073 private class InternalEventAccumulator extends
1074 AbstractAccumulator<DynamicConfigEvent> {
1075
1076 /**
1077 * Constructs the event accumulator with timer and event limit.
1078 */
1079 protected InternalEventAccumulator() {
1080 super(new Timer(TIMER), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
1081 }
1082
1083 @Override
1084 public void processItems(List<DynamicConfigEvent> events) {
1085 for (DynamicConfigEvent event : events) {
1086 checkNotNull(event, EVENT_NULL);
1087 Filter filter = new Filter();
1088 DataNode node;
1089 try {
1090 node = configService.readNode(event.subject(), filter);
1091 } catch (FailedException e) {
1092 node = null;
1093 }
1094 switch (event.type()) {
1095 case NODE_ADDED:
1096 processCreateFromStore(event.subject(), node);
1097 break;
1098
1099 case NODE_DELETED:
1100 processDeleteFromStore(node);
1101 break;
1102
1103 default:
1104 log.warn(UNKNOWN_EVENT, event.type());
1105 break;
1106 }
1107 }
1108 }
Bharat saraswalcdfda202017-03-24 23:40:50 +05301109 }
1110
1111 /**
1112 * A listener for leadership events.
1113 */
1114 private class InternalLeadershipListener implements LeadershipEventListener {
1115
1116 @Override
1117 public boolean isRelevant(LeadershipEvent event) {
1118 return event.subject().topic().equals(appId.name());
1119 }
1120
1121 @Override
1122 public void event(LeadershipEvent event) {
1123 switch (event.type()) {
1124 case LEADER_CHANGED:
1125 case LEADER_AND_CANDIDATES_CHANGED:
1126 if (localNodeId.equals(event.subject().leaderNodeId())) {
1127 log.info("Net l3vpn manager gained leadership");
1128 leaderChanged(true);
1129 } else {
1130 log.info("Net l3vpn manager leader changed. New " +
1131 "leader is {}", event.subject()
1132 .leaderNodeId());
1133 leaderChanged(false);
1134 }
1135 default:
1136 break;
1137 }
1138 }
1139 }
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05301140}