Using the Service Manager Self-Service Portal to Manage Configuration Manager Clients
This post is the 5th in a series focused on making common administrative tasks in System Center and Azure available via the Service Manager Self-Service Portal. The Configuration Manager and Operations Manager Connectors pull a lot of information into Service Manager but not everything necessary to manage clients, agents, and other settings. This solution allows for the managing of Configuration Manager clients including Installing, Reinstalling, and Deleting them from Configuration Manager.
Series
Prerequisites
The scenarios were designed using the following
- System Center Service Manager 2012 R2
- Self-Service Portal configured and working
- Active Directory Connector configured and working
- Configuration Manager Connector configured and working
- Orchestrator Connector configured and working
- System Center Configuration Manager 2012 R2
- Discovery configured and working
- System Center Orchestrator 2012 R2
- SC 2012 Configuration Manager Integration Pack configured and working
- SC 2012 Service Manager Integration Pack configured and working
- Configuration Manager Console installed on runbook servers (open the console, make sure you can connect to your site server)
- Operations Manager Console installed on runbook servers
- Service Manager Console installed on runbook servers
- Runbook servers configured to allow PowerShell scripts to run
- Previous Blogs
- Sync Configuration Manager Client and Operations Manager Agent State in Service Manager
Create a service account or use the one created in the previous blog post
- Give the account admin rights to Service Manager
- Give the account admin rights to Configuration Manager
- Give the account admin rights to Operations Manager
Create a share to store scripts and logs or use the one created in the previous blog post
- Create a share that the service account you created and authenticated users will have access to on the Runbook Servers that will be used for this scenario.
- In the share, create a folder called "Automation" and give the service account access to it.
- Copy ManageCMClients.ps1 into the Automation Folder
- In the share, create a sub-folder called "Logs" in the Automation Folder and give the applicable administrators access to it. Orchestrator will write logs to this folder and admins can use these logs for troubleshooting.
- In the Logs folder, create a sub-folder called "SRLogs" and give authenticated users access to it. Users of the Service Manager Portal will use these to see the status of the Collection Sync task so they will need rights to this folder.
param
(
[Parameter(Mandatory=$true)]
$CMSiteCode,
[Parameter(Mandatory=$true)]
$CMSiteServer,
[Parameter(Mandatory=$true)]
$VerboseLogging,
[Parameter(Mandatory=$true)]
$ServiceRequest,
[Parameter(Mandatory=$true)]
$DeviceList,
[Parameter(Mandatory=$true)]
$Action,
[Parameter(Mandatory=$true)]
$ClientSiteCode
)
#Functions
function LogIt
{
param (
[Parameter(Mandatory=$true)]
$message,
[Parameter(Mandatory=$true)]
$component,
[Parameter(Mandatory=$true)]
$type )
switch ($type)
{
1 { $type = "Info" }
2 { $type = "Warning" }
3 { $type = "Error" }
4 { $type = "Verbose" }
}
if (($type -eq "Verbose") -and ($Global:Verbose))
{
$toLog = "{0} `$$<{1}><{2} {3}><thread={4}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath $Global:LogFile
$Global:LogBuffer = $Global:LogBuffer + $message + "`r`n"
Write-Host $message
}
elseif ($type -ne "Verbose")
{
$toLog = "{0} `$$<{1}><{2} {3}><thread={4}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath $Global:LogFile
$Global:LogBuffer = $Global:LogBuffer + $toLog + "`r`n"
Write-Host $message
}
if (($type -eq 'Warning') -and ($Global:ScriptStatus -ne 'Error')) { $Global:ScriptStatus = $type }
if ($type -eq 'Error') { $Global:ScriptStatus = $type }
}
function CreateServiceRequestLog
{
param($serviceRequest, $srLogPath)
LogIt -message ("Full Log File Path:" + $Global:LogFile) -component "Main()" -type 1
if ($serviceRequest)
{
$srLog = Join-Path $srLogPath ("\Logs\SRLogs\" + $serviceRequest + ".log")
LogIt -message ("Service Request Log File Path:" + $srLog) -component "Main()" -type 1
$Global:LogBuffer | Out-File -Append -Encoding UTF8 -FilePath $srLog
}
}
function GetScriptDirectory
{
$invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $invocation.MyCommand.Path
}
function GetCMSiteConnection
{
param ($siteCode, $siteServer)
try { $CMModulePath = Join-Path -Path (Split-Path -Path "${Env:SMS_ADMIN_UI_PATH}" -ErrorAction Stop) -ChildPath "ConfigurationManager.psd1" }
catch
{
LogIt -message ("Cannot get path to CM console, will try default path: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 4
LogIt -message ("Trying static path: C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1") -component "GetCMSiteConnection()" -type 4
$CMModulePath = 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
}
Import-Module $CMModulePath -ErrorAction Stop
try { $CMProvider = Get-PSDrive -PSProvider 'CMSite' -Name $siteCode -ErrorAction Stop }
catch
{
LogIt -message ("Cannot connect to CM site by Site Code, will retry: " + $siteCode + " Error: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 4
try { $CMProvider = New-PSDrive -PSProvider 'AdminUI.PS.Provider\CMSite' -Name $siteCode -Root $siteServer -Description 'SCCM Site' -ErrorAction Stop}
catch
{
LogIt -message ("Cannot connect to CM site by Server Name, exiting: " + $siteServer + " Error: " + $_.Exception.Message) -component "GetCMSiteConnection()" -type 3
exit
}
}
LogIt -message ("Connected to CM Site: " + $siteCode) -component 'GetCMSiteConnection()' -type 1
CD "$($CMProvider.SiteCode):\"
return $CMProvider
}
function ManageClients
{
param($action, $deviceList, $siteCode)
if ($action -eq "Install") { PushClient -siteCode $siteCode -list $deviceList }
elseif ($action -eq "Reinstall") { ReinstallClient -siteCode $siteCode -list $deviceList }
elseif ($action -eq "Remove") { RemoveClient -list $deviceList }
}
function PushClient
{
param($list, $siteCode)
$devices = $list.Split(",")
foreach ($device in $devices)
{
try
{
Install-CMClient -DeviceName $device -IncludeDomainController $false -AlwaysInstallClient $true -ForceReinstall $false -SiteCode $siteCode
LogIt -message ("Submitted Install Request for: {0}" -f $device) -component "Main()" -type 1
}
catch
{
LogIt -message ("Failed to submit Install Request for: {0} Error: " -f $device, $_.Exception.Message) -component "Main()" -type 1
}
}
}
function RemoveClient
{
param($list)
$devices = $list.Split(",")
foreach ($device in $devices)
{
try
{
Remove-CMDevice -DeviceName $device -Force
LogIt -message ("Submitted Remove Request for: {0}" -f $device) -component "Main()" -type 1
}
catch
{
LogIt -message ("Failed to submit Remove Request for: {0} Error: " -f $device, $_.Exception.Message) -component "Main()" -type 1
}
}
}
function ReinstallClient
{
param($list, $siteCode)
$devices = $list.Split(",")
foreach ($device in $devices)
{
try
{
Install-CMClient -DeviceName $device -IncludeDomainController $false -AlwaysInstallClient $true -ForceReinstall $true -SiteCode $siteCode
LogIt -message ("Submitted ReInstall Request for: {0}" -f $device) -component "Main()" -type 1
}
catch
{
LogIt -message ("Failed to submit ReInstall Request for: {0} Error: " -f $device, $_.Exception.Message) -component "Main()" -type 1
}
}
}
#Main
$Version = "1.0"
[bool]$Global:Verbose = [System.Convert]::ToBoolean($VerboseLogging)
$Global:LogFile = Join-Path (GetScriptDirectory) 'Logs\ManageCMClients.log'
$Global:ScriptName = 'ManageCMClients.ps1'
$Global:LogBuffer = ''
$Global:ScriptStatus = 'Success'
LogIt -message ("Manage CM Clients Script v{0}" -f $Version) -type 1 -component "Main()"
#Connect to CM and SM
$CM = GetCMSiteConnection -siteCode $CMSiteCode -siteServer $CMSiteServer
#Manage Clients
ManageClients -action $Action -deviceList $DeviceList -siteCode $ClientSiteCode
#Log Result
$Ret = $Global:ScriptStatus
LogIt -message ("Script Complete, Result: {0}" -f $Ret) -component "Main()" -type 1
#Create SR Log if needed
CreateServiceRequestLog -serviceRequest $ServiceRequest -srLogPath (GetScriptDirectory)
Create Manage Clients Runbook
This Runbook will manage the clients in Configuration Manager, trigger the Windows Computer Extended Runbook created previously, and finally update the Description in the Service Request with the result of the Windows Computer Extended Runbook.
- Open the Orchestrator Runbook Designer
- Create a new runbook
- Drag the "Runbook Control\Initialize Data" activity into the new runbook
- Rename it to "Get Runbook GUID"
- Create a new string parameter under "Details" called RunbookID, and click "Finish"
- Drag the "SC 2012 Service Manager\Get Object" activity into the new runbook
- Rename it to "Get Runbook Object"
- Fill out the following properties under "Details"
- Connection: <Your Service Manager Connection>
- Class: Runbook Automation Activity
- Filters: SC Object Guid Equals {RunbookID from "Get Runbook GUID"
- Click "Finish" and link "Get Runbook GUID" to "Get Runbook Object"
- Drag the "SC 2012 Service Manager\Get Relationship" activity into the new runbook
- Rename it to "Get SR GUID"
- Link "Get Runbook Object" to "Get SR GUID"
- Fill out the following properties under "Details"
- Connection: <Your Service Manager Connection>
- Object Class: Runbook Automation Activity
- Object Guid: {SC Object Guid from "Get Runbook Object"}
- Related Class: Service Request
- Click "Finish"
- Drag the "SC 2012 Service Manager\Get Object" activity into the new runbook
- Rename it to "Get Service Request"
- Link "Get SR GUID" to "Get Service Request"
- Fill out the following properties under "Details"
- Connection: <Your Service Manager Connection>
- Class: Service Request
- Filters: SC Object GUID Equals {Related Object Guid from "Get SR GUID"}
- Click "Finish"
- Drag the "Utilities\Query XML" activity into the new runbook
- Rename it to "Get Action"
- Link "Get Service Request" to "Get Action"
- Fill out the following properties under "Details"
- XML Text: {User Input from "Get Service Request"}
- Xpath Query: /UserInputs/UserInput[@Question='Action']/@Answer
- Click "Finish"
- Drag the "Utilities\Query XML" activity into the new runbook
- Rename it to "Get Site Code"
- Link "Get Action" to "Get Site Code"
- Fill out the following properties under "Details"
- XML Text: {User Input from "Get Service Request"}
- Xpath Query: /UserInputs/UserInput[@Question='Site Code']/@Answer
- Click "Finish"
- Drag the "Utilities\Query XML" activity into the new runbook
- Rename it to "Get Devices"
- Link "Get Site Code" to "Get Devices"
- Fill out the following properties under "Details"
- XML Text: {User Input from "Get Service Request"}
- Xpath Query: /UserInputs/UserInput[@Question='Devices']/@Answer
- Click "Finish"
- Drag the "Utilities\Query XML" activity into the new runbook
- Rename it to "Get Device Display Names"
- Link "Get Devices" to "Get Device Display Names"
- Fill out the following properties under "Details"
- XML Text: {Query result from "Get Devices"}
- Xpath Query: //@DisplayName
Under "Run Behavior" select "Flatten" and use a comma as the separator
Click "Finish"
Drag the "System\Run Program" activity into the new runbook
Rename it to "Execute Action in CM"
Link "Get Device Display Names" to "Execute Action in CM"
Fill out the following properties under "Details"
- Program Path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- Parameters: -File <local sharepath>\Automation\ManageCMClients.ps1 -CMSiteCode CAS -CMSiteServer sccm2012r2cas.contoso.com -VerboseLogging false -ServiceRequest {ID from "Get Service Request"} -DeviceList {Query result from "Get Device Display Names"} -Action {Query result from "Get Action"} -ClientSiteCode {Query result from "Get Site Code"}
- Working Folder: <local sharepath>\Automation
- Note, the data between the curly braces are Published Data from the Data Bus. This is obtained by right-clicking on the white space and selecting the appropriate variable.
Specify the service account under "Security"
Click "Finish"
Drag the "Runbook Control\Invoke Runbook" activity into the new runbook
Rename it to "Sync CI's in SM"
Link "Execute Action in CM" with "Sync CI's in SM"
Under "Details" choose the Windows Computer Extended runbook created in the previous blog and ensure that "Wait for completion" is checked
Configure the ServiceRequest parameter: {ID from "Get Service Request"}
Click "Finish"
Drag the "Text File Management\Find Text" activity into the new runbook
Rename it to "Get Script Result"
Link "Sync CI's in SM" to "Get Script Result"
Fill out the following properties under "Details"
- File: <local sharepath>\Automation\Logs\SRLogs\{ID from "Get Service Request"}.log
- File encoding: Auto
- Search text: Info:Script Complete, Result:
- Click "Finish"
- Drag the "SC 2012 Service Manager\Update Object" activity into the new runbook
- Rename it to "Update Description of Service Request"
- Fill out the following properties under "Details"
- Connection: <Your Service Manager Connection>
- Class: Service Request
- Object Guid: {SC Object Guid from "Get Service Request"}
- Fields: Description {Original line from "Get Script Result"} CMTrace Log File: {File path from "Get Script Result"}
- Click "Finish" and link "Get Script Result" to "Update Description of Service Request"
- Check in the Runbook, it should look similar to this:
Create Runbook Automation Activity Template
The Runbook Automation Activity Template will be link the Runbook we just created to a Service Request that we will be created later.
- Open the Service Manager Console
- Go to Administration\Connectors and Synchronize your Orchestrator Runbook Connector
- Go to Library\Templates and click "Create Template"
Name: Manage Clients RAA Template
Description: Manage CM Clients RAA Template
Class: Runbook Automation Activity
Management Pack: Click "New"
- Name: DataCenter Automation: Configuration Manager Clients UI
- Description: Configuration Manager Clients Templates and Offerings
Click OK, the Runbook Activity Form should appear. Check "Is Ready For Automation"
- Title: Manage Clients RA
- Description: Manage CM Clients RA
- Click the "Runbook" Tab
- Click "Select" and choose the Runbook created earlier
- Click "Edit Mapping" and choose "Object\Id"
- Click "OK"
Create Service Request Template
The Service Request Template is needed to create a Request Offering using the Runbook Activity Template created previously
- Open the Service Manager Console
- Go to Library\Templates and click "Create Template"
- Name: Manage Clients SR Template
- Description: Manage CM Clients SR Template
- Class: Service Request
- Management Pack: DataCenter Automation: Configuration Manager Clients UI
- Click OK, the Service Request Form should appear.
- Title: Manage Clients SR
- Description: Manage CM Clients SR
- Click the "Activities" Tab
- Click the Plus sign and select the Runbook Activity Template created earlier
- Click OK when the form is launched
Create Request Offering for Client Install
The Client Install request offering will be used to configure the user interface displayed via the self-service portal
Open the Service Manager Console
Go to Library\Service Catalog\Request Offerings and Click "Create Request Offering"
- Title: Install Client
- Description: Install CM Client
- Template name: Manage Clients SR Template
- Management Pack: DataCenter Automation: Configuration Manager Clients UI
User Prompts
- Action | Required | Simple List
- Devices | Required | Query Results
- Site Code | Optional | Simple List
- Configure user prompts
- Action
Devices
Select Class: Windows Computer
Display Columns
- NetBIOS Computer Name
- Principal Name
- Configuration Manager Client
Options
- Allow the user to select multiple objects: checked
- Add user-selected objects to template object as related items: checked and "Manage Clients SR - (Service Request)"
Site Code
- Type each site code in your environment that would be used for client installs
Map Prompts
- Map Action to the Service Request "Notes" property
- Map Site Code to the Service Request "Description" property
Publish
- Offering status: Published
Click "Create"
Create Service Offering for Manage Clients
The Manage Clients service offering will be used to display the Manage Client requests via the self-service portal
- Open the Service Manager Console
- Go to Library\Service Catalog\Service Offerings and Click "Create Service Offering"
- Title: Client Management
- Overview: CM Client Management
- Description: Manage CM Clients
- Management Pack: DataCenter Automation: Configuration Manager Clients UI
- Request Offerings: Manage Clients
- Publish: Published
- Click "Create"
Test Scenarios
- Open the Service Manager Self-Service Portal
- Click on the Client Management Service Offering
- Click on the Manage Clients Request Offering
- Click Go to request form
- Select the Action, a device, and the appropriate site code
- Click Next and then Submit
- Repeat testing for each action
- Go to "My Requests" and ensure they were completed successfully
- Use CMTrace to view output of the logs
Request Form
CMTrace Log Example
Summary
This solution allows for the installation, reinstallation, and deletion of Configuration Manager clients by using the Service Manager Self-Service Portal. This solution also synchronizes the state, on-demand, of the client as it is modified via the Portal.
Continue to the 6th post in this series: Managing Configuration Manager Collections using the Service Manager Self-Service Portal