diff --git a/reference-architecture/azure-ansible/BUGS.md b/reference-architecture/azure-ansible/BUGS.md
new file mode 100755
index 000000000..80692a332
--- /dev/null
+++ b/reference-architecture/azure-ansible/BUGS.md
@@ -0,0 +1 @@
+Bugs
diff --git a/reference-architecture/azure-ansible/README.md b/reference-architecture/azure-ansible/README.md
new file mode 100755
index 000000000..03f6e36da
--- /dev/null
+++ b/reference-architecture/azure-ansible/README.md
@@ -0,0 +1,74 @@
+# Red Hat OpenShift Container Platform on Azure
+
+When creating the Red Hat OpenShift Container Platform on Azure, you will need a SSH RSA key for access.
+
+## SSH Key Generation
+
+1. [Windows](ssh_windows.md)
+2. [Linux](ssh_linux.md)
+3. [Mac](ssh_mac.md)
+
+## Create the Installation
+### Create the Installation on the Azure Portal
+
+
+
+
+
+
+
+
+
+## Parameters
+
+For macOS:
+
+1. SSHKeyData - Public Key - Copy/Paste from .ssh/id_rsa.pub - pbcopy < ~/.ssh/id_rsa.pub
+
+2. PoolId - From RHEL - subscription-manager list --available
+
+3. SSHPrivate Data - Base64 Encoded id_rsa - cat ~/.ssh/id_rsa | base64 | pbcopy
+
+For RHEL/Fedora/CentOS:
+
+1. SSHKeyData - Public Key - Copy/Paste from .ssh/id_rsa.pub - xclip -selection clipboard < ~/.ssh/id_rsa.pub
+
+2. PoolId - From RHEL - subscription-manager list --available
+
+3. SSHPrivate Data - Base64 Encoded id_rsa - cat ~/.ssh/id_rsa | base64 | xclip -selection clipboard
+
+### Input Parameters
+
+| Name| Type | Description |
+| ------------- | ------------- | ------------- |
+| adminUsername | String | Username for SSH Login and OpenShift Webconsole |
+| adminPassword | SecureString | Password for the OpenShift Webconsole |
+| sshKeyData | String | Public SSH Key for the Virtual Machines |
+| masterDnsName | String | DNS Prefix for the OpenShift Master / Webconsole |
+| numberOfNodes | Integer | Number of OpenShift Nodes to create |
+| masterVMSize | String | The size of the Master Virtual Machine |
+| infranodeVMSize| String | The size of the Infranode Virtual Machine |
+| nodeVMSize| String | The size of the each Node Virtual Machine |
+
+### Output Parameters
+
+| Name| Type | Description |
+| ------------- | ------------- | ------------- |
+| OpenShift Webconsole | String | URL of the OpenShift Webconsole |
+| OpenShift Master ssh |String | SSH String to Login at the Master |
+| OpenShift Router Public IP | String | Router Public IP. Needed if you want to create your own Wildcard DNS |
+
+------
+
+This template deploys Red Hat OpenShift on Azure.
+
+Attribution:
+
+Thanks to:
+Daniel Falkner - Microsoft Germany - For original templates.
+
+Harold Wong for his great support.
+
+Ivan McKinley
+
+For full commit history: Please see - https://github.com/glennswest/azure-openshift/
diff --git a/reference-architecture/azure-ansible/azuredeploy.json b/reference-architecture/azure-ansible/azuredeploy.json
new file mode 100755
index 000000000..b4b5b3894
--- /dev/null
+++ b/reference-architecture/azure-ansible/azuredeploy.json
@@ -0,0 +1,970 @@
+{
+ "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "adminUsername" : {
+ "type" : "string",
+ "minLength" : 1,
+ "metadata" : {
+ "description" : "User name for the Virtual Machine and OpenShift Webconsole."
+ }
+ },
+ "adminPassword" : {
+ "type" : "securestring",
+ "metadata" : {
+ "description" : "User password for the OpenShift Webconsole"
+ }
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "WildcardZone" : {
+ "type" : "string",
+ "minLength" : 1,
+ "metadata" : {
+ "description" : "Globally unique wildcard DNS domain for app access."
+ }
+ },
+ "numberOfNodes" : {
+ "type" : "int",
+ "defaultValue" : 3,
+ "minValue" : 3,
+ "maxValue" : 30,
+ "metadata" : {
+ "description" : "Number of OpenShift Nodes to deploy (max 30)"
+ }
+ },
+ "image" : {
+ "type" : "string",
+ "allowedValues" : [
+ "rhel"
+ ],
+ "defaultValue" : "rhel",
+ "metadata" : {
+ "description" : "OS to use.Red Hat Enterprise Linux"
+ }
+ },
+ "masterVMSize" : {
+ "type" : "string",
+ "defaultValue" : "Standard_DS3",
+ "allowedValues" : [
+ "Standard_A0",
+ "Standard_A1",
+ "Standard_A2",
+ "Standard_A3",
+ "Standard_A4",
+ "Standard_A5",
+ "Standard_A6",
+ "Standard_A7",
+ "Standard_A8",
+ "Standard_A9",
+ "Standard_A10",
+ "Standard_A11",
+ "Standard_D1",
+ "Standard_D2",
+ "Standard_D3",
+ "Standard_D4",
+ "Standard_D11",
+ "Standard_D12",
+ "Standard_D13",
+ "Standard_D14",
+ "Standard_D1_v2",
+ "Standard_D2_v2",
+ "Standard_D3_v2",
+ "Standard_D4_v2",
+ "Standard_D5_v2",
+ "Standard_D11_v2",
+ "Standard_D12_v2",
+ "Standard_D13_v2",
+ "Standard_D14_v2",
+ "Standard_G1",
+ "Standard_G2",
+ "Standard_G3",
+ "Standard_G4",
+ "Standard_G5",
+ "Standard_DS1",
+ "Standard_DS2",
+ "Standard_DS3",
+ "Standard_DS4",
+ "Standard_DS11",
+ "Standard_DS12",
+ "Standard_DS13",
+ "Standard_DS14",
+ "Standard_GS1",
+ "Standard_GS2",
+ "Standard_GS3",
+ "Standard_GS4",
+ "Standard_GS5"
+ ],
+ "metadata" : {
+ "description" : "The size of the Master Virtual Machine."
+ }
+ },
+ "infranodeVMSize" : {
+ "type" : "string",
+ "defaultValue" : "Standard_DS2",
+ "allowedValues" : [
+ "Standard_A0",
+ "Standard_A1",
+ "Standard_A2",
+ "Standard_A3",
+ "Standard_A4",
+ "Standard_A5",
+ "Standard_A6",
+ "Standard_A7",
+ "Standard_A8",
+ "Standard_A9",
+ "Standard_A10",
+ "Standard_A11",
+ "Standard_D1",
+ "Standard_D2",
+ "Standard_D3",
+ "Standard_D4",
+ "Standard_D11",
+ "Standard_D12",
+ "Standard_D13",
+ "Standard_D14",
+ "Standard_D1_v2",
+ "Standard_D2_v2",
+ "Standard_D3_v2",
+ "Standard_D4_v2",
+ "Standard_D5_v2",
+ "Standard_D11_v2",
+ "Standard_D12_v2",
+ "Standard_D13_v2",
+ "Standard_D14_v2",
+ "Standard_G1",
+ "Standard_G2",
+ "Standard_G3",
+ "Standard_G4",
+ "Standard_G5",
+ "Standard_DS1",
+ "Standard_DS2",
+ "Standard_DS3",
+ "Standard_DS4",
+ "Standard_DS11",
+ "Standard_DS12",
+ "Standard_DS13",
+ "Standard_DS14",
+ "Standard_GS1",
+ "Standard_GS2",
+ "Standard_GS3",
+ "Standard_GS4",
+ "Standard_GS5"
+ ],
+ "metadata" : {
+ "description" : "The size of the Infranode Virtual Machine."
+ }
+ },
+ "nodeVMSize" : {
+ "type" : "string",
+ "defaultValue" : "Standard_DS12",
+ "allowedValues" : [
+ "Standard_A0",
+ "Standard_A1",
+ "Standard_A2",
+ "Standard_A3",
+ "Standard_A4",
+ "Standard_A5",
+ "Standard_A6",
+ "Standard_A7",
+ "Standard_A8",
+ "Standard_A9",
+ "Standard_A10",
+ "Standard_A11",
+ "Standard_D1",
+ "Standard_D2",
+ "Standard_D3",
+ "Standard_D4",
+ "Standard_D11",
+ "Standard_D12",
+ "Standard_D13",
+ "Standard_D14",
+ "Standard_D1_v2",
+ "Standard_D2_v2",
+ "Standard_D3_v2",
+ "Standard_D4_v2",
+ "Standard_D5_v2",
+ "Standard_D11_v2",
+ "Standard_D12_v2",
+ "Standard_D13_v2",
+ "Standard_D14_v2",
+ "Standard_G1",
+ "Standard_G2",
+ "Standard_G3",
+ "Standard_G4",
+ "Standard_G5",
+ "Standard_DS1",
+ "Standard_DS2",
+ "Standard_DS3",
+ "Standard_DS4",
+ "Standard_DS11",
+ "Standard_DS12",
+ "Standard_DS13",
+ "Standard_DS14",
+ "Standard_GS1",
+ "Standard_GS2",
+ "Standard_GS3",
+ "Standard_GS4",
+ "Standard_GS5"
+ ],
+ "metadata" : {
+ "description" : "The size of the each Node Virtual Machine."
+ }
+ },
+ "RHNUserName" : {
+ "type" : "string",
+ "minLength" : 1,
+ "metadata" : {
+ "description" : "Red Hat Subscription User Name or Email Address"
+ }
+ },
+ "RHNPassword" : {
+ "type" : "securestring",
+ "metadata" : {
+ "description" : "Red Hat Subscription Password"
+ }
+ },
+ "SubscriptionPoolId" : {
+ "type" : "string",
+ "minLength" : 1,
+ "metadata" : {
+ "description" : "Pool ID of the Red Hat subscritpion to use"
+ }
+ },
+ "sshPrivateData" : {
+ "type" : "securestring",
+ "metadata" : {
+ "description" : "SSH RSA private key file as a base64 string."
+ }
+ },
+ "storeVMSize" : {
+ "type" : "string",
+ "defaultValue" : "Standard_DS3_v2",
+ "allowedValues" : [
+ "Standard_DS3_v2",
+ "Standard_DS12\t"
+ ],
+ "metadata" : {
+ "description" : "The size of the each Node Virtual Machine."
+ }
+ }
+ },
+ "variables" : {
+ "baseTemplateUrl" : "https://raw.githubusercontent.com/openshift/openshift-ansible-contrib/master/reference-architecture/azure-ansible/",
+ "baseVMachineTemplateUriInfranode" : "[concat(variables('baseTemplateUrl'), 'infranode.json')]",
+ "baseVMachineTemplateUriNode" : "[concat(variables('baseTemplateUrl'), 'node.json')]",
+ "baseVMachineTemplateUriMaster" : "[concat(variables('baseTemplateUrl'), 'master.json')]",
+ "location" : "[resourceGroup().location]",
+ "virtualNetworkName" : "openshiftVnet",
+ "addressPrefix" : "10.0.0.0/16",
+ "infranodesubnetName" : "infranodeSubnet",
+ "infranodesubnetPrefix" : "10.0.2.0/24",
+ "nodesubnetName" : "nodeSubnet",
+ "nodesubnetPrefix" : "10.0.1.0/24",
+ "mastersubnetName" : "masterSubnet",
+ "mastersubnetPrefix" : "10.0.0.0/24",
+ "apiVersion" : "2015-06-15",
+ "infranodeStorageName" : "[concat(uniqueString(resourceGroup().id), 'infranodesa')]",
+ "nodeStorageName" : "[concat(uniqueString(resourceGroup().id), 'nodesa')]",
+ "masterStorageName" : "[concat(uniqueString(resourceGroup().id), 'mastersa')]",
+ "vhdStorageType" : "Standard_LRS",
+ "vnetId" : "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
+ "infranodeSubnetRef" : "[concat(variables('vnetId'), '/subnets/', variables('infranodesubnetName'))]",
+ "nodeSubnetRef" : "[concat(variables('vnetId'), '/subnets/', variables('nodesubnetName'))]",
+ "masterSubnetRef" : "[concat(variables('vnetId'), '/subnets/', variables('mastersubnetName'))]",
+ "rhel" : {
+ "publisher" : "Redhat",
+ "offer" : "RHEL",
+ "sku" : "7.3",
+ "version" : "latest"
+ },
+ "baseVMachineTemplateUriBastion" : "[concat(variables('baseTemplateUrl'), 'bastion.json')]",
+ "tmApiVersion" : "2015-11-01",
+ "baseVMachineTemplateUriStore" : "[concat(variables('baseTemplateUrl'), 'store.json')]"
+ },
+ "resources" : [
+ {
+ "type" : "Microsoft.Storage/storageAccounts",
+ "name" : "[variables('infranodeStorageName')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[variables('location')]",
+ "tags" : {
+ "displayName" : "StorageAccount"
+ },
+ "properties" : {
+ "accountType" : "[variables('vhdStorageType')]"
+ }
+ },
+ {
+ "type" : "Microsoft.Storage/storageAccounts",
+ "name" : "[variables('nodeStorageName')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[variables('location')]",
+ "tags" : {
+ "displayName" : "StorageAccount"
+ },
+ "properties" : {
+ "accountType" : "[variables('vhdStorageType')]"
+ }
+ },
+ {
+ "type" : "Microsoft.Storage/storageAccounts",
+ "name" : "[variables('masterStorageName')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[variables('location')]",
+ "tags" : {
+ "displayName" : "StorageAccount"
+ },
+ "properties" : {
+ "accountType" : "[variables('vhdStorageType')]"
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/virtualNetworks",
+ "name" : "[variables('virtualNetworkName')]",
+ "location" : "[variables('location')]",
+ "tags" : {
+ "displayName" : "VirtualNetwork"
+ },
+ "properties" : {
+ "addressSpace" : {
+ "addressPrefixes" : [
+ "[variables('addressPrefix')]"
+ ]
+ },
+ "subnets" : [
+ {
+ "name" : "[variables('infranodesubnetName')]",
+ "properties" : {
+ "addressPrefix" : "[variables('infranodesubnetPrefix')]"
+ }
+ },
+ {
+ "name" : "[variables('nodesubnetName')]",
+ "properties" : {
+ "addressPrefix" : "[variables('nodesubnetPrefix')]"
+ }
+ },
+ {
+ "name" : "[variables('mastersubnetName')]",
+ "properties" : {
+ "addressPrefix" : "[variables('mastersubnetPrefix')]"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name" : "[concat('nodeSet', copyindex())]",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "copy" : {
+ "name" : "nodeSet",
+ "count" : "[parameters('numberOfNodes')]"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('nodeStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriNode')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "[concat('node', padLeft(add(copyindex(), 1), 2, '0'))]"
+ },
+ "sa" : {
+ "value" : "[variables('nodeStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('nodeSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('nodeVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "master1",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('masterStorageName'))]",
+ "[resourceId('Microsoft.Resources/deployments', 'infranode1')]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriMaster')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "master1"
+ },
+ "dnsName" : {
+ "value" : "[concat(resourceGroup().name,'m1')]"
+ },
+ "sa" : {
+ "value" : "[variables('masterStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('masterSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('masterVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "adminPassword" : {
+ "value" : "[parameters('adminPassword')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "numberOfNodes" : {
+ "value" : "[parameters('numberOfNodes')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "routerExtIP" : {
+ "value" : "[reference('infranode1').outputs.pip.value]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ },
+ "RHNUserName" : {
+ "value" : "[parameters('RHNUserName')]"
+ },
+ "RHNPassword" : {
+ "value" : "[parameters('RHNPassword')]"
+ },
+ "SubscriptionPoolId" : {
+ "value" : "[parameters('SubscriptionPoolId')]"
+ },
+ "sshPrivateData" : {
+ "value" : "[parameters('sshPrivateData')]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "infranode1",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('infranodeStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriInfranode')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "infranode1"
+ },
+ "sa" : {
+ "value" : "[variables('infranodeStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('infranodeSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('infranodeVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "bastion",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('masterStorageName'))]",
+ "[resourceId('Microsoft.Resources/deployments', 'master1')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master2')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master3')]",
+ "[resourceId('Microsoft.Resources/deployments', 'infranode1')]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriBastion')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "bastion"
+ },
+ "dnsName" : {
+ "value" : "[concat(resourceGroup().name,'b')]"
+ },
+ "sa" : {
+ "value" : "[variables('masterStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('masterSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('masterVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "adminPassword" : {
+ "value" : "[parameters('adminPassword')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "numberOfNodes" : {
+ "value" : "[parameters('numberOfNodes')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "routerExtIP" : {
+ "value" : "[reference('infranode1').outputs.pip.value]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ },
+ "RHNUserName" : {
+ "value" : "[parameters('RHNUserName')]"
+ },
+ "RHNPassword" : {
+ "value" : "[parameters('RHNPassword')]"
+ },
+ "SubscriptionPoolId" : {
+ "value" : "[parameters('SubscriptionPoolId')]"
+ },
+ "sshPrivateData" : {
+ "value" : "[parameters('sshPrivateData')]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "master2",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('masterStorageName'))]",
+ "[resourceId('Microsoft.Resources/deployments', 'infranode1')]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriMaster')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "master2"
+ },
+ "dnsName" : {
+ "value" : "[concat(resourceGroup().name,'m2')]"
+ },
+ "sa" : {
+ "value" : "[variables('masterStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('masterSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('masterVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "adminPassword" : {
+ "value" : "[parameters('adminPassword')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "numberOfNodes" : {
+ "value" : "[parameters('numberOfNodes')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "routerExtIP" : {
+ "value" : "[reference('infranode1').outputs.pip.value]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ },
+ "RHNUserName" : {
+ "value" : "[parameters('RHNUserName')]"
+ },
+ "RHNPassword" : {
+ "value" : "[parameters('RHNPassword')]"
+ },
+ "SubscriptionPoolId" : {
+ "value" : "[parameters('SubscriptionPoolId')]"
+ },
+ "sshPrivateData" : {
+ "value" : "[parameters('sshPrivateData')]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "master3",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('masterStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriMaster')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "master3"
+ },
+ "dnsName" : {
+ "value" : "[concat(resourceGroup().name,'m3')]"
+ },
+ "sa" : {
+ "value" : "[variables('masterStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('masterSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('masterVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "adminPassword" : {
+ "value" : "[parameters('adminPassword')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "numberOfNodes" : {
+ "value" : "[parameters('numberOfNodes')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "routerExtIP" : {
+ "value" : "[reference('infranode1').outputs.pip.value]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ },
+ "RHNUserName" : {
+ "value" : "[parameters('RHNUserName')]"
+ },
+ "RHNPassword" : {
+ "value" : "[parameters('RHNPassword')]"
+ },
+ "SubscriptionPoolId" : {
+ "value" : "[parameters('SubscriptionPoolId')]"
+ },
+ "sshPrivateData" : {
+ "value" : "[parameters('sshPrivateData')]"
+ }
+ }
+ }
+ },
+ {
+ "apiVersion" : "[variables('tmApiVersion')]",
+ "type" : "Microsoft.Network/trafficManagerProfiles",
+ "name" : "MasterLB",
+ "location" : "global",
+ "dependsOn" : [
+ "[resourceId('Microsoft.Resources/deployments', 'master1')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master2')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master3')]"
+ ],
+ "properties" : {
+ "profileStatus" : "Enabled",
+ "trafficRoutingMethod" : "Weighted",
+ "dnsConfig" : {
+ "relativeName" : "[resourceGroup().name]",
+ "ttl" : 30
+ },
+ "monitorConfig" : {
+ "protocol" : "https",
+ "port" : 8443,
+ "path" : "/api"
+ },
+ "endpoints" : [
+ {
+ "name" : "endpoint0",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'master1pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 1
+ }
+ },
+ {
+ "name" : "endpoint1",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'master2pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 2
+ }
+ },
+ {
+ "name" : "endpoint2",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'master3pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 3
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name" : "store1",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('nodeStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriStore')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "store1"
+ },
+ "sa" : {
+ "value" : "[variables('nodeStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('nodeSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('storeVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ },
+ "sshPrivateData" : {
+ "value" : "[parameters('sshPrivateData')]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "infranode2",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('infranodeStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriInfranode')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "infranode2"
+ },
+ "sa" : {
+ "value" : "[variables('infranodeStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('infranodeSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('infranodeVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ }
+ }
+ }
+ },
+ {
+ "name" : "infranode3",
+ "type" : "Microsoft.Resources/deployments",
+ "apiVersion" : "2013-03-01",
+ "dependsOn" : [
+ "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
+ "[concat('Microsoft.Storage/storageAccounts/', variables('infranodeStorageName'))]"
+ ],
+ "properties" : {
+ "mode" : "Incremental",
+ "templateLink" : {
+ "uri" : "[variables('baseVMachineTemplateUriInfranode')]",
+ "contentVersion" : "1.0.0.0"
+ },
+ "parameters" : {
+ "vmName" : {
+ "value" : "infranode3"
+ },
+ "sa" : {
+ "value" : "[variables('infranodeStorageName')]"
+ },
+ "subnetRef" : {
+ "value" : "[variables('infranodeSubnetRef')]"
+ },
+ "vmSize" : {
+ "value" : "[parameters('infranodeVMSize')]"
+ },
+ "adminUsername" : {
+ "value" : "[parameters('adminUsername')]"
+ },
+ "sshKeyData" : {
+ "value" : "[parameters('sshKeyData')]"
+ },
+ "baseTemplateUrl" : {
+ "value" : "[variables('baseTemplateUrl')]"
+ },
+ "imageReference" : {
+ "value" : "[variables(parameters('image'))]"
+ }
+ }
+ }
+ },
+ {
+ "apiVersion" : "[variables('tmApiVersion')]",
+ "type" : "Microsoft.Network/trafficManagerProfiles",
+ "name" : "AppLB",
+ "location" : "global",
+ "dependsOn" : [
+ "[resourceId('Microsoft.Resources/deployments', 'master1')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master2')]",
+ "[resourceId('Microsoft.Resources/deployments', 'master3')]"
+ ],
+ "properties" : {
+ "profileStatus" : "Enabled",
+ "trafficRoutingMethod" : "Weighted",
+ "dnsConfig" : {
+ "relativeName" : "[parameters('WildcardZone')]",
+ "ttl" : 30
+ },
+ "monitorConfig" : {
+ "protocol" : "https",
+ "port" : 8080,
+ "path" : "/api"
+ },
+ "endpoints" : [
+ {
+ "name" : "endpoint0",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'infranode1pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 1
+ }
+ },
+ {
+ "name" : "endpoint1",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'infranode2pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 2
+ }
+ },
+ {
+ "name" : "endpoint2",
+ "type" : "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties" : {
+ "targetResourceId" : "[resourceId('Microsoft.Network/publicIPAddresses', 'infranode3pip')]",
+ "endpointStatus" : "Enabled",
+ "weight" : 3
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "outputs" : {
+ "Openshift Webconsole" : {
+ "type" : "string",
+ "value" : "[concat('https://', reference('master1').outputs.fqdn.value, ':8443')]"
+ },
+ "Openshift Master ssh" : {
+ "type" : "string",
+ "value" : "[concat('ssh -A ', reference('bastion').outputs.pip.value)]"
+ },
+ "Openshift Router Public IP" : {
+ "type" : "string",
+ "value" : "[reference('infranode1').outputs.pip.value]"
+ }
+ }
+}
diff --git a/reference-architecture/azure-ansible/azuredeploy.parameters.json b/reference-architecture/azure-ansible/azuredeploy.parameters.json
new file mode 100755
index 000000000..a7cc0c762
--- /dev/null
+++ b/reference-architecture/azure-ansible/azuredeploy.parameters.json
@@ -0,0 +1,37 @@
+{
+ "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "adminUsername" : {
+ "value" : ""
+ },
+ "adminPassword" : {
+ "value" : ""
+ },
+ "sshKeyData" : {
+ "value" : ""
+ },
+ "WildcardZone" : {
+ "value" : ""
+ },
+ "numberOfNodes" : {
+ "value" : 3
+ },
+ "image" : {
+ "value" : "rhel"
+ },
+ "RHNUserName" : {
+ "value" : ""
+ },
+ "RHNPassword" : {
+ "value" : ""
+ },
+ "SubscriptionPoolId" : {
+ "value" : ""
+ },
+ "sshPrivateData" : {
+ "value" : ""
+ }
+ }
+}
+
diff --git a/reference-architecture/azure-ansible/bastion.json b/reference-architecture/azure-ansible/bastion.json
new file mode 100755
index 000000000..7e6be19e7
--- /dev/null
+++ b/reference-architecture/azure-ansible/bastion.json
@@ -0,0 +1,238 @@
+{
+ "$schema" : "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "vmName" : {
+ "type" : "string"
+ },
+ "dnsName" : {
+ "type" : "string"
+ },
+ "sa" : {
+ "type" : "string"
+ },
+ "subnetRef" : {
+ "type" : "string"
+ },
+ "vmSize" : {
+ "type" : "string"
+ },
+ "adminUsername" : {
+ "type" : "string"
+ },
+ "adminPassword" : {
+ "type" : "securestring"
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "numberOfNodes" : {
+ "type" : "int"
+ },
+ "baseTemplateUrl" : {
+ "type" : "string"
+ },
+ "routerExtIP" : {
+ "type" : "string"
+ },
+ "imageReference" : {
+ "type" : "object",
+ "metadata" : {
+ "description" : "imageReference object that should be used to create the virtual machine"
+ }
+ },
+ "RHNUserName" : {
+ "type" : "string"
+ },
+ "RHNPassword" : {
+ "type" : "securestring"
+ },
+ "SubscriptionPoolId" : {
+ "type" : "string"
+ },
+ "sshPrivateData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA private key file as a string."
+ }
+ }
+ },
+ "variables" : {
+ "apiVersion" : "2015-06-15",
+ "sshKeyPath" : "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
+ "sQuote" : "\""
+ },
+ "resources" : [
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/networkInterfaces",
+ "name" : "[concat(parameters('vmName'), 'nic')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "NetworkInterface"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/publicIPAddresses/', concat(parameters('vmName'), 'pip'))]",
+ "[concat('Microsoft.Network/networkSecurityGroups/', concat(parameters('vmName'), 'nsg'))]"
+ ],
+ "properties" : {
+ "ipConfigurations" : [
+ {
+ "name" : "ipconfig1",
+ "properties" : {
+ "privateIPAllocationMethod" : "Dynamic",
+ "publicIPAddress" : {
+ "id" : "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('vmName'), 'pip'))]"
+ },
+ "subnet" : {
+ "id" : "[parameters('subnetRef')]"
+ }
+ }
+ }
+ ],
+ "networkSecurityGroup" : {
+ "id" : "[resourceId('Microsoft.Network/networkSecurityGroups', concat(parameters('vmName'), 'nsg'))]"
+ }
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Compute/virtualMachines",
+ "name" : "[parameters('vmName')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachine"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'), 'nic'))]"
+ ],
+ "properties" : {
+ "hardwareProfile" : {
+ "vmSize" : "[parameters('vmSize')]"
+ },
+ "osProfile" : {
+ "computerName" : "[parameters('vmName')]",
+ "adminUsername" : "[parameters('adminUsername')]",
+ "linuxConfiguration" : {
+ "disablePasswordAuthentication" : "true",
+ "ssh" : {
+ "publicKeys" : [
+ {
+ "path" : "[variables('sshKeyPath')]",
+ "keyData" : "[parameters('sshKeyData')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile" : {
+ "imageReference" : "[parameters('imageReference')]",
+ "osDisk" : {
+ "name" : "osdisk",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '.vhd')]"
+ },
+ "caching" : "ReadWrite",
+ "createOption" : "FromImage"
+ },
+ "dataDisks" : [
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 0,
+ "name" : "datadisk1",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk1.vhd')]"
+ }
+ }
+ ]
+ },
+ "networkProfile" : {
+ "networkInterfaces" : [
+ {
+ "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('vmName'), 'nic'))]"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Compute/virtualMachines/extensions",
+ "name" : "[concat(parameters('vmName'),'/installcustomscript')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachineCustomScriptExtension"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
+ ],
+ "properties" : {
+ "publisher" : "Microsoft.OSTCExtensions",
+ "type" : "CustomScriptForLinux",
+ "typeHandlerVersion" : "1.3",
+ "settings" : {
+ "fileUris" : [
+ "[concat(parameters('baseTemplateUrl'), 'bastion.sh')]"
+ ],
+ "commandToExecute" : "[ concat('sh bastion.sh ', resourceGroup().name, ' ', parameters('adminUsername'), ' ', parameters('adminPassword'), ' ', reference(concat(parameters('vmName'), 'pip')).dnsSettings.fqdn, ' ', padLeft(parameters('numberOfNodes'), 2, '0'), ' ', parameters('routerExtIP'),' ', parameters('RHNUserName'), ' ', parameters('RHNPassword'),' ', parameters('SubscriptionPoolId'), ' ', variables('sQuote'), parameters('sshPrivateData'), variables('sQuote'), ' ', variables('sQuote'), parameters('sshKeyData'), variables('sQuote') ) ]"
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Network/networkSecurityGroups",
+ "name" : "[concat(parameters('vmName'), 'nsg')]",
+ "tags" : {
+ "displayName" : "NetworkSecurityGroup"
+ },
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "properties" : {
+ "securityRules" : [
+ {
+ "name" : "default-allow-ssh",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "22",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 1000,
+ "direction" : "Inbound"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/publicIPAddresses",
+ "name" : "[concat(parameters('vmName'), 'pip')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "PublicIPAddress"
+ },
+ "properties" : {
+ "publicIPAllocationMethod" : "Static",
+ "dnsSettings" : {
+ "domainNameLabel" : "[parameters('dnsName')]"
+ }
+ }
+ }
+ ],
+ "outputs" : {
+ "fqdn" : {
+ "type" : "string",
+ "value" : "[reference(concat(parameters('vmName'), 'pip')).dnsSettings.fqdn]"
+ },
+ "pip" : {
+ "type" : "string",
+ "value" : "[reference(concat(parameters('vmName'), 'pip')).ipAddress]"
+ }
+ }
+}
diff --git a/reference-architecture/azure-ansible/bastion.sh b/reference-architecture/azure-ansible/bastion.sh
new file mode 100755
index 000000000..e06577474
--- /dev/null
+++ b/reference-architecture/azure-ansible/bastion.sh
@@ -0,0 +1,323 @@
+#!/bin/bash
+
+export RESOURCEGROUP=$1
+export AUSERNAME=$2
+export PASSWORD=$3
+export HOSTNAME=$4
+export NODECOUNT=$5
+export ROUTEREXTIP=$6
+export RHNUSERNAME=$7
+export RHNPASSWORD=$8
+export RHNPOOLID=$9
+export SSHPRIVATEDATA=${10}
+export SSHPUBLICDATA=${11}
+export SSHPUBLICDATA2=${12}
+export SSHPUBLICDATA3=${13}
+
+ps -ef | grep bastion.sh > cmdline.out
+
+mkdir -p /home/$AUSERNAME/.ssh
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /home/$AUSERNAME/.ssh/id_rsa.pub
+echo $SSHPRIVATEDATA | base64 --d > /home/$AUSERNAME/.ssh/id_rsa
+chown $AUSERNAME /home/$AUSERNAME/.ssh/id_rsa.pub
+chmod 600 /home/$AUSERNAME/.ssh/id_rsa.pub
+chown $AUSERNAME /home/$AUSERNAME/.ssh/id_rsa
+chmod 600 /home/$AUSERNAME/.ssh/id_rsa
+
+mkdir -p /root/.ssh
+echo $SSHPRIVATEDATA | base64 --d > /root/.ssh/id_rsa
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa.pub
+chmod 600 /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa
+chmod 600 /root/.ssh/id_rsa
+
+sleep 30
+cat < /root/setup_ssmtp.sh
+# \$1 = Gmail Account (Leave off @gmail.com ie user)
+# \$2 = Gmail Password
+# \$3 = Notification email address
+# Setup ssmtp mta agent for use with gmail
+yum -y install wget
+wget -c https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-8.noarch.rpm
+rpm -ivh epel-release-7-8.noarch.rpm
+yum -y install ssmtp
+alternatives --set mta /usr/sbin/sendmail.ssmtp
+systemctl stop postfix
+systemctl disable postfix
+cat < /etc/ssmtp/ssmtp.conf
+root=postmaster
+mailhub=mail
+TLS_CA_File=/etc/pki/tls/certs/ca-bundle.crt
+mailhub=smtp.gmail.com:587 # SMTP server for Gmail
+Hostname=localhost
+UseTLS=YES
+UseSTARTTLS=Yes
+FromLineOverride=YES #TO CHANGE FROM EMAIL
+Root=\${3} # Redirect root email
+AuthUser=\${1}@gmail.com
+AuthPass=\${2}
+AuthMethod=LOGIN
+RewriteDomain=gmail.com
+EOFZ
+cat < /etc/ssmtp/revaliases
+root:\${1}@gmail.com:smtp.gmail.com:587
+EOFZ
+EOF
+chmod +x /root/setup_ssmtp.sh
+# Continue even if ssmtp.sh script errors out
+/root/setup_ssmtp.sh ${AUSERNAME} ${PASSWORD} ${RHNUSERNAME} || true
+
+echo "${RESOURCEGROUP} Bastion Host is starting software update" | mail -s "${RESOURCEGROUP} Bastion Software Install" ${RHNUSERNAME} || true
+# Continue Setting Up Bastion
+subscription-manager unregister
+yum -y remove RHEL7
+rm -f /etc/yum.repos.d/rh-cloud.repo
+# Found that wildcard disable not working all the time - make sure
+yum-config-manager --disable epel
+yum-config-manager --disable epel-testing
+subscription-manager register --username $RHNUSERNAME --password $RHNPASSWORD
+subscription-manager attach --pool=$RHNPOOLID
+subscription-manager repos --disable="*"
+subscription-manager repos --enable="rhel-7-server-rpms" --enable="rhel-7-server-extras-rpms"
+subscription-manager repos --enable="rhel-7-server-ose-3.3-rpms"
+yum -y install atomic-openshift-utils
+yum -y install git net-tools bind-utils iptables-services bridge-utils bash-completion httpd-tools
+touch /root/.updateok
+cat < /etc/ansible/hosts
+[OSEv3:children]
+masters
+etcd
+nodes
+misc
+
+[OSEv3:vars]
+azure_resource_group=${RESOURCEGROUP}
+rhn_pool_id=${RHNPOOLID}
+openshift_install_examples=true
+deployment_type=openshift-enterprise
+openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}]
+
+# default selectors for router and registry services
+openshift_router_selector='role=infra'
+openshift_registry_selector='role=infra'
+
+# Select default nodes for projects
+osm_default_node_selector="role=app"
+ansible_become=yes
+ansible_ssh_user=${AUSERNAME}
+remote_user=${AUSERNAME}
+
+openshift_master_default_subdomain=${ROUTEREXTIP}.xip.io
+openshift_use_dnsmasq=True
+openshift_public_hostname=${RESOURCEGROUP}.trafficmanager.net
+
+openshift_master_cluster_method=native
+openshift_master_cluster_hostname=${RESOURCEGROUP}.trafficmanager.net
+openshift_master_cluster_public_hostname=${RESOURCEGROUP}.trafficmanager.net
+
+# default storage plugin dependencies to install, by default the ceph and
+# glusterfs plugin dependencies will be installed, if available.
+osn_storage_plugin_deps=['iscsi']
+
+[masters]
+master1 openshift_node_labels="{'role': 'master'}"
+master2 openshift_node_labels="{'role': 'master'}"
+master3 openshift_node_labels="{'role': 'master'}"
+
+[etcd]
+master1
+master2
+master3
+
+[nodes]
+master1 openshift_node_labels="{'role':'master','zone':'default'}"
+master2 openshift_node_labels="{'role':'master','zone':'default'}"
+master3 openshift_node_labels="{'role':'master','zone':'default'}"
+node[01:${NODECOUNT}] openshift_node_labels="{'role': 'app', 'zone': 'default'}"
+infranode1 openshift_node_labels="{'role': 'infra', 'zone': 'default'}"
+infranode2 openshift_node_labels="{'role': 'infra', 'zone': 'default'}"
+infranode3 openshift_node_labels="{'role': 'infra', 'zone': 'default'}"
+
+[quotanodes]
+master1 openshift_node_labels="{'role':'master','zone':'default'}"
+master2 openshift_node_labels="{'role':'master','zone':'default'}"
+master3 openshift_node_labels="{'role':'master','zone':'default'}"
+node[01:${NODECOUNT}] openshift_node_labels="{'role': 'app', 'zone': 'default'}"
+
+[misc]
+store1
+EOF
+
+
+cat < /home/${AUSERNAME}/subscribe.yml
+---
+- hosts: all
+ vars:
+ description: "Subscribe OCP"
+ tasks:
+ - name: wait for .updateok
+ wait_for: path=/root/.updateok
+ - name: check connection
+ ping:
+ - name: Get rid of RHUI repos
+ file: path=/etc/yum.repos.d/rh-cloud.repo state=absent
+ - name: Get rid of RHUI load balancers
+ file: path=/etc/yum.repos.d/rhui-load-balancers state=absent
+ - name: remove the RHUI package
+ yum: name=RHEL7 state=absent
+ - name: Get rid of old subs
+ shell: subscription-manager unregister
+ ignore_errors: yes
+ - name: register hosts
+ shell: subscription-manager register --username ${RHNUSERNAME} --password ${RHNPASSWORD}
+ register: task_result
+ until: task_result.rc == 0
+ retries: 10
+ delay: 30
+ ignore_errors: yes
+ - name: attach sub
+ shell: subscription-manager attach --pool=$RHNPOOLID
+ register: task_result
+ until: task_result.rc == 0
+ retries: 10
+ delay: 30
+ ignore_errors: yes
+ - name: disable all repos
+ shell: subscription-manager repos --disable="*"
+ - name: enable rhel7 repo
+ shell: subscription-manager repos --enable="rhel-7-server-rpms"
+ - name: enable extras repos
+ shell: subscription-manager repos --enable="rhel-7-server-extras-rpms"
+ - name: enable OCP repos
+ shell: subscription-manager repos --enable="rhel-7-server-ose-3.3-rpms"
+ - name: install the latest version of PyYAML
+ yum: name=PyYAML state=latest
+ - name: Install the OCP client
+ yum: name=atomic-openshift-clients state=latest
+ - name: Update all hosts
+ command: yum -y update
+ async: 1200
+ poll: 10
+ - name: Wait for Things to Settle
+ pause: minutes=5
+EOF
+
+cat < /home/${AUSERNAME}/quota.yml
+---
+- hosts: quotanodes
+ vars:
+ description: "Fix EP Storage/Quota"
+ tasks:
+ - name: Change Node perFSGroup Qouta Setting
+ lineinfile: dest=/etc/origin/noce/node-config.yaml regexp=^perFSGroup: line=" perFSGroup:512Mi"
+ - name: Update Mount to Handle Quota
+ mount: fstype=xfs name=/var/lib/origin/openshift.local/volumes src=/dev/sdd option="gquota" state="mounted"
+EOF
+
+
+cat < /home/${AUSERNAME}/setupiscsi.yml
+- hosts: all
+ vars:
+ description: "Subscribe OCP"
+ tasks:
+ - name: Install iSCSI initiator utils
+ yum: name=iscsi-initiator-utils state=latest
+ - name: add new initiator name
+ lineinfile: dest=/etc/iscsi/initiatorname.iscsi create=yes regexp="InitiatorName=*" line="InitiatorName=iqn.2016-02.local.azure.nodes" state=present
+ - name: restart iSCSI service
+ shell: systemctl restart iscsi
+ ignore_errors: yes
+ - name: Enable iSCSI
+ shell: systemctl enable iscsi
+ ignore_errors: yes
+ - name: Start iSCSI Initiator Service
+ shell: systemctl start iscsi
+ ignore_errors: yes
+ - name: Discover iSCSI on all hosts
+ shell: iscsiadm --mode discovery --type sendtargets --portal store1
+ register: task_result
+ until: task_result.rc == 0
+ retries: 10
+ delay: 30
+ ignore_errors: yes
+ - name: Login All Hosts
+ shell: iscsiadm --mode node --portal store1 --login
+ register: task_result
+ until: task_result.rc == 0
+ retries: 10
+ delay: 30
+ ignore_errors: yes
+EOF
+
+
+cat < /home/${AUSERNAME}/postinstall.yml
+---
+- hosts: masters
+ vars:
+ description: "auth users"
+ tasks:
+ - name: Create Master Directory
+ file: path=/etc/origin/master state=directory
+ - name: add initial user to Red Hat OpenShift Container Platform
+ shell: htpasswd -c -b /etc/origin/master/htpasswd ${AUSERNAME} ${PASSWORD}
+
+EOF
+
+cat < /home/${AUSERNAME}/openshift-install.sh
+export ANSIBLE_HOST_KEY_CHECKING=False
+sleep 120
+ansible all --module-name=ping > ansible-preinstall-ping.out || true
+ansible-playbook /home/${AUSERNAME}/subscribe.yml
+echo "${RESOURCEGROUP} Bastion Host is starting ansible BYO" | mail -s "${RESOURCEGROUP} Bastion BYO Install" ${RHNUSERNAME} || true
+ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml < /dev/null &> byo.out
+
+wget http://master1:8443/api > healtcheck.out
+ansible-playbook /home/${AUSERNAME}/quota.yml
+ansible-playbook /home/${AUSERNAME}/postinstall.yml
+ansible-playbook /home/${AUSERNAME}/setupiscsi.yml
+cd /root
+mkdir .kube
+scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${AUSERNAME}@master1:~/.kube/config /tmp/kube-config
+cp /tmp/kube-config /root/.kube/config
+mkdir /home/${AUSERNAME}/.kube
+cp /tmp/kube-config /home/${AUSERNAME}/.kube/config
+chown --recursive ${AUSERNAME} /home/${AUSERNAME}/.kube
+rm -f /tmp/kube-config
+ansible-playbook /home/${AUSERNAME}/setupiscsi.yml
+echo "${RESOURCEGROUP} Installation Is Complete" | mail -s "${RESOURCEGROUP} Install Complete" ${RHNUSERNAME} || true
+EOF
+
+cat < /home/${AUSERNAME}/.ansible.cfg
+[defaults]
+remote_tmp = ~/.ansible/tmp
+local_tmp = ~/.ansible/tmp
+host_key_checking = False
+forks=30
+gather_timeout=60
+timeout=240
+[ssh_connection]
+control_path = ~/.ansible/cp/ssh%%h-%%p-%%r
+ssh_args = -o ControlMaster=auto -o ControlPersist=600s -o ControlPath=~/.ansible/cp-%h-%p-%r
+EOF
+chown ${AUSERNAME} /home/${AUSERNAME}/.ansible.cfg
+
+cat < /root/.ansible.cfg
+[defaults]
+remote_tmp = ~/.ansible/tmp
+local_tmp = ~/.ansible/tmp
+host_key_checking = False
+forks=30
+gather_timeout=60
+timeout=240
+[ssh_connection]
+control_path = ~/.ansible/cp/ssh%%h-%%p-%%r
+ssh_args = -o ControlMaster=auto -o ControlPersist=600s -o ControlPath=~/.ansible/cp-%h-%p-%r
+EOF
+
+
+cd /home/${AUSERNAME}
+chmod 755 /home/${AUSERNAME}/openshift-install.sh
+echo "${RESOURCEGROUP} Bastion Host is starting OpenShift Install" | mail -s "${RESOURCEGROUP} Bastion OpenShift Install Starting" ${RHNUSERNAME} || true
+/home/${AUSERNAME}/openshift-install.sh &> /home/${AUSERNAME}/openshift-install.out &
+exit 0
diff --git a/reference-architecture/azure-ansible/images/puttygen.png b/reference-architecture/azure-ansible/images/puttygen.png
new file mode 100644
index 000000000..2f1ac1b3c
Binary files /dev/null and b/reference-architecture/azure-ansible/images/puttygen.png differ
diff --git a/reference-architecture/azure-ansible/images/terminal.png b/reference-architecture/azure-ansible/images/terminal.png
new file mode 100644
index 000000000..cc5d544c8
Binary files /dev/null and b/reference-architecture/azure-ansible/images/terminal.png differ
diff --git a/reference-architecture/azure-ansible/infranode.json b/reference-architecture/azure-ansible/infranode.json
new file mode 100755
index 000000000..211013bd2
--- /dev/null
+++ b/reference-architecture/azure-ansible/infranode.json
@@ -0,0 +1,226 @@
+{
+ "$schema" : "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "vmName" : {
+ "type" : "string"
+ },
+ "sa" : {
+ "type" : "string"
+ },
+ "subnetRef" : {
+ "type" : "string"
+ },
+ "vmSize" : {
+ "type" : "string"
+ },
+ "adminUsername" : {
+ "type" : "string"
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "baseTemplateUrl" : {
+ "type" : "string"
+ },
+ "imageReference" : {
+ "type" : "object",
+ "metadata" : {
+ "description" : "imageReference object that should be used to create the virtual machine"
+ }
+ }
+ },
+ "variables" : {
+ "apiVersion" : "2015-06-15",
+ "sshKeyPath" : "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]"
+ },
+ "resources" : [
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/networkInterfaces",
+ "name" : "[concat(parameters('vmName'), 'nic')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "NetworkInterface"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/publicIPAddresses/', concat(parameters('vmName'), 'pip'))]",
+ "[concat('Microsoft.Network/networkSecurityGroups/', concat(parameters('vmName'), 'nsg'))]"
+ ],
+ "properties" : {
+ "ipConfigurations" : [
+ {
+ "name" : "ipconfig1",
+ "properties" : {
+ "privateIPAllocationMethod" : "Dynamic",
+ "publicIPAddress" : {
+ "id" : "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('vmName'), 'pip'))]"
+ },
+ "subnet" : {
+ "id" : "[parameters('subnetRef')]"
+ }
+ }
+ }
+ ],
+ "networkSecurityGroup" : {
+ "id" : "[resourceId('Microsoft.Network/networkSecurityGroups', concat(parameters('vmName'), 'nsg'))]"
+ }
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Compute/virtualMachines",
+ "name" : "[parameters('vmName')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachine"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'), 'nic'))]"
+ ],
+ "properties" : {
+ "hardwareProfile" : {
+ "vmSize" : "[parameters('vmSize')]"
+ },
+ "osProfile" : {
+ "computerName" : "[parameters('vmName')]",
+ "adminUsername" : "[parameters('adminUsername')]",
+ "linuxConfiguration" : {
+ "disablePasswordAuthentication" : "true",
+ "ssh" : {
+ "publicKeys" : [
+ {
+ "path" : "[variables('sshKeyPath')]",
+ "keyData" : "[parameters('sshKeyData')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile" : {
+ "imageReference" : "[parameters('imageReference')]",
+ "osDisk" : {
+ "name" : "osdisk",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '.vhd')]"
+ },
+ "caching" : "ReadWrite",
+ "createOption" : "FromImage"
+ },
+ "dataDisks" : [
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 0,
+ "name" : "datadisk1",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk1.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 1,
+ "name" : "datadisk2",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk2.vhd')]"
+ }
+ }
+ ]
+ },
+ "networkProfile" : {
+ "networkInterfaces" : [
+ {
+ "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('vmName'), 'nic'))]"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Compute/virtualMachines/extensions",
+ "name" : "[concat(parameters('vmName'),'/installcustomscript')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachineCustomScriptExtension"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
+ ],
+ "properties" : {
+ "publisher" : "Microsoft.OSTCExtensions",
+ "type" : "CustomScriptForLinux",
+ "typeHandlerVersion" : "1.3",
+ "settings" : {
+ "fileUris" : [
+ "[concat(parameters('baseTemplateUrl'), 'node.sh')]"
+ ],
+ "commandToExecute" : "sh node.sh"
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Network/networkSecurityGroups",
+ "name" : "[concat(parameters('vmName'), 'nsg')]",
+ "tags" : {
+ "displayName" : "NetworkSecurityGroup"
+ },
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "properties" : {
+ "securityRules" : [
+ {
+ "name" : "default-allow-openshift-router-http",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "80",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 1000,
+ "direction" : "Inbound"
+ }
+ },
+ {
+ "name" : "default-allow-openshift-router-https",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "443",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 2000,
+ "direction" : "Inbound"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/publicIPAddresses",
+ "name" : "[concat(parameters('vmName'), 'pip')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "PublicIPAddress"
+ },
+ "properties" : {
+ "publicIPAllocationMethod" : "Static"
+ }
+ }
+ ],
+ "outputs" : {
+ "pip" : {
+ "type" : "string",
+ "value" : "[reference(concat(parameters('vmName'), 'pip')).ipAddress]"
+ }
+ }
+}
diff --git a/reference-architecture/azure-ansible/master.json b/reference-architecture/azure-ansible/master.json
new file mode 100755
index 000000000..4fe1730c2
--- /dev/null
+++ b/reference-architecture/azure-ansible/master.json
@@ -0,0 +1,248 @@
+{
+ "$schema" : "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "vmName" : {
+ "type" : "string"
+ },
+ "dnsName" : {
+ "type" : "string"
+ },
+ "sa" : {
+ "type" : "string"
+ },
+ "subnetRef" : {
+ "type" : "string"
+ },
+ "vmSize" : {
+ "type" : "string"
+ },
+ "adminUsername" : {
+ "type" : "string"
+ },
+ "adminPassword" : {
+ "type" : "securestring"
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "numberOfNodes" : {
+ "type" : "int"
+ },
+ "baseTemplateUrl" : {
+ "type" : "string"
+ },
+ "routerExtIP" : {
+ "type" : "string"
+ },
+ "imageReference" : {
+ "type" : "object",
+ "metadata" : {
+ "description" : "imageReference object that should be used to create the virtual machine"
+ }
+ },
+ "RHNUserName" : {
+ "type" : "string"
+ },
+ "RHNPassword" : {
+ "type" : "securestring"
+ },
+ "SubscriptionPoolId" : {
+ "type" : "string"
+ },
+ "sshPrivateData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA private key file as a string."
+ }
+ }
+ },
+ "variables" : {
+ "apiVersion" : "2015-06-15",
+ "sshKeyPath" : "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
+ "sQuote" : "\""
+ },
+ "resources" : [
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/networkInterfaces",
+ "name" : "[concat(parameters('vmName'), 'nic')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "NetworkInterface"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/publicIPAddresses/', concat(parameters('vmName'), 'pip'))]",
+ "[concat('Microsoft.Network/networkSecurityGroups/', concat(parameters('vmName'), 'nsg'))]"
+ ],
+ "properties" : {
+ "ipConfigurations" : [
+ {
+ "name" : "ipconfig1",
+ "properties" : {
+ "privateIPAllocationMethod" : "Dynamic",
+ "publicIPAddress" : {
+ "id" : "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('vmName'), 'pip'))]"
+ },
+ "subnet" : {
+ "id" : "[parameters('subnetRef')]"
+ }
+ }
+ }
+ ],
+ "networkSecurityGroup" : {
+ "id" : "[resourceId('Microsoft.Network/networkSecurityGroups', concat(parameters('vmName'), 'nsg'))]"
+ }
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Compute/virtualMachines",
+ "name" : "[parameters('vmName')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachine"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'), 'nic'))]"
+ ],
+ "properties" : {
+ "hardwareProfile" : {
+ "vmSize" : "[parameters('vmSize')]"
+ },
+ "osProfile" : {
+ "computerName" : "[parameters('vmName')]",
+ "adminUsername" : "[parameters('adminUsername')]",
+ "linuxConfiguration" : {
+ "disablePasswordAuthentication" : "true",
+ "ssh" : {
+ "publicKeys" : [
+ {
+ "path" : "[variables('sshKeyPath')]",
+ "keyData" : "[parameters('sshKeyData')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile" : {
+ "imageReference" : "[parameters('imageReference')]",
+ "osDisk" : {
+ "name" : "osdisk",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '.vhd')]"
+ },
+ "caching" : "ReadWrite",
+ "createOption" : "FromImage"
+ },
+ "dataDisks" : [
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 0,
+ "name" : "datadisk1",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk1.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 1,
+ "name" : "datadisk2",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk2.vhd')]"
+ }
+ }
+ ]
+ },
+ "networkProfile" : {
+ "networkInterfaces" : [
+ {
+ "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('vmName'), 'nic'))]"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Compute/virtualMachines/extensions",
+ "name" : "[concat(parameters('vmName'),'/installcustomscript')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachineCustomScriptExtension"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
+ ],
+ "properties" : {
+ "publisher" : "Microsoft.OSTCExtensions",
+ "type" : "CustomScriptForLinux",
+ "typeHandlerVersion" : "1.3",
+ "settings" : {
+ "fileUris" : [
+ "[concat(parameters('baseTemplateUrl'), 'master.sh')]"
+ ],
+ "commandToExecute" : "[ concat('sh master.sh ', parameters('adminUsername'), ' ', parameters('adminPassword'), ' ', reference(concat(parameters('vmName'), 'pip')).dnsSettings.fqdn, ' ', padLeft(parameters('numberOfNodes'), 2, '0'), ' ', parameters('routerExtIP'),' ', parameters('RHNUserName'), ' ', parameters('RHNPassword'),' ', parameters('SubscriptionPoolId'), ' ', variables('sQuote'), parameters('sshPrivateData'), variables('sQuote'), ' ', variables('sQuote'), parameters('sshKeyData'), variables('sQuote') ) ]"
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Network/networkSecurityGroups",
+ "name" : "[concat(parameters('vmName'), 'nsg')]",
+ "tags" : {
+ "displayName" : "NetworkSecurityGroup"
+ },
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "properties" : {
+ "securityRules" : [
+ {
+ "name" : "default-allow-openshift-master",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "8443",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 2000,
+ "direction" : "Inbound"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/publicIPAddresses",
+ "name" : "[concat(parameters('vmName'), 'pip')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "PublicIPAddress"
+ },
+ "properties" : {
+ "publicIPAllocationMethod" : "Static",
+ "dnsSettings" : {
+ "domainNameLabel" : "[parameters('dnsName')]"
+ }
+ }
+ }
+ ],
+ "outputs" : {
+ "fqdn" : {
+ "type" : "string",
+ "value" : "[reference(concat(parameters('vmName'), 'pip')).dnsSettings.fqdn]"
+ },
+ "pip" : {
+ "type" : "string",
+ "value" : "[reference(concat(parameters('vmName'), 'pip')).ipAddress]"
+ }
+ }
+}
diff --git a/reference-architecture/azure-ansible/master.sh b/reference-architecture/azure-ansible/master.sh
new file mode 100755
index 000000000..c3546c73e
--- /dev/null
+++ b/reference-architecture/azure-ansible/master.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+USERNAME=$1
+PASSWORD=$2
+HOSTNAME=$3
+NODECOUNT=$4
+ROUTEREXTIP=$5
+RHNUSERNAME=$6
+RHNPASSWORD=$7
+RHNPOOLID=$8
+SSHPRIVATEDATA=$9
+SSHPUBLICDATA=${10}
+SSHPUBLICDATA2=${11}
+SSHPUBLICDATA3=${12}
+
+ps -ef | grep master.sh > cmdline.out
+
+mkdir -p /home/$USERNAME/.ssh
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /home/$USERNAME/.ssh/id_rsa.pub
+echo $SSHPRIVATEDATA | base64 --d > /home/$USERNAME/.ssh/id_rsa
+chown $USERNAME /home/$USERNAME/.ssh/id_rsa.pub
+chmod 600 /home/$USERNAME/.ssh/id_rsa.pub
+chown $USERNAME /home/$USERNAME/.ssh/id_rsa
+chmod 600 /home/$USERNAME/.ssh/id_rsa
+
+mkdir -p /root/.ssh
+echo $SSHPRIVATEDATA | base64 --d > /root/.ssh/id_rsa
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa.pub
+chmod 600 /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa
+chmod 600 /root/.ssh/id_rsa
+
+subscription-manager unregister
+subscription-manager register --username $RHNUSERNAME --password $RHNPASSWORD
+subscription-manager attach --pool=$RHNPOOLID
+subscription-manager repos --disable="*"
+subscription-manager repos --enable="rhel-7-server-rpms" --enable="rhel-7-server-extras-rpms"
+subscription-manager repos --enable="rhel-7-server-ose-3.3-rpms"
+yum -y install atomic-openshift-utils
+yum -y install wget git net-tools bind-utils iptables-services bridge-utils bash-completion httpd-tools
+yum -y install docker
+sed -i -e "s#^OPTIONS='--selinux-enabled'#OPTIONS='--selinux-enabled --insecure-registry 172.30.0.0/16'#" /etc/sysconfig/docker
+
+touch /root/.updateok
+
+cat < /etc/sysconfig/docker-storage-setup
+DEVS=/dev/sdc
+VG=docker-vg
+EXTRA_DOCKER_STORAGE_OPTIONS="--storage-opt dm.basesize=3G"
+EOF
+
+docker-storage-setup
+systemctl enable docker
+systemctl start docker
+
+
+cat < /home/${USERNAME}/.ansible.cfg
+[defaults]
+host_key_checking = False
+EOF
+chown ${USERNAME} /home/${USERNAME}/.ansible.cfg
+
+cat < /root/.ansible.cfg
+[defaults]
+host_key_checking = False
+EOF
+
+
diff --git a/reference-architecture/azure-ansible/node.json b/reference-architecture/azure-ansible/node.json
new file mode 100755
index 000000000..19d2c36ef
--- /dev/null
+++ b/reference-architecture/azure-ansible/node.json
@@ -0,0 +1,160 @@
+{
+ "$schema" : "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "vmName" : {
+ "type" : "string"
+ },
+ "sa" : {
+ "type" : "string"
+ },
+ "subnetRef" : {
+ "type" : "string"
+ },
+ "vmSize" : {
+ "type" : "string"
+ },
+ "adminUsername" : {
+ "type" : "string"
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "baseTemplateUrl" : {
+ "type" : "string"
+ },
+ "imageReference" : {
+ "type" : "object",
+ "metadata" : {
+ "description" : "imageReference object that should be used to create the virtual machine"
+ }
+ }
+ },
+ "variables" : {
+ "apiVersion" : "2015-06-15",
+ "sshKeyPath" : "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]"
+ },
+ "resources" : [
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/networkInterfaces",
+ "name" : "[concat(parameters('vmName'), 'nic')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "NetworkInterface"
+ },
+ "properties" : {
+ "ipConfigurations" : [
+ {
+ "name" : "ipconfig1",
+ "properties" : {
+ "privateIPAllocationMethod" : "Dynamic",
+ "subnet" : {
+ "id" : "[parameters('subnetRef')]"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Compute/virtualMachines",
+ "name" : "[parameters('vmName')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachine"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'), 'nic'))]"
+ ],
+ "properties" : {
+ "hardwareProfile" : {
+ "vmSize" : "[parameters('vmSize')]"
+ },
+ "osProfile" : {
+ "computerName" : "[parameters('vmName')]",
+ "adminUsername" : "[parameters('adminUsername')]",
+ "linuxConfiguration" : {
+ "disablePasswordAuthentication" : "true",
+ "ssh" : {
+ "publicKeys" : [
+ {
+ "path" : "[variables('sshKeyPath')]",
+ "keyData" : "[parameters('sshKeyData')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile" : {
+ "imageReference" : "[parameters('imageReference')]",
+ "osDisk" : {
+ "name" : "osdisk",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '.vhd')]"
+ },
+ "caching" : "ReadWrite",
+ "createOption" : "FromImage"
+ },
+ "dataDisks" : [
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 0,
+ "name" : "datadisk1",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk1.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 1,
+ "name" : "datadisk2",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk2.vhd')]"
+ }
+ }
+ ]
+ },
+ "networkProfile" : {
+ "networkInterfaces" : [
+ {
+ "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('vmName'), 'nic'))]"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Compute/virtualMachines/extensions",
+ "name" : "[concat(parameters('vmName'),'/installcustomscript')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachineCustomScriptExtension"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
+ ],
+ "properties" : {
+ "publisher" : "Microsoft.OSTCExtensions",
+ "type" : "CustomScriptForLinux",
+ "typeHandlerVersion" : "1.3",
+ "settings" : {
+ "fileUris" : [
+ "[concat(parameters('baseTemplateUrl'), 'node.sh')]"
+ ],
+ "commandToExecute" : "sh node.sh"
+ }
+ }
+ }
+ ],
+ "outputs" : {}
+}
diff --git a/reference-architecture/azure-ansible/node.sh b/reference-architecture/azure-ansible/node.sh
new file mode 100755
index 000000000..6e5c19a21
--- /dev/null
+++ b/reference-architecture/azure-ansible/node.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+#yum -y update
+yum -y install wget git net-tools bind-utils iptables-services bridge-utils bash-completion docker
+
+sed -i -e "s#^OPTIONS='--selinux-enabled'#OPTIONS='--selinux-enabled --insecure-registry 172.30.0.0/16'#" /etc/sysconfig/docker
+
+cat < /etc/sysconfig/docker-storage-setup
+DEVS=/dev/sdc
+VG=docker-vg
+EXTRA_DOCKER_STORAGE_OPTIONS="--storage-opt dm.basesize=3G"
+EOF
+
+docker-storage-setup
+systemctl enable docker
+touch /root/.updateok
+
diff --git a/reference-architecture/azure-ansible/ssh_linux.md b/reference-architecture/azure-ansible/ssh_linux.md
new file mode 100644
index 000000000..08977933c
--- /dev/null
+++ b/reference-architecture/azure-ansible/ssh_linux.md
@@ -0,0 +1,22 @@
+# Red Hat OpenShift Container Platform on Azure
+
+## SSH Key Generation - Linux/CentOS/Fedora
+1. Go to bash/command line/terminal on your client device.
+2. Enter the commands:
+```bash
+mkdir ~/.ssh
+chmod 700 ~/.ssh
+ssh-keygen -t rsa
+```
+3. At this point you will be prompted:
+
+```bash
+Generating public/private RSA key pair.
+Enter file in which to save the key (/home/b/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /home/b/.ssh/id_rsa.
+Your public key has been saved in /home/b/.ssh/id_rsa.pub.
+```
+
+Your public and private keys are now available in your home folder under the .ssh directory.
diff --git a/reference-architecture/azure-ansible/ssh_mac.md b/reference-architecture/azure-ansible/ssh_mac.md
new file mode 100644
index 000000000..e06d4c94f
--- /dev/null
+++ b/reference-architecture/azure-ansible/ssh_mac.md
@@ -0,0 +1,39 @@
+# Red Hat OpenShift Container Platform on Azure
+
+## SSH Key Generation - Linux/CentOS/Fedora
+1. Open the Terminal in the Application/Utilities folder.
+![Terminal ScreenShot][terminal]
+2. Enter the commands:
+```bash
+ssh-keygen -t rsa
+```
+3. At this point you will be prompted:
+
+```bash
+Generating public/private RSA key pair.
+Enter file in which to save the key (/Users/test/.ssh/id_rsa):
+Created directory '/Users/test/.ssh'.
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/test/.ssh/id_rsa.
+Your public key has been saved in /Users/test/.ssh/id_rsa.pub.
+The key fingerprint is:
+SHA256:2KeBdOEN/empJoqPYXuSMv5elJbS0KMwlcQBX4KuSPM test@host.com
+The keys randomart image is:
++---[RSA 2048]----+
+| .==o. o. |
+| .oo+ . +. |
+| .o o + o .. . |
+| o.o = O o |
+|o.o o O S .. . |
+|o E + + o |
+| o.. . . |
+| o.o*. . o |
+| ..=*+o. o |
++----[SHA256]-----+
+```
+
+Your public and private keys are now available in your home folder under the .ssh directory.
+
+
+[terminal]: https://github.com/openshift/openshift-ansible-contrib/raw/master/reference-architecture/azure-ansible/images/terminal.png
diff --git a/reference-architecture/azure-ansible/ssh_windows.md b/reference-architecture/azure-ansible/ssh_windows.md
new file mode 100644
index 000000000..8205d24e5
--- /dev/null
+++ b/reference-architecture/azure-ansible/ssh_windows.md
@@ -0,0 +1,19 @@
+# Red Hat Open Shift Container Platform on Azure
+
+## SSH Key Generation On Windows
+In Windows, use PuTTYgen to generate your public and private keys.
+
+1. Install PuTTY -
+[PuTTY](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)
+
+2. Launch PuTTYgen, and press the Generate Button. This will generate the key.
+![PuttyGen Screenshot][PuTTYgen]
+
+3. Leave Passphrase and Confirm Passprase Empty
+
+4. Save the public and private keys by clicking the Save public key and Save private key buttons.
+
+5. You will need the private and public keys for the Open Shift Install.
+
+
+[PuTTYgen]: https://github.com/openshift/openshift-ansible-contrib/raw/master/reference-architecture/azure-ansible/images/puttygen.png
diff --git a/reference-architecture/azure-ansible/store.json b/reference-architecture/azure-ansible/store.json
new file mode 100755
index 000000000..c224f5892
--- /dev/null
+++ b/reference-architecture/azure-ansible/store.json
@@ -0,0 +1,266 @@
+{
+ "$schema" : "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion" : "1.0.0.0",
+ "parameters" : {
+ "vmName" : {
+ "type" : "string"
+ },
+ "sa" : {
+ "type" : "string"
+ },
+ "subnetRef" : {
+ "type" : "string"
+ },
+ "vmSize" : {
+ "type" : "string"
+ },
+ "adminUsername" : {
+ "type" : "string"
+ },
+ "sshKeyData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA public key file as a string."
+ }
+ },
+ "baseTemplateUrl" : {
+ "type" : "string"
+ },
+ "imageReference" : {
+ "type" : "object",
+ "metadata" : {
+ "description" : "imageReference object that should be used to create the virtual machine"
+ }
+ },
+ "sshPrivateData" : {
+ "type" : "string",
+ "metadata" : {
+ "description" : "SSH RSA private key file as a base64 string."
+ }
+ }
+ },
+ "variables" : {
+ "apiVersion" : "2015-06-15",
+ "sshKeyPath" : "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
+ "sQuote" : "\""
+ },
+ "resources" : [
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Network/networkInterfaces",
+ "name" : "[concat(parameters('vmName'), 'nic')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "NetworkInterface"
+ },
+ "properties" : {
+ "ipConfigurations" : [
+ {
+ "name" : "ipconfig1",
+ "properties" : {
+ "privateIPAllocationMethod" : "Dynamic",
+ "subnet" : {
+ "id" : "[parameters('subnetRef')]"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "apiVersion" : "[variables('apiVersion')]",
+ "type" : "Microsoft.Compute/virtualMachines",
+ "name" : "[parameters('vmName')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachine"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'), 'nic'))]"
+ ],
+ "properties" : {
+ "hardwareProfile" : {
+ "vmSize" : "[parameters('vmSize')]"
+ },
+ "osProfile" : {
+ "computerName" : "[parameters('vmName')]",
+ "adminUsername" : "[parameters('adminUsername')]",
+ "linuxConfiguration" : {
+ "disablePasswordAuthentication" : "true",
+ "ssh" : {
+ "publicKeys" : [
+ {
+ "path" : "[variables('sshKeyPath')]",
+ "keyData" : "[parameters('sshKeyData')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile" : {
+ "imageReference" : "[parameters('imageReference')]",
+ "osDisk" : {
+ "name" : "osdisk",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '.vhd')]"
+ },
+ "caching" : "ReadWrite",
+ "createOption" : "FromImage"
+ },
+ "dataDisks" : [
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 0,
+ "name" : "datadisk1",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk1.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 1,
+ "name" : "datadisk2",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk2.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 2,
+ "name" : "datadisk3",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk3.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 3,
+ "name" : "datadisk4",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk4.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 4,
+ "name" : "datadisk5",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk5.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 5,
+ "name" : "datadisk6",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk6.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 6,
+ "name" : "datadisk7",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk7.vhd')]"
+ }
+ },
+ {
+ "caching" : "None",
+ "createOption" : "Empty",
+ "diskSizeGB" : "128",
+ "lun" : 7,
+ "name" : "datadisk8",
+ "vhd" : {
+ "uri" : "[concat('http://', parameters('sa'), '.blob.core.windows.net/openshiftvmachines/', parameters('vmName'), '_datadisk8.vhd')]"
+ }
+ }
+ ]
+ },
+ "networkProfile" : {
+ "networkInterfaces" : [
+ {
+ "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('vmName'), 'nic'))]"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Compute/virtualMachines/extensions",
+ "name" : "[concat(parameters('vmName'),'/installcustomscript')]",
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "tags" : {
+ "displayName" : "VirtualMachineCustomScriptExtension"
+ },
+ "dependsOn" : [
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
+ ],
+ "properties" : {
+ "publisher" : "Microsoft.OSTCExtensions",
+ "type" : "CustomScriptForLinux",
+ "typeHandlerVersion" : "1.3",
+ "settings" : {
+ "fileUris" : [
+ "[concat(parameters('baseTemplateUrl'), 'store.sh')]"
+ ],
+ "commandToExecute" : "[ concat('sh store.sh ', resourceGroup().name, ' ', parameters('adminUsername'), ' ', variables('sQuote'), parameters('sshPrivateData'), variables('sQuote'), ' ', variables('sQuote'), parameters('sshKeyData'), variables('sQuote') ) ]"
+ }
+ }
+ },
+ {
+ "type" : "Microsoft.Network/networkSecurityGroups",
+ "name" : "[concat(parameters('vmName'), 'nsg')]",
+ "tags" : {
+ "displayName" : "NetworkSecurityGroup"
+ },
+ "apiVersion" : "[variables('apiVersion')]",
+ "location" : "[resourceGroup().location]",
+ "properties" : {
+ "securityRules" : [
+ {
+ "name" : "default-allow-ssh",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "22",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 1000,
+ "direction" : "Inbound"
+ }
+ },
+ {
+ "name" : "default-allow-iscsi",
+ "properties" : {
+ "protocol" : "Tcp",
+ "sourcePortRange" : "*",
+ "destinationPortRange" : "3260",
+ "sourceAddressPrefix" : "*",
+ "destinationAddressPrefix" : "*",
+ "access" : "Allow",
+ "priority" : 2000,
+ "direction" : "Inbound"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "outputs" : {}
+}
diff --git a/reference-architecture/azure-ansible/store.sh b/reference-architecture/azure-ansible/store.sh
new file mode 100755
index 000000000..036be1a10
--- /dev/null
+++ b/reference-architecture/azure-ansible/store.sh
@@ -0,0 +1,182 @@
+#!/bin/bash
+
+RESOURCEGROUP=${1}
+USERNAME=${2}
+SSHPRIVATEDATA=${3}
+SSHPUBLICDATA=${4}
+SSHPUBLICDATA2=${5}
+SSHPUBLICDATA3=${6}
+
+export OSEUSERNAME=$2
+
+ps -ef | grep store.sh > cmdline.out
+
+mkdir -p /home/$USERNAME/.ssh
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /home/$USERNAME/.ssh/id_rsa.pub
+echo $SSHPRIVATEDATA | base64 --d > /home/$USERNAME/.ssh/id_rsa
+chown $USERNAME /home/$USERNAME/.ssh/id_rsa.pub
+chmod 600 /home/$USERNAME/.ssh/id_rsa.pub
+chown $USERNAME /home/$USERNAME/.ssh/id_rsa
+chmod 600 /home/$USERNAME/.ssh/id_rsa
+
+mkdir -p /root/.ssh
+echo $SSHPRIVATEDATA | base64 --d > /root/.ssh/id_rsa
+echo $SSHPUBLICDATA $SSHPUBLICDATA2 $SSHPUBLICDATA3 > /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa.pub
+chmod 600 /root/.ssh/id_rsa.pub
+chown root /root/.ssh/id_rsa
+chmod 600 /root/.ssh/id_rsa
+
+
+yum -y update
+yum -y install targetcli
+yum -y install lvm2
+systemctl start target
+systemctl enable target
+systemctl restart target.service
+firewall-cmd --permanent --add-port=3260/tcp
+firewall-cmd --reload
+touch /root/.updateok
+pvcreate /dev/sdc /dev/sdd /dev/sde /dev/sdf /dev/sdg /dev/sdh /dev/sdi /dev/sdj
+parted --script -a optimal /dev/sdc mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdd mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sde mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdf mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdg mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdh mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdi mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+parted --script -a optimal /dev/sdj mklabel gpt mkpart primary xfs 1M 100% set 1 lvm on
+pvcreate /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1 /dev/sdg1 /dev/sdh1 /dev/sdi1 /dev/sdj1
+vgcreate vg1 /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1 /dev/sdg1 /dev/sdh1 /dev/sdi1 /dev/sdj1
+cat << 'EOFZ' > /root/ose_pvcreate_lun
+#!/bin/bash
+
+# $1 = volumegroup
+# $2 = size
+# #3 = count
+
+if [[ -z ${stripsize+x} ]]; then
+ stripsize=8
+ fi
+
+if [ $# -eq 0 ]; then
+ echo "pvcreatelun volgroup size count"
+ echo " volgroup is the volgroup as created by vgcreate"
+ echo " size - example 1G"
+ echo " count - Optional - Number of luns to create"
+ echo " $OSEUSERNAME should be set to the OpenShift User Name"
+ exit 0
+ fi
+# Call ourselves recursively to do repeats
+if [ $# -eq 3 ]; then
+ for ((i=0;i < $3;i++))
+ do
+ ./ose_pvcreate_lun $1 $2
+ done
+ exit 0
+ fi
+
+STOREIP=$(hostname --ip-address)
+LUNFILE=~/.oseluncount.cnt
+DEVFILE=~/.osedevcount.cnt
+TAG=$0
+
+if [ -e ${LUNFILE} ]; then
+ count=$(cat ${LUNFILE})
+else
+ touch "$LUNFILE"
+ count=0
+fi
+
+if [ -e ${DEVFILE} ]; then
+ dcount=$(cat ${DEVFILE})
+else
+ touch "$DEVFILE"
+ dcount=1
+ echo ${dcount} > ${DEVFILE}
+fi
+
+lunid=${count}
+((count++))
+
+echo ${count} > ${LUNFILE}
+
+printf -v padcnt "%03d" $count
+export padcnt
+export volname="ose${dcount}n${padcnt}x$2"
+
+lvcreate -L $2G -i$stripsize -I64 -n $volname $1 | logger --tag $TAG
+mkfs.ext4 -q -F /dev/vg1/$volname 2>&1 | logger --tag $TAG
+if [ ${count} -eq 1 ]; then
+ echo "Setup device"
+ targetcli /iscsi create iqn.2016-02.local.store${dcount}:t1 | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/acls create iqn.2016-02.local.azure.nodes | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/ set attribute authentication=0 | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/ set parameter DefaultTime2Retain=60 | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/ set parameter DefaultTime2Wait=12 | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/ set parameter MaxConnections=10000 | logger --tag $TAG
+ targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/ set attribute prod_mode_write_protect=0 | logger --tag $TAG
+ targetcli saveconfig
+fi
+
+targetcli backstores/block/ create "$volname" /dev/vg1/"$volname" | logger --tag $TAG
+targetcli /iscsi/iqn.2016-02.local.store${dcount}:t1/tpg1/luns create /backstores/block/"$volname" | logger --tag $TAG
+
+targetcli saveconfig | logger --tag $TAG
+
+cat < $volname.yml
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: iscsipv${dcount}x${padcnt}
+spec:
+ capacity:
+ storage: ${2}Gi
+ accessModes:
+ - ReadWriteOnce
+ iscsi:
+ targetPortal: $STOREIP
+ iqn: iqn.2016-02.local.store${dcount}:t1
+ lun: ${lunid}
+ fsType: 'ext4'
+ readOnly: false
+
+EOF
+oc create -f $volname.yml
+rm -f $volname.yml
+if [ ${count} -eq 100 ]; then
+ ((dcount++))
+ count=0
+ echo ${count} > ${LUNFILE}
+ echo ${dcount} > ${DEVFILE}
+fi
+
+EOFZ
+firewall-cmd --permanent --add-port=3260/tcp
+firewall-cmd --reload
+chmod +x /root/ose_pvcreate_lun
+cd ~
+while true
+do
+ STATUS=$(curl -k -s -o /dev/null -w '%{http_code}' https://master1:8443/api)
+ if [ $STATUS -eq 200 ]; then
+ echo "Got 200! All done!"
+ break
+ else
+ echo "."
+ fi
+ sleep 10
+done
+
+cd /root
+mkdir .kube
+scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USERNAME}@master1:~/.kube/config /tmp/kube-config
+cp /tmp/kube-config /root/.kube/config
+mkdir /home/${USERNAME}/.kube
+cp /tmp/kube-config /home/${USERNAME}/.kube/config
+chown --recursive ${USERNAME} /home/${USERNAME}/.kube
+rm -f /tmp/kube-config
+./ose_pvcreate_lun vg1 10 20
+./ose_pvcreate_lun vg1 50 4
+./ose_pvcreate_lun vg1 1 400
+systemctl restart target.service
diff --git a/reference-architecture/azure-ansible/testcases/test_pv.sh b/reference-architecture/azure-ansible/testcases/test_pv.sh
new file mode 100644
index 000000000..fd657401f
--- /dev/null
+++ b/reference-architecture/azure-ansible/testcases/test_pv.sh
@@ -0,0 +1,8 @@
+oc new-project demo
+oc new-app https://github.com/openshift/ruby-hello-world
+oc expose service ruby-hello-world
+oc process -n openshift mysql-persistent -v DATABASE_SERVICE_NAME=database | oc create -f -
+oc env dc database --list | oc env dc ruby-hello-world -e -
+oc get pods
+oc get pv
+