2 * Copyright © 2021 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.tapi.listeners;
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import java.nio.charset.Charset;
12 import java.util.Optional;
13 import java.util.UUID;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
17 import org.opendaylight.transportpce.common.network.NetworkTransactionImpl;
18 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
19 import org.opendaylight.transportpce.common.network.RequestProcessor;
20 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSp;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.TransportpceRendererListener;
22 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState;
23 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
24 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState;
25 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
26 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
27 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1;
28 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey;
30 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
31 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 public class TapiRendererListenerImpl implements TransportpceRendererListener {
40 private static final Logger LOG = LoggerFactory.getLogger(TapiRendererListenerImpl.class);
41 private final DataBroker dataBroker;
42 private Uuid serviceUuid;
43 private RendererRpcResultSp serviceRpcResultSp;
44 private final NetworkTransactionService networkTransactionService;
46 public TapiRendererListenerImpl(DataBroker dataBroker) {
47 this.dataBroker = dataBroker;
48 this.networkTransactionService = new NetworkTransactionImpl(new RequestProcessor(this.dataBroker));
52 public void onRendererRpcResultSp(RendererRpcResultSp notification) {
53 if (compareServiceRpcResultSp(notification)) {
54 LOG.warn("ServiceRpcResultSp already wired !");
57 serviceRpcResultSp = notification;
58 int notifType = serviceRpcResultSp.getNotificationType().getIntValue();
59 LOG.info("Renderer '{}' Notification received : {}", serviceRpcResultSp.getNotificationType().getName(),
61 /* service-implementation-request. */
63 onServiceImplementationResult(notification);
68 * Process service implementation result for serviceName.
69 * @param notification RendererRpcResultSp
71 private void onServiceImplementationResult(RendererRpcResultSp notification) {
72 switch (serviceRpcResultSp.getStatus()) {
74 if (this.serviceUuid != null) {
75 onSuccededServiceImplementation();
79 onFailedServiceImplementation(notification.getServiceName());
82 LOG.warn("Service Implementation still pending according to RpcStatusEx");
85 LOG.warn("Service Implementation has an unknown RpcStatusEx code");
91 * Process succeeded service implementation for service.
93 private void onSuccededServiceImplementation() {
94 LOG.info("Service implemented !");
95 // TODO: update Connections and Connectivity Service states
96 ConnectivityService connectivityService = getConnectivityService(this.serviceUuid);
97 if (connectivityService == null) {
98 LOG.error("Couldnt retrieve service from datastore");
101 LOG.info("Connectivity service = {}", connectivityService.toString());
102 // TODO --> this throws error because the renderer goes really fast. Is this normal??
103 ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connectivityService)
104 .setAdministrativeState(AdministrativeState.UNLOCKED)
105 .setLifecycleState(LifecycleState.INSTALLED)
106 .setOperationalState(OperationalState.ENABLED)
108 for (Connection connection:updtConnServ.nonnullConnection().values()) {
109 updateConnectionState(connection.getConnectionUuid());
111 updateConnectivityService(updtConnServ);
115 * Process failed service implementation for serviceName.
116 * @param serviceName String
118 private void onFailedServiceImplementation(String serviceName) {
119 LOG.error("Renderer implementation failed !");
120 LOG.info("PCE cancel resource done OK !");
121 Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8")))
123 // get connections of connectivity service and remove them from tapi context and then remove
124 // service from context. The CEPs are maintained as they could be reused by another service
125 ConnectivityService connService = getConnectivityService(suuid);
126 if (connService == null) {
127 LOG.error("Service doesnt exist in tapi context");
130 for (Connection connection:connService.getConnection().values()) {
131 deleteConnection(connection.getConnectionUuid());
133 deleteConnectivityService(suuid);
137 value = "ES_COMPARING_STRINGS_WITH_EQ",
138 justification = "false positives, not strings but real object references comparisons")
139 private Boolean compareServiceRpcResultSp(RendererRpcResultSp notification) {
140 if (serviceRpcResultSp == null) {
143 if (serviceRpcResultSp.getNotificationType() != notification.getNotificationType()) {
146 if (serviceRpcResultSp.getServiceName() != notification.getServiceName()) {
149 if (serviceRpcResultSp.getStatus() != notification.getStatus()) {
152 if (serviceRpcResultSp.getStatusMessage() != notification.getStatusMessage()) {
158 private ConnectivityService getConnectivityService(Uuid suuid) {
159 // TODO: verify this is correct. Should we identify the context IID with the context UUID??
161 // First read connectivity service with service uuid and update info
162 InstanceIdentifier<ConnectivityService> connectivityServIID =
163 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
164 .child(org.opendaylight.yang.gen.v1.urn
165 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
166 .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
169 Optional<ConnectivityService> optConnServ =
170 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get();
171 if (!optConnServ.isPresent()) {
172 LOG.error("Connectivity service not found in tapi context");
175 return optConnServ.get();
176 } catch (InterruptedException | ExecutionException e) {
177 LOG.error("Failed to merge TAPI connectivity", e);
182 private void updateConnectionState(Uuid connectionUuid) {
183 // TODO: verify this is correct. Should we identify the context IID with the context UUID??
185 // First read connection with connection uuid and update info
186 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
187 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionIID =
188 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
189 .child(org.opendaylight.yang.gen.v1.urn
190 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
191 .child(org.opendaylight.yang.gen.v1.urn
192 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
193 new ConnectionKey(connectionUuid))
196 Optional<org.opendaylight.yang.gen.v1.urn
197 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> optConn =
198 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectionIID).get();
199 if (!optConn.isPresent()) {
200 LOG.error("Connection not found in tapi context");
203 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
204 newConnection = new ConnectionBuilder(optConn.get()).setLifecycleState(LifecycleState.INSTALLED)
205 .setOperationalState(OperationalState.ENABLED).build();
206 // merge in datastore
207 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectionIID,
209 this.networkTransactionService.commit().get();
210 LOG.info("TAPI connection merged successfully.");
211 } catch (InterruptedException | ExecutionException e) {
212 LOG.error("Failed to merge TAPI connection", e);
216 private void updateConnectivityService(ConnectivityService updtConnServ) {
217 // TODO: verify this is correct. Should we identify the context IID with the context UUID??
219 // First read connectivity service with connectivity service uuid and update info
220 InstanceIdentifier<ConnectivityService> connServIID =
221 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
222 .child(org.opendaylight.yang.gen.v1.urn
223 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
224 .child(ConnectivityService.class, new ConnectivityServiceKey(updtConnServ.getUuid()))
227 Optional<ConnectivityService> optConnServ =
228 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connServIID).get();
229 if (!optConnServ.isPresent()) {
230 LOG.error("Connection not found in tapi context");
233 ConnectivityService newConnServ = new ConnectivityServiceBuilder(updtConnServ).build();
234 // merge in datastore
235 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connServIID,
237 this.networkTransactionService.commit().get();
238 LOG.info("TAPI connectivity service merged successfully.");
239 } catch (InterruptedException | ExecutionException e) {
240 LOG.error("Failed to merge TAPI connectivity service", e);
244 private void deleteConnectivityService(Uuid suuid) {
245 // First read connectivity service with service uuid and update info
246 InstanceIdentifier<ConnectivityService> connectivityServIID =
247 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
248 .child(org.opendaylight.yang.gen.v1.urn
249 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
250 .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
253 this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID);
254 this.networkTransactionService.commit().get();
255 } catch (InterruptedException | ExecutionException e) {
256 LOG.error("Failed to delete TAPI connectivity service", e);
260 private void deleteConnection(Uuid connectionUuid) {
261 // First read connectivity service with service uuid and update info
262 InstanceIdentifier<org.opendaylight.yang.gen.v1
263 .urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionIID =
264 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
265 .child(org.opendaylight.yang.gen.v1.urn
266 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
267 .child(org.opendaylight.yang.gen.v1.urn
268 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
269 new org.opendaylight.yang.gen.v1.urn
270 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey(
274 this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID);
275 this.networkTransactionService.commit().get();
276 } catch (InterruptedException | ExecutionException e) {
277 LOG.error("Failed to delete TAPI connection", e);
281 public void setServiceUuid(Uuid serviceUuid) {
282 this.serviceUuid = serviceUuid;