Support for generalizing VMs (#49704)

This commit is contained in:
Zim Kalinowski 2018-12-10 16:21:09 +08:00 committed by GitHub
parent aec98b6aab
commit b89eb7a8c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 7 deletions

View file

@ -68,6 +68,12 @@ options:
- Toggle that controls if the machine is allocated/deallocated, only useful with state='present'.
default: True
type: bool
generalized:
description:
- Use with state 'present' to generalize the machine. Set to true to generalize the machine.
- Please note that this operation is irreversible.
type: bool
version_added: "2.8"
restarted:
description:
- Use with state 'present' to restart a running VM.
@ -496,7 +502,7 @@ EXAMPLES = '''
RETURN = '''
powerstate:
description: Indicates if the state is running, stopped, deallocated
description: Indicates if the state is running, stopped, deallocated, generalized
returned: always
type: string
example: running
@ -666,6 +672,7 @@ import re
try:
from msrestazure.azure_exceptions import CloudError
from msrestazure.tools import parse_resource_id
from msrest.polling import LROPoller
except ImportError:
# This is handled in azure_rm_common
pass
@ -727,6 +734,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
allocated=dict(type='bool', default=True),
restarted=dict(type='bool', default=False),
started=dict(type='bool', default=True),
generalized=dict(type='bool', default=False),
data_disks=dict(type='list'),
plan=dict(type='dict'),
accept_terms=dict(type='bool', default=False)
@ -765,6 +773,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.allocated = None
self.restarted = None
self.started = None
self.generalized = None
self.differences = None
self.data_disks = None
self.plan = None
@ -954,6 +963,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.log("CHANGED: virtual machine {0} running and requested state 'stopped'".format(self.name))
changed = True
powerstate_change = 'poweroff'
elif self.generalized and vm_dict['powerstate'] != 'generalized':
self.log("CHANGED: virtual machine {0} requested to be 'generalized'".format(self.name))
changed = True
powerstate_change = 'generalized'
self.differences = differences
@ -1298,6 +1311,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
elif powerstate_change == 'deallocated':
self.deallocate_vm()
elif powerstate_change == 'generalized':
self.power_off_vm()
self.generalize_vm()
self.results['ansible_facts']['azure_vm'] = self.serialize_vm(self.get_vm())
@ -1343,6 +1359,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if vm.instance_view:
result['powerstate'] = next((s.code.replace('PowerState/', '')
for s in vm.instance_view.statuses if s.code.startswith('PowerState')), None)
for s in vm.instance_view.statuses:
if s.code.lower() == "osstate/generalized":
result['powerstate'] = 'generalized'
# Expand network interfaces to include config properties
for interface in vm.network_profile.network_interfaces:
@ -1414,6 +1433,17 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.fail("Error deallocating virtual machine {0} - {1}".format(self.name, str(exc)))
return True
def generalize_vm(self):
self.results['actions'].append("Generalize virtual machine {0}".format(self.name))
self.log("Generalize virtual machine {0}".format(self.name))
try:
response = self.compute_client.virtual_machines.generalize(self.resource_group, self.name)
if isinstance(response, LROPoller):
self.get_poller_result(response)
except Exception as exc:
self.fail("Error generalizing virtual machine {0} - {1}".format(self.name, str(exc)))
return True
def delete_vm(self, vm):
vhd_uris = []
managed_disk_ids = []

View file

@ -305,6 +305,9 @@ class AzureRMVirtualMachineFacts(AzureRMModuleBase):
code = instance['statuses'][index]['code'].split('/')
if code[0] == 'PowerState':
power_state = code[1]
elif code[0] == 'OSState' and code[1] == 'generalized':
power_state = 'generalized'
break
new_result = {}
new_result['power_state'] = power_state
@ -317,12 +320,17 @@ class AzureRMVirtualMachineFacts(AzureRMModuleBase):
new_result['admin_username'] = result['properties']['osProfile']['adminUsername']
image = result['properties']['storageProfile'].get('imageReference')
if image is not None:
new_result['image'] = {
'publisher': image['publisher'],
'sku': image['sku'],
'offer': image['offer'],
'version': image['version']
}
if image.get('publisher', None) is not None:
new_result['image'] = {
'publisher': image['publisher'],
'sku': image['sku'],
'offer': image['offer'],
'version': image['version']
}
else:
new_result['image'] = {
'id': image.get('id', None)
}
vhd = result['properties']['storageProfile']['osDisk'].get('vhd')
if vhd is not None:

View file

@ -382,6 +382,21 @@
- assert:
that: not output.changed
- name: Generalize VM
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name2 }}"
generalized: yes
- name: Gather facts and check if machine is generalized
azure_rm_virtualmachine_facts:
resource_group: "{{ resource_group }}"
name: "{{ vm_name2 }}"
register: generalized_output
- assert:
that: generalized_output.vms[0].power_state == 'generalized'
- name: Delete dual NIC VM
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"