azure_rm_virtualmachine (and _facts): add boot_diagnostics control and facts (#49661)

pull/56198/head
James E. King III 6 years ago committed by Zim Kalinowski
parent 0d2a120454
commit 75788ecff4

@ -2,6 +2,7 @@
# #
# Copyright (c) 2016 Matt Davis, <mdavis@ansible.com> # Copyright (c) 2016 Matt Davis, <mdavis@ansible.com>
# Chris Houseknecht, <house@redhat.com> # Chris Houseknecht, <house@redhat.com>
# Copyright (c) 2018 James E. King, III (@jeking3) <jking@apache.org>
# #
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@ -277,8 +278,8 @@ options:
remove_on_absent: remove_on_absent:
description: description:
- "When removing a VM using state 'absent', also remove associated resources." - "When removing a VM using state 'absent', also remove associated resources."
- "It can be 'all' or 'all_autocreated' or a list with any of the following: ['network_interfaces', 'virtual_storage', 'public_ips']." - "It can be a list with any of the following: ['all', 'all_autocreated', 'network_interfaces', 'virtual_storage', 'public_ips']."
- "To remove all resources referred by VM use 'all'." - "To remove all resources referred by VM use 'all' (this includes autocreated)."
- "To remove all resources that were automatically created while provisioning VM use 'all_autocreated'." - "To remove all resources that were automatically created while provisioning VM use 'all_autocreated'."
- Any other input will be ignored. - Any other input will be ignored.
default: ['all'] default: ['all']
@ -352,6 +353,26 @@ options:
description: description:
- Specifies the certificate store on the Virtual Machine to which the certificate - Specifies the certificate store on the Virtual Machine to which the certificate
should be added. The specified certificate store is implicitly in the LocalMachine account. should be added. The specified certificate store is implicitly in the LocalMachine account.
boot_diagnostics:
description:
- Manage boot diagnostics settings for a virtual machine. Boot diagnostics
includes a serial console and remote console screenshots.
version_added: '2.9'
suboptions:
enabled:
description:
- Flag indicating if boot diagnostics is enabled.
required: true
type: bool
storage_account:
description:
- The name of an existing storage account to use for boot diagnostics.
- If omitted and C(storage_account_name) is defined one level up, that
will be used instead.
- If omitted and C(storage_account_name) is not defined one level up, and
C(enabled) is I(true), then a default storage account will be created
or used for the virtual machine to hold the boot diagnostics data.
required: false
extends_documentation_fragment: extends_documentation_fragment:
- azure - azure
@ -361,7 +382,7 @@ author:
- "Chris Houseknecht (@chouseknecht)" - "Chris Houseknecht (@chouseknecht)"
- "Matt Davis (@nitzmahone)" - "Matt Davis (@nitzmahone)"
- "Christopher Perrin (@cperrin88)" - "Christopher Perrin (@cperrin88)"
- "James E. King III (@jeking3)"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -452,6 +473,8 @@ EXAMPLES = '''
network_interfaces: testvm001 network_interfaces: testvm001
storage_container: osdisk storage_container: osdisk
storage_blob: osdisk.vhd storage_blob: osdisk.vhd
boot_diagnostics:
enabled: yes
image: image:
offer: CoreOS offer: CoreOS
publisher: CoreOS publisher: CoreOS
@ -798,7 +821,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
accept_terms=dict(type='bool', default=False), accept_terms=dict(type='bool', default=False),
license_type=dict(type='str', choices=['Windows_Server', 'Windows_Client']), license_type=dict(type='str', choices=['Windows_Server', 'Windows_Client']),
vm_identity=dict(type='str', choices=['SystemAssigned']), vm_identity=dict(type='str', choices=['SystemAssigned']),
winrm=dict(type='list') winrm=dict(type='list'),
boot_diagnostics=dict(type='dict'),
) )
self.resource_group = None self.resource_group = None
@ -842,6 +866,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.zones = None self.zones = None
self.license_type = None self.license_type = None
self.vm_identity = None self.vm_identity = None
self.boot_diagnostics = None
self.results = dict( self.results = dict(
changed=False, changed=False,
@ -853,6 +878,45 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
super(AzureRMVirtualMachine, self).__init__(derived_arg_spec=self.module_arg_spec, super(AzureRMVirtualMachine, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True) supports_check_mode=True)
@property
def boot_diagnostics_present(self):
return self.boot_diagnostics is not None and 'enabled' in self.boot_diagnostics
def get_boot_diagnostics_storage_account(self, limited=False, vm_dict=None):
"""
Get the boot diagnostics storage account.
Arguments:
- limited - if true, limit the logic to the boot_diagnostics storage account
this is used if initial creation of the VM has a stanza with
boot_diagnostics disabled, so we only create a storage account
if the user specifies a storage account name inside the boot_diagnostics
schema
- vm_dict - if invoked on an update, this is the current state of the vm including
tags, like the default storage group tag '_own_sa_'.
Normal behavior:
- try the self.boot_diagnostics.storage_account field
- if not there, try the self.storage_account_name field
- if not there, use the default storage account
If limited is True:
- try the self.boot_diagnostics.storage_account field
- if not there, None
"""
bsa = None
if 'storage_account' in self.boot_diagnostics:
bsa = self.get_storage_account(self.boot_diagnostics['storage_account'])
elif limited:
return None
elif self.storage_account_name:
bsa = self.get_storage_account(self.storage_account_name)
else:
bsa = self.create_default_storage_account(vm_dict=vm_dict)
self.log("boot diagnostics storage account:")
self.log(self.serialize_obj(bsa, 'StorageAccount'), pretty_print=True)
return bsa
def exec_module(self, **kwargs): def exec_module(self, **kwargs):
for key in list(self.module_arg_spec.keys()) + ['tags']: for key in list(self.module_arg_spec.keys()) + ['tags']:
@ -869,6 +933,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
results = dict() results = dict()
vm = None vm = None
network_interfaces = [] network_interfaces = []
requested_storage_uri = None
requested_vhd_uri = None requested_vhd_uri = None
data_disk_requested_vhd_uri = None data_disk_requested_vhd_uri = None
disable_ssh_password = None disable_ssh_password = None
@ -943,7 +1008,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if self.storage_account_name and not self.managed_disk_type: if self.storage_account_name and not self.managed_disk_type:
properties = self.get_storage_account(self.storage_account_name) properties = self.get_storage_account(self.storage_account_name)
requested_vhd_uri = '{0}{1}/{2}'.format(properties.primary_endpoints.blob, requested_storage_uri = properties.primary_endpoints.blob
requested_vhd_uri = '{0}{1}/{2}'.format(requested_storage_uri,
self.storage_container_name, self.storage_container_name,
self.storage_blob_name) self.storage_blob_name)
@ -1044,6 +1110,46 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if self.license_type is not None and vm_dict['properties'].get('licenseType') != self.license_type: if self.license_type is not None and vm_dict['properties'].get('licenseType') != self.license_type:
differences.append('License Type') differences.append('License Type')
changed = True changed = True
# Defaults for boot diagnostics
if 'diagnosticsProfile' not in vm_dict['properties']:
vm_dict['properties']['diagnosticsProfile'] = {}
if 'bootDiagnostics' not in vm_dict['properties']['diagnosticsProfile']:
vm_dict['properties']['diagnosticsProfile']['bootDiagnostics'] = {
'enabled': False,
'storageUri': None
}
if self.boot_diagnostics_present:
current_boot_diagnostics = vm_dict['properties']['diagnosticsProfile']['bootDiagnostics']
boot_diagnostics_changed = False
if self.boot_diagnostics['enabled'] != current_boot_diagnostics['enabled']:
current_boot_diagnostics['enabled'] = self.boot_diagnostics['enabled']
boot_diagnostics_changed = True
boot_diagnostics_storage_account = self.get_boot_diagnostics_storage_account(
limited=not self.boot_diagnostics['enabled'], vm_dict=vm_dict)
boot_diagnostics_blob = boot_diagnostics_storage_account.primary_endpoints.blob if boot_diagnostics_storage_account else None
if current_boot_diagnostics['storageUri'] != boot_diagnostics_blob:
current_boot_diagnostics['storageUri'] = boot_diagnostics_blob
boot_diagnostics_changed = True
if boot_diagnostics_changed:
differences.append('Boot Diagnostics')
changed = True
# Adding boot diagnostics can create a default storage account after initial creation
# this means we might also need to update the _own_sa_ tag
own_sa = (self.tags or {}).get('_own_sa_', None)
cur_sa = vm_dict.get('tags', {}).get('_own_sa_', None)
if own_sa and own_sa != cur_sa:
if 'Tags' not in differences:
differences.append('Tags')
if 'tags' not in vm_dict:
vm_dict['tags'] = {}
vm_dict['tags']['_own_sa_'] = own_sa
changed = True
self.differences = differences self.differences = differences
elif self.state == 'absent': elif self.state == 'absent':
@ -1066,7 +1172,6 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if changed: if changed:
if self.state == 'present': if self.state == 'present':
default_storage_account = None
if not vm: if not vm:
# Create the VM # Create the VM
self.log("Create virtual machine {0}".format(self.name)) self.log("Create virtual machine {0}".format(self.name))
@ -1103,14 +1208,15 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
# os disk # os disk
if not self.storage_account_name and not self.managed_disk_type: if not self.storage_account_name and not self.managed_disk_type:
storage_account = self.create_default_storage_account() storage_account = self.create_default_storage_account()
self.log("storage account:") self.log("os disk storage account:")
self.log(self.serialize_obj(storage_account, 'StorageAccount'), pretty_print=True) self.log(self.serialize_obj(storage_account, 'StorageAccount'), pretty_print=True)
requested_vhd_uri = 'https://{0}.blob.{1}/{2}/{3}'.format( requested_storage_uri = 'https://{0}.blob.{1}/'.format(
storage_account.name, storage_account.name,
self._cloud_environment.suffixes.storage_endpoint, self._cloud_environment.suffixes.storage_endpoint)
requested_vhd_uri = '{0}{1}/{2}'.format(
requested_storage_uri,
self.storage_container_name, self.storage_container_name,
self.storage_blob_name) self.storage_blob_name)
default_storage_account = storage_account # store for use by data disks if necessary
if not self.short_hostname: if not self.short_hostname:
self.short_hostname = self.name self.short_hostname = self.name
@ -1135,7 +1241,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
publisher=self.plan.get('publisher'), publisher=self.plan.get('publisher'),
promotion_code=self.plan.get('promotion_code')) promotion_code=self.plan.get('promotion_code'))
license_type = self.license_type # do this before creating vm_resource as it can modify tags
if self.boot_diagnostics_present and self.boot_diagnostics['enabled']:
boot_diag_storage_account = self.get_boot_diagnostics_storage_account()
vm_resource = self.compute_models.VirtualMachine( vm_resource = self.compute_models.VirtualMachine(
location=self.location, location=self.location,
@ -1206,6 +1314,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
elif not vm_resource.os_profile.windows_configuration.win_rm: elif not vm_resource.os_profile.windows_configuration.win_rm:
vm_resource.os_profile.windows_configuration.win_rm = winrm vm_resource.os_profile.windows_configuration.win_rm = winrm
if self.boot_diagnostics_present:
vm_resource.diagnostics_profile = self.compute_models.DiagnosticsProfile(
boot_diagnostics=self.compute_models.BootDiagnostics(
enabled=self.boot_diagnostics['enabled'],
storage_uri=boot_diag_storage_account.primary_endpoints.blob))
if self.admin_password: if self.admin_password:
vm_resource.os_profile.admin_password = self.admin_password vm_resource.os_profile.admin_password = self.admin_password
@ -1237,13 +1351,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if data_disk.get('storage_account_name'): if data_disk.get('storage_account_name'):
data_disk_storage_account = self.get_storage_account(data_disk['storage_account_name']) data_disk_storage_account = self.get_storage_account(data_disk['storage_account_name'])
else: else:
if(not default_storage_account): data_disk_storage_account = self.create_default_storage_account()
data_disk_storage_account = self.create_default_storage_account() self.log("data disk storage account:")
self.log("data disk storage account:") self.log(self.serialize_obj(data_disk_storage_account, 'StorageAccount'), pretty_print=True)
self.log(self.serialize_obj(data_disk_storage_account, 'StorageAccount'), pretty_print=True)
default_storage_account = data_disk_storage_account # store for use by future data disks if necessary
else:
data_disk_storage_account = default_storage_account
if not data_disk.get('storage_container_name'): if not data_disk.get('storage_container_name'):
data_disk['storage_container_name'] = 'vhds' data_disk['storage_container_name'] = 'vhds'
@ -1292,7 +1402,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
term = self.marketplace_client.marketplace_agreements.get( term = self.marketplace_client.marketplace_agreements.get(
publisher_id=plan_publisher, offer_id=plan_product, plan_id=plan_name) publisher_id=plan_publisher, offer_id=plan_product, plan_id=plan_name)
term.accepted = True term.accepted = True
agreement = self.marketplace_client.marketplace_agreements.create( self.marketplace_client.marketplace_agreements.create(
publisher_id=plan_publisher, offer_id=plan_product, plan_id=plan_name, parameters=term) publisher_id=plan_publisher, offer_id=plan_product, plan_id=plan_name, parameters=term)
except Exception as exc: except Exception as exc:
self.fail(("Error accepting terms for virtual machine {0} with plan {1}. " + self.fail(("Error accepting terms for virtual machine {0} with plan {1}. " +
@ -1353,9 +1463,6 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
) )
else: else:
os_profile = None os_profile = None
license_type = None
if self.license_type is None:
license_type = "None"
vm_resource = self.compute_models.VirtualMachine( vm_resource = self.compute_models.VirtualMachine(
location=vm_dict['location'], location=vm_dict['location'],
@ -1384,6 +1491,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if self.license_type is not None: if self.license_type is not None:
vm_resource.license_type = self.license_type vm_resource.license_type = self.license_type
if self.boot_diagnostics is not None:
vm_resource.diagnostics_profile = self.compute_models.DiagnosticsProfile(
boot_diagnostics=self.compute_models.BootDiagnostics(
enabled=vm_dict['properties']['diagnosticsProfile']['bootDiagnostics']['enabled'],
storage_uri=vm_dict['properties']['diagnosticsProfile']['bootDiagnostics']['storageUri']))
if vm_dict.get('tags'): if vm_dict.get('tags'):
vm_resource.tags = vm_dict['tags'] vm_resource.tags = vm_dict['tags']
@ -1661,26 +1774,26 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
except Exception as exc: except Exception as exc:
self.fail("Error deleting virtual machine {0} - {1}".format(self.name, str(exc))) self.fail("Error deleting virtual machine {0} - {1}".format(self.name, str(exc)))
if 'all_autocreated' in self.remove_on_absent: if 'all' in self.remove_on_absent or 'all_autocreated' in self.remove_on_absent:
self.remove_autocreated_resources(vm.tags) self.remove_autocreated_resources(vm.tags)
else:
# TODO: parallelize nic, vhd, and public ip deletions with begin_deleting
# TODO: best-effort to keep deleting other linked resources if we encounter an error
if self.remove_on_absent.intersection(set(['all', 'virtual_storage'])):
self.log('Deleting VHDs')
self.delete_vm_storage(vhd_uris)
self.log('Deleting managed disks')
self.delete_managed_disks(managed_disk_ids)
if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])): # TODO: parallelize nic, vhd, and public ip deletions with begin_deleting
self.log('Deleting network interfaces') # TODO: best-effort to keep deleting other linked resources if we encounter an error
for nic_dict in nic_names: if self.remove_on_absent.intersection(set(['all', 'virtual_storage'])):
self.delete_nic(nic_dict['resource_group'], nic_dict['name']) self.log('Deleting VHDs')
self.delete_vm_storage(vhd_uris)
self.log('Deleting managed disks')
self.delete_managed_disks(managed_disk_ids)
if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])):
self.log('Deleting network interfaces')
for nic_dict in nic_names:
self.delete_nic(nic_dict['resource_group'], nic_dict['name'])
if self.remove_on_absent.intersection(set(['all', 'public_ips'])): if self.remove_on_absent.intersection(set(['all', 'public_ips'])):
self.log('Deleting public IPs') self.log('Deleting public IPs')
for pip_dict in pip_names: for pip_dict in pip_names:
self.delete_pip(pip_dict['resource_group'], pip_dict['name']) self.delete_pip(pip_dict['resource_group'], pip_dict['name'])
return True return True
@ -1841,10 +1954,15 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
return True return True
return False return False
def create_default_storage_account(self): def create_default_storage_account(self, vm_dict=None):
''' '''
Create a default storage account <vm name>XXXX, where XXXX is a random number. If <vm name>XXXX exists, use it. Create (once) a default storage account <vm name>XXXX, where XXXX is a random number.
Otherwise, create one. NOTE: If <vm name>XXXX exists, use it instead of failing. Highly unlikely.
If this method is called multiple times across executions it will return the same
storage account created with the random name which is stored in a tag on the VM.
vm_dict is passed in during an update, so we can obtain the _own_sa_ tag and return
the default storage account we created in a previous invocation
:return: storage account object :return: storage account object
''' '''
@ -1853,6 +1971,15 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if self.tags is None: if self.tags is None:
self.tags = {} self.tags = {}
if self.tags.get('_own_sa_', None):
# We previously created one in the same invocation
return self.get_storage_account(self.tags['_own_sa_'])
if vm_dict and vm_dict.get('tags', {}).get('_own_sa_', None):
# We previously created one in a previous invocation
# We must be updating, like adding boot diagnostics
return self.get_storage_account(vm_dict['tags']['_own_sa_'])
# Attempt to find a valid storage account name # Attempt to find a valid storage account name
storage_account_name_base = re.sub('[^a-zA-Z0-9]', '', self.name[:20].lower()) storage_account_name_base = re.sub('[^a-zA-Z0-9]', '', self.name[:20].lower())
for i in range(0, 5): for i in range(0, 5):

@ -24,7 +24,7 @@ version_added: "2.7"
short_description: Get virtual machine facts. short_description: Get virtual machine facts.
description: description:
- Get facts for all virtual machines of a resource group. - Get facts for one or all virtual machines in a resource group.
options: options:
resource_group: resource_group:
@ -76,6 +76,32 @@ vms:
returned: always returned: always
type: str type: str
sample: admin sample: admin
boot_diagnostics:
description:
- Information about the boot diagnostics settings.
returned: always
type: complex
contains:
enabled:
description:
- Indicates if boot diagnostics are enabled.
type: bool
sample: true
storage_uri:
description:
- Indicates the storage account used by boot diagnostics.
type: str
sample: https://mystorageaccountname.blob.core.windows.net/
console_screenshot_uri:
description:
- Contains a URI to grab a console screenshot.
- Only present if enabled.
type: str
serial_console_log_uri:
description:
- Contains a URI to grab the serial console log.
- Only present if enabled.
type: str
data_disks: data_disks:
description: description:
- List of attached data disks. - List of attached data disks.
@ -206,8 +232,7 @@ except Exception:
# This is handled in azure_rm_common # This is handled in azure_rm_common
pass pass
from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict from ansible.module_utils.azure_rm_common import AzureRMModuleBase
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict
from ansible.module_utils.six.moves.urllib.parse import urlparse from ansible.module_utils.six.moves.urllib.parse import urlparse
import re import re
@ -358,6 +383,18 @@ class AzureRMVirtualMachineFacts(AzureRMModuleBase):
'id': image.get('id', None) 'id': image.get('id', None)
} }
new_result['boot_diagnostics'] = {
'enabled': 'diagnosticsProfile' in result['properties'] and
'bootDiagnostics' in result['properties']['diagnosticsProfile'] and
result['properties']['diagnosticsProfile']['bootDiagnostics']['enabled'] or False,
'storage_uri': 'diagnosticsProfile' in result['properties'] and
'bootDiagnostics' in result['properties']['diagnosticsProfile'] and
result['properties']['diagnosticsProfile']['bootDiagnostics']['storageUri'] or None
}
if new_result['boot_diagnostics']['enabled']:
new_result['boot_diagnostics']['console_screenshot_uri'] = result['properties']['instanceView']['bootDiagnostics']['consoleScreenshotBlobUri']
new_result['boot_diagnostics']['serial_console_log_uri'] = result['properties']['instanceView']['bootDiagnostics']['serialConsoleLogBlobUri']
vhd = result['properties']['storageProfile']['osDisk'].get('vhd') vhd = result['properties']['storageProfile']['osDisk'].get('vhd')
if vhd is not None: if vhd is not None:
url = urlparse(vhd['uri']) url = urlparse(vhd['uri'])

@ -1 +1,3 @@
- include: setup.yml
- include: virtualmachine.yml - include: virtualmachine.yml
- include: teardown.yml

@ -0,0 +1,74 @@
- name: Create random names
set_fact:
storage_account: "{{ resource_group | hash('md5') | truncate(24, True, '') }}"
storage_account2: "{{ resource_group | hash('md5') | truncate(18, True, '') }}"
vm_name1: "vm1{{ resource_group | hash('md5') | truncate(5, True, '') }}"
vm_name2: "vm2{{ resource_group | hash('md5') | truncate(5, True, '') }}"
vm_name3: "vm3{{ resource_group | hash('md5') | truncate(5, True, '') }}"
vm_name4: "vm4{{ resource_group | hash('md5') | truncate(5, True, '') }}"
abs_name1: "avbs1{{ resource_group | hash('md5') | truncate(3, True, '') }}"
abs_name2: "avbs2{{ resource_group | hash('md5') | truncate(3, True, '') }}"
- name: Create storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
account_type: Standard_LRS
- name: Create 2nd storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account2 }}"
account_type: Standard_LRS
- name: Create an availability set
azure_rm_availabilityset:
name: "{{ abs_name1 }}"
resource_group: "{{ resource_group }}"
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
address_prefixes: "10.10.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
address_prefix: "10.10.0.0/24"
virtual_network: "{{ vm_name1 }}"
- name: Create public ip
azure_rm_publicipaddress:
resource_group: "{{ resource_group }}"
allocation_method: Static
name: "{{ vm_name1 }}"
- name: Create security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
purge_rules: yes
rules:
- name: ALLOW_SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 100
direction: Inbound
- name: ALLOW_HTTP
protocol: Tcp
destination_port_range: 80
access: Allow
priority: 110
direction: Inbound
- name: Create NIC for single nic VM
azure_rm_networkinterface:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
virtual_network: "{{ vm_name1 }}"
subnet: "{{ vm_name1 }}"
public_ip_name: "{{ vm_name1 }}"
security_group: "{{ vm_name1 }}"

@ -0,0 +1,62 @@
- name: Destroy NIC for single nic VM
azure_rm_networkinterface:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
state: absent
- name: Destroy 2nd security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ vm_name2 }}"
state: absent
- name: Destroy security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
state: absent
- name: Destroy subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
virtual_network: "{{ vm_name1 }}"
name: "{{ vm_name1 }}"
state: absent
- name: Destroy virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
state: absent
- name: Destroy public ip
azure_rm_publicipaddress:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
state: absent
- name: Destroy 2nd availability set
azure_rm_availabilityset:
resource_group: "{{ resource_group }}"
name: "{{ abs_name2 }}"
state: absent
- name: Destroy an availability set
azure_rm_availabilityset:
resource_group: "{{ resource_group }}"
name: "{{ abs_name1 }}"
state: absent
- name: Destroy 2nd storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account2 }}"
force_delete_nonempty: true
state: absent
- name: Destroy storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
force_delete_nonempty: true
state: absent

@ -1,71 +1,4 @@
- name: Create random names - name: Create virtual machine with a single NIC and no boot diagnostics
set_fact:
storage_account: "{{ resource_group | hash('md5') | truncate(24, True, '') }}"
vm_name1: "vm1{{ resource_group | hash('md5') | truncate(5, True, '') }}"
vm_name2: "vm2{{ resource_group | hash('md5') | truncate(5, True, '') }}"
vm_name3: "vm3{{ resource_group | hash('md5') | truncate(5, True, '') }}"
abs_name1: "avbs1{{ resource_group | hash('md5') | truncate(3, True, '') }}"
abs_name2: "avbs2{{ resource_group | hash('md5') | truncate(3, True, '') }}"
- name: Create storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
account_type: Standard_LRS
- name: Create an availability set
azure_rm_availabilityset:
name: "{{ abs_name1 }}"
resource_group: "{{ resource_group }}"
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
address_prefixes: "10.10.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
address_prefix: "10.10.0.0/24"
virtual_network: "{{ vm_name1 }}"
- name: Create public ip
azure_rm_publicipaddress:
resource_group: "{{ resource_group }}"
allocation_method: Static
name: "{{ vm_name1 }}"
- name: Create security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
purge_rules: yes
rules:
- name: ALLOW_SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 100
direction: Inbound
- name: ALLOW_HTTP
protocol: Tcp
destination_port_range: 80
access: Allow
priority: 110
direction: Inbound
- name: Create NIC for single nic VM
azure_rm_networkinterface:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
virtual_network: "{{ vm_name1 }}"
subnet: "{{ vm_name1 }}"
public_ip_name: "{{ vm_name1 }}"
security_group: "{{ vm_name1 }}"
- name: Create virtual machine with a single NIC
register: output register: output
azure_rm_virtualmachine: azure_rm_virtualmachine:
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
@ -91,7 +24,92 @@
- assert: - assert:
that: that:
- azure_vm.properties.provisioningState == 'Succeeded'
- azure_vm.properties.availabilitySet.id - azure_vm.properties.availabilitySet.id
# initial response from creation has no diagnosticsProfile
# if you run it again however, there is one in the response
# so we handle both cases
- "'diagnosticsProfile' not in azure_vm.properties or not azure_vm.properties.diagnosticsProfile.bootDiagnostics.enabled"
- name: Get facts for virtual machine without boot diagnostics disabled
azure_rm_virtualmachine_facts:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
register: output
- assert:
that:
- output.vms != []
- not output.vms[0].boot_diagnostics.enabled
- not output.vms[0].boot_diagnostics.storage_uri
- name: Enable boot diagnostics on an existing VM for the first time without specifying a storage account
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
boot_diagnostics:
enabled: true
# without specifying storage_account you get a new default storage account for the VM
register: output
- assert:
that:
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.enabled
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.storageUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.consoleScreenshotBlobUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.serialConsoleLogBlobUri is defined
- name: Get facts for virtual machine with boot diagnostics enabled
azure_rm_virtualmachine_facts:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
register: output
- assert:
that:
- output.vms != []
- output.vms[0].boot_diagnostics.enabled
- output.vms[0].boot_diagnostics.storage_uri is defined
- output.vms[0].boot_diagnostics.console_screenshot_uri is defined
- output.vms[0].boot_diagnostics.serial_console_log_uri is defined
- name: Change the boot diagnostics storage account while enabled
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
boot_diagnostics:
enabled: true
storage_account: "{{ storage_account2 }}"
ignore_errors: true
register: output
- name: Disable boot diagnostics and change the storage account at the same time
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
boot_diagnostics:
enabled: false
storage_account: "{{ storage_account }}"
register: output
- assert:
that:
- not azure_vm.properties.diagnosticsProfile.bootDiagnostics.enabled
- name: Re-enable boot diagnostics on an existing VM where it was previously configured
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name1 }}"
boot_diagnostics:
enabled: true
register: output
- assert:
that:
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.enabled
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.storageUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.consoleScreenshotBlobUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.serialConsoleLogBlobUri is defined
# - add_host: # - add_host:
# name: new_azure_vm # name: new_azure_vm
@ -244,8 +262,7 @@
- assert: - assert:
that: azure_publicipaddresses | length == 0 that: azure_publicipaddresses | length == 0
- name: Create virtual machine without public ip address - name: Create virtual machine without public ip address and with boot diagnostics enabled
register: output
azure_rm_virtualmachine: azure_rm_virtualmachine:
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
name: testvmnoip name: testvmnoip
@ -256,14 +273,21 @@
os_type: Linux os_type: Linux
public_ip_allocation_method: Disabled public_ip_allocation_method: Disabled
availability_set: "{{ abs_name1 }}" availability_set: "{{ abs_name1 }}"
boot_diagnostics:
enabled: true
image: image:
offer: UbuntuServer offer: UbuntuServer
publisher: Canonical publisher: Canonical
sku: 16.04-LTS sku: 16.04-LTS
version: latest version: latest
register: output
- assert: - assert:
that: that:
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.enabled
- azure_vm.properties.diagnosticsProfile.bootDiagnostics.storageUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.consoleScreenshotBlobUri is defined
- azure_vm.properties.instanceView.bootDiagnostics.serialConsoleLogBlobUri is defined
- not 'publicIPAddress' in output.ansible_facts.azure_vm.properties.networkProfile.networkInterfaces[0].properties.ipConfigurations[0].properties - not 'publicIPAddress' in output.ansible_facts.azure_vm.properties.networkProfile.networkInterfaces[0].properties.ipConfigurations[0].properties
- name: Delete VM with no public ip - name: Delete VM with no public ip
@ -271,6 +295,7 @@
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
name: testvmnoip name: testvmnoip
state: absent state: absent
remove_on_absent: all_autocreated
vm_size: Standard_A0 vm_size: Standard_A0
async: 5000 async: 5000
poll: 0 poll: 0
@ -280,7 +305,7 @@
- name: testnic011 - name: testnic011
resource_group: "{{ resource_group_secondary }}" resource_group: "{{ resource_group_secondary }}"
- name: testnic012 - name: testnic012
resource_group: "{{ resource_group_secondary }}" resource_group: "{{ resource_group_secondary }}"
- name: Create an availability set - name: Create an availability set
azure_rm_availabilityset: azure_rm_availabilityset:
@ -307,11 +332,10 @@
name: "{{ item.name }}" name: "{{ item.name }}"
virtual_network: "{{ vn.state.id }}" virtual_network: "{{ vn.state.id }}"
subnet: "{{ vm_name2 }}" subnet: "{{ vm_name2 }}"
security_group: "{{ vm_name1 }}" security_group: "{{ vm_name2 }}"
loop: "{{ niclist }}" loop: "{{ niclist }}"
- name: Create virtual machine with two NICs - name: Create virtual machine with two NICs
register: output
azure_rm_virtualmachine: azure_rm_virtualmachine:
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
name: "{{ vm_name2 }}" name: "{{ vm_name2 }}"
@ -334,6 +358,8 @@
version: latest version: latest
tags: tags:
abc: def abc: def
register: output
- assert: - assert:
that: that:
- azure_vm.properties.availabilitySet.id - azure_vm.properties.availabilitySet.id
@ -350,7 +376,7 @@
that: that:
- results.vms | length == 1 - results.vms | length == 1
- results.vms[0].name == "{{ vm_name2 }}" - results.vms[0].name == "{{ vm_name2 }}"
- results.vms[0].location == 'eastus' - results.vms[0].location
- results.vms[0].admin_username == 'adminuser' - results.vms[0].admin_username == 'adminuser'
- results.vms[0].resource_group == "{{ resource_group }}" - results.vms[0].resource_group == "{{ resource_group }}"
- results.vms[0].power_state != None - results.vms[0].power_state != None
@ -548,6 +574,7 @@
- name: Assert that autocreated resources were deleted - name: Assert that autocreated resources were deleted
assert: assert:
that: that:
# what about the default storage group?
- output_nic.ansible_facts.azure_networkinterfaces | length == 0 - output_nic.ansible_facts.azure_networkinterfaces | length == 0
- output_nsg.ansible_facts.azure_securitygroups | length == 0 - output_nsg.ansible_facts.azure_securitygroups | length == 0
- output_pip.ansible_facts.azure_publicipaddresses | length == 0 - output_pip.ansible_facts.azure_publicipaddresses | length == 0

Loading…
Cancel
Save