Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider/azurerm: Add example of vm custom image w/new storage account #14468

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
9f0d990
initial commit - 101-vm-from-user-image
anniehedgpeth Apr 18, 2017
6f577a8
changed branch name
anniehedgpeth Apr 19, 2017
611d70a
not deploying - storage problems
anniehedgpeth Apr 21, 2017
fdff23a
provisions vm but image not properly prepared
anniehedgpeth Apr 21, 2017
0dac5ec
storage not correct
anniehedgpeth Apr 21, 2017
81e2559
provisions properly
anniehedgpeth Apr 22, 2017
7dc8150
changed main.tf to azuredeploy.tf
anniehedgpeth Apr 22, 2017
5c079fa
added tfvars and info for README
anniehedgpeth Apr 22, 2017
c86ef6f
tfvars ignored and corrected file ext
anniehedgpeth Apr 22, 2017
534b236
added CI config; added sane defaults for variables; updated deploymen…
Apr 24, 2017
0cf888b
deploy.sh to be executable
Apr 24, 2017
68f0003
executable deploy files
Apr 24, 2017
c898510
added CI files; changed vars
anniehedgpeth Apr 25, 2017
9d1541c
merge upstream/master
Apr 25, 2017
5c8ecd8
prep for PR
Apr 25, 2017
0267fca
removal of old folder
Apr 25, 2017
f9bf6ba
prep for PR
Apr 25, 2017
cec0679
wrong args for travis
Apr 25, 2017
d78e8bd
more PR prep
Apr 26, 2017
6bf2df2
updated README
anniehedgpeth Apr 26, 2017
b22cff0
commented out variables in terraform.tfvars
Apr 26, 2017
09175de
Merge branch 'topic-101-vm-from-user-image' of https://github.com/10t…
anniehedgpeth Apr 26, 2017
0843f45
Topic 101 vm from user image (#2)
scottzilla Apr 26, 2017
49caea5
added new template
Apr 26, 2017
2236828
oops, left off master
Apr 26, 2017
27167b5
Merge branch 'master' of github.com:harijayms/terraform
Apr 26, 2017
5b8f7bb
merge upstream; prep for PR
Apr 26, 2017
7f8fe25
prep for PR
Apr 27, 2017
eecb2d2
correct repository for destination
Apr 27, 2017
92e341d
renamed scripts to be more intuitive; added check for docker
Apr 27, 2017
23627c8
merge vm simple; vm from image
Apr 27, 2017
0fdf4cb
merge upstream
Apr 27, 2017
ac2e5c2
initial commit
anniehedgpeth Apr 27, 2017
935c19a
deploys locally
anniehedgpeth Apr 27, 2017
66b7441
updated deploy
anniehedgpeth Apr 27, 2017
c98b1d1
consolidated deploy and after_deploy into a single script; simplified…
Apr 27, 2017
0ef07bc
added terraform show
Apr 27, 2017
50e8d8a
changed to allow http & https (like ARM tmplt)
anniehedgpeth Apr 27, 2017
ace9b0b
changed host_name & host_name variable desc
anniehedgpeth Apr 27, 2017
5e99f81
added az cli check
Apr 28, 2017
ce1f573
merge upstream master
Apr 28, 2017
65826c1
on this branch, only build test_dir; master will aggregate all the ex…
Apr 28, 2017
2675c55
merge master
Apr 28, 2017
072a51a
added new constructs/naming for deploy scripts, etc.
Apr 28, 2017
06f1a7f
suppress az login output
Apr 28, 2017
3523ed3
suppress az login output
Apr 28, 2017
21837a9
forgot about line breaks
Apr 28, 2017
e1e3aa2
breaking build as an example
Apr 28, 2017
a0a7643
fixing broken build example
Apr 28, 2017
fd0231b
added cdn branch; ci uses running vm to test
anniehedgpeth Apr 28, 2017
02bfac9
Merge remote-tracking branch 'origin' into topic-101-vnet-two-subnets
Apr 28, 2017
74c4f6c
Merge branch 'topic-101-vnet-two-subnets'
anniehedgpeth May 1, 2017
2c02115
merge of CI config
anniehedgpeth May 1, 2017
487d9cd
fixed grammar in readme
May 1, 2017
d8ef7b1
prep for PR
May 1, 2017
25ef50c
took out armviz button and minor README changes
anniehedgpeth May 2, 2017
63c494d
changed host_name
anniehedgpeth May 2, 2017
9a5a15a
fixed merge conflicts
anniehedgpeth May 2, 2017
d821717
Sync with upstream
StephenWeatherford May 2, 2017
d7e2acb
changed host_name variable
anniehedgpeth May 2, 2017
dbaf8d1
updating Hashicorp's changes to merged simple linux branch
anniehedgpeth May 3, 2017
b850cd5
updating files to merge w/master and prep for Hashicorp pr
anniehedgpeth May 3, 2017
a6151bc
Revert "updating files to merge w/master and prep for Hashicorp pr"
anniehedgpeth May 3, 2017
5426739
Revert "updating Hashicorp's changes to merged simple linux branch"
anniehedgpeth May 3, 2017
9b809ac
Merge branch 'master' into topic-201-cdn-with-storage-account
anniehedgpeth May 3, 2017
5174369
removing vm from user image example from this branch
anniehedgpeth May 4, 2017
007ea39
Merge branch 'master' into topic-101-vm-from-user-image
anniehedgpeth May 4, 2017
f6c13d4
Merge pull request #10 from 10thmagnitude/topic-101-vm-from-user-image
anniehedgpeth May 4, 2017
1366980
removed old branch
anniehedgpeth May 4, 2017
6a1813e
azure-2-vms-loadbalancer-lbrules (#13)
scottzilla May 5, 2017
888b578
add CI build tag
scottzilla May 8, 2017
08c4d7f
initial commit; in progress
anniehedgpeth May 9, 2017
645a0eb
in progress
anniehedgpeth May 9, 2017
4fa1c63
merging hashicorp master into this branch
anniehedgpeth May 10, 2017
58ff5c8
undoing change to readme
anniehedgpeth May 10, 2017
915c017
in progress
anniehedgpeth May 10, 2017
ec7e532
Merge branch 'master' of https://github.com/hashicorp/terraform into …
anniehedgpeth May 10, 2017
64db6e4
in progress
anniehedgpeth May 11, 2017
9828fa3
doesn't winrm
anniehedgpeth May 11, 2017
a300e6e
deploys locally
anniehedgpeth May 12, 2017
0e426a0
added vars to deploy scripts; removed nsg
anniehedgpeth May 13, 2017
4fad6a1
chmod
anniehedgpeth May 13, 2017
a20238a
https typo
anniehedgpeth May 13, 2017
b1bc33a
deploy cleanup
anniehedgpeth May 13, 2017
c8a0618
deploys locally
anniehedgpeth May 14, 2017
bdbad24
targeting resources for destroy
anniehedgpeth May 14, 2017
25b9a6d
added graph
anniehedgpeth May 14, 2017
c89701c
merging Hashicorp master into this branch
anniehedgpeth May 14, 2017
45991e2
removing unmerged example
anniehedgpeth May 14, 2017
632c33b
reverting to Hashicorp's travis.yml
anniehedgpeth May 14, 2017
e94b929
reverting to branch travis.yml before branching to pr to Hashi
anniehedgpeth May 14, 2017
68a08f0
reverting to Hashicorp's .travis.yml
anniehedgpeth May 14, 2017
2223e13
clean up
anniehedgpeth May 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Create a new VM on a new storage account from a custom image

This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-custom-image-new-storage-account) Azure Quickstart Template. Changes to the ARM template that may have occurred since the creation of this example may not be reflected here.

This template allows you to create a new Virtual Machine from a custom image on a new storage account deployed together with the storage account, which means the source image VHD must be transferred to the newly created storage account before that Virtual Machine is deployed. This is accomplished by the usage of a transfer virtual machine that is deployed and then uses a script via custom script extension to copy the source VHD to the destination storage account. This process is used to overcome the limitation of the custom VHD that needs to reside at the same storage account where new virtual machines based on it will be spun up, the problem arises when you are also deploying the storage account within your template, since the storage account does not exist yet, how can you add the source VHDs beforehand?

Basically, it creates two VMs, one that is the transfer virtual machine and the second that is the actual virtual machine that is the goal of the deployment. Transfer VM can be removed later.

The process of this template is:

1. A Virtual Network is deployed
2. Virtual NICs for both Virtual Machines
3. Storage Account is created
3. Transfer Virtual Machine gets deployed
4. Transfer Virtual Machine starts the custom script extension to start the VHD copy from source to destination storage acounts
5. The new Virtual Machine based on a custom image VHD gets deployed

## Requirements

* A preexisting generalized (sysprepped) Windows image. For more information on how to create custom Windows images, please refer to [How to capture a Windows virtual machine in the Resource Manager deployment model](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-capture-image/) article.
* Source image blob full URL. e.g. https://pmcstorage01.blob.core.windows.net/images/images/Win10MasterImage-osDisk.72451a98-4c26-4375-90c5-0a940dd56bab.vhd. Note that container name always comes after https://pmcstorage01.blob.core.windows.net, in this example it is images. The actual blob name is **images/Win10MasterImage-osDisk.72451a98-4c26-4375-90c5-0a940dd56bab.vhd**.

![graph](/examples/azure-vm-custom-image-new-storage-account/graph.png)
59 changes: 59 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/deploy.ci.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash

set -o errexit -o nounset

docker run --rm -it \
-e ARM_CLIENT_ID \
-e ARM_CLIENT_SECRET \
-e ARM_SUBSCRIPTION_ID \
-e ARM_TENANT_ID \
-v $(pwd):/data \
--workdir=/data \
--entrypoint "/bin/sh" \
hashicorp/terraform:light \
-c "/bin/terraform get; \
/bin/terraform validate; \
/bin/terraform plan -out=out.tfplan \
-var source_img_uri=$EXISTING_IMAGE_URI \
-var hostname=$KEY \
-var resource_group=$KEY \
-var existing_resource_group=$EXISTING_RESOURCE_GROUP \
-var admin_password=$PASSWORD \
-var existing_storage_acct=$EXISTING_STORAGE_ACCOUNT_NAME \
-var custom_image_name=$CUSTOM_IMAGE_NAME; \
/bin/terraform apply out.tfplan; \
/bin/terraform show;"

# cleanup deployed azure resources via azure-cli
docker run --rm -it \
azuresdk/azure-cli-python \
sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \
az vm show -g $KEY -n myvm; \
az storage account show -g $KEY -n $KEY;"

# cleanup deployed azure resources via terraform
docker run --rm -it \
-e ARM_CLIENT_ID \
-e ARM_CLIENT_SECRET \
-e ARM_SUBSCRIPTION_ID \
-e ARM_TENANT_ID \
-v $(pwd):/data \
--workdir=/data \
--entrypoint "/bin/sh" \
hashicorp/terraform:light \
-c "/bin/terraform destroy -force \
-var source_img_uri=$EXISTING_IMAGE_URI \
-var hostname=$KEY \
-var resource_group=$KEY \
-var existing_resource_group=$EXISTING_RESOURCE_GROUP \
-var admin_password=$PASSWORD \
-var existing_storage_acct=$EXISTING_STORAGE_ACCOUNT_NAME \
-var custom_image_name=$CUSTOM_IMAGE_NAME \
-target=azurerm_virtual_machine.myvm \
-target=azurerm_virtual_machine.transfer \
-target=azurerm_network_interface.transfernic \
-target=azurerm_network_interface.mynic \
-target=azurerm_virtual_network.vnet \
-target=azurerm_public_ip.mypip \
-target=azurerm_public_ip.transferpip \
-target=azurerm_storage_account.stor;"
19 changes: 19 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/deploy.mac.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -o errexit -o nounset

if docker -v; then

# generate a unique string for CI deployment
export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12)
export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2)
export EXISTING_RESOURCE_GROUP=donotdelete
export EXISTING_IMAGE_URI=https://donotdeletedisks636.blob.core.windows.net/vhds/mywindowsimage20170510184809.vhd
export EXISTING_STORAGE_ACCOUNT_NAME=donotdeletedisks636
export CUSTOM_IMAGE_NAME=mywindowsimage20170510184809

/bin/sh ./deploy.ci.sh

else
echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/"
fi
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 165 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# provider "azurerm" {
# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID"
# client_id = "REPLACE-WITH-YOUR-CLIENT-ID"
# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET"
# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID"
# }

resource "azurerm_resource_group" "rg" {
name = "${var.resource_group}"
location = "${var.location}"
}

resource "azurerm_virtual_network" "vnet" {
name = "${var.hostname}vnet"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
address_space = ["${var.address_space}"]
}

resource "azurerm_subnet" "subnet" {
name = "${var.hostname}subnet"
virtual_network_name = "${azurerm_virtual_network.vnet.name}"
resource_group_name = "${azurerm_resource_group.rg.name}"
address_prefix = "${var.subnet_prefix}"
}

resource "azurerm_public_ip" "transferpip" {
name = "transferpip"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
public_ip_address_allocation = "Static"
}

resource "azurerm_network_interface" "transfernic" {
name = "transfernic"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"

ip_configuration {
name = "${azurerm_public_ip.transferpip.name}"
subnet_id = "${azurerm_subnet.subnet.id}"
private_ip_address_allocation = "Static"
public_ip_address_id = "${azurerm_public_ip.transferpip.id}"
private_ip_address = "10.0.0.5"
}
}

resource "azurerm_public_ip" "mypip" {
name = "mypip"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
public_ip_address_allocation = "Dynamic"
}

resource "azurerm_network_interface" "mynic" {
name = "mynic"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"

ip_configuration {
name = "${azurerm_public_ip.mypip.name}"
subnet_id = "${azurerm_subnet.subnet.id}"
private_ip_address_allocation = "Dynamic"
public_ip_address_id = "${azurerm_public_ip.mypip.id}"
}
}

resource "azurerm_storage_account" "existing" {
name = "${var.existing_storage_acct}"
resource_group_name = "${var.existing_resource_group}"
location = "${azurerm_resource_group.rg.location}"
account_type = "${var.existing_storage_acct_type}"

lifecycle = {
prevent_destroy = true
}
}

resource "azurerm_storage_account" "stor" {
name = "${var.hostname}"
resource_group_name = "${azurerm_resource_group.rg.name}"
location = "${azurerm_resource_group.rg.location}"
account_type = "${var.storage_account_type}"
}

resource "azurerm_virtual_machine" "transfer" {
name = "${var.transfer_vm_name}"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
vm_size = "${var.vm_size}"
network_interface_ids = ["${azurerm_network_interface.transfernic.id}"]

storage_os_disk {
name = "${var.hostname}-osdisk"
image_uri = "${var.source_img_uri}"
vhd_uri = "https://${var.existing_storage_acct}.blob.core.windows.net/${var.existing_resource_group}-vhds/${var.hostname}osdisk.vhd"
os_type = "${var.os_type}"
caching = "ReadWrite"
create_option = "FromImage"
}

os_profile {
computer_name = "${var.hostname}"
admin_username = "${var.admin_username}"
admin_password = "${var.admin_password}"
}
}

resource "azurerm_virtual_machine_extension" "script" {
name = "CustomScriptExtension"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
virtual_machine_name = "${azurerm_virtual_machine.transfer.name}"
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.4"
depends_on = ["azurerm_virtual_machine.transfer"]

settings = <<SETTINGS
{
"commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"Invoke-WebRequest -Uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-custom-image-new-storage-account/ImageTransfer.ps1 -OutFile C:/ImageTransfer.ps1\" "
}
SETTINGS
}

resource "azurerm_virtual_machine_extension" "execute" {
name = "CustomScriptExtension"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
virtual_machine_name = "${azurerm_virtual_machine.transfer.name}"
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.4"
depends_on = ["azurerm_virtual_machine_extension.script"]

settings = <<SETTINGS
{
"commandToExecute": "powershell -ExecutionPolicy Unrestricted -File C:\\ImageTransfer.ps1 -SourceImage ${var.source_img_uri} -SourceSAKey ${azurerm_storage_account.existing.primary_access_key} -DestinationURI https://${azurerm_storage_account.stor.name}.blob.core.windows.net/vhds -DestinationSAKey ${azurerm_storage_account.stor.primary_access_key}\" "
}
SETTINGS
}

resource "azurerm_virtual_machine" "myvm" {
name = "${var.new_vm_name}"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
vm_size = "${var.vm_size}"
network_interface_ids = ["${azurerm_network_interface.mynic.id}"]
depends_on = ["azurerm_virtual_machine_extension.execute"]

storage_os_disk {
name = "${var.hostname}osdisk"
image_uri = "https://${azurerm_storage_account.stor.name}.blob.core.windows.net/vhds/${var.custom_image_name}.vhd"
vhd_uri = "https://${var.hostname}.blob.core.windows.net/${var.hostname}-vhds/${var.hostname}osdisk.vhd"
os_type = "${var.os_type}"
caching = "ReadWrite"
create_option = "FromImage"
}

os_profile {
computer_name = "${var.hostname}"
admin_username = "${var.admin_username}"
admin_password = "${var.admin_password}"
}
}
15 changes: 15 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "hostname" {
value = "${var.hostname}"
}

output "ip_address" {
value = "${azurerm_public_ip.transferpip.ip_address}"
}

output "fqdn" {
value = "${azurerm_public_ip.transferpip.ip_address}"
}

output "id" {
value = "${azurerm_public_ip.transferpip.id}"
}
97 changes: 97 additions & 0 deletions examples/azure-vm-custom-image-new-storage-account/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
variable "resource_group" {
description = "Name of the resource group in which to deploy your new Virtual Machines"
}

variable "location" {
description = "The location/region where the virtual network resides."
default = "southcentralus"
}

variable "hostname" {
description = "This variable is used in this template to create various other names, such as vnet name, subnet name, storage account name, et. al."
}

variable "os_type" {
description = "Type of OS on the existing vhd. Allowed values: 'windows' or 'linux'."
default = "windows"
}

variable "existing_storage_acct" {
description = "The name of the storage account in which your existing VHD and image reside"
}

variable "existing_storage_acct_type" {
description = "The type of the storage account in which your existing VHD and image reside"
default = "Premium_LRS"
}

variable "existing_resource_group" {
description = "The name of the resource group in which your existing storage account with your existing VHD resides"
}

variable "address_space" {
description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created."
default = "10.0.0.0/16"
}

variable "subnet_prefix" {
description = "The address prefix to use for the subnet."
default = "10.0.0.0/24"
}

variable "storage_account_type" {
description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types."
default = "Standard_LRS"
}

variable "vm_size" {
description = "VM size of new virtual machine that will be deployed from a custom image."
default = "Standard_DS1_v2"
}

variable "image_publisher" {
description = "name of the publisher of the image (az vm image list)"
default = "MicrosoftWindowsServer"
}

variable "image_offer" {
description = "the name of the offer (az vm image list)"
default = "WindowsServer"
}

variable "image_sku" {
description = "image sku to apply (az vm image list)"
default = "2012-R2-Datacenter"
}

variable "image_version" {
description = "version of the image to apply (az vm image list)"
default = "latest"
}

variable "admin_username" {
description = "Name of the local administrator account, this cannot be 'Admin', 'Administrator', or 'root'."
default = "vmadmin"
}

variable "admin_password" {
description = "Local administrator password, complex password is required, do not use any variation of the word 'password' because it will be rejected. Minimum 8 characters."
}

variable "transfer_vm_name" {
description = "Name of the Windows VM that will perform the copy of the VHD from a source storage account to the new storage account created in the new deployment, this is known as transfer vm. Must be 3-15 characters."
default = "transfervm"
}

variable "new_vm_name" {
description = "Name of the new VM deployed from the custom image. Must be 3-15 characters."
default = "myvm"
}

variable "custom_image_name" {
description = "Name of the VHD to be used as source syspreped/generalized image to deploy the VM, for example 'mybaseimage.vhd'"
}

variable "source_img_uri" {
description = "Full URIs for one or more custom images (VHDs) that should be copied to the deployment storage account to spin up new VMs from them. URLs must be comma separated."
}