PowerShell Desired State Configuration (DSC) Journey – Day 2

If you haven’t read the DSC E-Book by Don Jones, do yourself a favor and do that.  It can be found here.

If you missed Day 1, you can find it here.

One of the reasons why I mention Don’s book (and not just because it’s awesome and he needs people to review it) is that I immediately learned several useful things.  Of the most importance to me on Day 2 of this journey is that you can parameterize your Configurations the same way you can parameterize PowerShell scripts and functions.

When we left off yesterday I had a Configuration Script that may or may not have been functional and I was getting ready to run it.  Here is the script in its current form.

Configuration TestConfig {

    Node $targetcomp {

        File ScriptPresence {

        Ensure = "Present"
        Type = "Directory"
        Recurse = $False
        SourcePath = "C:\Scripts\DSC"
        DestinationPath = "C:\Scripts"

        }

    }

}

Knowing what I know now about parameterizing the Configuration, that’s clearly not going to work.  So let’s add an actual parameter block and make it look all proper.

Configuration TestConfig {

    Parameter(
        [String[]]$ComputerName
    )

    Node $ComputerName {

        File ScriptPresence {

        Ensure = "Present"
        Type = "Directory"
        Recurse = $False
        SourcePath = "C:\Scripts\DSC"
        DestinationPath = "C:\Scripts"

        }
    }
}

What I am wanting this resource to do is copy the DSC directory (and it’s contents) into the C:\Scripts folder on my test server.  As of right now this Scripts folder doesn’t even exist, so I am hoping this resource knows how to create it.

Back on the Get Started with Windows PowerShell Desired State Configuration page, it states to run the script and it will appear in the console pane.  It runs.  Nothing breaks.  Great success.

Next, I need to enact this configuration by invoking the configuration.  However, before I do this another little nugget I picked up from Don’s E-Book is that when you run a configuration it’s going to create a folder and one or more MOF files (depending on your number of target nodes) and will do so at whatever folder the ISE is currently pointed at.  I would have assumed that it would have placed the files in the same directory that the modules are installed in, but guess not.

I run the Configuration Script by typing TestConfiguration in the ISE, and I am idiot.  This is what happens when you are trying to type fast and not paying attention.

DSC1

So I fixed that problem, and ran the Configuration from inside the ISE so that my session got the change and tried again.  I intentionally ran it without the ComputerName parameter just to see what would happen.  This happened.

DSC2

Excellent, so knowing what I know about parameters and PowerShell, will this work?

    Param(
        [Parameter(Mandatory=$True)]
        [String[]]$ComputerName
    )

Run the Configuration again, try to enact the Configuration with no Computer Name and…..it asks me for the ComputerName.  Excellent.  Before I put in the name of my test server here is what the folder structure on that server currently looks like.  No script server, no DSC server, and no PowerShell script.

DSC3

It completes with no errors.  In my C:\Scripts directory I know how a TestConfig folder and one .MOF file with the name of my server.  So far so good.  Reading farther on the TechNet documentation there is this line “To specify a different directory for the MOF files, use the OutputPath parameter when invoking the configuration.”  That is good to know.  Just to test this out I run my Configuration again with the command below and that works as expected.  Good to know.

TestConfig -ComputerName MyTestcomputer -OutputPath C:\Scripts\DSC

On to the last step!  First I feel obligated to put this section from the TechNet article in case people aren’t following along.  “The Wait parameter is optional and makes the cmdlet run interactively. Without this parameter, the cmdlet will create and return a job. If you use the OutputPath parameter when invoking the configuration, you must specify the same path using the Path parameter of the Start-DscConfiguration cmdlet.”  I first try to run the command below, with no ComputerName parameter again because I am curious if DSC is smart enough that it sees there is only one .MOF file and just automatically applies it.

Start-DscConfiguration -Wait -Verbose .\TestConfig

And…..failure!  About time something exciting happened.

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft
/Windows/DesiredStateConfiguration'.
The WS-Management service cannot process the request. The CIM namespace root/Microsoft/Windows/DesiredStateConfiguration is invalid. 
    + CategoryInfo          : ObjectNotFound: (root/Microsoft/...gurationManager:String) [], CimException
    + FullyQualifiedErrorId : HRESULT 0x80338000
    + PSComputerName        : SERVER_NAME

VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 0.221 seconds

My target server is Windows Server 2012 so it should have WinRM already configured.  Just to make sure I login and run winrm quickconfig and sure enough it’s already enabled.  Strange.  I next remember another note from Don’s E-book where you need to have KB2883200 installed on a Windows 8.1 machine or DSC will not work. I run Get-Hotfix, it’s there.  Damn.  Well, now what.  Quick thought am I running PowerShell ISE as Administrator?  Yes I am.  Damn.  Just to double check let’s run the same thing from just regular PowerShell.  Same thing.  I run the command with the -ComputerName parameter and specify the target server, same thing.  Well……on the target server I run Enable-PSRemoting (even though it should already be configured) and yes, it is already configured.

I continue reading through Don’s E-Book because I feel like the answer to my problem is probably in there somewhere.  Under the section on Pushing Configurations I find this:  “What this command will not do is take care of deploying any resources that your configuration requires. That’s on you, and it’s pretty much a manual process if you’re using push mode.”  Well that probably explains the problem, it probably has no idea what a File resource is.  I immediately wonder, is the version of PowerShell on this server 4.0?  $PSVersionTable tells me, no it’s not, it’s 3.0.  Which I am going to assume is also a problem.  I download and install Windows Management Framework 4.0 on the server, and while doing so immediately think that if I am going to need to do this for all my 2012 servers I wish I could do it by using DSC and not SCCM or Windows Update Services.

Anyways, I install WMF 4.0, reboot, run $PSVersionTable and it’s 4.0.  I run Get-DSCResource and I get the list of installed resources including the File resource.  Now this is looking promising, let’s try again.  I got farther this time no red text.  I will spare you all the Verbose output except for this part.

[[File]ScriptPresence] The system cannot find the file specified.

[[File]ScriptPresence] The related file/directory is: C:\Scripts.

[[File]ScriptPresence] The system cannot find the path specified.

[[File]ScriptPresence] The related file/directory is: C:\Scripts\DSC.

[[File]ScriptPresence] The path cannot point to the root directory or to the root of a net share.

[[File]ScriptPresence] The related file/directory is: C:\Scripts\DSC.

LCM:  [ End    Test     ]  [[File]ScriptPresence]  in 0.1250 seconds.

Problem is that it doesn’t like my path directories.  For one thing my Source Directory in the Configuration isn’t what I made it on my computer, so I fix that.  It also doesn’t appear to like the fact that the destination is missing the Scripts folder.  However, I check the target server and the Scripts folder is there.  Excellent news.  After I fix the configuration I run all the same commands that I ran above to generate a new .MOF file.  Now everything looks good, except my .ps1 file didn’t get copied.  Well perhaps I shouldn’t set -Recurse to $False in my Configuration?  I change that, re-run everything again…AND…..failure.  I suspect that this needs to be on a share that is network accessible and not my local hard drive.  That will be a good point to pick up on tomorrow.  For now, I need to go run some 800M intervals.

2 thoughts on “PowerShell Desired State Configuration (DSC) Journey – Day 2

  1. Yup, 3.0 was your problem. DSC is a feature of WMF 4.0. It doesn’t exist in 3.0, and you can’t target any machine not running 4.0.

Leave a Reply