1// Copyright 2021 The ChromiumOS Authors 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5syntax = "proto3"; 6 7package chromiumos.test.api; 8 9option go_package = "go.chromium.org/chromiumos/config/go/test/api"; 10 11import "chromiumos/config/api/device_config_id.proto"; 12 13import "chromiumos/longrunning/operations.proto"; 14 15// Provides network based access to a device under test for remote 16// command execution and device state/identity retrieval. 17service DutService { 18 // ExecCommand runs a command on a DUT. 19 // 20 // The working directory is /. 21 // A tty is not spawned for the command. 22 // The user and group is root. 23 // All signals have their default dispositions and are not masked. 24 // The umask is set to 0. 25 // 26 // The environment contains: 27 // 28 // TERM=dumb 29 // PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin 30 // LANG=en_US.UTF-8 31 // USER=root 32 // HOME=/root 33 // 34 // The environment MAY also contain SSH client variables. 35 // The environment SHALL NOT contain variables not mentioned above. 36 // 37 // If the stream is interrupted, the implementation MAY attempt to 38 // stop the command by sending SIGINT, SIGHUP, SIGTERM, or SIGKILL. 39 rpc ExecCommand(ExecCommandRequest) 40 returns (stream ExecCommandResponse); 41 42 // FetchCrashes gets a stream of all crash reports currently on the DUT. 43 // 44 // The stream returned may split up a crash over multiple 45 // `FetchCrashesResponse` protos. See the definition of that proto for 46 // details. 47 // 48 // This call is read-only: it doesn't delete the crashes that it reads. 49 rpc FetchCrashes(FetchCrashesRequest) returns (stream FetchCrashesResponse); 50 51 // Restart simply reboots a DUT and returns when done. 52 // 53 // This is necessary as we need to refresh our connection to the DUT at 54 // restart, and this allows a signaling to the server that the connection 55 // will be severed. 56 rpc Restart(RestartRequest) 57 returns (longrunning.Operation) { 58 option (longrunning.operation_info) = { 59 response_type: "RestartResponse", 60 metadata_type: "RestartMetadata" 61 }; 62 } 63 64 // Scans the live device to determine device config identifiers. 65 // 66 // The returned scan config can then be used to reverse lookup 67 // the actual DeviceConfigId values and corresponding configs. 68 rpc DetectDeviceConfigId(DetectDeviceConfigIdRequest) 69 returns (stream DetectDeviceConfigIdResponse); 70 71 // Fetch a file or dir from the device. 72 // 73 // The files will be returned via a tar'd bytestream. 74 rpc FetchFile(FetchFileRequest) 75 returns (stream File); 76 77 // Downloads files from GS to the DUT 78 // 79 // The files downloaded may be decompressed in this layer to save cycles (and 80 // space) in the DUT. This utilizes the cacheForDUT endpoint to download the 81 // files. 82 rpc Cache(CacheRequest) 83 returns (longrunning.Operation) { 84 option (longrunning.operation_info) = { 85 response_type: "CacheResponse", 86 metadata_type: "CacheMetadata" 87 }; 88 } 89 90 91 // Used to reestablish connection to DUT in case of drops. 92 // 93 // This is needed in case the connection to the DUT is lost and we need to 94 // keep the connection. Previously this was done by the service, but as we try 95 // to accomplish true microservice functionality (i.e.: no side-effects) we 96 // removed it and gave the option for the user to reconnect if needed with 97 // whichever algorithm they prefer. 98 rpc ForceReconnect(ForceReconnectRequest) 99 returns (longrunning.Operation) { 100 option (longrunning.operation_info) = { 101 response_type: "ForceReconnectResponse", 102 metadata_type: "ForceReconnectMetadata" 103 }; 104 } 105 106} 107 108 109message ExecCommandRequest { 110 // name is the resource name for the DUT. 111 // The DUT name is passed to the RTD when the RTD is started. 112 // It is not specified whether the name is the DUT hostname. 113 string name = 1; 114 // command is the command to run. 115 // If this contains no slashes, it is resolved using PATH. 116 // If this starts with /, it is used as an absolute path to the 117 // program to run. 118 // Otherwise, this is treated as a path relative to the working 119 // directory. 120 string command = 2; 121 // args are the arguments to pass to the command. The arguments 122 // are not quoted in any way, so passing shell variables and 123 // arguments containing spaces could fail. 124 repeated string args = 3; 125 // stdin is passed to the command as the program's stdin. 126 // The stream does not support seeking. 127 // An empty bytes is not treated specially; if the command reads 128 // from stdin, it will receive zero bytes. 129 bytes stdin = 4; 130 // stdout indicates how to handle the command's stdout. 131 Output stdout = 5; 132 // stderr indicates how to handle the command's stderr. 133 Output stderr = 6; 134} 135message ExecCommandResponse { 136 message ExitInfo { 137 // status provides information about how the command process 138 // terminated. 139 // 140 // If the command failed to start, status is set to an arbitrary 141 // non-zero value. 142 // 143 // If signaled is set, status is set to the signal that caused 144 // the command to terminate. 145 // 146 // Otherwise, status is set to the exit status of the process. 147 // Exit statuses outside of 0 to 255 inclusive are not supported; 148 // they will be mapped to an arbitrary non-zero value. 149 // 150 // status is zero if and only if the process was successfully 151 // started and exited with a zero status. 152 int32 status = 1; 153 // signaled indicates whether the command exited due to a signal. 154 // If set, status contains the signal. 155 bool signaled = 2; 156 // started indicates whether the command was started. 157 bool started = 3; 158 // error_message provides a human readable explanation for some errors. 159 // This MUST NOT be inspected by programs. 160 string error_message = 4; 161 } 162 // exit_info contains exit information. 163 // This is set when the command has exited or failed to start. 164 // This is set on the last message in the response stream. 165 ExitInfo exit_info = 1; 166 // stdout contains the shell command's stdout output since the last 167 // response in the stream. 168 // The implementation MAY batch or delay output to later 169 // responses in the stream. 170 bytes stdout = 2; 171 // stderr contains the shell command's stderr output since the last 172 // response in the stream. 173 // The implementation MAY batch or delay output to later 174 // responses in the stream. 175 bytes stderr = 3; 176} 177 178// Output enumeration for ExecCommandRequest. 179enum Output { 180 // OUTPUT_PIPE means to collect output and return it. 181 OUTPUT_PIPE = 0; 182 // OUTPUT_STDOUT is a special value for stderr which means to merge stderr 183 // into stdout. 184 OUTPUT_STDOUT = 1; 185} 186 187 188// Fetch files from remote host into local /var/tmp/remotefiles 189message FetchFileRequest { 190 string file = 1; 191} 192 193// Byte stream of the requested file. 194message File { 195 bytes file = 1; 196} 197 198message FetchCrashesRequest { 199 // If true, fetch the core file. 200 // For uploads to the crash server, that should generally be false. 201 // If the crash file is likely to be used for manual debugging (e.g. on 202 // a manually-invoked test suite run), this might be true. 203 // Coredumps can be extremely large (even gigabytes), so if resource usage 204 // is a concern, this should probably be false. 205 bool fetch_core = 2; 206 207 // dut is no longer necessary since this service is run on a per-dut basis. 208 // Reserving field in order to keep wire compatible with old proto. 209 reserved 1; 210} 211 212// When this response is streamed, the first proto with a given crash ID will 213// always contain the CrashInfo. 214// Files and core dumps (if present) may be streamed. If they are, 215// subsequent protos with the same crash ID will follow, each containing a chunk 216// of file/coredump. To reassemble these, concatenate the bytes received from 217// each subsequent proto with a matching crash_id (concatenate blobs that have 218// matching crash_ids and keys). 219// Additional crashes may be reported in the same stream with a new crash ID. 220message FetchCrashesResponse { 221 // Crash id. unique only within responses to a single FetchCrashes request. 222 // Used to assemble multiple streamed |FetchCrashesResponse| protos into a 223 // single crash report. 224 int64 crash_id = 1; 225 oneof data { 226 // Full details of crash report. 227 CrashInfo crash = 2; 228 // Misc file (e.g. minidump, large binary log, etc) 229 CrashBlob blob = 3; 230 // Coredump. Present if fetch_core was true in FetchCrashesRequest and 231 // the crash has a coredump. (kernel warnings, for example, do not have 232 // one). 233 bytes core = 4; 234 } 235} 236 237// The data in this proto matches the metadata from crash-reporter's meta files. 238// Sender::CreateCrashFormData puts this data into crash upload POST requests. 239// (See src/platform2/crash-reporter/crash_sender_util.cc.) 240// The names in this proto MUST match the names that crash-reporter uses so 241// that, when crashes are uploaded to the crash server, they are interpreted 242// as they are when crash-reporter uploads them. 243// Similarly, when this proto is converted into a POST request to send to the 244// crash server, the names must not be altered. 245message CrashInfo { 246 // Name of executable that crashed (e.g. "chrome") 247 string exec_name = 1; 248 // Product name (e.g. "Chrome_ChromeOS" or "ChromeOS") 249 string prod = 2; 250 // Product version (e.g. "12345.0.0") 251 string ver = 3; 252 // Crash signature (may not be populated for all crashes) 253 string sig = 4; 254 // The name of the integration test that was running when this crash 255 // happened, if any. 256 string in_progress_integration_test = 5; 257 // The name of the collector (e.g. chrome_collector, arc_collector) 258 string collector = 6; 259 // Additional key-value pairs of metadata (e.g. "crash_loop_mode = true"). 260 // These should be included in any POSTs to the crash server in a standard 261 // POST form, as seen in CreateCrashFormData. 262 // (despite the fact that this message is a subfield, it should be a flat 263 // structure in any POSTs). 264 repeated CrashMetadata fields = 7; 265} 266 267// Arbitrary text-only key-value pair corresponding to the key-value pairs in 268// crash report metadata files. 269message CrashMetadata { 270 // This value is a UTF8, human-readable, description of the data. 271 string key = 1; 272 // The value will be a human-readable string (e.g. "12345.0.0"), which must 273 // be valid UTF-8. 274 string text = 2; 275}; 276 277// Arbitrary non-UTF8 key-value pair from crash report metadata files. 278message CrashBlob { 279 // This value is a UTF8, human-readable, description of the data. 280 // This should be passed as the 'name' to the crash server. 281 // For instance, upload_file_fake_payload 282 string key = 1; 283 // The value is a blob (e.g. a file from sysfs or a minidump), which need 284 // not be valid UTF-8, and may be large. 285 bytes blob = 2; 286 // The basename of the file. Must be specified as the filename in data 287 // uploaded to the crash server. 288 // e.g. foo_binary.20201027.102345.0.dmp 289 string filename = 3; 290}; 291 292message RestartRequest { 293 // args are the arguments to pass to the reboot command. 294 repeated string args = 1; 295 296 message ReconnectRetry { 297 int32 times = 1; 298 int64 interval_ms = 2; 299 } 300 301 ReconnectRetry retry = 2; 302}; 303 304message RestartResponse { 305 // output represents the stdout for the reboot. Useful if the verbose flag is 306 // used. 307 string output = 1; 308 309} 310 311message RestartMetadata { 312} 313 314message CacheRequest { 315 // Where to place the file in the DUT: 316 // * Local DUT File 317 // * Pipe to command 318 message LocalFile { 319 string path = 1; 320 } 321 322 message Pipe { 323 string commands = 1; 324 } 325 326 oneof destination { 327 LocalFile file = 1; 328 Pipe pipe = 2; 329 } 330 331 // A file downloaded may be one of: 332 // * A regular file 333 // * A tar'd directory from which we fetch one file (source_file) 334 // * A zipped file 335 message GSFile { 336 string source_path = 1; 337 } 338 339 message GSZipFile { 340 string source_path = 1; 341 } 342 343 message GSTARFile { 344 string source_path = 1; 345 string source_file = 2; 346 } 347 348 message Retry { 349 int32 times = 1; 350 int64 interval_ms = 2; 351 } 352 353 oneof source { 354 GSFile gs_file = 3; 355 GSZipFile gs_zip_file = 4; 356 GSTARFile gs_tar_file = 5; 357 } 358 359 Retry retry = 6; 360} 361 362message CacheResponse { 363 message Success { 364 } 365 366 message Failure { 367 string error_message = 1; 368 } 369 370 oneof result { 371 Success success = 1; 372 Failure failure = 2; 373 } 374} 375 376message CacheMetadata { 377} 378 379message ForceReconnectRequest { 380} 381 382message ForceReconnectResponse { 383 message Success { 384 } 385 386 message Failure { 387 string error_message = 1; 388 } 389 390 oneof result { 391 Success success = 1; 392 Failure failure = 2; 393 } 394} 395 396message ForceReconnectMetadata { 397} 398 399message DetectDeviceConfigIdRequest { 400}; 401 402message DetectDeviceConfigIdResponse { 403 oneof result { 404 Success success = 1; 405 Failure failure = 2; 406 } 407 408 message Success { 409 chromiumos.config.api.DeviceConfigId.ScanConfig detected_scan_config = 1; 410 } 411 412 message Failure { 413 string error_message = 1; 414 } 415} 416