public static void Run(string hostName, Action action) { GlobalLockToken token = new GlobalLockToken("MACH_SHUT_3E94", TimeSpan.FromDays(1), TimeSpan.FromMinutes(10)); CriticalSection criticalSection = new CriticalSection(new DistributedLockManager(GlobalSettings.WcfHosts["Lock"])); criticalSection.RunConcurrent(token, action, _batchSize); }
/// <summary> /// ReSyncs the VM Inventory. /// </summary> /// <param name="credential">The VSphere credentials to use during synchronization.</param> public static void SyncInventory(UserCredential credential) { UserManager.CurrentUser = credential; TraceFactory.Logger.Debug("Acquiring Lock."); var token = new GlobalLockToken("VirtualMachineInventorySynchronization", TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(5)); // Create an explicit CriticalSection here because this call is coming from the UI where ExecutionServices is not initialized. CriticalSection criticalSection = new CriticalSection(new DistributedLockManager(GlobalSettings.WcfHosts["Lock"])); criticalSection.Run(token, UpdateInventory); }
/// <summary> /// Reserves a block of users. This MUST be called before being able to get user credentials. /// </summary> /// <param name="sessionId">The session id.</param> /// <param name="accountQuantity">The account quantity which is separated by account pool.</param> /// <returns>A <see cref="DomainAccountReservationSet"/> containing information on the reserved accounts.</returns> /// <exception cref="System.ArgumentNullException">accountQuantity</exception> /// <exception cref="System.InvalidOperationException">Domain accounts have already been reserved for this Session Id</exception> public static DomainAccountReservationSet Reserve(string sessionId, DomainAccountQuantityDictionary accountQuantity) { if (accountQuantity == null) { throw new ArgumentNullException("accountQuantity"); } DomainAccountReservationSet reservedBlock = new DomainAccountReservationSet(sessionId); Action action = new Action(() => { try { using (AssetInventoryContext context = DbConnect.AssetInventoryContext()) { if (context.DomainAccountReservations.Any(e => e.SessionId.Equals(sessionId, StringComparison.OrdinalIgnoreCase))) { //This could be a subsequent call to reserve. Clear all reservations before proceeding. Release(sessionId); } foreach (var poolType in accountQuantity.Keys) { int userCount = accountQuantity[poolType]; DomainAccountPool pool = SelectPool(context, poolType); int startIndex = ReserveBlock(context, sessionId, pool, userCount); TraceFactory.Logger.Debug($"New pool reserved: StartIndex: {startIndex}, UserCount: {userCount}, PoolName: {pool.DomainAccountKey}"); reservedBlock.Add(poolType, pool, startIndex, userCount); } } } catch (InsufficientDomainAccountsException) { ReleaseSessionReservations(sessionId); throw; } }); var token = new GlobalLockToken("DomainAccountReservation", TimeSpan.FromMinutes(11), TimeSpan.FromMinutes(2)); ExecutionServices.CriticalSection.Run(token, action); return(reservedBlock); }
/// <summary> /// Gets a replacement VM if one is not responding. /// </summary> /// <param name="replacedVMName">The name of the replaced VM.</param> /// <returns></returns> public static VirtualMachine GetReplacement(string replacedVMName) { VirtualMachine replacement = null; using (AssetInventoryContext context = DbConnect.AssetInventoryContext()) { //Get the SessionId that tried to power-on the failed machine FrameworkClient replacedVirtualMachine = Select(context, replacedVMName); LockToken lockToken = new GlobalLockToken("VirtualMachineReservation", new TimeSpan(0, 1, 0), new TimeSpan(0, 2, 0)); ExecutionServices.CriticalSection.Run(lockToken, () => { //Get the next available machine replacement = VirtualMachine.SelectReplacement(replacedVirtualMachine.PlatformUsage, replacedVirtualMachine.HoldId); if (replacement != null) { Reserve ( context, replacement.Name, replacedVirtualMachine.PlatformUsage, DateTime.Now, replacedVirtualMachine.SessionId, GlobalSettings.Environment ); context.SaveChanges(); } else { throw new VMInventoryException("Insufficient VMs available."); } }); } return(replacement); }
/// <summary> /// Reserves the requested VMs. /// </summary> /// <param name="sessionId">The session id.</param> /// <param name="credential">The user requesting the reservation.</param> /// <param name="requestedVMs">The requested VMs.</param> /// <param name="requiredVMQuantity">The required VM quantity.</param> /// <returns></returns> public static bool Reserve(string sessionId, UserCredential credential, RequestedVMDictionary requestedVMs, VMQuantityDictionary requiredVMQuantity) { if (requiredVMQuantity == null) { throw new ArgumentNullException("requiredVMQuantity"); } if (requestedVMs == null) { throw new ArgumentNullException("requestedVMs"); } DateTime currentTime = DateTime.Now; TraceFactory.Logger.Debug(requiredVMQuantity.ToString()); LockToken lockToken = new GlobalLockToken("VirtualMachineReservation", new TimeSpan(0, 1, 0), new TimeSpan(0, 2, 0)); ExecutionServices.CriticalSection.Run(lockToken, () => { // Need to work with a master list of VMs. If the requested set is empty, then the master list // will come from the database. Otherwise it will come from the requested set. List <VirtualMachine> masterMachineList = GetMasterList(credential, requestedVMs); // Copy the required VMs (by Platform) to their own dictionary as items will be removed. Dictionary <string, int> remainingPlatforms = requiredVMQuantity.ToDictionary(entry => entry.Key, entry => entry.Value); using (AssetInventoryContext context = DbConnect.AssetInventoryContext()) { // Iterate over each item in the required VM dictionary and process while (remainingPlatforms.Count > 0) { // Get the target platform and required count for each entry string targetPlatformId = remainingPlatforms.ElementAt(0).Key; int targetPlatformCount = remainingPlatforms.ElementAt(0).Value; TraceFactory.Logger.Debug("Target Platform {0} and machine count {1}".FormatWith(targetPlatformId, targetPlatformCount)); List <VirtualMachineSelection> machineSelections = GetMachineSelections(targetPlatformId, masterMachineList, remainingPlatforms); // Now try to reserve the VMs. If the required VMs are more than the available, then // this is an error. Otherwise work down the list for the number of VMs required. Since // they are now ordered the VMs selected will be the least unique and those will more // special associations will be further down the list. TraceFactory.Logger.Debug("Machine Platform: {0} - {1} Requested, {2} Available".FormatWith(targetPlatformId, targetPlatformCount, machineSelections.Count)); if (machineSelections.Count >= targetPlatformCount) { for (int i = 0; i < targetPlatformCount; i++) { Reserve ( context, machineSelections[i].Machine.Name, targetPlatformId, currentTime, sessionId, GlobalSettings.Environment ); //Once the machine is reserved, remove it from the master list. masterMachineList.Remove(machineSelections[i].Machine); TraceFactory.Logger.Debug("Host {0} reserved".FormatWith(machineSelections[i].Machine.Name)); } } else { throw new VMInventoryException("Only {0} {1} machines available of {2} requested." .FormatWith(machineSelections.Count, targetPlatformId, targetPlatformCount)); } // Remove the platform that was just processed remainingPlatforms.Remove(targetPlatformId); } // Save all the final changes. Do this at the end so that if there // is a problem, there is nothing to roll back. context.SaveChanges(); } //AssetInventoryContext }); //reservation.Run return(true); }
public static void Run(string hostName, Action action) { GlobalLockToken token = new GlobalLockToken("MACHINE_START_B58B", TimeSpan.FromDays(1), TimeSpan.FromMinutes(10)); ExecutionServices.CriticalSection.RunConcurrent(token, action, _batchSize); }