1 /* 2 * Copyright (C) 2018 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 */ 16 package com.android.tradefed.device.cloud; 17 18 import com.android.tradefed.device.TestDeviceOptions; 19 import com.android.tradefed.device.cloud.GceRemoteCmdFormatter.ScpMode; 20 import com.android.tradefed.log.LogUtil.CLog; 21 import com.android.tradefed.util.CommandResult; 22 import com.android.tradefed.util.CommandStatus; 23 import com.android.tradefed.util.FileUtil; 24 import com.android.tradefed.util.IRunUtil; 25 26 import java.io.File; 27 import java.io.IOException; 28 import java.util.Arrays; 29 import java.util.List; 30 31 /** Utility class to handle file from a remote instance */ 32 public class RemoteFileUtil { 33 34 /** 35 * Fetch a remote file in the container instance. 36 * 37 * @param remoteInstance The {@link GceAvdInfo} that describe the device. 38 * @param options a {@link TestDeviceOptions} describing the device options to be used for the 39 * GCE device. 40 * @param runUtil a {@link IRunUtil} to execute commands. 41 * @param timeout in millisecond for the fetch to complete 42 * @param remoteFilePath The remote path where to find the file. 43 * @return The pulled filed if successful, null otherwise 44 */ fetchRemoteFile( GceAvdInfo remoteInstance, TestDeviceOptions options, IRunUtil runUtil, long timeout, String remoteFilePath)45 public static File fetchRemoteFile( 46 GceAvdInfo remoteInstance, 47 TestDeviceOptions options, 48 IRunUtil runUtil, 49 long timeout, 50 String remoteFilePath) { 51 String fileName = new File(remoteFilePath).getName(); 52 File localFile = null; 53 try { 54 localFile = 55 FileUtil.createTempFile( 56 FileUtil.getBaseName(fileName) + "_", FileUtil.getExtension(fileName)); 57 if (fetchRemoteFile( 58 remoteInstance, options, runUtil, timeout, remoteFilePath, localFile)) { 59 return localFile; 60 } 61 } catch (IOException e) { 62 CLog.e(e); 63 } 64 FileUtil.deleteFile(localFile); 65 return null; 66 } 67 68 /** 69 * Fetch a remote file in the device or container instance. 70 * 71 * @param remoteInstance The {@link GceAvdInfo} that describe the device. 72 * @param options a {@link TestDeviceOptions} describing the device options to be used for the 73 * GCE device. 74 * @param runUtil a {@link IRunUtil} to execute commands. 75 * @param timeout in millisecond for the fetch to complete 76 * @param remoteFilePath The remote path where to find the file. 77 * @param localFile The local {@link File} where the remote file will be pulled 78 * @return True if successful, False otherwise 79 */ fetchRemoteFile( GceAvdInfo remoteInstance, TestDeviceOptions options, IRunUtil runUtil, long timeout, String remoteFilePath, File localFile)80 public static boolean fetchRemoteFile( 81 GceAvdInfo remoteInstance, 82 TestDeviceOptions options, 83 IRunUtil runUtil, 84 long timeout, 85 String remoteFilePath, 86 File localFile) { 87 return internalScpExec( 88 remoteInstance, 89 options, 90 null, 91 runUtil, 92 timeout, 93 remoteFilePath, 94 localFile, 95 ScpMode.PULL); 96 } 97 98 /** 99 * Fetch a remote directory from the remote host. 100 * 101 * @param remoteInstance The {@link GceAvdInfo} that describe the device. 102 * @param options a {@link TestDeviceOptions} describing the device options to be used for the 103 * GCE device. 104 * @param runUtil a {@link IRunUtil} to execute commands. 105 * @param timeout in millisecond for the fetch to complete 106 * @param remoteDirPath The remote path where to find the directory. 107 * @param localDir The local directory where to put the pulled files. 108 * @return True if successful, False otherwise 109 */ fetchRemoteDir( GceAvdInfo remoteInstance, TestDeviceOptions options, IRunUtil runUtil, long timeout, String remoteDirPath, File localDir)110 public static boolean fetchRemoteDir( 111 GceAvdInfo remoteInstance, 112 TestDeviceOptions options, 113 IRunUtil runUtil, 114 long timeout, 115 String remoteDirPath, 116 File localDir) { 117 return internalScpExec( 118 remoteInstance, 119 options, 120 Arrays.asList("-r"), 121 runUtil, 122 timeout, 123 remoteDirPath, 124 localDir, 125 ScpMode.PULL); 126 } 127 128 /** 129 * Fetch a remote directory from the remote host. 130 * 131 * @param remoteInstance The {@link GceAvdInfo} that describe the device. 132 * @param options a {@link TestDeviceOptions} describing the device options to be used for the 133 * GCE device. 134 * @param runUtil a {@link IRunUtil} to execute commands. 135 * @param timeout in millisecond for the fetch to complete 136 * @param remoteDirPath The remote path where to find the directory. 137 * @return The pulled directory {@link File} if successful, null otherwise 138 */ fetchRemoteDir( GceAvdInfo remoteInstance, TestDeviceOptions options, IRunUtil runUtil, long timeout, String remoteDirPath)139 public static File fetchRemoteDir( 140 GceAvdInfo remoteInstance, 141 TestDeviceOptions options, 142 IRunUtil runUtil, 143 long timeout, 144 String remoteDirPath) { 145 String dirName = new File(remoteDirPath).getName(); 146 File localFile = null; 147 try { 148 localFile = FileUtil.createTempDir(dirName); 149 if (internalScpExec( 150 remoteInstance, 151 options, 152 Arrays.asList("-r"), 153 runUtil, 154 timeout, 155 remoteDirPath, 156 localFile, 157 ScpMode.PULL)) { 158 return localFile; 159 } 160 } catch (IOException e) { 161 CLog.e(e); 162 } 163 FileUtil.deleteFile(localFile); 164 return null; 165 } 166 167 /** 168 * Push a {@link File} from the local host to the remote instance 169 * 170 * @param remoteInstance The {@link GceAvdInfo} that describe the device. 171 * @param options a {@link TestDeviceOptions} describing the device options to be used for the 172 * GCE device. 173 * @param scpArgs extra args to be passed to the scp command 174 * @param runUtil a {@link IRunUtil} to execute commands. 175 * @param timeout in millisecond for the fetch to complete 176 * @param remoteFilePath The remote path where to find the file. 177 * @param localFile The local {@link File} where the remote file will be pulled 178 * @return True if successful, False otherwise 179 */ pushFileToRemote( GceAvdInfo remoteInstance, TestDeviceOptions options, List<String> scpArgs, IRunUtil runUtil, long timeout, String remoteFilePath, File localFile)180 public static boolean pushFileToRemote( 181 GceAvdInfo remoteInstance, 182 TestDeviceOptions options, 183 List<String> scpArgs, 184 IRunUtil runUtil, 185 long timeout, 186 String remoteFilePath, 187 File localFile) { 188 return internalScpExec( 189 remoteInstance, 190 options, 191 scpArgs, 192 runUtil, 193 timeout, 194 remoteFilePath, 195 localFile, 196 ScpMode.PUSH); 197 } 198 internalScpExec( GceAvdInfo remoteInstance, TestDeviceOptions options, List<String> scpArgs, IRunUtil runUtil, long timeout, String remoteFilePath, File localFile, ScpMode mode)199 private static boolean internalScpExec( 200 GceAvdInfo remoteInstance, 201 TestDeviceOptions options, 202 List<String> scpArgs, 203 IRunUtil runUtil, 204 long timeout, 205 String remoteFilePath, 206 File localFile, 207 ScpMode mode) { 208 List<String> scpCmd = 209 GceRemoteCmdFormatter.getScpCommand( 210 options.getSshPrivateKeyPath(), 211 scpArgs, 212 options.getInstanceUser(), 213 remoteInstance.hostAndPort().getHost(), 214 remoteFilePath, 215 localFile.getAbsolutePath(), 216 mode); 217 CommandResult resScp = runUtil.runTimedCmd(timeout, scpCmd.toArray(new String[0])); 218 if (!CommandStatus.SUCCESS.equals(resScp.getStatus())) { 219 StringBuilder builder = new StringBuilder(); 220 builder.append("Issue when "); 221 if (ScpMode.PULL.equals(mode)) { 222 builder.append("pulling "); 223 } else { 224 builder.append("pushing "); 225 } 226 builder.append(String.format("file, status: %s", resScp.getStatus())); 227 CLog.e(builder.toString()); 228 CLog.e("%s", resScp.getStderr()); 229 return false; 230 } else { 231 return true; 232 } 233 } 234 } 235