void MarkProblemDevice(ITargetDevice Device) { if (ProblemDevices.Where(D => D.Name == Device.Name && D.Platform == Device.Platform).Count() > 0) { return; } // @todo Notify service of problem (reboot device, notify email, etc) // also, pass problem devices to service when asking for reservation, so don't get that device back ProblemDevices.Add(new ProblemDevice(Device.Name, Device.Platform)); }
void MarkProblemDevice(ITargetDevice Device) { if (ProblemDevices.Where(D => D.Name == Device.Name && D.Platform == Device.Platform).Count() > 0) { return; } // report device has a problem to the pool DevicePool.Instance.ReportDeviceError(Device, "MarkProblemDevice"); ProblemDevices.Add(new ProblemDevice(Device.Name, Device.Platform)); }
/// <summary> /// Helper that reserves and returns a list of available devices based on the passed in roles /// </summary> /// <param name="Configs"></param> /// <returns></returns> public bool TryReserveDevices() { List <ITargetDevice> AcquiredDevices = new List <ITargetDevice>(); List <ITargetDevice> SkippedDevices = new List <ITargetDevice>(); ReleaseDevices(); // figure out how many of each device we need Dictionary <UnrealTargetConstraint, int> RequiredDeviceTypes = new Dictionary <UnrealTargetConstraint, int>(); IEnumerable <UnrealSessionRole> RolesNeedingDevices = SessionRoles.Where(R => !R.IsNullRole()); // Get a count of the number of devices required for each platform RolesNeedingDevices.ToList().ForEach(C => { if (!RequiredDeviceTypes.ContainsKey(C.Constraint)) { RequiredDeviceTypes[C.Constraint] = 0; } RequiredDeviceTypes[C.Constraint]++; }); // check whether pool can accommodate devices if (!DevicePool.Instance.CheckAvailableDevices(RequiredDeviceTypes, ProblemDevices)) { return(false); } // AG - this needs more thought as it can either be good (lots of devices under contention, temp failure) or // just burn cycles spinning on something that won't ever work... // If we had problem devices last time see if there are enough of that type that we can exclude them //if (ProblemDevices.Count > 0) //{ // Dictionary<UnrealTargetPlatform, int> ProblemPlatforms = new Dictionary<UnrealTargetPlatform, int>(); // // count how many problems for each platform // ProblemDevices.ForEach(Device => // { // if (ProblemPlatforms.ContainsKey(Device.Platform) == false) // { // ProblemPlatforms[Device.Platform] = 0; // } // ProblemPlatforms[Device.Platform]++; // }); // List<ITargetDevice> ProblemsDevicesToRelease = new List<ITargetDevice>(); // // foreach device, see if we have enough others that we can ignore it // ProblemDevices.ForEach(Device => // { // if (ProblemPlatforms[Device.Platform] < AvailableDeviceTypes[Device.Platform]) // { // Log.Verbose("Had problem with device {0} last time, will now ignore", Device.Name); // } // else // { // Log.Verbose("Would like to ignore device {0} but not enough of this type in pool", Device.Name); // ProblemsDevicesToRelease.Add(Device); // } // }); // // remove any // ProblemDevices = ProblemDevices.Where(D => ProblemsDevicesToRelease.Contains(D) == false).ToList(); //} // nothing acquired yet... AcquiredDevices.Clear(); // for each platform, enumerate and select from the available devices foreach (var PlatformReqKP in RequiredDeviceTypes) { UnrealTargetConstraint Constraint = PlatformReqKP.Key; UnrealTargetPlatform? Platform = Constraint.Platform; int NeedOfThisType = RequiredDeviceTypes[Constraint]; DevicePool.Instance.EnumerateDevices(Constraint, Device => { int HaveOfThisType = AcquiredDevices.Where(D => D.Platform == Device.Platform && Constraint.Check(Device)).Count(); bool WeWant = NeedOfThisType > HaveOfThisType; if (WeWant) { bool Available = Device.IsAvailable; bool Have = AcquiredDevices.Contains(Device); bool Problem = ProblemDevices.Where(D => D.Name == Device.Name && D.Platform == Device.Platform).Count() > 0; Log.Verbose("Device {0}: Available:{1}, Have:{2}, HasProblem:{3}", Device.Name, Available, Have, Problem); if (Available && Have == false && Problem == false) { Log.Info("Acquiring device {0}", Device.Name); AcquiredDevices.Add(Device); HaveOfThisType++; } else { Log.Info("Skipping device {0}", Device.Name); SkippedDevices.Add(Device); } } // continue if we need more of this platform type return(HaveOfThisType < NeedOfThisType); }); } // If we got enough devices, go to step2 where we provision and try to connect them if (AcquiredDevices.Count == RolesNeedingDevices.Count()) { // actually acquire them DevicePool.Instance.ReserveDevices(AcquiredDevices); Log.Info("Selected devices {0} for client(s). Prepping", string.Join(", ", AcquiredDevices)); foreach (ITargetDevice Device in AcquiredDevices) { if (Device.IsOn == false) { Log.Info("Powering on {0}", Device); Device.PowerOn(); } else if (Globals.Params.ParseParam("reboot")) { Log.Info("Rebooting {0}", Device); Device.Reboot(); } if (Device.IsConnected == false) { Log.Verbose("Connecting to {0}", Device); Device.Connect(); } } // Step 3: Verify we actually connected to them var LostDevices = AcquiredDevices.Where(D => !D.IsConnected); if (LostDevices.Count() > 0) { Log.Info("Lost connection to devices {0} for client(s). ", string.Join(", ", LostDevices)); // mark these as problems. Could be something grabbed them before us, could be that they are // unresponsive in some way LostDevices.ToList().ForEach(D => MarkProblemDevice(D)); AcquiredDevices.ToList().ForEach(D => D.Disconnect()); DevicePool.Instance.ReleaseDevices(AcquiredDevices); AcquiredDevices.Clear(); } } if (AcquiredDevices.Count() != RolesNeedingDevices.Count()) { Log.Info("Failed to resolve all devices. Releasing the ones we have "); DevicePool.Instance.ReleaseDevices(AcquiredDevices); } else { ReservedDevices = AcquiredDevices; } // release devices that were skipped DevicePool.Instance.ReleaseDevices(SkippedDevices); return(ReservedDevices.Count() == RolesNeedingDevices.Count()); }