/// <summary> /// Runs the process and read output. /// </summary> /// <returns>The process and read output.</returns> /// <param name="processName">Process name.</param> /// <param name="processArgs">Process arguments.</param> /// <param name="timeout">Timeout.</param> public string RunProcessAndReadOutput(string processName, string processArgs, int timeout = 5000) { _logger.Debug(string.Format("RunProcessAndReadOutput processName: [{0}] args: [{1}]", processName, processArgs)); var psi = new ProcessStartInfo() { FileName = processName, Arguments = processArgs, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; var proc = new Process { StartInfo = psi }; proc.Start(); proc.WaitForExit(timeout); var output = proc.StandardOutput.ReadToEnd(); _logger.Debug(string.Format("RunProcessAndReadOutput output: [{0}]", string.Join("\n", output))); var errorOutput = proc.StandardError.ReadToEnd(); _logger.Debug(string.Format("RunProcessAndReadOutput errorOutput: [{0}]", string.Join("\n", errorOutput))); return(output + errorOutput); }
public IActionResult Create([FromBody] AppiumProcess appiumProcess) { LogRequestToDebug(); if (!ValidateAppiumProcess(appiumProcess, out var badRequest)) { return(badRequest); } if (_appiumRepository.Find(appiumProcess.DeviceId) != null) { // 409 = Conflict return(StatusCodeExtension(409, $"Appium is already running for {nameof(AppiumProcess.DeviceId)} [{appiumProcess.DeviceId}].")); } try { _appiumRepository.Add(appiumProcess); } catch (Exception ex) { return(StatusCodeExtension(500, "Failed to Add AppiumProcess in database. " + ex.Message)); } _logger.Debug(string.Format("Created new appiumProcess: [{0}]", JsonConvert.SerializeObject(appiumProcess))); return(CreatedAtRoute("getAppiumProcess", new { id = appiumProcess.DeviceId }, appiumProcess)); }
/// <inheritdoc /> /// <summary> /// Takes the screenshot ios device. /// </summary> /// <returns>The screenshot ios device.</returns> /// <param name="device">Device.</param> public FileStreamResult TakeScreenshotIosDevice(Device device) { var screenshotFolder = Path.Combine(Directory.GetCurrentDirectory(), "Screenshot"); Directory.CreateDirectory(screenshotFolder); var screenshotFilePath = Path.Combine(screenshotFolder, $"{device.Id}.tiff"); var screenshotRet = _externalProcesses.RunProcessAndReadOutput("idevicescreenshot", $" -u {device.Id} {screenshotFilePath}", 10000); _logger.Debug(screenshotRet); if (screenshotRet.Contains("Could not start screenshotr service")) { //throw new Exception($"Failed get screenshot. {screenshotRet}"); return(GetDefaultMobileImage()); } var convertedImagePath = Path.Combine(screenshotFolder, $"{device.Id}.jpg"); ConvertImage(screenshotFilePath, convertedImagePath); FileStream image; if (System.IO.File.Exists(convertedImagePath)) { image = System.IO.File.OpenRead(convertedImagePath); return(File(image, "image/jpeg")); } image = System.IO.File.OpenRead(screenshotFilePath); return(File(image, "image/tiff")); }
public IEnumerable <Device> GetAll() { LogRequestToDebug(); var devices = _devicesRepository.GetAll(); _logger.Debug(string.Format("GetAll devices: [{0}]", JsonConvert.SerializeObject(devices))); return(devices); }
public IEnumerable <ReservationApplied> GetAllAppliedReservations() { LogRequestToDebug(); var reservations = _reservationsAppliedRepository.GetAll(); _logger.Debug( string.Format("GetAll reservations applied: [{0}]", JsonConvert.SerializeObject(reservations))); return(reservations); }
public async Task <IActionResult> Delete(string id) { LogRequestToDebug(); var device = await _restClient.GetDevice(id); if (device == null) { return(NotFoundExtension("DeviceId not found in database.")); } String appiumLogPath = await GetAppiumLogFilePath(id); if (!System.IO.File.Exists(appiumLogPath)) { return(NotFoundExtension("Appium log not found on path:" + appiumLogPath)); } try { System.IO.File.Delete(appiumLogPath); } catch (Exception ex) { return(StatusCodeExtension(500, "Failed to delete AppiumLog. " + ex.Message)); } _logger.Debug(string.Format("Successfully deleted appiumLog on path: [{0}]", appiumLogPath)); return(OkExtension()); }
/// <summary> /// Initializes a new instance of the <see cref="T:MobileManager.Services.AndroidDeviceService"/> class. /// </summary> public AndroidDeviceService(IManagerConfiguration configuration, IManagerLogger logger, IExternalProcesses externalProcesses) { _logger = logger; _externalProcesses = externalProcesses; _logger.Debug("Running AndroidDeviceService service."); _deviceUtils = new DeviceUtils(_logger, _externalProcesses); _restClient = new RestClient(configuration, _logger); }
public IActionResult Command([FromBody] AdbCommand adbCommand) { if (!IsAdbCommandExecutable(adbCommand, out var actionResult)) { return(actionResult); } string output; try { output = _externalProcesses.RunProcessAndReadOutput("adb", $"-s {adbCommand.AndroidDeviceId} {adbCommand.Command}"); _logger.Debug($"{nameof(AdbCommand)} [{adbCommand.Command}] output: [{output}]"); } catch (Exception ex) { return(StatusCodeExtension(500, "Failed to run adb command. " + ex.Message)); } return(StatusCodeExtension(200, output)); }
public BadRequestObjectResult BadRequestExtension(object error) { _logger.Debug(string.Format("Response status code: [{0}], message: [{1}]", 400, JsonConvert.SerializeObject(error))); return(BadRequest(error)); }
/// <inheritdoc /> /// <summary> /// Locks the device. /// </summary> /// <returns>The device.</returns> /// <param name="deviceId">Device identifier.</param> /// <param name="restClient">Rest client.</param> /// <param name="appiumService">Appium service.</param> public async Task <Device> LockDevice(string deviceId, IRestClient restClient, IAppiumService appiumService) { _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}]."); var device = await restClient.GetDevice(deviceId); if (device == null) { throw new KeyNotFoundException("Failed to find device with id: " + deviceId); } _logger.Debug( $"{nameof(LockDevice)}: set device id [{deviceId}] available from [{device.Available}] to false."); device.Available = false; _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}] stop running Appium"); try { device.AppiumEndpoint = Task.Run(() => appiumService.StartAppiumForDeviceId(deviceId)).Result; } catch (Exception e) { _logger.Error($"{nameof(LockDevice)} failed with exception.", e); await UnlockDevice(device.Id, restClient, appiumService); throw; } _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}] set status from [{device.Status}] to LOCKED"); device.Status = DeviceStatus.Locked; var updatedDevice = await restClient.UpdateDevice(device); _logger.Debug($"{nameof(LockDevice)}: updated device [{JsonConvert.SerializeObject(updatedDevice)}]"); return(updatedDevice); }
/// <summary> /// Loads the connected IOS Devices async. /// </summary> /// <returns>The connected IOS Devices async.</returns> private async Task LoadConnectedIosDevicesAsync(CancellationToken cancellationToken) { _logger.Info($"{nameof(LoadConnectedIosDevicesAsync)} Thread started."); while (!cancellationToken.IsCancellationRequested) { try { _logger.Debug($"Running {nameof(LoadConnectedIosDevicesAsync)}."); if (await _restClient.TryToConnect()) { var output = _externalProcesses.RunProcessAndReadOutput("idevice_id", "-l"); var listOfIosDeviceIds = output.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList(); listOfIosDeviceIds = listOfIosDeviceIds.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct() .ToList(); await _deviceUtils.CheckAllDevicesInDevicePoolAreOnline(listOfIosDeviceIds, DeviceType.IOS, _restClient); foreach (var deviceId in listOfIosDeviceIds) { if (string.IsNullOrEmpty(deviceId)) { continue; } var deviceInDevicePool = await _restClient.GetDevice(deviceId); if (deviceInDevicePool != null) { if (deviceInDevicePool.Status == DeviceStatus.Offline) { SetNewDeviceProperties(deviceInDevicePool); await MountDeveloperDiskAsync(deviceInDevicePool); deviceInDevicePool.Status = DeviceStatus.Online; deviceInDevicePool.Available = true; await _restClient.UpdateDevice(deviceInDevicePool); continue; } _logger.Info( $"{nameof(LoadConnectedIosDevicesAsync)}: Device {deviceId} is already stored in database."); await MountDeveloperDiskAsync(deviceInDevicePool); continue; } var deviceName = _externalProcesses.RunProcessAndReadOutput("idevicename", $"-u {deviceId}"); if (string.IsNullOrEmpty(deviceName) || deviceName.Contains("ERROR")) { _logger.Error( $"{nameof(LoadConnectedIosDevicesAsync)}: Failed get device name for deviceId: [{deviceId}].\n[{deviceName}]"); continue; } var device = new DeviceFactory().NewDevice(deviceId, deviceName.Trim('\n'), true, DeviceType.IOS, DeviceStatus.Online); SetNewDeviceProperties(device); await TryAddNewDeviceToDevicePoolAsync(device); await MountDeveloperDiskAsync(device); } Thread.Sleep((await _restClient.GetManagerConfiguration()).IosDeviceServiceRefreshTime); } else { _logger.Error( $"{nameof(LoadConnectedIosDevicesAsync)}: Failed connecting to {_restClient.Endpoint} [STOP]"); WaitForGlobalReconnectTimeout(); } } catch (Exception e) { _logger.Error($"{nameof(LoadConnectedIosDevicesAsync)} exception.", e); WaitForGlobalReconnectTimeout(); } } }
/// <inheritdoc /> /// <summary> /// Starts the appium for device identifier. /// </summary> /// <returns>The appium for device identifier.</returns> /// <param name="deviceId">Device identifier.</param> public async Task <string> StartAppiumForDeviceId(string deviceId) { _logger.Info($"{nameof(StartAppiumForDeviceId)} {deviceId} Thread Started."); var configuration = await _restClient.GetManagerConfiguration(); var device = await _restClient.GetDevice(deviceId); _logger.Debug($"{nameof(StartAppiumForDeviceId)} - device: {JsonConvert.SerializeObject(device)}"); var appiumIpAddress = configuration.LocalIpAddress; var currentAppiumProcesses = await _restClient.GetAppiumProcesses(); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - currentAppiumProcesses: {JsonConvert.SerializeObject(currentAppiumProcesses)}"); var usedAppiumPorts = new List <string>(); foreach (var process in currentAppiumProcesses) { usedAppiumPorts.Add(process.AppiumPort); usedAppiumPorts.Add(process.AppiumBootstrapPort); usedAppiumPorts.Add(process.WebkitDebugProxyPort); usedAppiumPorts.Add(process.WdaLocalPort); } _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - usedAppiumPorts: {JsonConvert.SerializeObject(usedAppiumPorts)}"); var appiumPort = GetFreePortAsyncMac(configuration, usedAppiumPorts); usedAppiumPorts.Add(appiumPort); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - new appiumPort: {JsonConvert.SerializeObject(appiumPort)}"); var appiumBootstrapPort = GetFreePortAsyncMac(configuration, usedAppiumPorts); usedAppiumPorts.Add(appiumBootstrapPort); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - new appiumBootstrapPort: {JsonConvert.SerializeObject(appiumBootstrapPort)}"); var appiumLogFilePath = _appiumLogFolderPath; if (!appiumLogFilePath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) { appiumLogFilePath += Path.DirectorySeparatorChar; } appiumLogFilePath = appiumLogFilePath + deviceId + ".log"; _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - appiumLogFilePath: {JsonConvert.SerializeObject(appiumLogFilePath)}"); var webkitDebugProxyPort = GetFreePortAsyncMac(configuration, usedAppiumPorts); usedAppiumPorts.Add(webkitDebugProxyPort); var wdaLocalPort = GetFreePortAsyncMac(configuration, usedAppiumPorts); usedAppiumPorts.Add(wdaLocalPort); /* * String defaultCapabilities = "\\\"automation-name\\\" : \\\"XCUITest\\\"," + * " \\\"teamId\\\" : \\\"CB52FCDD4H\\\"," + * " \\\"signingId\\\" : \\\"iPhone Developer\\\"," + * " \\\"showXcodeLog\\\" : \\\"true\\\"," + * " \\\"realDeviceLogger\\\" : \\\"/usr/local/lib/node_modules/deviceconsole/deviceconsole\\\"," + * " \\\"bootstrapPath\\\" : \\\"/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent\\\"," + * " \\\"agentPath\\\" : \\\"/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj\\\"," + * " \\\"startIWDP\\\" : \\\"true\\\"," + * " \\\"sessionTimeout\\\" : \\\"6000\\\""; */ var appiumArguments = "" + " --session-override" + " --suppress-adb-kill-server" + " --log " + appiumLogFilePath + " --udid " + deviceId + " --address " + appiumIpAddress + " --port " + appiumPort + " --bootstrap-port " + appiumBootstrapPort + " --webkit-debug-proxy-port " + webkitDebugProxyPort + " --webdriveragent-port " + wdaLocalPort; /* * if (device.Type == Devices.Enums.DeviceType.iOS) * { * appiumArguments += " --default-capabilities \\\'{"+defaultCapabilities+"}\\\'"; * } */ _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - starting appium with args: {JsonConvert.SerializeObject(appiumArguments)}"); var appiumPid = _externalProcesses.RunProcessInBackground("appium", appiumArguments); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - appium started in terminal with pid: {JsonConvert.SerializeObject(appiumPid)}"); Thread.Sleep(3000); var psOutput = _externalProcesses.RunProcessAndReadOutput("ps", "ax"); var runningAppiumProcess = psOutput.Split('\n').Where(x => x.Contains("bin/appium") && x.Contains(deviceId)) .ToList(); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - runningAppiumProcess {JsonConvert.SerializeObject(runningAppiumProcess)} for device {device}."); var processId = ""; if (runningAppiumProcess.Count() != 1) { _logger.Error( $"{nameof(StartAppiumForDeviceId)}: Multiple appium processes running with deviceId={deviceId}. Killing them all..."); _externalProcesses.StopProcessRunningInBackground(deviceId); } else { processId = runningAppiumProcess.First().Trim().Split()[0]; _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - runningAppiumProcess with pid: {JsonConvert.SerializeObject(processId)}."); } if (string.IsNullOrEmpty(processId) && !_externalProcesses.IsProcessInBackgroundRunning(Convert.ToInt32(processId))) { throw new Exception($"{nameof(StartAppiumForDeviceId)}: Appium process failed to start successfully."); } appiumPid = Convert.ToInt32(processId); var appiumProcess = new AppiumProcess(deviceId, appiumPort, appiumBootstrapPort, appiumPid, webkitDebugProxyPort, wdaLocalPort); _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - adding appiumProcess: {JsonConvert.SerializeObject(appiumProcess)}."); var result = Task.Run(async() => await _restClient.AddAppiumProcess(appiumProcess)).Result; _logger.Debug( $"{nameof(StartAppiumForDeviceId)} - finished adding appiumProcess: with result [{result}]."); if (device.Type == DeviceType.IOS) { _logger.Debug($"{nameof(StartAppiumForDeviceId)} - starting iosWebkit for ios device {device}."); var iosWebkitPid = StartIosWebkitDebugProxy(deviceId, webkitDebugProxyPort); if (!_externalProcesses.IsProcessInBackgroundRunning(iosWebkitPid)) { _logger.Error( $"{nameof(StartAppiumForDeviceId)} - ios_webkit_debug_proxy process failed to start successfully."); throw new Exception( $"{nameof(StartAppiumForDeviceId)}: ios_webkit_debug_proxy process failed to start successfully."); } _logger.Debug($"{nameof(StartAppiumForDeviceId)} - starting IdeviceSyslog for ios device {device}."); StartIdeviceSyslog(deviceId); } _logger.Info($"{nameof(StartAppiumForDeviceId)} appiumEndpoint: {appiumIpAddress}:{appiumPort}"); var appiumEndpoint = new Uri($"http://{appiumIpAddress}:{appiumPort}/wd/hub"); return(appiumEndpoint.ToString()); }
/// <inheritdoc /> /// <summary> /// Applies the available reservations. /// </summary> /// <returns>The available reservations.</returns> //todo refactor - split into multiple methods public async Task <bool> ApplyAvailableReservations() { var reservationQueue = await LoadReservationQueue(); var appliedReservations = new List <ReservationApplied>(); foreach (var reservation in reservationQueue) { _logger.Info($"Applying reservation - item in queue: {JsonConvert.SerializeObject(reservation)}"); var reservedDevices = new List <ReservedDevice>(); if (reservation.RequestedDevices == null) { throw new NullReferenceException("RequestedDevices property on reservation is empty."); } var reservationEligible = true; if (reservation.RequestedDevices.Count > 1) { reservationEligible = await IsReservationEligible(reservation); } if (reservationEligible) { await ReserveAllRequestedDevices(reservation, reservedDevices); } else { _logger.Debug($"Reservation is not eligible. {JsonConvert.SerializeObject(reservation)}"); continue; } if (reservedDevices.Count == reservation.RequestedDevices.Count) { //ICollection<ReservationApplied> reservationApplied = null; try { var reservationApplied = await AddAppliedReservation(appliedReservations, reservation, reservedDevices); appliedReservations.AddRange(reservationApplied); } catch (Exception e) { _logger.Error($"Failed to AddAppliedReservation.", e); await UnlockAllReservedDevices(reservedDevices); continue; } _logger.Info( $"Applying reservation - removing reservation from queue: {JsonConvert.SerializeObject(reservation)}"); await RestClient.DeleteReservation(reservation.Id); } else if (reservedDevices.Any()) { await UnlockAllReservedDevices(reservedDevices); } } _logger.Info( $"Applying reservation - applied reservations: {JsonConvert.SerializeObject(appliedReservations)}"); return(appliedReservations.Any()); }
/// <inheritdoc /> /// <summary> /// Tries to connect. /// </summary> /// <returns>The to connect.</returns> public async Task <bool> TryToConnect() { _logger.Debug("Starting TryToConnect"); try { await _client.GetAsync("api/v1/configuration"); } catch (Exception e) { _logger.Info("Failed to connect to: " + _client.BaseAddress); _logger.Error("Failed to connect.", e); return(false); } _logger.Debug("Finished TryToConnect OK"); return(true); }
private async Task LoadConnectedAndroidDevicesAsync(CancellationToken cancellationToken) { _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)} Thread started."); try { while (!cancellationToken.IsCancellationRequested) { _logger.Debug($"Running {nameof(LoadConnectedAndroidDevicesAsync)}."); if (await _restClient.TryToConnect()) { var deviceIdAndStatus = GetAndroidDevicesFromAdbDevicesOutput(); await _deviceUtils.CheckAllDevicesInDevicePoolAreOnline(deviceIdAndStatus.Keys.ToList(), DeviceType.Android, _restClient); foreach (var deviceId in deviceIdAndStatus.Keys) { var deviceAlreadyInPool = await IsDeviceAlreadyInDevicePoolAsync(deviceId); if (!deviceAlreadyInPool) { var state = deviceIdAndStatus[deviceId]; if (state != "device") { _logger.Error( $"{nameof(LoadConnectedAndroidDevicesAsync)}: Device with id: [{deviceId}] is in incorrect state: [{state}]. Expected state is [device]"); continue; } } else { continue; } _logger.Debug( $"{nameof(LoadConnectedAndroidDevicesAsync)}: read device [{deviceId}] properties."); var deviceName = GetDeviceName(deviceId); if (string.IsNullOrWhiteSpace(deviceName)) { _logger.Error( $"{nameof(LoadConnectedAndroidDevicesAsync)}: Failed to get deviceName to device with id: '" + deviceId + "'"); continue; } _logger.Debug( $"{nameof(LoadConnectedAndroidDevicesAsync)}: new android device factory [{deviceId}] name [{deviceName.Trim('\n', '\r')}]."); var device = new DeviceFactory().NewDevice(deviceId, deviceName.Trim('\n', '\r'), true, DeviceType.Android, DeviceStatus.Online); var deviceProperties = GetDevicePropertiesById(deviceId); var properties = new List <DeviceProperties>(); foreach (var prop in deviceProperties) { properties.Add(new DeviceProperties(prop.Key, prop.Value)); } device.Properties = properties; await TryAddNewDeviceToDevicePoolAsync(device); _logger.Debug( $"{nameof(LoadConnectedAndroidDevicesAsync)}: TryAddNewDeviceToDevicePoolAsync [{JsonConvert.SerializeObject(device)}]."); await TryAddNewDeviceToDevicePoolAsync(device); } var sleepTime = (await _restClient.GetManagerConfiguration()).AndroidDeviceServiceRefreshTime; _logger.Debug($"{nameof(LoadConnectedAndroidDevicesAsync)}: sleep for [{sleepTime}]."); Thread.Sleep(sleepTime); } else { _logger.Error($"{nameof(LoadConnectedAndroidDevicesAsync)}: Failed connecting to " + _restClient.Endpoint + " [STOP]"); var sleep = AppConfigurationProvider.Get <ManagerConfiguration>().GlobalReconnectTimeout; _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)}: Sleep for [ms]: {sleep}"); Thread.Sleep(sleep); _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)}: Sleep finished"); } } _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)} STOP."); } catch (Exception e) { _logger.Error($"Stopping {nameof(LoadConnectedAndroidDevicesAsync)}.", e); } if (cancellationToken.IsCancellationRequested) { var result = _externalProcesses.RunProcessAndReadOutput("adb", "kill-server"); _logger.Debug( $"{nameof(LoadConnectedAndroidDevicesAsync)}: Stop ADB server to release ports - output:{result}"); } }