c2e507ac4c04c968687af47f5e0b39f1ed60449d
[transportpce.git] / tests / honeynode / 2.2.1 / honeynode-plugin-impl / src / main / java / io / fd / honeycomb / transportpce / device / notifications / DeviceNotificationProducer.java
1 /*
2  * Copyright (c) 2018 Orange and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package io.fd.honeycomb.transportpce.device.notifications;
17
18 import com.google.common.base.Preconditions;
19 import com.google.common.collect.Lists;
20 import com.google.inject.Inject;
21 import com.google.inject.name.Named;
22
23
24 import io.fd.honeycomb.notification.ManagedNotificationProducer;
25 import io.fd.honeycomb.notification.NotificationCollector;
26
27 import java.text.SimpleDateFormat;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Date;
31 import java.util.Iterator;
32 import java.util.List;
33
34
35
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.binding.api.DataObjectModification;
38 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
39 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
40 import org.opendaylight.mdsal.binding.api.DataTreeModification;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.ChangeNotification;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.ChangeNotification.Datastore;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.ChangeNotificationBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.change.notification.Edit;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.change.notification.EditBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.changed.by.parms.ChangedBy;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.changed.by.parms.ChangedByBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.changed.by.parms.changed.by.server.or.user.ServerBuilder;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.pack.Ports;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.pack.PortsKey;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.packs.CircuitPacks;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.packs.CircuitPacksKey;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.interfaces.grp.Interface;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.OrgOpenroadmDevice;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditOperationType;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
58 import org.opendaylight.yangtools.yang.binding.DataObject;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.opendaylight.yangtools.yang.binding.Notification;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 /**
65  * @author Martial COULIBALY ( mcoulibaly.ext@orange.com ) on behalf of Orange
66  */
67 public class DeviceNotificationProducer implements ManagedNotificationProducer {
68     private static final Logger LOG = LoggerFactory.getLogger(DeviceNotificationProducer.class);
69     private static final InstanceIdentifier<OrgOpenroadmDevice> DEVICE_CONTAINER_ID = InstanceIdentifier
70             .create(OrgOpenroadmDevice.class);
71     private static final String INTERFACE_CLASS = Interface.class.getName();
72
73     @Inject
74     @Named("device-databroker")
75     private DataBroker dataBroker;
76
77     @Override
78     public Collection<Class<? extends Notification>> getNotificationTypes() {
79         final ArrayList<Class<? extends Notification>> classes = Lists.newArrayList();
80         classes.add(ChangeNotification.class);
81         return classes;
82     }
83
84     @Override
85     public void close() throws Exception {
86         stop();
87     }
88
89     @Override
90     public void start(NotificationCollector collector) {
91         LOG.info("Starting notification stream for OrgOpenroadmDevice");
92         Preconditions.checkArgument(this.dataBroker != null, "Device datastore is null");
93         this.dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, DEVICE_CONTAINER_ID),
94                  new DataTreeChangeListener<OrgOpenroadmDevice>() {
95                     @Override
96                     public void onDataTreeChanged(Collection<DataTreeModification<OrgOpenroadmDevice>> changes) {
97                         LOG.info("onDataTreeChanged");
98                         ChangeNotification changeNotification = null;
99                         try {
100                             changeNotification = transformToNotification(changes);
101                             LOG.info("Emitting notification : {}", changeNotification);
102                             collector.onNotification(changeNotification);
103                         } catch (NullPointerException e) {
104                             LOG.warn("Failed to emit notification");
105                         }
106                     }
107                 });
108     }
109
110     @Override
111     public void stop() {
112         LOG.info("Stopping OrgOpenroadmDevice change notification");
113     }
114
115     /**
116      * Transform {@link Collection} of {@link DataTreeModification } to {@link ChangeNotification}
117      *
118      * @return changeNotification {@link ChangeNotification}
119      */
120     private ChangeNotification transformToNotification(Collection<DataTreeModification<OrgOpenroadmDevice>> changes) {
121         LOG.info("transforming changes to notification...");
122         ChangeNotification result = null;
123         List<Edit> editList = new ArrayList<Edit>();
124         for (DataTreeModification<OrgOpenroadmDevice> change : changes) {
125             LOG.info("Received Device change :\n{}", change.getRootNode().getModificationType());
126             final DataObjectModification<OrgOpenroadmDevice> rootNode = change.getRootNode();
127             final DataTreeIdentifier<OrgOpenroadmDevice> rootPath = change.getRootPath();
128             if (rootNode != null) {
129                 Collection<? extends DataObjectModification<? extends DataObject>> modifiedChildren = rootNode.getModifiedChildren();
130                 switch (rootNode.getModificationType()) {
131                 case SUBTREE_MODIFIED: // OrgOpenroadmDevice
132                     if (!modifiedChildren.isEmpty()) {
133                         Iterator<? extends DataObjectModification<? extends DataObject>> iterator = modifiedChildren.iterator();
134                         while (iterator.hasNext()) {
135                             DataObjectModification<? extends DataObject> modified = iterator.next();
136                             LOG.info(
137                                     "modified = \ndataType : {}\nid : {}\nmodifiedType : {}\noldData : {}\nnewData : {} \n",
138                                     modified.getDataType(), modified.getIdentifier(), modified.getModificationType(),
139                                     modified.getDataBefore(), modified.getDataAfter());
140                             String dataType = modified.getDataType().getName();
141                             if (dataType.equals(INTERFACE_CLASS)) {
142                                 Interface data = null;
143                                 LOG.info("Interface type update !");
144                                 switch (modified.getModificationType()) {
145                                 case SUBTREE_MODIFIED:
146                                     data = (Interface) modified.getDataAfter();
147                                     break;
148                                 case WRITE:
149                                     data = (Interface) modified.getDataAfter();
150                                     break;
151                                 case DELETE:
152                                     data = (Interface) modified.getDataBefore();
153                                     break;
154                                 default:
155                                     break;
156                                 }
157                                 if (data!= null) {
158                                     String circuitPackName = data.getSupportingCircuitPackName();
159                                     String port = data.getSupportingPort().toString();
160                                     String interfaceName = data.getName();
161                                     if (circuitPackName != null && port != null && interfaceName != null) {
162                                         InstanceIdentifier<Ports> portIId = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
163                                                 CircuitPacks.class, new CircuitPacksKey(circuitPackName)).child(Ports.class,
164                                                     new PortsKey(port));
165                                         Edit edit = new EditBuilder()
166                                                 .setOperation(EditOperationType.Merge)
167                                                 .setTarget(portIId)
168                                                 .build();
169                                         editList.add(edit);
170                                     }
171                                 } else {
172                                     LOG.warn("Interface data is null !");
173                                 }
174                             } else {
175                                 LOG.warn("modifiedChild is not an interface !");
176                             }
177                         }
178                     }
179                     break;
180                 case WRITE:
181                     LOG.info("device operational datastore is created !");
182                     break;
183                 case DELETE:
184                     LOG.info("device operational datastore is deleted !");
185                     break;
186                 default:
187                     break;
188                 }
189             } else {
190                 LOG.error("rootNode is null !");
191             }
192         }
193         if (!editList.isEmpty()) {
194             ChangedBy changedBy = new ChangedByBuilder().setServerOrUser(new ServerBuilder().setServer(true).build())
195                     .build();
196             String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX").format(new Date());
197             result = new ChangeNotificationBuilder().setChangedBy(changedBy).setChangeTime(new DateAndTime(time))
198                     .setDatastore(Datastore.Running).setEdit(editList).build();
199         } else {
200             LOG.warn("edit List is empty !");
201         }
202         return result;
203     }
204 }