2 * Copyright © 2020 Nokia, Inc. 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
8 package org.opendaylight.transportpce.servicehandler.listeners;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
14 import java.util.Optional;
15 import java.util.stream.Collectors;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
18 import org.opendaylight.transportpce.common.OperationResult;
19 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
20 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResult;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TransportpceNetworkmodelListener;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChanges;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesKey;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
27 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.AToZDirection;
28 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.AToZDirectionBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ZToADirection;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ZToADirectionBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.atoz.direction.AToZ;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.atoz.direction.AToZBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.atoz.direction.AToZKey;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ztoa.direction.ZToA;
35 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ztoa.direction.ZToABuilder;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ztoa.direction.ZToAKey;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.Resource;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.ResourceBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.resource.resource.TerminationPoint;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service.path.PathDescription;
41 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service.path.PathDescriptionBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
43 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class NetworkModelListenerImpl implements TransportpceNetworkmodelListener {
49 private static final Logger LOG = LoggerFactory.getLogger(NetworkModelListenerImpl.class);
50 private final NotificationPublishService notificationPublishService; // to be used for T-API notification
51 private ServiceDataStoreOperations serviceDataStoreOperations;
52 private TopologyUpdateResult topologyUpdateResult;
54 public NetworkModelListenerImpl(NotificationPublishService notificationPublishService,
55 ServiceDataStoreOperations serviceDataStoreOperations) {
56 this.notificationPublishService = notificationPublishService;
57 this.serviceDataStoreOperations = serviceDataStoreOperations;
61 public void onTopologyUpdateResult(TopologyUpdateResult notification) {
62 LOG.debug("Topology update notification: {}", notification.toString());
63 if (compareTopologyUpdateResult(notification)) {
64 LOG.warn("TopologyUpdateResult already wired !");
67 topologyUpdateResult = notification;
68 // Update service datastore and service path description
69 updateServicePaths(notification);
73 * Process topology update result.
74 * @param notification the result notification.
76 private void updateServicePaths(TopologyUpdateResult notification) {
78 Map<TopologyChangesKey, TopologyChanges> topologyChanges = notification.getTopologyChanges();
79 Optional<ServicePathList> servicePathListOptional = this.serviceDataStoreOperations.getServicePaths();
80 ServicePathList servicePathList = null;
81 if (!servicePathListOptional.isPresent()) {
82 LOG.warn("Enable to retrieve service path list");
85 servicePathList = servicePathListOptional.get();
86 for (ServicePaths servicePaths : servicePathList.getServicePaths().values()) {
87 String serviceName = servicePaths.getServicePathName();
88 PathDescription pathDescription = servicePaths.getPathDescription();
89 // update path descriptions in the datastore
90 Map<AToZKey, AToZ> updatedAtoZ = changePathElementStateAZ(topologyChanges, pathDescription);
91 Map<ZToAKey, ZToA> updatedZtoA = changePathElementStateZA(topologyChanges, pathDescription);
92 OperationResult operationResult = this.serviceDataStoreOperations
93 .modifyServicePath(buildNewPathDescription(pathDescription, updatedAtoZ, updatedZtoA), serviceName);
94 if (!operationResult.isSuccess()) {
95 LOG.warn("Service Path not updated in datastore!");
98 // update service in the datastore. Only path description with all elements in service can have a service
99 // in service. Therefore we check if all the states of the path description resources are inService
100 Optional<Services> serviceOptional = this.serviceDataStoreOperations.getService(serviceName);
101 Services services = null;
102 if (!serviceOptional.isPresent()) {
103 LOG.error("Couldn't retrieve service");
106 services = serviceOptional.get();
107 OperationResult operationResult1 = null;
108 if (org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev181130.State.InService
109 .equals(services.getOperationalState())
110 && !allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
111 LOG.debug("Service={} needs to be updated to outOfService", serviceName);
112 operationResult1 = this.serviceDataStoreOperations.modifyService(serviceName, State.OutOfService,
113 AdminStates.OutOfService);
114 } else if (org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev181130.State.OutOfService
115 .equals(services.getOperationalState())
116 && allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
117 LOG.debug("Service={} needs to be updated to inService", serviceName);
118 operationResult1 = this.serviceDataStoreOperations.modifyService(serviceName, State.InService,
119 AdminStates.InService);
121 LOG.debug("Service {} state doesnt need to be modified", serviceName);
123 if (operationResult1 != null && operationResult1.isSuccess()) {
124 LOG.info("Service state of {} correctly updated in datastore", serviceName);
129 private Map<ZToAKey, ZToA> changePathElementStateZA(Map<TopologyChangesKey, TopologyChanges> topologyChanges,
130 PathDescription pathDescription) {
132 Map<ZToAKey, ZToA> newztoaMap = new HashMap<>(pathDescription.getZToADirection().getZToA());
133 List<ZToA> tpResources = pathDescription.getZToADirection().getZToA().values().stream()
134 .filter(ele -> ele.getResource().getResource().implementedInterface().getSimpleName()
135 .equals("TerminationPoint"))
136 .collect(Collectors.toList());
137 for (ZToA ztoA : tpResources) {
138 String ztoAid = ztoA.getId();
139 State ztoAState = ztoA.getResource().getState();
140 TerminationPoint tp = (TerminationPoint) ztoA.getResource().getResource();
141 if (topologyChanges.containsKey(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId()))
142 && !topologyChanges.get(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId())).getState()
143 .equals(ztoAState)) {
144 LOG.debug("updating ztoa tp {}", ztoA);
145 State updatedState = topologyChanges.get(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId()))
147 Resource updatedResource = new ResourceBuilder()
149 .setState(updatedState)
151 ZToA updatedZToA = new ZToABuilder(ztoA)
153 .setResource(updatedResource)
155 newztoaMap.put(updatedZToA.key(), updatedZToA);
161 private Map<AToZKey, AToZ> changePathElementStateAZ(Map<TopologyChangesKey,
162 TopologyChanges> topologyChanges, PathDescription pathDescription) {
164 Map<AToZKey, AToZ> newatozMap = new HashMap<>(pathDescription.getAToZDirection().getAToZ());
165 List<AToZ> tpResources = pathDescription.getAToZDirection().getAToZ().values().stream()
166 .filter(ele -> ele.getResource().getResource().implementedInterface().getSimpleName()
167 .equals("TerminationPoint"))
168 .collect(Collectors.toList());
169 for (AToZ atoZ : tpResources) {
170 String atoZid = atoZ.getId();
171 State atoZState = atoZ.getResource().getState();
172 TerminationPoint tp = (TerminationPoint) atoZ.getResource().getResource();
173 if (topologyChanges.containsKey(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId()))
174 && !topologyChanges.get(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId())).getState()
175 .equals(atoZState)) {
176 LOG.debug("updating atoz tp {}", atoZ);
177 State updatedState = topologyChanges.get(new TopologyChangesKey(tp.getTpNodeId(), tp.getTpId()))
179 Resource updatedResource = new ResourceBuilder()
181 .setState(updatedState)
183 AToZ updatedAToZ = new AToZBuilder(atoZ)
185 .setResource(updatedResource)
187 newatozMap.put(updatedAToZ.key(), updatedAToZ);
193 private PathDescription buildNewPathDescription(PathDescription pathDescription, Map<AToZKey, AToZ> updatedAtoZ,
194 Map<ZToAKey, ZToA> updatedZtoA) {
195 AToZDirection atozDir = new AToZDirectionBuilder(pathDescription.getAToZDirection())
196 .setAToZ(updatedAtoZ)
198 ZToADirection ztoaDir = new ZToADirectionBuilder(pathDescription.getZToADirection())
199 .setZToA(updatedZtoA)
201 return new PathDescriptionBuilder()
202 .setAToZDirection(atozDir)
203 .setZToADirection(ztoaDir)
207 private boolean allElementsinPathinService(Map<AToZKey, AToZ> updatedAtoZ, Map<ZToAKey, ZToA> updatedZtoA) {
208 boolean allEleminService = true;
209 Iterator<AToZ> i1 = updatedAtoZ.values().iterator();
210 Iterator<ZToA> i2 = updatedZtoA.values().iterator();
211 // TODO: both directions have same length?
212 while (i1.hasNext() && i2.hasNext()) {
213 if (State.OutOfService.getIntValue() == i1.next().getResource().getState().getIntValue()
214 || State.OutOfService.getIntValue() == i2.next().getResource().getState().getIntValue()) {
215 allEleminService = false;
220 return allEleminService;
223 private boolean compareTopologyUpdateResult(TopologyUpdateResult notification) {
224 if (topologyUpdateResult == null) {
227 if (topologyUpdateResult.getTopologyChanges().values()
228 .equals(notification.getTopologyChanges().values())) {
234 public void setserviceDataStoreOperations(ServiceDataStoreOperations serviceData) {
235 this.serviceDataStoreOperations = serviceData;