Support for generalizing VMs (#49704)
This commit is contained in:
parent
aec98b6aab
commit
b89eb7a8c9
3 changed files with 60 additions and 7 deletions
|
@ -68,6 +68,12 @@ options:
|
||||||
- Toggle that controls if the machine is allocated/deallocated, only useful with state='present'.
|
- Toggle that controls if the machine is allocated/deallocated, only useful with state='present'.
|
||||||
default: True
|
default: True
|
||||||
type: bool
|
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:
|
restarted:
|
||||||
description:
|
description:
|
||||||
- Use with state 'present' to restart a running VM.
|
- Use with state 'present' to restart a running VM.
|
||||||
|
@ -496,7 +502,7 @@ EXAMPLES = '''
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = '''
|
||||||
powerstate:
|
powerstate:
|
||||||
description: Indicates if the state is running, stopped, deallocated
|
description: Indicates if the state is running, stopped, deallocated, generalized
|
||||||
returned: always
|
returned: always
|
||||||
type: string
|
type: string
|
||||||
example: running
|
example: running
|
||||||
|
@ -666,6 +672,7 @@ import re
|
||||||
try:
|
try:
|
||||||
from msrestazure.azure_exceptions import CloudError
|
from msrestazure.azure_exceptions import CloudError
|
||||||
from msrestazure.tools import parse_resource_id
|
from msrestazure.tools import parse_resource_id
|
||||||
|
from msrest.polling import LROPoller
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# This is handled in azure_rm_common
|
# This is handled in azure_rm_common
|
||||||
pass
|
pass
|
||||||
|
@ -727,6 +734,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
|
||||||
allocated=dict(type='bool', default=True),
|
allocated=dict(type='bool', default=True),
|
||||||
restarted=dict(type='bool', default=False),
|
restarted=dict(type='bool', default=False),
|
||||||
started=dict(type='bool', default=True),
|
started=dict(type='bool', default=True),
|
||||||
|
generalized=dict(type='bool', default=False),
|
||||||
data_disks=dict(type='list'),
|
data_disks=dict(type='list'),
|
||||||
plan=dict(type='dict'),
|
plan=dict(type='dict'),
|
||||||
accept_terms=dict(type='bool', default=False)
|
accept_terms=dict(type='bool', default=False)
|
||||||
|
@ -765,6 +773,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
|
||||||
self.allocated = None
|
self.allocated = None
|
||||||
self.restarted = None
|
self.restarted = None
|
||||||
self.started = None
|
self.started = None
|
||||||
|
self.generalized = None
|
||||||
self.differences = None
|
self.differences = None
|
||||||
self.data_disks = None
|
self.data_disks = None
|
||||||
self.plan = 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))
|
self.log("CHANGED: virtual machine {0} running and requested state 'stopped'".format(self.name))
|
||||||
changed = True
|
changed = True
|
||||||
powerstate_change = 'poweroff'
|
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
|
self.differences = differences
|
||||||
|
|
||||||
|
@ -1298,6 +1311,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
|
||||||
|
|
||||||
elif powerstate_change == 'deallocated':
|
elif powerstate_change == 'deallocated':
|
||||||
self.deallocate_vm()
|
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())
|
self.results['ansible_facts']['azure_vm'] = self.serialize_vm(self.get_vm())
|
||||||
|
|
||||||
|
@ -1343,6 +1359,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
|
||||||
if vm.instance_view:
|
if vm.instance_view:
|
||||||
result['powerstate'] = next((s.code.replace('PowerState/', '')
|
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.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
|
# Expand network interfaces to include config properties
|
||||||
for interface in vm.network_profile.network_interfaces:
|
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)))
|
self.fail("Error deallocating virtual machine {0} - {1}".format(self.name, str(exc)))
|
||||||
return True
|
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):
|
def delete_vm(self, vm):
|
||||||
vhd_uris = []
|
vhd_uris = []
|
||||||
managed_disk_ids = []
|
managed_disk_ids = []
|
||||||
|
|
|
@ -305,6 +305,9 @@ class AzureRMVirtualMachineFacts(AzureRMModuleBase):
|
||||||
code = instance['statuses'][index]['code'].split('/')
|
code = instance['statuses'][index]['code'].split('/')
|
||||||
if code[0] == 'PowerState':
|
if code[0] == 'PowerState':
|
||||||
power_state = code[1]
|
power_state = code[1]
|
||||||
|
elif code[0] == 'OSState' and code[1] == 'generalized':
|
||||||
|
power_state = 'generalized'
|
||||||
|
break
|
||||||
|
|
||||||
new_result = {}
|
new_result = {}
|
||||||
new_result['power_state'] = power_state
|
new_result['power_state'] = power_state
|
||||||
|
@ -317,12 +320,17 @@ class AzureRMVirtualMachineFacts(AzureRMModuleBase):
|
||||||
new_result['admin_username'] = result['properties']['osProfile']['adminUsername']
|
new_result['admin_username'] = result['properties']['osProfile']['adminUsername']
|
||||||
image = result['properties']['storageProfile'].get('imageReference')
|
image = result['properties']['storageProfile'].get('imageReference')
|
||||||
if image is not None:
|
if image is not None:
|
||||||
|
if image.get('publisher', None) is not None:
|
||||||
new_result['image'] = {
|
new_result['image'] = {
|
||||||
'publisher': image['publisher'],
|
'publisher': image['publisher'],
|
||||||
'sku': image['sku'],
|
'sku': image['sku'],
|
||||||
'offer': image['offer'],
|
'offer': image['offer'],
|
||||||
'version': image['version']
|
'version': image['version']
|
||||||
}
|
}
|
||||||
|
else:
|
||||||
|
new_result['image'] = {
|
||||||
|
'id': image.get('id', None)
|
||||||
|
}
|
||||||
|
|
||||||
vhd = result['properties']['storageProfile']['osDisk'].get('vhd')
|
vhd = result['properties']['storageProfile']['osDisk'].get('vhd')
|
||||||
if vhd is not None:
|
if vhd is not None:
|
||||||
|
|
|
@ -382,6 +382,21 @@
|
||||||
- assert:
|
- assert:
|
||||||
that: not output.changed
|
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
|
- name: Delete dual NIC VM
|
||||||
azure_rm_virtualmachine:
|
azure_rm_virtualmachine:
|
||||||
resource_group: "{{ resource_group }}"
|
resource_group: "{{ resource_group }}"
|
||||||
|
|
Loading…
Reference in a new issue