DSC in a vmware template?

I’m an active CBT nuggets subscriber and I just watched Don Jones’s series there on DSC, awesome stuff. And I’m getting a better grasp of what it can and can’t do. I’ve followed the guides on the net out there on setting up a pull server, so I have that. I have not yet pushed/pulled a config to/from a target/slave server “node”. I’m just at more of a brainbuster / trying to wrap my head around something issue than a technical one and hoping someone can shed some light:

Goal: I have a 2012 R2 template that has the latest DSC module and I redeploy this template using a vmware customization script that applies an IP address, changes the computername, and joins the domain. I want to setup such a template computer to automagically configure itself based on its AD-OU or AD computer group using DSC.

Problem: I’m at the point where I want to SetPullConfig on the target nodes to become slaves to my pull server. In all these guides I’m reading they’re talking about GUIDs vs hostnames, GUIDs required for pull while hostnames are good for push. It gets a little confusing, do I use a CSV file or a sql DB, or the brilliant idea I saw about AD guid? Is there a more comprehensive guide for the newbie about the AD guid way?

Topping it off, most guides seem to suggest you ‘should’ do things in this order:

  1. Create a MOF with a config for a target node (like install IIS on that server)
  2. Generate guid for node
  3. rename mof file
  4. apply to pull server

When my goal is more like:

  1. I don’t have a config for you yet.
  2. AD guid is fine, but if I have to generate one myself err what’s best practice?
  3. would I even have a mof file at this point - I don’t have any config for you!
  4. Ask me for your config and you shall receive!

I like the idea of being able to bring up a new server from template and it join itself to a particular server config group based on what location/group I add it to in AD. It’s not very clear to me how to go about getting there, any help would be appreciated!

If you want the servers that are in a particular OU to be all configured the same way, what you could do is have them use the same GUID and MOF file. You would just need some mechanism to pull that GUID out of AD and configure the Local Configuration Manager on the host (perhaps via a startup script, or something along those lines.)

That could be an awesome way to start, but I fear that it lacks some flexibility. I ‘expect’ that all my servers will share about 90% of their configurations. Then I’ll have some small ‘sub categories’ of servers that need additional input. Granted that could be sorted out by copying the same MOF and telling it to look at servers in a sub-OU of the first.

I’m thinking I like your idea Dave, but I want it to be more of a “I can go back on my word” kind of situation. I’m thinking a scheduled task that checks that the server is still in that OU, and if not it takes the inverse of the original MOF. Thus if I take a server out of a DSC targeted OU and place it elsewhere it will unconfigure itself, uninstall/remove roles/features no longer required, and delete any additional content. I can then move it to a new OU to receive a new config.

Using the ‘same guid aproach’ sort of sounds like “I define what a prod webserver looks like” and that’s it, and do the same for other ‘categories’ of server. It’d be nice to nitpick about individual servers after the fact, but there’s ways around that and it’s likely to be a more uniform environment anyway.

Thanks :slight_smile:

DSC doesn’t really have a way to “undo” a configuration, unless you were to write those inverted MOFs yourself. (If all of your OU configurations defined exactly the same settings, including defaults for things that they don’t care about, then I guess you’d get the same effect in the long run.)

From what I can see so far, it sounds kind of like you’re just reinventing Group Policy here, and that’s likely to be a bumpy ride.

Edit: In DevOps shops, where DSC is most likely to be used, you generally don’t bother trying to undo a configuration. You just kill the VM and build a new one with the config you want. :slight_smile:

Yeah, good point about reinventing the wheel :). I’m working on getting out of my ‘old ways’ here and finding new ways to work. The idea sprouted largely out of my familiarity with group policy. It’s always ‘more comfortable’ to work with what you know haha! But that doesn’t make it the best.

I like how DSC has more scalability of ‘things you can do’ and the online help/resources out there than group policy. I imagine that DSC will ultimately replace group policy except for certain ‘niche’ things in the long term.

Well I have to figure out that mechanism for using an OU guid now as you mentioned. google foo time!

New roadblock / Success story!

So I found an article on setting everything up to point to an AD OU, and use the PC guid from AD. The guy’s script is here: DSC/TargetADResourcesDSC.ps1 at master · ThojoUno/DSC · GitHub

I modified it so that all it would do is install IIS, copy some files to inetpub, and that’s about it. Went through it and it works on my servers!

Now my roadblock is that I’m scratching my head: I want to modify 1 server in particular and add more roles to this. (lets imagine that this is the odd one of the bunch that has just 1 thing I want different, but want that also to be managed by DSC). Do I have to edit the MOF file directly? I already have a MOF file with checksums and it’s working. Can I use powershell to modify the existing MOF for the single server in question?

In broader words I guess, how do I modify an existing DSC config for a node that’s already managed by another, grander/larger config?

Suppose that gets fixed / Keep whatever the fix was in mind

Next issue is automation:

I have this working now in that when executed manually it’ll review the OU, create GUIDs/MOFs of each object in that OU. I imagine that I can schedule this task to auto run so that new servers added to the OU get populated. I can also automate it easily enough to instruct the targets to talk to the Pull server. Here’s the problem: if the fix we find for the “odd server” is a manual/one time fix that needs to be applied after the ‘automation’ I’m referring to, how will I incorporate the ‘fix’ for the ‘odd server’ into automation?

Hope I’m making sense LOL, my mind is going bonkers. I’m more of a script kiddie than a “write-from scratch” person.

As far as DSC is concerned, each server has only one configuration document. It doesn’t merge or overwrite settings the way Group Policy does. (PowerShell v5 will have a partial configuration feature, but even then, you have to explicitly tell the node which MOF documents to apply.)

The servers that you want to have different settings would each need their own unique ConfigurationID, and the associated MOF file would need to contain the complete configuration for that server (including all of the settings that would normally be applied for that OU.) However, you don’t really need to think in terms of the MOF document too much, since that’s just the output from your configuration function. Instead, think of how you’d set up your Configuration function and its input (typically a hashtable passed to the -ConfigurationData parameter) in order to produce the MOF files that you need. If you’re going to need servers that are different from the other servers in their OU, then I’d probably scrap the idea of sharing a ConfigurationID among different hosts. Too much manual effort there. Instead, go with the example in the article you linked, where each host just pulls down its computer object’s GUID from Active Directory. (I’d probably not run that as a Push, but the same idea is fine.)

Then, in your ConfigurationData and Configuration function, you can have logic that builds up settings based on a host’s OU, for specific computers, or even based on group membership. That’s entirely up to you; the logic can cover anything you’d like, since the configuration is just executable PowerShell code.

I wouldn’t say that this will be simple, but it’s definitely possible. You’d just have to be careful about how you defined the settings and the logic, since the MOF files produced by a configuration can’t duplicate the same resource with the same set of key properties for a particular host. (e.g. you couldn’t have a set of OU settings that says to make sure IIS is absent, then a host-specific override to say that IIS should be present, unless you were careful to have the logic take care of making sure that only one WindowsFeature resource existed with name Web-Server. That sort of logic could potentially be easy to get wrong and tricky to read.)

You might want to check out the DscConfiguration module in GitHub - PowerShellOrg/DSC at development . It’s not tied to Active Directory, but does provide an example of how you might split up your configuration data in a hierarchical fashion, having node-specific settings override settings defined in a particular site, group of nodes, or global.

Then, in your ConfigurationData and Configuration function, you can have logic that builds up settings based on a host's OU, for specific computers, or even based on group membership. That's entirely up to you; the logic can cover anything you'd like, since the configuration is just executable PowerShell code.

I wouldn’t say that this will be simple, but it’s definitely possible. You’d just have to be careful about how you defined the settings and the logic, since the MOF files produced by a configuration can’t duplicate the same resource with the same set of key properties for a particular host. (e.g. you couldn’t have a set of OU settings that says to make sure IIS is absent, then a host-specific override to say that IIS should be present, unless you were careful to have the logic take care of making sure that only one WindowsFeature resource existed with name Web-Server. That sort of logic could potentially be easy to get wrong and tricky to read.)

Okay so I follow you with the basic idea:

  1. use example from the guy to pull from AD, and each host/node will use its own AD guid and have its own unique MOF file
    • Is it possible to take the MOF file I’ve already generated in bulk using this guys example, and reverse it back into powershell for editing that particular host manually/seperately from this whole script? So MOF –> powershell
  2. I understand that you can’t have negating configurations like a deny with an exception. I’m looking at this more from “Here’s my basic server managed by this bulk script, now I need to add more”. So 10 IIS servers, 1-2 of them need FTP and are otherwise the same.
  3. I’m still trying to figure out “targeting”. The guys example makes life real easy in targeting in that it bulk picks up everything in the OU I specify. Now if I understand you right, I can expand upon that and setup logic that combines a config on a more host granular level (as long as there’s no conflicting config entries)?

The how is where I’m stumped haha. In the guys example below he’s got his target of $Allnodes = ADservers in my OU, then in the actual CONFIGURATION he’s got Node = $allnodes.guid

#Pull computer objects for AD
function GetComputers {
    import-module ActiveDirectory
    Get-ADComputer -SearchBase "MY-OU-PATH" -Filter *
}
$computers = GetComputers

#Pull list of computers and GUIDs into hash table
$ConfigData = @{
    AllNodes = @(
        foreach ($node in $computers) {
            @{NodeName = $node.Name; NodeGUID = $node.objectGUID;}
        }
    )
}

#Set your configuration choices. In this case, install IIS, and replace the default website.
Configuration PullDemo {
    Node $Allnodes.NodeGUID {
                WindowsFeature IIS {
                    Ensure = 'Present'
                    Name = 'Web Server'
                }

Questions:

  • How do I add ‘roles’ to specific nodes in “All Nodes” and narrow it down by ‘roles’ in the existing situation?
  • I want to set roles kind of like in this technet article http://technet.microsoft.com/en-ca/library/dn249925.aspx, but have it dynamic in that its by a variable pcname: DEVwebXXXXX or PRODwebxxxx, DEVftpxxxxx etc
  • Once I have said role, how would I apply it to the config description? Would it be like this where it’s part of the same CONFIGURATION, but the node is re-specified?:

#Set your configuration choices. In this case, install IIS, and replace the default website.
Configuration PullDemo {
Node $Allnodes.NodeGUID {
WindowsFeature IIS {
Ensure = ‘Present’
Name = ‘Web Server’
}

Node $AllNodes.Where{$_.Role -eq "DEVftpSVR"}.NodeName [i][[s]node $AllNodes.Where{$_.Role -eq "WebServer"}.NodeGUID[/s]????[/i]
                WindowsFeature IIS {
                Ensure = 'Present'
                Name = 'FTP-Server'
              }

}

Thanks again, my brain is melting, I’m melting!

Hey Dave,

Wanted to formally apologize to you (And Don while I’m at it). I’m very much rushing headlong into something that I don’t know enough about and have been asking questions, when the answer really was: go back and learn the basics of powershell. I’d never worked with a hashtable before, much less known what a hashtable really was. I’ve gone to Don’s CBT nuggets powershell series and watched the videos about powershell providers, drives, and hashtables and practiced it (spent the better part of the day on it) and I totally get it now. I’ve been able to answer my own question about ‘specifying roles’, here’s the result.

#Pull computer objects for AD
function GetWebServers {
import-module ActiveDirectory
Get-ADComputer -SearchBase “MY ACTIVE DIRECTORY OU” -Filter *
}
$WebServers = GetWebServers

#Pull list of WebServers and GUIDs into hash table
$WebServerConfigData = @{
AllNodes = @(
foreach ($node in $WebServers) {
@{NodeName = $node.Name; NodeGUID = $node.objectGUID; NodeRole = ‘WebServer’}
}
)
}

From there, I can probably add more to the hashtable to specify it’s in a dev, qa, stage or prod environment, I can specify other “GetServers” commands based on server types, and keep it all in one config. And to top it off I can target servers with DSC based on role.

Thanks again, and sorry to come around here all demanding and newbish without having taken enough time to acquaint myself with the basics.

Ryan

No worries! Gotta start somewhere. :slight_smile: