Improve ovirt_vms, ovirt_hosts and ovirt_storage_domains (#35782)
* ovirt_vms: Add graphics consoles * ovirt_hosts: Fix kdump integration check * ovirt_storage_domains: Support multiple targets for block storages * ovirt_vms: add cloud_init_persist parameter * ovirt_vms: Change IO threads to int * ovirt_vms: Fix update check * ovirt_vms: Remove choices of OS, to not enforce it
This commit is contained in:
parent
51c4412de2
commit
7d4a2de66a
3 changed files with 222 additions and 138 deletions
|
@ -268,9 +268,6 @@ class HostsModule(BaseModule):
|
|||
ssh=otypes.Ssh(
|
||||
authentication_method=otypes.SshAuthenticationMethod.PUBLICKEY,
|
||||
) if self.param('public_key') else None,
|
||||
kdump_status=otypes.KdumpStatus(
|
||||
self.param('kdump_integration')
|
||||
) if self.param('kdump_integration') else None,
|
||||
spm=otypes.Spm(
|
||||
priority=self.param('spm_priority'),
|
||||
) if self.param('spm_priority') else None,
|
||||
|
@ -283,14 +280,15 @@ class HostsModule(BaseModule):
|
|||
) if self.param('kernel_params') else None,
|
||||
power_management=otypes.PowerManagement(
|
||||
enabled=self.param('power_management_enabled'),
|
||||
) if self.param('power_management_enabled') is not None else None,
|
||||
kdump_detection=self.param('kdump_integration') == 'enabled',
|
||||
) if self.param('power_management_enabled') is not None or self.param('kdump_integration') else None,
|
||||
)
|
||||
|
||||
def update_check(self, entity):
|
||||
kernel_params = self.param('kernel_params')
|
||||
return (
|
||||
equal(self.param('comment'), entity.comment) and
|
||||
equal(self.param('kdump_integration'), entity.kdump_status) and
|
||||
equal(self.param('kdump_integration'), 'enabled' if entity.power_management.kdump_detection else 'disabled') and
|
||||
equal(self.param('spm_priority'), entity.spm.priority) and
|
||||
equal(self.param('power_management_enabled'), entity.power_management.enabled) and
|
||||
equal(self.param('override_display'), getattr(entity.display, 'address', None)) and
|
||||
|
|
|
@ -93,7 +93,10 @@ options:
|
|||
- "C(username) - A CHAP user name for logging into a target."
|
||||
- "C(password) - A CHAP password for logging into a target."
|
||||
- "C(override_luns) - If I(True) ISCSI storage domain luns will be overridden before adding."
|
||||
- C(target_lun_map) - List of dictionary containing targets and LUNs."
|
||||
- "Note that these parameters are not idempotent."
|
||||
- "Parameter C(target_lun_map) is supported since Ansible 2.5."
|
||||
|
||||
posixfs:
|
||||
description:
|
||||
- "Dictionary with values for PosixFS storage type:"
|
||||
|
@ -196,6 +199,21 @@ EXAMPLES = '''
|
|||
critical_space_action_blocker: 5
|
||||
warning_low_space: 10
|
||||
|
||||
# Since Ansible 2.5 you can specify multiple targets for storage domain,
|
||||
# Add data iSCSI storage domain with multiple targets:
|
||||
- ovirt_storage_domains:
|
||||
name: data_iscsi
|
||||
host: myhost
|
||||
data_center: mydatacenter
|
||||
iscsi:
|
||||
target_lun_map:
|
||||
- target: iqn.2016-08-09.domain-01:nickname
|
||||
lun_id: 1IET_000d0001
|
||||
- target: iqn.2016-08-09.domain-02:nickname
|
||||
lun_id: 1IET_000d0002
|
||||
address: 10.34.63.204
|
||||
discard_after_delete: True
|
||||
|
||||
# Add data glusterfs storage domain
|
||||
- ovirt_storage_domains:
|
||||
name: glusterfs_1
|
||||
|
@ -294,18 +312,19 @@ class StorageDomainModule(BaseModule):
|
|||
|
||||
def _get_storage_type(self):
|
||||
for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs']:
|
||||
if self._module.params.get(sd_type) is not None:
|
||||
if self.param(sd_type) is not None:
|
||||
return sd_type
|
||||
|
||||
def _get_storage(self):
|
||||
for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs']:
|
||||
if self._module.params.get(sd_type) is not None:
|
||||
return self._module.params.get(sd_type)
|
||||
if self.param(sd_type) is not None:
|
||||
return self.param(sd_type)
|
||||
|
||||
def _login(self, storage_type, storage):
|
||||
if storage_type == 'iscsi':
|
||||
hosts_service = self._connection.system_service().hosts_service()
|
||||
host_id = get_id_by_name(hosts_service, self._module.params['host'])
|
||||
host_id = get_id_by_name(hosts_service, self.param('host'))
|
||||
if storage.get('target'):
|
||||
hosts_service.host_service(host_id).iscsi_login(
|
||||
iscsi=otypes.IscsiDetails(
|
||||
username=storage.get('username'),
|
||||
|
@ -314,6 +333,23 @@ class StorageDomainModule(BaseModule):
|
|||
target=storage.get('target'),
|
||||
),
|
||||
)
|
||||
elif storage.get('target_lun_map'):
|
||||
for target in [m['target'] for m in storage.get('target_lun_map')]:
|
||||
hosts_service.host_service(host_id).iscsi_login(
|
||||
iscsi=otypes.IscsiDetails(
|
||||
username=storage.get('username'),
|
||||
password=storage.get('password'),
|
||||
address=storage.get('address'),
|
||||
target=target,
|
||||
),
|
||||
)
|
||||
|
||||
def __target_lun_map(self, storage):
|
||||
if storage.get('target'):
|
||||
lun_ids = storage.get('lun_id') if isinstance(storage.get('lun_id'), list) else [(storage.get('lun_id'))]
|
||||
return [(lun_id, storage.get('target')) for lun_id in lun_ids]
|
||||
elif storage.get('target_lun_map'):
|
||||
return [(target_map.get('lun_id'), target_map.get('target')) for target_map in storage.get('target_lun_map')]
|
||||
|
||||
def build_entity(self):
|
||||
storage_type = self._get_storage_type()
|
||||
|
@ -321,29 +357,18 @@ class StorageDomainModule(BaseModule):
|
|||
self._login(storage_type, storage)
|
||||
|
||||
return otypes.StorageDomain(
|
||||
name=self._module.params['name'],
|
||||
description=self._module.params['description'],
|
||||
comment=self._module.params['comment'],
|
||||
wipe_after_delete=self._module.params['wipe_after_delete'],
|
||||
backup=self._module.params['backup'],
|
||||
critical_space_action_blocker=self._module.params['critical_space_action_blocker'],
|
||||
warning_low_space_indicator=self._module.params['warning_low_space'],
|
||||
import_=(
|
||||
True
|
||||
if self._module.params['state'] == 'imported' else None
|
||||
),
|
||||
id=(
|
||||
self._module.params['id']
|
||||
if self._module.params['state'] == 'imported' else None
|
||||
),
|
||||
type=otypes.StorageDomainType(
|
||||
self._module.params['domain_function']
|
||||
),
|
||||
host=otypes.Host(
|
||||
name=self._module.params['host'],
|
||||
),
|
||||
discard_after_delete=self._module.params['discard_after_delete']
|
||||
if storage_type in ['iscsi', 'fcp'] else False,
|
||||
name=self.param('name'),
|
||||
description=self.param('description'),
|
||||
comment=self.param('comment'),
|
||||
wipe_after_delete=self.param('wipe_after_delete'),
|
||||
backup=self.param('backup'),
|
||||
critical_space_action_blocker=self.param('critical_space_action_blocker'),
|
||||
warning_low_space_indicator=self.param('warning_low_space'),
|
||||
import_=True if self.param('state') == 'imported' else None,
|
||||
id=self.param('id') if self.param('state') == 'imported' else None,
|
||||
type=otypes.StorageDomainType(self.param('domain_function')),
|
||||
host=otypes.Host(name=self.param('host')),
|
||||
discard_after_delete=self.param('discard_after_delete'),
|
||||
storage=otypes.HostStorage(
|
||||
type=otypes.StorageType(storage_type),
|
||||
logical_units=[
|
||||
|
@ -351,14 +376,10 @@ class StorageDomainModule(BaseModule):
|
|||
id=lun_id,
|
||||
address=storage.get('address'),
|
||||
port=int(storage.get('port', 3260)),
|
||||
target=storage.get('target'),
|
||||
target=target,
|
||||
username=storage.get('username'),
|
||||
password=storage.get('password'),
|
||||
) for lun_id in (
|
||||
storage.get('lun_id')
|
||||
if isinstance(storage.get('lun_id'), list)
|
||||
else [storage.get('lun_id')]
|
||||
)
|
||||
) for lun_id, target in self.__target_lun_map(storage)
|
||||
] if storage_type in ['iscsi', 'fcp'] else None,
|
||||
override_luns=storage.get('override_luns'),
|
||||
mount_options=storage.get('mount_options'),
|
||||
|
@ -397,7 +418,7 @@ class StorageDomainModule(BaseModule):
|
|||
raise Exception(
|
||||
"Can't bring storage to state `%s`, because it seems that"
|
||||
"it is not attached to any datacenter"
|
||||
% self._module.params['state']
|
||||
% self.param('state')
|
||||
)
|
||||
else:
|
||||
if dc.status == dcstatus.UP:
|
||||
|
@ -423,7 +444,7 @@ class StorageDomainModule(BaseModule):
|
|||
return dc_service.storage_domains_service()
|
||||
|
||||
def _attached_sd_service(self, storage_domain):
|
||||
dc_name = self._module.params['data_center']
|
||||
dc_name = self.param('data_center')
|
||||
if not dc_name:
|
||||
# Find the DC, where the storage resides:
|
||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||
|
@ -443,8 +464,8 @@ class StorageDomainModule(BaseModule):
|
|||
wait(
|
||||
service=attached_sd_service,
|
||||
condition=lambda sd: sd.status == sdstate.MAINTENANCE,
|
||||
wait=self._module.params['wait'],
|
||||
timeout=self._module.params['timeout'],
|
||||
wait=self.param('wait'),
|
||||
timeout=self.param('timeout'),
|
||||
)
|
||||
|
||||
def _unattach(self, storage_domain):
|
||||
|
@ -460,15 +481,15 @@ class StorageDomainModule(BaseModule):
|
|||
wait(
|
||||
service=attached_sd_service,
|
||||
condition=lambda sd: sd is None,
|
||||
wait=self._module.params['wait'],
|
||||
timeout=self._module.params['timeout'],
|
||||
wait=self.param('wait'),
|
||||
timeout=self.param('timeout'),
|
||||
)
|
||||
|
||||
def pre_remove(self, storage_domain):
|
||||
# In case the user chose to destroy the storage domain there is no need to
|
||||
# move it to maintenance or detach it, it should simply be removed from the DB.
|
||||
# Also if storage domain in already unattached skip this step.
|
||||
if storage_domain.status == sdstate.UNATTACHED or self._module.params['destroy']:
|
||||
if storage_domain.status == sdstate.UNATTACHED or self.param('destroy'):
|
||||
return
|
||||
# Before removing storage domain we need to put it into maintenance state:
|
||||
self._maintenance(storage_domain)
|
||||
|
@ -478,7 +499,7 @@ class StorageDomainModule(BaseModule):
|
|||
|
||||
def post_create_check(self, sd_id):
|
||||
storage_domain = self._service.service(sd_id).get()
|
||||
dc_name = self._module.params['data_center']
|
||||
dc_name = self.param('data_center')
|
||||
if not dc_name:
|
||||
# Find the DC, where the storage resides:
|
||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||
|
@ -497,12 +518,12 @@ class StorageDomainModule(BaseModule):
|
|||
wait(
|
||||
service=attached_sd_service,
|
||||
condition=lambda sd: sd.status == sdstate.ACTIVE,
|
||||
wait=self._module.params['wait'],
|
||||
timeout=self._module.params['timeout'],
|
||||
wait=self.param('wait'),
|
||||
timeout=self.param('timeout'),
|
||||
)
|
||||
|
||||
def unattached_pre_action(self, storage_domain):
|
||||
dc_name = self._module.params['data_center']
|
||||
dc_name = self.param('data_center')
|
||||
if not dc_name:
|
||||
# Find the DC, where the storage resides:
|
||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||
|
@ -511,8 +532,13 @@ class StorageDomainModule(BaseModule):
|
|||
|
||||
def update_check(self, entity):
|
||||
return (
|
||||
equal(self._module.params['comment'], entity.comment) and
|
||||
equal(self._module.params['description'], entity.description)
|
||||
equal(self.param('comment'), entity.comment) and
|
||||
equal(self.param('description'), entity.description) and
|
||||
equal(self.param('backup'), entity.backup) and
|
||||
equal(self.param('critical_space_action_blocker'), entity.critical_space_action_blocker) and
|
||||
equal(self.param('discard_after_delete'), entity.discard_after_delete) and
|
||||
equal(self.param('wipe_after_delete'), entity.wipe_after_delete) and
|
||||
equal(self.param('warning_low_space_indicator'), entity.warning_low_space_indicator)
|
||||
)
|
||||
|
||||
|
||||
|
@ -578,9 +604,9 @@ def main():
|
|||
backup=dict(type='bool', default=None),
|
||||
critical_space_action_blocker=dict(type='int', default=None),
|
||||
warning_low_space=dict(type='int', default=None),
|
||||
destroy=dict(type='bool', default=False),
|
||||
format=dict(type='bool', default=False),
|
||||
discard_after_delete=dict(type='bool', default=True)
|
||||
destroy=dict(type='bool', default=None),
|
||||
format=dict(type='bool', default=None),
|
||||
discard_after_delete=dict(type='bool', default=None)
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
|
|
|
@ -371,6 +371,12 @@ options:
|
|||
- C(nic_name) - Set name to network interface of Virtual Machine.
|
||||
- C(nic_on_boot) - If I(True) network interface will be set to start on boot.
|
||||
version_added: "2.3"
|
||||
cloud_init_persist:
|
||||
description:
|
||||
- "If I(true) the C(cloud_init) or C(sysprep) parameters will be saved for the virtual machine
|
||||
and won't be virtual machine won't be started as run-once."
|
||||
version_added: "2.5"
|
||||
aliases: [ 'sysprep_persist' ]
|
||||
kernel_path:
|
||||
description:
|
||||
- Path to a kernel image used to boot the virtual machine.
|
||||
|
@ -496,9 +502,9 @@ options:
|
|||
description:
|
||||
- "If I(true), use smart card authentication."
|
||||
version_added: "2.5"
|
||||
io_threads_enabled:
|
||||
io_threads:
|
||||
description:
|
||||
- "If I(true), use IO threads."
|
||||
- "Number of IO threads used by virtual machine. I(0) means IO threading disabled."
|
||||
version_added: "2.5"
|
||||
ballooning_enabled:
|
||||
description:
|
||||
|
@ -527,6 +533,13 @@ options:
|
|||
- "C(model) - Model of the watchdog device. For example: I(i6300esb), I(diag288) or I(null)."
|
||||
- "C(action) - Watchdog action to be performed when watchdog is triggered. For example: I(none), I(reset), I(poweroff), I(pause) or I(dump)."
|
||||
version_added: "2.5"
|
||||
graphical_console:
|
||||
description:
|
||||
- "Assign graphical console to the virtual machine."
|
||||
- "Graphical console is a dictionary which can have following values:"
|
||||
- "C(headless_mode) - If I(true) disable the graphics console for this virtual machine."
|
||||
- "C(protocol) - Graphical protocol, one of I(VNC), I(SPICE), or both."
|
||||
version_added: "2.5"
|
||||
notes:
|
||||
- If VM is in I(UNASSIGNED) or I(UNKNOWN) state before any operation, the module will fail.
|
||||
If VM is in I(IMAGE_LOCKED) state before any operation, we try to wait for VM to be I(DOWN).
|
||||
|
@ -838,6 +851,10 @@ from ansible.module_utils.ovirt import (
|
|||
|
||||
class VmsModule(BaseModule):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(VmsModule, self).__init__(*args, **kwargs)
|
||||
self._initialization = None
|
||||
|
||||
def __get_template_with_version(self):
|
||||
"""
|
||||
oVirt/RHV in version 4.1 doesn't support search by template+version_number,
|
||||
|
@ -1017,8 +1034,8 @@ class VmsModule(BaseModule):
|
|||
smartcard_enabled=self.param('smartcard_enabled')
|
||||
) if self.param('smartcard_enabled') is not None else None,
|
||||
io=otypes.Io(
|
||||
threads=int(self.param('io_threads_enabled')),
|
||||
) if self.param('io_threads_enabled') is not None else None,
|
||||
threads=self.param('io_threads'),
|
||||
) if self.param('io_threads') is not None else None,
|
||||
rng_device=otypes.RngDevice(
|
||||
source=otypes.RngSource(self.param('rng_device')),
|
||||
) if self.param('rng_device') else None,
|
||||
|
@ -1027,8 +1044,9 @@ class VmsModule(BaseModule):
|
|||
name=cp.get('name'),
|
||||
regexp=cp.get('regexp'),
|
||||
value=str(cp.get('value')),
|
||||
) for cp in self.param('custom_properties')
|
||||
] if self.param('custom_properties') is not None else None
|
||||
) for cp in self.param('custom_properties') if cp
|
||||
] if self.param('custom_properties') is not None else None,
|
||||
initialization=self.get_initialization() if self.param('cloud_init_persist') else None,
|
||||
)
|
||||
|
||||
def update_check(self, entity):
|
||||
|
@ -1046,14 +1064,16 @@ class VmsModule(BaseModule):
|
|||
current = []
|
||||
if entity.custom_properties:
|
||||
current = [(cp.name, cp.regexp, str(cp.value)) for cp in entity.custom_properties]
|
||||
passed = [(cp.get('name'), cp.get('regexp'), str(cp.get('value'))) for cp in self.param('custom_properties')]
|
||||
passed = [(cp.get('name'), cp.get('regexp'), str(cp.get('value'))) for cp in self.param('custom_properties') if cp]
|
||||
return sorted(current) == sorted(passed)
|
||||
return True
|
||||
|
||||
cpu_mode = getattr(entity.cpu, 'mode')
|
||||
vm_display = entity.display
|
||||
return (
|
||||
check_cpu_pinning() and
|
||||
check_custom_properties() and
|
||||
not self.param('cloud_init_persist') and
|
||||
equal(self.param('cluster'), get_link_name(self._connection, entity.cluster)) and equal(convert_to_bytes(self.param('memory')), entity.memory) and
|
||||
equal(convert_to_bytes(self.param('memory_guaranteed')), entity.memory_policy.guaranteed) and
|
||||
equal(convert_to_bytes(self.param('memory_max')), entity.memory_policy.max) and
|
||||
|
@ -1065,8 +1085,8 @@ class VmsModule(BaseModule):
|
|||
equal(self.param('operating_system'), str(entity.os.type)) and
|
||||
equal(self.param('boot_menu'), entity.bios.boot_menu.enabled) and
|
||||
equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and
|
||||
equal(self.param('smartcard_enabled'), entity.display.smartcard_enabled) and
|
||||
equal(self.param('io_threads_enabled'), bool(entity.io.threads)) and
|
||||
equal(self.param('smartcard_enabled'), getattr(vm_display, 'smartcard_enabled', False)) and
|
||||
equal(self.param('io_threads'), entity.io.threads) and
|
||||
equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and
|
||||
equal(self.param('serial_console'), entity.console.enabled) and
|
||||
equal(self.param('usb_support'), entity.usb.enabled) and
|
||||
|
@ -1088,7 +1108,7 @@ class VmsModule(BaseModule):
|
|||
equal(self.param('serial_policy_value'), getattr(entity.serial_number, 'value', None)) and
|
||||
equal(self.param('placement_policy'), str(entity.placement_policy.affinity)) and
|
||||
equal(self.param('rng_device'), str(entity.rng_device.source) if entity.rng_device else None) and
|
||||
self.param('host') in [self._connection.follow_link(host).name for host in entity.placement_policy.hosts]
|
||||
self.param('host') in [self._connection.follow_link(host).name for host in entity.placement_policy.hosts or []]
|
||||
)
|
||||
|
||||
def pre_create(self, entity):
|
||||
|
@ -1098,13 +1118,15 @@ class VmsModule(BaseModule):
|
|||
self._module.params['template'] = 'Blank'
|
||||
|
||||
def post_update(self, entity):
|
||||
self.post_present(entity)
|
||||
self.post_present(entity.id)
|
||||
|
||||
def post_present(self, entity):
|
||||
def post_present(self, entity_id):
|
||||
# After creation of the VM, attach disks and NICs:
|
||||
entity = self._service.service(entity_id).get()
|
||||
self.changed = self.__attach_disks(entity)
|
||||
self.changed = self.__attach_nics(entity)
|
||||
self.changed = self.__attach_watchdog(entity)
|
||||
self.changed = self.__attach_graphical_console(entity)
|
||||
|
||||
def pre_remove(self, entity):
|
||||
# Forcibly stop the VM, if it's not in DOWN state:
|
||||
|
@ -1250,6 +1272,51 @@ class VmsModule(BaseModule):
|
|||
)
|
||||
return True
|
||||
|
||||
def __attach_graphical_console(self, entity):
|
||||
graphical_console = self.param('graphical_console')
|
||||
if not graphical_console:
|
||||
return
|
||||
|
||||
vm_service = self._service.service(entity.id)
|
||||
gcs_service = vm_service.graphics_consoles_service()
|
||||
graphical_consoles = gcs_service.list()
|
||||
|
||||
# Remove all graphical consoles if there are any:
|
||||
if bool(graphical_console.get('headless_mode')):
|
||||
if not self._module.check_mode:
|
||||
for gc in graphical_consoles:
|
||||
gcs_service.console_service(gc.id).remove()
|
||||
return len(graphical_consoles) > 0
|
||||
|
||||
# If there are not gc add any gc to be added:
|
||||
protocol = graphical_console.get('protocol')
|
||||
if isinstance(protocol, str):
|
||||
protocol = [protocol]
|
||||
|
||||
current_protocols = [str(gc.protocol) for gc in graphical_consoles]
|
||||
if not current_protocols:
|
||||
if not self._module.check_mode:
|
||||
for p in protocol:
|
||||
gcs_service.add(
|
||||
otypes.GraphicsConsole(
|
||||
protocol=otypes.GraphicsType(p),
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
# Update consoles:
|
||||
if sorted(protocol) != sorted(current_protocols):
|
||||
if not self._module.check_mode:
|
||||
for gc in graphical_consoles:
|
||||
gcs_service.console_service(gc.id).remove()
|
||||
for p in protocol:
|
||||
gcs_service.add(
|
||||
otypes.GraphicsConsole(
|
||||
protocol=otypes.GraphicsType(p),
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def __attach_disks(self, entity):
|
||||
if not self.param('disks'):
|
||||
return
|
||||
|
@ -1370,6 +1437,52 @@ class VmsModule(BaseModule):
|
|||
)
|
||||
self.changed = True
|
||||
|
||||
def get_initialization(self):
|
||||
if self._initialization is not None:
|
||||
return self._initialization
|
||||
|
||||
sysprep = self.param('sysprep')
|
||||
cloud_init = self.param('cloud_init')
|
||||
cloud_init_nics = self.param('cloud_init_nics') or []
|
||||
if cloud_init is not None:
|
||||
cloud_init_nics.append(cloud_init)
|
||||
|
||||
if cloud_init or cloud_init_nics:
|
||||
self._initialization = otypes.Initialization(
|
||||
nic_configurations=[
|
||||
otypes.NicConfiguration(
|
||||
boot_protocol=otypes.BootProtocol(
|
||||
nic.pop('nic_boot_protocol').lower()
|
||||
) if nic.get('nic_boot_protocol') else None,
|
||||
name=nic.pop('nic_name', None),
|
||||
on_boot=nic.pop('nic_on_boot', None),
|
||||
ip=otypes.Ip(
|
||||
address=nic.pop('nic_ip_address', None),
|
||||
netmask=nic.pop('nic_netmask', None),
|
||||
gateway=nic.pop('nic_gateway', None),
|
||||
) if (
|
||||
nic.get('nic_gateway') is not None or
|
||||
nic.get('nic_netmask') is not None or
|
||||
nic.get('nic_ip_address') is not None
|
||||
) else None,
|
||||
)
|
||||
for nic in cloud_init_nics
|
||||
if (
|
||||
nic.get('nic_gateway') is not None or
|
||||
nic.get('nic_netmask') is not None or
|
||||
nic.get('nic_ip_address') is not None or
|
||||
nic.get('nic_boot_protocol') is not None or
|
||||
nic.get('nic_on_boot') is not None
|
||||
)
|
||||
] if cloud_init_nics else None,
|
||||
**cloud_init
|
||||
)
|
||||
elif sysprep:
|
||||
self._initialization = otypes.Initialization(
|
||||
**sysprep
|
||||
)
|
||||
return self._initialization
|
||||
|
||||
|
||||
def _get_role_mappings(module):
|
||||
roleMappings = list()
|
||||
|
@ -1569,45 +1682,6 @@ def import_vm(module, connection):
|
|||
return True
|
||||
|
||||
|
||||
def _get_initialization(sysprep, cloud_init, cloud_init_nics):
|
||||
initialization = None
|
||||
if cloud_init or cloud_init_nics:
|
||||
initialization = otypes.Initialization(
|
||||
nic_configurations=[
|
||||
otypes.NicConfiguration(
|
||||
boot_protocol=otypes.BootProtocol(
|
||||
nic.pop('nic_boot_protocol').lower()
|
||||
) if nic.get('nic_boot_protocol') else None,
|
||||
name=nic.pop('nic_name', None),
|
||||
on_boot=nic.pop('nic_on_boot', None),
|
||||
ip=otypes.Ip(
|
||||
address=nic.pop('nic_ip_address', None),
|
||||
netmask=nic.pop('nic_netmask', None),
|
||||
gateway=nic.pop('nic_gateway', None),
|
||||
) if (
|
||||
nic.get('nic_gateway') is not None or
|
||||
nic.get('nic_netmask') is not None or
|
||||
nic.get('nic_ip_address') is not None
|
||||
) else None,
|
||||
)
|
||||
for nic in cloud_init_nics
|
||||
if (
|
||||
nic.get('nic_gateway') is not None or
|
||||
nic.get('nic_netmask') is not None or
|
||||
nic.get('nic_ip_address') is not None or
|
||||
nic.get('nic_boot_protocol') is not None or
|
||||
nic.get('nic_on_boot') is not None
|
||||
)
|
||||
] if cloud_init_nics else None,
|
||||
**cloud_init
|
||||
)
|
||||
elif sysprep:
|
||||
initialization = otypes.Initialization(
|
||||
**sysprep
|
||||
)
|
||||
return initialization
|
||||
|
||||
|
||||
def control_state(vm, vms_service, module):
|
||||
if vm is None:
|
||||
return
|
||||
|
@ -1671,19 +1745,7 @@ def main():
|
|||
cpu_shares=dict(type='int'),
|
||||
cpu_threads=dict(type='int'),
|
||||
type=dict(type='str', choices=['server', 'desktop', 'high_performance']),
|
||||
operating_system=dict(type='str',
|
||||
choices=[
|
||||
'rhel_6_ppc64', 'other', 'freebsd', 'windows_2003x64', 'windows_10',
|
||||
'rhel_6x64', 'rhel_4x64', 'windows_2008x64', 'windows_2008R2x64',
|
||||
'debian_7', 'windows_2012x64', 'ubuntu_14_04', 'ubuntu_12_04',
|
||||
'ubuntu_13_10', 'windows_8x64', 'other_linux_ppc64', 'windows_2003',
|
||||
'other_linux', 'windows_10x64', 'windows_2008', 'rhel_3', 'rhel_5',
|
||||
'rhel_4', 'other_ppc64', 'sles_11', 'rhel_6', 'windows_xp', 'rhel_7x64',
|
||||
'freebsdx64', 'rhel_7_ppc64', 'windows_7', 'rhel_5x64',
|
||||
'ubuntu_14_04_ppc64', 'sles_11_ppc64', 'windows_8',
|
||||
'windows_2012R2x64', 'windows_2008r2x64', 'ubuntu_13_04',
|
||||
'ubuntu_12_10', 'windows_7x64',
|
||||
]),
|
||||
operating_system=dict(type='str'),
|
||||
cd_iso=dict(type='str'),
|
||||
boot_devices=dict(type='list'),
|
||||
vnic_profile_mappings=dict(default=[], type='list'),
|
||||
|
@ -1708,6 +1770,7 @@ def main():
|
|||
nics=dict(type='list', default=[]),
|
||||
cloud_init=dict(type='dict'),
|
||||
cloud_init_nics=dict(type='list', default=[]),
|
||||
cloud_init_persist=dict(type='bool', default=False, aliases=['sysprep_persist']),
|
||||
sysprep=dict(type='dict'),
|
||||
host=dict(type='str'),
|
||||
clone=dict(type='bool', default=False),
|
||||
|
@ -1729,11 +1792,12 @@ def main():
|
|||
cpu_pinning=dict(type='list'),
|
||||
soundcard_enabled=dict(type='bool', default=None),
|
||||
smartcard_enabled=dict(type='bool', default=None),
|
||||
io_threads_enabled=dict(type='bool', default=None),
|
||||
io_threads=dict(type='int', default=None),
|
||||
ballooning_enabled=dict(type='bool', default=None),
|
||||
rng_device=dict(type='str'),
|
||||
custom_properties=dict(type='list'),
|
||||
watchdog=dict(type='dict'),
|
||||
graphical_console=dict(type='dict'),
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
|
@ -1760,12 +1824,6 @@ def main():
|
|||
if module.params['xen'] or module.params['kvm'] or module.params['vmware']:
|
||||
vms_module.changed = import_vm(module, connection)
|
||||
|
||||
sysprep = module.params['sysprep']
|
||||
cloud_init = module.params['cloud_init']
|
||||
cloud_init_nics = module.params['cloud_init_nics'] or []
|
||||
if cloud_init is not None:
|
||||
cloud_init_nics.append(cloud_init)
|
||||
|
||||
# In case VM don't exist, wait for VM DOWN state,
|
||||
# otherwise don't wait for any state, just update VM:
|
||||
ret = vms_module.create(
|
||||
|
@ -1774,11 +1832,11 @@ def main():
|
|||
clone=module.params['clone'],
|
||||
clone_permissions=module.params['clone_permissions'],
|
||||
)
|
||||
vms_module.post_present(vm)
|
||||
vms_module.post_present(ret['id'])
|
||||
|
||||
# Run the VM if it was just created, else don't run it:
|
||||
if state == 'running':
|
||||
initialization = _get_initialization(sysprep, cloud_init, cloud_init_nics)
|
||||
initialization = vms_module.get_initialization()
|
||||
ret = vms_module.action(
|
||||
action='start',
|
||||
post_action=vms_module._post_start_action,
|
||||
|
@ -1794,8 +1852,8 @@ def main():
|
|||
),
|
||||
wait_condition=lambda vm: vm.status == otypes.VmStatus.UP,
|
||||
# Start action kwargs:
|
||||
use_cloud_init=cloud_init is not None or len(cloud_init_nics) > 0,
|
||||
use_sysprep=sysprep is not None,
|
||||
use_cloud_init=not module.params.get('cloud_init_persist') and module.params.get('cloud_init') is not None,
|
||||
use_sysprep=not module.params.get('cloud_init_persist') and module.params.get('sysprep') is not None,
|
||||
vm=otypes.Vm(
|
||||
placement_policy=otypes.VmPlacementPolicy(
|
||||
hosts=[otypes.Host(name=module.params['host'])]
|
||||
|
@ -1815,7 +1873,7 @@ def main():
|
|||
module.params.get('initrd_path') or
|
||||
module.params.get('kernel_path') or
|
||||
module.params.get('host') or
|
||||
initialization
|
||||
initialization is not None and not module.params.get('cloud_init_persist')
|
||||
) else None,
|
||||
)
|
||||
|
||||
|
@ -1839,6 +1897,7 @@ def main():
|
|||
clone=module.params['clone'],
|
||||
clone_permissions=module.params['clone_permissions'],
|
||||
)
|
||||
vms_module.post_present(ret['id'])
|
||||
if module.params['force']:
|
||||
ret = vms_module.action(
|
||||
action='stop',
|
||||
|
@ -1860,6 +1919,7 @@ def main():
|
|||
clone=module.params['clone'],
|
||||
clone_permissions=module.params['clone_permissions'],
|
||||
)
|
||||
vms_module.post_present(ret['id'])
|
||||
ret = vms_module.action(
|
||||
action='suspend',
|
||||
pre_action=vms_module._pre_suspend_action,
|
||||
|
|
Loading…
Reference in a new issue