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