TAPI Connectivity service RPCs impl
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / connectivity / TapiConnectivityImpl.java
1 /*
2  * Copyright © 2018 Orange, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.transportpce.tapi.connectivity;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.nio.charset.Charset;
12 import java.util.HashMap;
13 import java.util.Map;
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.rev190531.RpcActions;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.sdnc.request.header.SdncRequestHeaderBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.OrgOpenroadmServiceService;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInput;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateOutput;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceDeleteInputBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceDeleteOutput;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.delete.input.ServiceDeleteReqInfo;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.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;
85
86 /**
87  * Top level service interface providing main TAPI Connectivity services.
88  */
89 public class TapiConnectivityImpl implements TapiConnectivityService {
90
91     private static final Logger LOG = LoggerFactory.getLogger(TapiConnectivityImpl.class);
92
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;
99
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;
111     }
112
113     @Override
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(
124                 input);
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();
133             }
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                 ServiceCreateInput sci = this.connectivityUtils.createORServiceInput(input, serviceUuid);
140                 if (sci == null) {
141                     return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
142                         "Couldnt map Service create input").buildFuture();
143                 }
144                 LOG.info("Service Create input = {}", sci);
145                 output = this.serviceHandler.serviceCreate(sci);
146                 if (!output.isDone()) {
147                     return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
148                         "Service create RPC failed").buildFuture();
149                 }
150             } else {
151                 LOG.error("Unknown UUID");
152                 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
153                     "SIPs do not exist in tapi context").buildFuture();
154             }
155         }
156         try {
157             if (output == null) {
158                 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
159                     "Failed to create service").buildFuture();
160             }
161             LOG.info("Service create request was successful");
162             if (output.get().getResult().getConfigurationResponseCommon().getResponseCode()
163                     .equals(ResponseCodes.RESPONSE_FAILED)) {
164                 return RpcResultBuilder.<CreateConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
165                     "Failed to create service").buildFuture();
166             }
167             LOG.info("Output of service request = {}", output.get().getResult());
168         } catch (InterruptedException | ExecutionException e) {
169             LOG.error("Error checking response code of service create", e);
170         }
171         // Connections and states should be created/updated when the pce and renderer are done :)
172         Map<EndPointKey, EndPoint> endPointList = createEndPoints(input.getEndPoint());
173         Name name = new NameBuilder()
174             .setValueName("Connectivity Service Name")
175             .setValue(serviceUuid.getValue())
176             .build();
177         ConnectivityService service = new ConnectivityServiceBuilder()
178             .setUuid(serviceUuid)
179             .setAdministrativeState(AdministrativeState.LOCKED)
180             .setOperationalState(OperationalState.DISABLED)
181             .setLifecycleState(LifecycleState.PLANNED)
182             .setServiceLayer(input.getConnectivityConstraint().getServiceLayer())
183             .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY)
184             .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL)
185             .setName(Map.of(name.key(), name))
186             .setConnection(new HashMap<>())
187             .setEndPoint(endPointList)
188             .build();
189         // add to tapi context
190         this.tapiContext.updateConnectivityContext(Map.of(service.key(), service), new HashMap<>());
191         LOG.info("Created locked service in Datastore. Waiting for PCE and Renderer to complete tasks...");
192         // return ConnectivityServiceCreateOutput
193         return RpcResultBuilder.success(new CreateConnectivityServiceOutputBuilder()
194             .setService(new ServiceBuilder(service).build()).build()).buildFuture();
195     }
196
197     private Map<EndPointKey, EndPoint> createEndPoints(
198             Map<org.opendaylight.yang.gen.v1.urn
199                 .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPointKey,
200                 org.opendaylight.yang.gen.v1.urn
201                     .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint> endPoints) {
202         Map<EndPointKey, EndPoint> endPointMap = new HashMap<>();
203         for (org.opendaylight.yang.gen.v1.urn
204                 .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint ep:
205                 endPoints.values()) {
206             EndPoint endpoint = new EndPointBuilder()
207                 .setServiceInterfacePoint(new ServiceInterfacePointBuilder()
208                     .setServiceInterfacePointUuid(ep.getServiceInterfacePoint().getServiceInterfacePointUuid())
209                     .build())
210                 .setName(ep.getName())
211                 .setAdministrativeState(ep.getAdministrativeState())
212                 .setDirection(ep.getDirection())
213                 .setLifecycleState(ep.getLifecycleState())
214                 .setOperationalState(ep.getOperationalState())
215                 .setLayerProtocolName(ep.getLayerProtocolName())
216                 .setCapacity(new CapacityBuilder()
217                     .setTotalSize(new TotalSizeBuilder().build())
218                     .setBandwidthProfile(new BandwidthProfileBuilder().build()) // TODO: implement bandwidth profile
219                     .build())
220                 .setProtectionRole(ep.getProtectionRole())
221                 .setRole(ep.getRole())
222                 .setLocalId(ep.getLocalId())
223                 .build();
224             endPointMap.put(endpoint.key(), endpoint);
225         }
226         return endPointMap;
227     }
228
229     @Override
230     public ListenableFuture<RpcResult<GetConnectivityServiceDetailsOutput>> getConnectivityServiceDetails(
231             GetConnectivityServiceDetailsInput input) {
232         // TODO Auto-generated method stub
233         Uuid serviceUuid = new Uuid(input.getServiceIdOrName());
234         ConnectivityService service = this.tapiContext.getConnectivityService(serviceUuid);
235         if (service == null) {
236             LOG.error("Service {} doesnt exist in tapi context", input.getServiceIdOrName());
237             return RpcResultBuilder.<GetConnectivityServiceDetailsOutput>failed().withError(RpcError.ErrorType.RPC,
238                     "Service doesnt exist in datastore").buildFuture();
239         }
240         return RpcResultBuilder.success(new GetConnectivityServiceDetailsOutputBuilder().setService(
241             new org.opendaylight.yang.gen.v1.urn
242                 .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.details.output.ServiceBuilder(
243                     service).build()).build()).buildFuture();
244     }
245
246     @Override
247     public ListenableFuture<RpcResult<UpdateConnectivityServiceOutput>> updateConnectivityService(
248             UpdateConnectivityServiceInput input) {
249         // TODO Auto-generated method stub. More complicated as it depends on what needs to be updated... left aside
250         return null;
251     }
252
253     @Override
254     public ListenableFuture<RpcResult<GetConnectionDetailsOutput>> getConnectionDetails(
255             GetConnectionDetailsInput input) {
256         // TODO Auto-generated method stub
257         Uuid connectionUuid = new Uuid(UUID.nameUUIDFromBytes(input.getConnectionIdOrName()
258             .getBytes(Charset.forName("UTF-8"))).toString());
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();
264         }
265         return RpcResultBuilder.success(new GetConnectionDetailsOutputBuilder().setConnection(
266                 new ConnectionBuilder(connection).build()).build()).buildFuture();
267     }
268
269     @Override
270     public ListenableFuture<RpcResult<DeleteConnectivityServiceOutput>> deleteConnectivityService(
271             DeleteConnectivityServiceInput input) {
272         //TODO Auto-generated method stub
273         // TODO add try
274         Uuid serviceUuid = new Uuid(input.getServiceIdOrName());
275         this.tapiContext.deleteConnectivityService(serviceUuid);
276         ListenableFuture<RpcResult<ServiceDeleteOutput>> output =
277             this.serviceHandler.serviceDelete(new ServiceDeleteInputBuilder()
278                 .setServiceDeleteReqInfo(new ServiceDeleteReqInfoBuilder()
279                     .setServiceName(input.getServiceIdOrName())
280                     .setTailRetention(ServiceDeleteReqInfo.TailRetention.No)
281                     .build())
282                 .setSdncRequestHeader(new SdncRequestHeaderBuilder()
283                     .setRequestId("request-1")
284                     .setRpcAction(RpcActions.ServiceDelete)
285                     .setNotificationUrl("notification url")
286                     .setRequestSystemId("appname")
287                     .build())
288                 .build());
289         if (output == null) {
290             return RpcResultBuilder.<DeleteConnectivityServiceOutput>failed().withError(RpcError.ErrorType.RPC,
291                 "Failed to delete Link").buildFuture();
292         }
293         LOG.info("Service is being deleted and devices are being rolled back");
294         return RpcResultBuilder.success(new DeleteConnectivityServiceOutputBuilder().build()).buildFuture();
295     }
296
297     @Override
298     public ListenableFuture<RpcResult<GetConnectivityServiceListOutput>> getConnectivityServiceList(
299             GetConnectivityServiceListInput input) {
300         // TODO Auto-generated method stub
301         Map<ConnectivityServiceKey, ConnectivityService> connMap = this.tapiContext.getConnectivityServices();
302         if (connMap == null) {
303             LOG.error("No services in tapi context");
304             return RpcResultBuilder.<GetConnectivityServiceListOutput>failed().withError(RpcError.ErrorType.RPC,
305                     "No services exist in datastore").buildFuture();
306         }
307
308         Map<ServiceKey, Service> serviceMap = new HashMap<>();
309         for (ConnectivityService connectivityService: connMap.values()) {
310             Service service = new org.opendaylight.yang.gen.v1.urn
311                 .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.ServiceBuilder(
312                     connectivityService).build();
313             serviceMap.put(service.key(), service);
314         }
315         return RpcResultBuilder.success(new GetConnectivityServiceListOutputBuilder().setService(serviceMap)
316             .build()).buildFuture();
317     }
318
319     @Override
320     public ListenableFuture<RpcResult<GetConnectionEndPointDetailsOutput>> getConnectionEndPointDetails(
321             GetConnectionEndPointDetailsInput input) {
322         // TODO Auto-generated method stub
323         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(input.getTopologyIdOrName()
324             .getBytes(Charset.forName("UTF-8"))).toString());
325         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNodeIdOrName()
326             .getBytes(Charset.forName("UTF-8"))).toString());
327         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNepIdOrName()
328             .getBytes(Charset.forName("UTF-8"))).toString());
329         Uuid cepUuid = new Uuid(UUID.nameUUIDFromBytes(input.getCepIdOrName()
330             .getBytes(Charset.forName("UTF-8"))).toString());
331         ConnectionEndPoint cep = this.tapiContext.getTapiCEP(topoUuid, nodeUuid, nepUuid, cepUuid);
332         if (cep == null) {
333             LOG.error("Cep doesnt exist in tapi context");
334             return RpcResultBuilder.<GetConnectionEndPointDetailsOutput>failed().withError(RpcError.ErrorType.RPC,
335                     "No cep with given Uuid exists in datastore").buildFuture();
336         }
337         return RpcResultBuilder.success(new GetConnectionEndPointDetailsOutputBuilder().setConnectionEndPoint(
338             new ConnectionEndPointBuilder(cep).build()).build()).buildFuture();
339     }
340 }