Decommission AD descriptions #96

This commit is contained in:
Gary Sharp
2016-10-10 20:07:20 +11:00
parent 23975f8fc3
commit 0f20b16f41
7 changed files with 196 additions and 17 deletions
@@ -0,0 +1,138 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.IO;
using System.Linq;
namespace Disco.Services.Interop.ActiveDirectory
{
public class ADDeviceDescriptionUpdateTask : ScheduledTask
{
public override string TaskName { get { return "Active Directory Device Description Update"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
#region Required Helpers
private static string RequiredFilePath(DiscoDataContext Database)
{
if (Database.DiscoConfiguration.DataStoreLocation != null)
return Path.Combine(Database.DiscoConfiguration.DataStoreLocation, "_ADDeviceDescriptionUpdateRequired.txt");
else
return null;
}
public static bool IsRequired(DiscoDataContext Database)
{
var requiredFilePath = RequiredFilePath(Database);
if (requiredFilePath == null)
return false;
else
return File.Exists(requiredFilePath);
}
public static void SetRequired(DiscoDataContext Database)
{
var requiredFilePath = RequiredFilePath(Database);
if (requiredFilePath != null)
{
File.WriteAllText(requiredFilePath, "This file exists to indicate an update to AD Device Descriptions is required. It will automatically be deleted when the update completes.");
File.SetAttributes(requiredFilePath, FileAttributes.Hidden);
}
}
#endregion
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
if (IsRequired(Database))
{
// Schedule in 5mins
var trigger = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddMinutes(3));
this.ScheduleTask(trigger);
}
}
public static ScheduledTaskStatus ScheduleImmediately()
{
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ADDeviceDescriptionUpdateTask)).Where(s => s.IsRunning).FirstOrDefault();
if (existingTask != null)
return existingTask;
var instance = new ADDeviceDescriptionUpdateTask();
return instance.ScheduleTask();
}
protected override void ExecuteTask()
{
using (DiscoDataContext database = new DiscoDataContext())
{
Status.UpdateStatus(0, "Updating Active Directory Device Descriptions", "Reading Devices");
// Devices
var devices = database.Devices.Where(d => d.DeviceDomainId != null)
.ToList();
int failedTotal = 0;
int notFoundTotal = 0;
int completedTotal = 0;
// Refine valid devices
devices = devices.Where(d => ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId)).ToList();
foreach (var domainGroup in devices.GroupBy(d => d.ComputerDomainName).ToList())
{
ADDomain domain;
if (domainGroup.Key != null && ActiveDirectory.Context.TryGetDomainByNetBiosName(domainGroup.Key, out domain))
{
var controller = domain.GetAvailableDomainController(RequireWritable: true);
foreach (var device in domainGroup)
{
completedTotal++;
if ((completedTotal % 10) == 0)
{
Status.UpdateStatus((100D / devices.Count) * completedTotal, $"Processing: {device.DeviceDomainId} ({device.SerialNumber})");
}
try
{
var adAccount = device.ActiveDirectoryAccount();
if (adAccount == null)
{
notFoundTotal++;
if (!device.DecommissionedDate.HasValue)
{
Status.LogWarning($"Unable to locate [{device.DeviceDomainId}] for commissioned device [{device.SerialNumber}] in the domain");
}
}
else
{
adAccount.SetDescription(controller, device);
}
}
catch (Exception ex)
{
failedTotal++;
Status.LogWarning($"Error when setting description of computer account [{device.DeviceDomainId}] for device [{device.SerialNumber}]: [{ex.GetType().Name}] {ex.Message}");
}
}
}
}
// Finished - Remove Placeholder File
var requiredFilePath = RequiredFilePath(database);
if (requiredFilePath != null && File.Exists(requiredFilePath))
File.Delete(requiredFilePath);
Status.SetFinishedMessage($"Finished updating device descriptions for {devices.Count:N0}. {notFoundTotal:N0} were not found. {failedTotal:N0} failed.");
Status.LogInformation(Status.FinishedMessage);
Status.Finished();
}
}
}
}
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
namespace Disco.Services.Interop.ActiveDirectory
{
@@ -178,15 +179,18 @@ namespace Disco.Services.Interop.ActiveDirectory
using (var deAccount = WritableDomainController.RetrieveDirectoryEntry(this.DistinguishedName))
{
var descriptionProp = deAccount.Entry.Properties["description"];
if (descriptionProp.Count > 0)
if (descriptionProp.Count != 1 || (descriptionProp[0] as string) != Description)
{
descriptionProp.Clear();
if (descriptionProp.Count > 0)
{
descriptionProp.Clear();
}
if (!string.IsNullOrEmpty(Description))
{
descriptionProp.Add(Description);
}
deAccount.Entry.CommitChanges();
}
if (!string.IsNullOrEmpty(Description))
{
descriptionProp.Add(Description);
}
deAccount.Entry.CommitChanges();
}
}
public void SetDescription(string Description)
@@ -196,19 +200,28 @@ namespace Disco.Services.Interop.ActiveDirectory
public void SetDescription(ADDomainController WritableDomainController, Device Device)
{
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
var descriptionBuilder = new StringBuilder();
if (Device.AssignedUserId != null)
if (Device.DecommissionedDate.HasValue)
{
descriptionBuilder.Append(Device.AssignedUser.UserId).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
descriptionBuilder.Append("Decommissioned: ")
.Append(Device.DecommissionReason.ReasonMessage())
.Append(" (").Append(Device.DecommissionedDate.Value.ToString("yyyy-MM-dd")).Append(')');
}
if (Device.DeviceModelId.HasValue)
else
{
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
}
if (Device.AssignedUserId != null)
{
descriptionBuilder.Append(Device.AssignedUser.UserId).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
}
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
if (Device.DeviceModelId.HasValue)
{
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
}
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
}
string description = descriptionBuilder.ToString().Trim();
if (description.Length > 1024)
@@ -336,7 +349,7 @@ namespace Disco.Services.Interop.ActiveDirectory
{
i.Entry.UsePropertyCache = false;
i.Entry.MoveTo(ou.Entry);
// Update Distinguished Name
this.DistinguishedName = i.Entry.Properties["distinguishedName"][0].ToString();
}