2 * Copyright 2019 Huawei Technologies Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onap.cli.fw.store;
20 import java.io.IOException;
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.Locale;
30 import java.util.TimeZone;
32 import org.apache.commons.io.FileUtils;
33 import org.onap.cli.fw.conf.OnapCommandConfig;
34 import org.onap.cli.fw.conf.OnapCommandConstants;
35 import org.onap.cli.fw.error.OnapCommandExecutionFailed;
36 import org.onap.cli.fw.error.OnapCommandExecutionNotFound;
37 import org.onap.cli.fw.utils.ProcessRunner;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public class OnapCommandExecutionStore {
42 private static Logger log = LoggerFactory.getLogger(OnapCommandExecutionStore.class);
44 private static boolean storeReady = false; // NOSONAR
45 private static final String REQUEST_ID = "requestId";
46 private static final String EXECUTION_ID = "executionId";
47 private static final String INPUT = "input";
48 private static final String STDOUT = "stdout";
49 private static final String STDERR = "stderr";
50 private static final String DEBUG = "debug";
51 private static final String IN_PROGRESS = "in-progress";
52 private static final String OUTPUT = "output";
53 private static final String ERROR = "error";
54 private static final String COMPLETED = "completed";
55 private static final String FAILED = "failed";
56 private static final String EXECUTIONID = "execution-id";
57 private static final String REQUESTID = "request-id";
59 private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
61 private static final String SEPARATOR = "__";
63 private enum SearchMode {
65 FILE //for developer mode
70 private static SearchMode searchMode = SearchMode.FILE;
72 String mode = OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_EXECUTION_SEARCH_MODE);
73 if (mode.equalsIgnoreCase(SearchMode.FIND.name()))
74 searchMode = SearchMode.FIND;
77 public static class ExecutionStoreContext {
78 private String requestId;
79 private String executionId;
80 private String profile;
81 private String storePath;
82 public String getExecutionId() {
85 public ExecutionStoreContext setExecutionId(String executionId) {
86 this.executionId = executionId;
89 public String getStorePath() {
92 public ExecutionStoreContext setStorePath(String storePath) {
93 this.storePath = storePath;
96 public String getRequestId() {
99 public ExecutionStoreContext setRequestId(String requestId) {
100 this.requestId = requestId;
103 public String getProfile() {
106 public void setProfile(String profile) {
107 this.profile = profile;
111 public static class Execution {
113 private String requestId;
114 private String status;
115 private String startTime;
116 private String endTime;
117 private String input;
118 private String output;
119 private String profile;
120 private String command;
121 private String product;
122 private String service;
124 public String getInput() {
127 public void setInput(String input) {
130 public String getOutput() {
133 public void setOutput(String output) {
134 this.output = output;
136 public String getProfile() {
139 public void setProfile(String profile) {
140 this.profile = profile;
142 public String getCommand() {
145 public void setCommand(String command) {
146 this.command = command;
148 public String getProduct() {
151 public void setProduct(String product) {
152 this.product = product;
154 public String getService() {
157 public void setService(String service) {
158 this.service = service;
160 public String getId() {
163 public void setId(String id) {
166 public String getEndTime() {
169 public void setEndTime(String endTime) {
170 this.endTime = endTime;
172 public void setStartTime(String timeOfExecution) {
173 this.startTime = timeOfExecution;
175 public String getStartTime() {
178 public String getStatus() {
181 public void setStatus(String status) {
182 this.status = status;
184 public String getRequestId() {
187 public void setRequestId(String requestId) {
188 this.requestId = requestId;
194 FileUtils.forceMkdir(new File(getBasePath()));
196 } catch (IOException e) {
197 log.error("Failed to create the data store results");
201 private static OnapCommandExecutionStore store = null;
203 private OnapCommandExecutionStore() {
204 this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
207 public static OnapCommandExecutionStore getStore() {
209 store = new OnapCommandExecutionStore();
215 private static String getBasePath() {
216 return OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_DATA_DIR) +
217 File.separator + "executions";
220 public ExecutionStoreContext storeExectutionStart(
221 String requestId, String product, String service, String cmd, String profile, String input) {
223 ExecutionStoreContext context = new ExecutionStoreContext();
224 context.setRequestId(requestId);
226 String executionId = requestId + "-" + System.currentTimeMillis();
227 context.setExecutionId(executionId);
229 String storePath = getBasePath() + File.separator + executionId + SEPARATOR + product +
230 SEPARATOR + service +
232 SEPARATOR + (profile != null ? profile : "" );
235 File dir = new File(storePath);
236 FileUtils.forceMkdir(dir);
237 context.setStorePath(dir.getAbsolutePath());
240 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.INFO_PRODUCT), product);
242 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.INFO_SERVICE), service);
244 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.RPC_CMD), cmd);
246 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + REQUEST_ID), requestId);
248 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + EXECUTION_ID), executionId);
251 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + INPUT), input);
252 if (profile != null) {
253 context.setProfile(profile);
254 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.RPC_PROFILE), profile);
257 FileUtils.touch(new File(context.getStorePath() + File.separator + STDOUT));
258 FileUtils.touch(new File(context.getStorePath() + File.separator + STDERR));
259 FileUtils.touch(new File(context.getStorePath() + File.separator + DEBUG));
261 FileUtils.touch(new File(context.getStorePath() + File.separator + IN_PROGRESS));
262 } catch (IOException e) {
263 log.error("Failed to store the execution start details {}", storePath);
269 public void storeExectutionEnd(
270 ExecutionStoreContext context,
271 String output, String error, String debug, boolean passed) {
275 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
277 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + ERROR), error);
279 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
281 FileUtils.touch(new File(context.getStorePath() + File.separator + COMPLETED));
283 FileUtils.touch(new File(context.getStorePath() + File.separator + FAILED));
284 Path path= Paths.get(context.getStorePath() + File.separator + IN_PROGRESS);
287 } catch (IOException e) {
288 log.error("Failed to delete "+ context.getStorePath() + File.separator + IN_PROGRESS);
290 } catch (IOException e) {
291 log.error("Failed to store the execution end details {}", context.storePath);
295 public void storeExectutionProgress(
296 ExecutionStoreContext context,
297 String output, String error, String debug) {
301 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
303 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + ERROR), error);
305 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
306 } catch (IOException e) {
307 log.error("Failed to store the execution end details {}", context.storePath);
311 public void storeExectutionDebug(
312 ExecutionStoreContext context,
317 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
319 } catch (IOException e) {
320 log.error("Failed to store the execution debug details {}", context.storePath);
324 public void storeExectutionOutput(
325 ExecutionStoreContext context,
329 if (output != null) {
330 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
332 } catch (IOException e) {
333 log.error("Failed to store the execution output details {}", context.storePath);
336 public List<OnapCommandExecutionStore.Execution> listExecutions(Map<String, String> search) throws OnapCommandExecutionFailed {
337 List <OnapCommandExecutionStore.Execution> list = new ArrayList<>();
340 List <String> dirs = new ArrayList<>();
341 if (System.getProperty("os.name").toLowerCase().startsWith("windows") || searchMode.equals(SearchMode.FILE)) {
342 for (File f: new File(getBasePath()).listFiles()) {
343 if(search.containsKey(EXECUTIONID)) {
344 if (f.getName().startsWith(search.get(EXECUTIONID)))
345 dirs.add(f.getAbsolutePath());
350 if(search.containsKey(REQUESTID)) {
351 if (f.getName().startsWith(search.get(REQUESTID)))
352 dirs.add(f.getAbsolutePath());
357 dirs.add(f.getAbsolutePath());
360 //find results -type d -newermt '2019-02-11 10:00:00' ! -newermt '2019-02-11 15:10:00' -name "*__*__profile-list*"
361 //find 'results' -type d -newermt '2019-02-11T10:00:00.000' ! -newermt '2019-02-11T15:10:00.000' -name "*__*__profile*"
363 StringBuilder searchString = new StringBuilder("find " + new File(getBasePath()).getAbsolutePath() + " -type d ");
365 String startTime = search.get("startTime");
366 if (startTime != null) {
367 searchString.append(" -newermt " + startTime);
370 String endTime = search.get("endTime");
371 if (endTime != null) {
372 searchString.append(" ! -newermt " + endTime);
375 searchString.append(" -name \"");
377 if(search.containsKey(EXECUTIONID)) {
378 searchString.append(search.get(EXECUTIONID));
379 } else if(search.containsKey(REQUESTID)) {
380 searchString.append(search.get(REQUESTID) + "*");
382 searchString.append("*");
385 for (String term: Arrays.asList("product", "service", "command", "profile")) {
386 searchString.append("__");
387 if (search.get(term) != null && !search.get(term).isEmpty()) {
388 searchString.append(search.get(term));
390 searchString.append("*");
393 if (!searchString.toString().endsWith("*"))
394 searchString.append("*");
396 searchString.append("\"");
398 ProcessRunner pr = new ProcessRunner(new String [] {searchString.toString()}, null, ".");
399 pr.setTimeout(10000);
402 if (pr.getExitCode() != 0) {
403 throw new OnapCommandExecutionFailed("System failed to search the executions with error " + pr.getError());
406 if (!pr.getOutput().trim().isEmpty())
407 dirs = Arrays.asList(pr.getOutput().split("\\r?\\n"));
410 for (String dir: dirs) {
411 list.add(this.makeExecution(dir));
413 } catch (Exception e) {
414 throw new OnapCommandExecutionFailed(e, "Failed to search the executions");
420 private Execution makeExecution(String executionStorePath) throws IOException {
421 OnapCommandExecutionStore.Execution exectuion = new OnapCommandExecutionStore.Execution();
422 if (new File(executionStorePath + File.separator + REQUEST_ID).exists())
423 exectuion.setRequestId(FileUtils.readFileToString(new File(executionStorePath + File.separator + REQUEST_ID)));
424 if (new File(executionStorePath + File.separator + EXECUTION_ID).exists())
425 exectuion.setId(FileUtils.readFileToString(new File(executionStorePath + File.separator + EXECUTION_ID)));
426 exectuion.setProduct(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_PRODUCT)));
427 exectuion.setService(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_SERVICE)));
428 exectuion.setCommand(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_CMD)));
429 if (new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE).exists())
430 exectuion.setProfile(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE)));
432 exectuion.setInput(FileUtils.readFileToString(new File(executionStorePath + File.separator + INPUT)));
433 exectuion.setStartTime(dateFormatter.format(new File(executionStorePath + File.separator + INPUT).lastModified()));
435 if (new File(executionStorePath + File.separator + IN_PROGRESS).exists()) {
436 exectuion.setStatus(IN_PROGRESS);
437 } else if (new File(executionStorePath + File.separator + COMPLETED).exists()) {
438 exectuion.setStatus(COMPLETED);
439 if (new File(executionStorePath + File.separator + OUTPUT).exists()) {
440 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + OUTPUT)));
441 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + OUTPUT).lastModified()));
443 } else if (new File(executionStorePath + File.separator + FAILED).exists()) {
444 exectuion.setStatus(FAILED);
445 if (new File(executionStorePath + File.separator + ERROR).exists()) {
446 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + ERROR)));
447 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + ERROR).lastModified()));
454 private File getExecutionDir(String executionId) throws OnapCommandExecutionNotFound {
455 File []f = new File(getBasePath()).listFiles((dir, name) -> {
456 if (name.startsWith(executionId)) return true;
461 throw new OnapCommandExecutionNotFound(executionId);
467 public String showExecutionOut(String executionId) throws OnapCommandExecutionNotFound {
469 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + "stdout"));
470 } catch (IOException e) {
475 public String showExecutionErr(String executionId) throws OnapCommandExecutionNotFound {
477 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + "stderr"));
478 } catch (IOException e) {
483 public String showExecutionDebug(String executionId) throws OnapCommandExecutionNotFound {
485 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + DEBUG));
486 } catch (IOException e) {
490 public Execution getExecution(String executionId) throws OnapCommandExecutionNotFound, OnapCommandExecutionFailed {
492 return this.makeExecution(this.getExecutionDir(executionId).getAbsolutePath());
493 } catch (IOException e) {
494 throw new OnapCommandExecutionFailed(e, "Failed to retrieve the execution");