Azure Virtual Machine Scale Set support (azure_rm_virtualmachine_scaleset) (#28381)

* initial virtual machine scaleset implementation

* added docs

* fixed formatting

* added update feature for os disk caching and capacity

* add tier

* added return

* add integration tests

* add vmss facts

* add data disk support

* added data disks docs

* update integration test
This commit is contained in:
Sertaç Özercan 2017-08-29 14:14:15 -07:00 committed by Matt Davis
parent 75998d3ca3
commit 2ea017a794
5 changed files with 1091 additions and 0 deletions

View file

@ -0,0 +1,760 @@
#!/usr/bin/python
#
# Copyright (c) 2016 Sertac Ozercan, <seozerca@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_virtualmachine_scaleset
version_added: "2.4"
short_description: Manage Azure virtual machine scale sets.
description:
- Create and update a virtual machine scale set.
options:
resource_group:
description:
- Name of the resource group containing the virtual machine scale set.
required: true
name:
description:
- Name of the virtual machine.
required: true
state:
description:
- Assert the state of the virtual machine scale set.
- State 'present' will check that the machine exists with the requested configuration. If the configuration
of the existing machine does not match, the machine will be updated.
state.
- State 'absent' will remove the virtual machine scale set.
default: present
choices:
- absent
- present
location:
description:
- Valid Azure location. Defaults to location of the resource group.
vm_size:
description:
- A valid Azure VM size value. For example, 'Standard_D4'. The list of choices varies depending on the
subscription and location. Check your subscription for available choices.
required: true
capacity:
description:
- Capacity of VMSS
required: true
tier:
description:
- SKU Tier
choices:
- Basic
- Standard
upgrade_policy:
description:
- Upgrade policy
choices:
- Manual
- Automatic
admin_username:
description:
- Admin username used to access the host after it is created. Required when creating a VM.
admin_password:
description:
- Password for the admin username. Not required if the os_type is Linux and SSH password authentication
is disabled by setting ssh_password_enabled to false.
ssh_password_enabled:
description:
- When the os_type is Linux, setting ssh_password_enabled to false will disable SSH password authentication
and require use of SSH keys.
default: true
ssh_public_keys:
description:
- "For os_type Linux provide a list of SSH keys. Each item in the list should be a dictionary where the
dictionary contains two keys: path and key_data. Set the path to the default location of the
authorized_keys files. On an Enterprise Linux host, for example, the path will be
/home/<admin username>/.ssh/authorized_keys. Set key_data to the actual value of the public key."
image:
description:
- "A dictionary describing the Marketplace image used to build the VM. Will contain keys: publisher,
offer, sku and version. NOTE: set image.version to 'latest' to get the most recent version of a given
image."
required: true
os_disk_caching:
description:
- Type of OS disk caching.
choices:
- ReadOnly
- ReadWrite
default: ReadOnly
aliases:
- disk_caching
os_type:
description:
- Base type of operating system.
choices:
- Windows
- Linux
default:
- Linux
managed_disk_type:
description:
- Managed disk type
choices:
- Standard_LRS
- Premium_LRS
data_disks:
description:
- Describes list of data disks.
required: false
default: null
version_added: "2.4"
suboptions:
lun:
description:
- The logical unit number for data disk
default: 0
version_added: "2.4"
disk_size_gb:
description:
- The initial disk size in GB for blank data disks
version_added: "2.4"
managed_disk_type:
description:
- Managed data disk type
choices:
- Standard_LRS
- Premium_LRS
version_added: "2.4"
caching:
description:
- Type of data disk caching.
choices:
- ReadOnly
- ReadWrite
default: ReadOnly
version_added: "2.4"
virtual_network_name:
description:
- Virtual Network name
aliases:
- virtual_network
subnet_name:
description:
- Subnet name
aliases:
- subnet
remove_on_absent:
description:
- When removing a VM using state 'absent', also remove associated resources
- "It can be 'all' or a list with any of the following: ['network_interfaces', 'virtual_storage', 'public_ips']"
- Any other input will be ignored
default: ['all']
extends_documentation_fragment:
- azure
- azure_tags
author:
- "Sertac Ozercan (@sozercan)"
'''
EXAMPLES = '''
- name: Create VMSS
azure_rm_virtualmachine_scaleset:
resource_group: Testing
name: testvmss
vm_size: Standard_DS1_v2
capacity: 2
virtual_network_name: testvnet
subnet_name: testsubnet
admin_username: adminUser
ssh_password_enabled: false
ssh_public_keys:
- path: /home/adminUser/.ssh/authorized_keys
key_data: < insert yor ssh public key here... >
managed_disk_type: Standard_LRS
image:
offer: CoreOS
publisher: CoreOS
sku: Stable
version: latest
data_disks:
- lun: 0
disk_size_gb: 64
caching: ReadWrite
managed_disk_type: Standard_LRS
'''
RETURN = '''
azure_vmss:
description: Facts about the current state of the object. Note that facts are not part of the registered output but available directly.
returned: always
type: complex
contains: {
"properties": {
"overprovision": true,
"singlePlacementGroup": true,
"upgradePolicy": {
"mode": "Manual"
},
"virtualMachineProfile": {
"networkProfile": {
"networkInterfaceConfigurations": [
{
"name": "testvmss",
"properties": {
"dnsSettings": {
"dnsServers": []
},
"enableAcceleratedNetworking": false,
"ipConfigurations": [
{
"name": "default",
"properties": {
"privateIPAddressVersion": "IPv4",
"subnet": {
"id": "/subscriptions/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/Testing/providers/Microsoft.Network/virtualNetworks/testvnet/subnets/testsubnet"
}
}
}
],
"primary": true
}
}
]
},
"osProfile": {
"adminUsername": "testuser",
"computerNamePrefix": "testvmss",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
"keyData": "",
"path": "/home/testuser/.ssh/authorized_keys"
}
]
}
},
"secrets": []
},
"storageProfile": {
"dataDisks": [
{
"caching": "ReadWrite",
"createOption": "empty",
"diskSizeGB": 64,
"lun": 0,
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
}
],
"imageReference": {
"offer": "CoreOS",
"publisher": "CoreOS",
"sku": "Stable",
"version": "899.17.0"
},
"osDisk": {
"caching": "ReadWrite",
"createOption": "fromImage",
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
}
}
}
},
"sku": {
"capacity": 2,
"name": "Standard_DS1_v2",
"tier": "Standard"
},
"tags": null,
"type": "Microsoft.Compute/virtualMachineScaleSets"
}
''' # NOQA
import random
import re
try:
from msrestazure.azure_exceptions import CloudError
from azure.mgmt.compute.models import VirtualMachineScaleSet, \
VirtualMachineScaleSetStorageProfile, \
VirtualMachineScaleSetOSProfile, \
VirtualMachineScaleSetOSDisk, VirtualMachineScaleSetDataDisk, \
VirtualMachineScaleSetManagedDiskParameters, \
VirtualMachineScaleSetNetworkProfile, LinuxConfiguration, \
SshConfiguration, SshPublicKey, VirtualMachineSizeTypes, \
DiskCreateOptionTypes, CachingTypes, \
VirtualMachineScaleSetVMProfile, VirtualMachineScaleSetIdentity, \
VirtualMachineScaleSetIPConfiguration, \
VirtualMachineScaleSetPublicIPAddressConfigurationDnsSettings, \
VirtualMachineScaleSetPublicIPAddressConfiguration, Sku, \
UpgradePolicy, VirtualMachineScaleSetNetworkConfiguration, \
ApiEntityReference, ImageReference
from azure.mgmt.network.models import PublicIPAddress, \
NetworkSecurityGroup, NetworkInterface, \
NetworkInterfaceIPConfiguration, Subnet, VirtualNetwork
except ImportError:
# This is handled in azure_rm_common
pass
from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict
AZURE_OBJECT_CLASS = 'VirtualMachineScaleSet'
AZURE_ENUM_MODULES = ['azure.mgmt.compute.models']
class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(type='str', required=True),
name=dict(type='str', required=True),
state=dict(choices=['present', 'absent'], default='present', type='str'),
location=dict(type='str'),
short_hostname=dict(type='str'),
vm_size=dict(type='str', required=True),
tier=dict(type='str', choices=['Basic', 'Standard']),
capacity=dict(type='int', default=1),
upgrade_policy=dict(type='str', choices=['Automatic', 'Manual']),
admin_username=dict(type='str'),
admin_password=dict(type='str', no_log=True),
ssh_password_enabled=dict(type='bool', default=True),
ssh_public_keys=dict(type='list'),
image=dict(type='dict'),
os_disk_caching=dict(type='str', aliases=['disk_caching'], choices=['ReadOnly', 'ReadWrite'],
default='ReadOnly'),
os_type=dict(type='str', choices=['Linux', 'Windows'], default='Linux'),
managed_disk_type=dict(type='str', choices=['Standard_LRS', 'Premium_LRS']),
data_disks=dict(type='list'),
subnet_name=dict(type='str', aliases=['subnet']),
virtual_network_name=dict(type='str', aliases=['virtual_network']),
remove_on_absent=dict(type='list', default=['all']),
)
self.resource_group = None
self.name = None
self.state = None
self.location = None
self.short_hostname = None
self.vm_size = None
self.capacity = None
self.tier = None
self.upgrade_policy = None
self.admin_username = None
self.admin_password = None
self.ssh_password_enabled = None
self.ssh_public_keys = None
self.image = None
self.os_disk_caching = None
self.managed_disk_type = None
self.data_disks = None
self.os_type = None
self.subnet_name = None
self.virtual_network_name = None
self.tags = None
self.differences = None
self.results = dict(
changed=False,
actions=[],
ansible_facts=dict(azure_vmss=None)
)
super(AzureRMVirtualMachineScaleSet, self).__init__(
derived_arg_spec=self.module_arg_spec,
supports_check_mode=True
)
def exec_module(self, **kwargs):
for key in list(self.module_arg_spec.keys()) + ['tags']:
setattr(self, key, kwargs[key])
# make sure options are lower case
self.remove_on_absent = set([resource.lower() for resource in self.remove_on_absent])
changed = False
results = dict()
vmss = None
disable_ssh_password = None
vmss_dict = None
virtual_network = None
subnet = None
resource_group = self.get_resource_group(self.resource_group)
if not self.location:
# Set default location
self.location = resource_group.location
if self.state == 'present':
# Verify parameters and resolve any defaults
if self.vm_size and not self.vm_size_is_valid():
self.fail("Parameter error: vm_size {0} is not valid for your subscription and location.".format(
self.vm_size
))
# if self.virtual_network_name:
# virtual_network = self.get_virtual_network(self.virtual_network_name)
if self.ssh_public_keys:
msg = "Parameter error: expecting ssh_public_keys to be a list of type dict where " \
"each dict contains keys: path, key_data."
for key in self.ssh_public_keys:
if not isinstance(key, dict):
self.fail(msg)
if not key.get('path') or not key.get('key_data'):
self.fail(msg)
if self.image:
if not self.image.get('publisher') or not self.image.get('offer') or not self.image.get('sku') \
or not self.image.get('version'):
self.error("parameter error: expecting image to contain publisher, offer, sku and version keys.")
image_version = self.get_image_version()
if self.image['version'] == 'latest':
self.image['version'] = image_version.name
self.log("Using image version {0}".format(self.image['version']))
disable_ssh_password = not self.ssh_password_enabled
try:
self.log("Fetching virtual machine scale set {0}".format(self.name))
vmss = self.compute_client.virtual_machine_scale_sets.get(self.resource_group, self.name)
self.check_provisioning_state(vmss, self.state)
vmss_dict = self.serialize_vmss(vmss)
if self.state == 'present':
differences = []
results = vmss_dict
if self.os_disk_caching and \
self.os_disk_caching != vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk']['caching']:
self.log('CHANGED: virtual machine scale set {0} - OS disk caching'.format(self.name))
differences.append('OS Disk caching')
changed = True
vmss_dict['properties']['virtualMachineProfile']['storageProfile']['osDisk']['caching'] = self.os_disk_caching
if self.capacity and \
self.capacity != vmss_dict['sku']['capacity']:
self.log('CHANGED: virtual machine scale set {0} - Capacity'.format(self.name))
differences.append('Capacity')
changed = True
vmss_dict['sku']['capacity'] = self.capacity
if self.data_disks and \
len(self.data_disks) != len(vmss_dict['properties']['virtualMachineProfile']['storageProfile']['dataDisks']):
self.log('CHANGED: virtual machine scale set {0} - Data Disks'.format(self.name))
differences.append('Data Disks')
changed = True
update_tags, vmss_dict['tags'] = self.update_tags(vmss_dict.get('tags', dict()))
if update_tags:
differences.append('Tags')
changed = True
self.differences = differences
elif self.state == 'absent':
self.log("CHANGED: virtual machine scale set {0} exists and requested state is 'absent'".format(self.name))
results = dict()
changed = True
except CloudError:
self.log('Virtual machine scale set {0} does not exist'.format(self.name))
if self.state == 'present':
self.log("CHANGED: virtual machine scale set {0} does not exist but state is 'present'.".format(self.name))
changed = True
self.results['changed'] = changed
self.results['ansible_facts']['azure_vmss'] = results
if self.check_mode:
return self.results
if changed:
if self.state == 'present':
if not vmss:
# Create the VMSS
self.log("Create virtual machine scale set {0}".format(self.name))
self.results['actions'].append('Created VMSS {0}'.format(self.name))
# Validate parameters
if not self.admin_username:
self.fail("Parameter error: admin_username required when creating a virtual machine scale set.")
if self.os_type == 'Linux':
if disable_ssh_password and not self.ssh_public_keys:
self.fail("Parameter error: ssh_public_keys required when disabling SSH password.")
if self.subnet_name:
subnet = self.get_subnet(self.virtual_network_name, self.subnet_name)
if not self.virtual_network_name:
default_vnet = self.create_default_vnet()
virtual_network = default_vnet.id
if not self.short_hostname:
self.short_hostname = self.name
managed_disk = VirtualMachineScaleSetManagedDiskParameters(storage_account_type=self.managed_disk_type)
vmss_resource = VirtualMachineScaleSet(
self.location,
tags=self.tags,
upgrade_policy=UpgradePolicy(
mode=self.upgrade_policy
),
sku=Sku(
name=self.vm_size,
capacity=self.capacity,
tier=self.tier,
),
virtual_machine_profile=VirtualMachineScaleSetVMProfile(
os_profile=VirtualMachineScaleSetOSProfile(
admin_username=self.admin_username,
computer_name_prefix=self.short_hostname,
),
storage_profile=VirtualMachineScaleSetStorageProfile(
os_disk=VirtualMachineScaleSetOSDisk(
managed_disk=managed_disk,
create_option=DiskCreateOptionTypes.from_image,
caching=self.os_disk_caching,
),
image_reference=ImageReference(
publisher=self.image['publisher'],
offer=self.image['offer'],
sku=self.image['sku'],
version=self.image['version'],
),
),
network_profile=VirtualMachineScaleSetNetworkProfile(
network_interface_configurations=[
VirtualMachineScaleSetNetworkConfiguration(
name=self.name,
primary=True,
ip_configurations=[
VirtualMachineScaleSetIPConfiguration(
name='default',
subnet=ApiEntityReference(
id=subnet.id
)
)
]
)
]
)
)
)
if self.admin_password:
vmss_resource.virtual_machine_profile.os_profile.admin_password = self.admin_password
if self.os_type == 'Linux':
vmss_resource.virtual_machine_profile.os_profile.linux_configuration = LinuxConfiguration(
disable_password_authentication=disable_ssh_password
)
if self.ssh_public_keys:
ssh_config = SshConfiguration()
ssh_config.public_keys = \
[SshPublicKey(path=key['path'], key_data=key['key_data']) for key in self.ssh_public_keys]
vmss_resource.virtual_machine_profile.os_profile.linux_configuration.ssh = ssh_config
if self.data_disks:
data_disks = []
for data_disk in self.data_disks:
data_disk_managed_disk = VirtualMachineScaleSetManagedDiskParameters(
storage_account_type=data_disk['managed_disk_type']
)
data_disk['caching'] = data_disk.get(
'caching',
CachingTypes.read_only
)
data_disks.append(VirtualMachineScaleSetDataDisk(
lun=data_disk['lun'],
caching=data_disk['caching'],
create_option=DiskCreateOptionTypes.empty,
disk_size_gb=data_disk['disk_size_gb'],
managed_disk=data_disk_managed_disk,
))
vmss_resource.virtual_machine_profile.storage_profile.data_disks = data_disks
self.log("Create virtual machine with parameters:")
self.create_or_update_vmss(vmss_resource)
elif self.differences and len(self.differences) > 0:
self.log("Update virtual machine scale set {0}".format(self.name))
self.results['actions'].append('Updated VMSS {0}'.format(self.name))
vmss_resource = self.get_vmss()
vmss_resource.virtual_machine_profile.storage_profile.os_disk.caching = self.os_disk_caching
vmss_resource.sku.capacity = self.capacity
data_disks = []
for data_disk in self.data_disks:
data_disks.append(VirtualMachineScaleSetDataDisk(
lun=data_disk['lun'],
caching=data_disk['caching'],
create_option=DiskCreateOptionTypes.empty,
disk_size_gb=data_disk['disk_size_gb'],
managed_disk=VirtualMachineScaleSetManagedDiskParameters(
storage_account_type=data_disk['managed_disk_type']
),
))
vmss_resource.virtual_machine_profile.storage_profile.data_disks = data_disks
self.log("Update virtual machine with parameters:")
self.create_or_update_vmss(vmss_resource)
self.results['ansible_facts']['azure_vmss'] = self.serialize_vmss(self.get_vmss())
elif self.state == 'absent':
# delete the VM
self.log("Delete virtual machine scale set {0}".format(self.name))
self.results['ansible_facts']['azure_vmss'] = None
self.delete_vmss(vmss)
# until we sort out how we want to do this globally
del self.results['actions']
return self.results
def get_vmss(self):
'''
Get the VMSS
:return: VirtualMachineScaleSet object
'''
try:
vmss = self.compute_client.virtual_machine_scale_sets.get(self.resource_group, self.name)
return vmss
except Exception as exc:
self.fail("Error getting virtual machine scale set {0} - {1}".format(self.name, str(exc)))
def get_virtual_network(self, name):
try:
vnet = self.network_client.virtual_networks.get(self.resource_group, name)
return vnet
except Exception as exc:
self.fail("Error fetching virtual network {0} - {1}".format(name, str(exc)))
def get_subnet(self, vnet_name, subnet_name):
self.log("Fetching subnet {0} in virtual network {1}".format(subnet_name, vnet_name))
try:
subnet = self.network_client.subnets.get(self.resource_group, vnet_name, subnet_name)
except Exception as exc:
self.fail("Error: fetching subnet {0} in virtual network {1} - {2}".format(
subnet_name,
vnet_name,
str(exc)))
return subnet
def serialize_vmss(self, vmss):
'''
Convert a VirtualMachineScaleSet object to dict.
:param vm: VirtualMachineScaleSet object
:return: dict
'''
result = self.serialize_obj(vmss, AZURE_OBJECT_CLASS, enum_modules=AZURE_ENUM_MODULES)
result['id'] = vmss.id
result['name'] = vmss.name
result['type'] = vmss.type
result['location'] = vmss.location
result['tags'] = vmss.tags
return result
def delete_vmss(self, vmss):
self.log("Deleting virtual machine scale set {0}".format(self.name))
self.results['actions'].append("Deleted virtual machine scale set {0}".format(self.name))
try:
poller = self.compute_client.virtual_machine_scale_sets.delete(self.resource_group, self.name)
# wait for the poller to finish
self.get_poller_result(poller)
except Exception as exc:
self.fail("Error deleting virtual machine scale set {0} - {1}".format(self.name, str(exc)))
return True
def get_image_version(self):
try:
versions = self.compute_client.virtual_machine_images.list(self.location,
self.image['publisher'],
self.image['offer'],
self.image['sku'])
except Exception as exc:
self.fail("Error fetching image {0} {1} {2} - {3}".format(self.image['publisher'],
self.image['offer'],
self.image['sku'],
str(exc)))
if versions and len(versions) > 0:
if self.image['version'] == 'latest':
return versions[len(versions) - 1]
for version in versions:
if version.name == self.image['version']:
return version
self.fail("Error could not find image {0} {1} {2} {3}".format(self.image['publisher'],
self.image['offer'],
self.image['sku'],
self.image['version']))
def create_or_update_vmss(self, params):
try:
poller = self.compute_client.virtual_machine_scale_sets.create_or_update(self.resource_group, self.name, params)
self.get_poller_result(poller)
except Exception as exc:
self.fail("Error creating or updating virtual machine {0} - {1}".format(self.name, str(exc)))
def vm_size_is_valid(self):
'''
Validate self.vm_size against the list of virtual machine sizes available for the account and location.
:return: boolean
'''
try:
sizes = self.compute_client.virtual_machine_sizes.list(self.location)
except Exception as exc:
self.fail("Error retrieving available machine sizes - {0}".format(str(exc)))
for size in sizes:
if size.name == self.vm_size:
return True
return False
def main():
AzureRMVirtualMachineScaleSet()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,238 @@
#!/usr/bin/python
#
# Copyright (c) 2017 Sertac Ozercan, <seozerca@microsoft.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_virtualmachine_scaleset_facts
version_added: "2.4"
short_description: Get Virtual Machine Scale Set facts
description:
- Get facts for a virtual machine scale set
options:
name:
description:
- Limit results to a specific virtual machine scale set
required: false
default: null
resource_group:
description:
- The resource group to search for the desired virtual machine scale set
required: false
default: null
extends_documentation_fragment:
- azure
author:
- "Sertac Ozercan (@sozercan)"
'''
EXAMPLES = '''
- name: Get facts for a virtual machine scale set
azure_rm_virtualmachine_scaleset_facts:
resource_group: Testing
name: testvmss001
- name: Get facts for all virtual networks
azure_rm_virtualmachine_scaleset_facts:
resource_group: Testing
- name: Get facts by tags
azure_rm_virtualmachine_scaleset_facts:
resource_group: Testing
tags:
- testing
'''
RETURN = '''
azure_vmss:
description: List of virtual machine scale sets
returned: always
type: list
example: [{
"location": "eastus",
"properties": {
"overprovision": true,
"singlePlacementGroup": true,
"upgradePolicy": {
"mode": "Manual"
},
"virtualMachineProfile": {
"networkProfile": {
"networkInterfaceConfigurations": [
{
"name": "testvmss",
"properties": {
"dnsSettings": {
"dnsServers": []
},
"enableAcceleratedNetworking": false,
"ipConfigurations": [
{
"name": "default",
"properties": {
"privateIPAddressVersion": "IPv4",
"subnet": {
"id": "/subscriptions/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/Testing/providers/Microsoft.Network/virtualNetworks/testvnet/subnets/testsubnet"
}
}
}
],
"primary": true
}
}
]
},
"osProfile": {
"adminUsername": "testuser",
"computerNamePrefix": "testvmss",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
"keyData": "",
"path": "/home/testuser/.ssh/authorized_keys"
}
]
}
},
"secrets": []
},
"storageProfile": {
"imageReference": {
"offer": "CoreOS",
"publisher": "CoreOS",
"sku": "Stable",
"version": "899.17.0"
},
"osDisk": {
"caching": "ReadWrite",
"createOption": "fromImage",
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
}
}
}
},
"sku": {
"capacity": 1,
"name": "Standard_DS1_v2",
"tier": "Standard"
}
}]
''' # NOQA
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
except:
# handled in azure_rm_common
pass
AZURE_OBJECT_CLASS = 'VirtualMachineScaleSet'
AZURE_ENUM_MODULES = ['azure.mgmt.compute.models']
class AzureRMVirtualMachineScaleSetFacts(AzureRMModuleBase):
"""Utility class to get virtual machine scale set facts"""
def __init__(self):
self.module_args = dict(
name=dict(type='str'),
resource_group=dict(type='str'),
tags=dict(type='list')
)
self.results = dict(
changed=False,
ansible_facts=dict(
azure_vmss=[]
)
)
self.name = None
self.resource_group = None
self.tags = None
super(AzureRMVirtualMachineScaleSetFacts, self).__init__(
derived_arg_spec=self.module_args,
supports_tags=False,
facts_module=True
)
def exec_module(self, **kwargs):
for key in self.module_args:
setattr(self, key, kwargs[key])
if self.name and not self.resource_group:
self.fail("Parameter error: resource group required when filtering by name.")
if self.name:
self.results['ansible_facts']['azure_vmss'] = self.get_item()
else:
self.results['ansible_facts']['azure_vmss'] = self.list_items()
return self.results
def get_item(self):
"""Get a single virtual machine scale set"""
self.log('Get properties for {}'.format(self.name))
item = None
results = []
try:
item = self.compute_client.virtual_machine_scale_sets.get(self.resource_group, self.name)
except CloudError:
pass
if item and self.has_tags(item.tags, self.tags):
results = [self.serialize_obj(item, AZURE_OBJECT_CLASS, enum_modules=AZURE_ENUM_MODULES)]
return results
def list_items(self):
"""Get all virtual machine scale sets"""
self.log('List all virtual machine scale sets')
try:
response = self.compute_client.virtual_machine_scale_sets.list(self.resource_group)
except CloudError as exc:
self.fail('Failed to list all items - {}'.format(str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(self.serialize_obj(item, AZURE_OBJECT_CLASS, enum_modules=AZURE_ENUM_MODULES))
return results
def main():
"""Main module execution code path"""
AzureRMVirtualMachineScaleSetFacts()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,3 @@
cloud/azure
posix/ci/cloud/azure
destructive

View file

@ -0,0 +1,2 @@
dependencies:
- setup_azure

View file

@ -0,0 +1,88 @@
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: testVnet
address_prefixes: "10.0.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
name: testSubnet
address_prefix: "10.0.1.0/24"
virtual_network: testVnet
- name: Create public IP address
azure_rm_publicipaddress:
resource_group: "{{ resource_group }}"
allocation_method: Dynamic
name: testPublicIP
- name: Create VMSS
azure_rm_virtualmachine_scaleset:
resource_group: "{{ resource_group }}"
name: testVMSS
vm_size: Standard_DS1_v2
admin_username: testuser
ssh_password_enabled: true
admin_password: "Password1234!"
capacity: 2
virtual_network_name: testVnet
subnet_name: testSubnet
upgrade_policy: Manual
tier: Standard
managed_disk_type: Standard_LRS
os_disk_caching: ReadWrite
image:
offer: CoreOS
publisher: CoreOS
sku: Stable
version: latest
data_disks:
- lun: 0
disk_size_gb: 64
caching: ReadWrite
managed_disk_type: Standard_LRS
register: results
- name: Assert that VMSS ran
assert:
that: results.changed
- name: Delete VMSS
azure_rm_virtualmachine_scaleset:
resource_group: "{{ resource_group }}"
name: testVMSS
state: absent
remove_on_absent: ['all']
vm_size: Standard_DS1_v2
admin_username: testuser
capacity: 2
virtual_network_name: testVnet
subnet_name: testSubnet
upgrade_policy: Manual
tier: Standard
os_disk_caching: ReadWrite
image:
offer: CoreOS
publisher: CoreOS
sku: Stable
version: latest
data_disks:
- lun: 0
disk_size_gb: 64
caching: ReadWrite
managed_disk_type: Standard_LRS
- name: Delete public IP address
azure_rm_publicipaddress:
resource_group: "{{ resource_group }}"
allocation_method: Dynamic
state: absent
name: testPublicIP
- name: Delete virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: testVnet
state: absent
address_prefixes: "10.0.0.0/16"