JsonStringConverter in GNPy
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / gnpy / GnpyUtilitiesImpl.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
9 package org.opendaylight.transportpce.pce.gnpy;
10
11 import java.io.IOException;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.stream.Collectors;
15 import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
16 import org.opendaylight.transportpce.common.converter.JsonStringConverter;
17 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
18 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
19 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi;
20 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApiBuilder;
21 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.ServiceFileBuilder;
22 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.TopologyFileBuilder;
23 import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Connections;
24 import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Elements;
25 import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathRouteObjects;
26 import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequest;
27 import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.Synchronization;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.PathComputationRequestInput;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.AToZDirection;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.AToZDirectionBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.ZToADirection;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.routing.constraints.sp.HardConstraints;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.opendaylight.yangtools.yang.common.Uint32;
35 import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Class that implements the functions asked to gnpy.
41  *
42  * @author Ahmed Triki ( ahmed.triki@orange.com )
43  *
44  */
45
46 public class GnpyUtilitiesImpl {
47
48     private static final Logger LOG = LoggerFactory.getLogger(GnpyUtilitiesImpl.class);
49     private PathComputationRequestInput input;
50     private GnpyTopoImpl gnpyTopo = null;
51     private GnpyResult gnpyAtoZ;
52     private GnpyResult gnpyZtoA;
53     private Uint32 requestId;
54     private BindingDOMCodecServices bindingDOMCodecServices;
55     private JsonStringConverter<GnpyApi> converter;
56
57
58     public GnpyUtilitiesImpl(NetworkTransactionService networkTransaction, PathComputationRequestInput input,
59             BindingDOMCodecServices bindingDOMCodecServices)
60         throws GnpyException {
61         this.gnpyTopo = new GnpyTopoImpl(networkTransaction);
62         this.input = input;
63         this.gnpyAtoZ = null;
64         this.gnpyZtoA = null;
65         this.requestId = Uint32.valueOf(0);
66         this.bindingDOMCodecServices = bindingDOMCodecServices;
67         this.converter =  new JsonStringConverter<>(bindingDOMCodecServices);
68     }
69
70     public boolean verifyComputationByGnpy(AToZDirection atoz, ZToADirection ztoa, PceConstraints pceHardConstraints)
71         throws GnpyException {
72
73         if (atoz == null || atoz.getAToZ() == null || ztoa == null || ztoa.getZToA() == null) {
74             throw new GnpyException("In GnpyUtilities: the path transmitted to Gnpy is null");
75         }
76
77         GnpyServiceImpl gnpySvc1 = new GnpyServiceImpl(input, atoz, requestId, gnpyTopo, pceHardConstraints);
78         this.gnpyAtoZ = gnpyResponseOneDirection(gnpySvc1);
79         boolean isPcePathFeasible = false;
80         isPcePathFeasible = this.gnpyAtoZ.getPathFeasibility();
81         GnpyServiceImpl gnpySvc2 = new GnpyServiceImpl(input, ztoa, requestId, gnpyTopo, pceHardConstraints);
82         this.gnpyZtoA = gnpyResponseOneDirection(gnpySvc2);
83         isPcePathFeasible &= this.gnpyZtoA.getPathFeasibility();
84         return isPcePathFeasible;
85     }
86
87     @SuppressWarnings("checkstyle:illegalcatch")
88     public GnpyResult gnpyResponseOneDirection(GnpyServiceImpl gnpySvc) throws GnpyException {
89         requestId = Uint32.valueOf((requestId.toJava()) + 1);
90         List<PathRequest> pathRequestList = new ArrayList<>(gnpySvc.getPathRequest().values());
91         List<Synchronization> synchronizationList = gnpySvc.getSynchronization();
92         // Send the computed path to GNPY tool
93         List<Elements> elementsList = new ArrayList<>(gnpyTopo.getElements().values());
94         List<Connections> connectionsList = gnpyTopo.getConnections();
95         String gnpyResponse;
96         try {
97             gnpyResponse = getGnpyResponse(elementsList, connectionsList, pathRequestList,
98                 synchronizationList);
99         } catch (Exception e) {
100             throw new GnpyException("Something went wrong", e);
101         }
102         // Analyze the response
103         if (gnpyResponse == null) {
104             throw new GnpyException("In GnpyUtilities: no response from GNPy server");
105         }
106         GnpyResult result = new GnpyResult(gnpyResponse, gnpyTopo, bindingDOMCodecServices);
107         result.analyzeResult();
108         return result;
109     }
110
111     public HardConstraints askNewPathFromGnpy(PceConstraints pceHardConstraints)
112             throws GnpyException {
113
114         AToZDirection atoztmp = new AToZDirectionBuilder()
115             .setRate(input.getServiceAEnd().getServiceRate())
116             .build();
117         GnpyServiceImpl gnpySvc = new GnpyServiceImpl(input, atoztmp, requestId, gnpyTopo, pceHardConstraints);
118         GnpyResult result = gnpyResponseOneDirection(gnpySvc);
119
120         if (result == null) {
121             throw new GnpyException("In GnpyUtilities: no result from the GNPy server");
122         }
123
124         if (!result.getPathFeasibility()) {
125             return null;
126         }
127         List<PathRouteObjects> pathRouteObjectList = result.analyzeResult();
128         return result.computeHardConstraintsFromGnpyPath(pathRouteObjectList);
129     }
130
131     public String getGnpyResponse(List<Elements> elementsList, List<Connections> connectionsList,
132         List<PathRequest> pathRequestList, List<Synchronization> synchronizationList)
133                 throws GnpyException {
134         GnpyApi gnpyApi = new GnpyApiBuilder()
135             .setTopologyFile(
136                 new TopologyFileBuilder()
137                 .setElements(elementsList.stream().collect(Collectors.toMap(Elements::key, element -> element)))
138                 .setConnections(connectionsList).build())
139             .setServiceFile(
140                 new ServiceFileBuilder()
141                 .setPathRequest(pathRequestList.stream()
142                         .collect(Collectors.toMap(PathRequest::key, pathRequest -> pathRequest)))
143                 .build())
144             .build();
145         try {
146             InstanceIdentifier<GnpyApi> idGnpyApi = InstanceIdentifier.builder(GnpyApi.class).build();
147             String gnpyJson = converter.createJsonStringFromDataObject(idGnpyApi, gnpyApi,
148                     JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02);
149             LOG.debug("GNPy Id: {} / json created : {}", idGnpyApi, gnpyJson);
150             ConnectToGnpyServer connect = new ConnectToGnpyServer();
151             String gnpyJsonModified = gnpyJson.replace("gnpy-eqpt-config:", "")
152                     .replace("gnpy-path-computation-simplified:", "").replace("gnpy-network-topology:", "");
153
154             return connect.returnGnpyResponse(gnpyJsonModified);
155         } catch (IOException e) {
156             LOG.error("Cannot convert data object to json string {}", gnpyApi);
157             throw new GnpyException("Cannot convert data object to json string", e);
158         }
159     }
160
161     public GnpyResult getGnpyAtoZ() {
162         return gnpyAtoZ;
163     }
164
165     public GnpyResult getGnpyZtoA() {
166         return gnpyZtoA;
167     }
168 }