Remove "response" from yang.
[packetcable.git] / packetcable-policy-server / src / main / java / org / opendaylight / controller / packetcable / provider / PacketcableProvider.java
1 package org.opendaylight.controller.packetcable.provider;
2
3 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
4 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
5 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
6 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
7 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
8 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
9 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
10 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
11 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Ccap;
12 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Qos;
13 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
14 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
15 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
16 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsKey;
17 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
18 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.Apps;
19 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.AppsKey;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.Subs;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.SubsKey;
22 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
23 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesKey;
24 import org.opendaylight.yangtools.concepts.ListenerRegistration;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.pcmm.rcd.IPCMMClient;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import javax.annotation.concurrent.ThreadSafe;
32 import java.net.InetAddress;
33 import java.net.UnknownHostException;
34 import java.util.*;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37
38 /**
39  * Called by ODL framework to start this bundle.
40  *
41  * This class is responsible for processing messages received from ODL's restconf interface.
42  * TODO - Remove some of these state maps and move some of this into the PCMMService
43  */
44 @ThreadSafe
45 public class PacketcableProvider implements BindingAwareProvider, DataChangeListener, AutoCloseable {
46
47     private static final Logger logger = LoggerFactory.getLogger(PacketcableProvider.class);
48
49     // keys to the /restconf/config/packetcable:ccap and /restconf/config/packetcable:qos config datastore
50     public static final InstanceIdentifier<Ccap> ccapIID = InstanceIdentifier.builder(Ccap.class).build();
51     public static final InstanceIdentifier<Qos> qosIID = InstanceIdentifier.builder(Qos.class).build();
52
53     /**
54      * The ODL object used to broker messages throughout the framework
55      */
56     private DataBroker dataBroker;
57
58     private MdsalUtils mdsalUtils;
59
60     private ListenerRegistration<DataChangeListener> ccapDataChangeListenerRegistration;
61     private ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration;
62
63     // TODO - Revisit these maps and remove the ones no longer necessary
64     private final Map<String, Ccaps> ccapMap = new ConcurrentHashMap<>();
65     private final Map<String, Gates> gateMap = new ConcurrentHashMap<>();
66     private final Map<String, String> gateCcapMap = new ConcurrentHashMap<>();
67     private final Map<Subnet, Ccaps> subscriberSubnetsMap = new ConcurrentHashMap<>();
68     private final Map<ServiceClassName, List<Ccaps>> downstreamScnMap = new ConcurrentHashMap<>();
69     private final Map<ServiceClassName, List<Ccaps>> upstreamScnMap = new ConcurrentHashMap<>();
70
71     /**
72      * Holds a PCMMService object for each CCAP being managed.
73      */
74     private final Map<String, PCMMService> pcmmServiceMap = new ConcurrentHashMap<>();
75
76     /**
77      * Constructor
78      */
79     public PacketcableProvider() {
80         logger.info("Starting provider");
81     }
82
83     @Override
84     public void onSessionInitiated(ProviderContext session) {
85         logger.info("Packetcable Session Initiated");
86
87         dataBroker =  session.getSALService(DataBroker.class);
88
89         mdsalUtils = new MdsalUtils(dataBroker);
90
91         ccapDataChangeListenerRegistration =
92                 dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
93                         PacketcableProvider.ccapIID, this, DataBroker.DataChangeScope.SUBTREE );
94
95         qosDataChangeListenerRegistration =
96                 dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
97                         PacketcableProvider.qosIID, this, DataBroker.DataChangeScope.SUBTREE );
98     }
99     /**
100      * Implemented from the AutoCloseable interface.
101      */
102     @Override
103     public void close() throws ExecutionException, InterruptedException {
104         if (ccapDataChangeListenerRegistration != null) {
105             ccapDataChangeListenerRegistration.close();
106         }
107
108         if (qosDataChangeListenerRegistration != null) {
109             qosDataChangeListenerRegistration.close();
110         }
111     }
112
113     public InetAddress getInetAddress(final String subId){
114         try {
115             return InetAddress.getByName(subId);
116         } catch (UnknownHostException e) {
117             logger.error("getInetAddress: {} FAILED: {}", subId, e.getMessage());
118             return null;
119         }
120     }
121
122     private String getIpPrefixStr(final IpPrefix ipPrefix) {
123         final Ipv4Prefix ipv4 = ipPrefix.getIpv4Prefix();
124         if (ipv4 != null) {
125             return ipv4.getValue();
126         } else {
127             return ipPrefix.getIpv6Prefix().getValue();
128         }
129     }
130
131     private void updateCcapMaps(final Ccaps ccap) {
132         // add ccap to the subscriberSubnets map
133         for (final IpPrefix ipPrefix : ccap.getSubscriberSubnets()) {
134             try {
135                 subscriberSubnetsMap.put(Subnet.createInstance(getIpPrefixStr(ipPrefix)), ccap);
136             } catch (UnknownHostException e) {
137                 logger.error("updateSubscriberSubnets: {}:{} FAILED: {}", ipPrefix, ccap, e.getMessage());
138             }
139         }
140         // ccap to upstream SCN map
141         for (final ServiceClassName scn : ccap.getUpstreamScns()) {
142             if (upstreamScnMap.containsKey(scn)) {
143                 upstreamScnMap.get(scn).add(ccap);
144             } else {
145                 final List<Ccaps> ccapList = new ArrayList<>();
146                 ccapList.add(ccap);
147                 upstreamScnMap.put(scn, ccapList);
148             }
149         }
150         // ccap to downstream SCN map
151         for (final ServiceClassName scn : ccap.getDownstreamScns()) {
152             if (downstreamScnMap.containsKey(scn)) {
153                 downstreamScnMap.get(scn).add(ccap);
154             } else {
155                 final List<Ccaps> ccapList = new ArrayList<>();
156                 ccapList.add(ccap);
157                 downstreamScnMap.put(scn, ccapList);
158             }
159         }
160     }
161
162     private void removeCcapFromAllMaps(final Ccaps ccap) {
163         // remove the ccap from all maps
164         // subscriberSubnets map
165         for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
166             if (entry.getValue() == ccap) {
167                 subscriberSubnetsMap.remove(entry.getKey());
168             }
169         }
170         // ccap to upstream SCN map
171         for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : upstreamScnMap.entrySet()) {
172             final List<Ccaps> ccapList = entry.getValue();
173             ccapList.remove(ccap);
174             if (ccapList.isEmpty()) {
175                 upstreamScnMap.remove(entry.getKey());
176             }
177         }
178         // ccap to downstream SCN map
179         for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : downstreamScnMap.entrySet()) {
180             final List<Ccaps> ccapList = entry.getValue();
181             ccapList.remove(ccap);
182             if (ccapList.isEmpty()) {
183                 downstreamScnMap.remove(entry.getKey());
184             }
185         }
186
187         final PCMMService service = pcmmServiceMap.remove(ccap.getCcapId());
188         if (service != null) service.disconect();
189     }
190
191     private Ccaps findCcapForSubscriberId(final InetAddress inetAddr) {
192         Ccaps matchedCcap = null;
193         int longestPrefixLen = -1;
194         for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
195             final Subnet subnet = entry.getKey();
196             if (subnet.isInNet(inetAddr)) {
197                 int prefixLen = subnet.getPrefixLen();
198                 if (prefixLen > longestPrefixLen) {
199                     matchedCcap = entry.getValue();
200                     longestPrefixLen = prefixLen;
201                 }
202             }
203         }
204         return matchedCcap;
205     }
206
207     private ServiceFlowDirection findScnOnCcap(final ServiceClassName scn, final Ccaps ccap) {
208         if (upstreamScnMap.containsKey(scn)) {
209             final List<Ccaps> ccapList = upstreamScnMap.get(scn);
210             if (ccapList.contains(ccap)) {
211                 return ServiceFlowDirection.Us;
212             }
213         } else if (downstreamScnMap.containsKey(scn)) {
214             final List<Ccaps> ccapList = downstreamScnMap.get(scn);
215             if (ccapList.contains(ccap)) {
216                 return ServiceFlowDirection.Ds;
217             }
218         }
219         return null;
220     }
221
222     /**
223      * Implemented from the DataChangeListener interface.
224      */
225
226     private class InstanceData {
227         // CCAP Identity
228         public final Map<InstanceIdentifier<Ccaps>, Ccaps> ccapIidMap = new HashMap<>();
229         // Gate Identity
230         public String subId;
231         public final Map<String, String> gatePathMap = new HashMap<>();
232         public String gatePath;
233         public final Map<InstanceIdentifier<Gates>, Gates> gateIidMap = new HashMap<>();
234         // remove path for either CCAP or Gates
235         public final Set<String> removePathList = new HashSet<>();
236
237         public final Set<InstanceIdentifier<?>> reqCcapIds = new HashSet<>();
238
239         public InstanceData(final Map<InstanceIdentifier<?>, DataObject> thisData) {
240             // only used to parse createdData or updatedData
241             getCcaps(thisData);
242             if (ccapIidMap.isEmpty()) {
243                 getGates(thisData);
244                 if (! gateIidMap.isEmpty()){
245                     gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId");
246                 }
247             }
248         }
249
250         public InstanceData(final Set<InstanceIdentifier<?>> thisData) {
251             // only used to parse the removedData paths
252             for (final InstanceIdentifier<?> removeThis : thisData) {
253                 getGatePathMap(removeThis);
254                 if (gatePathMap.containsKey("ccapId")) {
255                     gatePath = gatePathMap.get("ccapId");
256                     removePathList.add(gatePath);
257                 } else if (gatePathMap.containsKey("gateId")) {
258                     gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId") + "/" + gatePathMap.get("gateId");
259                     removePathList.add(gatePath);
260                 }
261             }
262         }
263         private void getGatePathMap(final InstanceIdentifier<?> thisInstance) {
264             logger.info("onDataChanged().getGatePathMap(): " + thisInstance);
265             try {
266                 final InstanceIdentifier<Ccaps> ccapInstance = thisInstance.firstIdentifierOf(Ccaps.class);
267                 if (ccapInstance != null) {
268                     final CcapsKey ccapKey = InstanceIdentifier.keyOf(ccapInstance);
269                     if (ccapKey != null) {
270                         gatePathMap.put("ccapId", ccapKey.getCcapId());
271                     }
272                 } else {
273                     // get the gate path keys from the InstanceIdentifier Map key set if they are there
274                     final InstanceIdentifier<Apps> appsInstance = thisInstance.firstIdentifierOf(Apps.class);
275                     if (appsInstance != null) {
276                         final AppsKey appKey = InstanceIdentifier.keyOf(appsInstance);
277                         if (appKey != null) {
278                             gatePathMap.put("appId", appKey.getAppId());
279                         }
280                     }
281                     final InstanceIdentifier<Subs> subsInstance = thisInstance.firstIdentifierOf(Subs.class);
282                     if (subsInstance != null) {
283                         final SubsKey subKey = InstanceIdentifier.keyOf(subsInstance);
284                         if (subKey != null) {
285                             subId = subKey.getSubId();
286                             gatePathMap.put("subId", subId);
287                         }
288                     }
289                     final InstanceIdentifier<Gates> gatesInstance = thisInstance.firstIdentifierOf(Gates.class);
290                     if (gatesInstance != null) {
291                         final GatesKey gateKey = InstanceIdentifier.keyOf(gatesInstance);
292                         if (gateKey != null) {
293                             gatePathMap.put("gateId", gateKey.getGateId());
294                         }
295                     }
296                 }
297             } catch (ClassCastException err) {
298                 logger.warn("Unexpected exception", err);
299             }
300         }
301
302         private void getCcaps(final Map<InstanceIdentifier<?>, DataObject> thisData) {
303             logger.info("onDataChanged().getCcaps(): " + thisData);
304             for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
305
306                 if (entry.getKey().getTargetType().equals(Ccaps.class)) {
307                     Ccaps ccaps = ((Ccaps) entry.getValue());
308                     InstanceIdentifier<Ccaps> ccapsIid = InstanceIdentifier.builder(Ccap.class).child(Ccaps.class, new CcapsKey(ccaps.getCcapId())).build();
309                     ccapIidMap.put(ccapsIid, ccaps);
310                 }
311
312                 if (entry.getKey().getTargetType().equals(Connection.class) ||
313                         entry.getKey().getTargetType().equals(Ccaps.class)) {
314                     reqCcapIds.add(entry.getKey());
315                 }
316             }
317         }
318
319         private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
320             logger.info("onDataChanged().getGates(): " + thisData);
321             for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
322                 if (entry.getValue() instanceof Gates) {
323                     final Gates gate = (Gates)entry.getValue();
324
325                     // TODO FIXME - Potential ClassCastException thrown here!!!
326                     final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
327                     getGatePathMap(gateIID);
328                     if (!gateIidMap.containsKey(gateIID)){
329                         gateIidMap.put(gateIID, gate);
330                     }
331                 }
332                 // TODO reconciliate gates
333 //                if (entry.getValue() instanceof Qos) {
334 //                    final Qos qos = (Qos) entry.getValue();
335 //                    if (qos.getApps() != null) {
336 //                        for (Apps apps : qos.getApps()) {
337 //                            if (apps.getSubs() != null) {
338 //                                for (Subs subs : apps.getSubs()) {
339 //                                    if (subs.getGates() != null) {
340 //                                        for (Gates gates : subs.getGates()) {
341 //                                            final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
342 //                                            getGatePathMap(gateIID);
343 //                                            if (!gateIidMap.containsKey(gateIID)){
344 //                                                gateIidMap.put(gateIID, gates);
345 //                                            }
346 //                                        }
347 //                                    }
348 //                                }
349 //                            }
350 //                        }
351 //                    }
352 //                }
353             }
354         }
355     }
356
357     @Override
358     public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
359         logger.info("onDataChanged");
360         // Determine what change action took place by looking at the change object's InstanceIdentifier sets
361         // and validate all instance data
362         if (!change.getCreatedData().isEmpty()) {
363             if (!new ValidateInstanceData(mdsalUtils, change.getCreatedData()).validateYang()) {
364                 // leave now -- a bad yang object has been detected and a response object has been inserted
365                 return;
366             }
367             onCreate(new InstanceData(change.getCreatedData()));
368         } else if (!change.getRemovedPaths().isEmpty()) {
369             onRemove(new InstanceData(change.getRemovedPaths()));
370         } else if (!change.getUpdatedData().isEmpty()) {
371             onUpdate(new InstanceData(change.getUpdatedData()));
372         } else {
373             // we should not be here -- complain bitterly and return
374             logger.error("onDataChanged(): Unknown change action: " + change);
375         }
376     }
377
378     private void onCreate(final InstanceData thisData) {
379         logger.info("onCreate(): " + thisData);
380
381         // get the CCAP parameters
382         String message;
383         if (! thisData.reqCcapIds.isEmpty()) {
384             for (Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : thisData.ccapIidMap.entrySet()) {
385                 final Ccaps thisCcap = entry.getValue();
386                 // get the CCAP node identity from the Instance Data
387                 final String ccapId = thisCcap.getCcapId();
388
389                 if (pcmmServiceMap.get(thisCcap.getCcapId()) == null) {
390                     final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, thisCcap);
391                     // TODO - may want to use the AMID but for the client type but probably not???
392 /*
393                             final PCMMService pcmmService = new PCMMService(
394                                     thisCcap.getAmId().getAmType().shortValue(), thisCcap);
395 */
396                     message = pcmmService.addCcap();
397                     if (message.contains("200 OK")) {
398                         pcmmServiceMap.put(thisCcap.getCcapId(), pcmmService);
399                         ccapMap.put(ccapId, thisCcap);
400                         updateCcapMaps(thisCcap);
401                         logger.info("Created CCAP: {}/{} : {}", thisData.gatePath, thisCcap, message);
402                         logger.info("Created CCAP: {} : {}", thisData.gatePath, message);
403                     } else {
404                         logger.error("Create CCAP Failed: {} : {}", thisData.gatePath, message);
405                         for (final InstanceIdentifier<?> instId : thisData.reqCcapIds) {
406                             mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, instId);
407                         }
408                         ccapMap.remove(ccapId);
409                     }
410                 } else {
411                     logger.error("Already monitoring CCAP - " + thisCcap);
412                     break;
413                 }
414             }
415         } else {
416             // get the PCMM gate parameters from the ccapId/appId/subId/gateId path in the Maps entry (if new gate)
417             for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : thisData.gateIidMap.entrySet()) {
418                 message = null;
419                 final Gates gate = entry.getValue();
420                 final String gateId = gate.getGateId();
421                 final String gatePathStr = thisData.gatePath + "/" + gateId ;
422                 final InetAddress subId = getInetAddress(thisData.subId);
423                 if (subId != null) {
424                     final Ccaps thisCcap = findCcapForSubscriberId(subId);
425                     if (thisCcap != null) {
426                         final String ccapId = thisCcap.getCcapId();
427                         // verify SCN exists on CCAP and force gateSpec.Direction to align with SCN direction
428                         final ServiceClassName scn = gate.getTrafficProfile().getServiceClassName();
429                         if (scn != null) {
430                             final ServiceFlowDirection scnDir = findScnOnCcap(scn, thisCcap);
431                             if (scnDir != null) {
432                                 if (pcmmServiceMap.get(thisCcap.getCcapId()) != null) {
433                                     message = pcmmServiceMap.get(thisCcap.getCcapId()).sendGateSet(gatePathStr, subId, gate, scnDir);
434                                     gateMap.put(gatePathStr, gate);
435                                     gateCcapMap.put(gatePathStr, thisCcap.getCcapId());
436
437                                     if (message.contains("200 OK")) {
438                                         logger.info("Created QoS gate {} for {}/{}/{} - {}",
439                                                 gateId, ccapId, gatePathStr, gate, message);
440                                         logger.info("Created QoS gate {} for {}/{} - {}",
441                                                 gateId, ccapId, gatePathStr, message);
442                                     } else {
443                                         logger.info("Unable to create QoS gate {} for {}/{}/{} - {}",
444                                                 gateId, ccapId, gatePathStr, gate, message);
445                                         logger.error("Unable to create QoS gate {} for {}/{} - {}",
446                                                 gateId, ccapId, gatePathStr, message);
447                                     }
448                                 } else {
449                                     logger.error("Unable to locate PCMM Service for CCAP - " + thisCcap);
450                                     break;
451                                 }
452                             } else {
453                                 logger.error("PCMMService: sendGateSet(): SCN {} not found on CCAP {} for {}/{}",
454                                         scn.getValue(), thisCcap, gatePathStr, gate);
455                                 message = String.format("404 Not Found - SCN %s not found on CCAP %s for %s",
456                                         scn.getValue(), thisCcap.getCcapId(), gatePathStr);
457                             }
458                         }
459                     } else {
460                         final String subIdStr = thisData.subId;
461                         message = String.format("404 Not Found - no CCAP found for subscriber %s in %s",
462                                 subIdStr, gatePathStr);
463                         logger.info("Create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}/{}",
464                                 gateId, subIdStr, gatePathStr, gate);
465                         logger.error("Create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}",
466                                 gateId, subIdStr, gatePathStr);
467                     }
468                 } else {
469                     final String subIdStr = thisData.subId;
470                     message = String.format("400 Bad Request - subId must be a valid IP address for subscriber %s in %s",
471                             subIdStr, gatePathStr);
472                     logger.info("Create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}/{}",
473                             gateId, subIdStr, gatePathStr, gate);
474                     logger.error("Create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}",
475                             gateId, subIdStr, gatePathStr);
476                 }
477                 if (!message.contains("200 OK")) {
478                     mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, entry.getKey());
479                 }
480             }
481         }
482     }
483
484     private void onRemove(final InstanceData thisData) {
485         logger.info("onRemove(): " + thisData);
486         for (final String gatePathStr: thisData.removePathList) {
487             if (gateMap.containsKey(gatePathStr)) {
488                 final Gates thisGate = gateMap.remove(gatePathStr);
489                 final String gateId = thisGate.getGateId();
490                 final String ccapId = gateCcapMap.remove(gatePathStr);
491                 final Ccaps thisCcap = ccapMap.get(ccapId);
492                 final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId());
493                 if (service != null) {
494                     service.sendGateDelete(gatePathStr);
495                     logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr, thisGate);
496                     logger.info("onDataChanged(): removed QoS gate {} for {}/{}: ", gateId, ccapId, gatePathStr);
497                 } else
498                     logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
499                             + thisCcap);
500             }
501         }
502         for (final String ccapIdStr: thisData.removePathList) {
503             if (ccapMap.containsKey(ccapIdStr)) {
504                 final Ccaps thisCcap = ccapMap.remove(ccapIdStr);
505                 removeCcapFromAllMaps(thisCcap);
506             }
507         }
508     }
509
510     private void onUpdate(final InstanceData oldData) {
511         logger.info("onUpdate(): " + oldData);
512         // update operation not allowed -- restore the original config object and complain
513         if (! oldData.ccapIidMap.isEmpty()) {
514             for (final Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : oldData.ccapIidMap.entrySet()) {
515                 final Ccaps ccap = entry.getValue();
516                 final String ccapId = ccap.getCcapId();
517                 // restores the original data - although I don't think this is what is done here! I think the update data is put into the DS/config
518                 mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, entry.getKey(), ccap);
519                 logger.error("onDataChanged(): CCAP update not permitted {}/{}", ccapId, ccap);
520             }
521         } else {
522             for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : oldData.gateIidMap.entrySet()) {
523                 final Gates gate = entry.getValue();
524                 final String gatePathStr = oldData.gatePath + "/" + gate.getGateId() ;
525              // restores the original data - although I don't think this is what is done here! I think the update data is put into the DS/config
526                 mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, entry.getKey(), gate);
527                 logger.error("onDataChanged(): QoS Gate update not permitted: {}/{}", gatePathStr, gate);
528             }
529         }
530     }
531 }