blob: 5e485d78995253166e4c6bd0954aafed36044a8b [file] [log] [blame]
Di Qian38c02a72019-11-18 19:14:07 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
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 */
16package com.android.tradefed.cluster;
17
18import com.android.loganalysis.util.ArrayUtil;
19import com.android.tradefed.log.LogUtil.CLog;
20import com.android.tradefed.util.CommandResult;
21import com.android.tradefed.util.CommandStatus;
22import com.android.tradefed.util.FileUtil;
23import com.android.tradefed.util.IRunUtil;
24import com.android.tradefed.util.RunUtil;
25import java.io.File;
26import java.io.IOException;
27import java.net.URL;
28import java.util.List;
29
30/** A class to download test resource files from file system/GCS/HTTP. */
31public class TestResourceDownloader {
32
33 private static final long DOWNLOAD_TIMEOUT_MS = 30 * 60 * 1000;
34 private static final long RETRY_INTERVAL_MS = 10 * 1000;
35 private static final int MAX_RETRY_COUNT = 2;
36
37 private final File mRootDir;
38 private IRunUtil mRunUtil = null;
39
40 public TestResourceDownloader(final File rootDir) {
41 mRootDir = rootDir;
42 }
43
44 public File download(TestResource resource) throws IOException {
45 final URL url = new URL(resource.getUrl());
46 final String protocol = url.getProtocol();
47 final File dest = new File(mRootDir, resource.getName());
48 final File parent = dest.getParentFile();
49 if (!parent.exists()) {
50 parent.mkdirs();
51 }
52 if ("file".equals(protocol)) {
53 final File src = new File(resource.getUrl().substring(6));
54 FileUtil.hardlinkFile(src, dest);
55 return dest;
56 }
57
58 final List<String> cmdArgs = buildDownloadCommandArgs(url, dest);
59 final CommandResult result =
60 getRunUtil()
61 .runTimedCmdRetry(
62 DOWNLOAD_TIMEOUT_MS,
63 RETRY_INTERVAL_MS,
64 MAX_RETRY_COUNT + 1,
65 cmdArgs.toArray(new String[0]));
66 if (!result.getStatus().equals(CommandStatus.SUCCESS)) {
67 final String msg =
68 String.format(
69 "Failed to download %s: command status=%s", url, result.getStatus());
70 CLog.e(msg);
71 CLog.e("stdout:\n'''\n%s'''\n", result.getStdout());
72 CLog.d("stderr:\n'''\n%s'''\n", result.getStderr());
73 throw new RuntimeException(msg);
74 }
75 return dest;
76 }
77
78 /** Build a list of command line arguments to download a file. */
79 private List<String> buildDownloadCommandArgs(URL url, File file) {
80 final String protocol = url.getProtocol();
81 if ("gs".equals(protocol)) {
82 // FIXME: Check whether gsutil is available on a host.
83 return ArrayUtil.list("gsutil", "cp", url.toString(), file.getAbsolutePath());
84 }
85 if ("http".equals(protocol) || "https".equals(protocol)) {
86 // FIXME: Check whether curl is available on a host.
87 // Add -L option to handle redirect.
88 return ArrayUtil.list("curl", "-o", file.getAbsolutePath(), "-fL", url.toString());
89 }
90 throw new UnsupportedOperationException("protocol " + protocol + " is not supported");
91 }
92
93 IRunUtil getRunUtil() {
94 if (mRunUtil == null) {
95 mRunUtil = new RunUtil();
96 }
97 return mRunUtil;
98 }
99}