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