Demo DSC – Part 3

In Part 1 of this series I talked about how I demo’d the building of a Domain Controller. In Part 2 I talked about demoing the building of a Pull Server, an App Server, and then using the two servers to show how a Pull Server works and what needs to be done to make the magic happen. If you didn’t read Part 1, here is the disclaimer:

This was never intended to demonstrate all the features and capabilities of DSC (there’s a lot!), but instead was done to show at a high level the kinds of things that are possible and to start a discussion about where it fits into our organization immediately and going forward

My outline for this part of the demo looked like this:

  1. Build Web Server
    1. Run BuildWebServer Script on the Web Server
    2. Talk about what’s going on while the server reboots
      1. File copy after domain join
      2. Install of Roles and Features, IIS Components
  2. Post Reboot
    1. Show IIS Site(s
      1. Show default as stopped
      2. Show DSCTest Website
    2. Browse to site from App Server – http://<WebServerName>:8080
    3. Break Web Server
      1. Change IIS Binding
      2. Delete WebSiteFiles Folder
    4. Show broken site from App Server
    5. Talk about various ways this could be fixed (Push/Pull)
    6. Run the BuildLabWebServer script on the Web Server
    7. Show working site from APP Server

For comedic purposes, here is what my awesome Microsoft Word Website looked like that I break in this demo:

CrappyWebsiteDSCDemo

 

Here is the Configuration script in its entirety. It’s also available on GitHub.

Demo DSC – Part 2

In Part 1 of this series I talked about how I demo’d the building of a Domain Controller. In Part 2 I am going to talk about how I demo’d building a Pull Server, an App Server, and used the two servers to show how a Pull Server works and what needs to be done to make the magic happen. If you didn’t read Part 1, here is the disclaimer:

This was never intended to demonstrate all the features and capabilities of DSC (there’s a lot!), but instead was done to show at a high level the kinds of things that are possible and to start a discussion about where it fits into our organization immediately and going forward

The outline for this part of my Demo looked like this:

  1. Talk about the purpose of a Pull server (Can also be used to push and write Configurations)
    1. Show how nothing is configured (name, domain, roles/features, etc
    2. Open ISE, Run BuildPullServer Script
    3. Will reboot. While rebooting show the computer account on the DC
    4. Login as domain account
      1. Create share C:\WebServerFiles, share with everyone (explain why we need it later). Explain that this could have been done with DSC, I just choose not to.  This Share will come into play later.
      2. Copy website files to this share (I created a “website” in Word to use with a Web Server, that will come in the last part of this series)

Here is the Configuration script in its entirety.  It’s also available on Github.

With that done I then built what I called an App Server. Don’t think that I somehow deployed an Application using DSC (I didn’t) but with a Web Server the last part of my demo I needed to call it something that sort of made sense so I called it an App Server. The build script for the App Server is below, and you can see that it’s much smaller than the previous two build scripts. In this case I wanted to show a minimal configuration for a build script and then demonstrate the process of configuring the App Server to pull a new Configuration.

Here is the Configuration script in its entirety.It’s also available on GitHub.

With that done, the next step is to create a Configuration on the Pull Server for the App Server to Pull. All this Configuration does is change the TimeZone on the App Server. Nothing fancy here. There are also some other pieces at the bottom of the Configuration script I should talk about. I have hardcoded a GUID for the server in the Configuration. You can either use this one or change it to your own. I am setting the source and destination paths and sticking the GUID onto the end of the .MOF file, which is required when you are pulling a Configuration. This GUID is how the server knows which Configuration belongs to it (as we will see here shortly). I am then copying the file from the source path to the destination path, and then creating a Checksum file for the .MOF (which is also required).

Here is the Configuration script in its entirety. It’s also available on Github.

With that done, we need to do one other thing before this is going to work. I pre-copied various DSC Resources to the Pull Server, so now we need to .ZIP up the XTimeZone resource so that it can be copied to the App Server when it pulls it’s Configuration. You do this by creating a .ZIP file of the xTimeZone Module and appending the version number to the end of it. In this case, my file name after creating the .ZIP Archive is xTimeZone_1.0.0 . This file then needs to be placed in the “$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules” folder, which is the ModulePath we specified in our Pull Server Configuration. Once that is done, we need to run the command below to also create a Checksum file for this Archive.

Next we need to create a Configuration to tell the App Server to Pull it’s Configuration. This is done by changing the Local Configuration Manager (LCM) settings on the App Server. In my demo I built this Configuration on the Pull Server and then pushed it to the App Server. The outline for this part of the demo looked like this:

  1. Create LCM Configuration. Comment out the Set line in the script. Explain the meta.mof file.
  2. Show LCM Configuration on App Server
  3. Show Consistency Task settings (there should be none)
  4. Push LCM Configuration from Pull Server to App Server
  5. Show LCM Configuration on App Server compared to previous
  6. Show Time Zone. Run Scheduled Task.
  7. Watch App Server for Time Change
    a. Change Time Zone again to something totally random
    b. Run Consistency Task again, watch Time Zone change again

Here is the Configuration script in its entirety.  It’s also available on Github.. You should also note in this script that the Configuration GUID from before makes an appearance here as well. This GUID is what tells the App Server which Configuration to look for on the Pull Server.

Demo DSC – Part 1

This is the first in a series of posts outlining how I presented a demo of Desired State Configuration (DSC) for the organization I work for. This was never intended to demonstrate all the features and capabilities of DSC (there’s a lot!), but instead was done to show at a high level the kinds of things that are possible and to start a discussion about where it fits into our organization immediately and going forward.

My demo was done using 4 Server 2012 R2 Virtual Machines on a single VMWare ESXi host. Because this environment was in a lab (with some unique networking challenges) and to make things easier for me during the demo I just copied the set of files from a Windows 8.1 machine on the same network as the host onto each VM individually.  I built and ran this demo using Wave 9 DSC Resources.  I switched to Wave 10 halfway through and had a problem with the xComputerManagement Resource (In Wave 10 it doesn’t properly evaluate the condition of whether or not the Computer Names match or not), and switched back to Wave 9 after that to avoid any further problems.  You will also notice in the script that I hardcoded credentials which is definitely not the recommended way to do it in a production environment.

The first thing I wanted to do was to build a Domain Controller on a brand new domain, that would be the foundation for showcasing other features of DSC in the rest of the demo. My outline for this part of the demo looked like this:

  1. Show New Server Build
    1. Show how nothing is configured (name, domain, time zone, IEESC, IP address etc)
    2. Open ISE, Run BuildDC Script. Show computer rename and restart section.
    3. Will restart – Talk about what just happened.
  2. Continue Server Build Post Reboot
    1. Login after reboot, show post Reboot scheduled task kicking off
      1. Show IP address change
      2. Wait for restart again (Approx 3:15 total at this point)
    2. Login after restart with Domain credentials
      1. Show Firewall Status
      2. Event Log Configuration
      3. Time Zone Configuration
  3. Run entire Configuration again to show nothing happens.

Here is the entire BuildDC Configuration Script in it’s entirety.  It’s also available on GitHub.

 

Exploring the PowerShell DSC xPendingReboot Resource

While building a DSC Demo for the new job this week I got the chance to explore using many of the “new” Resources that have been released.  One of those Resources is the xPendingReboot which I am going to talk about here, because the documentation wasn’t very clear (to me anyways after having been away from DSC for a long time) on how to use it properly.

The TechNet article on the Resource and an article by the Scripting Guy can be found at the links below.

https://gallery.technet.microsoft.com/scriptcenter/xPendingReboot-PowerShell-b269f154

http://blogs.technet.com/b/heyscriptingguy/archive/2014/10/15/use-powershell-dsc-to-check-pending-reboot.aspx

If you just look at it, you would assume you could do something like this to check for a reboot:

However, you would be wrong! If we create the .MOF file for this Configuration and run this against the local system (which has a reboot pending after a computer rename), the system doesn’t actually reboot itself, it just notifies you that a reboot is pending.

Well, that’s great and all but it didn’t reboot the machine like I needed it to. Looking at those examples, maybe I need to add the LocalConfigurationManager piece to make this work?

When you build this Configuration you will immediately notice you get a localhost.mof as well as a localhost.meta.mof . The Meta.mof is a result of making a change to the Local Configuration Manager (LCM) and should be a hint that something needs to be done with it :). The TechNet article uses a RebootNodeifNeeded = ‘True’ instead of the Boolean $True, which is not correct. If you try to build the Configuration using ‘True’ you get this error:

I am going to ignore the localhost.meta.mof file for now and just try this again to see what happens. And the exact same thing happens. If you are wondering if moving the LocalConfigurationManager section ahead of the xPendingReboot section matters or will help, it won’t. You actually need to change the LCM setting on the computer before starting the Configuration, because right now it is set to this. Notice the RebootNodeIfNeeded section at the bottom:

You do that by using this command:

Now when we start the Configuration, we get the exact same result as above, plus an automatic reboot!
PendingReboot






If you want everything in one file, you can find it here.

PowerShell DSC Journey – Day 23

No intro. Going right back into trying to add a Network Adapter and a VMNetwork to that adapter. I look first at the hardware profile, and lo and behold I have 9 legacy network adapters, which is interesting because yesterday I had none. So, I remove them all first.

Ok, first things first, let’s make sure I can get the network I want, which I can do using this command:

The next thing I can do is try to create a new network adapter on the Hardware Profile, which I can do using this command.

However, this creates a Legacy network adapter. After reading the help file I determine that I need the -Synthetic parameter in order to make it a non-legacy network adapter.

So, that’s all working now. Next step is to see if I can actually set the Virtual Network on the adapter itself, which is where I failed so hard yesterday. This works.

So, let’s try this next. And it works. I swear I did this a billion times but I am not even to go back and look because it might make me angry or depressed. Or both.

So, let’s run my Configuration and see what happens again. And it works. Of course it does.

I then add most of the same code to the section of Set-TargetResource for when a Hardware Profile doesn’t exist. Now let me delete my profile and try it. And of course I get some errors because I am using the $ResourceHWProfile variable in this section of code instead of just $Name. So, I change it to this.

And that works as well. One interesting thing to note. There is a lot of Write-Verbose commands I have that aren’t being written after this section of code. And I have no idea why either.

Well, that’s working now so I am happy. Now that I have a functioning Resource that does what I wanted it to do, this will be the last post in the series 🙂

PowerShell DSC Journey – Day 22

Alright, after my little fiasco yesterday I need to do a little re-configuring of my Configuration because of course DSC will not allow a Plain text password.

Here is the new version of the Configuration.

Now, let’s try to run this and see what breaks. And. Nothing breaks. I am literally speechless. Seriously.

Well. Here goes nothing. And I forgot to change something back in .psm1 file when I was messing around with it yesterday that caused this entire thing to blow up. I will spare you all the red text but here is the error.

With that fixed I try to run it, and I don’t get any errors, but clearly I have something to fix with my Test-TargetResource function because it just skipped running Set-TargetResource.

So, let’s see if we can figure out what’s going on. I am pretty sure this section is the problem.

I set the $result to $false, then tested for the $VMMServer, and returned $True, so DSC was like “oh hey, everything is gravy.” Fail on my part. Let’s fix this. I already know if the Credential or VMMServer is invalid that it will fail, so I just need to check to make sure $ResourceVMMServer exists and then do the rest of my checks. I am pretty sure this is going to fail for a couple of reasons, but I am going to test this anyways in the interest of full disclosure :).

I run several of my tests that I expect to return both $True and $False. I made a few changes and added one line, so here is the new and improved section of my code.

So, let’s try this again! HOLY BUCKETS IT WORKED! Minus, one small issue.

dsc62

Now, the one issue there is that no VMNetwork was set. Probably because there is no network adapter, which I am guessing I forgot to include in my Set-TargetResource. Let’s take a look.

Yeah, that’s not going to work. I need to create the adapter first. Turns out it’s easier than I thought it would be. Just kidding, I can’t use the parameter for $VMNetwork, it needs to be a different type.

Which opens a whole new can of worms because I need to check to make sure that is a valid VM Network somewhere. For the purposes of this, I am going to assume that if it should be present, it is a valid name. Actually I lied. We aren’t going to do that, because that opens up a giant mess when it comes to creating a new Virtual Network.

After banging away on this for about the last 30 minutes I am going to stop here for the day and pick it up again tomorrow. I am currently stuck on getting the right object type from Get-SCVMNetwork to pass to……..oh hell…wait a minute. Just kidding! Kidding again. I have a moment of genius! And this is also where I hate Virtual Machine Manager anymore. Only thing good to say is that I learned a hell of a lot more than I ever wanted to know about VMM cmdlets this afternoon.

So, let me delete the Hardware Profile and run my Configuration again. The network adapter didn’t get created. My brain is exhausted. I’m done for today. For real this time.

PowerShell DSC Journey – Day 21

Alright, when I left off I had added in some testing for the $Credential Property of the Resource in the Get-TargetResource and Test-TargetResource functions. Today I am going to do the same with Set-TargetResource, and then test my Configuration to see what I did wrong. If I survive that I will try to create a Hardware Profile with my Resource.

First things first, I add this same section to Set-TargetResource.

I think that is all I need to do here because Get-SCHardwareProfile and Set-SCHardwareProfile don’t require a credential.

I run my first test, and everything works great except the test removed the DVD Drive. Which it wasn’t supposed to do. And there is all some verbage for the CPU Count that is incorrect, and it looks like I need to add a case for when CPUCount is not specified.

Ok, let’s tackle the DVD Drive issue first. I didn’t specify an option for it, it was already present, and the profile was set to Ensure = Present, so it should not have been removed. Here is the code block.

What is happening is I am not specifying a value for the DVDDrive Property. So as far as it is concerned, the last Else statement gets executed. I am going to need to add a case for not specifying the DVDDrive Property. I reconfigured this code to look like this instead.

And that works exactly like it should. Now I need to do the same thing for CPUCount. This also works just fine. And it’s also at this point that I realize that I already have the VMNetwork parameter setup that way. Apparently it never occurred to me I would need to do the same thing for the others. Oh well. Moving along! I run a few more test and make a few more minor changes and tweaks but I am not going to bore you with those details. I just needed to update the part of the function that creates a new Hardware Profile with the same If checks as above.

And now. Let’s see how badly I have failed here. Let’s test this bad boy.

Pretty good. So far. I don’t expect this to continue.

Well. That was unexpected. I guess on to the next thing. Let’s try my Configuration again. Here is my current Configuration.

}

}

Alright. So….I declared my credential variable to be of the type [pscredential]. Maybe it needs to be [MSFT_Credential]? Let’s try it. But wait, I have the bright idea that I should check to see how the ADDomain resource handles it, and I find my answer in the .psm1 file for the resource.

Looks like I need to update my Resource.

Hmmm. How else would you get the schema.mof to show that Type? Then I look at the schema.mof for my resource and get my answer.

So the type Credential, automatically changes to that in the schema. Good to know. Now I try my Resource using [MSFT_Credential]$Credential and that fails.

This has me stumped. Nothing of use in the DSC Event Logs. Comparing my .psm1 file to the ADDomain.psm1 file, I notice that all of their credentials are of the type [PSCredential] while mine is of the type [System.Management.Automation.PSCredential]. Which is weird (I think?). I try to change the parameter in my Configuration to the type [System.Management.Automation.PSCredential] but I get the same error. So I am going to change the .psm1 type to just [pscredential] and see what happens. I reloaded everything and change the type for Credential back to [PSCredential] and the same thing still happens.

I am stumped. Going to call it a day on that front.

Edit: Thanks to Jason Hofferle for helping figure out what I was doing wrong (and it was something dumb). I was so wrapped up in the thought that I did something wrong in my Resource that I didn’t bother to specify the Credential property in my actual Configuration.

PowerShell DSC Journey – Day 20

When I left off yesterday I was trying to actually run a Configuration to create a Hardware Profile, and quickly realized that I was going to need a Credential parameter in order to do this, because not just anyone can connect to a Virtual Machine Manager server. So today’s post is going to be about adding a Credential property to my Configuration.

I am going to be referencing the Active Directory resource for this because I know that uses a credential parameter to authenticate to Active Directory. First thing first, let’s create a new DSC Resource Property.

Then I will need to update my resource with this new Property.

And here is what my schema.mof file looks like:

And this is a snippet of the Get-TargetResource function show the additional property as well.

Now, that’s all well and good, but how do I go about testing this in Get-TargetResource? Let’s take a look at what the Active Directory resource does. It looks like it is using the Credential property when testing other properties, so I will do the same. I believe I only need to add this where other commands need to authenticate to the VMMServer, and I should probably test to make sure the credential is valid. Get-SCHardwareProfile doesn’t require a credential, only the VMMServer name, so I don’t think I need to do anything there. I did add this to the Get-TargetResource function.

And I suppose I should test this now to see what breaks. This test prompted me for the credential and completed successfully.

Just to be safe I tried the same test but added a -Credential (Get-Credential) command and everything worked fine.

Here is a test where I submitted a completely bogus credential that has no permissions to anything.

Here is what I added to my Test-TargetResource Function.

So let’s test this out. I am astounded this is actually working properly. With valid credential:

With non valid Credential:

I am running out of time today and feel like this is a great place to stop. I will move on to the Set-TargetResource function tomorrow!

PowerShell DSC Journey – Day 19

Alright, so in my last post I was able to resolve the issue with my Custom Resource not showing up under Get-DSCResource (because as usual I was doing something dumb).

Proof!

Now, let’s try and write a Configuration! Look ma, no errors!

Let’s build this out for a test.

I run this Configuration and the .MOF gets created.

When I run this configuration I immediately encounter two errors.

The first issue crossed my mind literally as I was hitting enter to start the Configuration. That is, am I going to need a credential variable to pull this off because not just anyone can connect to a VMM Server. This error came from running PowerShell as Administrator. When I run PowerShell as my elevated account (which has access) this is what happens.

I am going to try this (although if it works this not a valid solution as far as I am concerned), and this shouldn’t work but I am going to try it anyways.

And it did exactly what I thought it should do (which is nice for a change).