2 * Copyright (c) 2015 CableLabs and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.packetcable.provider;
11 import static com.google.common.base.Preconditions.checkNotNull;
13 import com.google.common.base.Optional;
14 import com.google.common.collect.Maps;
15 import com.google.common.collect.Sets;
16 import com.google.common.util.concurrent.CheckedFuture;
17 import com.google.common.util.concurrent.Futures;
19 import java.net.InetAddress;
20 import java.net.UnknownHostException;
21 import java.text.DateFormat;
22 import java.text.SimpleDateFormat;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.List;
28 import java.util.Objects;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.Executor;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.Future;
36 import javax.annotation.Nonnull;
37 import javax.annotation.concurrent.ThreadSafe;
39 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
40 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
41 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
44 import org.opendaylight.controller.packetcable.provider.validation.DataValidator;
45 import org.opendaylight.controller.packetcable.provider.validation.ValidationException;
46 import org.opendaylight.controller.packetcable.provider.validation.Validator;
47 import org.opendaylight.controller.packetcable.provider.validation.impl.CcapsValidatorProviderFactory;
48 import org.opendaylight.controller.packetcable.provider.validation.impl.QosValidatorProviderFactory;
49 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
50 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
51 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.DateAndTime;
55 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.AppContext;
56 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapContext;
57 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionInput;
58 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionOutput;
59 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionOutputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionInput;
61 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionOutput;
62 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionOutputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.Ccaps;
64 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.PacketcableService;
65 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.Qos;
66 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesInput;
67 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesOutput;
68 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesOutputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ServiceClassName;
70 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ServiceFlowDirection;
71 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.attributes.ConnectionBuilder;
72 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccaps.Ccap;
73 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccaps.CcapBuilder;
74 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.Apps;
75 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.App;
76 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.AppBuilder;
77 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.AppKey;
78 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.Subscribers;
79 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.SubscribersBuilder;
80 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.Subscriber;
81 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.SubscriberBuilder;
82 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.SubscriberKey;
83 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.Gates;
84 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.GatesBuilder;
85 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.Gate;
86 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateBuilder;
87 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateKey;
88 import org.opendaylight.yangtools.concepts.ListenerRegistration;
89 import org.opendaylight.yangtools.yang.binding.DataObject;
90 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
91 import org.opendaylight.yangtools.yang.common.RpcResult;
92 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
93 import org.pcmm.rcd.IPCMMClient;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
98 * Called by ODL framework to start this bundle.
100 * This class is responsible for processing messages received from ODL's restconf interface.
101 * TODO - Remove some of these state maps and move some of this into the PCMMService
102 * TODO Don't implement PacketcableService, move that into an inner class
105 public class PacketcableProvider implements BindingAwareProvider, AutoCloseable, PacketcableService {
107 private static final Logger logger = LoggerFactory.getLogger(PacketcableProvider.class);
109 // keys to the /restconf/config/packetcable:ccaps and /restconf/config/packetcable:qos config datastore
110 private static final InstanceIdentifier<Ccaps> ccapsIID = InstanceIdentifier.builder(Ccaps.class).build();
111 private static final InstanceIdentifier<Qos> qosIID = InstanceIdentifier.builder(Qos.class).build();
113 // TODO - Revisit these maps and remove the ones no longer necessary
114 private final Map<String, Ccap> ccapMap = new ConcurrentHashMap<>();
115 private final Map<String, Gate> gateMap = new ConcurrentHashMap<>();
116 private final Map<String, String> gateCcapMap = new ConcurrentHashMap<>();
117 private final Map<Subnet, Ccap> subscriberSubnetsMap = new ConcurrentHashMap<>();
118 private final Map<ServiceClassName, List<Ccap>> downstreamScnMap = new ConcurrentHashMap<>();
119 private final Map<ServiceClassName, List<Ccap>> upstreamScnMap = new ConcurrentHashMap<>();
121 private final Executor executor = Executors.newSingleThreadExecutor();
124 * Holds a PCMMService object for each CCAP being managed.
126 private final Map<String, PCMMService> pcmmServiceMap = new ConcurrentHashMap<>();
129 * The ODL object used to broker messages throughout the framework
131 private DataBroker dataBroker;
132 private MdsalUtils mdsalUtils;
134 //Routed RPC Registration
135 private RoutedRpcRegistration<PacketcableService> rpcRegistration;
137 // Data change listeners/registrations
138 private final CcapsDataChangeListener ccapsDataChangeListener = new CcapsDataChangeListener();
139 private final QosDataChangeListener qosDataChangeListener = new QosDataChangeListener();
141 private ListenerRegistration<DataChangeListener> ccapsDataChangeListenerRegistration;
142 private ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration;
147 public PacketcableProvider() {
148 logger.info("Starting provider");
152 public void onSessionInitiated(ProviderContext session) {
153 logger.info("Packetcable Session Initiated");
154 logger.info("logging levels: error={}, warn={}, info={}, debug={}, trace={}", logger.isErrorEnabled(),
155 logger.isWarnEnabled(), logger.isInfoEnabled(), logger.isDebugEnabled(), logger.isTraceEnabled());
157 dataBroker = session.getSALService(DataBroker.class);
159 mdsalUtils = new MdsalUtils(dataBroker);
161 ccapsDataChangeListenerRegistration =
162 dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, ccapsIID.child(Ccap.class),
163 ccapsDataChangeListener, DataBroker.DataChangeScope.SUBTREE);
165 qosDataChangeListenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
166 PacketcableProvider.qosIID.child(Apps.class).child(App.class), qosDataChangeListener,
167 DataBroker.DataChangeScope.SUBTREE);
169 rpcRegistration = session.addRoutedRpcImplementation(PacketcableService.class, this);
170 logger.info("onSessionInitiated().rpcRgistration: {}", rpcRegistration);
175 * Implemented from the AutoCloseable interface.
178 public void close() throws ExecutionException, InterruptedException {
179 if (ccapsDataChangeListenerRegistration != null) {
180 ccapsDataChangeListenerRegistration.close();
183 if (qosDataChangeListenerRegistration != null) {
184 qosDataChangeListenerRegistration.close();
188 private void updateCcapMaps(final Ccap ccap) {
189 // add ccap to the subscriberSubnets map
190 for (final IpPrefix ipPrefix : ccap.getSubscriberSubnets()) {
192 subscriberSubnetsMap.put(Subnet.createInstance(getIpPrefixStr(ipPrefix)), ccap);
193 } catch (UnknownHostException e) {
194 logger.error("updateSubscriberSubnets: {}:{} FAILED: {}", ipPrefix, ccap, e.getMessage());
197 // ccap to upstream SCN map
198 for (final ServiceClassName scn : ccap.getUpstreamScns()) {
199 if (upstreamScnMap.containsKey(scn)) {
200 upstreamScnMap.get(scn).add(ccap);
202 final List<Ccap> ccapList = new ArrayList<>();
204 upstreamScnMap.put(scn, ccapList);
207 // ccap to downstream SCN map
208 for (final ServiceClassName scn : ccap.getDownstreamScns()) {
209 if (downstreamScnMap.containsKey(scn)) {
210 downstreamScnMap.get(scn).add(ccap);
212 final List<Ccap> ccapList = new ArrayList<>();
214 downstreamScnMap.put(scn, ccapList);
219 private String getIpPrefixStr(final IpPrefix ipPrefix) {
220 final Ipv4Prefix ipv4 = ipPrefix.getIpv4Prefix();
222 return ipv4.getValue();
224 return ipPrefix.getIpv6Prefix().getValue();
228 public InetAddress getInetAddress(final String subId) {
230 return InetAddress.getByName(subId);
231 } catch (UnknownHostException e) {
232 logger.error("getInetAddress: {} FAILED: {}", subId, e.getMessage());
237 private Ccap findCcapForSubscriberId(final InetAddress inetAddr) {
238 // TODO replace this with a loading cache, https://github.com/google/guava/wiki/CachesExplained
239 Ccap matchedCcap = null;
240 int longestPrefixLen = -1;
241 for (final Map.Entry<Subnet, Ccap> entry : subscriberSubnetsMap.entrySet()) {
242 final Subnet subnet = entry.getKey();
243 if (subnet.isInNet(inetAddr)) {
244 int prefixLen = subnet.getPrefixLen();
245 if (prefixLen > longestPrefixLen) {
246 matchedCcap = entry.getValue();
247 longestPrefixLen = prefixLen;
254 private ServiceFlowDirection findScnOnCcap(final ServiceClassName scn, final Ccap ccap) {
258 if (upstreamScnMap.containsKey(scn)) {
259 final List<Ccap> ccapList = upstreamScnMap.get(scn);
260 if (ccapList.contains(ccap)) {
261 return ServiceFlowDirection.Us;
263 } else if (downstreamScnMap.containsKey(scn)) {
264 final List<Ccap> ccapList = downstreamScnMap.get(scn);
265 if (ccapList.contains(ccap)) {
266 return ServiceFlowDirection.Ds;
272 private void removeCcapFromAllMaps(final Ccap ccap) {
273 // remove the ccap from all maps
274 // subscriberSubnets map
275 for (final Map.Entry<Subnet, Ccap> entry : subscriberSubnetsMap.entrySet()) {
276 if (entry.getValue() == ccap) {
277 subscriberSubnetsMap.remove(entry.getKey());
280 // ccap to upstream SCN map
281 for (final Map.Entry<ServiceClassName, List<Ccap>> entry : upstreamScnMap.entrySet()) {
282 final List<Ccap> ccapList = entry.getValue();
283 ccapList.remove(ccap);
284 if (ccapList.isEmpty()) {
285 upstreamScnMap.remove(entry.getKey());
288 // ccap to downstream SCN map
289 for (final Map.Entry<ServiceClassName, List<Ccap>> entry : downstreamScnMap.entrySet()) {
290 final List<Ccap> ccapList = entry.getValue();
291 ccapList.remove(ccap);
292 if (ccapList.isEmpty()) {
293 downstreamScnMap.remove(entry.getKey());
297 final PCMMService service = pcmmServiceMap.remove(ccap.getCcapId());
298 if (service != null) {
303 // ValidationException does not need to be thrown again
304 @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
305 private <T extends DataObject> void saveErrors(@Nonnull Map<InstanceIdentifier<T>, ValidationException> errorMap,
306 @Nonnull Map<InstanceIdentifier<T>, T> dataMap) {
308 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
311 for (InstanceIdentifier<T> iid : errorMap.keySet()) {
313 final ValidationException exception = errorMap.get(iid);
314 final T badData = dataMap.get(iid);
316 if (!badData.getImplementedInterface().isAssignableFrom(iid.getTargetType())) {
317 // InstanceIdentifier<T> does not have the same type as the DataObject
318 logger.error("Bad InstanceIdentifier to DataObject mapping, {} : {}", iid, badData);
322 if (badData instanceof Ccap) {
323 final Ccap ccap = (Ccap) badData;
325 final Ccap opperationalCcap =
326 new CcapBuilder().setCcapId(ccap.getCcapId()).setError(exception.getErrorMessages()).build();
329 // type match between iid and badData is done at start of loop
330 @SuppressWarnings("unchecked") final InstanceIdentifier<Ccap> ccapIID = (InstanceIdentifier<Ccap>) iid;
331 writeTransaction.put(LogicalDatastoreType.OPERATIONAL, ccapIID, opperationalCcap);
332 } else if (badData instanceof Gate) {
333 final Gate gate = (Gate) badData;
335 final Gate operationalGate =
336 new GateBuilder().setGateId(gate.getGateId()).setError(exception.getErrorMessages()).build();
338 final Gates operationalGates =
339 new GatesBuilder().setGate(Collections.singletonList(operationalGate)).build();
341 final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(iid.firstIdentifierOf(Subscriber.class));
342 final Subscriber operationalSubscriber =
343 new SubscriberBuilder().setSubscriberId(subscriberKey.getSubscriberId())
344 .setGates(operationalGates)
347 final Subscribers operationalSubscribers =
348 new SubscribersBuilder().setSubscriber(Collections.singletonList(operationalSubscriber))
351 final InstanceIdentifier<App> appIID = iid.firstIdentifierOf(App.class);
352 final AppKey appKey = InstanceIdentifier.keyOf(appIID);
353 final App operationalApp =
354 new AppBuilder().setAppId(appKey.getAppId()).setSubscribers(operationalSubscribers).build();
357 writeTransaction.put(LogicalDatastoreType.OPERATIONAL, appIID, operationalApp);
359 // If you get here a developer forgot to add a type above
360 logger.error("Unexpected type requested for error saving: {}", badData);
361 throw new IllegalStateException("Unsupported type for error saving");
367 CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
371 } catch (TransactionCommitFailedException e) {
372 logger.error("Failed to write errors to operational datastore", e);
377 * Removes Ccaps if all Ccap instances are removed
379 private class CcapsCleaner extends AbstractCleaner<Ccaps> {
381 public CcapsCleaner(final InstanceIdentifier<?> removedIID) {
382 super(removedIID, Ccaps.class, LogicalDatastoreType.OPERATIONAL);
386 protected boolean shouldClean(final Ccaps ccaps) {
387 return ccaps.getCcap().isEmpty();
393 * Removes Subscriber if all Gate instances are removed
395 private class SubscriberCleaner extends AbstractCleaner<Subscriber> {
397 public SubscriberCleaner(InstanceIdentifier<Gate> removedGateIID) {
398 super(removedGateIID, Subscriber.class, LogicalDatastoreType.OPERATIONAL);
402 protected boolean shouldClean(final Subscriber subscriber) {
403 return subscriber.getGates().getGate().isEmpty();
407 protected void postRemove(InstanceIdentifier<Subscriber> subscriberIID) {
408 executor.execute(new AppCleaner(subscriberIID));
414 * Removes App if all Subscribers are removed.
416 private class AppCleaner extends AbstractCleaner<App> {
418 public AppCleaner(InstanceIdentifier<Subscriber> removedSubscriberIID) {
419 super(removedSubscriberIID, App.class, LogicalDatastoreType.OPERATIONAL);
423 boolean shouldClean(final App app) {
424 return app.getSubscribers().getSubscriber().isEmpty();
428 void postRemove(final InstanceIdentifier<App> appIID) {
429 //unregister app rpc path
430 logger.info("Un-Registering App Routed RPC Path...");
431 rpcRegistration.unregisterPath(AppContext.class, appIID);
432 executor.execute(new AppsCleaner(appIID));
438 * Removes Apps if all App instances are removed.
440 private class AppsCleaner extends AbstractCleaner<Apps> {
442 public AppsCleaner(InstanceIdentifier<App> removedAppIID) {
443 super(removedAppIID, Apps.class, LogicalDatastoreType.OPERATIONAL);
447 protected boolean shouldClean(final Apps apps) {
448 return apps.getApp().isEmpty();
454 * Helper class to do the heavy lifting in removing object. Lets subclasses decide with
455 * {@link #shouldClean(DataObject)}. <br>
457 * Subclasses can react after an instance is removed by overriding {@link #postRemove(InstanceIdentifier)}
460 * The type that will be removed
462 private abstract class AbstractCleaner<T extends DataObject> implements Runnable {
463 final InstanceIdentifier<?> removedIID;
464 final Class<T> tClass;
465 final LogicalDatastoreType datastoreType;
467 public AbstractCleaner(InstanceIdentifier<?> removedIID, Class<T> tClass, LogicalDatastoreType datastoreType) {
468 this.removedIID = checkNotNull(removedIID);
469 this.tClass = checkNotNull(tClass);
470 this.datastoreType = checkNotNull(datastoreType);
475 InstanceIdentifier<T> tIID = removedIID.firstIdentifierOf(tClass);
477 Optional<T> optional = mdsalUtils.read(datastoreType, tIID);
478 if (optional.isPresent()) {
480 if (shouldClean(optional.get())) {
481 if (mdsalUtils.delete(datastoreType, tIID)) {
490 logger.error("Expected to find InstanceIdentifier<{}> but was not found: {}", tClass.getSimpleName(),
496 * If returns true the object will be removed from the datastore
499 * The object that might be removed.
500 * @return true if it should be removed.
502 abstract boolean shouldClean(final T object);
505 * Called after an instance is removed.
508 * the InstanceIdentifier of the removed object
510 void postRemove(InstanceIdentifier<T> tIID) {
514 void removeFailed(InstanceIdentifier<T> tIID) {
515 logger.error("Failed to remove {}", tIID);
521 * Listener for the packetcable:ccaps tree
523 private class CcapsDataChangeListener extends AbstractDataChangeListener<Ccap> {
525 private final DataValidator ccapsDataValidator = new DataValidator(new CcapsValidatorProviderFactory().build());
527 private final Set<InstanceIdentifier<Ccap>> updateQueue = Sets.newConcurrentHashSet();
529 public CcapsDataChangeListener() {
534 protected void handleCreatedData(final Map<InstanceIdentifier<Ccap>, Ccap> createdCcaps) {
535 if (createdCcaps.isEmpty()) {
539 final Map<InstanceIdentifier<Ccap>, ValidationException> errorMap =
540 ccapsDataValidator.validateOneType(createdCcaps, Validator.Extent.NODE_AND_SUBTREE);
542 // validate all new objects an update operational datastore
543 if (!errorMap.isEmpty()) {
544 // bad data write errors to operational datastore
545 saveErrors(errorMap, createdCcaps);
548 if (createdCcaps.size() > errorMap.size()) {
549 final Map<InstanceIdentifier<Ccap>, Ccap> goodData =
550 Maps.newHashMapWithExpectedSize(createdCcaps.size() - errorMap.size());
551 for (InstanceIdentifier<Ccap> iid : createdCcaps.keySet()) {
552 if (!errorMap.containsKey(iid)) {
553 goodData.put(iid, createdCcaps.get(iid));
556 addNewCcaps(goodData);
560 private void addNewCcaps(final Map<InstanceIdentifier<Ccap>, Ccap> goodData) {
561 for (InstanceIdentifier<Ccap> iid : goodData.keySet()) {
562 final Ccap ccap = goodData.get(iid);
565 if (pcmmServiceMap.containsKey(ccap.getCcapId())) {
566 logger.error("Already monitoring CCAP - " + ccap);
569 final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
570 // TODO - may want to use the AMID but for the client type but probably not???
572 final PCMMService pcmmService = new PCMMService(
573 thisCcap.getAmId().getAmType().shortValue(), thisCcap);
575 ConnectionBuilder connectionBuilder = new ConnectionBuilder();
576 String message = pcmmService.addCcap();
577 if (message.contains("200 OK")) {
578 pcmmServiceMap.put(ccap.getCcapId(), pcmmService);
579 ccapMap.put(ccap.getCcapId(), ccap);
580 updateCcapMaps(ccap);
581 logger.info("Created CCAP: {}/{} : {}", iid, ccap, message);
582 logger.info("Created CCAP: {} : {}", iid, message);
584 connectionBuilder.setConnected(true).setError(Collections.<String>emptyList());
586 logger.error("Create CCAP Failed: {} : {}", iid, message);
588 connectionBuilder.setConnected(false).setError(Collections.singletonList(message));
592 logger.info("Registering CCAP Routed RPC Path...");
593 rpcRegistration.registerPath(CcapContext.class, iid);
595 Optional<Ccap> optionalCcap = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
597 final CcapBuilder responseCcapBuilder;
598 if (optionalCcap.isPresent()) {
599 responseCcapBuilder = new CcapBuilder(optionalCcap.get());
601 responseCcapBuilder = new CcapBuilder();
602 responseCcapBuilder.setCcapId(ccap.getCcapId());
605 responseCcapBuilder.setConnection(connectionBuilder.build());
607 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, iid, responseCcapBuilder.build());
613 protected void handleUpdatedData(final Map<InstanceIdentifier<Ccap>, Ccap> updatedCcaps,
614 final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
616 // TODO actually support updates
618 // update operation not allowed -- restore the original config object and complain
619 for (final Map.Entry<InstanceIdentifier<Ccap>, Ccap> entry : updatedCcaps.entrySet()) {
620 if (!originalCcaps.containsKey(entry.getKey())) {
621 logger.error("No original data found for supposedly updated data: {}", entry.getValue());
625 // If this notification is coming from our modification ignore it.
626 if (updateQueue.contains(entry.getKey())) {
627 updateQueue.remove(entry.getKey());
631 final Ccap originalCcap = originalCcaps.get(entry.getKey());
632 //final Ccap updatedCcap = entry.getValue();
635 logger.info("Registering CCAP Routed RPC Path...");
636 rpcRegistration.registerPath(CcapContext.class, entry.getKey());
638 // restore the original data
639 updateQueue.add(entry.getKey());
640 mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalCcap);
641 logger.error("CCAP update not permitted {}", entry.getKey());
646 protected void handleRemovedData(final Set<InstanceIdentifier<Ccap>> removedCcapPaths,
647 final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
649 for (InstanceIdentifier<Ccap> iid : removedCcapPaths) {
650 final Ccap nukedCcap = originalCcaps.get(iid);
651 removeCcapFromAllMaps(nukedCcap);
653 //unregister ccap rpc path
654 logger.info("Un-Registering CCAP Routed RPC Path...");
655 rpcRegistration.unregisterPath(CcapContext.class, iid);
657 mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, iid);
659 // clean up ccaps level if it is now empty
660 executor.execute(new CcapsCleaner(iid));
667 private class QosDataChangeListener extends AbstractDataChangeListener<Gate> {
669 private final DataValidator qosDataValidator = new DataValidator(new QosValidatorProviderFactory().build());
670 private final Set<InstanceIdentifier<Gate>> updateQueue = Sets.newConcurrentHashSet();
672 public QosDataChangeListener() {
677 protected void handleCreatedData(final Map<InstanceIdentifier<Gate>, Gate> createdData) {
679 final Map<InstanceIdentifier<Gate>, ValidationException> errorMap =
680 qosDataValidator.validateOneType(createdData, Validator.Extent.NODE_AND_SUBTREE);
682 // validate all new objects an update operational datastore
683 if (!errorMap.isEmpty()) {
684 // bad data write errors to operational datastore
685 saveErrors(errorMap, createdData);
688 if (createdData.size() > errorMap.size()) {
689 final Map<InstanceIdentifier<Gate>, Gate> goodData =
690 Maps.newHashMapWithExpectedSize(createdData.size() - errorMap.size());
691 for (InstanceIdentifier<Gate> iid : createdData.keySet()) {
692 if (!errorMap.containsKey(iid)) {
693 goodData.put(iid, createdData.get(iid));
696 addNewGates(goodData);
701 private void addNewGates(final Map<InstanceIdentifier<Gate>, Gate> createdGates) {
703 for (InstanceIdentifier<Gate> gateIID : createdGates.keySet()) {
704 final Gate newGate = createdGates.get(gateIID);
706 final String newGatePathStr = makeGatePathString(gateIID);
708 // if a new app comes along add RPC registration
709 final InstanceIdentifier<App> appIID = gateIID.firstIdentifierOf(App.class);
710 // TBD verify if App ID exists first
712 //register appID RPC path
713 logger.info("Registering App Routed RPC Path...");
714 rpcRegistration.registerPath(AppContext.class, appIID);
716 final InstanceIdentifier<Subscriber> subscriberIID = gateIID.firstIdentifierOf(Subscriber.class);
717 final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID);
718 final InetAddress subscriberAddr = getInetAddress(subscriberKey.getSubscriberId());
719 if (subscriberAddr == null) {
720 final String msg = String.format("subscriberId must be a valid ipaddress: %s",
721 subscriberKey.getSubscriberId());
723 saveGateError(gateIID, newGatePathStr, msg);
727 final Ccap ccap = findCcapForSubscriberId(subscriberAddr);
729 final String msg = String.format("Unable to find Ccap for subscriber %s: @ %s",
730 subscriberKey.getSubscriberId(), newGatePathStr);
732 saveGateError(gateIID, newGatePathStr, msg);
736 final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName();
737 final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap);
738 if (scnDirection == null) {
740 String.format("SCN %s not found on CCAP %s for %s", scn, ccap.getCcapId(), newGatePathStr);
742 saveGateError(gateIID, newGatePathStr, msg);
746 final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId());
747 if (pcmmService == null) {
749 String.format("Unable to locate PCMM Service for CCAP: %s ; with subscriber: %s", ccap,
750 subscriberKey.getSubscriberId());
752 saveGateError(gateIID, newGatePathStr, msg);
756 PCMMService.GateSendStatus status =
757 pcmmService.sendGateSet(newGatePathStr, subscriberAddr, newGate, scnDirection);
758 if (status.didSucceed()) {
759 gateMap.put(newGatePathStr, newGate);
760 gateCcapMap.put(newGatePathStr, ccap.getCcapId());
762 final GateBuilder gateBuilder = new GateBuilder();
763 gateBuilder.setGateId(newGate.getGateId())
764 .setGatePath(newGatePathStr)
765 .setCcapId(ccap.getCcapId())
766 .setCopsGateId(status.getCopsGateId())
767 .setCopsGateState("")
768 .setTimestamp(getNowTimeStamp())
769 .setCopsGateTimeInfo("")
770 .setCopsGateUsageInfo("")
771 .setTimestamp(getNowTimeStamp());
773 if (!status.didSucceed()) {
774 gateBuilder.setError(Collections.singletonList(status.getMessage()));
776 PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr);
778 if (infoStatus.didSucceed()) {
779 gateBuilder.setCopsGateState(
780 infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason())
781 .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo())
782 .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo());
784 List<String> errors = new ArrayList<>(2);
786 // Keep GateSetErrors
787 if (gateBuilder.getError() != null) {
788 errors.addAll(gateBuilder.getError());
791 errors.add(infoStatus.getMessage());
792 gateBuilder.setError(errors);
797 Gate operationalGate = gateBuilder.build();
799 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate);
805 private void saveGateError(@Nonnull final InstanceIdentifier<Gate> gateIID, @Nonnull final String gatePathStr,
806 @Nonnull final String error) {
807 checkNotNull(gateIID);
810 final GateBuilder gateBuilder = new GateBuilder();
811 gateBuilder.setGateId(InstanceIdentifier.keyOf(gateIID).getGateId())
812 .setGatePath(gatePathStr)
814 .setCopsGateState("N/A");
816 gateBuilder.setError(Collections.singletonList(error));
818 Gate operationalGate = gateBuilder.build();
820 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate);
824 protected void handleUpdatedData(final Map<InstanceIdentifier<Gate>, Gate> updatedData,
825 final Map<InstanceIdentifier<Gate>, Gate> originalData) {
826 // TODO actually support updates
828 // update operation not allowed -- restore the original config object and complain
829 for (final Map.Entry<InstanceIdentifier<Gate>, Gate> entry : updatedData.entrySet()) {
830 if (!originalData.containsKey(entry.getKey())) {
831 logger.error("No original data found for supposedly updated data: {}", entry.getValue());
835 // If this notification is coming from our modification ignore it.
836 if (updateQueue.contains(entry.getKey())) {
837 updateQueue.remove(entry.getKey());
841 final Gate originalGate = originalData.get(entry.getKey());
843 // restores the original data
844 updateQueue.add(entry.getKey());
845 mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, entry.getKey(), originalGate);
846 logger.error("Update not permitted {}", entry.getKey());
854 protected void handleRemovedData(final Set<InstanceIdentifier<Gate>> removedPaths,
855 final Map<InstanceIdentifier<Gate>, Gate> originalData) {
857 for (final InstanceIdentifier<Gate> removedGateIID : removedPaths) {
859 mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, removedGateIID);
861 executor.execute(new SubscriberCleaner(removedGateIID));
863 final String gatePathStr = makeGatePathString(removedGateIID);
865 if (gateMap.containsKey(gatePathStr)) {
866 final Gate thisGate = gateMap.remove(gatePathStr);
867 final String gateId = thisGate.getGateId();
868 final String ccapId = gateCcapMap.remove(gatePathStr);
869 final Ccap thisCcap = ccapMap.get(ccapId);
870 final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId());
871 if (service != null) {
872 service.sendGateDelete(gatePathStr);
873 logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,
876 logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
886 private String makeGatePathString(InstanceIdentifier<Gate> iid) {
887 final InstanceIdentifier<App> appIID = iid.firstIdentifierOf(App.class);
888 final AppKey appKey = InstanceIdentifier.keyOf(appIID);
890 final InstanceIdentifier<Subscriber> subscriberIID = iid.firstIdentifierOf(Subscriber.class);
891 final SubscriberKey subscriberKey = InstanceIdentifier.keyOf(subscriberIID);
893 final GateKey gateKey = InstanceIdentifier.keyOf(iid);
895 return appKey.getAppId() + "/" + subscriberKey.getSubscriberId() + "/" + gateKey.getGateId();
901 public Future<RpcResult<CcapSetConnectionOutput>> ccapSetConnection(CcapSetConnectionInput input) {
902 // TODO refactor this method into smaller parts
904 InstanceIdentifier<Ccap> ccapIid = (InstanceIdentifier<Ccap>) input.getCcapId();
905 List<String> outputError = new ArrayList<String>();
906 String rpcResponse = null;
907 Boolean inputIsConnected = input.getConnection().isConnected();
908 Boolean effectiveIsConnected = null;
909 String ccapId = input.getCcapId().firstIdentifierOf(Ccap.class).firstKeyOf(Ccap.class).getCcapId();
910 PCMMService pcmmService = pcmmServiceMap.get(ccapId);
912 if (!inputIsConnected) {
913 // set connected false
914 if (pcmmService.getPcmmPdpSocket()) {
915 outputError.add(ccapId + ": CCAP COPS socket is already closed");
916 effectiveIsConnected = false;
918 //if (!pcmmService.getPcmmCcapClientIsConnected()) {
919 outputError.add(ccapId + ": CCAP client is disconnected with error: "
920 + pcmmService.getPcmmCcapClientConnectErrMsg());
922 pcmmService.ccapClient.disconnect();
923 effectiveIsConnected = false;
926 // set connected true
927 if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
928 outputError.add(ccapId + ": CCAP COPS socket is already open");
929 outputError.add(ccapId + ": CCAP client is connected");
930 effectiveIsConnected = true;
932 if (pcmmService.getPcmmCcapClientIsConnected()) {
933 pcmmService.ccapClient.disconnect();
935 pcmmService.ccapClient.connect();
936 if (pcmmService.getPcmmCcapClientIsConnected()) {
937 effectiveIsConnected = true;
938 outputError.add(ccapId + ": CCAP client is connected");
940 effectiveIsConnected = false;
941 outputError.add(ccapId + ": CCAP client is disconnected with error: "
942 + pcmmService.getPcmmCcapClientConnectErrMsg());
947 DateAndTime connectionDateAndTime = getNowTimeStamp();
948 org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.ccap.ConnectionBuilder
949 connectionRpcOutput =
950 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.ccap.ConnectionBuilder()
951 .setConnected(effectiveIsConnected)
952 .setError(outputError)
953 .setTimestamp(connectionDateAndTime);
955 org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.CcapBuilder ccapRpcOutput =
956 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.CcapBuilder().setCcapId(
957 ccapId).setConnection(connectionRpcOutput.build());
960 ConnectionBuilder connectionOps = new ConnectionBuilder().setConnected(effectiveIsConnected)
961 .setError(outputError)
962 .setTimestamp(connectionDateAndTime);
964 CcapBuilder responseCcapBuilder = new CcapBuilder().setCcapId(ccapId).setConnection(connectionOps.build());
967 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, ccapIid, responseCcapBuilder.build());
970 DateAndTime rpcDateAndTime = getNowTimeStamp();
971 rpcResponse = ccapId + ": CCAP set complete";
972 CcapSetConnectionOutputBuilder outputBuilder =
973 new CcapSetConnectionOutputBuilder().setCcap(ccapRpcOutput.build())
974 .setResponse(rpcResponse)
975 .setTimestamp(rpcDateAndTime);
977 return Futures.immediateFuture(RpcResultBuilder.success(outputBuilder.build()).build());
983 public Future<RpcResult<CcapPollConnectionOutput>> ccapPollConnection(CcapPollConnectionInput input) {
984 // TODO refactor this method into smaller parts
986 InstanceIdentifier<Ccap> ccapIid = (InstanceIdentifier<Ccap>) input.getCcapId();
987 List<String> outputError = new ArrayList<String>();
989 String ccapId = input.getCcapId().firstIdentifierOf(Ccap.class).firstKeyOf(Ccap.class).getCcapId();
990 PCMMService pcmmService = pcmmServiceMap.get(ccapId);
991 Boolean effectiveIsConnected = true;
992 String response = null;
993 org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder
994 connectionRpcOutput =
995 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder();
997 if (pcmmService != null) {
998 if (pcmmService.getPcmmPdpSocket()) {
999 outputError.add(ccapId + ": CCAP Cops socket is closed");
1000 if (!pcmmService.getPcmmCcapClientIsConnected()) {
1001 outputError.add(ccapId + ": CCAP client is disconnected with error: "
1002 + pcmmService.getPcmmCcapClientConnectErrMsg());
1004 effectiveIsConnected = false;
1006 //outputError.add(String.format(ccapId+": CCAP Cops socket is open"));
1007 if (!pcmmService.getPcmmCcapClientIsConnected()) {
1008 outputError.add(ccapId + ": CCAP client is disconnected with error: "
1009 + pcmmService.getPcmmCcapClientConnectErrMsg());
1010 effectiveIsConnected = false;
1012 outputError.add(ccapId + ": CCAP client is connected");
1015 DateAndTime connectionDateAndTime = getNowTimeStamp();
1018 ConnectionBuilder connectionOps = new ConnectionBuilder().setConnected(effectiveIsConnected)
1019 .setError(outputError)
1020 .setTimestamp(connectionDateAndTime);
1022 CcapBuilder responseCcapBuilder = new CcapBuilder().setCcapId(ccapId).setConnection(connectionOps.build());
1024 connectionRpcOutput =
1025 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder()
1026 .setConnected(effectiveIsConnected)
1027 .setError(outputError)
1028 .setTimestamp(connectionDateAndTime);
1030 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, ccapIid, responseCcapBuilder.build());
1031 response = ccapId + ": CCAP poll complete";
1033 //pcmmService is null, do not poll
1034 response = ccapId + ": CCAP connection null; no poll performed";
1037 DateAndTime rpcDateAndTime = getNowTimeStamp();
1039 org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.CcapBuilder ccapRpcOutput =
1040 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.CcapBuilder().setCcapId(
1041 ccapId).setConnection(connectionRpcOutput.build());
1043 CcapPollConnectionOutputBuilder outputBuilder =
1044 new CcapPollConnectionOutputBuilder().setCcap(ccapRpcOutput.build())
1045 .setResponse(response)
1046 .setTimestamp(rpcDateAndTime);
1048 return Futures.immediateFuture(RpcResultBuilder.success(outputBuilder.build()).build());
1053 private App readAppFromOperationalDatastore(InstanceIdentifier<App> appIid) {
1054 Optional<App> optionalApp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, appIid);
1055 AppBuilder thisAppBuilder = new AppBuilder(optionalApp.get());
1056 App thisApp = thisAppBuilder.build();
1057 logger.info("readAppFromConfigDatastore() retrived App: " + thisApp.getAppId());
1061 private Gate readGateFromOperationalDatastore(InstanceIdentifier<Gate> gateIid) {
1062 Optional<Gate> optionalGate = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, gateIid);
1063 if (optionalGate.isPresent()) {
1064 GateBuilder gateBuilder = new GateBuilder(optionalGate.get());
1065 Gate thisGate = gateBuilder.build();
1072 private Subscriber readSubscriberFromOperationalDatastore(InstanceIdentifier<Subscriber> subscriberIid) {
1073 Optional<Subscriber> optionalSubscriber = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, subscriberIid);
1074 if (optionalSubscriber.isPresent()) {
1075 SubscriberBuilder subscriberBuilder = new SubscriberBuilder(optionalSubscriber.get());
1076 Subscriber thisSubscriber = subscriberBuilder.build();
1077 return thisSubscriber;
1086 public Future<RpcResult<QosPollGatesOutput>> qosPollGates(QosPollGatesInput input) {
1087 // TODO refactor this method into smaller parts
1089 InstanceIdentifier<App> appIid = (InstanceIdentifier<App>) input.getAppId();
1090 //logger.info("qospollgates appIid : "+appIid.toString());
1091 App app = readAppFromOperationalDatastore(appIid);
1092 //logger.info("qospollgates app : "+app.toString());
1093 AppKey appKey = InstanceIdentifier.keyOf(appIid);
1094 String inputSubscriberId = input.getSubscriberId();
1095 String inputGateId = input.getGateId();
1096 List<String> gateOutputError = Collections.emptyList();
1097 String subscriberId = null;
1098 String gateId = null;
1099 String ccapId = null;
1100 String gatePathStr = null;
1101 String opsCopsGateId = null;
1102 Gate opsGate = null;
1104 String rpcResponse = null;
1106 org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.qos.poll.gates.output.GateBuilder gateOutputBuilder =
1107 new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.qos.poll.gates.output.GateBuilder();
1109 GateBuilder gateBuilder = new GateBuilder();
1111 if (inputSubscriberId != null) {
1112 if (inputGateId != null) {
1113 //Subscriber Id and Gate Id provided, only one gate to be poolled
1115 //generate the gateiid
1116 InstanceIdentifier<Gate> gateIid = appIid.builder()
1117 .child(Subscribers.class)
1118 .child(Subscriber.class, new SubscriberKey(inputSubscriberId))
1120 .child(Gate.class, new GateKey(inputGateId))
1124 opsGate = readGateFromOperationalDatastore(gateIid);
1126 //does the gate exists in the Operational DS?
1127 if (opsGate == null) {
1128 gatePathStr = appKey.getAppId() + "/" + inputSubscriberId + "/" + inputGateId;
1129 rpcResponse = gatePathStr + ": gate does not exist in the system; gate poll not performed";
1131 opsCopsGateId = opsGate.getCopsGateId();
1132 gatePathStr = opsGate.getGatePath();
1134 if ((!Objects.equals(opsCopsGateId, "")) && (!Objects.equals(opsCopsGateId, null))) {
1135 ccapId = findCcapForSubscriberId(getInetAddress(inputSubscriberId)).getCcapId();
1136 PCMMService pcmmService = pcmmServiceMap.get(ccapId);
1137 //is the CCAP socket open?
1138 if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
1139 PCMMService.GateSendStatus status = pcmmService.sendGateInfo(gatePathStr);
1140 DateAndTime gateDateAndTime = getNowTimeStamp();
1141 //logger.info("qospollgates Gate Status : GateID/"+status.getCopsGateId());
1142 //logger.info("qospollgates Gate Status : Message/"+status.getMessage());
1143 //logger.info("qospollgates Gate Status : DidSucceed/"+status.didSucceed());
1144 gateOutputError = Collections.singletonList(status.getMessage());
1146 gateOutputBuilder.setGatePath(gatePathStr)
1148 .setCopsGateState(status.getCopsGateState() + "/" + status.getCopsGateStateReason())
1149 .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
1150 .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
1151 .setCopsGateId(status.getCopsGateId())
1152 .setError(gateOutputError)
1153 .setTimestamp(gateDateAndTime);
1155 gateBuilder.setGateId(inputGateId)
1156 .setGatePath(gatePathStr)
1158 .setCopsGateState(status.getCopsGateState() + "/" + status.getCopsGateStateReason())
1159 .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
1160 .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
1161 .setCopsGateId(status.getCopsGateId())
1162 .setError(gateOutputError)
1163 .setTimestamp(gateDateAndTime);
1165 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIid, gateBuilder.build());
1166 rpcResponse = gatePathStr + ": gate poll complete";
1169 ccapId + ": CCAP socket is down or client disconnected; gate poll not performed";
1172 rpcResponse = gatePathStr + ": gate not active; gate poll not performed";
1176 //inputGateId is null; pool all gates for the subscriber if the sub exists
1178 //generate active subIid
1179 InstanceIdentifier<Subscriber> subIid = appIid.builder()
1180 .child(Subscribers.class)
1181 .child(Subscriber.class, new SubscriberKey(inputSubscriberId))
1183 //does the subscriber provided exists in the Operational Datastore?
1184 Subscriber sub = readSubscriberFromOperationalDatastore(subIid);
1186 //If Subscriber exsits poll all gates for the subscriber
1187 subscriberId = sub.getSubscriberId();
1188 List<Gate> gateList = sub.getGates().getGate();
1189 for (Gate gate : gateList) {
1190 //generate active gateIid
1191 gateId = gate.getGateId();
1192 InstanceIdentifier<Gate> gateIid =
1193 subIid.builder().child(Gates.class).child(Gate.class, new GateKey(gateId)).build();
1195 opsGate = readGateFromOperationalDatastore(gateIid);
1196 opsCopsGateId = opsGate.getCopsGateId();
1197 //generate active gatePathStr
1198 gatePathStr = appKey.getAppId() + "/" + subscriberId + "/" + gateId;
1200 if ((!Objects.equals(opsCopsGateId, "")) && (!Objects.equals(opsCopsGateId, null))) {
1201 ccapId = findCcapForSubscriberId(getInetAddress(subscriberId)).getCcapId();
1202 PCMMService pcmmService = pcmmServiceMap.get(ccapId);
1203 //is the CCAP socket open?
1204 if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
1205 PCMMService.GateSendStatus status = pcmmService.sendGateInfo(gatePathStr);
1206 DateAndTime gateDateAndTime = getNowTimeStamp();
1208 gateBuilder.setGateId(gateId)
1209 .setGatePath(gatePathStr)
1212 status.getCopsGateState() + "/" + status.getCopsGateStateReason())
1213 .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
1214 .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
1215 .setCopsGateId(status.getCopsGateId())
1216 .setError(gateOutputError)
1217 .setTimestamp(gateDateAndTime);
1219 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIid, gateBuilder.build());
1222 "qospollgates: {}: CCAP Cops socket is down or client disconnected; gate poll not performed",
1226 //TODO define what happens if a gate is not active.. is nothing ok?
1227 logger.info("qospollgates: {}: gate not active; gate poll not performed", gatePathStr);
1230 rpcResponse = inputSubscriberId + "/: subscriber subtree poll in progress";
1233 inputSubscriberId + "/: subscriber is not defined in the system, gate poll not performed";
1238 // inputSubId is null
1239 if (inputGateId != null) {
1240 gatePathStr = appKey.getAppId() + "/" + inputSubscriberId + "/" + inputGateId;
1241 rpcResponse = gatePathStr + ": Subscriber ID not provided; gate poll not performed";
1243 //poll all gates for the appId
1245 Subscribers subs = app.getSubscribers();
1247 logger.info("qospollgates subscribers: " + subs.toString());
1249 List<Subscriber> subList = subs.getSubscriber();
1250 logger.info("qospollgates subList: " + subList.toString());
1251 for (Subscriber sub : subList) {
1253 //generate active subIid
1254 subscriberId = sub.getSubscriberId();
1255 InstanceIdentifier<Subscriber> subIid = appIid.builder()
1256 .child(Subscribers.class)
1257 .child(Subscriber.class, new SubscriberKey(subscriberId))
1260 List<Gate> gateList = sub.getGates().getGate();
1261 for (Gate gate : gateList) {
1262 //logger.info("qospollgates active gate: "+gate);
1264 //generate active gateIid
1265 gateId = gate.getGateId();
1266 InstanceIdentifier<Gate> gateIid =
1267 subIid.builder().child(Gates.class).child(Gate.class, new GateKey(gateId)).build();
1269 opsGate = readGateFromOperationalDatastore(gateIid);
1270 opsCopsGateId = opsGate.getCopsGateId();
1271 //generate active gatePathStr
1272 gatePathStr = appKey.getAppId() + "/" + subscriberId + "/" + gateId;
1273 if ((!Objects.equals(opsCopsGateId, "")) && (!Objects.equals(opsCopsGateId, null))) {
1274 ccapId = findCcapForSubscriberId(getInetAddress(subscriberId)).getCcapId();
1275 PCMMService pcmmService = pcmmServiceMap.get(ccapId);
1276 //is the CCAP socket open?
1277 if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
1278 PCMMService.GateSendStatus status = pcmmService.sendGateInfo(gatePathStr);
1279 DateAndTime gateDateAndTime = getNowTimeStamp();
1280 gateOutputError = Collections.singletonList(status.getMessage());
1283 gateBuilder.setGateId(gateId)
1284 .setGatePath(gatePathStr)
1287 status.getCopsGateState() + "/" + status.getCopsGateStateReason())
1288 .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
1289 .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
1290 .setCopsGateId(status.getCopsGateId())
1291 .setError(gateOutputError)
1292 .setTimestamp(gateDateAndTime);
1294 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIid, gateBuilder.build());
1297 "qospollgates: {}: CCAP socket is down or client disconnected; gate poll not performed",
1301 //TODO define what happens if a gate is not active.. is nothing ok
1302 logger.info("qospollgates: {}: gate not active; gate poll not performed", gatePathStr);
1306 rpcResponse = appKey.getAppId() + "/: gate subtree poll in progress";
1310 DateAndTime rpcDateAndTime = getNowTimeStamp();
1312 QosPollGatesOutputBuilder outputBuilder = new QosPollGatesOutputBuilder().setTimestamp(rpcDateAndTime)
1313 .setResponse(rpcResponse)
1314 .setGate(gateOutputBuilder.build());
1315 return Futures.immediateFuture(RpcResultBuilder.success(outputBuilder.build()).build());
1318 private DateAndTime getNowTimeStamp() {
1319 DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
1320 return new DateAndTime(dateFormat.format(new Date()));