Vmss scale in policy (#66512)
* azure_rm_virtualmachinescaleset: add scale_in_policy and terminate_event_notification * azure_rm_virtualmachinescalesetinstance: add vmss instance protection policy support
This commit is contained in:
parent
e459eac565
commit
bc37ea96d5
8 changed files with 161 additions and 34 deletions
|
@ -936,7 +936,7 @@ class AzureRMModuleBase(object):
|
|||
if not self._network_client:
|
||||
self._network_client = self.get_mgmt_svc_client(NetworkManagementClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager,
|
||||
api_version='2018-08-01')
|
||||
api_version='2019-06-01')
|
||||
return self._network_client
|
||||
|
||||
@property
|
||||
|
@ -964,13 +964,13 @@ class AzureRMModuleBase(object):
|
|||
if not self._compute_client:
|
||||
self._compute_client = self.get_mgmt_svc_client(ComputeManagementClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager,
|
||||
api_version='2018-06-01')
|
||||
api_version='2019-07-01')
|
||||
return self._compute_client
|
||||
|
||||
@property
|
||||
def compute_models(self):
|
||||
self.log("Getting compute models")
|
||||
return ComputeManagementClient.models("2018-06-01")
|
||||
return ComputeManagementClient.models("2019-07-01")
|
||||
|
||||
@property
|
||||
def dns_client(self):
|
||||
|
|
|
@ -241,6 +241,19 @@ options:
|
|||
U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init#cloud-init-overview),
|
||||
follow these steps U(https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cloudinit-prepare-custom-image).
|
||||
version_added: "2.8"
|
||||
scale_in_policy:
|
||||
description:
|
||||
- define the order in which vmss instances are scaled-in
|
||||
choices:
|
||||
- Default
|
||||
- NewestVM
|
||||
- OldestVM
|
||||
version_added: "2.10"
|
||||
terminate_event_timeout_minutes:
|
||||
description:
|
||||
- timeout time for termination notification event
|
||||
- in range between 5 and 15
|
||||
version_added: "2.10"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- azure
|
||||
|
@ -261,6 +274,8 @@ EXAMPLES = '''
|
|||
virtual_network_name: testvnet
|
||||
upgrade_policy: Manual
|
||||
subnet_name: testsubnet
|
||||
terminate_event_timeout_minutes: 10
|
||||
scale_in_policy: NewestVM
|
||||
admin_username: adminUser
|
||||
ssh_password_enabled: false
|
||||
ssh_public_keys:
|
||||
|
@ -364,6 +379,11 @@ azure_vmss:
|
|||
sample: {
|
||||
"properties": {
|
||||
"overprovision": true,
|
||||
"scaleInPolicy": {
|
||||
"rules": [
|
||||
"NewestVM"
|
||||
]
|
||||
},
|
||||
"singlePlacementGroup": true,
|
||||
"upgradePolicy": {
|
||||
"mode": "Manual"
|
||||
|
@ -410,6 +430,12 @@ azure_vmss:
|
|||
},
|
||||
"secrets": []
|
||||
},
|
||||
"scheduledEventsProfile": {
|
||||
"terminateNotificationProfile": {
|
||||
"enable": true,
|
||||
"notBeforeTimeout": "PT10M"
|
||||
}
|
||||
},
|
||||
"storageProfile": {
|
||||
"dataDisks": [
|
||||
{
|
||||
|
@ -448,8 +474,6 @@ azure_vmss:
|
|||
}
|
||||
''' # NOQA
|
||||
|
||||
import random
|
||||
import re
|
||||
import base64
|
||||
|
||||
try:
|
||||
|
@ -508,6 +532,8 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
plan=dict(type='dict', options=dict(publisher=dict(type='str', required=True),
|
||||
product=dict(type='str', required=True), name=dict(type='str', required=True),
|
||||
promotion_code=dict(type='str'))),
|
||||
scale_in_policy=dict(type='str', choices=['Default', 'OldestVM', 'NewestVM']),
|
||||
terminate_event_timeout_minutes=dict(type='int')
|
||||
)
|
||||
|
||||
self.resource_group = None
|
||||
|
@ -542,11 +568,8 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
self.zones = None
|
||||
self.custom_data = None
|
||||
self.plan = None
|
||||
|
||||
required_if = [
|
||||
('state', 'present', [
|
||||
'vm_size'])
|
||||
]
|
||||
self.scale_in_policy = None
|
||||
self.terminate_event_timeout_minutes = None
|
||||
|
||||
mutually_exclusive = [('load_balancer', 'application_gateway')]
|
||||
self.results = dict(
|
||||
|
@ -558,13 +581,10 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
super(AzureRMVirtualMachineScaleSet, self).__init__(
|
||||
derived_arg_spec=self.module_arg_spec,
|
||||
supports_check_mode=True,
|
||||
required_if=required_if,
|
||||
mutually_exclusive=mutually_exclusive)
|
||||
|
||||
def exec_module(self, **kwargs):
|
||||
|
||||
nsg = None
|
||||
|
||||
for key in list(self.module_arg_spec.keys()) + ['tags']:
|
||||
setattr(self, key, kwargs[key])
|
||||
|
||||
|
@ -585,11 +605,8 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
results = dict()
|
||||
vmss = None
|
||||
disable_ssh_password = None
|
||||
vmss_dict = None
|
||||
virtual_network = None
|
||||
subnet = None
|
||||
image_reference = None
|
||||
custom_image = False
|
||||
load_balancer_backend_address_pools = None
|
||||
load_balancer_inbound_nat_pools = None
|
||||
load_balancer = None
|
||||
|
@ -737,6 +754,27 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
changed = True
|
||||
vmss_dict['zones'] = self.zones
|
||||
|
||||
if self.terminate_event_timeout_minutes:
|
||||
timeout = self.terminate_event_timeout_minutes
|
||||
if timeout < 5 or timeout > 15:
|
||||
self.fail("terminate_event_timeout_minutes should >= 5 and <= 15")
|
||||
iso_8601_format = "PT" + str(timeout) + "M"
|
||||
old = vmss_dict['properties']['virtualMachineProfile'].get('scheduledEventsProfile', {}).\
|
||||
get('terminateNotificationProfile', {}).get('notBeforeTimeout', "")
|
||||
if old != iso_8601_format:
|
||||
differences.append('terminateNotification')
|
||||
changed = True
|
||||
vmss_dict['properties']['virtualMachineProfile'].setdefault('scheduledEventsProfile', {})['terminateNotificationProfile'] = {
|
||||
'notBeforeTimeout': iso_8601_format,
|
||||
"enable": 'true'
|
||||
}
|
||||
|
||||
if self.scale_in_policy and self.scale_in_policy != vmss_dict['properties'].get('scaleInPolicy', {}).get('rules', [""])[0]:
|
||||
self.log("CHANGED: virtual machine sale sets {0} scale in policy".format(self.name))
|
||||
differences.append('scaleInPolicy')
|
||||
changed = True
|
||||
vmss_dict['properties'].setdefault('scaleInPolicy', {})['rules'] = [self.scale_in_policy]
|
||||
|
||||
nicConfigs = vmss_dict['properties']['virtualMachineProfile']['networkProfile']['networkInterfaceConfigurations']
|
||||
|
||||
backend_address_pool = nicConfigs[0]['properties']['ipConfigurations'][0]['properties'].get('loadBalancerBackendAddressPools', [])
|
||||
|
@ -752,7 +790,7 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
lb_or_ag_id = "{0}/".format(application_gateway.id)
|
||||
|
||||
backend_address_pool_id = backend_address_pool[0].get('id')
|
||||
if bool(lb_or_ag_id) != bool(backend_address_pool_id) or not backend_address_pool_id.startswith(lb_or_ag_id):
|
||||
if lb_or_ag_id is not None and (bool(lb_or_ag_id) != bool(backend_address_pool_id) or not backend_address_pool_id.startswith(lb_or_ag_id)):
|
||||
differences.append('load_balancer')
|
||||
changed = True
|
||||
|
||||
|
@ -785,6 +823,9 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
if self.state == 'present':
|
||||
if not vmss:
|
||||
# Create the VMSS
|
||||
if self.vm_size is None:
|
||||
self.fail("vm size must be set")
|
||||
|
||||
self.log("Create virtual machine scale set {0}".format(self.name))
|
||||
self.results['actions'].append('Created VMSS {0}'.format(self.name))
|
||||
|
||||
|
@ -793,9 +834,7 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
self.fail("Parameter error: ssh_public_keys required when disabling SSH password.")
|
||||
|
||||
if not self.virtual_network_name:
|
||||
default_vnet = self.create_default_vnet()
|
||||
virtual_network = default_vnet.id
|
||||
self.virtual_network_name = default_vnet.name
|
||||
self.fail("virtual network name is required")
|
||||
|
||||
if self.subnet_name:
|
||||
subnet = self.get_subnet(self.virtual_network_name, self.subnet_name)
|
||||
|
@ -877,6 +916,12 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
zones=self.zones
|
||||
)
|
||||
|
||||
if self.scale_in_policy:
|
||||
vmss_resource.scale_in_policy = self.gen_scale_in_policy()
|
||||
|
||||
if self.terminate_event_timeout_minutes:
|
||||
vmss_resource.virtual_machine_profile.scheduled_events_profile = self.gen_scheduled_event_profile()
|
||||
|
||||
if self.admin_password:
|
||||
vmss_resource.virtual_machine_profile.os_profile.admin_password = self.admin_password
|
||||
|
||||
|
@ -972,6 +1017,12 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
))
|
||||
vmss_resource.virtual_machine_profile.storage_profile.data_disks = data_disks
|
||||
|
||||
if self.scale_in_policy:
|
||||
vmss_resource.scale_in_policy = self.gen_scale_in_policy()
|
||||
|
||||
if self.terminate_event_timeout_minutes:
|
||||
vmss_resource.virtual_machine_profile.scheduled_events_profile = self.gen_scheduled_event_profile()
|
||||
|
||||
if image_reference is not None:
|
||||
vmss_resource.virtual_machine_profile.storage_profile.image_reference = image_reference
|
||||
self.log("Update virtual machine with parameters:")
|
||||
|
@ -1138,6 +1189,23 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase):
|
|||
name = azure_id_to_dict(id).get('name')
|
||||
return dict(id=id, name=name)
|
||||
|
||||
def gen_scheduled_event_profile(self):
|
||||
if self.terminate_event_timeout_minutes is None:
|
||||
return None
|
||||
|
||||
scheduledEventProfile = self.compute_models.ScheduledEventsProfile()
|
||||
terminationProfile = self.compute_models.TerminateNotificationProfile()
|
||||
terminationProfile.not_before_timeout = "PT" + str(self.terminate_event_timeout_minutes) + "M"
|
||||
terminationProfile.enable = True
|
||||
scheduledEventProfile.terminate_notification_profile = terminationProfile
|
||||
return scheduledEventProfile
|
||||
|
||||
def gen_scale_in_policy(self):
|
||||
if self.scale_in_policy is None:
|
||||
return None
|
||||
|
||||
return self.compute_models.ScaleInPolicy(rules=[self.scale_in_policy])
|
||||
|
||||
|
||||
def main():
|
||||
AzureRMVirtualMachineScaleSet()
|
||||
|
|
|
@ -41,11 +41,20 @@ options:
|
|||
power_state:
|
||||
description:
|
||||
- Use this option to change power state of the instance.
|
||||
required: True
|
||||
choices:
|
||||
- 'running'
|
||||
- 'stopped'
|
||||
- 'deallocated'
|
||||
protect_from_scale_in:
|
||||
type: bool
|
||||
description:
|
||||
- turn on/off instance protection from scale in
|
||||
version_added: "2.10"
|
||||
protect_from_scale_set_actions:
|
||||
type: bool
|
||||
description:
|
||||
- tun on/off instance protection from scale set actions
|
||||
version_added: "2.10"
|
||||
state:
|
||||
description:
|
||||
- State of the VMSS instance. Use C(present) to update an instance and C(absent) to delete an instance.
|
||||
|
@ -69,6 +78,13 @@ EXAMPLES = '''
|
|||
vmss_name: myVMSS
|
||||
instance_id: "2"
|
||||
latest_model: yes
|
||||
|
||||
- name: Turn on protect from scale in
|
||||
azure_rm_virtualmachinescalesetinstance:
|
||||
resource_group: myResourceGroup
|
||||
vmss_name: myVMSS
|
||||
instance_id: "2"
|
||||
protect_from_scale_in: true
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
|
@ -119,6 +135,12 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
type='str',
|
||||
choices=['running', 'stopped', 'deallocated']
|
||||
),
|
||||
protect_from_scale_in=dict(
|
||||
type='bool'
|
||||
),
|
||||
protect_from_scale_set_actions=dict(
|
||||
type='bool'
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
|
@ -136,13 +158,16 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
self.latest_model = None
|
||||
self.power_state = None
|
||||
self.state = None
|
||||
self.protect_from_scale_in = None
|
||||
self.protect_from_scale_set_actions = None
|
||||
super(AzureRMVirtualMachineScaleSetInstance, self).__init__(self.module_arg_spec, supports_tags=False)
|
||||
|
||||
def exec_module(self, **kwargs):
|
||||
for key in self.module_arg_spec:
|
||||
setattr(self, key, kwargs[key])
|
||||
self.mgmt_client = self.get_mgmt_svc_client(ComputeManagementClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager)
|
||||
base_url=self._cloud_environment.endpoints.resource_manager,
|
||||
api_version='2019-07-01')
|
||||
|
||||
instances = self.get()
|
||||
|
||||
|
@ -175,6 +200,14 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
if not self.check_mode:
|
||||
self.start(item['instance_id'])
|
||||
self.results['changed'] = True
|
||||
if self.protect_from_scale_in is not None or self.protect_from_scale_set_actions is not None:
|
||||
for item in instances:
|
||||
protection_policy = item['protection_policy']
|
||||
if protection_policy is None or self.protect_from_scale_in != protection_policy['protect_from_scale_in'] or \
|
||||
self.protect_from_scale_set_actions != protection_policy['protect_from_scale_set_actions']:
|
||||
if not self.check_mode:
|
||||
self.update_protection_policy(self.instance_id, self.protect_from_scale_in, self.protect_from_scale_set_actions)
|
||||
self.results['changed'] = True
|
||||
|
||||
self.results['instances'] = [{'id': item['id']} for item in instances]
|
||||
return self.results
|
||||
|
@ -202,8 +235,8 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
instance_ids=[instance_id])
|
||||
self.get_poller_result(poller)
|
||||
except CloudError as exc:
|
||||
self.log("Error applying latest model {0} - {1}".format(self.name, str(exc)))
|
||||
self.fail("Error applying latest model {0} - {1}".format(self.name, str(exc)))
|
||||
self.log("Error applying latest model {0} - {1}".format(self.vmss_name, str(exc)))
|
||||
self.fail("Error applying latest model {0} - {1}".format(self.vmss_name, str(exc)))
|
||||
|
||||
def delete(self, instance_id):
|
||||
try:
|
||||
|
@ -241,6 +274,27 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
self.log('Could not deallocate instance of Virtual Machine Scale Set VM.')
|
||||
self.fail('Could not deallocate instance of Virtual Machine Scale Set VM.')
|
||||
|
||||
def update_protection_policy(self, instance_id, protect_from_scale_in, protect_from_scale_set_actions):
|
||||
try:
|
||||
d = {}
|
||||
if protect_from_scale_in is not None:
|
||||
d['protect_from_scale_in'] = protect_from_scale_in
|
||||
if protect_from_scale_set_actions is not None:
|
||||
d['protect_from_scale_set_actions'] = protect_from_scale_set_actions
|
||||
protection_policy = self.compute_models.VirtualMachineScaleSetVMProtectionPolicy(**d)
|
||||
instance = self.mgmt_client.virtual_machine_scale_set_vms.get(resource_group_name=self.resource_group,
|
||||
vm_scale_set_name=self.vmss_name,
|
||||
instance_id=instance_id)
|
||||
instance.protection_policy = protection_policy
|
||||
poller = self.mgmt_client.virtual_machine_scale_set_vms.update(resource_group_name=self.resource_group,
|
||||
vm_scale_set_name=self.vmss_name,
|
||||
instance_id=instance_id,
|
||||
parameters=instance)
|
||||
self.get_poller_result(poller)
|
||||
except CloudError as e:
|
||||
self.log('Could not update instance protection policy.')
|
||||
self.fail('Could not update instance protection policy.')
|
||||
|
||||
def format_response(self, item):
|
||||
d = item.as_dict()
|
||||
iv = self.mgmt_client.virtual_machine_scale_set_vms.get_instance_view(resource_group_name=self.resource_group,
|
||||
|
@ -257,7 +311,8 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase):
|
|||
'tags': d.get('tags'),
|
||||
'instance_id': d.get('instance_id'),
|
||||
'latest_model': d.get('latest_model_applied'),
|
||||
'power_state': power_state
|
||||
'power_state': power_state,
|
||||
'protection_policy': d.get('protection_policy')
|
||||
}
|
||||
return d
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ azure-common==1.1.11
|
|||
azure-mgmt-authorization==0.51.1
|
||||
azure-mgmt-batch==5.0.1
|
||||
azure-mgmt-cdn==3.0.0
|
||||
azure-mgmt-compute==4.4.0
|
||||
azure-mgmt-compute==10.0.0
|
||||
azure-mgmt-containerinstance==1.4.0
|
||||
azure-mgmt-containerregistry==2.0.0
|
||||
azure-mgmt-containerservice==4.4.0
|
||||
|
@ -15,7 +15,7 @@ azure-mgmt-dns==2.1.0
|
|||
azure-mgmt-keyvault==1.1.0
|
||||
azure-mgmt-marketplaceordering==0.1.0
|
||||
azure-mgmt-monitor==0.5.2
|
||||
azure-mgmt-network==2.3.0
|
||||
azure-mgmt-network==4.0.0
|
||||
azure-mgmt-nspkg==2.0.0
|
||||
azure-mgmt-redis==5.0.0
|
||||
azure-mgmt-resource==2.1.0
|
||||
|
@ -27,8 +27,8 @@ azure-mgmt-trafficmanager==0.50.0
|
|||
azure-mgmt-web==0.41.0
|
||||
azure-nspkg==2.0.0
|
||||
azure-storage==0.35.1
|
||||
msrest==0.6.1
|
||||
msrestazure==0.5.0
|
||||
msrest==0.6.10
|
||||
msrestazure==0.6.2
|
||||
azure-keyvault==1.0.0a1
|
||||
azure-graphrbac==0.40.0
|
||||
azure-mgmt-cosmosdb==0.5.2
|
||||
|
|
|
@ -161,6 +161,9 @@ matrix:
|
|||
- env: T=azure/2.7/10
|
||||
- env: T=azure/3.6/10
|
||||
|
||||
- env: T=azure/2.7/11
|
||||
- env: T=azure/3.6/11
|
||||
|
||||
- env: T=vcenter/2.7/1
|
||||
- env: T=vcenter/3.6/1
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cloud/azure
|
||||
destructive
|
||||
shippable/azure/group8
|
||||
shippable/azure/group11
|
||||
azure_rm_postgresqlserver_facts
|
||||
azure_rm_postgresqldatabase
|
||||
azure_rm_postgresqldatabase_facts
|
||||
|
|
|
@ -163,6 +163,7 @@
|
|||
disk_size_gb: 64
|
||||
caching: ReadWrite
|
||||
managed_disk_type: Standard_LRS
|
||||
scale_in_policy: "NewestVM"
|
||||
register: results
|
||||
|
||||
- name: Assert that VMSS was created
|
||||
|
|
|
@ -7,7 +7,7 @@ azure-common==1.1.11
|
|||
azure-mgmt-authorization==0.51.1
|
||||
azure-mgmt-batch==5.0.1
|
||||
azure-mgmt-cdn==3.0.0
|
||||
azure-mgmt-compute==4.4.0
|
||||
azure-mgmt-compute==10.0.0
|
||||
azure-mgmt-containerinstance==1.4.0
|
||||
azure-mgmt-containerregistry==2.0.0
|
||||
azure-mgmt-containerservice==4.4.0
|
||||
|
@ -15,7 +15,7 @@ azure-mgmt-dns==2.1.0
|
|||
azure-mgmt-keyvault==1.1.0
|
||||
azure-mgmt-marketplaceordering==0.1.0
|
||||
azure-mgmt-monitor==0.5.2
|
||||
azure-mgmt-network==2.3.0
|
||||
azure-mgmt-network==4.0.0
|
||||
azure-mgmt-nspkg==2.0.0
|
||||
azure-mgmt-redis==5.0.0
|
||||
azure-mgmt-resource==2.1.0
|
||||
|
@ -27,8 +27,8 @@ azure-mgmt-trafficmanager==0.50.0
|
|||
azure-mgmt-web==0.41.0
|
||||
azure-nspkg==2.0.0
|
||||
azure-storage==0.35.1
|
||||
msrest==0.6.1
|
||||
msrestazure==0.5.0
|
||||
msrest==0.6.10
|
||||
msrestazure==0.6.2
|
||||
azure-keyvault==1.0.0a1
|
||||
azure-graphrbac==0.40.0
|
||||
azure-mgmt-cosmosdb==0.5.2
|
||||
|
|
Loading…
Reference in a new issue