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.

Moving SCOM 2012 R2 Database to New SQL Server Cluster

When our System Center environment (VMM, Orchestrator, SCOM, DPM) was originally setup all the databases were installed on a single SQL Server VM (but in separate instances).  For a variety of reasons I made the decision that our System Center databases needed to at least be in a cluster configuration.  Luckily I stumbled across this excellent guide by MVP Paul Keely about configuring a SQL 2012 Cluster with Always On to be used for System Center databases.  I am not going to cover any of that here, this post is just going to be about how to move the Operations Manager database once the new cluster is built.

First, I need to go on a rant about just plain poor timing on my part.  If you don’t care to read it, skip to the next paragraph.  There is an article published by Microsoft that talks about how to move the Operational Database.  If you look at that article you will notice that it was last updated on January 19th.  That’s awesome.  You know what’s not awesome?  I first attempted to move the Operational Database on January 17th.  It failed miserably.  Why?  Because the article I was working off of didn’t include a second registry key that needed to be modified.  That’s 6 hours of my  life I will never get back.

In my environment I have two Operations Manager Management servers, in this article they are named OPSMGR01 and OPSMGR02.  When I wrote up my plan for this move I duplicated some sections that needed to be done on both servers and I kept that the same in this article.  For the SQL Server name, I used the name of the new SQL Cluster as SQLCLUSTER followed by the instance name.  If you are moving the databases to a single server you would just use the server name followed by the instance name.

  1. Stop the following services on OPSMGR01 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  2. Stop the following services on OPSMGR02 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  3. Create full backup of OperationsManager Database on OLDSQLServer using SQL
    1. Copy backup file to \\SQLCLUSTERNODE1\SHARE
  4. Open SQL Management Studio on SQLCLUSTERNODE1 and connect to SQLCLUSTER\SCOM Instance
    1. Restore OperationsManager Database using SQL
  5. Delete backup file from \\SOMEFILESHARE (Needed the space for the massive SCOM Data Warehouse Database backup that was coming next)
  6. Backup Registry on OPSMGR01
  7. Backup Registry on OPSMGR02
  8. Update Registry on OPSMGR01
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseName: SQLCLUSTER\SCOM
      2. DatabaseServerName: OperationsManager
    4. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database and repeat step 3. (This was the aforementioned missing step)
  9. Update Registry on OPSMGR02
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseName: SQLCLUSTER\SCOM
      2. DatabaseServerName: OperationsManager
    4. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database and repeat step 3.
  10. Edit the following file on OPSMGR01
    1. Browse to %ProgramFiles%\System Center 2012\Operations Manager\Server\ConfigService.config
    2. Backup existing file (copy and rename to .old and place somewhere safe)
    3. Open Notepad as Administrator and open the file in Step 1.
    4. In the <Category> tags named “Cmdb” and “ConfigStore”, change the value for ServerName to the name of the new SQL server.
    5. SQLCLUSTER\SCOM
    6. Save changes and close
  11. Edit the following file on OPSMGR02
    1. Browse to %ProgramFiles%\System Center 2012\Operations Manager\Server\ConfigService.config
    2. Backup existing file (copy and rename to .old and place somewhere safe)
    3. Open Notepad as Administrator and open the file in Step 1.
    4. In the <Category> tags named “Cmdb” and “ConfigStore”, change the value for ServerName to the name of the new SQL server.
    5. SQLCLUSTER\SCOM
    6. Save changes and close
  12. Update the operational database with the new database server name on SQLCLUSTERNODE1
    1. Open SQL Server Management Studio. Connect to SQLCLUSTER\SCOM instance.
    2. Expand Databases, OperationsManager, and Tables.
    3. Right-click dbo.MT_Microsoft$SystemCenter$ManagementGroup, and then click Edit Top 200 Rows.
    4. Change the value in the SQLServerName_6B1D1BE8_EBB4_B425_08DC_2385C5930B04 column to SQLCLUSTER\SCOM
      1. The GUID part in your database isn’t going to match the one above.  It’s ok!
    5. Save the change.
  13. On SQLCLUSTERNODE1, update the operational database with the new database server name to specify the location of the Application Performance Monitoring tables
    1. Open SQL Server Management Studio. Connect to SQLCLUSTER\SCOM instance
    2. Expand Databases, OperationsManager, and Tables.
    3. Right-click dbo.MT_Microsoft$SystemCenter$OpsMgrDB$AppMonitoring, and then click Edit Top 200 Rows.
    4. Change the value in the MainDatabaseServerName_5C00C79B_6B71_6EEE_4ADE_80C11F84527A column to SC-SQLCLUS-SCOM\SCOM
      1. The GUID part in your database isn’t going to match the one above.  It’s ok!
    5. Save the change.
  14. Update security credentials on SQLCLUSTER\SCOM
    1. All of my security credentials carried over and I had no issues.  However, your environment may be completely different.  Definitely make sure to read this section in the TechNet documentation
  15. Execute these SQL commands on new OperationsManager database instance:
    1. sp_configure ‘show advanced options’,1
    2. reconfigure
    3. sp_configure ‘clr enabled’,1
    4. reconfigure
  16. Run the following SQL query (If you added the OperationsManager database to AlwaysOn before this step you can skip this step. I ran through all of this and added it to AlwaysOn once I knew for sure it was working on the new SQLCLUSTER):
    1. SELECT is_broker_enabled FROM sys.databases WHERE name=’OperationsManager’
      1. If the result of this query was an is_broker_enabled value of 1, skip this step. Otherwise, run the following SQL queries:
    2. ALTER DATABASE OperationsManager SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    3. ALTER DATABASE OperationsManager SET ENABLE_BROKER
    4. ALTER DATABASE OperationsManager SET MULTI_USER
  17. Stop SQL Services relating to SCOM on OLDSQLServer
  18. Open PowerShell.  Type Write-Host “Bye Kitty” to sacrifice a kitten
  19. Restart OPSMGR01 and OSPMGR02 (this was to ensure registry setting changes were picked up)
  20. Start the following services on OPSMGR01 and change their startup type to Automatic
    1. System Center Data Access
    2. System Center Management Configuration
  21. Start the following services on OPSMGR02 and change their startup type to Automatic
    1. System Center Data Access
    2. System Center Management Configuration
  22. Spam refresh OperationsManager event log on OPSMGR01.  Hopefully you see lots of informational messages and no errors about connections to the SQL Server.
  23. Start OperationsManager console.  Check stuff

That’s it!

Creation of the VMM Resource Group Failed

While trying to install VMM as a Highly Available following the steps in this article, I kept running into the same issue over and over and over again.  The installation would start, run for a few minutes, and then fail and rollback with this error at the end:  “Creation of the VMM resource group VMM failed.Ensure that the group name is valid, and cluster resource or group with the same name does not exist, and the group name is not used in the network.”

I first thought it was because I had pre-configured the DNS entry, but even after removing the DNS entry and verifying that neither cluster node could resolve it anymore the installation still failed.  Next I rebooted both nodes of the cluster.  The installation still failed.  My next thought is maybe I can’t use VMM as the HA VMM name so I used XXXVMM and sure enough it worked.  Now, whether or not that is because I had the VMM DNS entry created previously and it screwed something up, or because you really can’t use the VMM name, I don’t know.

At this point it said setup completed successfully, but with warnings.

 

Starting the clustered VMM service XXXVMM failed.Ensure that the user has permission, the VMM service is installed properly, and cluster resources can be brought online.A service connection point (SCP) could not be registered in Active Directory Domain Services (AD DS) for the VMM management server.Run “D:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\setup\ConfigureSCPTool.exe -install XXXVMM.nfm.com XXX\XXXVMM$” in a command window and then check AD DS. If an SCP is not registered, VMM consoles on other computers will not be able to connect to this VMM management server and deploying a Hyper-V host to a bare-metal computer will not work.

I ran the setup as a domain administrator, and am logged into the cluster node as this same domain administrator.

Looking at the Cluster event logs, this is the error I get when I try to manually bring the service online:

Failed to bring the resource VMM Service XXXVMM online.  Error code 0x80071736 The Resource failed to come online due to the failure of one or more resource providers.

Looking at Services, the System Center Virtual Machine Manager Agent service is running, but the System Center Virtual Machine Manager service is not running, and if I try to start it, it fails with the error.

In the Event Log, I find this error entry which seems pretty useful.

Cluster network name resource ‘XXXVMM’ failed to create its associated computer object in domain ‘nfm.com’ during: Resource online.

The text for the associated error code is: A constraint violation occurred.

Please work with your domain administrator to ensure that:

– The cluster identity ‘VMM-HV-CLUS01$’ has Create Computer Objects permissions. By default all computer objects are created in the same container as the cluster identity ‘VMM-HV-CLUS01$’.

– The quota for computer objects has not been reached.

– If there is an existing computer object, verify the Cluster Identity ‘VMM-HV-CLUS01$’ has ‘Full Control’ permission to that computer object using the Active Directory Users and Computers tool.

While looking in AD for this object, I also stumbled across a VMM computer object (who the hell knows where that come from) so I deleted that object as well.  I am nearly 100% certain that is what caused my installation using VMM as my VMM Cluster Name to fail.

At the very bottom of this article it outlines how to troubleshoot issues with Cluster AD Accounts.  The instructions are only slightly different for Server 2012, and it tells you how to grant only the permissions that you need.

With that done, I removed the VMM installation and tried it again, with the original VMM Cluster name (just VMM) and it worked fine, with no errors!

 

 

 

 

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 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).

So, I am going to need a $Credential parameter. That sounds like a good place to start tomorrow 🙂

PowerShell DSC Journey – Day 18

Yesterday I finished up modifying the Set-TargetResource function and doing all the tests and it seems to be working exactly the way that I want. The next step today is to turn this into a module, import it, write a DSC Configuration and see if it actually works.

I already have my SCVMM_Hardware.psm1 file, so I just need to add a module manifest file.

Looking at the other DSC Resources, none of them specify a root module, so I guess we will see if this breaks it or not. They also have multiple resources associated with each module, so that could be part of the reason as well.

This article on TechNet says to “Finally, use the New-ModuleManifest cmdlet to define a .psd1 file for your custom resource module. When you invoke this cmdlet, reference the script module (.psm1) file”, but the module manifest they show has the root module as ”, which doesn’t match up with what they are saying. I am just going to try it this way and see what happens. Because that’s what I do. Actually, I am going to change something up here to prepare for my other SCVMM Resource.

  • Rename the root folder to cSCVMM
  • Create a DSCResources folder underneath
  • Create a cSCVMM_Hardware folder, move my .psm1 and schema.mof files into this folder
  • Create the module manifest and place it in the root cSCVMM folder

Round 2.

So far so good! (No errors anyways). I am going to restart ISE and see if it loads the module or what happens. This is where I had so much trouble in my previous post. And I ran into the same issue. If I say Get-Module -Name cSCVMM nothing happens. If I do Get-Module -ListAvailable it shows up in the list. So first thing, I am going to get rid of the root module path and see what happens.

Same thing. Move it out of the DSCResources folder, same thing.

Looking at the other resources, they have a CLR version and a description, so let’s just try that (although I am sure that has nothing to do with it).

Long story short, turns out (once again) that I just don’t know what I am doing. Once you import it by name, you can then get the information on it. Duh.

So, now that I wasted a bunch of time on that, let’s see if I can remember how to build a Configuration :).

First issue I run into is, when I do Import-DSCResource -Module cSCVMM it acts like it has no idea what the hell that is. So, uh, what do I do about that?

So, yeah. My .psm1 file is exporting the commands, so that shouldn’t be a problem. I guess first thing first, let’s run Get-DSCResource and see what happens.

I get that error, but then all of the DSCResources are listed (except for mine).

Further investigation reveals this.

Alright, so that’s fun. I am going to backup here and try something referencing the steps in this article.

I create a “new” DSCResource using my properties. And guess what? Even then it doesn’t show up as a DSC Resource. So, that’s good right? I don’t think so. That article makes it seem like it should be pretty simple, so I don’t know what’s going on.

Next step, I am going to test this on WMF 4.0 (I am using WMF 5.0 Preview). And the same thing happens there. So that’s good I guess. I really have no idea what is going on here. Completely. Puzzled.

Time to stop for the day. Hopefully I think of something before tomorrow as of what to try next.

Edit: I was able to resolve this issue with the help of Don Jones on the PowerShell.org forums.

When I first created the Resource what I did was this:

What I should have done was this:
New-xDscResource -Name cSCVMM_Hardware -Property $DVDDrive, $VMNetwork, $CPUCount, $Ensure, $Name, $VMMServer -FriendlyName “SCVMM_Hardware” -ClassVersion 1.0 -Path ‘C:\Program Files\WindowsPowerShell\Modules\cSCVMM’

Since I didn’t specify the Module name it just created the DSC Resources folder and that messed up everything. Lesson learned!

PowerShell DSC Journey – Day 17

Alright. So yesterday I worked through some issues in the Set-TargetResource Function and left off with a big one still remaining. Namely, that even though I have Ensure = Present in my test of the Function, it is running through the Ensure = Absent portion of the script if the Hardware Profile already exists, which doesn’t make any sense.

Here is the section of the Function in question.

And if I run this Test with a Hardware Profile that already exists, this is the output that I get.

And I know it’s removing it because the Hardware Profile disappears from VMM. The question is, why? I can see from the Verbose output that $Ensure is set to Present, so why is the Function ignoring that? As another test, if I run the same test but set $Ensure to Absent, it removes it. But that was really just a diversion to avoid thinking about the real problem because I am completely stumped.

I change my Else block to ElseIf($Ensure = “Present”) and that has no effect. It just jumps right into the If Absent block and deleted the Hardware Profile. Lacking ideas I start going through the xVMHyperV Set-TargetResource function searching for Ensure to see how they do it. And they are using -eq in the If statement instead of =. Does this really make a difference? Yes, that’s the answer. After I change it to that, it evaluates the parameter properly. I feel like this is a very simple mistake that I made solely because of my lack of experience and knowledge of PowerShell.

Doing a little research in PowerShell using Get-Help I discover the following:

  • = is an Assignment Operator.  It sets the value of a variable to a specified value
  • -eq is a Comparison Operator.  It compares to objects looking for an identical value
  • Thus, = does not equal -eq.  I feel dumb.  I should have known that.

That being said, when I run my test using an existing Hardware Profile now (with Ensure = Present), I get this for output.

Clearly there are a couple of issues here. The DVDDrive section looks OK, but then in the CPU section I get this beauty for Verbose output.

Yeah, that’s not real useful. Looking at this it appears that $HWProfile.CPCount is not what I think it is. Actually I think it’s because I used $HWProfile instead of the $ResourceHWProfile variable. This is going to require a fix in a lot of places. I make those changes and try my test again. I get the expected output, except that I get the same error about the VirtualNetworkAdapter that I got above. This goes back to my work in the previous blog post about how to handle this, because I don’t want to make this parameter mandatory. So, I need to add in some additional logic to my Function here.

And now when I run my test, I get exactly the output that I would expect.

Boom!
I do various tests with different CPU, DVDDrive and VMNetwork settings and everything looks good. I do make a change to one line of Verbose output, but other than that everything checks out fine. This is really cool. I have an actual functioning DSC Custom Resource. Tomorrow I am going to turn this thing into a Module, and try out an actual DSC Configuration and see if that actually works before adding in my additional parameters.