Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for generalizing VMs #49704

Merged
merged 9 commits into from Dec 10, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 31 additions & 1 deletion lib/ansible/modules/cloud/azure/azure_rm_virtualmachine.py
Expand Up @@ -68,6 +68,12 @@
- Toggle that controls if the machine is allocated/deallocated, only useful with state='present'.
default: True
type: bool
generalized:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why 'd'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it follows other options, which are "started", "stopped".... etc....

description:
- Use with state 'present' to generalize the machine. Set to true to generalize the machine.
- Please note that this operation is irreversible.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we need stronger message to user, that once generalized, the vm is not usable.

type: bool
version_added: "2.8"
restarted:
description:
- Use with state 'present' to restart a running VM.
Expand Down Expand Up @@ -496,7 +502,7 @@

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
Expand Down Expand Up @@ -666,6 +672,7 @@
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
Expand Down Expand Up @@ -727,6 +734,7 @@ def __init__(self):
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)
Expand Down Expand Up @@ -765,6 +773,7 @@ def __init__(self):
self.allocated = None
self.restarted = None
self.started = None
self.generalized = None
self.differences = None
self.data_disks = None
self.plan = None
Expand Down Expand Up @@ -954,6 +963,10 @@ def exec_module(self, **kwargs):
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

Expand Down Expand Up @@ -1298,6 +1311,9 @@ def exec_module(self, **kwargs):

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())

Expand Down Expand Up @@ -1343,6 +1359,9 @@ def serialize_vm(self, vm):
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 == "OSState/generalized":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lower case to avoid case sensitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, won't hurt

result['powerstate'] = 'generalized'

# Expand network interfaces to include config properties
for interface in vm.network_profile.network_interfaces:
Expand Down Expand Up @@ -1414,6 +1433,17 @@ def deallocate_vm(self):
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 = []
Expand Down
20 changes: 14 additions & 6 deletions lib/ansible/modules/cloud/azure/azure_rm_virtualmachine_facts.py
Expand Up @@ -305,6 +305,9 @@ def serialize_vm(self, vm):
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
Expand All @@ -317,12 +320,17 @@ def serialize_vm(self, vm):
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:
Expand Down
Expand Up @@ -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 }}"
Expand Down