Instruction file imported from opendsc/opendsc (
.github/instructions/lcm.instructions.md). Copyright stays with the author.
LCM Service (OpenDsc.Lcm)
Cross-platform .NET background service that continuously monitors and/or remediates DSC configurations.
Key Components
| File | Purpose |
|---|---|
LcmWorker.cs |
Main background service implementing Monitor and Remediate modes |
DscExecutor.cs |
Runs dsc config test / dsc config set, parses structured output |
LcmConfig.cs |
Configuration model with validation |
ConfigPaths.cs |
Platform-specific configuration paths |
CertificateManager.cs |
Client certificate lifecycle (Managed / Platform source) |
PullServerClient.cs |
HTTP client for Pull Server communication |
Operational Modes
- Monitor — periodically runs
dsc config testto detect drift, logs results - Remediate — runs
dsc config testthen appliesdsc config setwhen drift detected
Configuration Model
public class LcmConfig
{
public ConfigurationMode ConfigurationMode { get; set; } = ConfigurationMode.Monitor;
public ConfigurationSource ConfigurationSource { get; set; } = ConfigurationSource.Local;
public string ConfigurationPath { get; set; } // Path to main.dsc.yaml (Local mode)
public TimeSpan ConfigurationModeInterval { get; set; } = TimeSpan.FromMinutes(15);
public string? DscExecutablePath { get; set; } // Defaults to 'dsc' in PATH
public PullServerSettings? PullServer { get; set; } // Pull mode only
}
Configuration Priority (highest wins)
- Command-line arguments
- Environment variables (prefix
LCM_) - System-wide config file:
- Windows:
%ProgramData%\OpenDSC\LCM\appsettings.json - Linux:
/etc/opendsc/lcm/appsettings.json - macOS:
/Library/Preferences/OpenDSC/LCM/appsettings.json
- Windows:
- Bundled
appsettings.jsonin service directory appsettings.{Environment}.json
Key Patterns
Dynamic mode switching — watches for config changes, gracefully switches without restart:
_configChangeToken = lcmMonitor.OnChange((config, name) => {
OnConfigurationReloaded(config); // Cancels current operation, switches mode
});
DSC execution:
var result = await dscExecutor.ExecuteTestAsync(config.ConfigurationPath, config, LogLevel.Information);
// Returns DscResult with messages, results[], hadErrors
Logging — uses LoggerMessage source-generated attributes for performance. All log messages are defined as partial methods in worker classes.
Pull Mode Flow
- Load/generate client certificate (
CertificateSource: Managedauto-generates;Platformloads from store by thumbprint) - Register node if not already registered → receives
NodeId - Check certificate expiry → rotate via
RotateCertificateAsync()if needed - Check configuration checksum → download if changed
- Execute
dsc config test; applydsc config setif Remediate mode and drift found - Submit compliance report if
ReportCompliance: true
Pull Server Configuration
{
"LCM": {
"ConfigurationSource": "Pull",
"PullServer": {
"ServerUrl": "https://pull-server.example.com",
"RegistrationKey": "shared-secret",
"NodeId": null,
"ReportCompliance": true,
"CertificateSource": "Managed",
"CertificateRotationInterval": "60.00:00:00",
"CertificatePath": "{ConfigDir}/certs/client.pfx"
}
}
}
Local Testing
$env:LCM_ConfigurationPath = "C:\configs\local\main.dsc.yaml"
$env:LCM_ConfigurationMode = "Monitor"
$env:LCM_ConfigurationModeInterval = "00:05:00"
.\artifacts\Lcm\OpenDsc.Lcm.exe