Using dsc - how can you deploy files related to existing services?

This topic contains 8 replies, has 5 voices, and was last updated by  John Trump 3 years ago.

  • Author
    Posts
  • #16521

    John Trump
    Participant

    I am looking into using DSC for application deployments. At the moment, we have a set of scripts that save the current start mode and state of all application services and then stop and disable all applications services before copying new application files to target servers. If we don't do this, the files tied to the services fail to publish because the old versions of the files are in use. Then after the copy, we set the services states back to what ever they were before (started/stopped and either disabled, manaual, or automatic).

    How can the desired effect of copying the new service related files to the target servers be accomplished using DSC?

  • #16523

    Dave Wyatt
    Moderator

    That's what the File resource does ( http://technet.microsoft.com/en-us/library/dn282129.aspx ). You can specify a SourcePath, which will be the location from which to copy each file. Note that by default, this will be running as LocalSystem (which authenticates as the computer's AD account to any remote shares). If you can't read the share when authenticating as the computer account, then you'll need to include the Credential parameter to the File resource as well.

  • #16524

    Jacob Benson
    Member

    There is also a Service resource. So, what you can do is to leverage the Service and File Resources using the DependsOn Property so that it stops the services, copies the files, and then starts the services. So it could look like something like this.

    Configuration MyApp
    
    {
    
        node ServerA
        {
            Service StopService1
            {
                Name = "Service1"
                State = "Stopped"
            }
    
            File CopyFiles1
            {
                SourcePath = "\\FileServer1\Files"
                DestinationPath = "ServerA\Service1\Files"
                Recurse = $True
                DependsOn = "[Service]Service1"
            }
    
            Service StartService1
            {
                Name = "Service1"
                State = "Running"
                DependsOn = "[File]CopyFiles1"
            }
        }
    
    }
    
  • #16525

    Dave Wyatt
    Moderator

    That would be DependsOn = "[Service][b]Stop[/b]Service1" 🙂

    Loving the new formatting plugin, but i'm not sure why it keeps mangling closing quotation marks (both single and double) in so many cases (but not every time... "Stopped" and "Running" look fine in the last post.)

  • #16527

    Jeremy Murrah
    Participant

    Jacob Benson wrote:There is also a Service resource. So, what you can do is to leverage the Service and File Resources using the DependsOn Property so that it stops the services, copies the files, and then starts the services. So it could look like something like this.

    Configuration MyApp
     
    {
     
        node ServerA
        {
            Service StopService1
            {
                Name = "Service1"
                State = "Stopped"
            }
     
            File CopyFiles1
            {
                SourcePath = "\\FileServer1\Files"
                DestinationPath = "ServerA\Service1\Files"
                Recurse = $True
                DependsOn = "[Service]Service1"
            }
     
            Service StartService1
            {
                Name = "Service1"
                State = "Running"
                DependsOn = "[File]CopyFiles1"
            }
        }
     
    }

    Just seeing if I understand this right, but in a pull scenario wouldn't the above restart the service every 15 minutes (or is it 30) since the service stop condition has no dependencies? It's almost like you'd need the service stop resource to depend inversely on the file copy resource. i.e. only stop the service if the file copy test fails. Right?

  • #16528

    Jacob Benson
    Member

    Yeah, the scenario outlined above would be less than ideal for a Pull server scenario. What you could do is have the File resource check the Checksum of the files to be copied first, and then do the rest if the Checksum has changed since the last time the files were copied. That way if the Checksum hadn't changed, the services wouldn't be stopped. But if the Checksum was changed, then it knows the files have changed and it does the rest.

    The valid Checksum options are:
    Indicates the checksum type to use when determining whether two files are the same. If Checksum is not specified, only the file or directory name is used for comparison. Valid values include: SHA-1, SHA-256, SHA-512, createdDate, modifiedDate.

  • #16529

    Dave Wyatt
    Moderator

    That's a good point. Whether you're using a Push or Pull server doesn't really matter, if your LCM is set up for ApplyAndAutoCorrect mode, it'll be constantly stopping and starting the service. Even if it's only set for ApplyAndMonitor, you'll still wind up getting a bunch of annoying log messages about the service that's running.

    Here's where you probably just need to bite the bullet and write a resource for installing the patch. The Set-TargetResource function can have all the functionality needed to stop and start services, copy down files, etc, without needing the LCM to try to chain that process together from multiple resources. Test-TargetResource would just be responsible for checking whether new versions of the files are available in some way. You could use the Script resource for this, or write a full custom resource (which would be my preference.)

  • #16596

    Jay Spang
    Participant

    Why not do the file copy in two steps, with the service restart depending on the first?

    Configuration MyApp
    {
        node ServerA
        {
            File CopyFilesFromSharetoStaging
            {
                SourcePath = "\\FileServer1\Files"
                DestinationPath = "ServerA\STAGINGDIR\Service1\Files"
                Recurse = $True
                Ensure = Present
            }
    		
            Service StopService1
            {
                Name = "Service1"
                State = "Stopped"
                DependsOn = "[File]CopyFilesFromShare"
            }
     
            File CopyFilesFromStaging
            {
                SourcePath = "ServerA\STAGINGDIR\Service1\Files"
                DestinationPath = "ServerA\Service1\Files"
                Recurse = $True
                DependsOn = "[Service]StopService1"
            }
     
            Service StartService1
            {
                Name = "Service1"
                State = "Running"
                DependsOn = "[File]CopyFilesFromStaging"
            }
        }
    }
    

    In the above code, the entire process will only start if the files on the "staging" dir on the server don't match the source on the fileserver. The service won't restart every time it runs, only when the files are changed.

  • #18361

    John Trump
    Participant

    I like the idea of copying the files to a staging directory on the target machine first. But there is yet another issue with this process involving the Service resource. It does not allow two separate operations on the same service in the same node block. Any other ideas?

    Configuration DSC_TEST
    {
        param()
    
        Node "FAHQSNA09VHPV14"
        {
            File DirectoryCopyToStage
            {
                Ensure = "Present"  # set Ensure to "Absent" or "Present"
                Type = "Directory" # Default is "File".
                Recurse = $true # Ensure presence of subdirectories, too
                SourcePath = "\\fahqsna09prodcifs\fastinstall`$\SCM\DSC\DSCDemo\DemoSource"
                DestinationPath = "C:\CM\DSC"    
                Force = $true
            }
    
            Service ServiceStopAndDisableExample
            {
                Name = "spooler"
                StartupType = "disabled"
                State = "stopped"
                DependsOn = "[File]DirectoryCopyToStage" # This means run "DirectoryCopyToStage" first.
            } 
    
            File DirectoryCopy
            {
                Ensure = "Present"  # set Ensure to "Absent" or "Present"
                Type = "Directory" # Default is "File".
                Recurse = $true # Ensure presence of subdirectories, too
                SourcePath = "C:\CM\DSC"
                DestinationPath = "C:\Users\Public\Documents\DSCDemo\DemoDestination"    
                DependsOn = "[Service]ServiceStopAndDisableExample" # This means run "ServiceStopAndDisableExample" first.
                Force = $true
            }
    
            Log AfterDirectoryCopy
            {
                # The message below gets written to the Microsoft-Windows-Desired State Configuration/Analytic log
                Message = "Finished running the file resource with ID DirectoryCopy"
                DependsOn = "[File]DirectoryCopy" # This means run "DirectoryCopy" first.
            } 
                   
            Service ServiceStartandAutomaticExample
            {
                Name = "spooler"
                StartupType = "automatic"
                State = "running"
                DependsOn = "[Log]AfterDirectoryCopy" # This means run "AfterDirectoryCopy" first.
            } 
        }
    }
    DSC_TEST -OutPutPath "c:\DSC_TEST\ClientConfig" 
    

    Here is the output when running Start-DscConfiguration -Path "c:\DSC_TEST\ClientConfig" -wait -Verbose

    Add-NodeKeys : The key properties combination 'spooler' is duplicated for keys
    'Name' of resource 'Service' in node 'FAHQSNA09VHPV14'. Please make sure key
    properties are unique for each resource in a node.
    At line:160 char:9
    + Add-NodeKeys $keyValues $keyNames $keywordName
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Write-Error], InvalidOper
    ationException
    + FullyQualifiedErrorId : DuplicateKeyInNode,Add-NodeKeys
    Errors occurred while processing configuration 'DSC_TEST'.
    At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfigurati
    on\PSDesiredStateConfiguration.psm1:2088 char:5
    + throw $errorRecord
    + ~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (DSC_TEST:String) [], InvalidO
    perationException
    + FullyQualifiedErrorId : FailToProcessConfiguration

You must be logged in to reply to this topic.