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";
58 private static final String OS_NAME = "os.name";
59 private static final String WINDOWS = "windows";
61 private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
63 private static final String SEPARATOR = "__";
65 private enum SearchMode {
67 FILE //for developer mode
72 private static SearchMode searchMode = SearchMode.FILE;
74 String mode = OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_EXECUTION_SEARCH_MODE);
75 if (mode.equalsIgnoreCase(SearchMode.FIND.name()))
76 searchMode = SearchMode.FIND;
79 public static class ExecutionStoreContext {
80 private String requestId;
81 private String executionId;
82 private String profile;
83 private String storePath;
84 public String getExecutionId() {
87 public ExecutionStoreContext setExecutionId(String executionId) {
88 this.executionId = executionId;
91 public String getStorePath() {
94 public ExecutionStoreContext setStorePath(String storePath) {
95 this.storePath = storePath;
98 public String getRequestId() {
101 public ExecutionStoreContext setRequestId(String requestId) {
102 this.requestId = requestId;
105 public String getProfile() {
108 public void setProfile(String profile) {
109 this.profile = profile;
113 public static class Execution {
115 private String requestId;
116 private String status;
117 private String startTime;
118 private String endTime;
119 private String input;
120 private String output;
121 private String profile;
122 private String command;
123 private String product;
124 private String service;
126 public String getInput() {
129 public void setInput(String input) {
132 public String getOutput() {
135 public void setOutput(String output) {
136 this.output = output;
138 public String getProfile() {
141 public void setProfile(String profile) {
142 this.profile = profile;
144 public String getCommand() {
147 public void setCommand(String command) {
148 this.command = command;
150 public String getProduct() {
153 public void setProduct(String product) {
154 this.product = product;
156 public String getService() {
159 public void setService(String service) {
160 this.service = service;
162 public String getId() {
165 public void setId(String id) {
168 public String getEndTime() {
171 public void setEndTime(String endTime) {
172 this.endTime = endTime;
174 public void setStartTime(String timeOfExecution) {
175 this.startTime = timeOfExecution;
177 public String getStartTime() {
180 public String getStatus() {
183 public void setStatus(String status) {
184 this.status = status;
186 public String getRequestId() {
189 public void setRequestId(String requestId) {
190 this.requestId = requestId;
196 FileUtils.forceMkdir(new File(getBasePath()));
198 } catch (IOException e) {
199 log.error("Failed to create the data store results");
203 private static OnapCommandExecutionStore store = null;
205 private OnapCommandExecutionStore() {
206 this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
209 public static OnapCommandExecutionStore getStore() {
211 store = new OnapCommandExecutionStore();
217 private static String getBasePath() {
218 return OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_DATA_DIR) +
219 File.separator + "executions";
222 public ExecutionStoreContext storeExectutionStart(
223 String requestId, String product, String service, String cmd, String profile, String input) {
225 ExecutionStoreContext context = new ExecutionStoreContext();
226 context.setRequestId(requestId);
228 String executionId = requestId + "-" + System.currentTimeMillis();
229 context.setExecutionId(executionId);
231 String storePath = getBasePath() + File.separator + executionId + SEPARATOR + product +
232 SEPARATOR + service +
234 SEPARATOR + (profile != null ? profile : "" );
237 File dir = new File(storePath);
238 FileUtils.forceMkdir(dir);
239 context.setStorePath(dir.getAbsolutePath());
242 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.INFO_PRODUCT), product);
244 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.INFO_SERVICE), service);
246 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.RPC_CMD), cmd);
248 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + REQUEST_ID), requestId);
250 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + EXECUTION_ID), executionId);
253 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + INPUT), input);
254 if (profile != null) {
255 context.setProfile(profile);
256 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OnapCommandConstants.RPC_PROFILE), profile);
259 FileUtils.touch(new File(context.getStorePath() + File.separator + STDOUT));
260 FileUtils.touch(new File(context.getStorePath() + File.separator + STDERR));
261 FileUtils.touch(new File(context.getStorePath() + File.separator + DEBUG));
263 FileUtils.touch(new File(context.getStorePath() + File.separator + IN_PROGRESS));
264 } catch (IOException e) {
265 log.error("Failed to store the execution start details {}", storePath);
271 public void storeExectutionEnd(
272 ExecutionStoreContext context,
273 String output, String error, String debug, boolean passed) {
277 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
279 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + ERROR), error);
281 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
283 FileUtils.touch(new File(context.getStorePath() + File.separator + COMPLETED));
285 FileUtils.touch(new File(context.getStorePath() + File.separator + FAILED));
286 Path path= Paths.get(context.getStorePath() + File.separator + IN_PROGRESS);
287 deleteFile(context, path);
288 } catch (IOException e) {
289 log.error("Failed to store the execution end details {}", context.storePath);
293 private void deleteFile(ExecutionStoreContext context, Path path){
296 } catch (IOException e) {
297 String contextPath = context.getStorePath() + File.separator + IN_PROGRESS;
298 log.error("Failed to delete {}", contextPath);
302 public void storeExectutionProgress(
303 ExecutionStoreContext context,
304 String output, String error, String debug) {
308 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
310 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + ERROR), error);
312 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
313 } catch (IOException e) {
314 log.error("Failed to store the execution end details {}", context.storePath);
318 public void storeExectutionDebug(
319 ExecutionStoreContext context,
324 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
326 } catch (IOException e) {
327 log.error("Failed to store the execution debug details {}", context.storePath);
331 public void storeExectutionOutput(
332 ExecutionStoreContext context,
336 if (output != null) {
337 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
339 } catch (IOException e) {
340 log.error("Failed to store the execution output details {}", context.storePath);
344 public List <String> listExecutionsWindows(Map<String, String> search, List <String> dirs){
345 for (File f: new File(getBasePath()).listFiles()) {
346 if(search.containsKey(EXECUTIONID)) {
347 if (f.getName().startsWith(search.get(EXECUTIONID)))
348 dirs.add(f.getAbsolutePath());
353 if(search.containsKey(REQUESTID)) {
354 if (f.getName().startsWith(search.get(REQUESTID)))
355 dirs.add(f.getAbsolutePath());
360 dirs.add(f.getAbsolutePath());
365 public List <String> searchAndListExecutions(Map<String, String> search, List <String> dirs) throws OnapCommandExecutionFailed, IOException, InterruptedException {
366 StringBuilder searchString = new StringBuilder("find " + new File(getBasePath()).getAbsolutePath() + " -type d ");
368 String startTime = search.get("startTime");
369 if (startTime != null) {
370 searchString.append(" -newermt " + startTime);
373 String endTime = search.get("endTime");
374 if (endTime != null) {
375 searchString.append(" ! -newermt " + endTime);
378 searchString.append(" -name \"");
380 if(search.containsKey(EXECUTIONID)) {
381 searchString.append(search.get(EXECUTIONID));
382 } else if(search.containsKey(REQUESTID)) {
383 searchString.append(search.get(REQUESTID) + "*");
385 searchString.append("*");
388 for (String term: Arrays.asList("product", "service", "command", "profile")) {
389 searchString.append("__");
390 if (search.get(term) != null && !search.get(term).isEmpty()) {
391 searchString.append(search.get(term));
393 searchString.append("*");
396 if (!searchString.toString().endsWith("*"))
397 searchString.append("*");
399 searchString.append("\"");
401 ProcessRunner pr = new ProcessRunner(new String [] {searchString.toString()}, null, ".");
402 pr.setTimeout(10000);
405 if (pr.getExitCode() != 0) {
406 throw new OnapCommandExecutionFailed("System failed to search the executions with error " + pr.getError());
409 if (!pr.getOutput().trim().isEmpty())
410 dirs = Arrays.asList(pr.getOutput().split("\\r?\\n"));
415 public List<OnapCommandExecutionStore.Execution> listExecutions(Map<String, String> search) throws OnapCommandExecutionFailed {
416 List <OnapCommandExecutionStore.Execution> list = new ArrayList<>();
419 List <String> dirs = new ArrayList<>();
420 if (System.getProperty(OS_NAME).toLowerCase().startsWith(WINDOWS) || searchMode.equals(SearchMode.FILE)) {
421 dirs = listExecutionsWindows(search, dirs);
423 //find results -type d -newermt '2019-02-11 10:00:00' ! -newermt '2019-02-11 15:10:00' -name "*__*__profile-list*"
424 //find 'results' -type d -newermt '2019-02-11T10:00:00.000' ! -newermt '2019-02-11T15:10:00.000' -name "*__*__profile*"
425 dirs = searchAndListExecutions(search, dirs);
428 for (String dir: dirs) {
429 list.add(this.makeExecution(dir));
431 } catch (Exception e) {// NOSONAR
432 throw new OnapCommandExecutionFailed(e, "Failed to search the executions");
438 private Execution makeExecution(String executionStorePath) throws IOException {
439 OnapCommandExecutionStore.Execution exectuion = new OnapCommandExecutionStore.Execution();
440 if (new File(executionStorePath + File.separator + REQUEST_ID).exists())
441 exectuion.setRequestId(FileUtils.readFileToString(new File(executionStorePath + File.separator + REQUEST_ID)));
442 if (new File(executionStorePath + File.separator + EXECUTION_ID).exists())
443 exectuion.setId(FileUtils.readFileToString(new File(executionStorePath + File.separator + EXECUTION_ID)));
444 exectuion.setProduct(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_PRODUCT)));
445 exectuion.setService(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_SERVICE)));
446 exectuion.setCommand(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_CMD)));
447 if (new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE).exists())
448 exectuion.setProfile(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE)));
450 exectuion.setInput(FileUtils.readFileToString(new File(executionStorePath + File.separator + INPUT)));
451 exectuion.setStartTime(dateFormatter.format(new File(executionStorePath + File.separator + INPUT).lastModified()));
453 if (new File(executionStorePath + File.separator + IN_PROGRESS).exists()) {
454 exectuion.setStatus(IN_PROGRESS);
455 } else if (new File(executionStorePath + File.separator + COMPLETED).exists()) {
456 exectuion.setStatus(COMPLETED);
457 if (new File(executionStorePath + File.separator + OUTPUT).exists()) {
458 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + OUTPUT)));
459 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + OUTPUT).lastModified()));
461 } else if (new File(executionStorePath + File.separator + FAILED).exists()) {
462 exectuion.setStatus(FAILED);
463 if (new File(executionStorePath + File.separator + ERROR).exists()) {
464 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + ERROR)));
465 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + ERROR).lastModified()));
472 private File getExecutionDir(String executionId) throws OnapCommandExecutionNotFound {
473 File []f = new File(getBasePath()).listFiles((dir, name) -> {
474 return name.startsWith(executionId);
478 throw new OnapCommandExecutionNotFound(executionId);
484 public String showExecutionOut(String executionId) throws OnapCommandExecutionNotFound {
486 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + STDOUT));
487 } catch (IOException e) {
492 public String showExecutionErr(String executionId) throws OnapCommandExecutionNotFound {
494 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + STDERR));
495 } catch (IOException e) {
500 public String showExecutionDebug(String executionId) throws OnapCommandExecutionNotFound {
502 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + DEBUG));
503 } catch (IOException e) {
507 public Execution getExecution(String executionId) throws OnapCommandExecutionNotFound, OnapCommandExecutionFailed {
509 return this.makeExecution(this.getExecutionDir(executionId).getAbsolutePath());
510 } catch (IOException e) {
511 throw new OnapCommandExecutionFailed(e, "Failed to retrieve the execution");