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);
285 deleteFile(context, path);
286 } catch (IOException e) {
287 log.error("Failed to store the execution end details {}", context.storePath);
291 private void deleteFile(ExecutionStoreContext context, Path path){
294 } catch (IOException e) {
295 String contextPath = context.getStorePath() + File.separator + IN_PROGRESS;
296 log.error("Failed to delete {}", contextPath);
300 public void storeExectutionProgress(
301 ExecutionStoreContext context,
302 String output, String error, String debug) {
306 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
308 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + ERROR), error);
310 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
311 } catch (IOException e) {
312 log.error("Failed to store the execution end details {}", context.storePath);
316 public void storeExectutionDebug(
317 ExecutionStoreContext context,
322 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + DEBUG), debug);
324 } catch (IOException e) {
325 log.error("Failed to store the execution debug details {}", context.storePath);
329 public void storeExectutionOutput(
330 ExecutionStoreContext context,
334 if (output != null) {
335 FileUtils.writeStringToFile(new File(context.getStorePath() + File.separator + OUTPUT), output);
337 } catch (IOException e) {
338 log.error("Failed to store the execution output details {}", context.storePath);
341 public List<OnapCommandExecutionStore.Execution> listExecutions(Map<String, String> search) throws OnapCommandExecutionFailed {
342 List <OnapCommandExecutionStore.Execution> list = new ArrayList<>();
345 List <String> dirs = new ArrayList<>();
346 if (System.getProperty("os.name").toLowerCase().startsWith("windows") || searchMode.equals(SearchMode.FILE)) {
347 for (File f: new File(getBasePath()).listFiles()) {
348 if(search.containsKey(EXECUTIONID)) {
349 if (f.getName().startsWith(search.get(EXECUTIONID)))
350 dirs.add(f.getAbsolutePath());
355 if(search.containsKey(REQUESTID)) {
356 if (f.getName().startsWith(search.get(REQUESTID)))
357 dirs.add(f.getAbsolutePath());
362 dirs.add(f.getAbsolutePath());
365 //find results -type d -newermt '2019-02-11 10:00:00' ! -newermt '2019-02-11 15:10:00' -name "*__*__profile-list*"
366 //find 'results' -type d -newermt '2019-02-11T10:00:00.000' ! -newermt '2019-02-11T15:10:00.000' -name "*__*__profile*"
368 StringBuilder searchString = new StringBuilder("find " + new File(getBasePath()).getAbsolutePath() + " -type d ");
370 String startTime = search.get("startTime");
371 if (startTime != null) {
372 searchString.append(" -newermt " + startTime);
375 String endTime = search.get("endTime");
376 if (endTime != null) {
377 searchString.append(" ! -newermt " + endTime);
380 searchString.append(" -name \"");
382 if(search.containsKey(EXECUTIONID)) {
383 searchString.append(search.get(EXECUTIONID));
384 } else if(search.containsKey(REQUESTID)) {
385 searchString.append(search.get(REQUESTID) + "*");
387 searchString.append("*");
390 for (String term: Arrays.asList("product", "service", "command", "profile")) {
391 searchString.append("__");
392 if (search.get(term) != null && !search.get(term).isEmpty()) {
393 searchString.append(search.get(term));
395 searchString.append("*");
398 if (!searchString.toString().endsWith("*"))
399 searchString.append("*");
401 searchString.append("\"");
403 ProcessRunner pr = new ProcessRunner(new String [] {searchString.toString()}, null, ".");
404 pr.setTimeout(10000);
407 if (pr.getExitCode() != 0) {
408 throw new OnapCommandExecutionFailed("System failed to search the executions with error " + pr.getError());
411 if (!pr.getOutput().trim().isEmpty())
412 dirs = Arrays.asList(pr.getOutput().split("\\r?\\n"));
415 for (String dir: dirs) {
416 list.add(this.makeExecution(dir));
418 } catch (Exception e) {// NOSONAR
419 throw new OnapCommandExecutionFailed(e, "Failed to search the executions");
425 private Execution makeExecution(String executionStorePath) throws IOException {
426 OnapCommandExecutionStore.Execution exectuion = new OnapCommandExecutionStore.Execution();
427 if (new File(executionStorePath + File.separator + REQUEST_ID).exists())
428 exectuion.setRequestId(FileUtils.readFileToString(new File(executionStorePath + File.separator + REQUEST_ID)));
429 if (new File(executionStorePath + File.separator + EXECUTION_ID).exists())
430 exectuion.setId(FileUtils.readFileToString(new File(executionStorePath + File.separator + EXECUTION_ID)));
431 exectuion.setProduct(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_PRODUCT)));
432 exectuion.setService(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.INFO_SERVICE)));
433 exectuion.setCommand(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_CMD)));
434 if (new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE).exists())
435 exectuion.setProfile(FileUtils.readFileToString(new File(executionStorePath + File.separator + OnapCommandConstants.RPC_PROFILE)));
437 exectuion.setInput(FileUtils.readFileToString(new File(executionStorePath + File.separator + INPUT)));
438 exectuion.setStartTime(dateFormatter.format(new File(executionStorePath + File.separator + INPUT).lastModified()));
440 if (new File(executionStorePath + File.separator + IN_PROGRESS).exists()) {
441 exectuion.setStatus(IN_PROGRESS);
442 } else if (new File(executionStorePath + File.separator + COMPLETED).exists()) {
443 exectuion.setStatus(COMPLETED);
444 if (new File(executionStorePath + File.separator + OUTPUT).exists()) {
445 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + OUTPUT)));
446 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + OUTPUT).lastModified()));
448 } else if (new File(executionStorePath + File.separator + FAILED).exists()) {
449 exectuion.setStatus(FAILED);
450 if (new File(executionStorePath + File.separator + ERROR).exists()) {
451 exectuion.setOutput(FileUtils.readFileToString(new File(executionStorePath + File.separator + ERROR)));
452 exectuion.setEndTime(dateFormatter.format(new File(executionStorePath + File.separator + ERROR).lastModified()));
459 private File getExecutionDir(String executionId) throws OnapCommandExecutionNotFound {
460 File []f = new File(getBasePath()).listFiles((dir, name) -> {
461 return name.startsWith(executionId);
465 throw new OnapCommandExecutionNotFound(executionId);
471 public String showExecutionOut(String executionId) throws OnapCommandExecutionNotFound {
473 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + "stdout"));
474 } catch (IOException e) {
479 public String showExecutionErr(String executionId) throws OnapCommandExecutionNotFound {
481 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + "stderr"));
482 } catch (IOException e) {
487 public String showExecutionDebug(String executionId) throws OnapCommandExecutionNotFound {
489 return FileUtils.readFileToString(new File (this.getExecutionDir(executionId).getAbsolutePath() + File.separator + DEBUG));
490 } catch (IOException e) {
494 public Execution getExecution(String executionId) throws OnapCommandExecutionNotFound, OnapCommandExecutionFailed {
496 return this.makeExecution(this.getExecutionDir(executionId).getAbsolutePath());
497 } catch (IOException e) {
498 throw new OnapCommandExecutionFailed(e, "Failed to retrieve the execution");