2 * Copyright © 2018 Orange, 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.connectivity;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.nio.charset.StandardCharsets;
12 import java.util.HashMap;
14 import java.util.UUID;
15 import java.util.concurrent.ExecutionException;
16 import org.opendaylight.transportpce.common.OperationResult;
17 import org.opendaylight.transportpce.common.ResponseCodes;
18 import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl;
19 import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl;
20 import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl;
21 import org.opendaylight.transportpce.tapi.utils.TapiContext;
22 import org.opendaylight.transportpce.tapi.validation.CreateConnectivityServiceValidation;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.RpcActions;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.sdnc.request.header.SdncRequestHeaderBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.OrgOpenroadmServiceService;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateInput;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateOutput;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceDeleteInputBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceDeleteOutput;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.delete.input.ServiceDeleteReqInfo;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.delete.input.ServiceDeleteReqInfoBuilder;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.ForwardingDirection;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.BandwidthProfileBuilder;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.TotalSizeBuilder;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePoint;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePointKey;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceInput;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceOutput;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceOutputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceInput;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceOutput;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceOutputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsInput;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsOutput;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsOutputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsInput;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsOutput;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsOutputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsInput;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsOutput;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsOutputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListInput;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListOutput;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListOutputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ServiceType;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.TapiConnectivityService;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.UpdateConnectivityServiceInput;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.UpdateConnectivityServiceOutput;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPoint;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
69 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
70 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPoint;
71 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPointBuilder;
72 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPointKey;
73 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.end.point.CapacityBuilder;
74 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.end.point.ServiceInterfacePointBuilder;
75 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.output.ServiceBuilder;
76 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connection.details.output.ConnectionBuilder;
77 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connection.end.point.details.output.ConnectionEndPointBuilder;
78 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.Service;
79 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.ServiceKey;
80 import org.opendaylight.yangtools.yang.common.RpcError;
81 import org.opendaylight.yangtools.yang.common.RpcResult;
82 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
83 import org.slf4j.Logger;
84 import org.slf4j.LoggerFactory;
87 * Top level service interface providing main TAPI Connectivity services.
89 public class TapiConnectivityImpl implements TapiConnectivityService {
91 private static final Logger LOG = LoggerFactory.getLogger(TapiConnectivityImpl.class);
93 private OrgOpenroadmServiceService serviceHandler;
94 private final TapiContext tapiContext;
95 private final ConnectivityUtils connectivityUtils;
96 private TapiPceListenerImpl pceListenerImpl;
97 private TapiRendererListenerImpl rendererListenerImpl;
98 private TapiServiceHandlerListenerImpl serviceHandlerListenerImpl;
100 public TapiConnectivityImpl(OrgOpenroadmServiceService serviceHandler, TapiContext tapiContext,
101 ConnectivityUtils connectivityUtils, TapiPceListenerImpl pceListenerImpl,
102 TapiRendererListenerImpl rendererListenerImpl,
103 TapiServiceHandlerListenerImpl serviceHandlerListenerImpl) {
104 LOG.info("inside TapiImpl constructor");
105 this.serviceHandler = serviceHandler;
106 this.tapiContext = tapiContext;
107 this.connectivityUtils = connectivityUtils;
108 this.pceListenerImpl = pceListenerImpl;
109 this.rendererListenerImpl = rendererListenerImpl;
110 this.serviceHandlerListenerImpl = serviceHandlerListenerImpl;
114 public ListenableFuture<RpcResult<CreateConnectivityServiceOutput>> createConnectivityService(
115 CreateConnectivityServiceInput input) {
116 // TODO: later version of TAPI models include Name as an input parameter in connectivity.yang
117 LOG.info("RPC create-connectivity received: {}", input.getEndPoint());
118 Uuid serviceUuid = new Uuid(UUID.randomUUID().toString());
119 this.pceListenerImpl.setInput(input);
120 this.pceListenerImpl.setServiceUuid(serviceUuid);
121 this.rendererListenerImpl.setServiceUuid(serviceUuid);
122 ListenableFuture<RpcResult<ServiceCreateOutput>> output = null;
123 OperationResult validationResult = CreateConnectivityServiceValidation.validateCreateConnectivityServiceRequest(
125 if (validationResult.isSuccess()) {
126 LOG.info("input parameter of RPC create-connectivity are being handled");
127 // check uuid of SIP in tapi context
128 Map<ServiceInterfacePointKey, ServiceInterfacePoint> sipMap = this.tapiContext.getTapiContext()
129 .getServiceInterfacePoint();
130 if (sipMap == null) {
131 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
132 "SIP list is empty").buildFuture();
134 if (sipMap.containsKey(new ServiceInterfacePointKey(input.getEndPoint().values().stream().findFirst().get()
135 .getServiceInterfacePoint().getServiceInterfacePointUuid()))
136 && sipMap.containsKey(new ServiceInterfacePointKey(input.getEndPoint().values().stream().skip(1)
137 .findFirst().get().getServiceInterfacePoint().getServiceInterfacePointUuid()))) {
138 LOG.info("SIPs found in sipMap");
139 // TODO: differentiate between OTN service and GbE service in TAPI
140 ServiceCreateInput sci = this.connectivityUtils.createORServiceInput(input, serviceUuid);
142 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
143 "Couldnt map Service create input").buildFuture();
145 LOG.info("Service Create input = {}", sci);
146 output = this.serviceHandler.serviceCreate(sci);
147 if (!output.isDone()) {
148 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
149 "Service create RPC failed").buildFuture();
152 LOG.error("Unknown UUID");
153 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
154 "SIPs do not exist in tapi context").buildFuture();
158 if (output == null) {
159 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
160 "Failed to create service").buildFuture();
162 LOG.info("Service create request was successful");
163 if (output.get().getResult().getConfigurationResponseCommon().getResponseCode()
164 .equals(ResponseCodes.RESPONSE_FAILED)) {
165 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
166 "Failed to create service").buildFuture();
168 LOG.info("Output of service request = {}", output.get().getResult());
169 } catch (InterruptedException | ExecutionException e) {
170 LOG.error("Error checking response code of service create", e);
172 // Connections and states should be created/updated when the pce and renderer are done :)
173 Map<EndPointKey, EndPoint> endPointList = createEndPoints(input.getEndPoint());
174 Name name = new NameBuilder()
175 .setValueName("Connectivity Service Name")
176 .setValue(serviceUuid.getValue())
178 ConnectivityService service = new ConnectivityServiceBuilder()
179 .setUuid(serviceUuid)
180 .setAdministrativeState(AdministrativeState.LOCKED)
181 .setOperationalState(OperationalState.DISABLED)
182 .setLifecycleState(LifecycleState.PLANNED)
183 .setServiceLayer(input.getConnectivityConstraint().getServiceLayer())
184 .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY)
185 .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL)
186 .setName(Map.of(name.key(), name))
187 .setConnection(new HashMap<>())
188 .setEndPoint(endPointList)
190 // add to tapi context
191 this.tapiContext.updateConnectivityContext(Map.of(service.key(), service), new HashMap<>());
192 LOG.info("Created locked service in Datastore. Waiting for PCE and Renderer to complete tasks...");
193 // return ConnectivityServiceCreateOutput
194 return RpcResultBuilder.success(new CreateConnectivityServiceOutputBuilder()
195 .setService(new ServiceBuilder(service).build()).build()).buildFuture();
198 private Map<EndPointKey, EndPoint> createEndPoints(
199 Map<org.opendaylight.yang.gen.v1.urn
200 .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPointKey,
201 org.opendaylight.yang.gen.v1.urn
202 .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint> endPoints) {
203 Map<EndPointKey, EndPoint> endPointMap = new HashMap<>();
204 for (org.opendaylight.yang.gen.v1.urn
205 .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint ep:
206 endPoints.values()) {
207 EndPoint endpoint = new EndPointBuilder()
208 .setServiceInterfacePoint(new ServiceInterfacePointBuilder()
209 .setServiceInterfacePointUuid(ep.getServiceInterfacePoint().getServiceInterfacePointUuid())
211 .setName(ep.getName())
212 .setAdministrativeState(ep.getAdministrativeState())
213 .setDirection(ep.getDirection())
214 .setLifecycleState(ep.getLifecycleState())
215 .setOperationalState(ep.getOperationalState())
216 .setLayerProtocolName(ep.getLayerProtocolName())
217 .setCapacity(new CapacityBuilder()
218 .setTotalSize(new TotalSizeBuilder().build())
219 .setBandwidthProfile(new BandwidthProfileBuilder().build()) // TODO: implement bandwidth profile
221 .setProtectionRole(ep.getProtectionRole())
222 .setRole(ep.getRole())
223 .setLocalId(ep.getLocalId())
225 endPointMap.put(endpoint.key(), endpoint);
231 public ListenableFuture<RpcResult<GetConnectivityServiceDetailsOutput>> getConnectivityServiceDetails(
232 GetConnectivityServiceDetailsInput input) {
233 // TODO Auto-generated method stub
234 Uuid serviceUuid = getUuidFromIput(input.getServiceIdOrName());
235 ConnectivityService service = this.tapiContext.getConnectivityService(serviceUuid);
236 if (service == null) {
237 LOG.error("Service {} doesnt exist in tapi context", input.getServiceIdOrName());
238 return RpcResultBuilder.<GetConnectivityServiceDetailsOutput>failed().withError(RpcError.ErrorType.RPC,
239 "Service doesnt exist in datastore").buildFuture();
241 return RpcResultBuilder.success(new GetConnectivityServiceDetailsOutputBuilder().setService(
242 new org.opendaylight.yang.gen.v1.urn
243 .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.details.output.ServiceBuilder(
244 service).build()).build()).buildFuture();
248 public ListenableFuture<RpcResult<UpdateConnectivityServiceOutput>> updateConnectivityService(
249 UpdateConnectivityServiceInput input) {
250 // TODO Auto-generated method stub. More complicated as it depends on what needs to be updated... left aside
255 public ListenableFuture<RpcResult<GetConnectionDetailsOutput>> getConnectionDetails(
256 GetConnectionDetailsInput input) {
257 // TODO Auto-generated method stub
258 Uuid connectionUuid = getUuidFromIput(input.getConnectionIdOrName());
259 Connection connection = this.tapiContext.getConnection(connectionUuid);
260 if (connection == null) {
261 LOG.error("Connection {} doesnt exist in tapi context", input.getConnectionIdOrName());
262 return RpcResultBuilder.<GetConnectionDetailsOutput>failed().withError(RpcError.ErrorType.RPC,
263 "Connection doesnt exist in datastore").buildFuture();
265 return RpcResultBuilder.success(new GetConnectionDetailsOutputBuilder().setConnection(
266 new ConnectionBuilder(connection).build()).build()).buildFuture();
270 public ListenableFuture<RpcResult<DeleteConnectivityServiceOutput>> deleteConnectivityService(
271 DeleteConnectivityServiceInput input) {
272 //TODO Auto-generated method stub
274 if (input.getServiceIdOrName() != null) {
276 Uuid serviceUuid = getUuidFromIput(input.getServiceIdOrName());
277 this.tapiContext.deleteConnectivityService(serviceUuid);
278 ListenableFuture<RpcResult<ServiceDeleteOutput>> output =
279 this.serviceHandler.serviceDelete(new ServiceDeleteInputBuilder()
280 .setServiceDeleteReqInfo(new ServiceDeleteReqInfoBuilder()
281 .setServiceName(input.getServiceIdOrName())
282 .setTailRetention(ServiceDeleteReqInfo.TailRetention.No)
284 .setSdncRequestHeader(new SdncRequestHeaderBuilder()
285 .setRequestId("request-1")
286 .setNotificationUrl("notification url")
287 .setRequestSystemId("appname")
288 .setRpcAction(RpcActions.ServiceDelete)
291 RpcResult<ServiceDeleteOutput> rpcResult = output.get();
292 if (!rpcResult.getResult().getConfigurationResponseCommon().getResponseCode()
293 .equals(ResponseCodes.RESPONSE_FAILED)) {
294 LOG.info("Service is being deleted and devices are being rolled back");
295 return RpcResultBuilder.success(new DeleteConnectivityServiceOutputBuilder().build()).buildFuture();
297 LOG.error("Failed to delete service. Deletion process failed");
298 } catch (InterruptedException | ExecutionException e) {
299 LOG.error("Failed to delete service.", e);
302 return RpcResultBuilder.<DeleteConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
303 "Failed to delete Service").buildFuture();
307 public ListenableFuture<RpcResult<GetConnectivityServiceListOutput>> getConnectivityServiceList(
308 GetConnectivityServiceListInput input) {
309 // TODO Auto-generated method stub
310 Map<ConnectivityServiceKey, ConnectivityService> connMap = this.tapiContext.getConnectivityServices();
311 if (connMap == null) {
312 LOG.error("No services in tapi context");
313 return RpcResultBuilder.<GetConnectivityServiceListOutput>failed().withError(RpcError.ErrorType.RPC,
314 "No services exist in datastore").buildFuture();
317 Map<ServiceKey, Service> serviceMap = new HashMap<>();
318 for (ConnectivityService connectivityService: connMap.values()) {
319 Service service = new org.opendaylight.yang.gen.v1.urn
320 .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.ServiceBuilder(
321 connectivityService).build();
322 serviceMap.put(service.key(), service);
324 return RpcResultBuilder.success(new GetConnectivityServiceListOutputBuilder().setService(serviceMap)
325 .build()).buildFuture();
329 public ListenableFuture<RpcResult<GetConnectionEndPointDetailsOutput>> getConnectionEndPointDetails(
330 GetConnectionEndPointDetailsInput input) {
331 // TODO Auto-generated method stub
332 Uuid topoUuid = getUuidFromIput(input.getTopologyIdOrName());
333 Uuid nodeUuid = getUuidFromIput(input.getNodeIdOrName());
334 Uuid nepUuid = getUuidFromIput(input.getNepIdOrName());
335 Uuid cepUuid = getUuidFromIput(input.getCepIdOrName());
336 ConnectionEndPoint cep = this.tapiContext.getTapiCEP(topoUuid, nodeUuid, nepUuid, cepUuid);
338 LOG.error("Cep doesnt exist in tapi context");
339 return RpcResultBuilder.<GetConnectionEndPointDetailsOutput>failed().withError(RpcError.ErrorType.RPC,
340 "No cep with given Uuid exists in datastore").buildFuture();
342 return RpcResultBuilder.success(new GetConnectionEndPointDetailsOutputBuilder().setConnectionEndPoint(
343 new ConnectionEndPointBuilder(cep).build()).build()).buildFuture();
346 private Uuid getUuidFromIput(String serviceIdOrName) {
348 UUID.fromString(serviceIdOrName);
349 LOG.info("Given attribute {} is a UUID", serviceIdOrName);
350 return new Uuid(serviceIdOrName);
351 } catch (IllegalArgumentException e) {
352 LOG.info("Given attribute {} is not a UUID", serviceIdOrName);
353 return new Uuid(UUID.nameUUIDFromBytes(serviceIdOrName.getBytes(StandardCharsets.UTF_8)).toString());