├── .gitignore
├── README.md
├── azure-powershell-windows
├── EventStoreScriptExtensionProvisionFile.ps1
├── ProvisionEventStore.ps1
└── README.md
├── azure-resource-manager
├── EventStoreCluster.sln
├── EventStoreCluster
│ ├── CreateStripedDataDisk.ps1
│ ├── Deployment.targets
│ ├── EventStoreCluster.deployproj
│ ├── Scripts
│ │ └── Deploy-AzureResourceGroup.ps1
│ ├── Templates
│ │ ├── azuredeploy.json
│ │ ├── azuredeploy.param.dev.json
│ │ ├── cluster-nodes-0disk-resources.json
│ │ ├── cluster-nodes-16disk-resources.json
│ │ ├── cluster-nodes-2disk-resources.json
│ │ ├── cluster-nodes-4disk-resources.json
│ │ ├── cluster-nodes-8disk-resources.json
│ │ ├── create-data-disks.ps1
│ │ ├── data-nodes-0disk-resources.json
│ │ ├── empty-resources.json
│ │ ├── eventstore-ubuntu-sources.txt
│ │ ├── eventstore-windows-sources.csv
│ │ ├── install-eventstore.ps1
│ │ ├── install-nginx.ps1
│ │ ├── jumpbox-resources.json
│ │ ├── master.ps1
│ │ ├── shared-resources.json
│ │ └── tmpl
│ │ │ └── data-nodes.yml
│ └── Tools
│ │ ├── AzCopy.exe
│ │ ├── Microsoft.Data.Edm.dll
│ │ ├── Microsoft.Data.OData.dll
│ │ ├── Microsoft.Data.Services.Client.dll
│ │ ├── Microsoft.WindowsAzure.Storage.DataMovement.dll
│ │ └── Microsoft.WindowsAzure.Storage.dll
└── README.md
└── vagrant-eventstore-cluster
├── .gitignore
├── Berksfile
├── LICENSE
├── README.md
└── Vagrantfile
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opensdf
80 | *.sdf
81 | *.cachefile
82 |
83 | # Visual Studio profiler
84 | *.psess
85 | *.vsp
86 | *.vspx
87 | *.sap
88 |
89 | # TFS 2012 Local Workspace
90 | $tf/
91 |
92 | # Guidance Automation Toolkit
93 | *.gpState
94 |
95 | # ReSharper is a .NET coding add-in
96 | _ReSharper*/
97 | *.[Rr]e[Ss]harper
98 | *.DotSettings.user
99 |
100 | # JustCode is a .NET coding add-in
101 | .JustCode
102 |
103 | # TeamCity is a build add-in
104 | _TeamCity*
105 |
106 | # DotCover is a Code Coverage Tool
107 | *.dotCover
108 |
109 | # NCrunch
110 | _NCrunch_*
111 | .*crunch*.local.xml
112 | nCrunchTemp_*
113 |
114 | # MightyMoose
115 | *.mm.*
116 | AutoTest.Net/
117 |
118 | # Web workbench (sass)
119 | .sass-cache/
120 |
121 | # Installshield output folder
122 | [Ee]xpress/
123 |
124 | # DocProject is a documentation generator add-in
125 | DocProject/buildhelp/
126 | DocProject/Help/*.HxT
127 | DocProject/Help/*.HxC
128 | DocProject/Help/*.hhc
129 | DocProject/Help/*.hhk
130 | DocProject/Help/*.hhp
131 | DocProject/Help/Html2
132 | DocProject/Help/html
133 |
134 | # Click-Once directory
135 | publish/
136 |
137 | # Publish Web Output
138 | *.[Pp]ublish.xml
139 | *.azurePubxml
140 | # TODO: Comment the next line if you want to checkin your web deploy settings
141 | # but database connection strings (with potential passwords) will be unencrypted
142 | *.pubxml
143 | *.publishproj
144 |
145 | # NuGet Packages
146 | *.nupkg
147 | # The packages folder can be ignored because of Package Restore
148 | **/packages/*
149 | # except build/, which is used as an MSBuild target.
150 | !**/packages/build/
151 | # Uncomment if necessary however generally it will be regenerated when needed
152 | #!**/packages/repositories.config
153 |
154 | # Windows Azure Build Output
155 | csx/
156 | *.build.csdef
157 |
158 | # Windows Azure Emulator
159 | efc/
160 | rfc/
161 |
162 | # Windows Store app package directory
163 | AppPackages/
164 |
165 | # Visual Studio cache files
166 | # files ending in .cache can be ignored
167 | *.[Cc]ache
168 | # but keep track of directories ending in .cache
169 | !*.[Cc]ache/
170 |
171 | # Others
172 | ClientBin/
173 | [Ss]tyle[Cc]op.*
174 | ~$*
175 | *~
176 | *.dbmdl
177 | *.dbproj.schemaview
178 | *.pfx
179 | *.publishsettings
180 | node_modules/
181 | orleans.codegen.cs
182 |
183 | # RIA/Silverlight projects
184 | Generated_Code/
185 |
186 | # Backup & report files from converting an old project file
187 | # to a newer Visual Studio version. Backup files are not needed,
188 | # because we have git ;-)
189 | _UpgradeReport_Files/
190 | Backup*/
191 | UpgradeLog*.XML
192 | UpgradeLog*.htm
193 |
194 | # SQL Server files
195 | *.mdf
196 | *.ldf
197 |
198 | # Business Intelligence projects
199 | *.rdl.data
200 | *.bim.layout
201 | *.bim_*.settings
202 |
203 | # Microsoft Fakes
204 | FakesAssemblies/
205 |
206 | # GhostDoc plugin setting file
207 | *.GhostDoc.xml
208 |
209 | # Node.js Tools for Visual Studio
210 | .ntvs_analysis.dat
211 |
212 | # Visual Studio 6 build log
213 | *.plg
214 |
215 | # Visual Studio 6 workspace options file
216 | *.opt
217 |
218 | # Visual Studio LightSwitch build output
219 | **/*.HTMLClient/GeneratedArtifacts
220 | **/*.DesktopClient/GeneratedArtifacts
221 | **/*.DesktopClient/ModelManifest.xml
222 | **/*.Server/GeneratedArtifacts
223 | **/*.Server/ModelManifest.xml
224 | _Pvt_Extensions
225 |
226 | # Paket dependency manager
227 | .paket/paket.exe
228 |
229 | # FAKE - F# Make
230 | .fake/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EventStore DevOps
2 |
3 | This project is used to setup an [Event Store](https://geteventstore.com/) cluster on Azure. The preferred method is to use the azure resource manager approach.
4 |
5 | * **azure-resource-manager** - Use Azure Resource Manager to create a cluster
6 | * **vagrant-eventstore-cluster** - *not actively maintained* create a local Event Store cluster in vagrant and virtual box. Cloned from [seif/vagrant-eventstore-cluster](https://github.com/seif/vagrant-eventstore-cluster) and now references my fork of [eventstore-cookbook](https://github.com/pbolduc/eventstore-cookbook)
7 | * **azure-powershell-Windows** - *depreicated* create an arbitrary sized Event Store cluster on Windows hosts on Windows Azure
--------------------------------------------------------------------------------
/azure-powershell-windows/EventStoreScriptExtensionProvisionFile.ps1:
--------------------------------------------------------------------------------
1 | param (
2 | [Int]
3 | $clusterSize,
4 | [string]
5 | $VMName,
6 | [Int]
7 | $nodeNumber,
8 | [Int]
9 | $IntIp,
10 | [Int]
11 | $ExtIp,
12 | [Int]
13 | $IntTcpPort = 1112,
14 | [Int]
15 | $IntHttpPort = 2112,
16 | [Int]
17 | $ExtTcpPort = 1113,
18 | [Int]
19 | $ExtHttpPort = 2113
20 | )
21 |
22 |
23 | function Extract-ZipFile($file, $destination)
24 | {
25 | if (![System.IO.Directory]::Exists($destination)) {
26 | [System.IO.Directory]::CreateDirectory($destination)
27 | }
28 | $shell = new-object -com shell.application
29 | $zip = $shell.NameSpace($file)
30 |
31 | foreach($item in $zip.items()) {
32 | $shell.Namespace($destination).copyhere($item)
33 | }
34 | }
35 |
36 | function Install-Chocolatey($InstallToPath) {
37 | $env:ChocolateyInstall = $InstallToPath
38 | iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
39 | }
40 |
41 | function Download-EventStore($DownloadUrl, $SaveToPath) {
42 | $client = new-object System.Net.WebClient
43 | $client.DownloadFile($DownloadUrl, $SaveToPath)
44 | }
45 |
46 | function Format-DataDisks() {
47 | $Interleave = 65536 # is this the best value for EventStore?
48 | $uninitializedDisks = Get-PhysicalDisk -CanPool $true
49 |
50 | $poolDisks = $uninitializedDisks
51 | $numberOfDisksPerPool = $poolDisks.Length
52 |
53 | $poolName = "Data Storage Pool"
54 | $newPool = New-StoragePool -FriendlyName $poolName -StorageSubSystemFriendlyName "Storage Spaces*" -PhysicalDisks $poolDisks
55 |
56 | $virtualDiskJob = New-VirtualDisk -StoragePoolFriendlyName $poolName -FriendlyName $poolName -ResiliencySettingName Simple -ProvisioningType Fixed -Interleave $Interleave `
57 | -NumberOfDataCopies 1 -NumberOfColumns $numberOfDisksPerPool -UseMaximumSize -AsJob
58 |
59 | Receive-Job -Job $virtualDiskJobs -Wait
60 | Wait-Job -Job $virtualDiskJobs
61 | Remove-Job -Job $virtualDiskJobs
62 |
63 | # Initialize and format the virtual disks on the pools
64 | $formatted = Get-VirtualDisk | Initialize-Disk -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -Confirm:$false
65 |
66 | # Create the data directory
67 | $formatted | ForEach-Object {
68 | # Get current drive letter.
69 | $downloadDriveLetter = $_.DriveLetter
70 |
71 | # Create the data directory
72 | $dataDirectory = "$($downloadDriveLetter):\Data"
73 |
74 | New-Item $dataDirectory -Type directory -Force | Out-Null
75 | }
76 |
77 | # Dive time to the storage service to pick up the changes
78 | Start-Sleep -Seconds 60
79 | }
80 |
81 | function New-EventStoreConfigFile() {
82 |
83 | $seeds = @()
84 | for ($n = 1; $n -le $clusterSize; $n++) {
85 | $nodeName = $VMName + "-" + $n
86 | if ($nodeName -ne $env:COMPUTERNAME) {
87 | do {
88 | # the other nodes may not be running yet, wait for them to return an ip address
89 | $ip = (Resolve-DnsName $nodeName -Type A -ErrorAction SilentlyContinue).IPAddress
90 | } while ($ip -eq $null)
91 |
92 | #
93 | $seeds += "'" + $ip + ":" + $IntHttpPort + "'"
94 | }
95 | }
96 |
97 | $gossipSeed = $seeds -join ','
98 |
99 | # this is a bit of a hack that depends on the BGInfo plugin. Is there a better way to determine this?
100 | #$publicIp = PS C:\Users\eventstore> (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Azure\BGInfo").PublicIp
101 |
102 | $configFile = "C:\EventStore\EventStore-Config.yaml"
103 | $ipAddress = (Resolve-DnsName $env:COMPUTERNAME -Type A).IPAddress
104 |
105 | $IntIp = $ipAddress
106 | $ExtIp = $ipAddress
107 |
108 | "# EventStore configuration file. Created at: $(Get-Date -Format 'u')" | Out-File -FilePath $configFile
109 | "Db: F:\Data\eventstore" | Out-File -FilePath $configFile -Append
110 | "Log: D:\Logs\eventstore" | Out-File -FilePath $configFile -Append
111 | "IntIp: $IntIp" | Out-File -FilePath $configFile -Append
112 | "ExtIp: $ExtIp" | Out-File -FilePath $configFile -Append
113 | "IntTcpPort: $IntTcpPort" | Out-File -FilePath $configFile -Append
114 | "IntHttpPort: $IntHttpPort" | Out-File -FilePath $configFile -Append
115 | "ExtTcpPort: $ExtTcpPort" | Out-File -FilePath $configFile -Append
116 | "ExtHttpPort: $ExtHttpPort" | Out-File -FilePath $configFile -Append
117 | "DiscoverViaDns: false" | Out-File -FilePath $configFile -Append
118 | "GossipSeed: [$gossipSeed]" | Out-File -FilePath $configFile -Append
119 | "ClusterSize: $clusterSize" | Out-File -FilePath $configFile -Append
120 | }
121 |
122 | #
123 | # Azure VM's have Temporary Storage on D:\ - Store only log data / temp files there
124 | #
125 |
126 | Format-DataDisks
127 |
128 | Install-Chocolatey -InstallToPath "C:\Chocolatey"
129 | Download-EventStore -DownloadUrl "http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.2.zip" -SaveToPath "D:\EventStore-OSS-Win-v3.0.2.zip"
130 | Extract-ZipFile -file "D:\EventStore-OSS-Win-v3.0.2.zip" -destination "C:\EventStore\v3.0.2\"
131 |
132 | New-EventStoreConfigFile
133 |
134 | choco install nssm --version 2.24.0
135 | #choco install logstash
136 | #choco install timberwinr
137 |
138 | #
139 | #
140 | #
141 | $ipAddress = (Resolve-DnsName $env:COMPUTERNAME -Type A).IPAddress
142 |
143 | #Database Node Internal HTTP Interface (open source and commercial)
144 | netsh http add urlacl url=http://${ipAddress}:${IntHttpPort}/ user="NT AUTHORITY\LOCAL SERVICE"
145 |
146 | # Database Node External HTTP Interface (open source and commercial)
147 | netsh http add urlacl url=http://${ipAddress}:${ExtHttpPort}/ user="NT AUTHORITY\LOCAL SERVICE"
148 |
149 | # Manager Node Internal HTTP Interface (commercial only)
150 | #netsh http add urlacl url=http://$ipAddress:30777/ user="NT AUTHORITY\LOCAL SERVICE"
151 |
152 | # Manager Node External HTTP Interface (commercial only)
153 | #netsh http add urlacl url=http://$ipAddress:30778/ user="NT AUTHORITY\LOCAL SERVICE"
154 |
155 | # Added all the ports, but think I only require the 2112,2113 ports
156 | New-NetFirewallRule -Name Allow_EventStore_Int_In -DisplayName "Allow inbound Internal Event Store traffic" -Protocol TCP -Direction Inbound -Action Allow -LocalPort ${IntTcpPort},${IntHttpPort}
157 | New-NetFirewallRule -Name Allow_EventStore_Ext_In -DisplayName "Allow inbound External Event Store traffic" -Protocol TCP -Direction Inbound -Action Allow -LocalPort ${ExtTcpPort},${ExtHttpPort}
158 |
159 | C:\Chocolatey\lib\NSSM.2.24.0\Tools\nssm-2.24\win64\nssm.exe install EventStore C:\EventStore\v3.0.2\EventStore.ClusterNode.exe --config C:\EventStore\EventStore-Config.yaml
160 | C:\Chocolatey\lib\NSSM.2.24.0\Tools\nssm-2.24\win64\nssm.exe set EventStore Description "The EventStore service."
161 |
162 |
163 | #net start EventStore
--------------------------------------------------------------------------------
/azure-powershell-windows/ProvisionEventStore.ps1:
--------------------------------------------------------------------------------
1 | # ProvisionEventStore.ps1
2 |
3 | <#
4 | .SYNOPSIS
5 | .DESCRIPTION
6 | .EXAMPLE
7 | #>
8 |
9 | # http://azure.microsoft.com/en-us/documentation/articles/install-configure-powershell/
10 | # Add-AzureAccount
11 |
12 | param
13 | (
14 | [Int]$ClusterSize,
15 | [Int]$DataDiskSize = 0,
16 | [String]$Location,
17 | [String]$InstanceSize,
18 | [String]$username,
19 | [String]$password,
20 | [String]$ServiceName,
21 | [String]$VMName,
22 | [String]$ImageName,
23 | [String]$AffinityGroup,
24 | [String]$TargetStorageAccountName,
25 | [Int]$MaxDisksPerStorageAccount = 40,
26 | [Int]$MaxDataDisksPerVirtualMachine = 0,
27 | [String]$AvailabilitySetName,
28 | [String]$VNetName,
29 | [String]$VNetSubnetName,
30 | [String]$CustomScriptExtensionStorageAccountName,
31 | [String]$CustomScriptExtensionStorageAccountKey,
32 | [String]$CustomScriptExtensionContainerName,
33 | [String]$CustomScriptExtensionProvisionFile
34 | )
35 |
36 | function Get-RandomStorageAccountName {
37 | param (
38 | [Parameter(Mandatory = $true)]
39 | [String]
40 | $prefix,
41 | [ValidateRange(3,24)]
42 | [Int]
43 | $maxLength = 24
44 | )
45 |
46 | $name = $prefix.ToLower()
47 | while ($name.Length -lt 24) {
48 | $name = $name + [char](Get-Random -Minimum 97 -Maximum 122)
49 | }
50 | return $name
51 | }
52 |
53 | function Ensure-AzureAffinityGroup {
54 | param
55 | (
56 | [Parameter(Mandatory = $true)]
57 | [String]
58 | $name,
59 | [Parameter(Mandatory = $true)]
60 | [string]$location
61 | )
62 |
63 | $affinityGroup = Get-AzureAffinityGroup -Name $name -ErrorAction SilentlyContinue
64 | if ($affinityGroup -eq $null) {
65 | New-AzureAffinityGroup -Location $location -Name $name | Out-Null
66 | } elseif ($affinityGroup.Location -ne $location) {
67 | $actualLocation = $affinityGroup.Location
68 | Write-Error "Affinity Group '$name' exists, but is not in location '$location'. It is in location '$actualLocation'."
69 | }
70 | }
71 |
72 | function Ensure-StorageAccount() {
73 | if ((Get-AzureStorageAccount -StorageAccountName $TargetStorageAccountName -ErrorAction SilentlyContinue) -eq $null) {
74 |
75 | $storageAccountName = Get-RandomStorageAccountName($TargetStorageAccountName)
76 | New-AzureStorageAccount -AffinityGroup $AffinityGroup -StorageAccountName $storageAccountName -Type Standard_LRS | Out-Null
77 |
78 | # Wait for the storage account to be available so we can use it
79 | Write-Verbose "$(Get-Date -Format 'T') Waiting for storage account $storageAccountName to be available..."
80 | while ((Get-AzureStorageAccount -StorageAccountName $storageAccountName).StatusOfPrimary -ne "Available") {
81 | Start-Sleep -Seconds 1
82 | }
83 | return $storageAccountName
84 | } else {
85 | return $TargetStorageAccountName
86 | }
87 | }
88 |
89 | function Create-EventStoreNodes {
90 | param (
91 | [Parameter(Mandatory = $true)]
92 | [String]
93 | $StorageAccountName
94 | )
95 | <# Subscription Limits - http://azure.microsoft.com/en-us/documentation/articles/azure-subscription-service-limits/
96 |
97 | Default Max limit
98 | Cores 20 10,000
99 | Storage accounts per subscription - 100 100
100 |
101 | Max 8 KB IOPS per persistent disk (Basic Tier) 300
102 | Max 8 KB IOPS per persistent disk (Standard Tier) 500
103 | Total Request Rate (assuming 1KB object size) per storage account 20,000
104 | Target Throughput for Single Blob Up to 60 MB per second, or up to 500 requests per second
105 | #>
106 |
107 | # create the cloud service first so that it will be ready when the VM are created below
108 | New-AzureService -ServiceName $ServiceName -AffinityGroup $AffinityGroup | Out-Null
109 |
110 | $vms = @()
111 |
112 | $numberOfDataDisks = (Get-AzureRoleSize -InstanceSize $InstanceSize).MaxDataDiskCount
113 |
114 | # if we are limiting the total data disks
115 | if ($MaxDataDisksPerVirtualMachine -ge 1) {
116 | $numberOfDataDisks = [System.Math]::Min($numberOfDataDisks,$MaxDataDisksPerVirtualMachine)
117 | }
118 |
119 | $totalDiskCount = $ClusterSize * ($numberOfDataDisks+1) # OS Disk + N data disks $MaxDiskPerStorageAccount
120 |
121 | if ($totalDiskCount -ge 40) {
122 | Write-Warning "You may have too many disks per storage account. Your performance may degrade. See http://blogs.msdn.com/b/mast/archive/2014/10/14/configuring-azure-virtual-machines-for-optimal-storage-performance.aspx"
123 | }
124 |
125 | for ($node=1;$node -le $ClusterSize;$node++) {
126 | $name = $VMName + "-" + $node
127 |
128 | $vm = New-AzureVMConfig -ImageName $ImageName -InstanceSize $InstanceSize -Name $name -AvailabilitySetName $AvailabilitySetName
129 | $vm = $vm | Set-AzureSubnet -SubnetNames $VNetSubnetName
130 |
131 | $isWindows = $true
132 | if ($isWindows) {
133 | $vm = $vm | Add-AzureProvisioningConfig -AdminUsername $username -Password $password -Windows
134 | } else {
135 | $vm = $vm | Add-AzureProvisioningConfig -LinuxUser $username -Password $password -Linux
136 | }
137 |
138 | if ($true) {
139 | $StandardTcpPort = 1113
140 | $StandardHttpPort = 2113
141 |
142 | $ExtTcpPort = $StandardTcpPort + ($node - 1) * 100
143 | $ExtHttpPort = $StandardHttpPort + ($node - 1) * 100
144 |
145 | # http://michaelwasham.com/windows-azure-powershell-reference-guide/configuring-disks-endpoints-vms-powershell/
146 | $vm = $vm | Add-AzureEndpoint -Name 'EventStoreTcp' -LocalPort $ExtTcpPort -PublicPort $ExtTcpPort -Protocol Tcp
147 | $vm = $vm | Add-AzureEndpoint -Name 'EventStoreHttp' -LocalPort $ExtHttpPort -PublicPort $ExtHttpPort -Protocol Tcp
148 | }
149 |
150 | $vm = $vm | Set-AzureVMCustomScriptExtension `
151 | -StorageAccountName $CustomScriptExtensionStorageAccountName `
152 | -StorageAccountKey $CustomScriptExtensionStorageAccountKey `
153 | -ContainerName $CustomScriptExtensionContainerName `
154 | -FileName $CustomScriptExtensionProvisionFile `
155 | -Run $CustomScriptExtensionProvisionFile `
156 | -Argument "-clusterSize $ClusterSize -VMName $VMName -nodeNumber $node -ExtTcpPort $ExtTcpPort -ExtHttpPort $ExtHttpPort"
157 |
158 | # Attach the maximum data disks allowed for the virtual machine size
159 | if ($DataDiskSize -gt 0) {
160 |
161 | $minSizeInGB = 4 # min size for each disk to be stripped: All disks must be at least 4 GB.
162 | $sizeInGB = [int][System.Math]::Max([System.Math]::Ceiling($DataDiskSize / $numberOfDataDisks), $minSizeInGB)
163 |
164 | for ($index = 0; $index -lt $numberOfDataDisks; $index++) {
165 | $label = "Data disk " + $index
166 | # The maximum number of data disks that may simultaneously use read caching is 4.
167 | $vm = $vm | Add-AzureDataDisk -CreateNew -DiskSizeInGB $sizeInGB -DiskLabel $label -LUN $index -HostCaching None
168 | }
169 | }
170 |
171 | $vms += $vm
172 | }
173 |
174 | # create all of the VMs
175 | New-AzureVM -ServiceName $ServiceName -VNetName $VNetName -VMs $vms | Out-Null
176 | }
177 |
178 | Write-Verbose "$(Get-Date -Format 'T') Ensuring Affinity Group '$AffinityGroup' exists and is in '$Location' location."
179 | Ensure-AzureAffinityGroup $AffinityGroup $Location
180 | $storageAccountName = Ensure-StorageAccount
181 |
182 | $SubscriptionName = (Get-AzureSubscription).SubscriptionName
183 | Set-AzureSubscription -SubscriptionName $SubscriptionName -CurrentStorageAccount $storageAccountName
184 |
185 | Write-Verbose "$(Get-Date -Format 'T') Creating Virtual Machines"
186 | Create-EventStoreNodes -StorageAccountName $storageAccountName
--------------------------------------------------------------------------------
/azure-powershell-windows/README.md:
--------------------------------------------------------------------------------
1 | I thought I would share the work I have done to automatically setup Event Store running on Azure VMs. Right now, it only targets Windows hosts, but should be easily extended for Linux. To extend for Linux, you would need to create a shell script to replace the PowerShell provisioning script shown in step #4. I have observed it takes about 20 minutes until all the VMs are running with Event Store.
2 |
3 | https://gist.github.com/pbolduc/f8ba49358a97e1e95332
4 |
5 | Files:
6 |
7 | * ProvisionEventStore.ps1 - creates Affinity Group, Storage Account, VMs and data disks for VMs
8 | * EventStoreScriptExtensionProvisionFile.ps1 - Run automatically on the VM to install and configure Event Store to run as a service using NSSM
9 |
10 | Features:
11 |
12 | * Creates any number of VMs for your cluster. No validation to ensure the number is odd. See -ClusterSize
13 | * Creates a stripped data disk using as many data disks the VM will support based on the instance size. The user specifies total target disk size in GB
14 | * Creates all VMs inside the same cloud service. VMs in the same cloud service can resolve the VM names to internal IP addresses
15 | * Uses a virtual network so nodes can user internal addresses for communication
16 | * Sets up all resources in one affinity group to ensure VMs and storage are close to each other in the data center
17 | * Creates a random storage account name to avoid conflicts (uses the user supplied prefix)
18 |
19 | on each VM created:
20 |
21 | * Formats all the data disks into a single striped volume
22 | * Installs Chocolatey
23 | * Installs NSSM using Chocolatey
24 | * Downloads Event Store 3.0.1 from http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.1.zip
25 | * Determines the IP addresses of the other nodes and configures the gossip seeds in the configuration file
26 | * Adds a service called 'EventStore' that will start automatically
27 | * Logs are written to D:\Logs\eventstore\
28 | * Data is stored to F:\Data\eventstore\
29 | * Adds firewall rules to allow Event Store traffic
30 | * Adds netsh urlacls for Event Store
31 |
32 | How to use:
33 |
34 | 1. Manually create a virtual network so that your Event Store nodes can talk to each other on private IP addresses
35 | 2. Manually create a named subnet in your virtual network
36 | 3. Manually create a storage account and container to host the the custom script extension
37 | 4. Upload file EventStoreScriptExtensionProvisionFile.ps1 (found in the gist) to your custom script extension container
38 | 5. Install the Azure PowerShell Cmdlets and ensure they are working with your subscription (see: How to install and configure Azure PowerShell)
39 | 6. Login to your Azure account using Add-AzureAccount and/or
40 | 7. Run ProvisionEventStore.ps1 with your desired parameters
41 |
42 | Example Execution:
43 |
44 | ```
45 | # Run Add-AzureAccount to get a authorization token
46 |
47 | $VerbosePreference = 'Continue'
48 |
49 | Write-Verbose "$(Get-Date -Format 'T') Starting Provision Environment"
50 |
51 | . "$PSScriptRoot\ProvisionEventStore.ps1" `
52 | -ClusterSize 3 `
53 | -DataDiskSize 160 `
54 | -Location "West US" `
55 | -InstanceSize "Medium" `
56 | -username "admin-username" `
57 | -password "admin-password" `
58 | -ServiceName "cloud-service-name" `
59 | -VMName "vm-name-prefix" `
60 | -ImageName "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201502.01-en.us-127GB.vhd" `
61 | -AffinityGroup "affinity-group-name" `
62 | -TargetStorageAccountName "target-storage-account" `
63 | -AvailabilitySetName "availability-set-name" `
64 | -VNetName "virtual-network-name" `
65 | -VNetSubnetName "subnet-name" `
66 | -CustomScriptExtensionStorageAccountName "storage-account-name" `
67 | -CustomScriptExtensionStorageAccountKey 'storage-account-key' `
68 | -CustomScriptExtensionContainerName 'storage-account-container-name' `
69 | -CustomScriptExtensionProvisionFile 'EventStoreScriptExtensionProvisionFile.ps1'
70 |
71 | Write-Verbose "$(Get-Date -Format 'T') Provision Complete"
72 | ```
73 |
74 | Example output:
75 | ```
76 | VERBOSE: 1:54:35 PM Starting Provision Environment
77 | VERBOSE: 1:54:35 PM Ensuring Affinity Group 'EventStore' exists and is in 'West US' location.
78 | VERBOSE: 1:54:35 PM - Begin Operation: Get-AzureAffinityGroup
79 | VERBOSE: 1:54:36 PM - Completed Operation: Get-AzureAffinityGroup
80 | VERBOSE: 1:54:36 PM - Begin Operation: Get-AzureStorageAccount
81 | VERBOSE: 1:54:37 PM - Completed Operation: Get-AzureStorageAccount
82 | WARNING: GeoReplicationEnabled property will be deprecated in a future release of Azure PowerShell. The value will be merged into the AccountType property.
83 | VERBOSE: 1:54:37 PM - Begin Operation: New-AzureStorageAccount
84 | VERBOSE: 1:55:09 PM - Completed Operation: New-AzureStorageAccount
85 | VERBOSE: 1:55:09 PM Waiting for storage account eventstoreaeugnjsexgyefy to be available...
86 | VERBOSE: 1:55:09 PM - Begin Operation: Get-AzureStorageAccount
87 | VERBOSE: 1:55:10 PM - Completed Operation: Get-AzureStorageAccount
88 | WARNING: GeoReplicationEnabled property will be deprecated in a future release of Azure PowerShell. The value will be merged into the AccountType property.
89 | VERBOSE: 1:55:12 PM Creating Virtual Machines
90 | VERBOSE: 1:55:12 PM - Begin Operation: New-AzureService
91 | VERBOSE: 1:55:14 PM - Completed Operation: New-AzureService
92 | VERBOSE: 1:55:14 PM - Begin Operation: Get-AzureRoleSize
93 | VERBOSE: 1:55:14 PM - Completed Operation: Get-AzureRoleSize
94 | VERBOSE: 1:55:28 PM - Begin Operation: New-AzureVM - Create Deployment with VM ES-demo-1
95 | VERBOSE: 1:56:40 PM - Completed Operation: New-AzureVM - Create Deployment with VM ES-demo-1
96 | VERBOSE: 1:56:40 PM - Begin Operation: New-AzureVM - Create VM ES-demo-2
97 | VERBOSE: 1:57:47 PM - Completed Operation: New-AzureVM - Create VM ES-demo-2
98 | VERBOSE: 1:57:47 PM - Begin Operation: New-AzureVM - Create VM ES-demo-3
99 | VERBOSE: 1:58:53 PM - Completed Operation: New-AzureVM - Create VM ES-demo-3
100 | VERBOSE: 1:58:53 PM Provision Complete
101 | ```
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{151D2E53-A2C4-4D7D-83FE-D05416EBD58E}") = "EventStoreCluster", "EventStoreCluster\EventStoreCluster.deployproj", "{637B288B-477E-48A9-B609-F894EA0F566B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {637B288B-477E-48A9-B609-F894EA0F566B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {637B288B-477E-48A9-B609-F894EA0F566B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {637B288B-477E-48A9-B609-F894EA0F566B}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {637B288B-477E-48A9-B609-F894EA0F566B}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/CreateStripedDataDisk.ps1:
--------------------------------------------------------------------------------
1 | Write-Verbose 'Creating Storage Pool'
2 |
3 | $storagePoolFriendlyName = 'LUN-0'
4 | $virtualDiskFriendlyName = 'Datastore01'
5 | $physicalDisks = Get-PhysicalDisk -CanPool $true
6 | $numberOfColumns = $physicalDisks.Length
7 |
8 | New-StoragePool -FriendlyName $storagePoolFriendlyName `
9 | -StorageSubSystemUniqueId (Get-StorageSubSystem -FriendlyName '*Space*').uniqueID `
10 | -PhysicalDisks $physicalDisks
11 |
12 | Write-Verbose 'Creating Virtual Disk'
13 |
14 | New-VirtualDisk -FriendlyName $virtualDiskFriendlyName `
15 | -StoragePoolFriendlyName $storagePoolFriendlyName `
16 | -UseMaximumSize `
17 | -NumberOfColumns $NumberOfColumns `
18 | -Interleave 65536 `
19 | -ProvisioningType Fixed `
20 | -ResiliencySettingName Simple
21 |
22 | Start-Sleep -Seconds 20
23 |
24 | Write-Verbose 'Initializing Disk'
25 |
26 | Initialize-Disk -VirtualDisk (Get-VirtualDisk -FriendlyName $virtualDiskFriendlyName)
27 |
28 | Start-Sleep -Seconds 20
29 |
30 | $diskNumber = ((Get-VirtualDisk -FriendlyName $virtualDiskFriendlyName | Get-Disk).Number)
31 |
32 | Write-Verbose 'Creating Partition'
33 |
34 | New-Partition -DiskNumber $diskNumber `
35 | -UseMaximumSize `
36 | -AssignDriveLetter `
37 | -DriveLetter F
38 |
39 | Start-Sleep -Seconds 20
40 |
41 | Write-Verbose 'Formatting Volume and Assigning Drive Letter'
42 |
43 | Format-Volume -DriveLetter F `
44 | -FileSystem NTFS `
45 | -NewFileSystemLabel 'Data' `
46 | -Confirm:$false `
47 | -Force
48 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Deployment.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | bin\$(Configuration)\
7 | false
8 | true
9 | false
10 | None
11 | obj\
12 | $(BaseIntermediateOutputPath)\
13 | $(BaseIntermediateOutputPath)$(Configuration)\
14 | $(IntermediateOutputPath)ProjectReferences
15 | $(ProjectReferencesOutputPath)\
16 | true
17 |
18 |
19 |
20 | false
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Always
33 |
34 |
35 | Never
36 |
37 |
38 | false
39 | Build
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | _GetDeploymentProjectContent;
48 | _CalculateContentOutputRelativePaths;
49 | _GetReferencedProjectsOutput;
50 | _CalculateArtifactStagingDirectory;
51 | _CopyOutputToArtifactStagingDirectory;
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Configuration=$(Configuration);Platform=$(Platform)
69 |
70 |
71 |
75 |
76 |
77 |
78 | $([System.IO.Path]::GetFileNameWithoutExtension('%(ProjectReference.Identity)'))
79 |
80 |
81 |
82 |
83 |
84 |
85 | $(OutDir)
86 | $(OutputPath)
87 | $(ArtifactStagingDirectory)\
88 | $(ArtifactStagingDirectory)staging\
89 | $(Build_StagingDirectory)
90 |
91 |
92 |
93 |
94 |
96 |
97 | <_OriginalIdentity>%(DeploymentProjectContentOutput.Identity)
98 | <_RelativePath>$(_OriginalIdentity.Replace('$(MSBuildProjectDirectory)', ''))
99 |
100 |
101 |
102 |
103 | $(_RelativePath)
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | PrepareForRun
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/EventStoreCluster.deployproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 |
9 | Release
10 | AnyCPU
11 |
12 |
13 |
14 | 637b288b-477e-48a9-b609-f894ea0f566b
15 |
16 |
17 | Deployment
18 | 1.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | False
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | False
57 |
58 |
59 | False
60 |
61 |
62 | False
63 |
64 |
65 | False
66 |
67 |
68 | False
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Scripts/Deploy-AzureResourceGroup.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 |
3 | Param(
4 | [string] [Parameter(Mandatory=$true)] $ResourceGroupLocation,
5 | [string] $ResourceGroupName = 'EventStoreCluster',
6 | [switch] $UploadArtifacts,
7 | [string] $StorageAccountName,
8 | [string] $StorageAccountResourceGroupName,
9 | [string] $StorageContainerName = $ResourceGroupName.ToLowerInvariant() + '-stageartifacts',
10 | [string] $TemplateFile = '..\Templates\azuredeploy.json',
11 | [string] $TemplateParametersFile = '..\Templates\azuredeploy.param.dev.json',
12 | [string] $ArtifactStagingDirectory = '..\bin\Debug\staging',
13 | [string] $AzCopyPath = '..\Tools\AzCopy.exe',
14 | [string] $DSCSourceFolder = '..\DSC'
15 | )
16 |
17 | if (Get-Module -ListAvailable | Where-Object { $_.Name -eq 'AzureResourceManager' -and $_.Version -ge '1.5.1' }) {
18 | Throw "The version of the Azure PowerShell cmdlets installed on this machine are not compatible with this script. For help updating this script visit: http://go.microsoft.com/fwlink/?LinkID=623011"
19 | }
20 |
21 | Import-Module Azure -ErrorAction SilentlyContinue
22 |
23 | try {
24 | [Microsoft.Azure.Common.Authentication.AzureSession]::ClientFactory.AddUserAgent("VSAzureTools-$UI$($host.name)".replace(" ","_"), "2.7.1")
25 | } catch { }
26 |
27 | Set-StrictMode -Version 3
28 |
29 | $OptionalParameters = New-Object -TypeName Hashtable
30 | $TemplateFile = [System.IO.Path]::Combine($PSScriptRoot, $TemplateFile)
31 | $TemplateParametersFile = [System.IO.Path]::Combine($PSScriptRoot, $TemplateParametersFile)
32 |
33 | if ($UploadArtifacts)
34 | {
35 | # Convert relative paths to absolute paths if needed
36 | $AzCopyPath = [System.IO.Path]::Combine($PSScriptRoot, $AzCopyPath)
37 | $ArtifactStagingDirectory = [System.IO.Path]::Combine($PSScriptRoot, $ArtifactStagingDirectory)
38 | $DSCSourceFolder = [System.IO.Path]::Combine($PSScriptRoot, $DSCSourceFolder)
39 |
40 | Set-Variable ArtifactsLocationName '_artifactsLocation' -Option ReadOnly
41 | Set-Variable ArtifactsLocationSasTokenName '_artifactsLocationSasToken' -Option ReadOnly
42 |
43 | $OptionalParameters.Add($ArtifactsLocationName, $null)
44 | $OptionalParameters.Add($ArtifactsLocationSasTokenName, $null)
45 |
46 | # Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present
47 | $JsonContent = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json
48 | $JsonParameters = $JsonContent | Get-Member -Type NoteProperty | Where-Object {$_.Name -eq "parameters"}
49 |
50 | if ($JsonParameters -eq $null) {
51 | $JsonParameters = $JsonContent
52 | }
53 | else {
54 | $JsonParameters = $JsonContent.parameters
55 | }
56 |
57 | $JsonParameters | Get-Member -Type NoteProperty | ForEach-Object {
58 | $ParameterValue = $JsonParameters | Select-Object -ExpandProperty $_.Name
59 |
60 | if ($_.Name -eq $ArtifactsLocationName -or $_.Name -eq $ArtifactsLocationSasTokenName) {
61 | $OptionalParameters[$_.Name] = $ParameterValue.value
62 | }
63 | }
64 |
65 | if ($StorageAccountResourceGroupName) {
66 | # Switch-AzureMode AzureResourceManager
67 | $StorageAccountKey = (Get-AzureStorageAccountKey -ResourceGroupName $StorageAccountResourceGroupName -Name $StorageAccountName).Key1
68 | }
69 | else {
70 | # Switch-AzureMode AzureServiceManagement
71 | $StorageAccountKey = (Get-AzureStorageKey -StorageAccountName $StorageAccountName).Primary
72 | }
73 |
74 | $StorageAccountContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
75 |
76 | # Create DSC configuration archive
77 | if (Test-Path $DSCSourceFolder) {
78 | Add-Type -Assembly System.IO.Compression.FileSystem
79 | $ArchiveFile = Join-Path $ArtifactStagingDirectory "dsc.zip"
80 | Remove-Item -Path $ArchiveFile -ErrorAction SilentlyContinue
81 | [System.IO.Compression.ZipFile]::CreateFromDirectory($DSCSourceFolder, $ArchiveFile)
82 | }
83 |
84 | # Generate the value for artifacts location if it is not provided in the parameter file
85 | $ArtifactsLocation = $OptionalParameters[$ArtifactsLocationName]
86 | if ($ArtifactsLocation -eq $null) {
87 | $ArtifactsLocation = $StorageAccountContext.BlobEndPoint + $StorageContainerName
88 | $OptionalParameters[$ArtifactsLocationName] = $ArtifactsLocation
89 | }
90 |
91 | # Use AzCopy to copy files from the local storage drop path to the storage account container
92 | & $AzCopyPath """$ArtifactStagingDirectory""", $ArtifactsLocation, "/DestKey:$StorageAccountKey", "/S", "/Y", "/Z:$env:LocalAppData\Microsoft\Azure\AzCopy\$ResourceGroupName"
93 |
94 | # Generate the value for artifacts location SAS token if it is not provided in the parameter file
95 | $ArtifactsLocationSasToken = $OptionalParameters[$ArtifactsLocationSasTokenName]
96 | if ($ArtifactsLocationSasToken -eq $null) {
97 | # Create a SAS token for the storage container - this gives temporary read-only access to the container (defaults to 1 hour).
98 | $ArtifactsLocationSasToken = New-AzureStorageContainerSASToken -Container $StorageContainerName -Context $StorageAccountContext -Permission r
99 | $ArtifactsLocationSasToken = ConvertTo-SecureString $ArtifactsLocationSasToken -AsPlainText -Force
100 | $OptionalParameters[$ArtifactsLocationSasTokenName] = $ArtifactsLocationSasToken
101 | }
102 | }
103 |
104 | # Create or update the resource group using the specified template file and template parameters file
105 | # Switch-AzureMode AzureResourceManager
106 | Login-AzureRmAccount
107 | New-AzureRmResourceGroup -Name $ResourceGroupName -Location $ResourceGroupLocation
108 | New-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName `
109 | -TemplateFile $TemplateFile `
110 | -TemplateParameterFile $TemplateParametersFile `
111 | @OptionalParameters `
112 | -Force -Verbose
113 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "location": {
18 | "type": "string",
19 | "allowedValues": [
20 | "ResourceGroup",
21 | "Brazil South",
22 | "Canada Central",
23 | "Canada East",
24 | "Central US",
25 | "East Asia",
26 | "East US",
27 | "East US 2",
28 | "Japan East",
29 | "Japan West",
30 | "North Central US",
31 | "North Europe",
32 | "South Central US",
33 | "Southeast Asia",
34 | "West Central US",
35 | "West Europe",
36 | "West US",
37 | "West US 2"
38 | ],
39 | "defaultValue": "ResourceGroup",
40 | "metadata": {
41 | "description": "Location where resources will be provisioned. A value of 'ResourceGroup' will deploy the resource to the same location of the resource group the resources are provisioned into"
42 | }
43 | },
44 | "virtualNetworkName": {
45 | "type": "string",
46 | "defaultValue": "es-vnet",
47 | "metadata": {
48 | "description": "Virtual Network"
49 | }
50 | },
51 | "OS": {
52 | "type": "string",
53 | "defaultValue": "windows",
54 | "allowedValues": [
55 | "ubuntu",
56 | "windows"
57 | ],
58 | "metadata": {
59 | "description": "The operating system to deploy Event Store cluster on"
60 | }
61 | },
62 | "jumpbox": {
63 | "type": "string",
64 | "defaultValue": "No",
65 | "allowedValues": [
66 | "Yes",
67 | "No"
68 | ],
69 | "metadata": {
70 | "description": "Optionally add a virtual machine to the deployment which you can use to connect and manage virtual machines on the internal network"
71 | }
72 | },
73 | "vmEventStoreNodeCount": {
74 | "type": "int",
75 | "defaultValue": 1,
76 | "allowedValues": [
77 | 1,
78 | 3,
79 | 5,
80 | 7,
81 | 9
82 | ],
83 | "metadata": {
84 | "description": "Number of Event Store client nodes to provision"
85 | }
86 | },
87 | "vmSizeEventStoreNode": {
88 | "type": "string",
89 | "defaultValue": "Standard_D2",
90 | "allowedValues": [
91 | "Standard_D1",
92 | "Standard_D2",
93 | "Standard_D3",
94 | "Standard_D4",
95 | "Standard_A2",
96 | "Standard_A3",
97 | "Standard_A4",
98 | "Standard_A7",
99 | "Standard_DS1",
100 | "Standard_DS2",
101 | "Standard_DS3",
102 | "Standard_DS4",
103 | "Standard_DS13"
104 | ],
105 | "metadata": {
106 | "description": "Size of the Event Store data nodes"
107 | }
108 | },
109 | "vmEventStoreDataDiskSize": {
110 | "type": "int",
111 | "defaultValue": 4,
112 | "metadata": {
113 | "description": "Size of each data disk attached to data nodes in (Gb). You can only pool disks that have 4GB of contiguous unallocated space."
114 | }
115 | },
116 | "esVersion": {
117 | "type": "string",
118 | "defaultValue": "3.8.1",
119 | "allowedValues": [
120 | "3.8.1",
121 | "3.8.0",
122 | "3.7.0",
123 | "3.6.3",
124 | "3.6.2",
125 | "3.6.1",
126 | "3.6.0",
127 | "3.5.0",
128 | "3.4.0",
129 | "3.3.1",
130 | "3.3.0",
131 | "3.2.2",
132 | "3.2.1",
133 | "3.2.0",
134 | "3.1.0",
135 | "3.0.5",
136 | "3.0.3",
137 | "3.0.2",
138 | "3.0.1",
139 | "3.0.0"
140 | ],
141 | "metadata": {
142 | "description": "Event Store version to install"
143 | }
144 | },
145 | "githubAccount": {
146 | "type": "string",
147 | "defaultValue": "pbolduc",
148 | "metadata": {
149 | "description": "The GitHub account to use down load the resource manager template assets (ie scripts to download, install and configure the VMs). You will only need to change this if you have your own copy or working of a separate branch."
150 | }
151 | },
152 | "githubProject": {
153 | "type": "string",
154 | "defaultValue": "EventStore-DevOps",
155 | "metadata": {
156 | "description": "The GitHub project to down load the resource manager templates assets (ie scripts to download, install and configure the VMs). You will only need to change this if you have your own copy or working of a separate branch."
157 | }
158 | },
159 | "githubBranch": {
160 | "type": "string",
161 | "defaultValue": "master",
162 | "metadata": {
163 | "description": "The GitHub branch to use down load the resource manager templates assets (ie scripts to download, install and configure the VMs). You will only need to change this if you have your own copy or working of a separate branch."
164 | }
165 | }
166 | },
167 | "variables": {
168 | "templateBaseUrl": "[concat('https://raw.githubusercontent.com/',parameters('githubAccount'),'/',parameters('githubProject'),'/',parameters('githubBranch'),'/azure-resource-manager/EventStoreCluster/Templates/')]",
169 | "locationMap": {
170 | "ResourceGroup": "[resourceGroup().location]",
171 | "Brazil South": "[parameters('location')]",
172 | "Canada Central": "[parameters('location')]",
173 | "Canada East": "[parameters('location')]",
174 | "Central US": "[parameters('location')]",
175 | "East Asia": "[parameters('location')]",
176 | "East US": "[parameters('location')]",
177 | "East US 2": "[parameters('location')]",
178 | "Japan East": "[parameters('location')]",
179 | "Japan West": "[parameters('location')]",
180 | "North Central US": "[parameters('location')]",
181 | "North Europe": "[parameters('location')]",
182 | "South Central US": "[parameters('location')]",
183 | "Southeast Asia": "[parameters('location')]",
184 | "West Central US": "[parameters('location')]",
185 | "West Europe": "[parameters('location')]",
186 | "West US": "[parameters('location')]",
187 | "West US 2": "[parameters('location')]"
188 | },
189 | "location": "[variables('locationMap')[parameters('location')]]",
190 | "storageAccountPrefix": "esdata",
191 | "storageAccountNameShared": "[concat(variables('storageAccountPrefix'), 's', uniqueString(resourceGroup().id, deployment().name))]",
192 | "networkSettings": {
193 | "virtualNetworkName": "[parameters('virtualNetworkName')]",
194 | "networkSecurityGroupName": "[concat(parameters('virtualNetworkName'), '-nsg')]",
195 | "addressPrefix": "10.0.0.0/16",
196 | "subnet": {
197 | "eventstore": {
198 | "name": "eventstore",
199 | "prefix": "10.0.1.0/28",
200 | "networkPrefix": "10.0.1",
201 | "vnet": "[parameters('virtualNetworkName')]"
202 | }
203 | }
204 | },
205 | "sharedTemplateUrl": "[concat(variables('templateBaseUrl'), 'shared-resources.json')]",
206 | "jumpboxTemplateYes": "jumpbox-resources.json",
207 | "jumpboxTemplateNo": "empty-resources.json",
208 | "jumpboxTemplateUrl": "[concat(variables('templateBaseUrl'), variables(concat('jumpboxTemplate',parameters('jumpbox'))))]",
209 | "windowsScripts": [
210 | "[concat(variables('templateBaseUrl'), 'master.ps1')]",
211 | "[concat(variables('templateBaseUrl'), 'create-data-disks.ps1')]",
212 | "[concat(variables('templateBaseUrl'), 'install-eventstore.ps1')]",
213 | "[concat(variables('templateBaseUrl'), 'eventstore-windows-sources.csv')]",
214 | "[concat(variables('templateBaseUrl'), 'install-nginx.ps1')]"
215 | ],
216 | "windowsSettings": {
217 | "imageReference": {
218 | "publisher": "MicrosoftWindowsServer",
219 | "offer": "WindowsServer",
220 | "sku": "2012-R2-Datacenter",
221 | "version": "latest"
222 | },
223 | "managementPort": "3389",
224 | "extentionSettings": {
225 | "eventstore": {
226 | "publisher": "Microsoft.Compute",
227 | "type": "CustomScriptExtension",
228 | "typeHandlerVersion": "1.8",
229 | "autoUpgradeMinorVersion": true,
230 | "settings": {
231 | "fileUris": "[variables('windowsScripts')]",
232 | "commandToExecute": "[concat('powershell.exe -File master.ps1 -ClusterSize ',parameters('vmEventStoreNodeCount'),' -esVer ',parameters('esVersion'))]"
233 | }
234 | }
235 | }
236 | },
237 | "osSettings": "[variables(concat(parameters('OS'), 'Settings'))]",
238 | "virtualMachineSkuSettings": {
239 | "Standard_D1": {
240 | "dataDisks": 2,
241 | "nodesPerStorageAccount": 6,
242 | "storageAccountType": "Standard_LRS"
243 | },
244 | "Standard_D2": {
245 | "dataDisks": 4,
246 | "nodesPerStorageAccount": 4,
247 | "storageAccountType": "Standard_LRS"
248 | },
249 | "Standard_D3": {
250 | "dataDisks": 8,
251 | "nodesPerStorageAccount": 3,
252 | "storageAccountType": "Standard_LRS"
253 | },
254 | "Standard_D4": {
255 | "dataDisks": 16,
256 | "nodesPerStorageAccount": 2,
257 | "storageAccountType": "Standard_LRS"
258 | },
259 | "Standard_DS1": {
260 | "dataDisks": 2,
261 | "nodesPerStorageAccount": 6,
262 | "storageAccountType": "Premium_LRS"
263 | },
264 | "Standard_DS2": {
265 | "dataDisks": 4,
266 | "nodesPerStorageAccount": 4,
267 | "storageAccountType": "Premium_LRS"
268 | },
269 | "Standard_DS3": {
270 | "dataDisks": 8,
271 | "nodesPerStorageAccount": 4,
272 | "storageAccountType": "Premium_LRS"
273 | },
274 | "Standard_DS4": {
275 | "dataDisks": 16,
276 | "nodesPerStorageAccount": 2,
277 | "storageAccountType": "Premium_LRS"
278 | },
279 | "Standard_DS13": {
280 | "dataDisks": 16,
281 | "nodesPerStorageAccount": 2,
282 | "storageAccountType": "Premium_LRS"
283 | },
284 | "Standard_A2": {
285 | "dataDisks": 4,
286 | "nodesPerStorageAccount": 6,
287 | "storageAccountType": "Standard_LRS"
288 | },
289 | "Standard_A3": {
290 | "dataDisks": 8,
291 | "nodesPerStorageAccount": 4,
292 | "storageAccountType": "Standard_LRS"
293 | },
294 | "Standard_A4": {
295 | "dataDisks": 16,
296 | "nodesPerStorageAccount": 2,
297 | "storageAccountType": "Standard_LRS"
298 | },
299 | "Standard_A7": {
300 | "dataDisks": 16,
301 | "nodesPerStorageAccount": 2,
302 | "storageAccountType": "Standard_LRS"
303 | }
304 | },
305 | "eventStoreClusterNodesPerStorageAccount": "[variables('virtualMachineSkuSettings')[parameters('vmSizeEventStoreNode')].nodesPerStorageAccount]",
306 | "storageBinPackMap": [
307 | "[div(sub(add(1, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
308 | "[div(sub(add(2, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
309 | "[div(sub(add(3, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
310 | "[div(sub(add(4, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
311 | "[div(sub(add(5, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
312 | "[div(sub(add(6, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
313 | "[div(sub(add(7, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
314 | "[div(sub(add(8, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
315 | "[div(sub(add(9, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
316 | "[div(sub(add(10, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
317 | "[div(sub(add(11, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
318 | "[div(sub(add(12, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
319 | "[div(sub(add(13, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
320 | "[div(sub(add(14, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
321 | "[div(sub(add(15, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
322 | "[div(sub(add(16, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
323 | "[div(sub(add(17, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
324 | "[div(sub(add(18, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
325 | "[div(sub(add(19, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
326 | "[div(sub(add(20, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
327 | "[div(sub(add(21, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
328 | "[div(sub(add(22, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
329 | "[div(sub(add(23, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
330 | "[div(sub(add(24, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
331 | "[div(sub(add(25, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
332 | "[div(sub(add(26, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
333 | "[div(sub(add(27, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
334 | "[div(sub(add(28, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
335 | "[div(sub(add(29, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
336 | "[div(sub(add(30, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
337 | "[div(sub(add(31, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
338 | "[div(sub(add(32, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
339 | "[div(sub(add(33, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
340 | "[div(sub(add(34, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
341 | "[div(sub(add(35, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
342 | "[div(sub(add(36, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
343 | "[div(sub(add(37, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
344 | "[div(sub(add(38, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
345 | "[div(sub(add(39, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
346 | "[div(sub(add(40, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
347 | "[div(sub(add(51, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
348 | "[div(sub(add(52, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
349 | "[div(sub(add(53, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
350 | "[div(sub(add(54, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
351 | "[div(sub(add(55, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
352 | "[div(sub(add(56, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
353 | "[div(sub(add(57, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
354 | "[div(sub(add(58, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
355 | "[div(sub(add(59, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
356 | "[div(sub(add(60, variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]"
357 | ],
358 | "clusterNodeStorageSettings": {
359 | "count": "[div(sub(add(parameters('vmEventStoreNodeCount'), variables('eventStoreClusterNodesPerStorageAccount')), 1), variables('eventStoreClusterNodesPerStorageAccount'))]",
360 | "mapping": "[variables('storageBinPackMap')]",
361 | "accountType": "[variables('virtualMachineSkuSettings')[parameters('vmSizeEventStoreNode')].storageAccountType]",
362 | "prefix": "[concat(variables('storageAccountPrefix'), 'd', uniqueString(resourceGroup().id, deployment().name))]"
363 | },
364 | "clusterNodeTemplateUrl": "[concat(variables('templateBaseUrl'), 'cluster-nodes-', string(variables('virtualMachineSkuSettings')[parameters('vmSizeEventStoreNode')].dataDisks), 'disk-resources.json')]",
365 | },
366 | "resources": [
367 | {
368 | "name": "shared",
369 | "type": "Microsoft.Resources/deployments",
370 | "apiVersion": "2015-01-01",
371 | "properties": {
372 | "mode": "Incremental",
373 | "templateLink": {
374 | "uri": "[variables('sharedTemplateUrl')]",
375 | "contentVersion": "1.0.0.0"
376 | },
377 | "parameters": {
378 | "location": {
379 | "value": "[variables('location')]"
380 | },
381 | "networkSettings": {
382 | "value": "[variables('networkSettings')]"
383 | },
384 | "storageAccountName": {
385 | "value": "[variables('storageAccountNameShared')]"
386 | },
387 | "subnet": { "value": "eventstore" }
388 | }
389 | }
390 | },
391 | {
392 | "name": "cluster-nodes",
393 | "type": "Microsoft.Resources/deployments",
394 | "apiVersion": "2015-01-01",
395 | "dependsOn": [
396 | "[concat('Microsoft.Resources/deployments/', 'shared')]"
397 | ],
398 | "properties": {
399 | "mode": "Incremental",
400 | "templateLink": {
401 | "uri": "[variables('clusterNodeTemplateUrl')]",
402 | "contentVersion": "1.0.0.0"
403 | },
404 | "parameters": {
405 | "adminUsername": {
406 | "value": "[parameters('adminUsername')]"
407 | },
408 | "adminPassword": {
409 | "value": "[parameters('adminPassword')]"
410 | },
411 | "location": {
412 | "value": "[variables('location')]"
413 | },
414 | "storageSettings": {
415 | "value": "[variables('clusterNodeStorageSettings')]"
416 | },
417 | "subnet": {
418 | "value": "[variables('networkSettings').subnet.eventstore]"
419 | },
420 | "vmSize": {
421 | "value": "[parameters('vmSizeEventStoreNode')]"
422 | },
423 | "vmCount": {
424 | "value": "[parameters('vmEventStoreNodeCount')]"
425 | },
426 | "dataDiskSize": {
427 | "value": "[parameters('vmEventStoreDataDiskSize')]"
428 | },
429 | "namespace": {
430 | "value": "es"
431 | },
432 | "osSettings": {
433 | "value": "[variables('osSettings')]"
434 | }
435 | }
436 | }
437 | }
438 | ],
439 | "outputs": {
440 | }
441 | }
442 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/azuredeploy.param.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "value": "EventStoreAdmin"
7 | },
8 | "adminPassword": {
9 | "value": "YourEventStoreVMPassword"
10 | },
11 | "jumpbox": {
12 | "value": "No"
13 | },
14 | "vmEventStoreNodeCount": {
15 | "value": 3
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/cluster-nodes-0disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[concat(parameters('namespace'), 'vm')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyIndex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/networkInterfaces",
102 | "name": "[concat(parameters('namespace'), 'nic', copyIndex())]",
103 | "location": "[parameters('location')]",
104 | "copy": {
105 | "name": "[concat(parameters('namespace'),'nicLoop')]",
106 | "count": "[parameters('vmCount')]"
107 | },
108 | "properties": {
109 | "ipConfigurations": [
110 | {
111 | "name": "ipconfig1",
112 | "properties": {
113 | "privateIPAllocationMethod": "Dynamic",
114 | "subnet": {
115 | "id": "[variables('subnetRef')]"
116 | }
117 | }
118 | }
119 | ]
120 | }
121 | },
122 | {
123 | "apiVersion": "2015-06-15",
124 | "type": "Microsoft.Compute/virtualMachines",
125 | "name": "[concat(parameters('namespace'), 'vm', copyIndex())]",
126 | "location": "[parameters('location')]",
127 | "copy": {
128 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
129 | "count": "[parameters('vmCount')]"
130 | },
131 | "dependsOn": [
132 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), 'nic', copyIndex())]",
133 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()])]"
134 | ],
135 | "properties": {
136 | "availabilitySet": {
137 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
138 | },
139 | "hardwareProfile": {
140 | "vmSize": "[parameters('vmSize')]"
141 | },
142 | "osProfile": {
143 | "computerName": "[concat(parameters('namespace'), 'vm', copyIndex())]",
144 | "adminUsername": "[parameters('adminUsername')]",
145 | "adminPassword": "[parameters('adminPassword')]"
146 | },
147 | "storageProfile": {
148 | "imageReference": "[parameters('osSettings').imageReference]",
149 | "osDisk": {
150 | "name": "osdisk",
151 | "vhd": {
152 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()], '.blob.core.windows.net/vhd/', variables('vmName'), copyIndex(), '-osdisk.vhd')]"
153 | },
154 | "caching": "ReadWrite",
155 | "createOption": "FromImage"
156 | }
157 | },
158 | "networkProfile": {
159 | "networkInterfaces": [
160 | {
161 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'nic', copyIndex()))]"
162 | }
163 | ]
164 | }
165 | },
166 | "resources": [
167 | {
168 | "type": "Microsoft.Compute/virtualMachines/extensions",
169 | "name": "[concat(parameters('namespace'),'-vm-', copyIndex(), '/installapplications')]",
170 | "location": "[parameters('location')]",
171 | "apiVersion": "2015-06-15",
172 | "dependsOn": [
173 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyIndex())]"
174 | ],
175 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
176 | }
177 | ]
178 | }
179 | ]
180 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/cluster-nodes-16disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[parameters('namespace')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyIndex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/publicIPAddresses",
102 | "name": "[concat(parameters('namespace'), '-pip-', copyIndex())]",
103 | "location": "[parameters('location')]",
104 | "copy": {
105 | "name": "[concat(parameters('namespace'),'pipLoop')]",
106 | "count": "[parameters('vmCount')]"
107 | },
108 | "properties": {
109 | "publicIPAllocationMethod": "Dynamic"
110 | }
111 | },
112 | {
113 | "apiVersion": "2015-06-15",
114 | "type": "Microsoft.Network/networkInterfaces",
115 | "name": "[concat(parameters('namespace'), '-nic-', copyIndex())]",
116 | "location": "[parameters('location')]",
117 | "copy": {
118 | "name": "[concat(parameters('namespace'),'nicLoop')]",
119 | "count": "[parameters('vmCount')]"
120 | },
121 | "dependsOn": [
122 | "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyIndex())]"
123 | ],
124 | "properties": {
125 | "ipConfigurations": [
126 | {
127 | "name": "ipconfig1",
128 | "properties": {
129 | "privateIPAddress": "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyIndex())))]",
130 | "privateIPAllocationMethod": "Static",
131 | "subnet": {
132 | "id": "[variables('subnetRef')]"
133 | }
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | {
140 | "apiVersion": "2015-06-15",
141 | "type": "Microsoft.Compute/virtualMachines",
142 | "name": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
143 | "location": "[parameters('location')]",
144 | "copy": {
145 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
146 | "count": "[parameters('vmCount')]"
147 | },
148 | "dependsOn": [
149 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyIndex())]",
150 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()])]"
151 | ],
152 | "properties": {
153 | "availabilitySet": {
154 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
155 | },
156 | "hardwareProfile": {
157 | "vmSize": "[parameters('vmSize')]"
158 | },
159 | "osProfile": {
160 | "computerName": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
161 | "adminUsername": "[parameters('adminUsername')]",
162 | "adminPassword": "[parameters('adminPassword')]"
163 | },
164 | "storageProfile": {
165 | "imageReference": "[parameters('osSettings').imageReference]",
166 | "osDisk": {
167 | "name": "osdisk",
168 | "vhd": {
169 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyIndex(), '-osdisk.vhd')]"
170 | },
171 | "caching": "ReadWrite",
172 | "createOption": "FromImage"
173 | },
174 | "dataDisks": [
175 | {
176 | "name": "datadisk1",
177 | "diskSizeGB": "[parameters('dataDiskSize')]",
178 | "lun": 0,
179 | "vhd": {
180 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk1' ,'.vhd')]"
181 | },
182 | "caching": "None",
183 | "createOption": "Empty"
184 | },
185 | {
186 | "name": "datadisk2",
187 | "diskSizeGB": "[parameters('dataDiskSize')]",
188 | "lun": 1,
189 | "vhd": {
190 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk2' ,'.vhd')]"
191 | },
192 | "caching": "None",
193 | "createOption": "Empty"
194 | },
195 | {
196 | "name": "datadisk3",
197 | "diskSizeGB": "[parameters('dataDiskSize')]",
198 | "lun": 2,
199 | "vhd": {
200 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk3' ,'.vhd')]"
201 | },
202 | "caching": "None",
203 | "createOption": "Empty"
204 | },
205 | {
206 | "name": "datadisk4",
207 | "diskSizeGB": "[parameters('dataDiskSize')]",
208 | "lun": 3,
209 | "vhd": {
210 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk4' ,'.vhd')]"
211 | },
212 | "caching": "None",
213 | "createOption": "Empty"
214 | },
215 | {
216 | "name": "datadisk5",
217 | "diskSizeGB": "[parameters('dataDiskSize')]",
218 | "lun": 4,
219 | "vhd": {
220 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk5' ,'.vhd')]"
221 | },
222 | "caching": "None",
223 | "createOption": "Empty"
224 | },
225 | {
226 | "name": "datadisk6",
227 | "diskSizeGB": "[parameters('dataDiskSize')]",
228 | "lun": 5,
229 | "vhd": {
230 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk6' ,'.vhd')]"
231 | },
232 | "caching": "None",
233 | "createOption": "Empty"
234 | },
235 | {
236 | "name": "datadisk7",
237 | "diskSizeGB": "[parameters('dataDiskSize')]",
238 | "lun": 6,
239 | "vhd": {
240 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk7' ,'.vhd')]"
241 | },
242 | "caching": "None",
243 | "createOption": "Empty"
244 | },
245 | {
246 | "name": "datadisk8",
247 | "diskSizeGB": "[parameters('dataDiskSize')]",
248 | "lun": 7,
249 | "vhd": {
250 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk8' ,'.vhd')]"
251 | },
252 | "caching": "None",
253 | "createOption": "Empty"
254 | },
255 | {
256 | "name": "datadisk9",
257 | "diskSizeGB": "[parameters('dataDiskSize')]",
258 | "lun": 8,
259 | "vhd": {
260 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk9' ,'.vhd')]"
261 | },
262 | "caching": "None",
263 | "createOption": "Empty"
264 | },
265 | {
266 | "name": "datadisk10",
267 | "diskSizeGB": "[parameters('dataDiskSize')]",
268 | "lun": 9,
269 | "vhd": {
270 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk10' ,'.vhd')]"
271 | },
272 | "caching": "None",
273 | "createOption": "Empty"
274 | },
275 | {
276 | "name": "datadisk11",
277 | "diskSizeGB": "[parameters('dataDiskSize')]",
278 | "lun": 10,
279 | "vhd": {
280 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk11' ,'.vhd')]"
281 | },
282 | "caching": "None",
283 | "createOption": "Empty"
284 | },
285 | {
286 | "name": "datadisk12",
287 | "diskSizeGB": "[parameters('dataDiskSize')]",
288 | "lun": 11,
289 | "vhd": {
290 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk12' ,'.vhd')]"
291 | },
292 | "caching": "None",
293 | "createOption": "Empty"
294 | },
295 | {
296 | "name": "datadisk13",
297 | "diskSizeGB": "[parameters('dataDiskSize')]",
298 | "lun": 12,
299 | "vhd": {
300 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk13' ,'.vhd')]"
301 | },
302 | "caching": "None",
303 | "createOption": "Empty"
304 | },
305 | {
306 | "name": "datadisk14",
307 | "diskSizeGB": "[parameters('dataDiskSize')]",
308 | "lun": 13,
309 | "vhd": {
310 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk14' ,'.vhd')]"
311 | },
312 | "caching": "None",
313 | "createOption": "Empty"
314 | },
315 | {
316 | "name": "datadisk15",
317 | "diskSizeGB": "[parameters('dataDiskSize')]",
318 | "lun": 14,
319 | "vhd": {
320 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk15' ,'.vhd')]"
321 | },
322 | "caching": "None",
323 | "createOption": "Empty"
324 | },
325 | {
326 | "name": "datadisk16",
327 | "diskSizeGB": "[parameters('dataDiskSize')]",
328 | "lun": 15,
329 | "vhd": {
330 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk16' ,'.vhd')]"
331 | },
332 | "caching": "None",
333 | "createOption": "Empty"
334 | }
335 | ]
336 | },
337 | "networkProfile": {
338 | "networkInterfaces": [
339 | {
340 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyIndex()))]"
341 | }
342 | ]
343 | }
344 | },
345 | "resources": [
346 | {
347 | "type": "Microsoft.Compute/virtualMachines/extensions",
348 | "name": "[concat(parameters('namespace'),'-vm-', copyIndex(), '/installapplications')]",
349 | "location": "[parameters('location')]",
350 | "apiVersion": "2015-06-15",
351 | "dependsOn": [
352 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyIndex())]"
353 | ],
354 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
355 | }
356 | ]
357 | }
358 | ]
359 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/cluster-nodes-2disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[parameters('namespace')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyIndex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/publicIPAddresses",
102 | "name": "[concat(parameters('namespace'), '-pip-', copyIndex())]",
103 | "location": "[parameters('location')]",
104 | "copy": {
105 | "name": "[concat(parameters('namespace'),'pipLoop')]",
106 | "count": "[parameters('vmCount')]"
107 | },
108 | "properties": {
109 | "publicIPAllocationMethod": "Dynamic"
110 | }
111 | },
112 | {
113 | "apiVersion": "2015-06-15",
114 | "type": "Microsoft.Network/networkInterfaces",
115 | "name": "[concat(parameters('namespace'), '-nic-', copyIndex())]",
116 | "location": "[parameters('location')]",
117 | "copy": {
118 | "name": "[concat(parameters('namespace'),'nicLoop')]",
119 | "count": "[parameters('vmCount')]"
120 | },
121 | "dependsOn": [
122 | "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyIndex())]"
123 | ],
124 | "properties": {
125 | "ipConfigurations": [
126 | {
127 | "name": "ipconfig1",
128 | "properties": {
129 | "privateIPAddress": "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyIndex())))]",
130 | "privateIPAllocationMethod": "Static",
131 | "subnet": {
132 | "id": "[variables('subnetRef')]"
133 | }
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | {
140 | "apiVersion": "2015-06-15",
141 | "type": "Microsoft.Compute/virtualMachines",
142 | "name": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
143 | "location": "[parameters('location')]",
144 | "copy": {
145 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
146 | "count": "[parameters('vmCount')]"
147 | },
148 | "dependsOn": [
149 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyIndex())]",
150 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()])]"
151 | ],
152 | "properties": {
153 | "availabilitySet": {
154 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
155 | },
156 | "hardwareProfile": {
157 | "vmSize": "[parameters('vmSize')]"
158 | },
159 | "osProfile": {
160 | "computerName": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
161 | "adminUsername": "[parameters('adminUsername')]",
162 | "adminPassword": "[parameters('adminPassword')]"
163 | },
164 | "storageProfile": {
165 | "imageReference": "[parameters('osSettings').imageReference]",
166 | "osDisk": {
167 | "name": "osdisk",
168 | "vhd": {
169 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyIndex(), '-osdisk.vhd')]"
170 | },
171 | "caching": "ReadWrite",
172 | "createOption": "FromImage"
173 | },
174 | "dataDisks": [
175 | {
176 | "name": "datadisk1",
177 | "diskSizeGB": "[parameters('dataDiskSize')]",
178 | "lun": 0,
179 | "vhd": {
180 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk1' ,'.vhd')]"
181 | },
182 | "caching": "None",
183 | "createOption": "Empty"
184 | },
185 | {
186 | "name": "datadisk2",
187 | "diskSizeGB": "[parameters('dataDiskSize')]",
188 | "lun": 1,
189 | "vhd": {
190 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk2' ,'.vhd')]"
191 | },
192 | "caching": "None",
193 | "createOption": "Empty"
194 | }
195 | ]
196 | },
197 | "networkProfile": {
198 | "networkInterfaces": [
199 | {
200 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyIndex()))]"
201 | }
202 | ]
203 | }
204 | },
205 | "resources": [
206 | {
207 | "type": "Microsoft.Compute/virtualMachines/extensions",
208 | "name": "[concat(parameters('namespace'),'-vm-', copyIndex(), '/installapplications')]",
209 | "location": "[parameters('location')]",
210 | "apiVersion": "2015-06-15",
211 | "dependsOn": [
212 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyIndex())]"
213 | ],
214 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
215 | }
216 | ]
217 | }
218 | ]
219 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/cluster-nodes-4disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[parameters('namespace')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyIndex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/publicIPAddresses",
102 | "name": "[concat(parameters('namespace'), '-pip-', copyIndex())]",
103 | "location": "[parameters('location')]",
104 | "copy": {
105 | "name": "[concat(parameters('namespace'),'pipLoop')]",
106 | "count": "[parameters('vmCount')]"
107 | },
108 | "properties": {
109 | "publicIPAllocationMethod": "Dynamic"
110 | }
111 | },
112 | {
113 | "apiVersion": "2015-06-15",
114 | "type": "Microsoft.Network/networkInterfaces",
115 | "name": "[concat(parameters('namespace'), '-nic-', copyIndex())]",
116 | "location": "[parameters('location')]",
117 | "copy": {
118 | "name": "[concat(parameters('namespace'),'nicLoop')]",
119 | "count": "[parameters('vmCount')]"
120 | },
121 | "dependsOn": [
122 | "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyIndex())]"
123 | ],
124 | "properties": {
125 | "ipConfigurations": [
126 | {
127 | "name": "ipconfig1",
128 | "properties": {
129 | "privateIPAddress": "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyIndex())))]",
130 | "privateIPAllocationMethod": "Static",
131 | "subnet": {
132 | "id": "[variables('subnetRef')]"
133 | },
134 | "publicIPAddress": {
135 | "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('namespace'), '-pip-', copyIndex()))]"
136 | }
137 | }
138 | }
139 | ]
140 | }
141 | },
142 | {
143 | "apiVersion": "2015-06-15",
144 | "type": "Microsoft.Compute/virtualMachines",
145 | "name": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
146 | "location": "[parameters('location')]",
147 | "copy": {
148 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
149 | "count": "[parameters('vmCount')]"
150 | },
151 | "dependsOn": [
152 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyIndex())]",
153 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()])]"
154 | ],
155 | "properties": {
156 | "availabilitySet": {
157 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
158 | },
159 | "hardwareProfile": {
160 | "vmSize": "[parameters('vmSize')]"
161 | },
162 | "osProfile": {
163 | "computerName": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
164 | "adminUsername": "[parameters('adminUsername')]",
165 | "adminPassword": "[parameters('adminPassword')]"
166 | },
167 | "storageProfile": {
168 | "imageReference": "[parameters('osSettings').imageReference]",
169 | "osDisk": {
170 | "name": "osdisk",
171 | "vhd": {
172 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyIndex(), '-osdisk.vhd')]"
173 | },
174 | "caching": "ReadWrite",
175 | "createOption": "FromImage"
176 | },
177 | "dataDisks": [
178 | {
179 | "name": "datadisk1",
180 | "diskSizeGB": "[parameters('dataDiskSize')]",
181 | "lun": 0,
182 | "vhd": {
183 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk1' ,'.vhd')]"
184 | },
185 | "caching": "None",
186 | "createOption": "Empty"
187 | },
188 | {
189 | "name": "datadisk2",
190 | "diskSizeGB": "[parameters('dataDiskSize')]",
191 | "lun": 1,
192 | "vhd": {
193 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk2' ,'.vhd')]"
194 | },
195 | "caching": "None",
196 | "createOption": "Empty"
197 | },
198 | {
199 | "name": "datadisk3",
200 | "diskSizeGB": "[parameters('dataDiskSize')]",
201 | "lun": 2,
202 | "vhd": {
203 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk3' ,'.vhd')]"
204 | },
205 | "caching": "None",
206 | "createOption": "Empty"
207 | },
208 | {
209 | "name": "datadisk4",
210 | "diskSizeGB": "[parameters('dataDiskSize')]",
211 | "lun": 3,
212 | "vhd": {
213 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk4' ,'.vhd')]"
214 | },
215 | "caching": "None",
216 | "createOption": "Empty"
217 | }
218 | ]
219 | },
220 | "networkProfile": {
221 | "networkInterfaces": [
222 | {
223 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyIndex()))]"
224 | }
225 | ]
226 | }
227 | },
228 | "resources": [
229 | {
230 | "type": "Microsoft.Compute/virtualMachines/extensions",
231 | "name": "[concat(parameters('namespace'),'-vm-', copyIndex(), '/installapplications')]",
232 | "location": "[parameters('location')]",
233 | "apiVersion": "2015-06-15",
234 | "dependsOn": [
235 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyIndex())]"
236 | ],
237 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
238 | }
239 | ]
240 | }
241 | ]
242 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/cluster-nodes-8disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[parameters('namespace')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyIndex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/publicIPAddresses",
102 | "name": "[concat(parameters('namespace'), '-pip-', copyIndex())]",
103 | "location": "[parameters('location')]",
104 | "copy": {
105 | "name": "[concat(parameters('namespace'),'pipLoop')]",
106 | "count": "[parameters('vmCount')]"
107 | },
108 | "properties": {
109 | "publicIPAllocationMethod": "Dynamic"
110 | }
111 | },
112 | {
113 | "apiVersion": "2015-06-15",
114 | "type": "Microsoft.Network/networkInterfaces",
115 | "name": "[concat(parameters('namespace'), '-nic-', copyIndex())]",
116 | "location": "[parameters('location')]",
117 | "copy": {
118 | "name": "[concat(parameters('namespace'),'nicLoop')]",
119 | "count": "[parameters('vmCount')]"
120 | },
121 | "dependsOn": [
122 | "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyIndex())]"
123 | ],
124 | "properties": {
125 | "ipConfigurations": [
126 | {
127 | "name": "ipconfig1",
128 | "properties": {
129 | "privateIPAddress": "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyIndex())))]",
130 | "privateIPAllocationMethod": "Static",
131 | "subnet": {
132 | "id": "[variables('subnetRef')]"
133 | }
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | {
140 | "apiVersion": "2015-06-15",
141 | "type": "Microsoft.Compute/virtualMachines",
142 | "name": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
143 | "location": "[parameters('location')]",
144 | "copy": {
145 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
146 | "count": "[parameters('vmCount')]"
147 | },
148 | "dependsOn": [
149 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyIndex())]",
150 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()])]"
151 | ],
152 | "properties": {
153 | "availabilitySet": {
154 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
155 | },
156 | "hardwareProfile": {
157 | "vmSize": "[parameters('vmSize')]"
158 | },
159 | "osProfile": {
160 | "computerName": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
161 | "adminUsername": "[parameters('adminUsername')]",
162 | "adminPassword": "[parameters('adminPassword')]"
163 | },
164 | "storageProfile": {
165 | "imageReference": "[parameters('osSettings').imageReference]",
166 | "osDisk": {
167 | "name": "osdisk",
168 | "vhd": {
169 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyIndex(), '-osdisk.vhd')]"
170 | },
171 | "caching": "ReadWrite",
172 | "createOption": "FromImage"
173 | },
174 | "dataDisks": [
175 | {
176 | "name": "datadisk1",
177 | "diskSizeGB": "[parameters('dataDiskSize')]",
178 | "lun": 0,
179 | "vhd": {
180 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk1' ,'.vhd')]"
181 | },
182 | "caching": "None",
183 | "createOption": "Empty"
184 | },
185 | {
186 | "name": "datadisk2",
187 | "diskSizeGB": "[parameters('dataDiskSize')]",
188 | "lun": 1,
189 | "vhd": {
190 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk2' ,'.vhd')]"
191 | },
192 | "caching": "None",
193 | "createOption": "Empty"
194 | },
195 | {
196 | "name": "datadisk3",
197 | "diskSizeGB": "[parameters('dataDiskSize')]",
198 | "lun": 2,
199 | "vhd": {
200 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk3' ,'.vhd')]"
201 | },
202 | "caching": "None",
203 | "createOption": "Empty"
204 | },
205 | {
206 | "name": "datadisk4",
207 | "diskSizeGB": "[parameters('dataDiskSize')]",
208 | "lun": 3,
209 | "vhd": {
210 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk4' ,'.vhd')]"
211 | },
212 | "caching": "None",
213 | "createOption": "Empty"
214 | },
215 | {
216 | "name": "datadisk5",
217 | "diskSizeGB": "[parameters('dataDiskSize')]",
218 | "lun": 4,
219 | "vhd": {
220 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk5' ,'.vhd')]"
221 | },
222 | "caching": "None",
223 | "createOption": "Empty"
224 | },
225 | {
226 | "name": "datadisk6",
227 | "diskSizeGB": "[parameters('dataDiskSize')]",
228 | "lun": 5,
229 | "vhd": {
230 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk6' ,'.vhd')]"
231 | },
232 | "caching": "None",
233 | "createOption": "Empty"
234 | },
235 | {
236 | "name": "datadisk7",
237 | "diskSizeGB": "[parameters('dataDiskSize')]",
238 | "lun": 6,
239 | "vhd": {
240 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk7' ,'.vhd')]"
241 | },
242 | "caching": "None",
243 | "createOption": "Empty"
244 | },
245 | {
246 | "name": "datadisk8",
247 | "diskSizeGB": "[parameters('dataDiskSize')]",
248 | "lun": 7,
249 | "vhd": {
250 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyIndex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyIndex(),'dataDisk8' ,'.vhd')]"
251 | },
252 | "caching": "None",
253 | "createOption": "Empty"
254 | }
255 | ]
256 | },
257 | "networkProfile": {
258 | "networkInterfaces": [
259 | {
260 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyIndex()))]"
261 | }
262 | ]
263 | }
264 | },
265 | "resources": [
266 | {
267 | "type": "Microsoft.Compute/virtualMachines/extensions",
268 | "name": "[concat(parameters('namespace'),'-vm-', copyIndex(), '/installapplications')]",
269 | "location": "[parameters('location')]",
270 | "apiVersion": "2015-06-15",
271 | "dependsOn": [
272 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyIndex())]"
273 | ],
274 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
275 | }
276 | ]
277 | }
278 | ]
279 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/create-data-disks.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # This script will create a stripped data disk with all available disks.
3 | # Note: For disks to be added to a pool, they must be at least 4GB in size.
4 | #
5 | $ErrorActionPreference="SilentlyContinue"
6 | Stop-Transcript | out-null
7 | $ErrorActionPreference = "Continue"
8 | Start-Transcript -path C:\ps-output-createdisks.txt -append -noClobber
9 |
10 | Write-Verbose 'Creating Storage Pool'
11 |
12 | $storagePoolFriendlyName = 'LUN-0'
13 | $virtualDiskFriendlyName = 'Datastore01'
14 | $physicalDisks = Get-PhysicalDisk -CanPool $true
15 | $numberOfColumns = $physicalDisks.Length
16 |
17 | New-StoragePool -FriendlyName $storagePoolFriendlyName `
18 | -StorageSubSystemUniqueId (Get-StorageSubSystem -FriendlyName '*Space*').uniqueID `
19 | -PhysicalDisks $physicalDisks
20 |
21 | Write-Verbose 'Creating Virtual Disk'
22 |
23 | New-VirtualDisk -FriendlyName $virtualDiskFriendlyName `
24 | -StoragePoolFriendlyName $storagePoolFriendlyName `
25 | -UseMaximumSize `
26 | -NumberOfColumns $NumberOfColumns `
27 | -Interleave 65536 `
28 | -ProvisioningType Fixed `
29 | -ResiliencySettingName Simple
30 |
31 | Start-Sleep -Seconds 20
32 |
33 | Write-Verbose 'Initializing Disk'
34 |
35 | Initialize-Disk -VirtualDisk (Get-VirtualDisk -FriendlyName $virtualDiskFriendlyName)
36 |
37 | Start-Sleep -Seconds 20
38 |
39 | $diskNumber = ((Get-VirtualDisk -FriendlyName $virtualDiskFriendlyName | Get-Disk).Number)
40 |
41 | Write-Verbose 'Creating Partition'
42 |
43 | New-Partition -DiskNumber $diskNumber `
44 | -UseMaximumSize `
45 | -DriveLetter F
46 |
47 | Start-Sleep -Seconds 20
48 |
49 | Write-Verbose 'Formatting Volume and Assigning Drive Letter'
50 |
51 | Format-Volume -DriveLetter F `
52 | -FileSystem NTFS `
53 | -NewFileSystemLabel 'Data' `
54 | -Confirm:$false `
55 | -Force
56 |
57 | Stop-Transcript
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/data-nodes-0disk-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUsername": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Admin username used when provisioning virtual machines"
9 | }
10 | },
11 | "adminPassword": {
12 | "type": "securestring",
13 | "metadata": {
14 | "description": "Admin password used when provisioning virtual machines"
15 | }
16 | },
17 | "storageSettings": {
18 | "type": "object",
19 | "metadata": {
20 | "description": "Storage Account Settings"
21 | }
22 | },
23 | "location": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "Location where resources will be provisioned"
27 | }
28 | },
29 | "subnet": {
30 | "type": "object",
31 | "metadata": {
32 | "description": "The name of the subnet to deploy resources into"
33 | }
34 | },
35 | "vmSize": {
36 | "type": "string",
37 | "defaultValue": "Standard_A1",
38 | "metadata": {
39 | "description": "Size of the Elasticsearch data nodes"
40 | }
41 | },
42 | "vmCount": {
43 | "type": "int",
44 | "defaultValue": 2,
45 | "metadata": {
46 | "description": "Number of Elasticsearch data nodes"
47 | }
48 | },
49 | "osSettings": {
50 | "type": "object",
51 | "metadata": {
52 | "description": "OS settings to deploy on"
53 | }
54 | },
55 | "dataDiskSize": {
56 | "type": "int",
57 | "defaultValue": 1023,
58 | "metadata": {
59 | "description": "Size of each data disk attached to data nodes in (Gb)"
60 | }
61 | },
62 | "namespace": {
63 | "type": "string",
64 | "metadata": {
65 | "description": "The namespace for resources created by this template"
66 | }
67 | }
68 | },
69 | "variables": {
70 | "vmStorageAccountContainerName": "vhd",
71 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
72 | "storageAccountName": "[concat(parameters('storageSettings').prefix)]",
73 | "vmName": "[parameters('namespace')]"
74 | },
75 | "resources": [
76 | {
77 | "type": "Microsoft.Storage/storageAccounts",
78 | "name": "[concat(variables('storageAccountName'), copyindex(1))]",
79 | "apiVersion": "2015-05-01-preview",
80 | "location": "[parameters('location')]",
81 | "copy": {
82 | "name": "[concat(parameters('namespace'),'storageLoop')]",
83 | "count": "[parameters('storageSettings').count]"
84 | },
85 | "properties": {
86 | "accountType": "[parameters('storageSettings').accountType]"
87 | }
88 | },
89 | {
90 | "apiVersion": "2015-06-15",
91 | "type": "Microsoft.Compute/availabilitySets",
92 | "name": "[concat(parameters('namespace'), '-set')]",
93 | "location": "[parameters('location')]",
94 | "properties": {
95 | "platformUpdateDomainCount": 20,
96 | "platformFaultDomainCount": 3
97 | }
98 | },
99 | {
100 | "apiVersion": "2015-06-15",
101 | "type": "Microsoft.Network/publicIPAddresses",
102 | "name": "[concat(parameters('namespace'), '-pip-', copyindex())]",
103 | "location": "[parameters('location')]",
104 | "properties": {
105 | "publicIPAllocationMethod": "Dynamic"
106 | }
107 | },
108 | {
109 | "apiVersion": "2015-06-15",
110 | "type": "Microsoft.Network/networkInterfaces",
111 | "name": "[concat(parameters('namespace'), '-nic-', copyindex())]",
112 | "location": "[parameters('location')]",
113 | "copy": {
114 | "name": "[concat(parameters('namespace'),'nicLoop')]",
115 | "count": "[parameters('vmCount')]"
116 | },
117 | "dependsOn": [
118 | "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyindex())]"
119 | ],
120 | "properties": {
121 | "ipConfigurations": [
122 | {
123 | "name": "ipconfig1",
124 | "properties": {
125 | "privateIPAddress": "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyindex())))]",
126 | "privateIPAllocationMethod": "Static",
127 | "subnet": {
128 | "id": "[variables('subnetRef')]"
129 | }
130 | }
131 | }
132 | ]
133 | }
134 | },
135 | {
136 | "apiVersion": "2015-06-15",
137 | "type": "Microsoft.Compute/virtualMachines",
138 | "name": "[concat(parameters('namespace'), '-vm-', copyindex())]",
139 | "location": "[parameters('location')]",
140 | "copy": {
141 | "name": "[concat(parameters('namespace'), 'virtualMachineLoop')]",
142 | "count": "[parameters('vmCount')]"
143 | },
144 | "dependsOn": [
145 | "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyindex())]",
146 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyindex()])]"
147 | ],
148 | "properties": {
149 | "availabilitySet": {
150 | "id": "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
151 | },
152 | "hardwareProfile": {
153 | "vmSize": "[parameters('vmSize')]"
154 | },
155 | "osProfile": {
156 | "computername": "[concat(parameters('namespace'), '-vm-', copyIndex())]",
157 | "adminUsername": "[parameters('adminUsername')]",
158 | "adminPassword": "[parameters('adminPassword')]"
159 | },
160 | "storageProfile": {
161 | "imageReference": "[parameters('osSettings').imageReference]",
162 | "osDisk": {
163 | "name": "osdisk",
164 | "vhd": {
165 | "uri": "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyindex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyindex(), '-osdisk.vhd')]"
166 | },
167 | "caching": "ReadWrite",
168 | "createOption": "FromImage"
169 | }
170 | },
171 | "networkProfile": {
172 | "networkInterfaces": [
173 | {
174 | "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyindex()))]"
175 | }
176 | ]
177 | }
178 | },
179 | "resources": [
180 | {
181 | "type": "Microsoft.Compute/virtualMachines/extensions",
182 | "name": "[concat(parameters('namespace'),'-vm-', copyindex(), '/createdatadisk')]",
183 | "location": "[parameters('location')]",
184 | "apiVersion": "2015-06-15",
185 | "dependsOn": [
186 | "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyindex())]"
187 | ],
188 | "properties": "[parameters('osSettings').extentionSettings.eventstore]"
189 | }
190 | ]
191 | }
192 | ]
193 | }
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/empty-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "location": {
6 | "type": "string",
7 | "defaultValue": ""
8 | },
9 | "subnet": {
10 | "type": "object",
11 | "defaultValue": {}
12 | },
13 | "storageAccountName": {
14 | "type": "string",
15 | "defaultValue": ""
16 | },
17 | "adminUsername": {
18 | "type": "string",
19 | "defaultValue": ""
20 | },
21 | "adminPassword": {
22 | "type": "securestring",
23 | "defaultValue": ""
24 | },
25 | "osSettings": {
26 | "type": "object",
27 | "defaultValue": {}
28 | },
29 | "vmSize": {
30 | "type": "string",
31 | "defaultValue": ""
32 | },
33 | "vmCount": {
34 | "type": "int",
35 | "defaultValue": 0
36 | },
37 | "lbBackendPools": {
38 | "type": "object",
39 | "defaultValue": {}
40 | }
41 | },
42 | "variables": {},
43 | "resources": [],
44 | "outputs": {}
45 | }
46 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/eventstore-ubuntu-sources.txt:
--------------------------------------------------------------------------------
1 | #
2 | # to do: make this file contents something unbuntu shell script can process natively
3 | #
4 |
5 | "3.8.1": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.8.1.tar.gz",
6 | "3.8.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.8.0.tar.gz",
7 | "3.7.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.7.0.tar.gz",
8 | "3.6.3": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.6.3.tar.gz",
9 | "3.6.2": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.6.2.tar.gz",
10 | "3.6.1": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.6.1.tar.gz",
11 | "3.6.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.6.0.tar.gz",
12 | "3.5.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.5.0.tar.gz",
13 | "3.4.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-14.04-v3.4.0.tar.gz",
14 | "3.3.1": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.3.1.tar.gz",
15 | "3.3.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.3.0.tar.gz",
16 | "3.2.2": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.2.2.tar.gz",
17 | "3.2.1": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.2.1.tar.gz",
18 | "3.2.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.2.0.tar.gz",
19 | "3.1.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.1.0.tar.gz",
20 | "3.0.5": "http://download.geteventstore.com/binaries/EventStore-OSS-Linux-v3.0.5.tar.gz",
21 | "3.0.3": "http://download.geteventstore.com/binaries/EventStore-OSS-Linux-v3.0.3.tar.gz",
22 | "3.0.2": "http://download.geteventstore.com/binaries/EventStore-OSS-Linux-v3.0.2.tar.gz",
23 | "3.0.1": "http://download.geteventstore.com/binaries/EventStore-OSS-Linux-v3.0.1.tar.gz",
24 | "3.0.0": "http://download.geteventstore.com/binaries/EventStore-OSS-Linux-v3.0.0.tar.gz"
25 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/eventstore-windows-sources.csv:
--------------------------------------------------------------------------------
1 | "3.8.1",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.8.1.zip
2 | "3.8.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.8.0.zip
3 | "3.7.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.7.0.zip
4 | "3.6.3",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.6.3.zip
5 | "3.6.2",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.6.2.zip
6 | "3.6.1",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.6.1.zip
7 | "3.6.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.6.0.zip
8 | "3.5.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.5.0.zip
9 | "3.4.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.4.0.zip
10 | "3.3.1",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.3.1.zip
11 | "3.3.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.3.0.zip
12 | "3.2.2",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.2.2.zip
13 | "3.2.1",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.2.1.zip
14 | "3.2.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.2.0.zip
15 | "3.1.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.1.0.zip
16 | "3.0.5",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.5.zip
17 | "3.0.3",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.3.zip
18 | "3.0.2",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.2.zip
19 | "3.0.1",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.1.zip
20 | "3.0.0",http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.0.0.zip
21 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/install-eventstore.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # install_eventstore.ps1
3 | #
4 | param (
5 | [string]
6 | $EventStoreVersion,
7 | [string]
8 | $nssmDownloadUrl,
9 | [string]
10 | $IntIp,
11 | [string]
12 | $ExtIp,
13 | [string]
14 | $ExtIpAdvertiseAs,
15 | [Int]
16 | $ClusterSize = 1,
17 | [Int]
18 | $IntTcpPort = 1112,
19 | [Int]
20 | $ExtTcpPort = 1113,
21 | [Int]
22 | $IntHttpPort = 2112,
23 | [Int]
24 | $ExtHttpPort = 2113,
25 | [string]
26 | $downloadDirectory
27 | )
28 |
29 | function Extract-ZipFile($file, $destination) {
30 | if (![System.IO.Directory]::Exists($destination)) {
31 | [System.IO.Directory]::CreateDirectory($destination)
32 | }
33 |
34 | $shell = new-object -com shell.application
35 | $zip = $shell.NameSpace($file)
36 |
37 | foreach($item in $zip.items()) {
38 | $shell.Namespace($destination).copyhere($item)
39 | }
40 | }
41 |
42 | function Download-FileTo($DownloadUrl, $path) {
43 | $uri = [System.Uri]$DownloadUrl
44 | $filename = $uri.Segments[$uri.Segments.Length-1]
45 | $outFile = Join-Path $path -ChildPath $filename
46 |
47 | Invoke-WebRequest $DownloadUrl -OutFile $outFile | Out-Null
48 | return $outFile
49 | }
50 |
51 | $ErrorActionPreference="SilentlyContinue"
52 | Stop-Transcript | out-null
53 | $ErrorActionPreference = "Continue"
54 | Start-Transcript -path C:\ps-output-es.txt -append -noClobber
55 |
56 | $nssmZip = Download-FileTo -DownloadUrl $nssmDownloadUrl -Path $downloadDirectory
57 | # NSSM is packed with in a folder already
58 | Extract-ZipFile -File $nssmZip -Destination F:\
59 |
60 | $url = (Import-Csv -Header Version,Url -Path eventstore-windows-sources.csv | Where-Object { $_.Version -eq $esVer }).Url
61 | $eventStoreZip = Download-FileTo -DownloadUrl $url -Path $downloadDirectory
62 | Extract-ZipFile -File $eventStoreZip -Destination F:\eventstore\bin\
63 |
64 | #
65 | #
66 | #
67 | $ipAddress = (Resolve-DnsName $env:COMPUTERNAME -Type A).IPAddress
68 |
69 | #Database Node Internal HTTP Interface (open source and commercial)
70 | #netsh http add urlacl url=http://${ipAddress}:${IntHttpPort}/ user="NT AUTHORITY\LOCAL SERVICE"
71 |
72 | # Database Node External HTTP Interface (open source and commercial)
73 | #netsh http add urlacl url=http://${ipAddress}:${ExtHttpPort}/ user="NT AUTHORITY\LOCAL SERVICE"
74 |
75 | # Manager Node Internal HTTP Interface (commercial only)
76 | #netsh http add urlacl url=http://$ipAddress:30777/ user="NT AUTHORITY\LOCAL SERVICE"
77 |
78 | # Manager Node External HTTP Interface (commercial only)
79 | #netsh http add urlacl url=http://$ipAddress:30778/ user="NT AUTHORITY\LOCAL SERVICE"
80 |
81 | New-NetFirewallRule -Name Allow_EventStore_Int_In `
82 | -DisplayName "Allow inbound Internal Event Store traffic" `
83 | -Protocol TCP `
84 | -Direction Inbound `
85 | -Action Allow `
86 | -LocalPort $IntTcpPort,$ExtTcpPort
87 |
88 | New-NetFirewallRule -Name Allow_EventStore_Ext_In `
89 | -DisplayName "Allow inbound External Event Store traffic" `
90 | -Protocol TCP `
91 | -Direction Inbound `
92 | -Action Allow `
93 | -LocalPort $IntHttpPort,$ExtHttpPort
94 |
95 | # SET COMMON_OPTS=-MemDb -Log D:\eventstore\logs -ClusterSize 3 -DiscoverViaDns false -GossipSeed %IP0%:2112,%IP1%:2112,%IP2%:2112
96 | #
97 | # EventStore.ClusterNode.exe %COMMON_OPTS% -IntIp %IP0% -ExtIp %IP0% -ExtIpAdvertiseAs %PIP0%
98 | # EventStore.ClusterNode.exe %COMMON_OPTS% -IntIp %IP1% -ExtIp %IP1% -ExtIpAdvertiseAs %PIP1%
99 | # EventStore.ClusterNode.exe %COMMON_OPTS% -IntIp %IP2% -ExtIp %IP2% -ExtIpAdvertiseAs %PIP2%
100 |
101 | Add-Content F:\eventstore\config.yaml "# default Event Store configuration file`n"
102 | Add-Content F:\eventstore\config.yaml "Db: F:\eventstore\data`n"
103 | Add-Content F:\eventstore\config.yaml "Log: D:\eventstore\logs`n"
104 | Add-Content F:\eventstore\config.yaml "IntIp: $ipAddress`n"
105 | # Don't need these, locking down the ES behind NGinx
106 | # Add-Content F:\eventstore\config.yaml "ExtIp: $ipAddress`n"
107 | # Add-Content F:\eventstore\config.yaml "ExtIpAdvertiseAs: $ExtIpAdvertiseAs`n"
108 | Add-Content F:\eventstore\config.yaml "ClusterSize: $ClusterSize`n"
109 | Add-Content F:\eventstore\config.yaml "DiscoverViaDns: false`n"
110 | Add-Content F:\eventstore\config.yaml "GossipSeed: 10.0.1.4:$IntHttpPort,10.0.1.5:$IntHttpPort,10.0.1.6:$IntHttpPort`n"
111 |
112 | Add-Content F:\eventstore\install-service.cmd "F:\nssm-2.24\win64\nssm.exe install EventStore F:\eventstore\bin\EventStore.ClusterNode.exe --config F:\eventstore\config.yaml"
113 | Add-Content F:\eventstore\install-service.cmd "F:\nssm-2.24\win64\nssm.exe set EventStore Description ""The EventStore service"""
114 |
115 | Add-Content F:\eventstore\start-service.cmd "net start EventStore"
116 | Add-Content F:\eventstore\stop-service.cmd "net stop EventStore"
117 |
118 | . F:\eventstore\install-service.cmd
119 | . F:\eventstore\start-service.cmd
120 |
121 | Stop-Transcript
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/install-nginx.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # install_nginx.ps1
3 | #
4 | param (
5 | [string]
6 | $NGinxVersion,
7 | [string]
8 | $NGinxDownloadUrl,
9 | [string]
10 | $downloadDirectory
11 | )
12 |
13 | function Extract-ZipFile($file, $destination) {
14 | if (![System.IO.Directory]::Exists($destination)) {
15 | [System.IO.Directory]::CreateDirectory($destination)
16 | }
17 |
18 | $shell = new-object -com shell.application
19 | $zip = $shell.NameSpace($file)
20 |
21 | foreach($item in $zip.items()) {
22 | $shell.Namespace($destination).copyhere($item)
23 | }
24 | }
25 |
26 | function Download-FileTo($DownloadUrl, $path) {
27 | $uri = [System.Uri]$DownloadUrl
28 | $filename = $uri.Segments[$uri.Segments.Length-1]
29 | $outFile = Join-Path $path -ChildPath $filename
30 |
31 | Invoke-WebRequest $DownloadUrl -OutFile $outFile | Out-Null
32 | return $outFile
33 | }
34 |
35 | $ErrorActionPreference="SilentlyContinue"
36 | Stop-Transcript | out-null
37 | $ErrorActionPreference = "Continue"
38 | Start-Transcript -path C:\ps-output-nginx.txt -append -noClobber
39 |
40 | $nginxZip = Download-FileTo -DownloadUrl $NGinxDownloadUrl -Path $downloadDirectory
41 | Extract-ZipFile -File $nginxZip -Destination F:\nginx\bin\
42 |
43 | New-NetFirewallRule -Name Allow_80_In `
44 | -DisplayName "Allow inbound port 80 traffic" `
45 | -Protocol TCP `
46 | -Direction Inbound `
47 | -Action Allow `
48 | -LocalPort 80
49 |
50 | Add-Content F:\nginx\install-service.cmd "F:\nssm-2.24\win64\nssm.exe install Nginx F:\nginx\bin\nginx-1.10.1\nginx.exe"
51 | Add-Content F:\nginx\install-service.cmd "F:\nssm-2.24\win64\nssm.exe set Nginx Description ""The Nginx service"""
52 |
53 | Add-Content F:\nginx\start-service.cmd "net start Nginx"
54 | Add-Content F:\nginx\stop-service.cmd "net stop Nginx"
55 |
56 | . F:\nginx\install-service.cmd
57 | . F:\nginx\start-service.cmd
58 |
59 | Stop-Transcript
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/jumpbox-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "namespace": {
6 | "type": "string",
7 | "defaultValue": "jumpbox",
8 | "metadata": {
9 | "description": "The namespace prefix for resources created by this template"
10 | }
11 | },
12 | "location": {
13 | "type": "string",
14 | "metadata": {
15 | "description": "Location where resources will be provisioned"
16 | }
17 | },
18 | "subnet": {
19 | "type": "object",
20 | "metadata": {
21 | "description": "Subnet object for provisioning resources in (expects properties name as the subnet name, and vnet as the virtual network name on the object)"
22 | }
23 | },
24 | "storageAccountName": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "Existing Storage Account where the Virtual Machine's disks will be placed"
28 | }
29 | },
30 | "adminUsername": {
31 | "type": "string",
32 | "metadata": {
33 | "description": "Administrator user name used when provisioning virtual machines"
34 | }
35 | },
36 | "adminPassword": {
37 | "type": "securestring",
38 | "metadata": {
39 | "description": "Administrator password used when provisioning virtual machines"
40 | }
41 | },
42 | "osSettings": {
43 | "type": "object",
44 | "metadata": {
45 | "description": "Elasticsearch deployment platform settings"
46 | }
47 | }
48 | },
49 | "variables": {
50 | "vmStorageAccountContainerName": "vhd",
51 | "vmSize": "Standard_A0",
52 | "subnetRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]",
53 | "vmName": "[concat(parameters('namespace'), '-vm')]",
54 | "publicIpName": "[concat(parameters('namespace'), '-pip')]",
55 | "securityGroupName": "[concat(parameters('namespace'), '-nsg')]",
56 | "nicName": "[concat(parameters('namespace'), '-nic')]"
57 | },
58 | "resources": [
59 | {
60 | "apiVersion": "2015-06-15",
61 | "type": "Microsoft.Network/networkSecurityGroups",
62 | "name": "[variables('securityGroupName')]",
63 | "location": "[parameters('location')]",
64 | "properties": {
65 | "securityRules": [
66 | {
67 | "name": "SSH",
68 | "properties": {
69 | "description": "Allows SSH traffic",
70 | "protocol": "Tcp",
71 | "sourcePortRange": "[parameters('osSettings').managementPort]",
72 | "destinationPortRange": "[parameters('osSettings').managementPort]",
73 | "sourceAddressPrefix": "*",
74 | "destinationAddressPrefix": "*",
75 | "access": "Allow",
76 | "priority": 100,
77 | "direction": "Inbound"
78 | }
79 | }
80 | ]
81 | }
82 | },
83 | {
84 | "apiVersion": "2015-06-15",
85 | "type": "Microsoft.Network/publicIPAddresses",
86 | "name": "[variables('publicIpName')]",
87 | "location": "[parameters('location')]",
88 | "properties": {
89 | "publicIPAllocationMethod": "Dynamic"
90 | }
91 | },
92 | {
93 | "apiVersion": "2015-06-15",
94 | "type": "Microsoft.Network/networkInterfaces",
95 | "name": "[variables('nicName')]",
96 | "location": "[parameters('location')]",
97 | "dependsOn": [
98 | "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIpName'))]",
99 | "[concat('Microsoft.Network/networkSecurityGroups/', variables('securityGroupName'))]"
100 | ],
101 | "properties": {
102 | "ipConfigurations": [
103 | {
104 | "name": "ipconfig1",
105 | "properties": {
106 | "privateIPAllocationMethod": "Dynamic",
107 | "publicIPAddress": {
108 | "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIpName'))]"
109 | },
110 | "subnet": {
111 | "id": "[variables('subnetRef')]"
112 | },
113 | "networkSecurityGroup": {
114 | "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('securityGroupName'))]"
115 | }
116 | }
117 | }
118 | ]
119 | }
120 | },
121 | {
122 | "apiVersion": "2015-06-15",
123 | "type": "Microsoft.Compute/virtualMachines",
124 | "name": "[variables('vmName')]",
125 | "location": "[parameters('location')]",
126 | "dependsOn": [
127 | "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
128 | ],
129 | "properties": {
130 | "hardwareProfile": {
131 | "vmSize": "[variables('vmSize')]"
132 | },
133 | "osProfile": {
134 | "computerName": "[variables('vmName')]",
135 | "adminUsername": "[parameters('adminUsername')]",
136 | "adminPassword": "[parameters('adminPassword')]"
137 | },
138 | "storageProfile": {
139 | "imageReference": "[parameters('osSettings').imageReference]",
140 | "osDisk": {
141 | "name": "osdisk",
142 | "vhd": {
143 | "uri": "[concat('http://', parameters('storageAccountName'),'.blob.core.windows.net/vhd/', variables('vmName'), '-osdisk.vhd')]"
144 | },
145 | "caching": "ReadWrite",
146 | "createOption": "FromImage"
147 | }
148 | },
149 | "networkProfile": {
150 | "networkInterfaces": [
151 | {
152 | "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
153 | }
154 | ]
155 | }
156 | }
157 | }
158 | ],
159 | "outputs": {}
160 | }
161 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/master.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # master.ps1
3 | #
4 | param(
5 | [Int32]$ClusterSize,
6 | [string]$esVer,
7 | [string]$nginxVer="1.10.1",
8 | [string]$nginxUrl="https://landdb.blob.core.windows.net/eventstore-cluster-resources/nginx-1.10.1.zip"
9 | )
10 |
11 | $ErrorActionPreference="SilentlyContinue"
12 | Stop-Transcript | out-null
13 | $ErrorActionPreference = "Continue"
14 | Start-Transcript -path C:\ps-output-master.txt -append -noClobber
15 |
16 | $downloadDirectory = 'D:\download'
17 | New-Item $downloadDirectory -ItemType Directory | Out-Null
18 |
19 | . .\create-data-disks.ps1
20 |
21 | # TODO: These parameters should come from the template!
22 | . .\install-eventstore.ps1 -EventStoreVersion $esVer `
23 | -nssmDownloadUrl "https://nssm.cc/release/nssm-2.24.zip" `
24 | -ClusterSize $ClusterSize `
25 | -downloadDirectory $downloadDirectory
26 |
27 | . .\install-nginx.ps1 -NGinxVersion $nginxVer `
28 | -NGinxDownloadUrl $nginxUrl `
29 | -downloadDirectory $downloadDirectory
30 |
31 | Stop-Transcript
32 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/shared-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "location": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "Location where resources will be provisioned"
9 | }
10 | },
11 | "networkSettings": {
12 | "type": "object",
13 | "metadata": {
14 | "description": "Network settings object"
15 | }
16 | },
17 | "storageAccountName": {
18 | "type": "string",
19 | "metadata": {
20 | "description": "Storage account used for share virtual machine images"
21 | }
22 | },
23 | "subnet": {
24 | "type": "string",
25 | "metadata": {
26 | "description": "The name of the subnet to use from the network settings."
27 | }
28 | }
29 | },
30 | "variables": {
31 | },
32 | "resources": [
33 | {
34 | "apiVersion": "2015-06-15",
35 | "type": "Microsoft.Network/networkSecurityGroups",
36 | "name": "[parameters('networkSettings').networkSecurityGroupName]",
37 | "location": "[parameters('location')]",
38 | "properties": {
39 | "securityRules": [
40 | {
41 | "name": "Allow-EventStore-Web-HTTP",
42 | "properties": {
43 | "description": "Allows inbound web traffic from anyone",
44 | "protocol": "Tcp",
45 | "sourcePortRange": "*",
46 | "destinationPortRange": "80",
47 | "sourceAddressPrefix": "Internet",
48 | "destinationAddressPrefix": "VirtualNetwork",
49 | "access": "Allow",
50 | "priority": 100,
51 | "direction": "Inbound"
52 | }
53 | },
54 | {
55 | "name": "Allow-EventStore-TCP",
56 | "properties": {
57 | "description": "Allows inbound EventStore TCP traffic from anyone",
58 | "protocol": "Tcp",
59 | "sourcePortRange": "*",
60 | "destinationPortRange": "1113",
61 | "sourceAddressPrefix": "Internet",
62 | "destinationAddressPrefix": "VirtualNetwork",
63 | "access": "Allow",
64 | "priority": 110,
65 | "direction": "Inbound"
66 | }
67 | },
68 | {
69 | "name": "Allow-EventStore-HTTP",
70 | "properties": {
71 | "description": "Allows inbound EventStore HTTP traffic from anyone",
72 | "protocol": "Tcp",
73 | "sourcePortRange": "*",
74 | "destinationPortRange": "2113",
75 | "sourceAddressPrefix": "Internet",
76 | "destinationAddressPrefix": "VirtualNetwork",
77 | "access": "Allow",
78 | "priority": 120,
79 | "direction": "Inbound"
80 | }
81 | }
82 | ]
83 | }
84 | },
85 | {
86 | "type": "Microsoft.Storage/storageAccounts",
87 | "name": "[parameters('storageAccountName')]",
88 | "apiVersion": "2015-05-01-preview",
89 | "location": "[parameters('location')]",
90 | "properties": {
91 | "accountType": "Standard_LRS"
92 | }
93 | },
94 | {
95 | "apiVersion": "2015-06-15",
96 | "dependsOn": [
97 | "[concat('Microsoft.Network/networkSecurityGroups/', parameters('networkSettings').networkSecurityGroupName)]"
98 | ],
99 | "type": "Microsoft.Network/virtualNetworks",
100 | "name": "[parameters('networkSettings').virtualNetworkName]",
101 | "location": "[parameters('location')]",
102 | "properties": {
103 | "addressSpace": {
104 | "addressPrefixes": [
105 | "[parameters('networkSettings').addressPrefix]"
106 | ]
107 | },
108 | "subnets": [
109 | {
110 | "name": "[parameters('networkSettings').subnet[parameters('subnet')].name]",
111 | "properties": {
112 | "addressPrefix": "[parameters('networkSettings').subnet[parameters('subnet')].prefix]",
113 | "networkSecurityGroup": {
114 | "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSettings').networkSecurityGroupName)]"
115 | }
116 | }
117 | }
118 | ]
119 | }
120 | }
121 | ]
122 | }
123 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Templates/tmpl/data-nodes.yml:
--------------------------------------------------------------------------------
1 | "$schema": https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#
2 | contentVersion: 1.0.0.0
3 | parameters:
4 | adminUsername:
5 | type: string
6 | metadata:
7 | description: Admin username used when provisioning virtual machines
8 | adminPassword:
9 | type: securestring
10 | metadata:
11 | description: Admin password used when provisioning virtual machines
12 | storageSettings:
13 | type: object
14 | metadata:
15 | description: Storage Account Settings
16 | location:
17 | type: string
18 | metadata:
19 | description: Location where resources will be provisioned
20 | subnet:
21 | type: object
22 | metadata:
23 | description: The name of the subnet to deploy resources into
24 | vmSize:
25 | type: string
26 | defaultValue: Standard_A1
27 | metadata:
28 | description: Size of the Elasticsearch data nodes
29 | vmCount:
30 | type: int
31 | defaultValue: 2
32 | metadata:
33 | description: Number of Elasticsearch data nodes
34 | osSettings:
35 | type: object
36 | metadata:
37 | description: OS settings to deploy on
38 | dataDiskSize:
39 | type: int
40 | defaultValue: 1023
41 | metadata:
42 | description: Size of each data disk attached to data nodes in (Gb)
43 | namespace:
44 | type: string
45 | metadata:
46 | description: The namespace for resources created by this template
47 | variables:
48 | vmStorageAccountContainerName: vhd
49 | subnetRef: "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('subnet').vnet), '/subnets/', parameters('subnet').name)]"
50 | storageAccountName: "[concat(parameters('storageSettings').prefix)]"
51 | vmName: "[parameters('namespace')]"
52 | resources:
53 | - type: Microsoft.Storage/storageAccounts
54 | name: "[concat(variables('storageAccountName'), copyindex(1))]"
55 | apiVersion: 2015-05-01-preview
56 | location: "[parameters('location')]"
57 | copy:
58 | name: "[concat(parameters('namespace'),'storageLoop')]"
59 | count: "[parameters('storageSettings').count]"
60 | properties:
61 | accountType: "[parameters('storageSettings').accountType]"
62 | - apiVersion: '2015-06-15'
63 | type: Microsoft.Compute/availabilitySets
64 | name: "[concat(parameters('namespace'), '-set')]"
65 | location: "[parameters('location')]"
66 | properties:
67 | platformUpdateDomainCount: 20
68 | platformFaultDomainCount: 3
69 | - apiVersion: '2015-06-15'
70 | type: Microsoft.Network/publicIPAddresses
71 | name: "[concat(parameters('namespace'), '-pip-', copyindex())]"
72 | location: "[parameters('location')]"
73 | properties:
74 | publicIPAllocationMethod: Dynamic
75 | - apiVersion: '2015-06-15'
76 | type: Microsoft.Network/networkInterfaces
77 | name: "[concat(parameters('namespace'), '-nic-', copyindex())]"
78 | location: "[parameters('location')]"
79 | copy:
80 | name: "[concat(parameters('namespace'),'nicLoop')]"
81 | count: "[parameters('vmCount')]"
82 | dependsOn:
83 | - "[concat('Microsoft.Network/publicIPAddresses/', parameters('namespace'), '-pip-', copyindex())]"
84 | properties:
85 | ipConfigurations:
86 | - name: ipconfig1
87 | properties:
88 | privateIPAddress: "[concat(parameters('subnet').networkPrefix, '.', string(add(4,copyindex())))]"
89 | privateIPAllocationMethod: Static
90 | subnet:
91 | id: "[variables('subnetRef')]"
92 | - apiVersion: '2015-06-15'
93 | type: Microsoft.Compute/virtualMachines
94 | name: "[concat(parameters('namespace'), '-vm-', copyindex())]"
95 | location: "[parameters('location')]"
96 | copy:
97 | name: "[concat(parameters('namespace'), 'virtualMachineLoop')]"
98 | count: "[parameters('vmCount')]"
99 | dependsOn:
100 | - "[concat('Microsoft.Network/networkInterfaces/', parameters('namespace'), '-nic-', copyindex())]"
101 | - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), parameters('storageSettings').mapping[copyindex()])]"
102 | properties:
103 | availabilitySet:
104 | id: "[resourceId('Microsoft.Compute/availabilitySets', concat(parameters('namespace'), '-set'))]"
105 | hardwareProfile:
106 | vmSize: "[parameters('vmSize')]"
107 | osProfile:
108 | computername: "[concat(parameters('namespace'), '-vm-', copyIndex())]"
109 | adminUsername: "[parameters('adminUsername')]"
110 | adminPassword: "[parameters('adminPassword')]"
111 | storageProfile:
112 | imageReference: "[parameters('osSettings').imageReference]"
113 | osDisk:
114 | name: osdisk
115 | vhd:
116 | uri: "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyindex()], '.blob.core.windows.net/vhds/', variables('vmName'), '-vm-', copyindex(), '-osdisk.vhd')]"
117 | caching: ReadWrite
118 | createOption: FromImage
119 | dataDisks:
120 | - name: datadisk::index
121 | diskSizeGB: "[parameters('dataDiskSize')]"
122 | lun: 0
123 | vhd:
124 | uri: "[concat('http://', variables('storageAccountName'), parameters('storageSettings').mapping[copyindex()],'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', parameters('namespace'),'-vm-', copyindex(),'dataDisk::index' ,'.vhd')]"
125 | caching: None
126 | createOption: Empty
127 | networkProfile:
128 | networkInterfaces:
129 | - id: "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('namespace'),'-nic-', copyindex()))]"
130 | resources:
131 | - type: Microsoft.Compute/virtualMachines/extensions
132 | name: "[concat(parameters('namespace'),'-vm-', copyindex(), '/createdatadisk')]"
133 | location: "[parameters('location')]"
134 | apiVersion: '2015-06-15'
135 | dependsOn:
136 | - "[concat('Microsoft.Compute/virtualMachines/', parameters('namespace'), '-vm-', copyindex())]"
137 | properties: "[parameters('osSettings').extentionSettings.eventstore]"
138 |
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/AzCopy.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/AzCopy.exe
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.Edm.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.Edm.dll
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.OData.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.OData.dll
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.Services.Client.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/Microsoft.Data.Services.Client.dll
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/Microsoft.WindowsAzure.Storage.DataMovement.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/Microsoft.WindowsAzure.Storage.DataMovement.dll
--------------------------------------------------------------------------------
/azure-resource-manager/EventStoreCluster/Tools/Microsoft.WindowsAzure.Storage.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pbolduc/EventStore-DevOps/5ee8b2c6fcfcef55900cf54b5990af6184794b4c/azure-resource-manager/EventStoreCluster/Tools/Microsoft.WindowsAzure.Storage.dll
--------------------------------------------------------------------------------
/azure-resource-manager/README.md:
--------------------------------------------------------------------------------
1 | # Install Event Store cluster on Virtual Machines
2 |
3 |
4 |
5 |
6 |
7 | Create a multi-machine Event Store cluster on Windows (Ubuntu is not complete). This template is heavily influenced by the [Elasticsearch cluster on Virtual Machines](https://github.com/Azure/azure-quickstart-templates/tree/master/elasticsearch) template sample on GitHub.
8 |
9 | Parameters | Default | Description
10 | ------------- | ------------- | -------------
11 | adminUsername | | The operating system admin username used when provisioning virtual machines
12 | adminPassword | | The operating system admin password used when provisioning virtual machines
13 | location | ResourceGroup | Location where resources will be provisioned. A value of 'ResourceGroup' will deploy the resource to the same location of the resource group the resources are provisioned into
14 | virtualNetworkName | es-vnet | Virtual Network name
15 | OS | windows | The operating system to install on the VM. Allowed values are: windows or ubuntu. (*ubuntu is not complete*)
16 | jumpbox | No | Optionally add a virtual machine to the deployment which you can use to connect and manage virtual machines on the internal network
17 | vmEventStoreNodeCount | 1 | Number of Event Store nodes to provision. The number must be odd. The template limits this to 9.
18 | vmSizeEventStoreNode | Standard_D2 | The VM size to deploy
19 | vmEventStoreDataDiskSize | 4 | Size of each data disk attached to data nodes in (Gb). Each VM size will be provisioned with the maximum number of data disks to maximize the IOPS. In Windows, you can only pool disks that have at least 4GB of contiguous unallocated space. Setting this less than 4 will prevent striping of data disks and the installation will fail.
20 | esVersion | 3.8.1 | The Event Store version to install
21 | githubAccount | pbolduc | The github parameters allow changing the template root URL. This allows customization of the source location install scripts that are uploaded to azure for provisioning.
22 | githubProject | EventStore-DevOps |
23 | githubBranch | master |
24 |
25 |
26 | * a Storage Account for OS Disks
27 | * one or more storage accounts for data disks
28 | * each VM will have multiple data disks striped together for higher IOPS (based on the maximum number of data disks allowed for VM size)
29 | * an Availability Set
30 | * a Virtual Network with a single subnet with 16 available addresses
31 | * a Network Security Group
32 | * a Public IP address for each node
33 | * a NIC for each node
34 | * a VM for each node
35 |
36 | ## Network Security Group configuration
37 |
38 | The network security is setup in [shared-resources.json](EventStoreCluster/Templates/shared-resources.json)
39 |
40 | * Allow Inbound TCP on port 80
41 | * Allow Inbound TCP on port 1113
42 | * Allow Inbound TCP on port 2113
43 |
--------------------------------------------------------------------------------
/vagrant-eventstore-cluster/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant
2 | Berksfile.lock
3 |
--------------------------------------------------------------------------------
/vagrant-eventstore-cluster/Berksfile:
--------------------------------------------------------------------------------
1 | source "https://supermarket.chef.io"
2 |
3 | cookbook 'eventstore', github: 'pbolduc/eventstore-cookbook'
4 |
--------------------------------------------------------------------------------
/vagrant-eventstore-cluster/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/vagrant-eventstore-cluster/README.md:
--------------------------------------------------------------------------------
1 | # vagrant-eventstore-cluster
2 |
3 |
4 | **Note**: cloned from [seif/vagrant-eventstore-cluster](https://github.com/seif/vagrant-eventstore-cluster)
5 |
6 |
7 | Vagrant files to setup a local EventStore cluster using OpsCode Chef Cookbook
8 |
9 | > This is a work in progress.
10 | > Cluster and gossip seem to be setup correctly now, but having issues with Projections.
11 |
12 | ## Usage
13 |
14 | ### Install Vagrant
15 |
16 | Download and install [Vagrant](http://downloads.vagrantup.com/).
17 |
18 | ### Install Vagrant plugins
19 |
20 | ``` bash
21 | vagrant plugin install vagrant-berkshelf
22 | vagrant plugin install vagrant-omnibus
23 | vagrant plugin install vagrant-cachier
24 | ```
25 |
26 | ### Clone this repository
27 |
28 | ``` bash
29 | git clone https://github.com/seif/vagrant-eventstore-cluster.git
30 | cd vagrant-eventstore-cluster
31 | ```
32 |
33 | ### Start the cluster
34 |
35 | ``` bash
36 | vagrant up
37 | ```
38 |
39 | Wait for all operations to complete, the cluster nodes should now be available at the address 33.33.33.10, 33.33.33.20 and 33.33.33.30
40 |
41 | ## Customising
42 |
43 | ### Vagrant configuration
44 |
45 | There are some variables at the top of the file which you can use to customise the cluster:
46 |
47 | * **NODE_COUNT:** The number of nodes in the cluster.
48 | * **IP_INCREMENT:** How much to increment the ip of each node by.
49 | * **BASE_IP:** The first 3 octects that will make up the ip, the last octet is made up of the IP_INCREMENT * node index.
50 |
51 | ### EventStore configuration
52 |
53 | The [Event Store cookbook](http://community.opscode.com/cookbooks/eventstore) is used to provision the machines.
54 |
55 | EventStore configuration parameters can be passed in by modifying the Vagrantfile and adding some keys/values to the eventstore/config hash. Any added keys will be put into the /etc/eventstore/config.json file.
56 |
57 |
58 |
--------------------------------------------------------------------------------
/vagrant-eventstore-cluster/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | NODE_COUNT = 3
5 | BASE_IP = "33.33.33"
6 | IP_INCREMENT = 10
7 |
8 | seeds = []
9 |
10 | (1..NODE_COUNT).each do |index|
11 | last_octet = index * IP_INCREMENT
12 | node_ip = "#{BASE_IP}.#{last_octet}"
13 | seeds << {'index' => index,
14 | 'name' => "node#{index}",
15 | 'ip' => node_ip}
16 | end
17 |
18 | Vagrant.configure("2") do |cluster|
19 | # Install latest chef on the client node, requires vagrant-omnibus plugin
20 | cluster.omnibus.chef_version = :latest
21 |
22 | # Configure caching, so that cache can be shared among nodes, minimising downloads. Requires vagrant-cachier plugin
23 | # Uncomment next line to enable cachier, seems to cause problems on windows
24 | cluster.cache.auto_detect = true
25 |
26 | # Enable berkshelf because it makes manages cookbooks much simpler. Required vagrant-berkshelf plugin
27 | cluster.berkshelf.enabled = true
28 |
29 |
30 | seeds.each do |seed|
31 | cluster.vm.define seed['name'] do |config|
32 | config.vm.box = "ubuntu/trusty64"
33 | config.vm.provider(:virtualbox) { |v| v.customize ["modifyvm", :id, "--memory", 1024] }
34 |
35 | config.vm.hostname = seed['name']
36 | config.vm.network :private_network, ip: seed['ip']
37 |
38 | # Provision using Chef.
39 | config.vm.provision :chef_solo do |chef|
40 | chef.json = {
41 | :eventstore => {
42 | :config => {
43 | :IntIp => seed['ip'],
44 | :ExtIp => seed['ip'],
45 | :IntHttpPort => 2112,
46 | :ExtHttpPort => 2113,
47 | :IntTcpPort => 1112,
48 | :ExtTcpPort => 1113,
49 | :ClusterSize => NODE_COUNT,
50 | :DiscoverViaDns => false,
51 | :GossipSeed => seeds.reject{|s| s['index'] == seed['index']}.map{|i| "#{i['ip']}:2112"}
52 | }
53 | }
54 | }
55 | chef.add_recipe "eventstore"
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------