ba9920cb28751338a34e4951effa9f7d9b9b3c6a
[cli.git] / grpc / grpc-server / src / main / java / org / open / infc / grpc / server / OpenInterfaceGrpcServer.java
1 /*
2  * Copyright 2018 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.open.infc.grpc.server;
18
19 import java.io.IOException;
20 import java.net.InetAddress;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26
27 import org.onap.cli.fw.cmd.OnapCommand;
28 import org.onap.cli.fw.conf.OnapCommandConfig;
29 import org.onap.cli.fw.conf.OnapCommandConstants;
30 import org.onap.cli.fw.error.OnapCommandException;
31 import org.onap.cli.fw.input.OnapCommandParameter;
32 import org.onap.cli.fw.input.OnapCommandParameterType;
33 import org.onap.cli.fw.output.OnapCommandResultType;
34 import org.onap.cli.fw.registrar.OnapCommandRegistrar;
35 import org.onap.cli.fw.store.OnapCommandExecutionStore;
36 import org.onap.cli.fw.store.OnapCommandExecutionStore.ExecutionStoreContext;
37 import org.onap.cli.main.OnapCli;
38 import org.onap.cli.main.utils.OnapCliArgsParser;
39 import org.open.infc.grpc.Args;
40 import org.open.infc.grpc.Input;
41 import org.open.infc.grpc.OpenInterfaceGrpc;
42 import org.open.infc.grpc.Output;
43 import org.open.infc.grpc.Output.Builder;
44 import org.open.infc.grpc.Result;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import com.google.gson.JsonParser;
49
50 import io.grpc.Server;
51 import io.grpc.ServerBuilder;
52 import io.grpc.stub.StreamObserver;
53
54 public class OpenInterfaceGrpcServer {
55
56       private static final Logger logger = LoggerFactory.getLogger(OpenInterfaceGrpcServer.class.getName());
57
58       private static final String CONF_FILE = "oclip-grpc-server.properties";
59       private static final String CONF_SERVER_PORT = "oclip.grpc_server_port";
60       private static final String CONF_SERVER_HOST = "oclip.grpc_server_host";
61
62       static {
63           OnapCommandConfig.addProperties(CONF_FILE);
64       }
65       private Server server;
66
67       private void start(String portArg) throws IOException {
68         /* The port on which the server should run */
69         int port = Integer.parseInt(portArg == null ? OnapCommandConfig.getPropertyValue(CONF_SERVER_PORT) : portArg);
70         String host = OnapCommandConfig.getPropertyValue(CONF_SERVER_HOST);
71         if (host == null) {
72             host = InetAddress.getLocalHost().getHostAddress().trim();
73         }
74         server = ServerBuilder.forPort(port)
75             .addService(new OpenInterfaceGrpcImpl())
76             .build()
77             .start();
78         logger.info("Server started, listening on {}", port);
79
80         try {
81             OnapCommandRegistrar.getRegistrar().setHost(host);
82             OnapCommandRegistrar.getRegistrar().setPort(port);
83         } catch (OnapCommandException e) {
84             //Never Occurs
85         }
86
87         Runtime.getRuntime().addShutdownHook(new Thread() {
88           @Override
89           public void run() {
90             // Use stderr here since the logger may have been reset by its JVM shutdown hook.
91             System.err.println("*** shutting down gRPC server since JVM is shutting down"); //NOSONAR
92             OpenInterfaceGrpcServer.this.stop();
93             System.err.println("*** server shut down"); //NOSONAR
94           }
95         });
96       }
97
98       private void stop() {
99         if (server != null) {
100           server.shutdown();
101         }
102       }
103
104       /**
105        * Await termination on the main thread since the grpc library uses daemon threads.
106        */
107       private void blockUntilShutdown() throws InterruptedException {
108         if (server != null) {
109           server.awaitTermination();
110         }
111       }
112
113       /**
114        * Main launches the server from the command line.
115        */
116       public static void main(String[] args) throws IOException, InterruptedException {
117         final OpenInterfaceGrpcServer server = new OpenInterfaceGrpcServer();
118         server.start(args.length ==1 ? args[0] : null); //NOSONAR
119         server.blockUntilShutdown();
120       }
121
122       static class OpenRemoteCli extends OnapCli {
123           public OpenRemoteCli(String[] args) {
124             super(args);
125         }
126
127         private String outputs = "";
128
129           @Override
130           public void print(String msg) {
131               outputs += msg + "\n";
132           }
133
134           public String getResult() {
135               return outputs;
136           }
137       }
138
139       static class OpenInterfaceGrpcImpl extends OpenInterfaceGrpc.OpenInterfaceImplBase {
140
141         @Override
142         public void invoke(Input req, StreamObserver<Output> responseObserver) {
143             Output output = null;
144             logger.info("{}", req);
145
146             String product = req.getOptionsMap().get(OnapCommandConstants.RPC_PRODUCT);
147             String format =  req.getOptionsMap().getOrDefault(OnapCommandConstants.DEFAULT_PARAMETER_OUTPUT_FORMAT, OnapCommandResultType.JSON.name().toLowerCase());
148             String commandName = req.getAction();
149             String profile = req.getOptionsMap().get(OnapCommandConstants.RPC_PROFILE);
150             OnapCommand cmd = null;
151
152             ExecutionStoreContext executionStoreContext = null;
153             try {
154                 cmd = OnapCommandRegistrar.getRegistrar().get(commandName, product);
155                 cmd.getParametersMap().get(OnapCommandConstants.DEFAULT_PARAMETER_OUTPUT_FORMAT).setValue(format);
156
157                 if (!cmd.isRpc()) {
158                     if (profile != null) {
159                         //Set the profile to current one
160                         OnapCommandRegistrar.getRegistrar().setProfile(
161                                 profile,
162                                 new ArrayList<>(),
163                                 new ArrayList<>());
164
165                         //fill from profile
166                         Map<String, String> cache= OnapCommandRegistrar.getRegistrar().getParamCache(product);
167                         for (OnapCommandParameter param: cmd.getParameters()) {
168                             if (cache.containsKey(
169                                     cmd.getInfo().getService() + ":" + cmd.getName() + ":" + param.getLongOption())) {
170                                 param.setValue(cache.get(
171                                         cmd.getInfo().getService() + ":" + cmd.getName() + ":" + param.getLongOption()));
172                             } else if (cache.containsKey(
173                                     cmd.getInfo().getService() + ":" + param.getLongOption())) {
174                                 param.setValue(cache.get(
175                                         cmd.getInfo().getService() + ":" + param.getLongOption()));
176                             } else if (cache.containsKey(param.getLongOption())) {
177                                 param.setValue(cache.get(param.getLongOption()));
178                             }
179                         }
180                     }
181
182                     Set <String> params = cmd.getParametersMap().keySet();
183                     for (Entry<String, String> arg: req.getParamsMap().entrySet()) {
184                         if (params.contains(arg.getKey()))
185                             cmd.getParametersMap().get(arg.getKey()).setValue(arg.getValue());
186                     }
187
188                     //fill values from the file, if needed
189                     for (OnapCommandParameter param: cmd.getParameters()) {
190                         if (param.getParameterType().equals(OnapCommandParameterType.JSON)) {
191                             param.setValue(OnapCliArgsParser.readJsonStringFromUrl(param.getValue().toString(), param.getName()));
192
193                         } else if (param.getParameterType().equals(OnapCommandParameterType.TEXT)) {
194                             param.setValue(OnapCliArgsParser.readTextStringFromUrl(param.getValue().toString(), param.getName()));
195
196                         } else if (param.getParameterType().equals(OnapCommandParameterType.BYTE)) {
197                             param.setValue(OnapCliArgsParser.readBytesFromUrl(param.getValue().toString(), param.getName()));
198
199                         } else if (param.getParameterType().equals(OnapCommandParameterType.YAML)) {
200                             param.setValue(OnapCliArgsParser.readYamlStringFromUrl(param.getValue().toString(), param.getName()));
201
202                         }
203                     }
204
205                 } else {
206                     cmd.getParametersMap().get(OnapCommandConstants.INFO_PRODUCT).setValue(product);
207
208                     if (profile != null)
209                         cmd.getParametersMap().get(OnapCommandConstants.RPC_PROFILE).setValue(profile);
210
211                     cmd.getParametersMap().get(OnapCommandConstants.RPC_CMD).setValue(commandName);
212                     cmd.getParametersMap().get(OnapCommandConstants.RPC_ARGS).setValue(req.getParamsMap());
213                     cmd.getParametersMap().get(OnapCommandConstants.RPC_MODE).setValue(OnapCommandConstants.RPC_MODE_RUN_RPC);
214                 }
215
216                     //Start the execution
217                         if (!cmd.isRpc()&&req.getRequestId() != null && !req.getRequestId().isEmpty() && !(cmd.getInfo().getProduct().equalsIgnoreCase("open-cli") &&
218                                 cmd.getName().equalsIgnoreCase("execution-list"))) {
219                         String input = cmd.getArgsJson(true);
220                         executionStoreContext = OnapCommandExecutionStore.getStore().storeExectutionStart(
221                                 req.getRequestId(),
222                                 cmd.getInfo().getProduct(),
223                                 cmd.getInfo().getService(),
224                                 cmd.getName(),
225                                 profile,
226                                 input);
227                         }
228                 cmd.setExecutionContext(executionStoreContext);
229                 cmd.execute();
230
231                 if (!cmd.isRpc()) {
232                     //Track and/or persist the execution context
233                     new OnapCli().handleTracking(cmd);
234
235                     String printOut = cmd.getResult().print();
236                     Builder reply = Output.newBuilder();
237                     reply.putAttrs(OnapCommandConstants.ERROR, "{}");
238
239                     if (executionStoreContext != null)
240                         reply.putAddons("execution-id", executionStoreContext.getExecutionId());
241
242                     // use the status from the plugin.
243                     reply.setSuccess(cmd.getResult().isPassed());
244
245                     setOutputAttr(reply, printOut);
246
247                     output = reply.build();
248                     logger.info("{}", output);
249                 } else {
250                     //Rpc command will set the output.
251                     output = (Output) cmd.getResult().getOutput();
252                 }
253
254             } catch (OnapCommandException e) {
255                 logger.info(e.getMessage());
256
257                 Builder reply = Output.newBuilder();
258                 reply.putAttrs(OnapCommandConstants.RESULTS, "{}");
259                 reply.setSuccess(false);
260                 reply.putAttrs(OnapCommandConstants.ERROR, e.toJsonString());
261                 if (executionStoreContext != null) {
262                        OnapCommandExecutionStore.getStore().storeExectutionEnd(
263                                 executionStoreContext,
264                                 null,
265                                 e.getMessage(),
266                                 cmd.getResult().getDebugInfo(),
267                                 false);
268                       reply.putAddons("execution-id", executionStoreContext.getExecutionId());
269                 }
270
271                 output = reply.build();
272             }
273
274             responseObserver.onNext(output);
275             responseObserver.onCompleted();
276         }
277
278         public static void setOutputAttr(Builder reply, String printOut){
279             try {
280                 reply.putAttrs(OnapCommandConstants.RESULTS, new JsonParser().parse(printOut).toString());
281             } catch (Exception e) { // NOSONAR
282                 reply.putAttrs(OnapCommandConstants.RESULTS, printOut);
283             }
284         }
285
286         @Override
287         public void remoteCli(Args req, StreamObserver<Result> responseObserver) {
288             logger.info("{}", req);
289
290             List<String> args = new ArrayList<>();
291             if (req.getRequestId() != null) {
292                 args.add(OnapCommandParameter.printLongOption(OnapCommandConstants.RPC_REQID));
293                 args.add(req.getRequestId());
294             }
295
296             args.addAll(req.getArgsList());
297             OpenRemoteCli cli = new OpenRemoteCli(args.toArray(new String [] {}));
298             cli.handle();
299             logger.info(cli.getResult());
300             Result reply = Result.newBuilder().setExitCode(cli.getExitCode()).setOutput(cli.getResult()).build();
301             responseObserver.onNext(reply);
302             responseObserver.onCompleted();
303         }
304       }
305 }