├── scripts
├── placeholder.txt
├── SetupServiceFabric
│ ├── README.md
│ └── SetupServiceFabric.sh
├── CodePackageToDockerPackage
│ ├── README.md
│ └── CreateDockerPackage.ps1
└── BackupRetentionScript
│ ├── modules
│ ├── README.md
│ ├── RetentionScript.psm1
│ ├── RetentionScriptAzureBlobStore.psm1
│ ├── RetentionScriptFileShare.psm1
│ └── UtilScript.psm1
│ ├── README.md
│ ├── RetentionScript.ps1
│ ├── RetentionScriptAzureBlobStore.ps1
│ ├── RetentionScriptFileShare.ps1
│ └── UtilScript.ps1
├── templates
├── placeholder.txt
├── service-integration
│ ├── network-apim.parameters.json
│ ├── apim.parameters.json
│ ├── network-apim.json
│ └── apim.json
├── nodetype-upgrade
│ ├── parameters.json
│ └── README.md
├── nodetype-upgrade-nonprimary
│ ├── parameters.json
│ └── README.md
├── cluster-tutorial
│ ├── vnet-cluster.parameters.json
│ └── vnet-linuxcluster.parameters.json
└── networking
│ ├── template_original.json
│ └── template_existingvnet.json
├── docker
└── service-fabric-reliableservices-windowsservercore
│ ├── Dockerfile
│ ├── README.md
│ └── InstallPreReq.ps1
├── code
└── SFBinaryLoaderForContainers
│ ├── README.md
│ └── SFBinaryLoader.cs
├── README.md
├── LICENSE
├── SECURITY.md
└── .gitignore
/scripts/placeholder.txt:
--------------------------------------------------------------------------------
1 | Create a new directory for each script here.
--------------------------------------------------------------------------------
/templates/placeholder.txt:
--------------------------------------------------------------------------------
1 | Create a new directory for each Resource Manager template here.
--------------------------------------------------------------------------------
/docker/service-fabric-reliableservices-windowsservercore/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/windows/servercore:ltsc2016
2 | ADD InstallPreReq.ps1 /
3 | RUN powershell -File C:\InstallPreReq.ps1
4 | RUN setx PATH "%PATH%;C:\sffabricbin;C:\sffabricruntimeload" /M
--------------------------------------------------------------------------------
/docker/service-fabric-reliableservices-windowsservercore/README.md:
--------------------------------------------------------------------------------
1 | # About
2 | This folder has Dockerfile to create a Windows Server Core image with prerequisites and environment variables setup to run Service Fabric services inside containers.
3 |
4 | ## More details
5 | For more information, see the [How to containerize your Service Fabric Services](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-services-inside-containers)
6 |
--------------------------------------------------------------------------------
/code/SFBinaryLoaderForContainers/README.md:
--------------------------------------------------------------------------------
1 |
2 | # About SFBinaryLoader.cs Script
3 | This class is sample code on how to load the Service Fabric binaries when hosting service fabric services from within containers. This code should be included in your project and referenced from program main.
4 |
5 | ## More details
6 | For more details, see the [How to containerize your Service Fabric Services](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-services-inside-containers).
7 |
--------------------------------------------------------------------------------
/templates/service-integration/network-apim.parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "apimNetworkSecurityGroupName": {
6 | "value": "apim-vnet-security"
7 | },
8 | "vnetAddressSpace": {
9 | "value": "172.16.0.0/20"
10 | },
11 | "apimSubnetSpace": {
12 | "value": "172.16.0.0/27"
13 | },
14 | "apimSubnetName": {
15 | "value": "apim-subnet"
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/scripts/SetupServiceFabric/README.md:
--------------------------------------------------------------------------------
1 |
2 | # About SetupServiceFabric.sh Script
3 | This script is used for automated installation of Service Fabric Runtime and Common SDK on Linux.
4 | It also sets up the Service Fabric CLI 'sfctl'.
5 |
6 | ## Usage
7 | Use following command for automated installation of Service Fabric Runtime and Common SDK.
8 |
9 | ```bash
10 | git clone https://github.com/Azure/service-fabric-scripts-and-templates.git
11 | cd scripts/SetupServiceFabric
12 | sudo ./SetupServiceFabric.sh
13 | ```
14 |
15 | ## More details
16 | For more details, see the [Service Fabric get started on Linux](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-linux).
17 |
--------------------------------------------------------------------------------
/scripts/CodePackageToDockerPackage/README.md:
--------------------------------------------------------------------------------
1 |
2 | # About CreateDockerPackage.ps1 Script
3 | This script is a utility used to help convert your service fabric code package to a container package.
4 |
5 | ## Usage
6 |
7 | ```powershell
8 | $codePackagePath = 'Path to the code package to containerize.'
9 | $dockerPackageOutputDirectoryPath = 'Output path for the generated docker folder.'
10 | $applicationExeName = 'Name of the ode package executable.'
11 | CreateDockerPackage.ps1 -CodePackageDirectoryPath $codePackagePath -DockerPackageOutputDirectoryPath $dockerPackageOutputDirectoryPath -ApplicationExeName $applicationExeName
12 | ```
13 |
14 | ## More details
15 | For more information, see the [How to containerize your Service Fabric Services](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-services-inside-containers)
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing
3 |
4 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
5 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
6 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
7 |
8 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
9 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
10 | provided by the bot. You will only need to do this once across all repos using our CLA.
11 |
12 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
13 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
14 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
15 |
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/modules/README.md:
--------------------------------------------------------------------------------
1 |
2 | # About the scripts:
3 | Service Fabric Backup Restore Service (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-backuprestoreservice-quickstart-azurecluster),
4 | currently in preview, allows you to take periodic backups of your Reliable stateful service and Reliable Actors. Depending on the frequency of your backup interval, backups can really grow fast.
5 | While we work on providing retention support integrated with the service, this script would help you manage your storage till that time. It allows you to delete backups older than a specified time.
6 |
7 | ## Usage
8 | Import all the modules, and the use of these modules is same as of RetentionScript.ps1.
9 | Example:
10 | ```powershell
11 | Start-RetentionScript -DateTimeBefore "2018-06-18 23.44.03Z" -ConnectionString "your-connection-string" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -SSLCertificateThumbPrint "Client#Certificate#Thumbpring" -ServiceId "WebReferenceApplication~RestockRequestManager"
12 | ```
13 | These modules come in handy while scheduling the script from azure time trigger.
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/templates/nodetype-upgrade/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "clusterLocation": {
6 | "value": "southcentralus"
7 | },
8 | "clusterName": {
9 | "value": "sftestupgrade"
10 | },
11 | "adminUserName": {
12 | "value": "testadmin"
13 | },
14 | "adminPassword": {
15 | "value": "Password#1234"
16 | },
17 | "loadBalancedAppPort1": {
18 | "value": 80
19 | },
20 | "loadBalancedAppPort2": {
21 | "value": 443
22 | },
23 | "clusterProtectionLevel": {
24 | "value": "EncryptAndSign"
25 | },
26 | "certificateStoreValue": {
27 | "value": "My"
28 | },
29 | "certificateThumbprint": {
30 | "value": ""
31 | },
32 | "sourceVaultValue": {
33 | "value": ""
34 | },
35 | "certificateUrlValue": {
36 | "value": ""
37 | },
38 | "storageAccountType": {
39 | "value": "Standard_LRS"
40 | },
41 | "supportLogStorageAccountType": {
42 | "value": "Standard_LRS"
43 | },
44 | "applicationDiagnosticsStorageAccountType": {
45 | "value": "Standard_LRS"
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/templates/nodetype-upgrade-nonprimary/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "clusterLocation": {
6 | "value": "southcentralus"
7 | },
8 | "clusterName": {
9 | "value": "sftestupgrade"
10 | },
11 | "adminUserName": {
12 | "value": "testadmin"
13 | },
14 | "adminPassword": {
15 | "value": "Password#1234"
16 | },
17 | "loadBalancedAppPort1": {
18 | "value": 80
19 | },
20 | "loadBalancedAppPort2": {
21 | "value": 443
22 | },
23 | "clusterProtectionLevel": {
24 | "value": "EncryptAndSign"
25 | },
26 | "certificateStoreValue": {
27 | "value": "My"
28 | },
29 | "certificateThumbprint": {
30 | "value": ""
31 | },
32 | "sourceVaultValue": {
33 | "value": ""
34 | },
35 | "certificateUrlValue": {
36 | "value": ""
37 | },
38 | "storageAccountType": {
39 | "value": "Standard_LRS"
40 | },
41 | "supportLogStorageAccountType": {
42 | "value": "Standard_LRS"
43 | },
44 | "applicationDiagnosticsStorageAccountType": {
45 | "value": "Standard_LRS"
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/code/SFBinaryLoaderForContainers/SFBinaryLoader.cs:
--------------------------------------------------------------------------------
1 | namespace StatelessContainer
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Reflection;
6 |
7 | public static class SFBinaryLoader
8 | {
9 | private const string FabricCodePathEnvironmentVariableName = "FabricCodePath";
10 | private static string SFCodePath;
11 |
12 | static SFBinaryLoader()
13 | {
14 | AppDomain.CurrentDomain.AssemblyResolve += LoadFromFabricCodePath;
15 | }
16 |
17 | public static void Initialize()
18 | {
19 | SFCodePath = Environment.GetEnvironmentVariable(FabricCodePathEnvironmentVariableName, EnvironmentVariableTarget.Process);
20 | }
21 |
22 | private static Assembly LoadFromFabricCodePath(object sender, ResolveEventArgs args)
23 | {
24 | string assemblyName = new AssemblyName(args.Name).Name;
25 |
26 | if (string.IsNullOrEmpty(SFCodePath))
27 | {
28 | throw new InvalidOperationException("The path from where to resolve the Service Fabric binaries has not been set; please try calling SFBinaryLoader.Initialize().");
29 | }
30 |
31 | try
32 | {
33 | string assemblyPath = Path.Combine(SFCodePath, assemblyName + ".dll");
34 | if (File.Exists(assemblyPath))
35 | {
36 | return Assembly.LoadFrom(assemblyPath);
37 | }
38 | }
39 | catch (Exception e)
40 | {
41 | // Supress any Exception so that we can continue to
42 | // load the assembly through other means
43 | Console.WriteLine("Exception in LoadFromFabricCodePath={0}", e.ToString());
44 | }
45 |
46 | return null;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/templates/cluster-tutorial/vnet-cluster.parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "vnetName": {
6 | "value": "sf-vnet"
7 | },
8 | "vnetAddressSpace": {
9 | "value": "172.16.0.0/20"
10 | },
11 | "sfSubnetSpace": {
12 | "value": "172.16.2.0/23"
13 | },
14 | "sfSubnetName": {
15 | "value": "sf-subnet"
16 | },
17 | "location":{
18 | "value": "southcentralus"
19 | },
20 | "clusterName": {
21 | "value": "mysfcluster123"
22 | },
23 | "adminUserName": {
24 | "value": "adminuser"
25 | },
26 | "adminPassword": {
27 | "value": "Pa$sw00rd!123"
28 | },
29 | "certificateThumbprint": {
30 | "value": ""
31 | },
32 | "sourceVaultValue": {
33 | "value": ""
34 | },
35 | "certificateUrlValue": {
36 | "value": ""
37 | },
38 | "subnetName": {
39 | "value": "sf-subnet"
40 | },
41 | "networkSecurityGroupName": {
42 | "value": "sf-vnet-security"
43 | },
44 | "vmImagePublisher": {
45 | "value": "MicrosoftWindowsServer"
46 | },
47 | "vmImageOffer": {
48 | "value": "WindowsServer"
49 | },
50 | "vmImageSku": {
51 | "value": "2016-Datacenter-with-Containers"
52 | },
53 | "vmImageVersion": {
54 | "value": "latest"
55 | },
56 | "loadBalancedAppPort1": {
57 | "value": 80
58 | },
59 | "loadBalancedAppPort2": {
60 | "value": 443
61 | },
62 | "certificateStoreValue": {
63 | "value": "My"
64 | },
65 | "clusterProtectionLevel": {
66 | "value": "EncryptAndSign"
67 | },
68 | "storageAccountType": {
69 | "value": "Standard_LRS"
70 | },
71 | "supportLogStorageAccountType": {
72 | "value": "Standard_LRS"
73 | },
74 | "applicationDiagnosticsStorageAccountType": {
75 | "value": "Standard_LRS"
76 | },
77 | "nt0InstanceCount": {
78 | "value": 5
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/templates/cluster-tutorial/vnet-linuxcluster.parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "vnetName": {
6 | "value": "sf-vnet"
7 | },
8 | "vnetAddressSpace": {
9 | "value": "10.0.0.0/16"
10 | },
11 | "sfSubnetSpace": {
12 | "value": "10.0.2.0/24"
13 | },
14 | "sfSubnetName": {
15 | "value": "sf-subnet"
16 | },
17 | "location":{
18 | "value": "southcentralus"
19 | },
20 | "clusterName": {
21 | "value": "mysfcluster"
22 | },
23 | "adminUserName": {
24 | "value": "adminuser"
25 | },
26 | "adminPassword": {
27 | "value": "Pa$sw00rd!123"
28 | },
29 | "certificateThumbprint": {
30 | "value": ""
31 | },
32 | "sourceVaultValue": {
33 | "value": ""
34 | },
35 | "certificateUrlValue": {
36 | "value": ""
37 | },
38 | "subnetName": {
39 | "value": "sf-subnet"
40 | },
41 | "networkSecurityGroupName": {
42 | "value": "sf-vnet-security"
43 | },
44 | "vmImagePublisher": {
45 | "value": "Canonical"
46 | },
47 | "vmImageOffer": {
48 | "value": "UbuntuServer"
49 | },
50 | "vmImageSku": {
51 | "value": "16.04-LTS"
52 | },
53 | "vmImageVersion": {
54 | "value": "latest"
55 | },
56 | "loadBalancedAppPort1": {
57 | "value": 80
58 | },
59 | "loadBalancedAppPort2": {
60 | "value": 443
61 | },
62 | "certificateStorevalue": {
63 | "value": "My"
64 | },
65 | "clusterProtectionLevel": {
66 | "value": "EncryptAndSign"
67 | },
68 | "storageAccountType": {
69 | "value": "Standard_LRS"
70 | },
71 | "supportLogStorageAccountType": {
72 | "value": "Standard_LRS"
73 | },
74 | "applicationDiagnosticsStorageAccountType": {
75 | "value": "Standard_LRS"
76 | },
77 | "nt0InstanceCount": {
78 | "value": 5
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/templates/service-integration/apim.parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "apimInstanceName": {
6 | "value": "sfapim"
7 | },
8 | "apimPublisherEmail": {
9 | "value": "user@contoso.com"
10 | },
11 | "apimSku": {
12 | "value": "Developer"
13 | },
14 | "serviceFabricCertificateName": {
15 | "value": "sfclustertutorialgroup320171031144217"
16 | },
17 | "serviceFabricCertificate": {
18 | "value": ""
19 | },
20 | "certificatePassword": {
21 | "value": "q6D7nN%6ck@6"
22 | },
23 | "serviceFabricCertificateThumbprint": {
24 | "value": ""
25 | },
26 | "url_path": {
27 | "value": "/api/values"
28 | },
29 | "clusterHttpManagementEndpoint": {
30 | "value": "https://mysfcluster123.southcentralus.cloudapp.azure.com:19080"
31 | },
32 | "inbound_policy":{
33 | "value": "\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n"
34 | },
35 | "policies_policy_name": {
36 | "value": "policy"
37 | },
38 | "apis_service_fabric_app_name": {
39 | "value": "service-fabric-app"
40 | },
41 | "apim_service_fabric_product_name": {
42 | "value": "service-fabric-api-product"
43 | },
44 | "service_fabric_backend_name": {
45 | "value": "servicefabric"
46 | },
47 | "apis_service_fabric_app_name_operation": {
48 | "value": "service-fabric-app-operation"
49 | },
50 | "vnetName": {
51 | "value": "sf-vnet"
52 | },
53 | "subnetName": {
54 | "value": "apim-subnet"
55 | },
56 | "vnetVersion": {
57 | "value": "2017-03-01"
58 | },
59 | "networkSecurityGroupName": {
60 | "value": "apim-vnet-security"
61 | },
62 | "networkSecurityGroupVersion": {
63 | "value": "2017-03-01"
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/docker/service-fabric-reliableservices-windowsservercore/InstallPreReq.ps1:
--------------------------------------------------------------------------------
1 | $scriptDirectory = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
2 | $containerSetupLogDirectory = Join-Path $scriptDirectory "ContainerSetupLogs"
3 |
4 | $dotnetUrl = "https://download.visualstudio.microsoft.com/download/pr/518aafee-1285-4153-a30a-e4eefd538c90/6437d77a67b9c6b8cf0b7b3323004229/dotnet-runtime-3.1.6-win-x64.exe"
5 | $vcpp11redistUrl = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe"
6 | $vcpp14redistUrl = "https://download.visualstudio.microsoft.com/download/pr/11687625/2cd2dba5748dc95950a5c42c2d2d78e4/VC_redist.x64.exe"
7 |
8 | $TempDir = $env:TEMP
9 | $dotnetPath = Join-Path $TempDir "dotnet-runtime-3.1.6-win-x64.exe"
10 | $vcpp11redistPath = Join-Path $TempDir "vcredist_x64.exe"
11 | $vcpp14redistPath = Join-Path $TempDir "vc14_redist.x64.exe"
12 |
13 | $DownloadStartTime = [DateTime]::UtcNow
14 |
15 | $webClient = New-Object System.Net.WebClient
16 | $webClient.DownloadFile($vcpp11redistUrl, $vcpp11redistPath)
17 |
18 | $DownloadEndTime = [DateTime]::UtcNow
19 |
20 | if(Test-Path($vcpp11redistPath))
21 | {
22 | Write-Output "$($vcpp11redistPath) file download Time: $(($DownloadEndTime).Subtract($DownloadStartTime).TotalSeconds) secs"
23 |
24 | Write-Output "Installing vc++ 11 Redistributable..."
25 |
26 | Start-Process "$vcpp11redistPath" -ArgumentList "/install /quiet /norestart /log $(Join-Path $containerSetupLogDirectory vcpp11redistlog.txt)" -Wait
27 |
28 | Write-Output "Done."
29 | }
30 | else
31 | {
32 | Write-Error "Download failed"
33 | }
34 |
35 | $DownloadStartTime = [DateTime]::UtcNow
36 |
37 | $webClient.DownloadFile($vcpp14redistUrl, $vcpp14redistPath)
38 |
39 | $DownloadEndTime = [DateTime]::UtcNow
40 |
41 | if(Test-Path($vcpp14redistPath))
42 | {
43 | Write-Output "$($vcpp14redistPath) file download Time: $(($DownloadEndTime).Subtract($DownloadStartTime).TotalSeconds) secs"
44 |
45 | Write-Output "Installing vc++ 14 Redistributable..."
46 |
47 | Start-Process "$vcpp14redistPath" -ArgumentList "/install /quiet /norestart /log $(Join-Path $containerSetupLogDirectory vcpp14redistlog.txt)" -Wait
48 |
49 | Write-Output "Done."
50 | }
51 | else
52 | {
53 | Write-Error "Download failed"
54 | }
55 |
56 | $DownloadStartTime = [DateTime]::UtcNow
57 |
58 | $webClient.DownloadFile($dotnetUrl, $dotnetPath)
59 |
60 | $DownloadEndTime = [DateTime]::UtcNow
61 |
62 | if(Test-Path($dotnetPath))
63 | {
64 | Write-Output "$($dotnetPath) file download Time: $(($DownloadEndTime).Subtract($DownloadStartTime).TotalSeconds) secs"
65 |
66 | Write-Output "Installing dotnet 3.1.6..."
67 |
68 | Start-Process "$dotnetPath" -ArgumentList "/install /quiet /norestart /log $(Join-Path $containerSetupLogDirectory log.txt)" -Wait
69 |
70 | Write-Output "Done."
71 | }
72 | else
73 | {
74 | Write-Error "Download failed"
75 | }
76 |
--------------------------------------------------------------------------------
/templates/service-integration/network-apim.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "vnetName": {
6 | "defaultValue": "sf-vnet",
7 | "type": "string"
8 | },
9 | "vnetAddressSpace": {
10 | "defaultValue": "172.16.0.0/20",
11 | "type": "string"
12 | },
13 | "apimSubnetName": {
14 | "defaultValue": "apim-subnet",
15 | "type": "string"
16 | },
17 | "apimSubnetSpace": {
18 | "defaultValue": "172.16.0.0/27",
19 | "type": "string"
20 | },
21 | "apimNetworkSecurityGroupName": {
22 | "defaultValue": "apim-vnet-security",
23 | "type": "string"
24 | }
25 | },
26 | "variables": {
27 | "location": "[string(resourceGroup().location)]",
28 | "vnetApiVersion": "2017-03-01",
29 | "sgApiVersion": "2017-03-01"
30 | },
31 | "outputs": {
32 | "vnet": {
33 | "type": "object",
34 | "value": "[reference(parameters('vnetName'))]"
35 | },
36 | "vnetVersion": {
37 | "type": "string",
38 | "value": "[variables('vnetApiVersion')]"
39 | },
40 | "vnetName": {
41 | "type": "string",
42 | "value": "[parameters('vnetName')]"
43 | },
44 | "sgVersion": {
45 | "type": "string",
46 | "value": "[variables('sgApiVersion')]"
47 | },
48 | "apimSubnetName": {
49 | "type": "string",
50 | "value": "[parameters('apimSubnetName')]"
51 | },
52 | "apimSgName": {
53 | "type": "string",
54 | "value": "[parameters('apimNetworkSecurityGroupName')]"
55 | }
56 | },
57 | "resources": [
58 | {
59 |
60 | "apiVersion": "[variables('sgApiversion')]",
61 |
62 | "type": "Microsoft.Network/virtualNetworks/subnets",
63 |
64 | "name": "[concat(parameters('vnetName'), '/', parameters('apimSubnetName'))]",
65 |
66 | "location": "[variables('location')]",
67 |
68 | "properties": {
69 | "addressPrefix": "[parameters('apimSubnetSpace')]",
70 | "networkSecurityGroup": {
71 | "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('apimNetworkSecurityGroupName'))]"
72 | }
73 | },
74 | "dependsOn": [
75 | "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('apimNetworkSecurityGroupName'))]"
76 | ]
77 |
78 | },
79 | {
80 | "type": "Microsoft.Network/networkSecurityGroups",
81 | "name": "[parameters('apimNetworkSecurityGroupName')]",
82 | "apiVersion": "[variables('sgApiversion')]",
83 | "location": "[variables('location')]",
84 | "tags": {
85 | "resourceType": "API Management"
86 | }
87 | }
88 | ],
89 | "outputs": {}
90 | }
--------------------------------------------------------------------------------
/scripts/CodePackageToDockerPackage/CreateDockerPackage.ps1:
--------------------------------------------------------------------------------
1 | param (
2 | [Parameter(Mandatory=$true, ParameterSetName = "Exe")]
3 | [Parameter(Mandatory=$true, ParameterSetName = "Dll")]
4 | [string] $CodePackageDirectoryPath,
5 |
6 | [Parameter(Mandatory=$true, ParameterSetName = "Exe")]
7 | [Parameter(Mandatory=$true, ParameterSetName = "Dll")]
8 | [string] $DockerPackageOutputDirectoryPath,
9 |
10 | [Parameter(Mandatory=$false, ParameterSetName = "Exe")]
11 | [string] $ApplicationExeName,
12 |
13 | [Parameter(Mandatory=$false, ParameterSetName = "Dll")]
14 | [string] $DotnetCoreDllName
15 | )
16 |
17 | if(!(Test-Path -Path $CodePackageDirectoryPath))
18 | {
19 | Write-Error "CodePackageDirectoryPath does not exist."
20 | exit 1
21 | }
22 |
23 | if(!(Test-Path -Path $DockerPackageOutputDirectoryPath))
24 | {
25 | Write-Host $DockerPackageOutputDirectoryPath "does not exist. Creating directory.."
26 | New-Item -ItemType directory $DockerPackageOutputDirectoryPath | Out-Null
27 | Write-Host "Created " $DockerPackageOutputDirectoryPath
28 | }
29 |
30 | # Remove publish folder if it exists, and remove the dockerfile
31 | $DockerPublishPath = Join-Path $DockerPackageOutputDirectoryPath -ChildPath "publish"
32 | if(Test-Path -Path $DockerPublishPath)
33 | {
34 | Remove-Item -Path $DockerPublishPath -Recurse -Force
35 | Write-Host "Removed existing publish directory."
36 | }
37 |
38 | $dockerfilePath = Join-Path $DockerPackageOutputDirectoryPath -ChildPath "Dockerfile"
39 | if(Test-Path -Path $dockerfilePath)
40 | {
41 | Remove-Item -Path $dockerfilePath -Force
42 | Write-Host "Removed existing Dockerfile."
43 | }
44 |
45 | $DockerPublishPath = Join-Path $DockerPackageOutputDirectoryPath -ChildPath "publish"
46 | if(!(Test-Path -Path $DockerPublishPath))
47 | {
48 | New-Item -ItemType directory $DockerPublishPath | Out-Null
49 | Write-Host "Created " $DockerPublishPath
50 | }
51 |
52 |
53 | Write-Host "Copying all files from " $CodePackageDirectoryPath " to " $DockerPublishPath
54 | $SourceCopyPath = Join-Path $CodePackageDirectoryPath -ChildPath "*"
55 | Copy-Item -Path $SourceCopyPath -Destination $DockerPublishPath -Recurse -Force
56 | Write-Host "Files successfully copied."
57 |
58 | Remove-Item $CodePackageDirectoryPath -Recurse -Force
59 | Write-Host "Removed " $CodePackageDirectoryPath
60 |
61 | $initScriptPath = Join-Path $DockerPublishPath -ChildPath "init.bat"
62 |
63 | if ($ApplicationExeName)
64 | {
65 | $initScriptContents = [System.IO.Path]::GetFileNameWithoutExtension($ApplicationExeName) + ".exe"
66 | }
67 | elseif ($DotnetCoreDllName)
68 | {
69 | $initScriptContents = "dotnet " + [System.IO.Path]::GetFileNameWithoutExtension($DotnetCoreDllName) + ".dll"
70 | }
71 | else
72 | {
73 | $warning = "Modify init.bat inside " + $DockerPublishPath + " to include the name of your startup executable."
74 | Write-Warning $warning
75 | }
76 |
77 | Write-Host "Creating init.bat for docker package"
78 | New-Item -ItemType file $initScriptPath -Value $initScriptContents -Force | Out-Null
79 |
80 | $dockerfilePath = Join-Path $DockerPackageOutputDirectoryPath -ChildPath "Dockerfile"
81 | $dockerfileContents = 'FROM mcr.microsoft.com/windows/servercore:ltsc2019
82 | ADD https://raw.githubusercontent.com/microsoft/service-fabric-scripts-and-templates/master/docker/service-fabric-reliableservices-windowsservercore/InstallPreReq.ps1 /
83 | RUN powershell -File C:\InstallPreReq.ps1
84 | RUN setx PATH "%PATH%;C:\sffabricbin;C:\sffabricruntimeload" /M
85 | ADD publish/ /
86 | CMD C:\init.bat'
87 |
88 | Write-Host "Creating Dockerfile"
89 | New-Item -ItemType file $dockerfilePath -Value $dockerfileContents -Force | Out-Null
90 |
91 | Write-Host "Docker package successfully created at " $DockerPackageOutputDirectoryPath
92 |
--------------------------------------------------------------------------------
/templates/nodetype-upgrade-nonprimary/README.md:
--------------------------------------------------------------------------------
1 | # Scale up a Service Fabric cluster non-primary node type
2 |
3 | These before/after templates represent the steps of upgrading the primary node type VM size and operating system of an example cluster.
4 |
5 | The initial state of the example test cluster consists of two node types of Silver durability, backed by a single scale set with five nodes. The upgraded state of the cluster adds an additional, upgraded scale set (with VM size from Standard_D2_V2 to Standard D4_V2, and OS from Windows Server 2019 to 2022 Datacenter). Follow these commands to walkthrough the complete upgrade scenario. For a more detailed discussion of the procedure, see [Scale up a Service Fabric cluster primary node type](https://docs.microsoft.com/azure/service-fabric/service-fabric-scale-up-primary-node-type).
6 |
7 | ```powershell
8 | # Sign in to your Azure account
9 | Login-AzAccount -SubscriptionId ""
10 |
11 | # Assign deployment variables
12 | $resourceGroupName = "sftestupgradegroup"
13 | $certOutputFolder = "c:\certificates"
14 | $certPassword = "Password!1" | ConvertTo-SecureString -AsPlainText -Force
15 | $certSubjectName = "sftestupgrade.southcentralus.cloudapp.azure.com"
16 | $templateFilePath = "C:\Initial-TestClusterSetup.json"
17 | $parameterFilePath = "C:\parameters.json"
18 |
19 | # Deploy the initial test cluster
20 | New-AzServiceFabricCluster `
21 | -ResourceGroupName $resourceGroupName `
22 | -CertificateOutputFolder $certOutputFolder `
23 | -CertificatePassword $certPassword `
24 | -CertificateSubjectName $certSubjectName `
25 | -TemplateFile $templateFilePath `
26 | -ParameterFile $parameterFilePath
27 |
28 | # Import the local .pfx file to your certificate store
29 | cd c:\certificates
30 | $certPfx = ".\sftestupgradegroup20200312121003.pfx"
31 |
32 | Import-PfxCertificate `
33 | -FilePath $certPfx `
34 | -CertStoreLocation Cert:\CurrentUser\My `
35 | -Password (ConvertTo-SecureString Password!1 -AsPlainText -Force)
36 |
37 | # Connect to the cluster and check health
38 | $clusterName = "sftestupgrade.southcentralus.cloudapp.azure.com:19000"
39 | $thumb = "BB796AA33BD9767E7DA27FE5182CF8FDEE714A70"
40 |
41 | Connect-ServiceFabricCluster `
42 | -ConnectionEndpoint $clusterName `
43 | -KeepAliveIntervalInSec 10 `
44 | -X509Credential `
45 | -ServerCertThumbprint $thumb `
46 | -FindType FindByThumbprint `
47 | -FindValue $thumb `
48 | -StoreLocation CurrentUser `
49 | -StoreName My
50 |
51 | Get-ServiceFabricClusterHealth
52 |
53 | # Find your certificate Key Vault references (in Azure portal)
54 | $certUrlValue = "https://sftestupgradegroup.vault.azure.net/secrets/sftestupgradegroup20200309235308/dac0e7b7f9d4414984ccaa72bfb2ea39"
55 | $thumb = "BB796AA33BD9767E7DA27FE5182CF8FDEE714A70"
56 | $sourceVaultValue = "/subscriptions/########-####-####-####-############/resourceGroups/sftestupgradegroup/providers/Microsoft.KeyVault/vaults/sftestupgradegroup"
57 |
58 | # Deploy the updated template with new scale set (upgraded to use managed disks)
59 | $templateFilePath = "C:\Step1-AddNonPrimaryNodeType.json"
60 |
61 | New-AzResourceGroupDeployment `
62 | -ResourceGroupName $resourceGroupName `
63 | -TemplateFile $templateFilePath `
64 | -TemplateParameterFile $parameterFilePath `
65 | -CertificateThumbprint $thumb `
66 | -CertificateUrlValue $certUrlValue `
67 | -SourceVaultValue $sourceVaultValue `
68 | -Verbose
69 |
70 | # Ensure cluster is healthy, then disable nodes in the original scale set
71 | Get-ServiceFabricClusterHealth
72 |
73 | # Disable the nodes in the original scale set.
74 | $nodeType = "nt1vm"
75 | $nodes = Get-ServiceFabricNode
76 |
77 | Write-Host "Disabling nodes..."
78 | foreach($node in $nodes)
79 | {
80 | if ($node.NodeType -eq $nodeType)
81 | {
82 | $node.NodeName
83 |
84 | Disable-ServiceFabricNode -Intent RemoveNode -NodeName $node.NodeName -Force
85 | }
86 | }
87 |
88 | # Stop data on the disabled nodes.
89 | foreach($node in $nodes)
90 | {
91 | if ($node.NodeType -eq $nodeType)
92 | {
93 | $node.NodeName
94 |
95 | Start-ServiceFabricNodeTransition -Stop -OperationId (New-Guid) -NodeInstanceId $node.NodeInstanceId -NodeName $node.NodeName -StopDurationInSeconds 10000
96 | }
97 | }
98 |
99 | # Remove the original scale set
100 | $scaleSetName = "nt1vm"
101 | $scaleSetResourceType = "Microsoft.Compute/virtualMachineScaleSets"
102 |
103 | Remove-AzResource -ResourceName $scaleSetName -ResourceType $scaleSetResourceType -ResourceGroupName $resourceGroupName -Force
104 |
105 | # Delete the original IP and load balancer resources
106 | $lbName = "LB-sftestupgrade-nt1vm"
107 | $lbResourceType = "Microsoft.Network/loadBalancers"
108 | $ipResourceType = "Microsoft.Network/publicIPAddresses"
109 | $oldPublicIpName = "PublicIP-LB-FE-nt0vm"
110 |
111 | Remove-AzResource -ResourceName $lbName -ResourceType $lbResourceType -ResourceGroupName $resourceGroupName -Force
112 | Remove-AzResource -ResourceName $oldPublicIpName -ResourceType $ipResourceType -ResourceGroupName $resourceGroupName -Force
113 |
114 | # Remove node states for the deleted scale set
115 | $nodeType = "nt1vm"
116 | $nodes = Get-ServiceFabricNode
117 |
118 | Write-Host "Removing node state..."
119 | foreach($node in $nodes)
120 | {
121 | if ($node.NodeType -eq $nodeType)
122 | {
123 | $node.NodeName
124 |
125 | Remove-ServiceFabricNodeState -NodeName $node.NodeName -Force
126 | }
127 | }
128 |
129 | # Update the template to reflect your changes and redeploy
130 | $templateFilePath = "C:\Step2-CleanupOriginalNonPrimaryNodeType"
131 |
132 | New-AzResourceGroupDeployment `
133 | -ResourceGroupName $resourceGroupName `
134 | -TemplateFile $templateFilePath `
135 | -TemplateParameterFile $parameterFilePath `
136 | -CertificateThumbprint $thumb `
137 | -CertificateUrlValue $certUrlValue `
138 | -SourceVaultValue $sourceVaultValue `
139 | -Verbose
140 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/README.md:
--------------------------------------------------------------------------------
1 |
2 | # About the scripts:
3 | Service Fabric Backup Restore Service (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-backuprestoreservice-quickstart-azurecluster),
4 | currently in preview, allows you to take periodic backups of your Reliable stateful service and Reliable Actors. Depending on the frequency of your backup interval, backups can really grow fast.
5 | While we work on providing retention support integrated with the service, this script would help you manage your storage till that time. It allows you to delete backups older than a specified time.
6 |
7 | ## Usage
8 | This script support both the storage types supported by Backup Restore service:
9 | 1) Azure blob store
10 | 2) File Share
11 |
12 | ## How to use with Azure Storage:
13 |
14 | You can run the script by providing single azure storage connection string as parameter or you can also provide azure account name and key separately.
15 | Examples:
16 | 1) The below example will delete all the backups in the storage(specifed with connection string) of the service with serviceid *WebReferenceApplication~RestockRequestManager*.
17 | ```powershell
18 | .\RetentionScript.ps1 -DateTimeBefore "2018-06-18 23.44.03Z" -ConnectionString "your-connection-string" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -ServiceId "WebReferenceApplication~RestockRequestManager"
19 | ```
20 | 2) In this example, passing storage account name and key separately.
21 | ```powershell
22 | .\RetentionScript.ps1 -DateTimeBefore "2018-06-18 23.44.03Z" -StorageAccountName "storageaccountname" -StorageAccountName "storgeAccountName" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -ServiceId "WebReferenceApplication~RestockRequestManager"
23 | ```
24 | 3) You can also filter the container for cleanup. This example will delete backup data for all the partitions available on the container named brstorage:
25 | ```powershell
26 | .\RetentionScript.ps1 -ContainerName "brstorage"-DateTimeBefore "2018-06-18 23.44.03Z" -StorageAccountName "storageaccountname" -StorageAccountName "storgeAccountName" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring"
27 | ```
28 | 3) Similarly you can also filter the application by providing the ApplicationId. If Application name is *fabric:/WebReferenceApplication* then,
29 | application id is *WebReferenceApplication*:
30 | ```powershell
31 | .\RetentionScript.ps1 -ContainerName "brstorage"-DateTimeBefore "2018-06-18 23.44.03Z" -StorageAccountName "storageaccountname" -StorageAccountName "storgeAccountName" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -ApplicationId "WebReferenceApplication"
32 | ```
33 | 4) Filtering for parition with partitionId *18cf9495-7233-42a0-929d-5ca9c110b861*
34 | ```powershell
35 | .\RetentionScript.ps1 -ContainerName "brstorage"-DateTimeBefore "2018-06-18 23.44.03Z" -StorageAccountName "storageaccountname" -StorageAccountName "storgeAccountName" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -PartitionId "18cf9495-7233-42a0-929d-5ca9c110b861"
36 | ```
37 |
38 | ## How to use with File Storage:
39 |
40 | If the storage is protected with userName(in the format Domain\user) and password, then, you need to provide password as securestring to the input variable *Password*
41 | Examples:
42 | The below example will delete backups of the paritition with partition id "18cf9495-7233-42a0-929d-5ca9c110b861" before "2018-06-18 23.44.03Z".
43 | ```powershell
44 | $pass = "Passoword" | ConvertTo-SecureString -AsPlainText -Force
45 | .\RetentionScript.ps1 -DateTimeBefore "2018-06-18 23.44.03Z" -FileShareUserName "Domain\brsuser" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -Password $pass -FileSharePath "\\fileshare\sharedfolder" -PartitionId "18cf9495-7233-42a0-929d-5ca9c110b861"
46 | ```
47 |
48 | The below example will delete backups of the application with application id *WebReferenceApplication* before "2018-06-18 23.44.03Z".
49 | ```powershell
50 | .\RetentionScript.ps1 -DateTimeBefore "2018-06-18 23.44.03Z" -FileShareUserName "Domain\brsuser" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -Password $pass -FileSharePath "\\fileshare\sharedfolder" -ApplicationId "WebReferenceApplication"
51 | ```
52 |
53 | The below example will delete backups of the service with service id *WebReferenceApplication~RestockRequestManager* before "2018-06-18 23.44.03Z".
54 | ```powershell
55 | .\RetentionScript.ps1 -DateTimeBefore "2018-06-18 23.44.03Z" -FileShareUserName "Domain\brsuser" -ClusterEndPoint "clustername.centralus.cloupapp.azure.com:19080" -ClientCertificateThumbprint "Client#Certificate#Thumbpring" -Password $pass -FileSharePath "\\fileshare\sharedfolder" -ServiceId "WebReferenceApplication~RestockRequestManager"
56 | ```
57 |
58 | ## Notes:
59 |
60 | 1) DateTimeBefore should be provided in the format(*yyyy-MM-dd HH.mm.ssZ*)
61 | 2) ClientCertificateThumbprint is required if you are cleaning up storage of a secured cluster.
62 | 3) If the management end point of the cluster is this *https://cluster.centralus.cloudapp.azure.com:19080/*, then, the clusterendpoint will be *cluster.centralus.cloudapp.azure.com:19080*
63 | 4) The above script will delete the data for only those partitions on the storage which are found active on the cluster end point provided.
64 | If you need to delete data for the partitions which are not active on the cluster, then add -DeleteNotFoundPartitions flag while running the retention script.
65 |
66 | ## How to schedule the script?
67 |
68 | For azure storage, it is recommended to use azure function time trigger to schedule the script. For more information, please visit https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer
69 | For file share, you can use windows task scheduler.
70 |
71 | ## More details
72 | For more information about the parameters , please read description of RetentionScript.ps1 file by opening it in any text editor.
73 |
--------------------------------------------------------------------------------
/templates/nodetype-upgrade/README.md:
--------------------------------------------------------------------------------
1 | # Scale up a Service Fabric cluster primary node type
2 |
3 | These before/after templates represent the steps of upgrading the primary node type VM size and operating system of an example cluster.
4 |
5 | The initial state of the example test cluster consists of one node type of Silver durability, backed by a single scale set with five nodes. The upgraded state of the cluster adds an additional, upgraded scale set (with VM size from Standard_D2_V2 to Standard D4_V2, and OS from Windows Server 2019 to 2022 Datacenter). Follow these commands to walkthrough the complete upgrade scenario. For a more detailed discussion of the procedure, see [Scale up a Service Fabric cluster primary node type](https://docs.microsoft.com/azure/service-fabric/service-fabric-scale-up-primary-node-type).
6 |
7 | ```powershell
8 | # Sign in to your Azure account
9 | Login-AzAccount -SubscriptionId ""
10 |
11 | # Assign deployment variables
12 | $resourceGroupName = "sftestupgradegroup"
13 | $certOutputFolder = "c:\certificates"
14 | $certPassword = "Password!1" | ConvertTo-SecureString -AsPlainText -Force
15 | $certSubjectName = "sftestupgrade.southcentralus.cloudapp.azure.com"
16 | $templateFilePath = "C:\Initial-TestClusterSetup.json"
17 | $parameterFilePath = "C:\parameters.json"
18 |
19 | # Deploy the initial test cluster
20 | New-AzServiceFabricCluster `
21 | -ResourceGroupName $resourceGroupName `
22 | -CertificateOutputFolder $certOutputFolder `
23 | -CertificatePassword $certPassword `
24 | -CertificateSubjectName $certSubjectName `
25 | -TemplateFile $templateFilePath `
26 | -ParameterFile $parameterFilePath
27 |
28 | # Import the local .pfx file to your certificate store
29 | cd c:\certificates
30 | $certPfx = ".\sftestupgradegroup20200312121003.pfx"
31 |
32 | Import-PfxCertificate `
33 | -FilePath $certPfx `
34 | -CertStoreLocation Cert:\CurrentUser\My `
35 | -Password (ConvertTo-SecureString Password!1 -AsPlainText -Force)
36 |
37 | # Connect to the cluster and check health
38 | $clusterName = "sftestupgrade.southcentralus.cloudapp.azure.com:19000"
39 | $thumb = "BB796AA33BD9767E7DA27FE5182CF8FDEE714A70"
40 |
41 | Connect-ServiceFabricCluster `
42 | -ConnectionEndpoint $clusterName `
43 | -KeepAliveIntervalInSec 10 `
44 | -X509Credential `
45 | -ServerCertThumbprint $thumb `
46 | -FindType FindByThumbprint `
47 | -FindValue $thumb `
48 | -StoreLocation CurrentUser `
49 | -StoreName My
50 |
51 | Get-ServiceFabricClusterHealth
52 |
53 | # Find your certificate Key Vault references (in Azure portal)
54 | $certUrlValue = "https://sftestupgradegroup.vault.azure.net/secrets/sftestupgradegroup20200309235308/dac0e7b7f9d4414984ccaa72bfb2ea39"
55 | $thumb = "BB796AA33BD9767E7DA27FE5182CF8FDEE714A70"
56 | $sourceVaultValue = "/subscriptions/########-####-####-####-############/resourceGroups/sftestupgradegroup/providers/Microsoft.KeyVault/vaults/sftestupgradegroup"
57 |
58 | # Deploy the updated template with new scale set (upgraded to use managed disks)
59 | $templateFilePath = "C:\Step1-AddPrimaryNodeType.json"
60 |
61 | New-AzResourceGroupDeployment `
62 | -ResourceGroupName $resourceGroupName `
63 | -TemplateFile $templateFilePath `
64 | -TemplateParameterFile $parameterFilePath `
65 | -CertificateThumbprint $thumb `
66 | -CertificateUrlValue $certUrlValue `
67 | -SourceVaultValue $sourceVaultValue `
68 | -Verbose
69 |
70 | # Ensure cluster is healthy, then disable nodes in the original scale set
71 | Get-ServiceFabricClusterHealth
72 |
73 | # Disable the nodes in the original scale set.
74 | $nodeType = "nt0vm"
75 | $nodes = Get-ServiceFabricNode
76 |
77 | Write-Host "Disabling nodes..."
78 | foreach($node in $nodes)
79 | {
80 | if ($node.NodeType -eq $nodeType)
81 | {
82 | $node.NodeName
83 |
84 | Disable-ServiceFabricNode -Intent RemoveNode -NodeName $node.NodeName -Force
85 | }
86 | }
87 |
88 | # Stop data on the disabled nodes.
89 | foreach($node in $nodes)
90 | {
91 | if ($node.NodeType -eq $nodeType)
92 | {
93 | $node.NodeName
94 |
95 | Start-ServiceFabricNodeTransition -Stop -OperationId (New-Guid) -NodeInstanceId $node.NodeInstanceId -NodeName $node.NodeName -StopDurationInSeconds 10000
96 | }
97 | }
98 |
99 | # Remove the original scale set
100 | $scaleSetName = "nt0vm"
101 | $scaleSetResourceType = "Microsoft.Compute/virtualMachineScaleSets"
102 |
103 | Remove-AzResource -ResourceName $scaleSetName -ResourceType $scaleSetResourceType -ResourceGroupName $resourceGroupName -Force
104 |
105 | # Delete the original IP and load balancer resources
106 | $lbName = "LB-sftestupgrade-nt0vm"
107 | $lbResourceType = "Microsoft.Network/loadBalancers"
108 | $ipResourceType = "Microsoft.Network/publicIPAddresses"
109 | $oldPublicIpName = "PublicIP-LB-FE-nt0vm"
110 | $newPublicIpName = "PublicIP-LB-FE-nt1vm"
111 |
112 | $oldPrimaryPublicIP = Get-AzPublicIpAddress -Name $oldPublicIpName -ResourceGroupName $resourceGroupName
113 | $primaryDNSName = $oldPrimaryPublicIP.DnsSettings.DomainNameLabel
114 | $primaryDNSFqdn = $oldPrimaryPublicIP.DnsSettings.Fqdn
115 |
116 | Remove-AzResource -ResourceName $lbName -ResourceType $lbResourceType -ResourceGroupName $resourceGroupName -Force
117 | Remove-AzResource -ResourceName $oldPublicIpName -ResourceType $ipResourceType -ResourceGroupName $resourceGroupName -Force
118 |
119 | $PublicIP = Get-AzPublicIpAddress -Name $newPublicIpName -ResourceGroupName $resourceGroupName
120 | $PublicIP.DnsSettings.DomainNameLabel = $primaryDNSName
121 | $PublicIP.DnsSettings.Fqdn = $primaryDNSFqdn
122 | Set-AzPublicIpAddress -PublicIpAddress $PublicIP
123 |
124 | # Remove node states for the deleted scale set
125 | $nodeType = "nt0vm"
126 | $nodes = Get-ServiceFabricNode
127 |
128 | Write-Host "Removing node state..."
129 | foreach($node in $nodes)
130 | {
131 | if ($node.NodeType -eq $nodeType)
132 | {
133 | $node.NodeName
134 |
135 | Remove-ServiceFabricNodeState -NodeName $node.NodeName -Force
136 | }
137 | }
138 |
139 | # Update the template to reflect your changes and redeploy
140 | $templateFilePath = "C:\Step3-CleanupOriginalPrimaryNodeType"
141 |
142 | New-AzResourceGroupDeployment `
143 | -ResourceGroupName $resourceGroupName `
144 | -TemplateFile $templateFilePath `
145 | -TemplateParameterFile $parameterFilePath `
146 | -CertificateThumbprint $thumb `
147 | -CertificateUrlValue $certUrlValue `
148 | -SourceVaultValue $sourceVaultValue `
149 | -Verbose
150 |
151 |
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/RetentionScript.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This powersehll script helps delete older backups from Azure storage or file share which were taken using the Service Fabric Backup Restore service.
4 |
5 | .PARAMETER FileShareUserName
6 | FileShareUserName associated with file share.
7 |
8 | .PARAMETER FileSharePath
9 | The file share path of the storage configured for backup.
10 |
11 | .PARAMETER StorageType
12 | It could be one of the two storages supported:
13 | 1. AzureBlob
14 | 2. FileShare
15 |
16 | .PARAMETER DateTimeBefore(Required)
17 | It is the date time value for deleting the backups before that time. It should be provided in the format(yyyy-MM-dd HH.mm.ssZ)
18 | Example:
19 | $DateTimeBefore = [DateTime]::Now.ToString("yyyy-MM-dd HH.mm.ssZ")
20 |
21 | .PARAMETER ConnectionString
22 | Connection string to the azure storage configured for backup.
23 |
24 | .PARAMETER Password
25 | File share password for the user name $FileShareUserName.It must be specified in Secure String
26 | Example:
27 | $Password ="Password" | ConvertTo-SecureString -AsPlainText -Force
28 |
29 | .PARAMETER ContainerName(Optional)
30 | Container name of storage in which backups are stored.
31 |
32 | .PARAMETER StorageAccountName
33 | Azure storage account name
34 |
35 | .PARAMETER StorageAccountKey
36 | Azure storage account key
37 |
38 | .PARAMETER ClusterEndPoint(Required)
39 | It is the management end point of the cluster.
40 | example:
41 | ManagementEndpoint : https://clustername.centralus.cloudapp.azure.com:19080
42 | $ClusterEndPoint : clustername.centralus.cloudapp.azure.com:19080
43 |
44 | .PARAMETER DeleteNotFoundPartitions(Optional)
45 | If there are partitions on the storage which are not found on the cluster, and you want to delete complete data in the partition
46 | then, enable the flag and run the script.
47 |
48 | .PARAMETER PartitionId(Optional)
49 | Filter to delete data for a particular partition on the cluster
50 |
51 | .PARAMETER ApplicationId
52 | Filter to delete data for a particular Application on the cluster
53 | Example:
54 | if ApplicationName(without fabric:) is "application/Name" then,
55 | $ApplicationId = "application~Name"(Replace "/" with "~")
56 |
57 | .PARAMETER ServiceId
58 | Filter to delete data for a particular service on the cluster
59 | Example:
60 | if ServiceName(without fabric:) is "Service/Name" then,
61 | $ServiceId = "Service~Name"(Replace "/" with "~")
62 |
63 | .PARAMETER ClientCertificateThumbprint(Required in case of secured cluster)
64 | Thumbprint of the client certificate
65 | #>
66 |
67 | [CmdletBinding(PositionalBinding = $false)]
68 | param (
69 | [Parameter(Mandatory=$false)]
70 | [String] $FileShareUserName,
71 |
72 | [Parameter(Mandatory=$false)]
73 | [String] $FileSharePath,
74 |
75 | [Parameter(Mandatory=$true)]
76 | [String] $StorageType,
77 |
78 | [Parameter(Mandatory=$true)]
79 | [String] $DateTimeBefore,
80 |
81 | [Parameter(Mandatory=$false)]
82 | [String] $ConnectionString,
83 |
84 | [Parameter(Mandatory=$false)]
85 | [SecureString] $Password,
86 |
87 | [Parameter(Mandatory=$false)]
88 | [String] $ContainerName,
89 |
90 | [Parameter(Mandatory=$false)]
91 | [string] $StorageAccountName,
92 |
93 | [Parameter(Mandatory=$false)]
94 | [String] $StorageAccountKey,
95 |
96 | [Parameter(Mandatory=$true)]
97 | [String] $ClusterEndPoint,
98 |
99 | [Parameter(Mandatory=$false)]
100 | [Switch] $DeleteNotFoundPartitions,
101 |
102 | [Parameter(Mandatory=$false)]
103 | [String] $PartitionId,
104 |
105 | [Parameter(Mandatory=$false)]
106 | [String] $ServiceId,
107 |
108 | [Parameter(Mandatory=$false)]
109 | [String] $ApplicationId,
110 |
111 | [Parameter(Mandatory=$false)]
112 | [String] $ClientCertificateThumbprint
113 | )
114 |
115 | $command = ""
116 | if($StorageType -eq "FileShare")
117 | {
118 | if(!$FileSharePath)
119 | {
120 | $FileSharePath = Read-Host -Prompt "Please enter the FileShare path"
121 | }
122 |
123 | if($FileShareUserName)
124 | {
125 | $command = $command + ".\RetentionScriptFileShare.ps1 -UserName `"$FileShareUserName`" -FileSharePath `"$FileSharePath`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
126 | if(!$Password)
127 | {
128 | $Password = Read-Host -Prompt "Please enter password for the userName: $FileShareUserName" -AsSecureString
129 | }
130 | $Global:Pass = $Password
131 | }
132 | else {
133 | $command = $command + ".\RetentionScriptFileShare.ps1 -FileSharePath `"$FileSharePath`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
134 | }
135 | }
136 | elseif($StorageType -eq "AzureBlob")
137 | {
138 | if($ConnectionString)
139 | {
140 | if($ContainerName)
141 | {
142 | $command = $command + ".\RetentionScriptAzureBlobStore.ps1 -ConnectionString `"$ConnectionString`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
143 | }
144 | else {
145 | $command = $command + ".\RetentionScriptAzureBlobStore.ps1 -ConnectionString `"$ConnectionString`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
146 | }
147 | }
148 | else {
149 | if(!$StorageAccountName)
150 | {
151 | $StorageAccountName = Read-Host -Prompt "Please enter the Storage account name"
152 | }
153 | if(!$StorageAccountKey)
154 | {
155 | $StorageAccountKey = Read-Host -Prompt "Please enter the Storage account key"
156 | }
157 | $command = $command + ".\RetentionScriptAzureBlobStore.ps1 -StorageAccountName `"$StorageAccountName`" -StorageAccountKey `"$StorageAccountKey`" -DateTimeBefore `"$DateTimeBefore`" -ContainerName `"$ContainerName`" -ClusterEndPoint `"$ClusterEndPoint`""
158 | }
159 |
160 | if($ContainerName)
161 | {
162 | $command = $command + " -ContainerName `"$ContainerName`""
163 | }
164 | }
165 | else {
166 | throw "The storage of type $StorageType not supported"
167 | }
168 |
169 | if($ApplicationId)
170 | {
171 | $command = $command + " -ApplicationId `"$ApplicationId`""
172 | }
173 | if($ServiceId)
174 | {
175 | $command = $command + " -ServiceId `"$ServiceId`""
176 | }
177 |
178 | if($ClientCertificateThumbprint)
179 | {
180 | $command = $command + " -ClientCertificateThumbprint `"$ClientCertificateThumbprint`""
181 | }
182 |
183 | if($PartitionId)
184 | {
185 | $command = $command + " -PartitionId `"$PartitionId`""
186 | }
187 |
188 | if($DeleteNotFoundPartitions)
189 | {
190 | $command = $command + " -DeleteNotFoundPartitions"
191 | }
192 |
193 | $scriptBlock = [ScriptBlock]::Create($command)
194 | Invoke-Command $scriptBlock
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/modules/RetentionScript.psm1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This powersehll module helps delete older backups from Azure storage or file share which were taken using the Service Fabric Backup Restore service.
4 |
5 | .PARAMETER FileShareUserName
6 | FileShareUserName associated with file share.
7 |
8 | .PARAMETER FileSharePath
9 | The file share path of the storage configured for backup.
10 |
11 | .PARAMETER StorageType
12 | It could be one of the two storages supported:
13 | 1. AzureBlob
14 | 2. FileShare
15 |
16 | .PARAMETER DateTimeBefore(Required)
17 | It is the date time value for deleting the backups before that time. It should be provided in the format(yyyy-MM-dd HH.mm.ssZ)
18 | Example:
19 | $DateTimeBefore = [DateTime]::Now.ToString("yyyy-MM-dd HH.mm.ssZ")
20 |
21 | .PARAMETER ConnectionString
22 | Connection string to the azure storage configured for backup.
23 |
24 | .PARAMETER Password
25 | File share password for the user name $FileShareUserName.It must be specified in Secured String
26 | Example:
27 | $pass ="Password" | ConvertTo-SecureString -AsPlainText -Force
28 |
29 | .PARAMETER ContainerName(Optional)
30 | Container name of storage in which backups are stored.
31 |
32 | .PARAMETER StorageAccountName
33 | Azure storage account name
34 |
35 | .PARAMETER StorageAccountKey
36 | Azure storage account key
37 |
38 | .PARAMETER ClusterEndPoint(Required)
39 | It is the management end point of the cluster.
40 | example:
41 | ManagementEndpoint : https://clustername.centralus.cloudapp.azure.com:19080
42 | $ClusterEndPoint : clustername.centralus.cloudapp.azure.com:19080
43 |
44 | .PARAMETER DeleteNotFoundPartitions(Optional)
45 | If there are partitions on the storage which are not found on the cluster, and you want to delete complete data in the partition
46 | then, enable the flag and run the script.
47 |
48 | .PARAMETER PartitionId(Optional)
49 | Filter to delete data for a particular partition on the cluster
50 |
51 | .PARAMETER ApplicationId
52 | Filter to delete data for a particular Application on the cluster
53 | Example:
54 | if ApplicationName(without fabric:) is "application/Name" then,
55 | $ApplicationId = "application~Name"(Replace "/" with "~")
56 |
57 | .PARAMETER ServiceId
58 | Filter to delete data for a particular service on the cluster
59 | Example:
60 | if ServiceName(without fabric:) is "Service/Name" then,
61 | $ServiceId = "Service~Name"(Replace "/" with "~")
62 |
63 | .PARAMETER ClientCertificateThumbprint(Required in case of secured cluster)
64 | Thumbprint of the client certificate
65 | #>
66 |
67 | Function Start-RetentionScript
68 | {
69 | [CmdletBinding(PositionalBinding = $false)]
70 | param (
71 | [Parameter(Mandatory=$false)]
72 | [String] $FileShareUserName,
73 |
74 | [Parameter(Mandatory=$false)]
75 | [String] $FileSharePath,
76 |
77 | [Parameter(Mandatory=$true)]
78 | [String] $StorageType,
79 |
80 | [Parameter(Mandatory=$true)]
81 | [String] $DateTimeBefore,
82 |
83 | [Parameter(Mandatory=$false)]
84 | [String] $ConnectionString,
85 |
86 | [Parameter(Mandatory=$false)]
87 | [SecureString] $Password,
88 |
89 | [Parameter(Mandatory=$false)]
90 | [String] $ContainerName,
91 |
92 | [Parameter(Mandatory=$false)]
93 | [string] $StorageAccountName,
94 |
95 | [Parameter(Mandatory=$false)]
96 | [String] $StorageAccountKey,
97 |
98 | [Parameter(Mandatory=$true)]
99 | [String] $ClusterEndPoint,
100 |
101 | [Parameter(Mandatory=$false)]
102 | [Switch] $DeleteNotFoundPartitions,
103 |
104 | [Parameter(Mandatory=$false)]
105 | [String] $PartitionId,
106 |
107 | [Parameter(Mandatory=$false)]
108 | [String] $ServiceId,
109 |
110 | [Parameter(Mandatory=$false)]
111 | [String] $ApplicationId,
112 |
113 | [Parameter(Mandatory=$false)]
114 | [String] $ClientCertificateThumbprint
115 | )
116 |
117 | $command = ""
118 | if($StorageType -eq "FileShare")
119 | {
120 | if(!$FileSharePath)
121 | {
122 | $FileSharePath = Read-Host -Prompt "Please enter the FileSharePath"
123 | }
124 |
125 | if($FileShareUserName)
126 | {
127 | $command = $command + "Start-RetentionScriptFileShare -UserName `"$FileShareUserName`" -FileSharePath `"$FileSharePath`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
128 | if(!$Password)
129 | {
130 | $Password = Read-Host -Prompt "Please enter password for the userName: $FileShareUserName" -AsSecureString
131 | }
132 | $Global:Pass = $Password
133 |
134 | }
135 | else {
136 | $command = $command + "Start-RetentionScriptFileShare -FileSharePath `"$FileSharePath`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
137 | }
138 | }
139 | elseif($StorageType -eq "AzureBlob")
140 | {
141 | if($ConnectionString)
142 | {
143 | if($ContainerName)
144 | {
145 | $command = $command + "Start-RetentionScriptAzureShare -ConnectionString `"$ConnectionString`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
146 | }
147 | else {
148 | $command = $command + "Start-RetentionScriptAzureShare -ConnectionString `"$ConnectionString`" -DateTimeBefore `"$DateTimeBefore`" -ClusterEndPoint `"$ClusterEndPoint`""
149 | }
150 | }
151 | else {
152 | if(!$StorageAccountName)
153 | {
154 | $StorageAccountName = Read-Host -Prompt "Please enter the Storage account name"
155 | }
156 | if(!$StorageAccountKey)
157 | {
158 | $StorageAccountKey = Read-Host -Prompt "Please enter the Storage account key"
159 | }
160 | $command = $command + "Start-RetentionScriptAzureShare -StorageAccountName `"$StorageAccountName`" -StorageAccountKey `"$StorageAccountKey`" -DateTimeBefore `"$DateTimeBefore`" -ContainerName `"$ContainerName`" -ClusterEndPoint `"$ClusterEndPoint`""
161 | }
162 |
163 | if($ContainerName)
164 | {
165 | $command = $command + " -ContainerName `"$ContainerName`""
166 | }
167 | }
168 | else {
169 | throw "The storage of type $StorageType not supported"
170 | }
171 |
172 | if($ApplicationId)
173 | {
174 | $command = $command + " -ApplicationId `"$ApplicationId`""
175 | }
176 | if($ServiceId)
177 | {
178 | $command = $command + " -ServiceId `"$ServiceId`""
179 | }
180 |
181 | if($ClientCertificateThumbprint)
182 | {
183 | $command = $command + " -ClientCertificateThumbprint `"$ClientCertificateThumbprint`""
184 | }
185 |
186 | if($PartitionId)
187 | {
188 | $command = $command + " -PartitionId `"$PartitionId`""
189 | }
190 |
191 | if($DeleteNotFoundPartitions)
192 | {
193 | $command = $command + " -DeleteNotFoundPartitions"
194 | }
195 |
196 | $scriptBlock = [ScriptBlock]::Create($command)
197 | Invoke-Command $scriptBlock
198 | }
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/RetentionScriptAzureBlobStore.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding(PositionalBinding = $false)]
2 | param (
3 | [Parameter(Mandatory=$false)]
4 | [String] $ConnectionString,
5 |
6 | [Parameter(Mandatory=$false)]
7 | [String] $ContainerName,
8 |
9 | [Parameter(Mandatory=$false)]
10 | [string] $StorageAccountName,
11 |
12 | [Parameter(Mandatory=$false)]
13 | [String] $StorageAccountKey,
14 |
15 | [Parameter(Mandatory=$true)]
16 | [String] $DateTimeBefore,
17 |
18 | [Parameter(Mandatory=$true)]
19 | [String] $ClusterEndpoint,
20 |
21 | [Parameter(Mandatory=$false)]
22 | [switch] $DeleteNotFoundPartitions,
23 |
24 | [Parameter(Mandatory=$false)]
25 | [String] $PartitionId,
26 |
27 | [Parameter(Mandatory=$false)]
28 | [String] $ServiceId,
29 |
30 | [Parameter(Mandatory=$false)]
31 | [String] $ApplicationId,
32 |
33 | [Parameter(Mandatory=$false)]
34 | [String] $ClientCertificateThumbprint
35 | )
36 | . .\UtilScript.ps1
37 |
38 | $partitionIdListToWatch = New-Object System.Collections.ArrayList
39 |
40 | if($ApplicationId)
41 | {
42 | if($ClientCertificateThumbprint)
43 | {
44 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
45 | }
46 | else {
47 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
48 | }
49 | }
50 | elseif($ServiceId)
51 | {
52 | if($ClientCertificateThumbprint)
53 | {
54 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
55 | }
56 | else {
57 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint
58 | }
59 | }
60 | elseif($PartitionId)
61 | {
62 | $partitionIdListToWatch.Add($PartitionId)
63 | }
64 |
65 | $contextForStorageAccount = $null
66 |
67 | if($ConnectionString)
68 | {
69 | $contextForStorageAccount = New-AzureStorageContext -ConnectionString $ConnectionString
70 | }
71 | else
72 | {
73 | $contextForStorageAccount = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
74 | }
75 |
76 | $containerNameList = New-Object System.Collections.ArrayList
77 |
78 | if(!$ContainerName)
79 | {
80 | $containers = Get-AzureStorageContainer -Context $contextForStorageAccount
81 | foreach($container in $containers)
82 | {
83 | $containerNameList.Add($container.Name) | Out-Null
84 | }
85 | }
86 | Else {
87 | $containerNameList.Add($ContainerName) | Out-Null
88 | }
89 |
90 | foreach($containerName in $containerNameList)
91 | {
92 | $token = $null
93 | $pathsList = New-Object System.Collections.ArrayList
94 | do
95 | {
96 | $blobs = Get-AzureStorageBlob -Container $ContainerName -ContinuationToken $token -Context $contextForStorageAccount
97 |
98 | foreach($blob in $blobs)
99 | {
100 | $pathsList.Add($blob.Name) | Out-Null
101 | }
102 | if($blobs.Count -le 0) { Break;}
103 | $token = $blobs[$blobs.Count -1].ContinuationToken;
104 | }
105 | While ($token -ne $Null)
106 | $partitionDict = New-Object 'system.collections.generic.dictionary[[string],[system.collections.generic.list[string]]]'
107 | $finalDateTimeObject = $dateTimeBeforeObject
108 | $partitionDict = Get-PartitionDict -pathsList $pathsList
109 | $partitionCountDict = New-Object 'system.collections.generic.dictionary[[String],[Int32]]'
110 |
111 | foreach($partitionid in $partitionDict.Keys)
112 | {
113 | $partitionCountDict[$partitionid] = $partitionDict[$partitionid].Count
114 | if($partitionIdListToWatch.Count -ne 0 -and !$partitionIdListToWatch.Contains($partitionid))
115 | {
116 | continue
117 | }
118 | if($ClientCertificateThumbprint)
119 | {
120 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions -ClientCertificateThumbprint $ClientCertificateThumbprint
121 | }
122 | else {
123 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions
124 | }
125 | if($finalDateTimeObject -eq [DateTime]::MinValue)
126 | {
127 | continue
128 | }
129 | $deleteCount = 0
130 | foreach($blobPath in $partitionDict[$partitionid])
131 | {
132 | $fileNameWithExtension = Split-Path $blobPath -Leaf
133 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fileNameWithExtension)
134 | $extension = [IO.Path]::GetExtension($fileNameWithExtension)
135 | if($extension -eq ".zip" -or $extension -eq ".bkmetadata" )
136 | {
137 | $dateTimeObject = [DateTime]::ParseExact($fileNameWithoutExtension + "Z","yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
138 | if($dateTimeObject.ToUniversalTime() -lt $finalDateTimeObject.ToUniversalTime())
139 | {
140 | Write-Host "Deleting the file: $blobPath"
141 | Remove-AzureStorageBlob -Blob $blobPath -Container $containerName -Context $contextForStorageAccount
142 | $partitionCountDict[$partitionid] = $partitionCountDict[$partitionid] -1
143 | $deleteCount = $deleteCount + 1
144 | if($partitionCountDict[$partitionid] -eq 0)
145 | {
146 | Write-Warning -Message "The backup count in this $partitionid is zero. It could happen if the partition is not found on the $ClusterEndpoint"
147 | }
148 | }
149 | }
150 | }
151 | $numberOfBackupsLeft = $partitionCountDict[$partitionid]
152 | Write-Host "Cleanup for the partitionID: $partitionid is complete "
153 | Write-Host "The number of backup left in the partition after cleanup: $numberOfBackupsLeft"
154 | Write-Host "The number of backup files deleted : $deleteCount (.bkmetadata + .zip files)"
155 | }
156 | }
157 |
158 |
159 | $newPathsList = New-Object System.Collections.ArrayList
160 | $newToken = $null
161 | do
162 | {
163 | $blobs = Get-AzureStorageBlob -Container $ContainerName -ContinuationToken $newToken -Context $contextForStorageAccount
164 |
165 | foreach($blob in $blobs)
166 | {
167 | $newPathsList.Add($blob.Name) | Out-Null
168 | }
169 | if($blobs.Count -le 0) { Break;}
170 | $newToken = $blobs[$blobs.Count -1].ContinuationToken;
171 | }
172 | While ($newToken -ne $Null)
173 |
174 | $newPartitionDict = Get-PartitionDict -pathsList $newPathsList
175 |
176 | foreach($partitionid in $newPartitionDict.Keys)
177 | {
178 | if($partitionCountDict.ContainsKey)
179 | {
180 | if($partitionCountDict[$partitionid] -gt $newPartitionDict[$partitionid].Count)
181 | {
182 | throw "The partition with partitionId : $partitionid has less number of backups than expected."
183 | }
184 | }
185 | Start-BackupDataCorruptionTest -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
186 | }
187 |
188 |
189 |
190 |
191 |
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/modules/RetentionScriptAzureBlobStore.psm1:
--------------------------------------------------------------------------------
1 | Function Start-RetentionScriptAzureShare
2 | {
3 | [CmdletBinding(PositionalBinding = $false)]
4 | param (
5 | [Parameter(Mandatory=$false)]
6 | [String] $ConnectionString,
7 |
8 | [Parameter(Mandatory=$false)]
9 | [String] $ContainerName,
10 |
11 | [Parameter(Mandatory=$false)]
12 | [string] $StorageAccountName,
13 |
14 | [Parameter(Mandatory=$false)]
15 | [String] $StorageAccountKey,
16 |
17 | [Parameter(Mandatory=$true)]
18 | [String] $DateTimeBefore,
19 |
20 | [Parameter(Mandatory=$true)]
21 | [String] $ClusterEndpoint,
22 |
23 | [Parameter(Mandatory=$false)]
24 | [switch] $DeleteNotFoundPartitions,
25 |
26 | [Parameter(Mandatory=$false)]
27 | [String] $PartitionId,
28 |
29 | [Parameter(Mandatory=$false)]
30 | [String] $ServiceId,
31 |
32 | [Parameter(Mandatory=$false)]
33 | [String] $ApplicationId,
34 |
35 | [Parameter(Mandatory=$false)]
36 | [String] $ClientCertificateThumbprint
37 | )
38 |
39 | $partitionIdListToWatch = New-Object System.Collections.ArrayList
40 |
41 | if($ApplicationId)
42 | {
43 | if($ClientCertificateThumbprint)
44 | {
45 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
46 | }
47 | else {
48 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
49 | }
50 | }
51 | elseif($ServiceId)
52 | {
53 | if($ClientCertificateThumbprint)
54 | {
55 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
56 | }
57 | else {
58 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint
59 | }
60 | }
61 | elseif($PartitionId)
62 | {
63 | $partitionIdListToWatch.Add($PartitionId)
64 | }
65 |
66 | $contextForStorageAccount = $null
67 |
68 | if($ConnectionString)
69 | {
70 | $contextForStorageAccount = New-AzureStorageContext -ConnectionString $ConnectionString
71 | }
72 | else
73 | {
74 | $contextForStorageAccount = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
75 | }
76 |
77 | $containerNameList = New-Object System.Collections.ArrayList
78 |
79 | if(!$ContainerName)
80 | {
81 | $containers = Get-AzureStorageContainer -Context $contextForStorageAccount
82 | foreach($container in $containers)
83 | {
84 | $containerNameList.Add($container.Name) | Out-Null
85 | }
86 | }
87 | Else {
88 | $containerNameList.Add($ContainerName) | Out-Null
89 | }
90 |
91 | foreach($containerName in $containerNameList)
92 | {
93 | $token = $null
94 | $pathsList = New-Object System.Collections.ArrayList
95 | do
96 | {
97 | $blobs = Get-AzureStorageBlob -Container $ContainerName -ContinuationToken $token -Context $contextForStorageAccount
98 |
99 | foreach($blob in $blobs)
100 | {
101 | $pathsList.Add($blob.Name) | Out-Null
102 | }
103 | if($blobs.Count -le 0) { Break;}
104 | $token = $blobs[$blobs.Count -1].ContinuationToken;
105 | }
106 | While ($token -ne $Null)
107 | $partitionDict = New-Object 'system.collections.generic.dictionary[[string],[system.collections.generic.list[string]]]'
108 | $finalDateTimeObject = $dateTimeBeforeObject
109 | $partitionDict = Get-PartitionDict -pathsList $pathsList
110 | $partitionCountDict = New-Object 'system.collections.generic.dictionary[[String],[Int32]]'
111 |
112 | foreach($partitionid in $partitionDict.Keys)
113 | {
114 | $partitionCountDict[$partitionid] = $partitionDict[$partitionid].Count
115 | if($partitionIdListToWatch.Count -ne 0 -and !$partitionIdListToWatch.Contains($partitionid))
116 | {
117 | continue
118 | }
119 | if($ClientCertificateThumbprint)
120 | {
121 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions -ClientCertificateThumbprint $ClientCertificateThumbprint
122 | }
123 | else {
124 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions
125 | }
126 | if($finalDateTimeObject -eq [DateTime]::MinValue)
127 | {
128 | continue
129 | }
130 | $deleteCount = 0
131 | foreach($blobPath in $partitionDict[$partitionid])
132 | {
133 | $fileNameWithExtension = Split-Path $blobPath -Leaf
134 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fileNameWithExtension)
135 | $extension = [IO.Path]::GetExtension($fileNameWithExtension)
136 | if($extension -eq ".zip" -or $extension -eq ".bkmetadata" )
137 | {
138 | $dateTimeObject = [DateTime]::ParseExact($fileNameWithoutExtension + "Z","yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
139 | if($dateTimeObject.ToUniversalTime() -lt $finalDateTimeObject.ToUniversalTime())
140 | {
141 | Write-Host "Deleting the file: $blobPath"
142 | Remove-AzureStorageBlob -Blob $blobPath -Container $containerName -Context $contextForStorageAccount
143 | $partitionCountDict[$partitionid] = $partitionCountDict[$partitionid] -1
144 | $deleteCount = $deleteCount + 1
145 | if($partitionCountDict[$partitionid] -eq 0)
146 | {
147 | Write-Warning -Message "The backup count in this $partitionid is zero. It could happen if the partition is not found on the $ClusterEndpoint"
148 | }
149 | }
150 | }
151 | }
152 | $numberOfBackupsLeft = $partitionCountDict[$partitionid]
153 | Write-Host "Cleanup for the partitionID: $partitionid is complete "
154 | Write-Host "The number of backup left in the partition after cleanup: $numberOfBackupsLeft"
155 | Write-Host "The number of backup files deleted : $deleteCount (.bkmetadata + .zip files)"
156 | }
157 | }
158 |
159 |
160 | $newPathsList = New-Object System.Collections.ArrayList
161 | $newToken = $null
162 | do
163 | {
164 | $blobs = Get-AzureStorageBlob -Container $ContainerName -ContinuationToken $newToken -Context $contextForStorageAccount
165 |
166 | foreach($blob in $blobs)
167 | {
168 | $newPathsList.Add($blob.Name) | Out-Null
169 | }
170 | if($blobs.Count -le 0) { Break;}
171 | $newToken = $blobs[$blobs.Count -1].ContinuationToken;
172 | }
173 | While ($newToken -ne $Null)
174 |
175 | $newPartitionDict = Get-PartitionDict -pathsList $newPathsList
176 |
177 | foreach($partitionid in $newPartitionDict.Keys)
178 | {
179 | if($partitionCountDict.ContainsKey)
180 | {
181 | if($partitionCountDict[$partitionid] -gt $newPartitionDict[$partitionid].Count)
182 | {
183 | throw "The partition with partitionId : $partitionid has less number of backups than expected."
184 | }
185 | }
186 | Start-BackupDataCorruptionTest -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
187 | }
188 |
189 |
190 |
191 |
192 | }
--------------------------------------------------------------------------------
/scripts/SetupServiceFabric/SetupServiceFabric.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # This script installs and sets up the Service Fabric Runtime and Common SDK.
5 | # It also sets up Azure Service Fabric CLI
6 |
7 | # Usage: sudo ./SetupServiceFabric.sh
8 | # Above fetches Service Fabric Runtime and SDK along with required packages/dependencies from repositories and does the setup.
9 | # This script also supports installation of SDK from local .deb packages of Servie Fabric runtime and sdk. Both packages will be needed for installation and paths should be provided as parameter, make sure files are present at given paths.
10 | # Below is the sample:
11 | # sudo ./SetupServiceFabric.sh --servicefabricruntime=/mnt/c/Users/sindoria/Downloads/servicefabric_8.2.142.2.deb --servicefabricsdk=/mnt/c/Users/sindoria/Downloads/servicefabric_sdkcommon_1.4.2.deb
12 | #
13 |
14 | if [ "$EUID" -ne 0 ]; then
15 | echo Please run this script as root or using sudo
16 | exit
17 | fi
18 |
19 | ExitIfError()
20 | {
21 | if [ $1 != 0 ]; then
22 | echo "$2" 1>&2
23 | exit -1
24 | fi
25 | }
26 |
27 | Distribution=`lsb_release -cs`
28 | if [[ "xenial" != "$Distribution" && "bionic" != "$Distribution" ]]; then
29 | echo "Service Fabric is not supported on $Distribution"
30 | exit -1
31 | fi
32 |
33 | # Check ServiceFabricRuntimePath and ServiceFabricSdkPath have been provided. If yes, extract that
34 | ServiceFabricRuntimePath=""
35 | ServiceFabricSdkPath=""
36 | for i in "$@"
37 | do
38 | case $i in
39 | -sfrt=*|--servicefabricruntime=*)
40 | ServiceFabricRuntimePath="${i#*=}"
41 | ;;
42 | -sfs=*|--servicefabricsdk=*)
43 | ServiceFabricSdkPath="${i#*=}"
44 | ;;
45 | *)
46 | echo Error: Unknown option passed in: $i
47 | exit 1
48 | ;;
49 | esac
50 | done
51 |
52 | # Check if systemd is running as PID1, if not it should be enabled via systemd-genie
53 | pidone=$(ps --no-headers -o comm 1)
54 | if [[ "systemd" != "$pidone" ]]; then
55 | # Set systemd-genie to run systemd as PID 1
56 | echo "Setting up systemd-genie to run systemd as PID 1"
57 | echo "Installing .NET SDK and runtime 5.0"
58 | wget https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
59 | dpkg -i packages-microsoft-prod.deb
60 | rm packages-microsoft-prod.deb
61 |
62 | echo "Installing the .NET SDK"
63 | apt-get update; \
64 | apt-get install -y apt-transport-https && \
65 | apt-get update && \
66 | apt-get install -y dotnet-sdk-5.0
67 |
68 | echo "Installing the .NET runtime "
69 | apt-get update; \
70 | apt-get install -y apt-transport-https && \
71 | apt-get update && \
72 | apt-get install -y aspnetcore-runtime-5.0
73 |
74 | echo "Adding the wsl-translinux repository"
75 | apt install apt-transport-https
76 |
77 | wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg
78 | chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg
79 |
80 | file="/etc/apt/sources.list.d/wsl-transdebian.list"
81 | echo "deb https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main" >> $file
82 | echo "deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main" >> $file
83 | cat $file
84 |
85 | apt update
86 | echo "Installing systemd-genie"
87 | apt install -y systemd-genie
88 |
89 | # Start genie
90 | echo "Starting genie"
91 | genie -i
92 | echo "Genie has been started"
93 | fi
94 |
95 | #
96 | # If setup is being done inside WLS2 Distribution, then below helps in doing installation inside genie namespace if needed
97 | #
98 | genieCommand=''
99 | isGenieInstalled=$(apt list --installed | grep systemd-genie)
100 |
101 | if [[ ! -z "$isGenieInstalled" ]]; then
102 | isGenieRunning=$(genie -r)
103 | isOutsideGenie=$(genie -b)
104 |
105 | if [[ "$isGenieRunning"=="runnning" ]]; then
106 | # If outside genie then genie prefix command should be used.
107 | if [[ "$isOutsideGenie"=="outside" ]]; then
108 | genieCommand="genie -c"
109 | fi
110 | # if genie is used for cluster management, current user should get permission to control service without sudo password.
111 | # This enables cluster management from windows host via Powershell or LocalClusterManager.
112 | # find user running the script
113 | usr=$SUDO_USER
114 | # if this script is being run by root dont do anything
115 | if [ -z "$usr" ] || [ "root" = "$usr" ]; then
116 | echo "This script should be run by default user with sudo, otherwise add in /etc/sudoers manually. This enables linux cluster management from windwos host via powershell or LocalClusterManager."
117 | else
118 | # Copy /etc/sudoers to /tmp/sudoers.new
119 | cp /etc/sudoers /tmp/sudoers.new
120 | # Remove entery if exists and then make an entry for current user
121 | userentry="$usr ALL = (ALL) NOPASSWD:ALL"
122 | sed -i "/${userentry}/d" /tmp/sudoers.new
123 | sed -i "$ a ${userentry}" /tmp/sudoers.new
124 | # check validity of entry using visudo, if validation is successful, replace /etc/sudoers
125 | visudo -c -f /tmp/sudoers.new
126 | if [ "$?" -eq "0" ]; then
127 | cp /tmp/sudoers.new /etc/sudoers
128 | fi
129 | rm /tmp/sudoers.new
130 | fi
131 | fi
132 | fi
133 |
134 | #
135 | # Install all packages
136 | #
137 | MSPackage="https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
138 | wget -q $MSPackage
139 | dpkg -i packages-microsoft-prod.deb
140 | ExitIfError $? "Error@$LINENO: Failed to add package $MSPackage"
141 |
142 | curl -fsSL https://packages.microsoft.com/keys/msopentech.asc | apt-key add -
143 | ExitIfError $? "Error@$LINENO: Failed to add MS GPG key"
144 |
145 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
146 | ExitIfError $? "Error@$LINENO: Failed to add Docker GPG key"
147 |
148 | add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
149 | ExitIfError $? "Error@$LINENO: Failed to setup docker repository"
150 |
151 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
152 | apt-add-repository "deb http://repos.azul.com/azure-only/zulu/apt stable main"
153 | ExitIfError $? "Error@$LINENO: Failed to add key for zulu repo"
154 |
155 | apt-get update
156 |
157 | #
158 | # Install Service Fabric SDK.
159 | #
160 | echo "servicefabric servicefabric/accepted-eula-ga select true" | debconf-set-selections
161 | echo "servicefabricsdkcommon servicefabricsdkcommon/accepted-eula-ga select true" | debconf-set-selections
162 |
163 | #
164 | # If local debian packages for ServiceFabricRunTime and ServiceFabricSDK are provided, install SF SDK from these packages
165 | #
166 | if [[ ! -z $ServiceFabricRuntimePath ]] && [[ ! -z $ServiceFabricSdkPath ]]; then
167 | echo "Copying $ServiceFabricRuntimePath to /var/cache/apt/archives/servicefabric.deb"
168 | cp $ServiceFabricRuntimePath /var/cache/apt/archives/servicefabric.deb
169 | echo "Copying $ServiceFabricSdkPath to /var/cache/apt/archives/servicefabricsdkcommon.deb"
170 | cp $ServiceFabricSdkPath /var/cache/apt/archives/servicefabricsdkcommon.deb
171 |
172 | echo "Installing servicefabric and servicefabricsdkcommon from local .deb packages"
173 | $genieCommand dpkg -i /var/cache/apt/archives/servicefabric.deb
174 | # Fix broken dependencies for servicefabric if any.
175 | $genieCommand apt-get install -f -y
176 | $genieCommand dpkg -i /var/cache/apt/archives/servicefabricsdkcommon.deb
177 | # Fix broken dependencies for servicefabricsdkcommon if any.
178 | $genieCommand apt-get install -f -y
179 |
180 | echo "Removing /var/cache/apt/archives/servicefabric.deb and /var/cache/apt/archives/servicefabricsdkcommon.deb"
181 | rm /var/cache/apt/archives/servicefabric.deb
182 | rm /var/cache/apt/archives/servicefabricsdkcommon.deb
183 | else
184 | $genieCommand apt-get install servicefabricsdkcommon -f -y
185 | ExitIfError $? "Error@$LINENO: Failed to install Service Fabric SDK"
186 | fi
187 |
188 | #
189 | # Setup Azure Service Fabric CLI
190 | #
191 |
192 | $genieCommand apt-get install python3 -f -y
193 | ExitIfError $? "Error@$LINENO: Failed to install python3 for sfctl setup."
194 |
195 | $genieCommand apt-get install python3-pip -f -y
196 | ExitIfError $? "Error@$LINENO: Failed to install pip for sfctl setup."
197 |
198 | $genieCommand pip3 install sfctl
199 | ExitIfError $? "Error@$LINENO: sfctl installation failed."
200 |
201 | export PATH=$PATH:$HOME/.local/bin/
202 |
203 | echo "Successfully completed Service Fabric SDK installation and setup."
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/RetentionScriptFileShare.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding(PositionalBinding = $false)]
2 | param (
3 | [Parameter(Mandatory=$false)]
4 | [String] $UserName,
5 |
6 | [Parameter(Mandatory=$true)]
7 | [String] $FileSharePath,
8 |
9 | [Parameter(Mandatory=$true)]
10 | [String] $DateTimeBefore,
11 |
12 | [Parameter(Mandatory=$true)]
13 | [String] $ClusterEndpoint,
14 |
15 | [Parameter(Mandatory=$false)]
16 | [switch] $DeleteNotFoundPartitions,
17 |
18 | [Parameter(Mandatory=$false)]
19 | [String] $PartitionId,
20 |
21 | [Parameter(Mandatory=$false)]
22 | [String] $ServiceId,
23 |
24 | [Parameter(Mandatory=$false)]
25 | [String] $ApplicationId,
26 |
27 | [Parameter(Mandatory=$false)]
28 | [String] $ClientCertificateThumbprint
29 | )
30 |
31 |
32 | Add-Type -Namespace Import -Name Win32 -MemberDefinition @'
33 | [DllImport("advapi32.dll", SetLastError = true)]
34 | public static extern bool LogonUser(string user, string domain, string password, int logonType, int logonProvider, out IntPtr token);
35 |
36 | [DllImport("kernel32.dll", SetLastError = true)]
37 | public static extern bool CloseHandle(IntPtr handle);
38 | '@
39 | . .\UtilScript.ps1
40 |
41 | Function Get-LogonUserToken
42 | {
43 | param([Parameter(Mandatory=$true)][string]$UsernameToLogon,
44 | [Parameter(Mandatory=$true)][string]$Domain,
45 | [Parameter(Mandatory=$true)][SecureString]$PassToUse,
46 | [Parameter(Mandatory=$false)][string]$LogonType = 'NEW_CREDENTIALS',
47 | [Parameter(Mandatory=$false)][string]$LogonProvider = 'WINNT50'
48 | )
49 |
50 | $tokenHandle = [IntPtr]::Zero
51 |
52 |
53 | $LogonTypeID = Switch ($LogonType) {
54 | 'BATCH' { 4 }
55 | 'INTERACTIVE' { 2 }
56 | 'NETWORK' { 3 }
57 | 'NETWORK_CLEARTEXT' { 8 }
58 | 'NEW_CREDENTIALS' { 9 }
59 | 'SERVICE' { 5 }
60 | }
61 |
62 | $LogonProviderID = Switch ($LogonProvider) {
63 | 'DEFAULT' { 0 }
64 | 'WINNT40' { 2 }
65 | 'WINNT50' { 3 }
66 | }
67 | $unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PassToUse)
68 | $passunenc = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($unmanagedString)
69 | $returnValue = [Import.Win32]::LogonUser($UsernameToLogon, $Domain, $passunenc, $LogonTypeID, $LogonProviderID, [ref]$tokenHandle)
70 |
71 | #If it fails, throw the verbose with the error code
72 | if (!$returnValue) {
73 | $errCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error();
74 | Write-Host "Impersonate-User failed a call to LogonUser with error code: $errCode"
75 | throw [System.ComponentModel.Win32Exception]$errCode
76 |
77 | }
78 |
79 | return $tokenHandle
80 | }
81 |
82 | $filePathList = New-Object System.Collections.ArrayList
83 | $Global:ImpersonatedUser = @{}
84 |
85 | $partitionIdListToWatch = New-Object System.Collections.ArrayList
86 |
87 | if($ApplicationId)
88 | {
89 | if($ClientCertificateThumbprint)
90 | {
91 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
92 | }
93 | else {
94 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
95 | }
96 | }
97 | elseif($ServiceId)
98 | {
99 | if($ClientCertificateThumbprint)
100 | {
101 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
102 | }
103 | else {
104 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint
105 | }
106 | }
107 | elseif($PartitionId)
108 | {
109 | $partitionIdListToWatch.Add($PartitionId)
110 | }
111 |
112 |
113 | if($UserName)
114 | {
115 | $userNameDomainList = $username.Split("\",[StringSplitOptions]'RemoveEmptyEntries')
116 |
117 | if($userNameDomainList.Count -eq 2)
118 | {
119 | $userNameToTry = $userNameDomainList[1]
120 | $domain = $userNameDomainList[0]
121 | }
122 | else {
123 | $userNameToTry = $UserName
124 | $domain = "."
125 | }
126 |
127 | $userToken = Get-LogonUserToken -Username $userNameToTry -Domain $domain -PassToUse $Global:Pass
128 | $Global:ImpersonatedUser.ImpersonationContext = [System.Security.Principal.WindowsIdentity]::Impersonate($userToken)
129 |
130 | # Close the handle to the token. Voided to mask the Boolean return value.
131 | [void][Import.Win32]::CloseHandle($userToken)
132 |
133 | }
134 |
135 |
136 | Get-ChildItem -Path $FileSharePath -Include *.bkmetadata -Recurse | ForEach-Object {$filePathList.Add($_.FullName) | Out-Null}
137 | Get-ChildItem -Path $FileSharePath -Include *.zip -Recurse | ForEach-Object {$filePathList.Add($_.FullName) | Out-Null}
138 |
139 | $partitionDict = Get-PartitionDict -pathsList $filePathList
140 | $partitionCountDict = New-Object 'system.collections.generic.dictionary[[String],[Int32]]'
141 |
142 | foreach($partitionid in $partitionDict.Keys)
143 | {
144 | $partitionCountDict[$partitionid] = $partitionDict[$partitionid].Count
145 | if($partitionIdListToWatch.Count -ne 0 -and !$partitionIdListToWatch.Contains($partitionid) )
146 | {
147 | continue
148 | }
149 | if($ClientCertificateThumbprint)
150 | {
151 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions -ClientCertificateThumbprint $ClientCertificateThumbprint
152 | }
153 | else {
154 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions
155 | }
156 | if($finalDateTimeObject -eq [DateTime]::MinValue)
157 | {
158 | continue
159 | }
160 | $deleteCount = 0
161 | foreach($filePath in $partitionDict[$partitionid])
162 | {
163 | $fileNameWithExtension = Split-Path $filePath -Leaf
164 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fileNameWithExtension)
165 | $extension = [IO.Path]::GetExtension($fileNameWithExtension)
166 | if($extension -eq ".zip" -or $extension -eq ".bkmetadata" )
167 | {
168 | $dateTimeObject = [DateTime]::ParseExact($fileNameWithoutExtension + "Z","yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
169 | if($dateTimeObject.ToUniversalTime() -lt $finalDateTimeObject.ToUniversalTime())
170 | {
171 | Remove-Item -Path $filePath
172 | $deleteCount = $deleteCount + 1
173 | $partitionCountDict[$partitionid] = $partitionCountDict[$partitionid] -1
174 | if($partitionCountDict[$partitionid] -lt 0)
175 | {
176 | Write-Warning -Message "The backup count in this $partitionid is zero. It could happen if the partition is not found on the $ClusterEndpoint"
177 | }
178 | }
179 | }
180 | }
181 | $numberOfBackupsLeft = $partitionCountDict[$partitionid]
182 | Write-Host "Cleanup for the partitionID: $partitionid is complete "
183 | Write-Host "The number of backup left in the partition after cleanup: $numberOfBackupsLeft"
184 | Write-Host "The number of backup files deleted : $deleteCount (.bkmetadata + .zip files)"
185 | }
186 |
187 |
188 | $testFilePathList = New-Object System.Collections.ArrayList
189 |
190 | Get-ChildItem -Path $FileSharePath -Include *.bkmetadata -Recurse | ForEach-Object {$testFilePathList.Add($_.FullName) | Out-Null}
191 | Get-ChildItem -Path $FileSharePath -Include *.zip -Recurse | ForEach-Object {$testFilePathList.Add($_.FullName) | Out-Null}
192 | $newPartitionDict = Get-PartitionDict -pathsList $filePathList
193 |
194 | foreach($partitionid in $newPartitionDict.Keys)
195 | {
196 | if($partitionCountDict.ContainsKey)
197 | {
198 | if($partitionCountDict[$partitionid] -gt $newPartitionDict[$partitionid].Count)
199 | {
200 | throw "The partition with partitionId : $partitionid has less number of backups than expected."
201 | }
202 | }
203 | Start-BackupDataCorruptionTest -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
204 | }
205 |
206 |
207 |
208 | if($UserName)
209 | {
210 | $ImpersonatedUser.ImpersonationContext.Undo()
211 | Remove-Variable ImpersonatedUser -Scope Global
212 | }
213 |
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/modules/RetentionScriptFileShare.psm1:
--------------------------------------------------------------------------------
1 | Function Start-RetentionScriptFileShare
2 | {
3 | [CmdletBinding(PositionalBinding = $false)]
4 | param (
5 | [Parameter(Mandatory=$false)]
6 | [String] $UserName,
7 |
8 | [Parameter(Mandatory=$true)]
9 | [String] $FileSharePath,
10 |
11 | [Parameter(Mandatory=$true)]
12 | [String] $DateTimeBefore,
13 |
14 | [Parameter(Mandatory=$true)]
15 | [String] $ClusterEndpoint,
16 |
17 | [Parameter(Mandatory=$false)]
18 | [switch] $DeleteNotFoundPartitions,
19 |
20 | [Parameter(Mandatory=$false)]
21 | [String] $PartitionId,
22 |
23 | [Parameter(Mandatory=$false)]
24 | [String] $ServiceId,
25 |
26 | [Parameter(Mandatory=$false)]
27 | [String] $ApplicationId,
28 |
29 | [Parameter(Mandatory=$false)]
30 | [String] $ClientCertificateThumbprint
31 | )
32 |
33 |
34 | Add-Type -Namespace Import -Name Win32 -MemberDefinition @'
35 | [DllImport("advapi32.dll", SetLastError = true)]
36 | public static extern bool LogonUser(string user, string domain, string password, int logonType, int logonProvider, out IntPtr token);
37 |
38 | [DllImport("kernel32.dll", SetLastError = true)]
39 | public static extern bool CloseHandle(IntPtr handle);
40 | '@
41 |
42 | Function Get-LogonUserToken
43 | {
44 | param([Parameter(Mandatory=$true)][string]$UsernameToLogon,
45 | [Parameter(Mandatory=$true)][string]$Domain,
46 | [Parameter(Mandatory=$true)][SecureString]$PassToUse,
47 | [Parameter(Mandatory=$false)][string]$LogonType = 'NEW_CREDENTIALS',
48 | [Parameter(Mandatory=$false)][string]$LogonProvider = 'WINNT50'
49 | )
50 |
51 | $tokenHandle = [IntPtr]::Zero
52 |
53 |
54 | $LogonTypeID = Switch ($LogonType) {
55 | 'BATCH' { 4 }
56 | 'INTERACTIVE' { 2 }
57 | 'NETWORK' { 3 }
58 | 'NETWORK_CLEARTEXT' { 8 }
59 | 'NEW_CREDENTIALS' { 9 }
60 | 'SERVICE' { 5 }
61 | }
62 |
63 | $LogonProviderID = Switch ($LogonProvider) {
64 | 'DEFAULT' { 0 }
65 | 'WINNT40' { 2 }
66 | 'WINNT50' { 3 }
67 | }
68 | $unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PassToUse)
69 | $passunenc = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($unmanagedString)
70 | $returnValue = [Import.Win32]::LogonUser($UsernameToLogon, $Domain, $passunenc, $LogonTypeID, $LogonProviderID, [ref]$tokenHandle)
71 |
72 | #If it fails, throw the verbose with the error code
73 | if (!$returnValue) {
74 | $errCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error();
75 | Write-Host "Impersonate-User failed a call to LogonUser with error code: $errCode"
76 | throw [System.ComponentModel.Win32Exception]$errCode
77 |
78 | }
79 |
80 | return $tokenHandle
81 | }
82 |
83 | $filePathList = New-Object System.Collections.ArrayList
84 | $Global:ImpersonatedUser = @{}
85 |
86 | $partitionIdListToWatch = New-Object System.Collections.ArrayList
87 |
88 | if($ApplicationId)
89 | {
90 | if($ClientCertificateThumbprint)
91 | {
92 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
93 | }
94 | else {
95 | $partitionIdListToWatch = Get-PartitionIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
96 | }
97 | }
98 | elseif($ServiceId)
99 | {
100 | if($ClientCertificateThumbprint)
101 | {
102 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
103 | }
104 | else {
105 | $partitionIdListToWatch = Get-PartitionIdList -ServiceId $ServiceId -ClusterEndpoint $ClusterEndpoint
106 | }
107 | }
108 | elseif($PartitionId)
109 | {
110 | $partitionIdListToWatch.Add($PartitionId)
111 | }
112 |
113 |
114 | if($UserName)
115 | {
116 | $userNameDomainList = $username.Split("\",[StringSplitOptions]'RemoveEmptyEntries')
117 |
118 | if($userNameDomainList.Count -eq 2)
119 | {
120 | $userNameToTry = $userNameDomainList[1]
121 | $domain = $userNameDomainList[0]
122 | }
123 | else {
124 | $userNameToTry = $UserName
125 | $domain = "."
126 | }
127 |
128 | $userToken = Get-LogonUserToken -Username $userNameToTry -Domain $domain -PassToUse $Global:Pass
129 | $Global:ImpersonatedUser.ImpersonationContext = [System.Security.Principal.WindowsIdentity]::Impersonate($userToken)
130 |
131 | # Close the handle to the token. Voided to mask the Boolean return value.
132 | [void][Import.Win32]::CloseHandle($userToken)
133 |
134 | }
135 |
136 |
137 | Get-ChildItem -Path $FileSharePath -Include *.bkmetadata -Recurse | ForEach-Object {$filePathList.Add($_.FullName) | Out-Null}
138 | Get-ChildItem -Path $FileSharePath -Include *.zip -Recurse | ForEach-Object {$filePathList.Add($_.FullName) | Out-Null}
139 |
140 | $partitionDict = Get-PartitionDict -pathsList $filePathList
141 | $partitionCountDict = New-Object 'system.collections.generic.dictionary[[String],[Int32]]'
142 |
143 | foreach($partitionid in $partitionDict.Keys)
144 | {
145 | $partitionCountDict[$partitionid] = $partitionDict[$partitionid].Count
146 | if($partitionIdListToWatch.Count -ne 0 -and !$partitionIdListToWatch.Contains($partitionid) )
147 | {
148 | continue
149 | }
150 | if($ClientCertificateThumbprint)
151 | {
152 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions -ClientCertificateThumbprint $ClientCertificateThumbprint
153 | }
154 | else {
155 | $finalDateTimeObject = Get-FinalDateTimeBefore -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -DeleteNotFoundPartitions $DeleteNotFoundPartitions
156 | }
157 | if($finalDateTimeObject -eq [DateTime]::MinValue)
158 | {
159 | continue
160 | }
161 | $deleteCount = 0
162 | foreach($filePath in $partitionDict[$partitionid])
163 | {
164 | $fileNameWithExtension = Split-Path $filePath -Leaf
165 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fileNameWithExtension)
166 | $extension = [IO.Path]::GetExtension($fileNameWithExtension)
167 | if($extension -eq ".zip" -or $extension -eq ".bkmetadata" )
168 | {
169 | $dateTimeObject = [DateTime]::ParseExact($fileNameWithoutExtension + "Z","yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
170 | if($dateTimeObject.ToUniversalTime() -lt $finalDateTimeObject.ToUniversalTime())
171 | {
172 | Remove-Item -Path $filePath
173 | $deleteCount = $deleteCount + 1
174 | $partitionCountDict[$partitionid] = $partitionCountDict[$partitionid] -1
175 | if($partitionCountDict[$partitionid] -lt 0)
176 | {
177 | Write-Warning -Message "The backup count in this $partitionid is zero. It could happen if the partition is not found on the $ClusterEndpoint"
178 | }
179 | }
180 | }
181 | }
182 | $numberOfBackupsLeft = $partitionCountDict[$partitionid]
183 | Write-Host "Cleanup for the partitionID: $partitionid is complete "
184 | Write-Host "The number of backup left in the partition after cleanup: $numberOfBackupsLeft"
185 | Write-Host "The number of backup files deleted : $deleteCount (.bkmetadata + .zip files)"
186 | }
187 |
188 |
189 | $testFilePathList = New-Object System.Collections.ArrayList
190 |
191 | Get-ChildItem -Path $FileSharePath -Include *.bkmetadata -Recurse | ForEach-Object {$testFilePathList.Add($_.FullName) | Out-Null}
192 | Get-ChildItem -Path $FileSharePath -Include *.zip -Recurse | ForEach-Object {$testFilePathList.Add($_.FullName) | Out-Null}
193 | $newPartitionDict = Get-PartitionDict -pathsList $filePathList
194 |
195 | foreach($partitionid in $newPartitionDict.Keys)
196 | {
197 | if($partitionCountDict.ContainsKey)
198 | {
199 | if($partitionCountDict[$partitionid] -gt $newPartitionDict[$partitionid].Count)
200 | {
201 | throw "The partition with partitionId : $partitionid has less number of backups than expected."
202 | }
203 | }
204 | Start-BackupDataCorruptionTest -DateTimeBefore $DateTimeBefore -Partitionid $partitionid -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
205 | }
206 |
207 |
208 |
209 | if($UserName)
210 | {
211 | $ImpersonatedUser.ImpersonationContext.Undo()
212 | Remove-Variable ImpersonatedUser -Scope Global
213 | }
214 |
215 | }
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/modules/UtilScript.psm1:
--------------------------------------------------------------------------------
1 | Function Get-PartitionDict
2 | {
3 | [CmdletBinding(PositionalBinding = $false)]
4 | param([Parameter(Mandatory=$true)][System.Collections.ArrayList]$pathsList
5 | )
6 |
7 | $partitionDict = New-Object 'system.collections.generic.dictionary[[string],[system.collections.generic.list[string]]]'
8 | foreach($path in $pathsList)
9 | {
10 | $pathList = $path.Split("\",[StringSplitOptions]'RemoveEmptyEntries')
11 | $length = $pathList.Count
12 | $partitionID = $null
13 | if($length -le 1)
14 | {
15 | $pathList = $path.Split("/",[StringSplitOptions]'RemoveEmptyEntries')
16 | $length = $pathList.Count
17 | if($length -le 1)
18 | {
19 | throw "$path is not in correct format."
20 | }
21 | Else
22 | {
23 | $partitionID = $pathList[$length - 2]
24 | }
25 | }
26 | Else {
27 | $partitionID = $pathList[$length - 2]
28 | }
29 |
30 |
31 | if($partitionID -eq $null)
32 | {
33 | throw "Not able to extract partitionID"
34 | }
35 |
36 | if(!$partitionDict.ContainsKey($partitionID))
37 | {
38 | $partitionDict.Add($partitionID, $path)
39 | }
40 | else {
41 | $partitionDict[$partitionID].add($path)
42 | }
43 | }
44 |
45 | return $partitionDict
46 | }
47 |
48 | Function Get-FinalDateTimeBefore
49 | {
50 | [CmdletBinding(PositionalBinding = $false)]
51 | param([Parameter(Mandatory=$true)][string]$DateTimeBefore,
52 | [Parameter(Mandatory=$true)][string]$Partitionid,
53 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
54 | [Parameter(Mandatory=$false)][bool]$DeleteNotFoundPartitions,
55 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
56 | )
57 |
58 | $dateTimeBeforeObject = [DateTime]::ParseExact($DateTimeBefore,"yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
59 | $finalDateTimeObject = $dateTimeBeforeObject
60 | $dateTimeBeforeString = $dateTimeBeforeObject.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
61 | $url = "http://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
62 | $backupEnumerations = $null
63 | try {
64 | if($ClientCertificateThumbprint)
65 | {
66 | $url = "https://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
67 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url -CertificateThumbprint $ClientCertificateThumbprint
68 | }
69 | else {
70 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url
71 | }
72 | $backupEnumerations = $pagedBackupEnumeration.Items | Sort-Object -Property @{Expression = {[DateTime]::ParseExact($_.CreationTimeUtc,"yyyy-MM-ddTHH:mm:ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)}; Ascending = $false}
73 | }
74 | catch {
75 | $err = $_.ToString() | ConvertFrom-Json
76 | if($err.Error.Code -eq "FABRIC_E_PARTITION_NOT_FOUND")
77 | {
78 | Write-Warning "$Partitionid is not found on the cluster : $ClusterEndpoint"
79 | if($DeleteNotFoundPartitions -eq $true)
80 | {
81 | Write-Warning "DeleteNotFoundPartitions flag is enabled so, deleting data all in this partition"
82 | return [DateTime]::MaxValue
83 | }
84 | else {
85 | Write-Warning "If you want to remove data on this partition as well, please run the script by enabling DeleteNotFoundPartitions flag."
86 | return [DateTime]::MinValue
87 | }
88 | }
89 | else {
90 | throw $_.Exception.Message
91 | }
92 | }
93 |
94 | $fullBackupFound = $false
95 | foreach($backupEnumeration in $backupEnumerations)
96 | {
97 | if($backupEnumeration.BackupType -eq "Full")
98 | {
99 | $finalDateTimeObject = [DateTime]::Parse($backupEnumeration.CreationTimeUtc)
100 | $fullBackupFound = $true
101 | break
102 | }
103 | }
104 | if($backupEnumerations.Count -eq 0)
105 | {
106 | Write-Host "There are no backups available in the partition: $Partitionid before the specified date."
107 | return [DateTime]::MinValue
108 | }
109 |
110 | if(!$fullBackupFound)
111 | {
112 | Write-Host "The Backups Before this $dateTimeBeforeString date are corrupt as no full backup is found, So, deleting them."
113 | }
114 | return $finalDateTimeObject
115 | }
116 |
117 |
118 | Function Get-PartitionIdList
119 | {
120 | [CmdletBinding(PositionalBinding = $false)]
121 | param([Parameter(Mandatory=$false)][string]$ApplicationId,
122 | [Parameter(Mandatory=$false)][string]$ServiceId,
123 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
124 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
125 | )
126 | # need to add continuationToken Logic here.
127 | $serviceIdList = New-Object System.Collections.ArrayList
128 | if($ApplicationId)
129 | {
130 | if($ClientCertificateThumbprint)
131 | {
132 | $serviceIdList = Get-ServiceIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
133 | }
134 | else {
135 | $serviceIdList = Get-ServiceIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
136 | }
137 | }
138 | else {
139 | $serviceIdList.Add($ServiceId) | Out-Null
140 | }
141 |
142 | $partitionIdList = New-Object System.Collections.ArrayList
143 |
144 | foreach($serviceId in $serviceIdList)
145 | {
146 | $continuationToken = $null
147 | do
148 | {
149 | if($ClientCertificateThumbprint)
150 | {
151 | $partitionInfoList = Invoke-RestMethod -Uri "https://$ClusterEndpoint/Services/$serviceId/$/GetPartitions?api-version=6.4&ContinuationToken=$continuationToken" -CertificateThumbprint $ClientCertificateThumbprint
152 | }
153 | else {
154 | $partitionInfoList = Invoke-RestMethod -Uri "http://$ClusterEndpoint/Services/$serviceId/$/GetPartitions?api-version=6.4&ContinuationToken=$continuationToken"
155 | }
156 | foreach($partitionInfo in $partitionInfoList.Items)
157 | {
158 | $partitionIdList.Add($partitionInfo.PartitionInformation.Id)
159 | }
160 | $continuationToken = $partitionInfoList.ContinuationToken
161 | }while($continuationToken -ne "")
162 | }
163 | $length = $partitionIdList.Count
164 | Write-Host "The total number of partitions found on the cluster $ClusterEndpoint are $length"
165 | return $partitionIdList
166 | }
167 |
168 |
169 | Function Get-ServiceIdList
170 | {
171 | [CmdletBinding(PositionalBinding = $false)]
172 | param([Parameter(Mandatory=$true)][string]$ApplicationId,
173 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
174 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
175 | )
176 |
177 | $continuationToken = $null
178 | $serviceIdList = New-Object System.Collections.ArrayList
179 | do
180 | {
181 | if($ClientCertificateThumbprint)
182 | {
183 | $serviceInfoList = Invoke-RestMethod -Uri "https://$ClusterEndpoint/Applications/$ApplicationId/$/GetServices?api-version=6.4&ContinuationToken=$continuationToken" -CertificateThumbprint $ClientCertificateThumbprint
184 | }
185 | else {
186 | $serviceInfoList = Invoke-RestMethod -Uri "http://$ClusterEndpoint/Applications/$ApplicationId/$/GetServices?api-version=6.4&ContinuationToken=$continuationToken"
187 | }
188 | foreach($serviceInfo in $serviceInfoList.Items)
189 | {
190 | $serviceIdList.Add($serviceInfo.Id) | Out-Null
191 | }
192 | $continuationToken = $serviceInfoList.ContinuationToken
193 | }while($continuationToken -ne "")
194 |
195 | $length = $serviceIdList.Count
196 | Write-Host "$ApplicationId has $length number of services"
197 | return $serviceIdList
198 | }
199 |
200 |
201 | Function Start-BackupDataCorruptionTest
202 | {
203 | [CmdletBinding(PositionalBinding = $false)]
204 | param([Parameter(Mandatory=$true)][string]$DateTimeBefore,
205 | [Parameter(Mandatory=$true)][string]$Partitionid,
206 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
207 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
208 | )
209 | $dateTimeBeforeObject = [DateTime]::ParseExact($DateTimeBefore,"yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
210 | $dateTimeBeforeString = $dateTimeBeforeObject.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
211 | $url = "http://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
212 |
213 | $backupEnumerations = $null
214 | try {
215 | if($ClientCertificateThumbprint)
216 | {
217 | $url = "https://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
218 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url -CertificateThumbprint $ClientCertificateThumbprint
219 | }
220 | else {
221 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url
222 | }
223 | $backupEnumerations = $pagedBackupEnumeration.Items | Sort-Object -Property @{Expression = {[DateTime]::ParseExact($_.CreationTimeUtc,"yyyy-MM-ddTHH:mm:ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)}; Ascending = $true}
224 |
225 | if($backupEnumerations -ne $null -and $backupEnumerations[0].BackupType -ne "Full")
226 | {
227 | throw "Data is corrupted for this partition : $Partitionid"
228 | }
229 | }
230 | catch {
231 | $err = $_.ToString() | ConvertFrom-Json
232 | if($err.Error.Code -eq "FABRIC_E_PARTITION_NOT_FOUND")
233 | {
234 | Write-Host "Partition: $Partitionid not found, so, could not go through with testing the integrity of data of this partition."
235 | }
236 | else {
237 | throw $_.Exception.Message
238 | }
239 | }
240 | }
--------------------------------------------------------------------------------
/scripts/BackupRetentionScript/UtilScript.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Utility functions for retention script.
4 | #>
5 |
6 | Function Get-PartitionDict
7 | {
8 | [CmdletBinding(PositionalBinding = $false)]
9 | param([Parameter(Mandatory=$true)][System.Collections.ArrayList]$pathsList
10 | )
11 |
12 | $partitionDict = New-Object 'system.collections.generic.dictionary[[string],[system.collections.generic.list[string]]]'
13 | foreach($path in $pathsList)
14 | {
15 | $pathList = $path.Split("\",[StringSplitOptions]'RemoveEmptyEntries')
16 | $length = $pathList.Count
17 | $partitionID = $null
18 | if($length -le 1)
19 | {
20 | $pathList = $path.Split("/",[StringSplitOptions]'RemoveEmptyEntries')
21 | $length = $pathList.Count
22 | if($length -le 1)
23 | {
24 | throw "$path is not in correct format."
25 | }
26 | Else
27 | {
28 | $partitionID = $pathList[$length - 2]
29 | }
30 | }
31 | Else {
32 | $partitionID = $pathList[$length - 2]
33 | }
34 |
35 |
36 | if($partitionID -eq $null)
37 | {
38 | throw "Not able to extract partitionID"
39 | }
40 |
41 | if(!$partitionDict.ContainsKey($partitionID))
42 | {
43 | $partitionDict.Add($partitionID, $path)
44 | }
45 | else {
46 | $partitionDict[$partitionID].add($path)
47 | }
48 | }
49 |
50 | return $partitionDict
51 | }
52 |
53 | Function Get-FinalDateTimeBefore
54 | {
55 | [CmdletBinding(PositionalBinding = $false)]
56 | param([Parameter(Mandatory=$true)][string]$DateTimeBefore,
57 | [Parameter(Mandatory=$true)][string]$Partitionid,
58 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
59 | [Parameter(Mandatory=$false)][bool]$DeleteNotFoundPartitions,
60 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
61 | )
62 |
63 | # DateTime Improvement to be done here.
64 | $dateTimeBeforeObject = [DateTime]::ParseExact($DateTimeBefore,"yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
65 | $finalDateTimeObject = $dateTimeBeforeObject
66 | $dateTimeBeforeString = $dateTimeBeforeObject.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
67 | $url = "http://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
68 | $backupEnumerations = $null
69 | try {
70 | if($ClientCertificateThumbprint)
71 | {
72 | $url = "https://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
73 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url -CertificateThumbprint $ClientCertificateThumbprint
74 | }
75 | else {
76 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url
77 | }
78 | $backupEnumerations = $pagedBackupEnumeration.Items | Sort-Object -Property @{Expression = {[DateTime]::ParseExact($_.CreationTimeUtc,"yyyy-MM-ddTHH:mm:ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)}; Ascending = $false}
79 | }
80 | catch {
81 | $err = $_.ToString() | ConvertFrom-Json
82 | if($err.Error.Code -eq "FABRIC_E_PARTITION_NOT_FOUND")
83 | {
84 | Write-Warning "$Partitionid is not found on the cluster : $ClusterEndpoint"
85 | if($DeleteNotFoundPartitions -eq $true)
86 | {
87 | Write-Warning "DeleteNotFoundPartitions flag is enabled so, deleting data all in this partition"
88 | return [DateTime]::MaxValue
89 | }
90 | else {
91 | Write-Warning "If you want to remove data in this partition as well, please run the script by enabling DeleteNotFoundPartitions flag."
92 | return [DateTime]::MinValue
93 | }
94 | }
95 | else {
96 | throw $_.Exception.Message
97 | }
98 | }
99 |
100 | $fullBackupFound = $false
101 | foreach($backupEnumeration in $backupEnumerations)
102 | {
103 | if($backupEnumeration.BackupType -eq "Full")
104 | {
105 | $finalDateTimeObject = [DateTime]::Parse($backupEnumeration.CreationTimeUtc)
106 | $fullBackupFound = $true
107 | break
108 | }
109 | }
110 | if($backupEnumerations.Count -eq 0)
111 | {
112 | Write-Host "There are no backups available in the partition: $Partitionid before the specified date."
113 | return [DateTime]::MinValue
114 | }
115 |
116 | if(!$fullBackupFound)
117 | {
118 | Write-Host "The Backups Before this $dateTimeBeforeString date are corrupt as no full backup is found, So, deleting them."
119 | }
120 | return $finalDateTimeObject
121 | }
122 |
123 |
124 | Function Get-PartitionIdList
125 | {
126 | [CmdletBinding(PositionalBinding = $false)]
127 | param([Parameter(Mandatory=$false)][string]$ApplicationId,
128 | [Parameter(Mandatory=$false)][string]$ServiceId,
129 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
130 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
131 | )
132 |
133 | $serviceIdList = New-Object System.Collections.ArrayList
134 | if($ApplicationId)
135 | {
136 | if($ClientCertificateThumbprint)
137 | {
138 | $serviceIdList = Get-ServiceIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint -ClientCertificateThumbprint $ClientCertificateThumbprint
139 | }
140 | else {
141 | $serviceIdList = Get-ServiceIdList -ApplicationId $ApplicationId -ClusterEndpoint $ClusterEndpoint
142 | }
143 | }
144 | else {
145 | $serviceIdList.Add($ServiceId) | Out-Null
146 | }
147 |
148 | $partitionIdList = New-Object System.Collections.ArrayList
149 |
150 | foreach($serviceId in $serviceIdList)
151 | {
152 | $continuationToken = $null
153 | do
154 | {
155 | if($ClientCertificateThumbprint)
156 | {
157 | $partitionInfoList = Invoke-RestMethod -Uri "https://$ClusterEndpoint/Services/$serviceId/$/GetPartitions?api-version=6.4&ContinuationToken=$continuationToken" -CertificateThumbprint $ClientCertificateThumbprint
158 | }
159 | else {
160 | $partitionInfoList = Invoke-RestMethod -Uri "http://$ClusterEndpoint/Services/$serviceId/$/GetPartitions?api-version=6.4&ContinuationToken=$continuationToken"
161 | }
162 | foreach($partitionInfo in $partitionInfoList.Items)
163 | {
164 | $partitionIdList.Add($partitionInfo.PartitionInformation.Id)
165 | }
166 | $continuationToken = $partitionInfoList.ContinuationToken
167 | }while($continuationToken -ne "")
168 | }
169 | $length = $partitionIdList.Count
170 | Write-Host "The total number of partitions found on the cluster are $length"
171 | return $partitionIdList
172 | }
173 |
174 |
175 | Function Get-ServiceIdList
176 | {
177 | [CmdletBinding(PositionalBinding = $false)]
178 | param([Parameter(Mandatory=$true)][string]$ApplicationId,
179 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
180 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
181 | )
182 |
183 | $continuationToken = $null
184 | $serviceIdList = New-Object System.Collections.ArrayList
185 | do
186 | {
187 | if($ClientCertificateThumbprint)
188 | {
189 | $serviceInfoList = Invoke-RestMethod -Uri "https://$ClusterEndpoint/Applications/$ApplicationId/$/GetServices?api-version=6.4&ContinuationToken=$continuationToken" -CertificateThumbprint $ClientCertificateThumbprint
190 | }
191 | else {
192 | $serviceInfoList = Invoke-RestMethod -Uri "http://$ClusterEndpoint/Applications/$ApplicationId/$/GetServices?api-version=6.4&ContinuationToken=$continuationToken"
193 | }
194 | foreach($serviceInfo in $serviceInfoList.Items)
195 | {
196 | $serviceIdList.Add($serviceInfo.Id) | Out-Null
197 | }
198 | $continuationToken = $serviceInfoList.ContinuationToken
199 | }while($continuationToken -ne "")
200 |
201 | $length = $serviceIdList.Count
202 | Write-Host "$ApplicationId has $length number of services"
203 | return $serviceIdList
204 | }
205 |
206 |
207 | Function Start-BackupDataCorruptionTest
208 | {
209 | [CmdletBinding(PositionalBinding = $false)]
210 | param([Parameter(Mandatory=$true)][string]$DateTimeBefore,
211 | [Parameter(Mandatory=$true)][string]$Partitionid,
212 | [Parameter(Mandatory=$true)][string]$ClusterEndpoint,
213 | [Parameter(Mandatory=$false)][string]$ClientCertificateThumbprint
214 | )
215 | $dateTimeBeforeObject = [DateTime]::ParseExact($DateTimeBefore,"yyyy-MM-dd HH.mm.ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)
216 | $dateTimeBeforeString = $dateTimeBeforeObject.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
217 | # DateTime Improvement to be done here.
218 | $url = "http://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
219 |
220 | $backupEnumerations = $null
221 | try {
222 | if($ClientCertificateThumbprint)
223 | {
224 | $url = "https://$ClusterEndpoint/Partitions/$Partitionid/$/GetBackups?api-version=6.4&EndDateTimeFilter=$dateTimeBeforeString"
225 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url -CertificateThumbprint $ClientCertificateThumbprint
226 | }
227 | else {
228 | $pagedBackupEnumeration = Invoke-RestMethod -Uri $url
229 | }
230 | $backupEnumerations = $pagedBackupEnumeration.Items | Sort-Object -Property @{Expression = {[DateTime]::ParseExact($_.CreationTimeUtc,"yyyy-MM-ddTHH:mm:ssZ",[System.Globalization.DateTimeFormatInfo]::InvariantInfo,[System.Globalization.DateTimeStyles]::None)}; Ascending = $true}
231 |
232 | if($backupEnumerations -ne $null -and $backupEnumerations[0].BackupType -ne "Full")
233 | {
234 | throw "Data is corrupted for this partition : $Partitionid"
235 | }
236 | }
237 | catch {
238 | $err = $_.ToString() | ConvertFrom-Json
239 | if($err.Error.Code -eq "FABRIC_E_PARTITION_NOT_FOUND")
240 | {
241 | Write-Host "Partition: $Partitionid not found, so, could not go through with testing the integrity of data of this partition."
242 | }
243 | else {
244 | throw $_.Exception.Message
245 | }
246 | }
247 | }
--------------------------------------------------------------------------------
/templates/service-integration/apim.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "apimInstanceName": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The name of your API Management service."
9 | }
10 | },
11 | "apimPublisherEmail": {
12 | "type": "string",
13 | "minLength": 1,
14 | "metadata": {
15 | "description": "The email address of the owner of the service"
16 | }
17 | },
18 | "apimSku": {
19 | "type": "string",
20 | "allowedValues": [
21 | "Developer",
22 | "Premium"
23 | ],
24 | "defaultValue": "Developer",
25 | "metadata": {
26 | "description": "The pricing tier of this API Management service. Only Developer and Premium are supported when deploying into a shared VNET."
27 | }
28 | },
29 | "serviceFabricCertificateName": {
30 | "defaultValue": "service-fabric-certificate-name",
31 | "type": "string"
32 | },
33 | "serviceFabricCertificate": {
34 | "type": "securestring",
35 | "metadata": {
36 | "description": "Base-64 encoded PFX certificate to talk to Service Fabric Backend ."
37 | }
38 | },
39 | "certificatePassword": {
40 | "type": "securestring",
41 | "metadata": {
42 | "description": "Certificate password to use to talk to Service Fabric Backend."
43 | }
44 | },
45 | "serviceFabricCertificateThumbprint": {
46 | "type": "string",
47 | "metadata": {
48 | "description": "Certificate Thumbprint to use to talk to Service Fabric Backend."
49 | }
50 | },
51 | "clusterHttpManagementEndpoint": {
52 | "type": "string",
53 | "metadata": {
54 | "description": "cluster HTTP management endpoint."
55 | }
56 | },
57 | "policies_policy_name": {
58 | "defaultValue": "policy",
59 | "type": "string"
60 | },
61 | "inbound_policy":{
62 | "defaultValue": "\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n",
63 | "type": "string"
64 | },
65 | "apis_service_fabric_app_name": {
66 | "defaultValue": "service-fabric-app",
67 | "type": "string"
68 | },
69 | "apim_service_fabric_product_name": {
70 | "defaultValue": "service-fabric-api-product",
71 | "type": "String"
72 | },
73 | "service_fabric_backend_name": {
74 | "defaultValue": "servicefabric",
75 | "type": "string"
76 | },
77 | "apis_service_fabric_app_name_operation": {
78 | "defaultValue": "service-fabric-app-operation",
79 | "type": "string"
80 | },
81 | "url_path": {
82 | "defaultValue": "/api/values",
83 | "type": "string"
84 | },
85 | "vnetName": {
86 | "defaultValue": "sf-apim-vnet",
87 | "type": "string",
88 | "metadata": {
89 | "description": "The name of the VNET that contains the Service Fabric cluster and API Management service deployment."
90 | }
91 | },
92 | "subnetName": {
93 | "defaultValue": "apim-subnet",
94 | "type": "string",
95 | "metadata": {
96 | "description": "The name subnet to deploy the API Management service to. This subnet cannot have any other resources in it and must be in the same VNET that contains the Service Fabric cluster back-end."
97 | }
98 | },
99 | "vnetVersion": {
100 | "defaultValue": "2017-03-01",
101 | "type": "string",
102 | "metadata": {
103 | "description": "The version of the VNET resource to which the subnet belongs as defined by the subnetName parameter."
104 | }
105 | },
106 | "networkSecurityGroupName": {
107 | "defaultValue": "apim-vnet-security",
108 | "type": "string",
109 | "metadata": {
110 | "description": "The name Network Security Group to deploy the API Management service to. This NSG must be applied to the subnet in the 'subnetName' parameter."
111 | }
112 | },
113 | "networkSecurityGroupVersion": {
114 | "defaultValue": "2017-03-01",
115 | "type": "string",
116 | "metadata": {
117 | "description": "The version of the Network Security Group resource."
118 | }
119 | }
120 | },
121 | "variables": {
122 | "location": "[string(resourceGroup().location)]",
123 | "apimSubnetId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]"
124 | },
125 | "resources": [
126 | {
127 | "type": "Microsoft.ApiManagement/service",
128 | "sku": {
129 | "name": "[parameters('apimSku')]",
130 | "capacity": 1
131 | },
132 | "name": "[parameters('apimInstanceName')]",
133 | "apiVersion": "2017-03-01",
134 | "location": "[variables('location')]",
135 | "tags": {},
136 | "properties": {
137 | "publisherEmail": "[parameters('apimPublisherEmail')]",
138 | "publisherName": "Microsoft",
139 | "virtualNetworkConfiguration": {
140 | "subnetResourceId": "[variables('apimSubnetId')]",
141 | "location": "[variables('location')]"
142 | },
143 | "customProperties": {
144 | "subnetAddress": "[reference(variables('apimSubnetId'), parameters('vnetVersion')).addressPrefix]"
145 | },
146 | "virtualNetworkType": "External"
147 | }
148 | },
149 | {
150 | "apiVersion": "2017-03-01",
151 | "type": "Microsoft.ApiManagement/service/certificates",
152 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('serviceFabricCertificateName'))]",
153 | "dependsOn": [
154 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]"
155 | ],
156 | "properties": {
157 | "data": "[parameters('serviceFabricCertificate')]",
158 | "password": "[parameters('certificatePassword')]"
159 | }
160 | },
161 | {
162 | "apiVersion": "2017-03-01",
163 | "type": "Microsoft.ApiManagement/service/backends",
164 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('service_fabric_backend_name'))]",
165 | "dependsOn": [
166 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]",
167 | "[resourceId('Microsoft.ApiManagement/service/certificates', parameters('apimInstanceName'), parameters('serviceFabricCertificateName'))]"
168 | ],
169 | "properties": {
170 | "description": "My Service Fabric backend",
171 | "url": "fabric:/fake/service",
172 | "protocol": "http",
173 | "resourceId": "[parameters('clusterHttpManagementEndpoint')]",
174 | "properties": {
175 | "serviceFabricCluster": {
176 | "managementEndpoints": [
177 | "[parameters('clusterHttpManagementEndpoint')]"
178 | ],
179 | "clientCertificateThumbprint": "[parameters('serviceFabricCertificateThumbprint')]",
180 | "serverCertificateThumbprints": [
181 | "[parameters('serviceFabricCertificateThumbprint')]"
182 | ],
183 | "maxPartitionResolutionRetries": 5
184 | }
185 | }
186 | }
187 | },
188 | {
189 | "type": "Microsoft.ApiManagement/service/products",
190 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('apim_service_fabric_product_name'))]",
191 | "apiVersion": "2017-03-01",
192 | "scale": null,
193 | "properties": {
194 | "displayName": "Service Fabric Apis",
195 | "description": "Subscribers have access to Service Fabric Apis.",
196 | "terms": null,
197 | "subscriptionRequired": true,
198 | "approvalRequired": false,
199 | "subscriptionsLimit": 1,
200 | "state": "published"
201 | },
202 | "dependsOn": [
203 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]"
204 | ]
205 | },
206 | {
207 | "type": "Microsoft.ApiManagement/service/apis",
208 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('apis_service_fabric_app_name'))]",
209 | "apiVersion": "2017-03-01",
210 | "scale": null,
211 | "properties": {
212 | "displayName": "Service Fabric App",
213 | "apiRevision": "1",
214 | "description": "",
215 | "serviceUrl": "http://servicefabric",
216 | "path": "myapp",
217 | "protocols": [
218 | "http",
219 | "https"
220 | ],
221 | "authenticationSettings": null,
222 | "subscriptionKeyParameterNames": null,
223 | "isCurrent": true
224 | },
225 | "dependsOn": [
226 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]"
227 | ]
228 | },
229 | {
230 | "type": "Microsoft.ApiManagement/service/apis/operations",
231 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('apis_service_fabric_app_name'), '/', parameters('apis_service_fabric_app_name_operation'))]",
232 | "apiVersion": "2017-03-01",
233 | "scale": null,
234 | "properties": {
235 | "displayName": "Values",
236 | "method": "GET",
237 | "urlTemplate": "[parameters('url_path')]",
238 | "description": "",
239 | "policies": null
240 | },
241 | "dependsOn": [
242 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]",
243 | "[resourceId('Microsoft.ApiManagement/service/apis', parameters('apimInstanceName'), parameters('apis_service_fabric_app_name'))]"
244 | ]
245 | },
246 | {
247 | "type": "Microsoft.ApiManagement/service/apis/policies",
248 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('apis_service_fabric_app_name'), '/', parameters('policies_policy_name'))]",
249 | "apiVersion": "2017-03-01",
250 | "properties": {
251 | "policyContent": "[parameters('inbound_policy')]"
252 | },
253 | "dependsOn": [
254 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]",
255 | "[resourceId('Microsoft.ApiManagement/service/apis', parameters('apimInstanceName'), parameters('apis_service_fabric_app_name'))]",
256 | "[resourceId('Microsoft.ApiManagement/service/backends', parameters('apimInstanceName'), parameters('service_fabric_backend_name'))]"
257 | ]
258 | },
259 | {
260 | "type": "Microsoft.ApiManagement/service/products/apis",
261 | "name": "[concat(parameters('apimInstanceName'), '/', parameters('apim_service_fabric_product_name'), '/', parameters('apis_service_fabric_app_name'))]",
262 | "apiVersion": "2017-03-01",
263 | "scale": null,
264 | "properties": {},
265 | "dependsOn": [
266 | "[resourceId('Microsoft.ApiManagement/service', parameters('apimInstanceName'))]",
267 | "[resourceId('Microsoft.ApiManagement/service/apis', parameters('apimInstanceName'), parameters('apis_service_fabric_app_name'))]",
268 | "[resourceId('Microsoft.ApiManagement/service/products', parameters('apimInstanceName'), parameters('apim_service_fabric_product_name'))]"
269 | ]
270 | },
271 | {
272 | "type": "Microsoft.Network/networkSecurityGroups",
273 | "name": "[parameters('networkSecurityGroupName')]",
274 | "apiVersion": "[parameters('networkSecurityGroupVersion')]",
275 | "location": "[variables('location')]",
276 | "properties": {
277 | "securityRules": [
278 | {
279 | "name": "Client_communication_to_API_Management",
280 | "properties": {
281 | "protocol": "TCP",
282 | "sourcePortRange": "*",
283 | "destinationPortRange": "80",
284 | "sourceAddressPrefix": "Internet",
285 | "destinationAddressPrefix": "[reference(variables('apimSubnetId'), parameters('vnetVersion')).addressPrefix]",
286 | "access": "Allow",
287 | "priority": 100,
288 | "direction": "Inbound"
289 | }
290 | },
291 | {
292 | "name": "Secure_Client_communication_to_API_Management",
293 | "properties": {
294 | "protocol": "TCP",
295 | "sourcePortRange": "*",
296 | "destinationPortRange": "443",
297 | "sourceAddressPrefix": "Internet",
298 | "destinationAddressPrefix": "[reference(variables('apimSubnetId'), parameters('vnetVersion')).addressPrefix]",
299 | "access": "Allow",
300 | "priority": 110,
301 | "direction": "Inbound"
302 | }
303 | },
304 | {
305 | "name": "Management_endpoint_for_Azure_portal_and_Powershell",
306 | "properties": {
307 | "protocol": "TCP",
308 | "sourcePortRange": "*",
309 | "destinationPortRange": "3443",
310 | "sourceAddressPrefix": "Internet",
311 | "destinationAddressPrefix": "VirtualNetwork",
312 | "access": "Allow",
313 | "priority": 120,
314 | "direction": "Inbound"
315 | }
316 | },
317 | {
318 | "name": "Dependency_on_Redis_Cache",
319 | "properties": {
320 | "protocol": "TCP",
321 | "sourcePortRange": "*",
322 | "destinationPortRange": "6381-6383",
323 | "sourceAddressPrefix": "VirtualNetwork",
324 | "destinationAddressPrefix": "VirtualNetwork",
325 | "access": "Allow",
326 | "priority": 130,
327 | "direction": "Inbound"
328 | }
329 | },
330 | {
331 | "name": "Dependency_on_Azure_Storage_and_Azure_Service_Bus",
332 | "properties": {
333 | "protocol": "TCP",
334 | "sourcePortRange": "*",
335 | "destinationPortRange": "80",
336 | "sourceAddressPrefix": "VirtualNetwork",
337 | "destinationAddressPrefix": "Internet",
338 | "access": "Allow",
339 | "priority": 100,
340 | "direction": "Outbound"
341 | }
342 | },
343 | {
344 | "name": "Dependency_on_Azure_SQL",
345 | "properties": {
346 | "protocol": "TCP",
347 | "sourcePortRange": "*",
348 | "destinationPortRange": "1433",
349 | "sourceAddressPrefix": "VirtualNetwork",
350 | "destinationAddressPrefix": "Internet",
351 | "access": "Allow",
352 | "priority": 110,
353 | "direction": "Outbound"
354 | }
355 | },
356 | {
357 | "name": "Dependency_on_Azure_SQL_V12",
358 | "properties": {
359 | "protocol": "TCP",
360 | "sourcePortRange": "*",
361 | "destinationPortRange": "11000-11999",
362 | "sourceAddressPrefix": "VirtualNetwork",
363 | "destinationAddressPrefix": "Internet",
364 | "access": "Allow",
365 | "priority": 120,
366 | "direction": "Outbound"
367 | }
368 | },
369 | {
370 | "name": "Dependency_on_Azure_SQL_V12_2",
371 | "properties": {
372 | "protocol": "TCP",
373 | "sourcePortRange": "*",
374 | "destinationPortRange": "14000-14999",
375 | "sourceAddressPrefix": "VirtualNetwork",
376 | "destinationAddressPrefix": "Internet",
377 | "access": "Allow",
378 | "priority": 130,
379 | "direction": "Outbound"
380 | }
381 | },
382 | {
383 | "name": "Dependency_on_Service_Bus",
384 | "properties": {
385 | "protocol": "TCP",
386 | "sourcePortRange": "*",
387 | "destinationPortRange": "9350-9354",
388 | "sourceAddressPrefix": "VirtualNetwork",
389 | "destinationAddressPrefix": "Internet",
390 | "access": "Allow",
391 | "priority": 140,
392 | "direction": "Outbound"
393 | }
394 | },
395 | {
396 | "name": "Dependency_for_Log_to_event_Hub_policy",
397 | "properties": {
398 | "protocol": "*",
399 | "sourcePortRange": "*",
400 | "destinationPortRange": "5671",
401 | "sourceAddressPrefix": "VirtualNetwork",
402 | "destinationAddressPrefix": "Internet",
403 | "access": "Allow",
404 | "priority": 150,
405 | "direction": "Outbound"
406 | }
407 | },
408 | {
409 | "name": "Dependency_on_Redis_Cache_outbound",
410 | "properties": {
411 | "protocol": "TCP",
412 | "sourcePortRange": "*",
413 | "destinationPortRange": "6381-6383",
414 | "sourceAddressPrefix": "VirtualNetwork",
415 | "destinationAddressPrefix": "VirtualNetwork",
416 | "access": "Allow",
417 | "priority": 160,
418 | "direction": "Outbound"
419 | }
420 | },
421 | {
422 | "name": "Dependency_on_Azure_File_Share_for_GIT",
423 | "properties": {
424 | "protocol": "TCP",
425 | "sourcePortRange": "*",
426 | "destinationPortRange": "445",
427 | "sourceAddressPrefix": "VirtualNetwork",
428 | "destinationAddressPrefix": "Internet",
429 | "access": "Allow",
430 | "priority": 170,
431 | "direction": "Outbound"
432 | }
433 | },
434 | {
435 | "name": "Azure_Infrastructure_Load_Balancer",
436 | "properties": {
437 | "protocol": "TCP",
438 | "sourcePortRange": "*",
439 | "destinationPortRange": "*",
440 | "sourceAddressPrefix": "AzureLoadBalancer",
441 | "destinationAddressPrefix": "VirtualNetwork",
442 | "access": "Allow",
443 | "priority": 140,
444 | "direction": "Inbound"
445 | }
446 | }
447 | ]
448 | }
449 | }
450 | ]
451 | }
452 |
--------------------------------------------------------------------------------
/templates/networking/template_original.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "clusterLocation": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Location of the Cluster"
9 | }
10 | },
11 | "clusterName": {
12 | "type": "string",
13 | "defaultValue": "Cluster",
14 | "metadata": {
15 | "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only"
16 | }
17 | },
18 | "nt0applicationStartPort": {
19 | "type": "int",
20 | "defaultValue": 20000
21 | },
22 | "nt0applicationEndPort": {
23 | "type": "int",
24 | "defaultValue": 30000
25 | },
26 | "nt0ephemeralStartPort": {
27 | "type": "int",
28 | "defaultValue": 49152
29 | },
30 | "nt0ephemeralEndPort": {
31 | "type": "int",
32 | "defaultValue": 65534
33 | },
34 | "nt0fabricTcpGatewayPort": {
35 | "type": "int",
36 | "defaultValue": 19000
37 | },
38 | "nt0fabricHttpGatewayPort": {
39 | "type": "int",
40 | "defaultValue": 19080
41 | },
42 | "subnet0Name": {
43 | "type": "string",
44 | "defaultValue": "Subnet-0"
45 | },
46 | "subnet0Prefix": {
47 | "type": "string",
48 | "defaultValue": "10.0.0.0/24"
49 | },
50 | "computeLocation": {
51 | "type": "string"
52 | },
53 | "vmStorageAccountName": {
54 | "type": "string"
55 | },
56 | "publicIPAddressName": {
57 | "type": "string",
58 | "defaultValue": "PublicIP-VM"
59 | },
60 | "publicIPAddressType": {
61 | "type": "string",
62 | "allowedValues": [
63 | "Dynamic"
64 | ],
65 | "defaultValue": "Dynamic"
66 | },
67 | "vmStorageAccountContainerName": {
68 | "type": "string",
69 | "defaultValue": "vhds"
70 | },
71 | "adminUserName": {
72 | "type": "string",
73 | "defaultValue": "testadm",
74 | "metadata": {
75 | "description": "Remote desktop user Id"
76 | }
77 | },
78 | "adminPassword": {
79 | "type": "securestring",
80 | "metadata": {
81 | "description": "Remote desktop user password. Must be a strong password"
82 | }
83 | },
84 | "virtualNetworkName": {
85 | "type": "string",
86 | "defaultValue": "VNet"
87 | },
88 | "addressPrefix": {
89 | "type": "string",
90 | "defaultValue": "10.0.0.0/16"
91 | },
92 | "dnsName": {
93 | "type": "string"
94 | },
95 | "nicName": {
96 | "type": "string",
97 | "defaultValue": "NIC"
98 | },
99 | "lbName": {
100 | "type": "string",
101 | "defaultValue": "LoadBalancer"
102 | },
103 | "lbIPName": {
104 | "type": "string",
105 | "defaultValue": "PublicIP-LB-FE"
106 | },
107 | "overProvision": {
108 | "type": "string",
109 | "defaultValue": "false"
110 | },
111 | "vmImagePublisher": {
112 | "type": "string",
113 | "defaultValue": "MicrosoftWindowsServer"
114 | },
115 | "vmImageOffer": {
116 | "type": "string",
117 | "defaultValue": "WindowsServer"
118 | },
119 | "vmImageSku": {
120 | "type": "string",
121 | "defaultValue": "2012-R2-Datacenter"
122 | },
123 | "vmImageVersion": {
124 | "type": "string",
125 | "defaultValue": "latest"
126 | },
127 | "loadBalancedAppPort1": {
128 | "type": "int",
129 | "defaultValue": 80,
130 | "metadata": {
131 | "description": "Input endpoint1 for the application to use. Replace it with what your application uses"
132 | }
133 | },
134 | "storageAccountType": {
135 | "type": "string",
136 | "allowedValues": [
137 | "Standard_LRS",
138 | "Standard_GRS"
139 | ],
140 | "defaultValue": "Standard_LRS",
141 | "metadata": {
142 | "description": "Replication option for the VM image storage account"
143 | }
144 | },
145 | "supportLogStorageAccountType": {
146 | "type": "string",
147 | "allowedValues": [
148 | "Standard_LRS",
149 | "Standard_GRS"
150 | ],
151 | "defaultValue": "Standard_LRS",
152 | "metadata": {
153 | "description": "Replication option for the support log storage account"
154 | }
155 | },
156 | "supportLogStorageAccountName": {
157 | "type": "string",
158 | "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]",
159 | "metadata": {
160 | "description": "Name for the storage account that contains support logs from the cluster"
161 | }
162 | },
163 | "applicationDiagnosticsStorageAccountType": {
164 | "type": "string",
165 | "allowedValues": [
166 | "Standard_LRS",
167 | "Standard_GRS"
168 | ],
169 | "defaultValue": "Standard_LRS",
170 | "metadata": {
171 | "description": "Replication option for the application diagnostics storage account"
172 | }
173 | },
174 | "applicationDiagnosticsStorageAccountName": {
175 | "type": "string",
176 | "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]",
177 | "metadata": {
178 | "description": "Name for the storage account that contains application diagnostics data from the cluster"
179 | }
180 | },
181 | "nt0InstanceCount": {
182 | "type": "int",
183 | "defaultValue": 5,
184 | "metadata": {
185 | "description": "Instance count for node type"
186 | }
187 | },
188 | "vmNodeType0Name": {
189 | "type": "string",
190 | "defaultValue": "Node1",
191 | "maxLength": 9
192 | },
193 | "vmNodeType0Size": {
194 | "type": "string",
195 | "defaultValue": "Standard_D1_v2"
196 | }
197 | },
198 | "variables": {
199 | "vmssApiVersion": "2016-03-30",
200 | "lbApiVersion": "2015-06-15",
201 | "vNetApiVersion": "2015-06-15",
202 | "storageApiVersion": "2016-01-01",
203 | "publicIPApiVersion": "2015-06-15",
204 | "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
205 | "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]",
206 | "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]",
207 | "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]",
208 | "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]",
209 | "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]",
210 | "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]",
211 | "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]",
212 | "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]",
213 | "uniqueStringArray0": [
214 | "[concat(variables('vmStorageAccountName0'), '0')]",
215 | "[concat(variables('vmStorageAccountName0'), '1')]",
216 | "[concat(variables('vmStorageAccountName0'), '2')]",
217 | "[concat(variables('vmStorageAccountName0'), '3')]",
218 | "[concat(variables('vmStorageAccountName0'), '4')]"
219 | ]
220 | },
221 | "resources": [
222 | {
223 | "apiVersion": "[variables('storageApiVersion')]",
224 | "type": "Microsoft.Storage/storageAccounts",
225 | "name": "[parameters('supportLogStorageAccountName')]",
226 | "location": "[parameters('computeLocation')]",
227 | "dependsOn": [],
228 | "properties": {},
229 | "kind": "Storage",
230 | "sku": {
231 | "name": "[parameters('supportLogStorageAccountType')]"
232 | },
233 | "tags": {
234 | "resourceType": "Service Fabric",
235 | "clusterName": "[parameters('clusterName')]"
236 | }
237 | },
238 | {
239 | "apiVersion": "[variables('storageApiVersion')]",
240 | "type": "Microsoft.Storage/storageAccounts",
241 | "name": "[parameters('applicationDiagnosticsStorageAccountName')]",
242 | "location": "[parameters('computeLocation')]",
243 | "dependsOn": [],
244 | "properties": {},
245 | "kind": "Storage",
246 | "sku": {
247 | "name": "[parameters('applicationDiagnosticsStorageAccountType')]"
248 | },
249 | "tags": {
250 | "resourceType": "Service Fabric",
251 | "clusterName": "[parameters('clusterName')]"
252 | }
253 | },
254 | {
255 | "apiVersion": "[variables('vNetApiVersion')]",
256 | "type": "Microsoft.Network/virtualNetworks",
257 | "name": "[parameters('virtualNetworkName')]",
258 | "location": "[parameters('computeLocation')]",
259 | "properties": {
260 | "addressSpace": {
261 | "addressPrefixes": [
262 | "[parameters('addressPrefix')]"
263 | ]
264 | },
265 | "subnets": [
266 | {
267 | "name": "[parameters('subnet0Name')]",
268 | "properties": {
269 | "addressPrefix": "[parameters('subnet0Prefix')]"
270 | }
271 | }
272 | ]
273 | },
274 | "tags": {
275 | "resourceType": "Service Fabric",
276 | "clusterName": "[parameters('clusterName')]"
277 | }
278 | },
279 | {
280 | "apiVersion": "[variables('publicIPApiVersion')]",
281 | "type": "Microsoft.Network/publicIPAddresses",
282 | "name": "[concat(parameters('lbIPName'),'-','0')]",
283 | "location": "[parameters('computeLocation')]",
284 | "properties": {
285 | "dnsSettings": {
286 | "domainNameLabel": "[parameters('dnsName')]"
287 | },
288 | "publicIPAllocationMethod": "Dynamic"
289 | },
290 | "tags": {
291 | "resourceType": "Service Fabric",
292 | "clusterName": "[parameters('clusterName')]"
293 | }
294 | },
295 | {
296 | "apiVersion": "[variables('lbApiVersion')]",
297 | "type": "Microsoft.Network/loadBalancers",
298 | "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]",
299 | "location": "[parameters('computeLocation')]",
300 | "dependsOn": [
301 | "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]"
302 | ],
303 | "properties": {
304 | "frontendIPConfigurations": [
305 | {
306 | "name": "LoadBalancerIPConfig",
307 | "properties": {
308 | "publicIPAddress": {
309 | "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]"
310 | }
311 | }
312 | }
313 | ],
314 | "backendAddressPools": [
315 | {
316 | "name": "LoadBalancerBEAddressPool",
317 | "properties": {}
318 | }
319 | ],
320 | "loadBalancingRules": [
321 | {
322 | "name": "LBRule",
323 | "properties": {
324 | "backendAddressPool": {
325 | "id": "[variables('lbPoolID0')]"
326 | },
327 | "backendPort": "[parameters('nt0fabricTcpGatewayPort')]",
328 | "enableFloatingIP": "false",
329 | "frontendIPConfiguration": {
330 | "id": "[variables('lbIPConfig0')]"
331 | },
332 | "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]",
333 | "idleTimeoutInMinutes": "5",
334 | "probe": {
335 | "id": "[variables('lbProbeID0')]"
336 | },
337 | "protocol": "tcp"
338 | }
339 | },
340 | {
341 | "name": "LBHttpRule",
342 | "properties": {
343 | "backendAddressPool": {
344 | "id": "[variables('lbPoolID0')]"
345 | },
346 | "backendPort": "[parameters('nt0fabricHttpGatewayPort')]",
347 | "enableFloatingIP": "false",
348 | "frontendIPConfiguration": {
349 | "id": "[variables('lbIPConfig0')]"
350 | },
351 | "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]",
352 | "idleTimeoutInMinutes": "5",
353 | "probe": {
354 | "id": "[variables('lbHttpProbeID0')]"
355 | },
356 | "protocol": "tcp"
357 | }
358 | },
359 | {
360 | "name": "AppPortLBRule1",
361 | "properties": {
362 | "backendAddressPool": {
363 | "id": "[variables('lbPoolID0')]"
364 | },
365 | "backendPort": "[parameters('loadBalancedAppPort1')]",
366 | "enableFloatingIP": "false",
367 | "frontendIPConfiguration": {
368 | "id": "[variables('lbIPConfig0')]"
369 | },
370 | "frontendPort": "[parameters('loadBalancedAppPort1')]",
371 | "idleTimeoutInMinutes": "5",
372 | "probe": {
373 | "id": "[concat(variables('lbID0'),'/probes/AppPortProbe1')]"
374 | },
375 | "protocol": "tcp"
376 | }
377 | }
378 | ],
379 | "probes": [
380 | {
381 | "name": "FabricGatewayProbe",
382 | "properties": {
383 | "intervalInSeconds": 5,
384 | "numberOfProbes": 2,
385 | "port": "[parameters('nt0fabricTcpGatewayPort')]",
386 | "protocol": "tcp"
387 | }
388 | },
389 | {
390 | "name": "FabricHttpGatewayProbe",
391 | "properties": {
392 | "intervalInSeconds": 5,
393 | "numberOfProbes": 2,
394 | "port": "[parameters('nt0fabricHttpGatewayPort')]",
395 | "protocol": "tcp"
396 | }
397 | },
398 | {
399 | "name": "AppPortProbe1",
400 | "properties": {
401 | "intervalInSeconds": 5,
402 | "numberOfProbes": 2,
403 | "port": "[parameters('loadBalancedAppPort1')]",
404 | "protocol": "tcp"
405 | }
406 | }
407 | ],
408 | "inboundNatPools": [
409 | {
410 | "name": "LoadBalancerBEAddressNatPool",
411 | "properties": {
412 | "backendPort": "3389",
413 | "frontendIPConfiguration": {
414 | "id": "[variables('lbIPConfig0')]"
415 | },
416 | "frontendPortRangeEnd": "4500",
417 | "frontendPortRangeStart": "3389",
418 | "protocol": "tcp"
419 | }
420 | }
421 | ]
422 | },
423 | "tags": {
424 | "resourceType": "Service Fabric",
425 | "clusterName": "[parameters('clusterName')]"
426 | }
427 | },
428 | {
429 | "apiVersion": "[variables('storageApiVersion')]",
430 | "type": "Microsoft.Storage/storageAccounts",
431 | "name": "[variables('uniqueStringArray0')[copyIndex()]]",
432 | "location": "[parameters('computeLocation')]",
433 | "dependsOn": [],
434 | "properties": {},
435 | "copy": {
436 | "name": "storageLoop",
437 | "count": 5
438 | },
439 | "kind": "Storage",
440 | "sku": {
441 | "name": "[parameters('storageAccountType')]"
442 | },
443 | "tags": {
444 | "resourceType": "Service Fabric",
445 | "clusterName": "[parameters('clusterName')]"
446 | }
447 | },
448 | {
449 | "apiVersion": "[variables('vmssApiVersion')]",
450 | "type": "Microsoft.Compute/virtualMachineScaleSets",
451 | "name": "[parameters('vmNodeType0Name')]",
452 | "location": "[parameters('computeLocation')]",
453 | "dependsOn": [
454 | "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]",
455 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0])]",
456 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1])]",
457 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]",
458 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]",
459 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]",
460 | "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]",
461 | "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]",
462 | "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]"
463 | ],
464 | "properties": {
465 | "overprovision": "[parameters('overProvision')]",
466 | "upgradePolicy": {
467 | "mode": "Automatic"
468 | },
469 | "virtualMachineProfile": {
470 | "extensionProfile": {
471 | "extensions": [
472 | {
473 | "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricNode')]",
474 | "properties": {
475 | "type": "ServiceFabricNode",
476 | "autoUpgradeMinorVersion": false,
477 | "protectedSettings": {
478 | "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]",
479 | "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]"
480 | },
481 | "publisher": "Microsoft.Azure.ServiceFabric",
482 | "settings": {
483 | "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]",
484 | "nodeTypeRef": "[parameters('vmNodeType0Name')]",
485 | "dataPath": "D:\\\\SvcFab",
486 | "durabilityLevel": "Bronze"
487 | },
488 | "typeHandlerVersion": "1.0"
489 | }
490 | },
491 | {
492 | "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]",
493 | "properties": {
494 | "type": "IaaSDiagnostics",
495 | "autoUpgradeMinorVersion": true,
496 | "protectedSettings": {
497 | "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]",
498 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]",
499 | "storageAccountEndPoint": "https://core.windows.net/"
500 | },
501 | "publisher": "Microsoft.Azure.Diagnostics",
502 | "settings": {
503 | "WadCfg": {
504 | "DiagnosticMonitorConfiguration": {
505 | "overallQuotaInMB": "50000",
506 | "EtwProviders": {
507 | "EtwEventSourceProviderConfiguration": [
508 | {
509 | "provider": "Microsoft-ServiceFabric-Actors",
510 | "scheduledTransferKeywordFilter": "1",
511 | "scheduledTransferPeriod": "PT5M",
512 | "DefaultEvents": {
513 | "eventDestination": "ServiceFabricReliableActorEventTable"
514 | }
515 | },
516 | {
517 | "provider": "Microsoft-ServiceFabric-Services",
518 | "scheduledTransferPeriod": "PT5M",
519 | "DefaultEvents": {
520 | "eventDestination": "ServiceFabricReliableServiceEventTable"
521 | }
522 | }
523 | ],
524 | "EtwManifestProviderConfiguration": [
525 | {
526 | "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8",
527 | "scheduledTransferLogLevelFilter": "Information",
528 | "scheduledTransferKeywordFilter": "4611686018427387904",
529 | "scheduledTransferPeriod": "PT5M",
530 | "DefaultEvents": {
531 | "eventDestination": "ServiceFabricSystemEventTable"
532 | }
533 | }
534 | ]
535 | }
536 | }
537 | },
538 | "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]"
539 | },
540 | "typeHandlerVersion": "1.5"
541 | }
542 | }
543 | ]
544 | },
545 | "networkProfile": {
546 | "networkInterfaceConfigurations": [
547 | {
548 | "name": "[concat(parameters('nicName'), '-0')]",
549 | "properties": {
550 | "ipConfigurations": [
551 | {
552 | "name": "[concat(parameters('nicName'),'-',0)]",
553 | "properties": {
554 | "loadBalancerBackendAddressPools": [
555 | {
556 | "id": "[variables('lbPoolID0')]"
557 | }
558 | ],
559 | "loadBalancerInboundNatPools": [
560 | {
561 | "id": "[variables('lbNatPoolID0')]"
562 | }
563 | ],
564 | "subnet": {
565 | "id": "[variables('subnet0Ref')]"
566 | }
567 | }
568 | }
569 | ],
570 | "primary": true
571 | }
572 | }
573 | ]
574 | },
575 | "osProfile": {
576 | "adminPassword": "[parameters('adminPassword')]",
577 | "adminUsername": "[parameters('adminUsername')]",
578 | "computernamePrefix": "[parameters('vmNodeType0Name')]"
579 | },
580 | "storageProfile": {
581 | "imageReference": {
582 | "publisher": "[parameters('vmImagePublisher')]",
583 | "offer": "[parameters('vmImageOffer')]",
584 | "sku": "[parameters('vmImageSku')]",
585 | "version": "[parameters('vmImageVersion')]"
586 | },
587 | "osDisk": {
588 | "vhdContainers": [
589 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
590 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
591 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
592 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
593 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]"
594 | ],
595 | "name": "vmssosdisk",
596 | "caching": "ReadOnly",
597 | "createOption": "FromImage"
598 | }
599 | }
600 | }
601 | },
602 | "sku": {
603 | "name": "[parameters('vmNodeType0Size')]",
604 | "capacity": "[parameters('nt0InstanceCount')]",
605 | "tier": "Standard"
606 | },
607 | "tags": {
608 | "resourceType": "Service Fabric",
609 | "clusterName": "[parameters('clusterName')]"
610 | }
611 | },
612 | {
613 | "apiVersion": "2016-09-01",
614 | "type": "Microsoft.ServiceFabric/clusters",
615 | "name": "[parameters('clusterName')]",
616 | "location": "[parameters('clusterLocation')]",
617 | "dependsOn": [
618 | "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]"
619 | ],
620 | "properties": {
621 | "clientCertificateCommonNames": [],
622 | "clientCertificateThumbprints": [],
623 | "clusterState": "Default",
624 | "diagnosticsStorageAccountConfig": {
625 | "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]",
626 | "protectedAccountKeyName": "StorageAccountKey1",
627 | "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]",
628 | "storageAccountName": "[parameters('supportLogStorageAccountName')]",
629 | "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]"
630 | },
631 | "fabricSettings": [],
632 | "managementEndpoint": "[concat('http://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]",
633 | "nodeTypes": [
634 | {
635 | "name": "[parameters('vmNodeType0Name')]",
636 | "applicationPorts": {
637 | "endPort": "[parameters('nt0applicationEndPort')]",
638 | "startPort": "[parameters('nt0applicationStartPort')]"
639 | },
640 | "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]",
641 | "durabilityLevel": "Bronze",
642 | "ephemeralPorts": {
643 | "endPort": "[parameters('nt0ephemeralEndPort')]",
644 | "startPort": "[parameters('nt0ephemeralStartPort')]"
645 | },
646 | "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]",
647 | "isPrimary": true,
648 | "vmInstanceCount": "[parameters('nt0InstanceCount')]"
649 | }
650 | ],
651 | "provisioningState": "Default",
652 | "reliabilityLevel": "Silver",
653 | "upgradeMode": "Automatic",
654 | "vmImage": "Windows"
655 | },
656 | "tags": {
657 | "resourceType": "Service Fabric",
658 | "clusterName": "[parameters('clusterName')]"
659 | }
660 | }
661 | ],
662 | "outputs": {
663 | "clusterProperties": {
664 | "value": "[reference(parameters('clusterName'))]",
665 | "type": "object"
666 | }
667 | }
668 | }
--------------------------------------------------------------------------------
/templates/networking/template_existingvnet.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "clusterLocation": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Location of the Cluster"
9 | }
10 | },
11 | "clusterName": {
12 | "type": "string",
13 | "defaultValue": "Cluster",
14 | "metadata": {
15 | "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only"
16 | }
17 | },
18 | "nt0applicationStartPort": {
19 | "type": "int",
20 | "defaultValue": 20000
21 | },
22 | "nt0applicationEndPort": {
23 | "type": "int",
24 | "defaultValue": 30000
25 | },
26 | "nt0ephemeralStartPort": {
27 | "type": "int",
28 | "defaultValue": 49152
29 | },
30 | "nt0ephemeralEndPort": {
31 | "type": "int",
32 | "defaultValue": 65534
33 | },
34 | "nt0fabricTcpGatewayPort": {
35 | "type": "int",
36 | "defaultValue": 19000
37 | },
38 | "nt0fabricHttpGatewayPort": {
39 | "type": "int",
40 | "defaultValue": 19080
41 | },
42 | "subnet0Name": {
43 | "type": "string",
44 | "defaultValue": "default"
45 | },
46 | "existingVNetRGName": {
47 | "type": "string",
48 | "defaultValue": "ExistingRG"
49 | },
50 | "existingVNetName": {
51 | "type": "string",
52 | "defaultValue": "ExistingRG-vnet"
53 | },
54 | /*
55 | "subnet0Name": {
56 | "type": "string",
57 | "defaultValue": "Subnet-0"
58 | },
59 | "subnet0Prefix": {
60 | "type": "string",
61 | "defaultValue": "10.0.0.0/24"
62 | },*/
63 | "computeLocation": {
64 | "type": "string"
65 | },
66 | "vmStorageAccountName": {
67 | "type": "string"
68 | },
69 | "publicIPAddressName": {
70 | "type": "string",
71 | "defaultValue": "PublicIP-VM"
72 | },
73 | "publicIPAddressType": {
74 | "type": "string",
75 | "allowedValues": [
76 | "Dynamic"
77 | ],
78 | "defaultValue": "Dynamic"
79 | },
80 | "vmStorageAccountContainerName": {
81 | "type": "string",
82 | "defaultValue": "vhds"
83 | },
84 | "adminUserName": {
85 | "type": "string",
86 | "defaultValue": "testadm",
87 | "metadata": {
88 | "description": "Remote desktop user Id"
89 | }
90 | },
91 | "adminPassword": {
92 | "type": "securestring",
93 | "metadata": {
94 | "description": "Remote desktop user password. Must be a strong password"
95 | }
96 | },
97 | "virtualNetworkName": {
98 | "type": "string",
99 | "defaultValue": "VNet"
100 | },
101 | "addressPrefix": {
102 | "type": "string",
103 | "defaultValue": "10.0.0.0/16"
104 | },
105 | "dnsName": {
106 | "type": "string"
107 | },
108 | "nicName": {
109 | "type": "string",
110 | "defaultValue": "NIC"
111 | },
112 | "lbName": {
113 | "type": "string",
114 | "defaultValue": "LoadBalancer"
115 | },
116 | "lbIPName": {
117 | "type": "string",
118 | "defaultValue": "PublicIP-LB-FE"
119 | },
120 | "overProvision": {
121 | "type": "string",
122 | "defaultValue": "false"
123 | },
124 | "vmImagePublisher": {
125 | "type": "string",
126 | "defaultValue": "MicrosoftWindowsServer"
127 | },
128 | "vmImageOffer": {
129 | "type": "string",
130 | "defaultValue": "WindowsServer"
131 | },
132 | "vmImageSku": {
133 | "type": "string",
134 | "defaultValue": "2012-R2-Datacenter"
135 | },
136 | "vmImageVersion": {
137 | "type": "string",
138 | "defaultValue": "latest"
139 | },
140 | "loadBalancedAppPort1": {
141 | "type": "int",
142 | "defaultValue": 80,
143 | "metadata": {
144 | "description": "Input endpoint1 for the application to use. Replace it with what your application uses"
145 | }
146 | },
147 | "storageAccountType": {
148 | "type": "string",
149 | "allowedValues": [
150 | "Standard_LRS",
151 | "Standard_GRS"
152 | ],
153 | "defaultValue": "Standard_LRS",
154 | "metadata": {
155 | "description": "Replication option for the VM image storage account"
156 | }
157 | },
158 | "supportLogStorageAccountType": {
159 | "type": "string",
160 | "allowedValues": [
161 | "Standard_LRS",
162 | "Standard_GRS"
163 | ],
164 | "defaultValue": "Standard_LRS",
165 | "metadata": {
166 | "description": "Replication option for the support log storage account"
167 | }
168 | },
169 | "supportLogStorageAccountName": {
170 | "type": "string",
171 | "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]",
172 | "metadata": {
173 | "description": "Name for the storage account that contains support logs from the cluster"
174 | }
175 | },
176 | "applicationDiagnosticsStorageAccountType": {
177 | "type": "string",
178 | "allowedValues": [
179 | "Standard_LRS",
180 | "Standard_GRS"
181 | ],
182 | "defaultValue": "Standard_LRS",
183 | "metadata": {
184 | "description": "Replication option for the application diagnostics storage account"
185 | }
186 | },
187 | "applicationDiagnosticsStorageAccountName": {
188 | "type": "string",
189 | "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]",
190 | "metadata": {
191 | "description": "Name for the storage account that contains application diagnostics data from the cluster"
192 | }
193 | },
194 | "nt0InstanceCount": {
195 | "type": "int",
196 | "defaultValue": 5,
197 | "metadata": {
198 | "description": "Instance count for node type"
199 | }
200 | },
201 | "vmNodeType0Name": {
202 | "type": "string",
203 | "defaultValue": "Node1",
204 | "maxLength": 9
205 | },
206 | "vmNodeType0Size": {
207 | "type": "string",
208 | "defaultValue": "Standard_D1_v2"
209 | }
210 | },
211 | "variables": {
212 | "vmssApiVersion": "2016-03-30",
213 | "lbApiVersion": "2015-06-15",
214 | "vNetApiVersion": "2015-06-15",
215 | "storageApiVersion": "2016-01-01",
216 | "publicIPApiVersion": "2015-06-15",
217 | /*"vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",*/
218 | "vnetID": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('existingVNetRGName'), '/providers/Microsoft.Network/virtualNetworks/', parameters('existingVNetName'))]",
219 | "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]",
220 | "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]",
221 | "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]",
222 | "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]",
223 | "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]",
224 | "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]",
225 | "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]",
226 | "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]",
227 | "uniqueStringArray0": [
228 | "[concat(variables('vmStorageAccountName0'), '0')]",
229 | "[concat(variables('vmStorageAccountName0'), '1')]",
230 | "[concat(variables('vmStorageAccountName0'), '2')]",
231 | "[concat(variables('vmStorageAccountName0'), '3')]",
232 | "[concat(variables('vmStorageAccountName0'), '4')]"
233 | ]
234 | },
235 | "resources": [
236 | {
237 | "apiVersion": "[variables('storageApiVersion')]",
238 | "type": "Microsoft.Storage/storageAccounts",
239 | "name": "[parameters('supportLogStorageAccountName')]",
240 | "location": "[parameters('computeLocation')]",
241 | "dependsOn": [],
242 | "properties": {},
243 | "kind": "Storage",
244 | "sku": {
245 | "name": "[parameters('supportLogStorageAccountType')]"
246 | },
247 | "tags": {
248 | "resourceType": "Service Fabric",
249 | "clusterName": "[parameters('clusterName')]"
250 | }
251 | },
252 | {
253 | "apiVersion": "[variables('storageApiVersion')]",
254 | "type": "Microsoft.Storage/storageAccounts",
255 | "name": "[parameters('applicationDiagnosticsStorageAccountName')]",
256 | "location": "[parameters('computeLocation')]",
257 | "dependsOn": [],
258 | "properties": {},
259 | "kind": "Storage",
260 | "sku": {
261 | "name": "[parameters('applicationDiagnosticsStorageAccountType')]"
262 | },
263 | "tags": {
264 | "resourceType": "Service Fabric",
265 | "clusterName": "[parameters('clusterName')]"
266 | }
267 | },
268 | /*
269 | {
270 | "apiVersion": "[variables('vNetApiVersion')]",
271 | "type": "Microsoft.Network/virtualNetworks",
272 | "name": "[parameters('virtualNetworkName')]",
273 | "location": "[parameters('computeLocation')]",
274 | "properties": {
275 | "addressSpace": {
276 | "addressPrefixes": [
277 | "[parameters('addressPrefix')]"
278 | ]
279 | },
280 | "subnets": [
281 | {
282 | "name": "[parameters('subnet0Name')]",
283 | "properties": {
284 | "addressPrefix": "[parameters('subnet0Prefix')]"
285 | }
286 | }
287 | ]
288 | },
289 | "tags": {
290 | "resourceType": "Service Fabric",
291 | "clusterName": "[parameters('clusterName')]"
292 | }
293 | },
294 | */
295 | {
296 | "apiVersion": "[variables('publicIPApiVersion')]",
297 | "type": "Microsoft.Network/publicIPAddresses",
298 | "name": "[concat(parameters('lbIPName'),'-','0')]",
299 | "location": "[parameters('computeLocation')]",
300 | "properties": {
301 | "dnsSettings": {
302 | "domainNameLabel": "[parameters('dnsName')]"
303 | },
304 | "publicIPAllocationMethod": "Dynamic"
305 | },
306 | "tags": {
307 | "resourceType": "Service Fabric",
308 | "clusterName": "[parameters('clusterName')]"
309 | }
310 | },
311 | {
312 | "apiVersion": "[variables('lbApiVersion')]",
313 | "type": "Microsoft.Network/loadBalancers",
314 | "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]",
315 | "location": "[parameters('computeLocation')]",
316 | "dependsOn": [
317 | "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]"
318 | ],
319 | "properties": {
320 | "frontendIPConfigurations": [
321 | {
322 | "name": "LoadBalancerIPConfig",
323 | "properties": {
324 | "publicIPAddress": {
325 | "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]"
326 | }
327 | }
328 | }
329 | ],
330 | "backendAddressPools": [
331 | {
332 | "name": "LoadBalancerBEAddressPool",
333 | "properties": {}
334 | }
335 | ],
336 | "loadBalancingRules": [
337 | {
338 | "name": "LBRule",
339 | "properties": {
340 | "backendAddressPool": {
341 | "id": "[variables('lbPoolID0')]"
342 | },
343 | "backendPort": "[parameters('nt0fabricTcpGatewayPort')]",
344 | "enableFloatingIP": "false",
345 | "frontendIPConfiguration": {
346 | "id": "[variables('lbIPConfig0')]"
347 | },
348 | "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]",
349 | "idleTimeoutInMinutes": "5",
350 | "probe": {
351 | "id": "[variables('lbProbeID0')]"
352 | },
353 | "protocol": "tcp"
354 | }
355 | },
356 | {
357 | "name": "LBHttpRule",
358 | "properties": {
359 | "backendAddressPool": {
360 | "id": "[variables('lbPoolID0')]"
361 | },
362 | "backendPort": "[parameters('nt0fabricHttpGatewayPort')]",
363 | "enableFloatingIP": "false",
364 | "frontendIPConfiguration": {
365 | "id": "[variables('lbIPConfig0')]"
366 | },
367 | "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]",
368 | "idleTimeoutInMinutes": "5",
369 | "probe": {
370 | "id": "[variables('lbHttpProbeID0')]"
371 | },
372 | "protocol": "tcp"
373 | }
374 | },
375 | {
376 | "name": "AppPortLBRule1",
377 | "properties": {
378 | "backendAddressPool": {
379 | "id": "[variables('lbPoolID0')]"
380 | },
381 | "backendPort": "[parameters('loadBalancedAppPort1')]",
382 | "enableFloatingIP": "false",
383 | "frontendIPConfiguration": {
384 | "id": "[variables('lbIPConfig0')]"
385 | },
386 | "frontendPort": "[parameters('loadBalancedAppPort1')]",
387 | "idleTimeoutInMinutes": "5",
388 | "probe": {
389 | "id": "[concat(variables('lbID0'),'/probes/AppPortProbe1')]"
390 | },
391 | "protocol": "tcp"
392 | }
393 | }
394 | ],
395 | "probes": [
396 | {
397 | "name": "FabricGatewayProbe",
398 | "properties": {
399 | "intervalInSeconds": 5,
400 | "numberOfProbes": 2,
401 | "port": "[parameters('nt0fabricTcpGatewayPort')]",
402 | "protocol": "tcp"
403 | }
404 | },
405 | {
406 | "name": "FabricHttpGatewayProbe",
407 | "properties": {
408 | "intervalInSeconds": 5,
409 | "numberOfProbes": 2,
410 | "port": "[parameters('nt0fabricHttpGatewayPort')]",
411 | "protocol": "tcp"
412 | }
413 | },
414 | {
415 | "name": "AppPortProbe1",
416 | "properties": {
417 | "intervalInSeconds": 5,
418 | "numberOfProbes": 2,
419 | "port": "[parameters('loadBalancedAppPort1')]",
420 | "protocol": "tcp"
421 | }
422 | }
423 | ],
424 | "inboundNatPools": [
425 | {
426 | "name": "LoadBalancerBEAddressNatPool",
427 | "properties": {
428 | "backendPort": "3389",
429 | "frontendIPConfiguration": {
430 | "id": "[variables('lbIPConfig0')]"
431 | },
432 | "frontendPortRangeEnd": "4500",
433 | "frontendPortRangeStart": "3389",
434 | "protocol": "tcp"
435 | }
436 | }
437 | ]
438 | },
439 | "tags": {
440 | "resourceType": "Service Fabric",
441 | "clusterName": "[parameters('clusterName')]"
442 | }
443 | },
444 | {
445 | "apiVersion": "[variables('storageApiVersion')]",
446 | "type": "Microsoft.Storage/storageAccounts",
447 | "name": "[variables('uniqueStringArray0')[copyIndex()]]",
448 | "location": "[parameters('computeLocation')]",
449 | "dependsOn": [],
450 | "properties": {},
451 | "copy": {
452 | "name": "storageLoop",
453 | "count": 5
454 | },
455 | "kind": "Storage",
456 | "sku": {
457 | "name": "[parameters('storageAccountType')]"
458 | },
459 | "tags": {
460 | "resourceType": "Service Fabric",
461 | "clusterName": "[parameters('clusterName')]"
462 | }
463 | },
464 | {
465 | "apiVersion": "[variables('vmssApiVersion')]",
466 | "type": "Microsoft.Compute/virtualMachineScaleSets",
467 | "name": "[parameters('vmNodeType0Name')]",
468 | "location": "[parameters('computeLocation')]",
469 | "dependsOn": [
470 | /* "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", */
471 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0])]",
472 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1])]",
473 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]",
474 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]",
475 | "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]",
476 | "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]",
477 | "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]",
478 | "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]"
479 | ],
480 | "properties": {
481 | "overprovision": "[parameters('overProvision')]",
482 | "upgradePolicy": {
483 | "mode": "Automatic"
484 | },
485 | "virtualMachineProfile": {
486 | "extensionProfile": {
487 | "extensions": [
488 | {
489 | "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricNode')]",
490 | "properties": {
491 | "type": "ServiceFabricNode",
492 | "autoUpgradeMinorVersion": false,
493 | "protectedSettings": {
494 | "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]",
495 | "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]"
496 | },
497 | "publisher": "Microsoft.Azure.ServiceFabric",
498 | "settings": {
499 | "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]",
500 | "nodeTypeRef": "[parameters('vmNodeType0Name')]",
501 | "dataPath": "D:\\\\SvcFab",
502 | "durabilityLevel": "Bronze"
503 | },
504 | "typeHandlerVersion": "1.0"
505 | }
506 | },
507 | {
508 | "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]",
509 | "properties": {
510 | "type": "IaaSDiagnostics",
511 | "autoUpgradeMinorVersion": true,
512 | "protectedSettings": {
513 | "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]",
514 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]",
515 | "storageAccountEndPoint": "https://core.windows.net/"
516 | },
517 | "publisher": "Microsoft.Azure.Diagnostics",
518 | "settings": {
519 | "WadCfg": {
520 | "DiagnosticMonitorConfiguration": {
521 | "overallQuotaInMB": "50000",
522 | "EtwProviders": {
523 | "EtwEventSourceProviderConfiguration": [
524 | {
525 | "provider": "Microsoft-ServiceFabric-Actors",
526 | "scheduledTransferKeywordFilter": "1",
527 | "scheduledTransferPeriod": "PT5M",
528 | "DefaultEvents": {
529 | "eventDestination": "ServiceFabricReliableActorEventTable"
530 | }
531 | },
532 | {
533 | "provider": "Microsoft-ServiceFabric-Services",
534 | "scheduledTransferPeriod": "PT5M",
535 | "DefaultEvents": {
536 | "eventDestination": "ServiceFabricReliableServiceEventTable"
537 | }
538 | }
539 | ],
540 | "EtwManifestProviderConfiguration": [
541 | {
542 | "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8",
543 | "scheduledTransferLogLevelFilter": "Information",
544 | "scheduledTransferKeywordFilter": "4611686018427387904",
545 | "scheduledTransferPeriod": "PT5M",
546 | "DefaultEvents": {
547 | "eventDestination": "ServiceFabricSystemEventTable"
548 | }
549 | }
550 | ]
551 | }
552 | }
553 | },
554 | "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]"
555 | },
556 | "typeHandlerVersion": "1.5"
557 | }
558 | }
559 | ]
560 | },
561 | "networkProfile": {
562 | "networkInterfaceConfigurations": [
563 | {
564 | "name": "[concat(parameters('nicName'), '-0')]",
565 | "properties": {
566 | "ipConfigurations": [
567 | {
568 | "name": "[concat(parameters('nicName'),'-',0)]",
569 | "properties": {
570 | "loadBalancerBackendAddressPools": [
571 | {
572 | "id": "[variables('lbPoolID0')]"
573 | }
574 | ],
575 | "loadBalancerInboundNatPools": [
576 | {
577 | "id": "[variables('lbNatPoolID0')]"
578 | }
579 | ],
580 | "subnet": {
581 | "id": "[variables('subnet0Ref')]"
582 | }
583 | }
584 | }
585 | ],
586 | "primary": true
587 | }
588 | }
589 | ]
590 | },
591 | "osProfile": {
592 | "adminPassword": "[parameters('adminPassword')]",
593 | "adminUsername": "[parameters('adminUsername')]",
594 | "computernamePrefix": "[parameters('vmNodeType0Name')]"
595 | },
596 | "storageProfile": {
597 | "imageReference": {
598 | "publisher": "[parameters('vmImagePublisher')]",
599 | "offer": "[parameters('vmImageOffer')]",
600 | "sku": "[parameters('vmImageSku')]",
601 | "version": "[parameters('vmImageVersion')]"
602 | },
603 | "osDisk": {
604 | "vhdContainers": [
605 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
606 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
607 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
608 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]",
609 | "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]"
610 | ],
611 | "name": "vmssosdisk",
612 | "caching": "ReadOnly",
613 | "createOption": "FromImage"
614 | }
615 | }
616 | }
617 | },
618 | "sku": {
619 | "name": "[parameters('vmNodeType0Size')]",
620 | "capacity": "[parameters('nt0InstanceCount')]",
621 | "tier": "Standard"
622 | },
623 | "tags": {
624 | "resourceType": "Service Fabric",
625 | "clusterName": "[parameters('clusterName')]"
626 | }
627 | },
628 | {
629 | "apiVersion": "2016-09-01",
630 | "type": "Microsoft.ServiceFabric/clusters",
631 | "name": "[parameters('clusterName')]",
632 | "location": "[parameters('clusterLocation')]",
633 | "dependsOn": [
634 | "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]"
635 | ],
636 | "properties": {
637 | "clientCertificateCommonNames": [],
638 | "clientCertificateThumbprints": [],
639 | "clusterState": "Default",
640 | "diagnosticsStorageAccountConfig": {
641 | "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]",
642 | "protectedAccountKeyName": "StorageAccountKey1",
643 | "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]",
644 | "storageAccountName": "[parameters('supportLogStorageAccountName')]",
645 | "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]"
646 | },
647 | "fabricSettings": [],
648 | "managementEndpoint": "[concat('http://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]",
649 | "nodeTypes": [
650 | {
651 | "name": "[parameters('vmNodeType0Name')]",
652 | "applicationPorts": {
653 | "endPort": "[parameters('nt0applicationEndPort')]",
654 | "startPort": "[parameters('nt0applicationStartPort')]"
655 | },
656 | "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]",
657 | "durabilityLevel": "Bronze",
658 | "ephemeralPorts": {
659 | "endPort": "[parameters('nt0ephemeralEndPort')]",
660 | "startPort": "[parameters('nt0ephemeralStartPort')]"
661 | },
662 | "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]",
663 | "isPrimary": true,
664 | "vmInstanceCount": "[parameters('nt0InstanceCount')]"
665 | }
666 | ],
667 | "provisioningState": "Default",
668 | "reliabilityLevel": "Silver",
669 | "upgradeMode": "Automatic",
670 | "vmImage": "Windows"
671 | },
672 | "tags": {
673 | "resourceType": "Service Fabric",
674 | "clusterName": "[parameters('clusterName')]"
675 | }
676 | }
677 | ],
678 | "outputs": {
679 | "clusterProperties": {
680 | "value": "[reference(parameters('clusterName'))]",
681 | "type": "object"
682 | }
683 | }
684 | }
--------------------------------------------------------------------------------