Master Plan – Automating an SCCM Site Installation

I was thinking, “Man, (or woman), it would sure be coolio if I could push one button and *presto!* I have a fully-built SCCM site server, without having to install anything but Windows itself“.  There’s some really shiny stuff out there already, like hydration kits and prerequisite installers.  But then, I thought “That’s not enough!  I need it to be ‘real’.  I need more!!” I want to build the site itself, and configure EVERYTHING to be JUST LIKE A REAL site out in the real world.  So, here’s how I sketched it out…

  1. Install Windows Server
    1. Do NOT patch it
  2. Create all the folders in all the right places
  3. Install Windows Server roles and features
  4. Install ADK for Windows 10
  5. Install MDT
  6. Install SQL Server with file auto-growth settings, Domain Service accounts, and register the SPNs
  7. Configure SQL Server memory limits
  8. Install the WSUS role
  9. Run the WSUS post-install configuration step
  10. Create file NO_SMS_ON_DRIVE.SMS on C:\
  11. Install Configuration Manager 1511 (not the latest baseline) with a Site Code, Site Name, Roles
  12. Configure Discovery Methods, including Network Discovery, where each one runs every day
  13. Initiate Discovery Methods
  14. Create Site Boundaries and Boundary Groups
  15. Configure Client Settings
  16. Configure Client Push Installation
    1. Configure automatic client installation and client upgrades
  17. Create and Configure Query-based Collections
  18. Configure all Query Collections to update every hour
  19. Create and Configure a set of Applications
  20. Deploy Applications to Collections
  21. Add everyone in IT to the “Full Administrator” RBAC role in SCCM
  22. Add everyone in IT to the SQL Server server admins role
  23. Install Symantec Antivirus, McAfee Antivirus, Cylance Agent and anything else on the same host
  24. Turn on the Domain Firewall
  25. Create an OSD configuration
    1. Windows 10 Image captured from a 5-year old machine with EVERY conceivable application installed.  If it’s not at least 10 GB, we have to repeat until it does.
    2. Boot Images – add every component and every driver for every model we have
    3. Drivers – everything.  all of it.
    4. Applications – only those product names which begin with 0 – 9 or A – Z.
    5. Task Sequences – create a dozen with names that mean nothing to anyone unless they’re on drugs
    6. Deploy each TS  to “All Systems” via PXE without a password
  26. Set a scheduled task to reboot the site server every night at the same time the backups and SQL jobs are supposed to run
  27. Add “Domain Users” to the local Administrators group
  28. Turn off Site Maintenance tasks: backups, reindex.
  29. Do not install Ola’s tools – or Steve’s guidelines for SQL – they just make it run too well.
  30. Install Google Chrome, MS Office, Adobe Reader and any freeware applications I can find on the primary site server
  31. Change the NIC to use DHCP
  32. Install additional Web Site applications within IIS
  33. Verify no PKI exists and then configure all clients to use PKI only.
  34. Take a snapshot/checkpoint every day and once a month revert to a previous snapshot from a week earlier.
  35. Post job openings to all the job search sites insisting the candidate ONLY know Ghost or Acronis and has never touched or even heard of SCCM or MDT, ever.
  36. Configure Azure with O365 and and EMS tenant
  37. Integrate SCCM and EMS
  38. Enroll devices in EMS/Intune
  39. Deploy SCCM clients to the Intune devices
  40. Automatically open support tickets with Microsoft on why the clients stop working in EMS/Intune

That should just about cover it.

SCCM, SQL, DBATools, and Coffee

Warning:  This article is predicated on (A) basic reader familiarity with System Center Configuration Manager and the SQL Server aspects, and (B) nothing better to do with your time.

Caveat/Disclaimer:  As with most of my blog meanderings, I post from the hip.  I fully understand that it exposes my ignorance at times, and that can be painful at times, but adds another avenue for me to learn and grow.

marie-wilson-cooking

I don’t recall exactly when I was turned onto Ola Hallengren, or Steve Thompson, but it’s been a few years, at least.  The same could be said for Kent Agerlund, Johan Arwidmark, Mike Niehaus, and others.  None of whom I’ve yet to meet in person, but maybe some day.  However, that point in time is when my Stevie Wonder approach to SQL “optimization” went from poking at crocodiles with a pair of chopsticks, to saying “A-Ha!  THAT’s how it’s supposed to work!

As a small testament to this, while at Ignite 2016, I waited in line for the SQL Server guy at his booth, like an 8 year old girl at a Justin Bieber autograph signing, just to get a chance to ask a question about how to “automate SQL tasks like maintenance plans, and jobs, etc.”.  The guy looked downward in deep thought, then looked back at me and said “Have you heard of Ola Hallengren?”  I said “Yes!” and he replied, “he’s your best bet right now.

Quite a lot has changed.

For some background, I was working on a small project for a customer at that time focusing on automated build-out of an SCCM site using PowerShell and BoxStarter.  I had a cute little gist script that I could invoke from the PowerShell console on the intended target machine (virtual machine), and it would go to work:

  • Install Windows Server roles and features
  • Install ADK 10
  • Install MDT 2013
  • Install SQL Server 2014
  • Adjust SQL memory allocations (min/max)
  • Install WSUS server role and features
  • Install Configuration Manager
  • Install ConfigMgr Toolkit 2012 R2
  • and so on.

Since it was first posted, it went through about a dozen iterative “improvements” (translation: breaking it and fixing and improving and breaking and fixing, and repeat).

The very first iteration included the base build settings as well, such as naming the computer, assigning a static IPv4 address, DNS servers and gateway, join to an AD domain, etc.  But I decided to pull that part out into a separate gist script.

The main thing about this experiment that consumed the most time for me was:

  1. On-the-fly .INI construction for the SQL automated install
  2. On-the-fly .INI construction for the SCCM install
  3. On-the-fly SQL memory allocation configuration

Aside from the hard-coding of content sources (not included on this list), item 2 drove me nuts because I didn’t realize the “SA expiration” date property was required in the .INI file.  The amount of coffee I consumed in that 12 hour window would change my enamel coloring forever.  Chicks dig scars though, right?  Whatever.

Then came item 3.  I settled on the following chunk of code, which works…

$SQLMemMin = 8192
$SQLMemMax = 8192
...
write-output "info: configuring SQL server memory limits..."
write-output "info: minimum = $SQLMemMin"
write-output "info: maximum = $SQLMemMax"
try {
  [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
  [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
  $SQLMemory = New-Object ('Microsoft.SqlServer.Management.Smo.Server') ("(local)")
  $SQLMemory.Configuration.MinServerMemory.ConfigValue = $SQLMemMin
  $SQLMemory.Configuration.MaxServerMemory.ConfigValue = $SQLMemMax
  $SQLMemory.Configuration.Alter()
  write-output "info: SQL memory limits have been configured."
}
catch {
  write-output "error: failed to modify SQL memory limits. Continuing..."
}

But there’s a few problems, or potential problems, with this approach…

  1. It’s ugly (to me anyway)
  2. The min and max values are static
  3. If you change this to use a calculated/derived value (reading WMI values) and use the 80% allocation rule, and the VM has dynamic memory, it goes sideways.

Example:

$mem = $(Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory
$tmem = [math]::Round($mem/1024/1024,0)
...

I know that option 2 assumes a “bad practice” (dynamic memory), but it happens in the real world and I wanted to “cover all bases” with this lab experiment.  The problem that it causes is that the values returned from a WMI query can fluctuate along with the host memory allocation status, so the 80% value can be way off at times.

Regardless, forget all that blabber about static values and dynamic tragedy.  There’s a better way.  A MUCH better way.  Enter DBATools.  DBATools was the brainchild of Chrissy LeMaire, which is another name to add to any list that has Ola’s name on it. (side note: read Chrissy’s creds, pretty f-ing impressive). There are other routes to this as well, but I’ve found this one to be most user friendly for my needs. (Feel free to post better suggestions below, I welcome feedback!)

Install-Module dbatools
$sqlHost = "cm01.contoso.com"
$sqlmem = Test-DbaMaxMemory -SqlServer $sqlHost
if ($sqlmem.SqlMaxMB -gt $sqlmem.RecommendedMB) {
  Set-DbaMaxMemory -SqlServer $sqlHost -MaxMB $sqlmem.RecommendedMB
}

This is ONLY AN EXAMPLE, and contains an obvious flaw: I’m not injecting an explicit 80% derived value for the -MaxMB parameter.  However, this can be accomplished (assuming dynamic memory is not enabled) as follows…

Install-Module dbatools
$sqlHost = "cm01.contoso.com"
$sqlmem = Test-DbaMaxMemory -SqlServer $sqlHost
$totalMem = $sqlmem.TotalMB
$newMax = $totalMem * 0.8
if ($sqlmem.SqlMaxMB -ne $newMax) {
  Set-DbaMaxMemory -SqlServer $sqlHost -MaxMB $newMax
}

Here’s the code execution results from my lab…

sqlmemory2

You might have surmised that this was executed on a machine which has dynamic memory enabled, which is correct.  The Hyper-V guest VM configuration is questionable…

hyperv_setup1.png

This is one of the reasons I opted for static values in the original script.

Thoughts / Conclusions

Some possible workarounds for this mess would be trying to detect dynamic memory (from within the guest machine) which might be difficult, or insist on a declarative static memory assignment.

Another twist to all of this, and one reason I kind of shelved the whole experiment, was a conversation with other engineers regarding the use of other automation/sequencing tools like PowerShell DSC, Ansible, and Terraform.

The final takeaway of this is to try and revisit any projects/code which are still in use, to apply newer approaches when it makes sense.  If that means shorter code, improved security and performance, more capabilities, greater abstraction/generalization (for reuse), or whatever, it’s good to bring newer ideas to bear on older tools.  In this example, it was just replacing a big chunk of raw .NET reflection code with cleaner and more efficient PowerShell module code.  Backing out 10,000 feet, the entire gist could be replaced with something more efficient.

More Information

DBATools – twitterslackyoutubegithub

Ola Hallengren – web  (Ola doesn’t tweet much, yet)

My Twitter list of super awesometacular increditastical techno-uber genius folks – HERE

Back to my coffee.  I hope you enjoyed reading this!  Please post comments, thoughts, criticisms, stupid jokes, or winning lottery numbers below.  If nothing else, please rate this article using the stars above? – Thank you!

Expert Tips for SCCM Log Analysis

1wearandtear

1. Locate cmtrace.exe (or another suitable “active” log viewer)
2. Open cmtrace.exe and click “yes” to register it as default log viewer
3. Consume precisely 5 quarts of a strong, caffeinated liquid substance
4. Browse to location (folder) with log files and double-click desired log file
5. Rub eyelids approximately 12 times, make sure to yawn fully and loud
6. Stare at log details and look for any lines colored in red.
7. Ignore red lines which do not actually display an error, but are instead mentioning that they’re looking for an error
8. Ignore yellow lines which do not actually display a warning, but instead show mention of looking for warnings
9. Rub eyelids 12 more times.
10. Announce to whomever interrupts that you’re busy reviewing log files (the louder the better)
11. Open another log file (selected at random)
12. Stare intently at one line, without scrolling
13. Rub chin, squint, and nod slightly. You may also say “hmmmm”
14. Scroll and repeat step 12
15. Repeat steps 10 through 13, approximately 5 more times.
16. Open browser and begin searching for fragments of error messages along with “sccm error log…”
17. Inhale deeply, exhale loudly.
18. Consume more caffeinated liquids
19. Rub eyes some more
20. Lunch break.

(Seriously) 5 Most Common SCCM Issues

Joking aside (for a few minutes anyway)…

teamamerica3

The five (5) most common root causes for SCCM site issues that I’ve seen over the past year, working as a consultant.

  • Site scale:  (smallest) 500, (largest) 180,000
  • Site types: CAS (5%), Primary alone (85%), Primary with Secondaries (5%), None (5%) aka “new install”
  • Avg staffing: (IT dept) 12-24 (SCCM admin) 1
  • Avg coffee consumption: 1 cup per 30 minutes
  • Avg sleep: 5.2 hours

1 – Lack of planning before installing the environment

In the past year alone, I’ve run across almost a dozen sites which had a CAS and didn’t need one, or Secondary sites, and didn’t need them, and so on.  Some didn’t have a FSP and could’ve used one.  Some weren’t using the appropriate credentials for client installations, network access and so on.  And lately, many seem to have pinned their plans on outdated platforms, such as Windows Server 2008 R2 or SQL Server 2012.  At least keep them patched (e.g. SQL 2012 SP3 CU9)

2 – Lack of monitoring and following-up on warnings/errors

Of the last 24 customer engagements I’ve been involved with, roughly 60% do not keep a daily watch over site issues (sites, components, clients, content distribution, deployments, etc.).  Of those that do monitor, about half ignore lingering warnings which impact site performance.

3 – Lack of cohesive management

This varies by scale/size of the organization (at least in my world).   Often it’s a matter of job roles and organizational divisions.  For example, DBA’s controlling the SQL Server environment without allowing SCCM admins any direct access (very bad).  Or AD admins who drag their feet (or push back) on requests for schema extensions, keeping AD accounts “clean” and so on.  Or Network Admins who fight back against using PXE, no matter what the rationale.  In many cases, it rolls up to team managers who don’t work well together, so resolving conflicts and barriers is difficult, especially when the CTO or CIO prefer to avoid dealing with it.  My advise: deal with it!  The good of the company outweighs your stupid personal disagreements.

4 – Lack of keeping up on updates

Whether it’s the Windows Server, SQL Server, ADK, MDT or Configuration Manager itself, all of these require persistent support and oversight. Keep them patched.  But more importantly, READ THE PATCH details first.  Understand what’s being “fixed” or “modified” (or deprecated) as well as “known issues”.  You can save yourself a shit-ton (that’s a scientific measurement, by the way) of headaches and support costs by not blindly installing without understanding.  However, do not avoid patching simply because of fear and doubt.  You work in IT, which means “change” is inevitable and continuous.  It’s why the “soft” in “software” exists (trust me, Babbage wasn’t kidding around).

5 – Inefficient use of features

This one alone could be broken out into sub-categories actually, and now that I mentioned it, I will…

a – Ignoring features which are not fully understood (not doing research)

b – Continuing to use outdated methods (disk imaging, for one, like Acronis or Ghost)

c – Ignoring other System Center capabilities (SCOM, Orchestrator, etc.)

d – Not following “best practices” (excessive permissions on common accounts, incorrect client installation settings

e – Paying for 3rd-party products which SCCM (or other System Center) capabilities could provide (depends upon the individual requirements of course)

f – Ignoring 3rd-party products out of fear of the unknown (FUD)

g – Ignoring new features added with each build (current branch), such as Azure, OMS, UA, and mobile device features

h – [my peeve] Inefficient mapping of tools to processes.  Such as ignoring Group Policy in favor of doing everything in SCCM or via scripts. Continuing to use familiar solutions even when newer and better (cheaper, faster, more efficient, more reliable) solutions are available.

i – Insufficient use of Internet search tools (Google, Bing, etc.)

Did I miss anything?

5 Tips for Fixing Broken SCCM DMZ services

080530-N-7981E-259

The following five (5) tips should help even the most seasoned SCCM expert determine the root cause for problematic DMZ environments.

Reasons you’re having trouble with your SCCM DMZ

1 – You don’t actually have a DMZ

2 – The DMZ doesn’t contain a SCCM site system, nor an AD Forest trust, nor any network connections back into the internal network.  You might also not have any SCCM clients that operate in the DMZ.

3 – You have no idea what “SCCM” or “DMZ” are.  And you don’t really care.

4 – You work in the Finance department.

5 – Why are you reading this?

Sorry – I needed a break from mind-numbing emails and phone calls today.

CMWT 2017.04.24.01 Released

cmwtlogo5

I’m trying something different this time, so I will let you tell me if it’s better or worse than what I was doing.

What I was doing: Uploading raw files to the Github repo, and uploading a .ZIP to a separate repo under the same account.

What I’m trying now: Uploading raw files to the Github repo and let everyone download the entire stack using the Github “clone or download” feature.  The Download option makes a .ZIP of the entire mess, so it seems like a better option (so far).

What’s new in 2017.04.24.01

  • Bug fixes to AD users, groups and SCCM device details
  • AD user page now allows adding to AD groups
  • AD groups are filtered using the _protectedgroups.txt file (you can edit this to your liking)

More info here

SCCM Collection Queries by Server Role

MFfn7

Rather than spew forth a bunch of sample queries, I’ll just hand you a virtual fishing rod, a case of imaginary beer, and point you to the make-believe boat.  This little procedure came in handy today with a customer I was helping.  I hope it helps you as well…

  • Device Collections
    • Create Device Collection
      • Name: Servers – WDS Servers (example)
        • Limiting collection: (whatever has servers with clients)
        • Use incremental updates for this collection (check)
        • Add Rule > Query-Rule
          • Name: 1 (or whatever you want, I’m lazy)
          • Edit Query Statement:
            • Omit duplicate rows (check)
            • Criteria tab
              • “Select” button (click it)
              • Class = Server Feature
              • Attribute = Name (click OK)
                • Is Equal To (leave as-is)
              • Click the “Value” button
                • Select an appropriate Feature Name
                • Enjoy a cold one!