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