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(
|
ssh=otypes.Ssh(
|
||||||
authentication_method=otypes.SshAuthenticationMethod.PUBLICKEY,
|
authentication_method=otypes.SshAuthenticationMethod.PUBLICKEY,
|
||||||
) if self.param('public_key') else None,
|
) 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(
|
spm=otypes.Spm(
|
||||||
priority=self.param('spm_priority'),
|
priority=self.param('spm_priority'),
|
||||||
) if self.param('spm_priority') else None,
|
) if self.param('spm_priority') else None,
|
||||||
|
@ -283,14 +280,15 @@ class HostsModule(BaseModule):
|
||||||
) if self.param('kernel_params') else None,
|
) if self.param('kernel_params') else None,
|
||||||
power_management=otypes.PowerManagement(
|
power_management=otypes.PowerManagement(
|
||||||
enabled=self.param('power_management_enabled'),
|
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):
|
def update_check(self, entity):
|
||||||
kernel_params = self.param('kernel_params')
|
kernel_params = self.param('kernel_params')
|
||||||
return (
|
return (
|
||||||
equal(self.param('comment'), entity.comment) and
|
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('spm_priority'), entity.spm.priority) and
|
||||||
equal(self.param('power_management_enabled'), entity.power_management.enabled) and
|
equal(self.param('power_management_enabled'), entity.power_management.enabled) and
|
||||||
equal(self.param('override_display'), getattr(entity.display, 'address', None)) 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(username) - A CHAP user name for logging into a target."
|
||||||
- "C(password) - A CHAP password 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(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."
|
- "Note that these parameters are not idempotent."
|
||||||
|
- "Parameter C(target_lun_map) is supported since Ansible 2.5."
|
||||||
|
|
||||||
posixfs:
|
posixfs:
|
||||||
description:
|
description:
|
||||||
- "Dictionary with values for PosixFS storage type:"
|
- "Dictionary with values for PosixFS storage type:"
|
||||||
|
@ -196,6 +199,21 @@ EXAMPLES = '''
|
||||||
critical_space_action_blocker: 5
|
critical_space_action_blocker: 5
|
||||||
warning_low_space: 10
|
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
|
# Add data glusterfs storage domain
|
||||||
- ovirt_storage_domains:
|
- ovirt_storage_domains:
|
||||||
name: glusterfs_1
|
name: glusterfs_1
|
||||||
|
@ -294,18 +312,19 @@ class StorageDomainModule(BaseModule):
|
||||||
|
|
||||||
def _get_storage_type(self):
|
def _get_storage_type(self):
|
||||||
for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs']:
|
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
|
return sd_type
|
||||||
|
|
||||||
def _get_storage(self):
|
def _get_storage(self):
|
||||||
for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs']:
|
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 self._module.params.get(sd_type)
|
return self.param(sd_type)
|
||||||
|
|
||||||
def _login(self, storage_type, storage):
|
def _login(self, storage_type, storage):
|
||||||
if storage_type == 'iscsi':
|
if storage_type == 'iscsi':
|
||||||
hosts_service = self._connection.system_service().hosts_service()
|
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(
|
hosts_service.host_service(host_id).iscsi_login(
|
||||||
iscsi=otypes.IscsiDetails(
|
iscsi=otypes.IscsiDetails(
|
||||||
username=storage.get('username'),
|
username=storage.get('username'),
|
||||||
|
@ -314,6 +333,23 @@ class StorageDomainModule(BaseModule):
|
||||||
target=storage.get('target'),
|
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):
|
def build_entity(self):
|
||||||
storage_type = self._get_storage_type()
|
storage_type = self._get_storage_type()
|
||||||
|
@ -321,29 +357,18 @@ class StorageDomainModule(BaseModule):
|
||||||
self._login(storage_type, storage)
|
self._login(storage_type, storage)
|
||||||
|
|
||||||
return otypes.StorageDomain(
|
return otypes.StorageDomain(
|
||||||
name=self._module.params['name'],
|
name=self.param('name'),
|
||||||
description=self._module.params['description'],
|
description=self.param('description'),
|
||||||
comment=self._module.params['comment'],
|
comment=self.param('comment'),
|
||||||
wipe_after_delete=self._module.params['wipe_after_delete'],
|
wipe_after_delete=self.param('wipe_after_delete'),
|
||||||
backup=self._module.params['backup'],
|
backup=self.param('backup'),
|
||||||
critical_space_action_blocker=self._module.params['critical_space_action_blocker'],
|
critical_space_action_blocker=self.param('critical_space_action_blocker'),
|
||||||
warning_low_space_indicator=self._module.params['warning_low_space'],
|
warning_low_space_indicator=self.param('warning_low_space'),
|
||||||
import_=(
|
import_=True if self.param('state') == 'imported' else None,
|
||||||
True
|
id=self.param('id') if self.param('state') == 'imported' else None,
|
||||||
if self._module.params['state'] == 'imported' else None
|
type=otypes.StorageDomainType(self.param('domain_function')),
|
||||||
),
|
host=otypes.Host(name=self.param('host')),
|
||||||
id=(
|
discard_after_delete=self.param('discard_after_delete'),
|
||||||
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,
|
|
||||||
storage=otypes.HostStorage(
|
storage=otypes.HostStorage(
|
||||||
type=otypes.StorageType(storage_type),
|
type=otypes.StorageType(storage_type),
|
||||||
logical_units=[
|
logical_units=[
|
||||||
|
@ -351,14 +376,10 @@ class StorageDomainModule(BaseModule):
|
||||||
id=lun_id,
|
id=lun_id,
|
||||||
address=storage.get('address'),
|
address=storage.get('address'),
|
||||||
port=int(storage.get('port', 3260)),
|
port=int(storage.get('port', 3260)),
|
||||||
target=storage.get('target'),
|
target=target,
|
||||||
username=storage.get('username'),
|
username=storage.get('username'),
|
||||||
password=storage.get('password'),
|
password=storage.get('password'),
|
||||||
) for lun_id in (
|
) for lun_id, target in self.__target_lun_map(storage)
|
||||||
storage.get('lun_id')
|
|
||||||
if isinstance(storage.get('lun_id'), list)
|
|
||||||
else [storage.get('lun_id')]
|
|
||||||
)
|
|
||||||
] if storage_type in ['iscsi', 'fcp'] else None,
|
] if storage_type in ['iscsi', 'fcp'] else None,
|
||||||
override_luns=storage.get('override_luns'),
|
override_luns=storage.get('override_luns'),
|
||||||
mount_options=storage.get('mount_options'),
|
mount_options=storage.get('mount_options'),
|
||||||
|
@ -397,7 +418,7 @@ class StorageDomainModule(BaseModule):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Can't bring storage to state `%s`, because it seems that"
|
"Can't bring storage to state `%s`, because it seems that"
|
||||||
"it is not attached to any datacenter"
|
"it is not attached to any datacenter"
|
||||||
% self._module.params['state']
|
% self.param('state')
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if dc.status == dcstatus.UP:
|
if dc.status == dcstatus.UP:
|
||||||
|
@ -423,7 +444,7 @@ class StorageDomainModule(BaseModule):
|
||||||
return dc_service.storage_domains_service()
|
return dc_service.storage_domains_service()
|
||||||
|
|
||||||
def _attached_sd_service(self, storage_domain):
|
def _attached_sd_service(self, storage_domain):
|
||||||
dc_name = self._module.params['data_center']
|
dc_name = self.param('data_center')
|
||||||
if not dc_name:
|
if not dc_name:
|
||||||
# Find the DC, where the storage resides:
|
# Find the DC, where the storage resides:
|
||||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||||
|
@ -443,8 +464,8 @@ class StorageDomainModule(BaseModule):
|
||||||
wait(
|
wait(
|
||||||
service=attached_sd_service,
|
service=attached_sd_service,
|
||||||
condition=lambda sd: sd.status == sdstate.MAINTENANCE,
|
condition=lambda sd: sd.status == sdstate.MAINTENANCE,
|
||||||
wait=self._module.params['wait'],
|
wait=self.param('wait'),
|
||||||
timeout=self._module.params['timeout'],
|
timeout=self.param('timeout'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _unattach(self, storage_domain):
|
def _unattach(self, storage_domain):
|
||||||
|
@ -460,15 +481,15 @@ class StorageDomainModule(BaseModule):
|
||||||
wait(
|
wait(
|
||||||
service=attached_sd_service,
|
service=attached_sd_service,
|
||||||
condition=lambda sd: sd is None,
|
condition=lambda sd: sd is None,
|
||||||
wait=self._module.params['wait'],
|
wait=self.param('wait'),
|
||||||
timeout=self._module.params['timeout'],
|
timeout=self.param('timeout'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def pre_remove(self, storage_domain):
|
def pre_remove(self, storage_domain):
|
||||||
# In case the user chose to destroy the storage domain there is no need to
|
# 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.
|
# 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.
|
# 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
|
return
|
||||||
# Before removing storage domain we need to put it into maintenance state:
|
# Before removing storage domain we need to put it into maintenance state:
|
||||||
self._maintenance(storage_domain)
|
self._maintenance(storage_domain)
|
||||||
|
@ -478,7 +499,7 @@ class StorageDomainModule(BaseModule):
|
||||||
|
|
||||||
def post_create_check(self, sd_id):
|
def post_create_check(self, sd_id):
|
||||||
storage_domain = self._service.service(sd_id).get()
|
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:
|
if not dc_name:
|
||||||
# Find the DC, where the storage resides:
|
# Find the DC, where the storage resides:
|
||||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||||
|
@ -497,12 +518,12 @@ class StorageDomainModule(BaseModule):
|
||||||
wait(
|
wait(
|
||||||
service=attached_sd_service,
|
service=attached_sd_service,
|
||||||
condition=lambda sd: sd.status == sdstate.ACTIVE,
|
condition=lambda sd: sd.status == sdstate.ACTIVE,
|
||||||
wait=self._module.params['wait'],
|
wait=self.param('wait'),
|
||||||
timeout=self._module.params['timeout'],
|
timeout=self.param('timeout'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def unattached_pre_action(self, storage_domain):
|
def unattached_pre_action(self, storage_domain):
|
||||||
dc_name = self._module.params['data_center']
|
dc_name = self.param('data_center')
|
||||||
if not dc_name:
|
if not dc_name:
|
||||||
# Find the DC, where the storage resides:
|
# Find the DC, where the storage resides:
|
||||||
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
dc_name = self._find_attached_datacenter_name(storage_domain.name)
|
||||||
|
@ -511,8 +532,13 @@ class StorageDomainModule(BaseModule):
|
||||||
|
|
||||||
def update_check(self, entity):
|
def update_check(self, entity):
|
||||||
return (
|
return (
|
||||||
equal(self._module.params['comment'], entity.comment) and
|
equal(self.param('comment'), entity.comment) and
|
||||||
equal(self._module.params['description'], entity.description)
|
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),
|
backup=dict(type='bool', default=None),
|
||||||
critical_space_action_blocker=dict(type='int', default=None),
|
critical_space_action_blocker=dict(type='int', default=None),
|
||||||
warning_low_space=dict(type='int', default=None),
|
warning_low_space=dict(type='int', default=None),
|
||||||
destroy=dict(type='bool', default=False),
|
destroy=dict(type='bool', default=None),
|
||||||
format=dict(type='bool', default=False),
|
format=dict(type='bool', default=None),
|
||||||
discard_after_delete=dict(type='bool', default=True)
|
discard_after_delete=dict(type='bool', default=None)
|
||||||
)
|
)
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
|
|
|
@ -371,6 +371,12 @@ options:
|
||||||
- C(nic_name) - Set name to network interface of Virtual Machine.
|
- 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.
|
- C(nic_on_boot) - If I(True) network interface will be set to start on boot.
|
||||||
version_added: "2.3"
|
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:
|
kernel_path:
|
||||||
description:
|
description:
|
||||||
- Path to a kernel image used to boot the virtual machine.
|
- Path to a kernel image used to boot the virtual machine.
|
||||||
|
@ -496,9 +502,9 @@ options:
|
||||||
description:
|
description:
|
||||||
- "If I(true), use smart card authentication."
|
- "If I(true), use smart card authentication."
|
||||||
version_added: "2.5"
|
version_added: "2.5"
|
||||||
io_threads_enabled:
|
io_threads:
|
||||||
description:
|
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"
|
version_added: "2.5"
|
||||||
ballooning_enabled:
|
ballooning_enabled:
|
||||||
description:
|
description:
|
||||||
|
@ -527,6 +533,13 @@ options:
|
||||||
- "C(model) - Model of the watchdog device. For example: I(i6300esb), I(diag288) or I(null)."
|
- "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)."
|
- "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"
|
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:
|
notes:
|
||||||
- If VM is in I(UNASSIGNED) or I(UNKNOWN) state before any operation, the module will fail.
|
- 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).
|
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):
|
class VmsModule(BaseModule):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(VmsModule, self).__init__(*args, **kwargs)
|
||||||
|
self._initialization = None
|
||||||
|
|
||||||
def __get_template_with_version(self):
|
def __get_template_with_version(self):
|
||||||
"""
|
"""
|
||||||
oVirt/RHV in version 4.1 doesn't support search by template+version_number,
|
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')
|
smartcard_enabled=self.param('smartcard_enabled')
|
||||||
) if self.param('smartcard_enabled') is not None else None,
|
) if self.param('smartcard_enabled') is not None else None,
|
||||||
io=otypes.Io(
|
io=otypes.Io(
|
||||||
threads=int(self.param('io_threads_enabled')),
|
threads=self.param('io_threads'),
|
||||||
) if self.param('io_threads_enabled') is not None else None,
|
) if self.param('io_threads') is not None else None,
|
||||||
rng_device=otypes.RngDevice(
|
rng_device=otypes.RngDevice(
|
||||||
source=otypes.RngSource(self.param('rng_device')),
|
source=otypes.RngSource(self.param('rng_device')),
|
||||||
) if self.param('rng_device') else None,
|
) if self.param('rng_device') else None,
|
||||||
|
@ -1027,8 +1044,9 @@ class VmsModule(BaseModule):
|
||||||
name=cp.get('name'),
|
name=cp.get('name'),
|
||||||
regexp=cp.get('regexp'),
|
regexp=cp.get('regexp'),
|
||||||
value=str(cp.get('value')),
|
value=str(cp.get('value')),
|
||||||
) for cp in self.param('custom_properties')
|
) for cp in self.param('custom_properties') if cp
|
||||||
] if self.param('custom_properties') is not None else None
|
] 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):
|
def update_check(self, entity):
|
||||||
|
@ -1046,14 +1064,16 @@ class VmsModule(BaseModule):
|
||||||
current = []
|
current = []
|
||||||
if entity.custom_properties:
|
if entity.custom_properties:
|
||||||
current = [(cp.name, cp.regexp, str(cp.value)) for cp in 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 sorted(current) == sorted(passed)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
cpu_mode = getattr(entity.cpu, 'mode')
|
cpu_mode = getattr(entity.cpu, 'mode')
|
||||||
|
vm_display = entity.display
|
||||||
return (
|
return (
|
||||||
check_cpu_pinning() and
|
check_cpu_pinning() and
|
||||||
check_custom_properties() 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(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_guaranteed')), entity.memory_policy.guaranteed) and
|
||||||
equal(convert_to_bytes(self.param('memory_max')), entity.memory_policy.max) 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('operating_system'), str(entity.os.type)) and
|
||||||
equal(self.param('boot_menu'), entity.bios.boot_menu.enabled) and
|
equal(self.param('boot_menu'), entity.bios.boot_menu.enabled) and
|
||||||
equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and
|
equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and
|
||||||
equal(self.param('smartcard_enabled'), entity.display.smartcard_enabled) and
|
equal(self.param('smartcard_enabled'), getattr(vm_display, 'smartcard_enabled', False)) and
|
||||||
equal(self.param('io_threads_enabled'), bool(entity.io.threads)) and
|
equal(self.param('io_threads'), entity.io.threads) and
|
||||||
equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and
|
equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and
|
||||||
equal(self.param('serial_console'), entity.console.enabled) and
|
equal(self.param('serial_console'), entity.console.enabled) and
|
||||||
equal(self.param('usb_support'), entity.usb.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('serial_policy_value'), getattr(entity.serial_number, 'value', None)) and
|
||||||
equal(self.param('placement_policy'), str(entity.placement_policy.affinity)) 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
|
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):
|
def pre_create(self, entity):
|
||||||
|
@ -1098,13 +1118,15 @@ class VmsModule(BaseModule):
|
||||||
self._module.params['template'] = 'Blank'
|
self._module.params['template'] = 'Blank'
|
||||||
|
|
||||||
def post_update(self, entity):
|
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:
|
# 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_disks(entity)
|
||||||
self.changed = self.__attach_nics(entity)
|
self.changed = self.__attach_nics(entity)
|
||||||
self.changed = self.__attach_watchdog(entity)
|
self.changed = self.__attach_watchdog(entity)
|
||||||
|
self.changed = self.__attach_graphical_console(entity)
|
||||||
|
|
||||||
def pre_remove(self, entity):
|
def pre_remove(self, entity):
|
||||||
# Forcibly stop the VM, if it's not in DOWN state:
|
# Forcibly stop the VM, if it's not in DOWN state:
|
||||||
|
@ -1250,6 +1272,51 @@ class VmsModule(BaseModule):
|
||||||
)
|
)
|
||||||
return True
|
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):
|
def __attach_disks(self, entity):
|
||||||
if not self.param('disks'):
|
if not self.param('disks'):
|
||||||
return
|
return
|
||||||
|
@ -1370,6 +1437,52 @@ class VmsModule(BaseModule):
|
||||||
)
|
)
|
||||||
self.changed = True
|
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):
|
def _get_role_mappings(module):
|
||||||
roleMappings = list()
|
roleMappings = list()
|
||||||
|
@ -1569,45 +1682,6 @@ def import_vm(module, connection):
|
||||||
return True
|
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):
|
def control_state(vm, vms_service, module):
|
||||||
if vm is None:
|
if vm is None:
|
||||||
return
|
return
|
||||||
|
@ -1671,19 +1745,7 @@ def main():
|
||||||
cpu_shares=dict(type='int'),
|
cpu_shares=dict(type='int'),
|
||||||
cpu_threads=dict(type='int'),
|
cpu_threads=dict(type='int'),
|
||||||
type=dict(type='str', choices=['server', 'desktop', 'high_performance']),
|
type=dict(type='str', choices=['server', 'desktop', 'high_performance']),
|
||||||
operating_system=dict(type='str',
|
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',
|
|
||||||
]),
|
|
||||||
cd_iso=dict(type='str'),
|
cd_iso=dict(type='str'),
|
||||||
boot_devices=dict(type='list'),
|
boot_devices=dict(type='list'),
|
||||||
vnic_profile_mappings=dict(default=[], type='list'),
|
vnic_profile_mappings=dict(default=[], type='list'),
|
||||||
|
@ -1708,6 +1770,7 @@ def main():
|
||||||
nics=dict(type='list', default=[]),
|
nics=dict(type='list', default=[]),
|
||||||
cloud_init=dict(type='dict'),
|
cloud_init=dict(type='dict'),
|
||||||
cloud_init_nics=dict(type='list', default=[]),
|
cloud_init_nics=dict(type='list', default=[]),
|
||||||
|
cloud_init_persist=dict(type='bool', default=False, aliases=['sysprep_persist']),
|
||||||
sysprep=dict(type='dict'),
|
sysprep=dict(type='dict'),
|
||||||
host=dict(type='str'),
|
host=dict(type='str'),
|
||||||
clone=dict(type='bool', default=False),
|
clone=dict(type='bool', default=False),
|
||||||
|
@ -1729,11 +1792,12 @@ def main():
|
||||||
cpu_pinning=dict(type='list'),
|
cpu_pinning=dict(type='list'),
|
||||||
soundcard_enabled=dict(type='bool', default=None),
|
soundcard_enabled=dict(type='bool', default=None),
|
||||||
smartcard_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),
|
ballooning_enabled=dict(type='bool', default=None),
|
||||||
rng_device=dict(type='str'),
|
rng_device=dict(type='str'),
|
||||||
custom_properties=dict(type='list'),
|
custom_properties=dict(type='list'),
|
||||||
watchdog=dict(type='dict'),
|
watchdog=dict(type='dict'),
|
||||||
|
graphical_console=dict(type='dict'),
|
||||||
)
|
)
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
|
@ -1760,12 +1824,6 @@ def main():
|
||||||
if module.params['xen'] or module.params['kvm'] or module.params['vmware']:
|
if module.params['xen'] or module.params['kvm'] or module.params['vmware']:
|
||||||
vms_module.changed = import_vm(module, connection)
|
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,
|
# In case VM don't exist, wait for VM DOWN state,
|
||||||
# otherwise don't wait for any state, just update VM:
|
# otherwise don't wait for any state, just update VM:
|
||||||
ret = vms_module.create(
|
ret = vms_module.create(
|
||||||
|
@ -1774,11 +1832,11 @@ def main():
|
||||||
clone=module.params['clone'],
|
clone=module.params['clone'],
|
||||||
clone_permissions=module.params['clone_permissions'],
|
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:
|
# Run the VM if it was just created, else don't run it:
|
||||||
if state == 'running':
|
if state == 'running':
|
||||||
initialization = _get_initialization(sysprep, cloud_init, cloud_init_nics)
|
initialization = vms_module.get_initialization()
|
||||||
ret = vms_module.action(
|
ret = vms_module.action(
|
||||||
action='start',
|
action='start',
|
||||||
post_action=vms_module._post_start_action,
|
post_action=vms_module._post_start_action,
|
||||||
|
@ -1794,8 +1852,8 @@ def main():
|
||||||
),
|
),
|
||||||
wait_condition=lambda vm: vm.status == otypes.VmStatus.UP,
|
wait_condition=lambda vm: vm.status == otypes.VmStatus.UP,
|
||||||
# Start action kwargs:
|
# Start action kwargs:
|
||||||
use_cloud_init=cloud_init is not None or len(cloud_init_nics) > 0,
|
use_cloud_init=not module.params.get('cloud_init_persist') and module.params.get('cloud_init') is not None,
|
||||||
use_sysprep=sysprep is not None,
|
use_sysprep=not module.params.get('cloud_init_persist') and module.params.get('sysprep') is not None,
|
||||||
vm=otypes.Vm(
|
vm=otypes.Vm(
|
||||||
placement_policy=otypes.VmPlacementPolicy(
|
placement_policy=otypes.VmPlacementPolicy(
|
||||||
hosts=[otypes.Host(name=module.params['host'])]
|
hosts=[otypes.Host(name=module.params['host'])]
|
||||||
|
@ -1815,7 +1873,7 @@ def main():
|
||||||
module.params.get('initrd_path') or
|
module.params.get('initrd_path') or
|
||||||
module.params.get('kernel_path') or
|
module.params.get('kernel_path') or
|
||||||
module.params.get('host') or
|
module.params.get('host') or
|
||||||
initialization
|
initialization is not None and not module.params.get('cloud_init_persist')
|
||||||
) else None,
|
) else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1839,6 +1897,7 @@ def main():
|
||||||
clone=module.params['clone'],
|
clone=module.params['clone'],
|
||||||
clone_permissions=module.params['clone_permissions'],
|
clone_permissions=module.params['clone_permissions'],
|
||||||
)
|
)
|
||||||
|
vms_module.post_present(ret['id'])
|
||||||
if module.params['force']:
|
if module.params['force']:
|
||||||
ret = vms_module.action(
|
ret = vms_module.action(
|
||||||
action='stop',
|
action='stop',
|
||||||
|
@ -1860,6 +1919,7 @@ def main():
|
||||||
clone=module.params['clone'],
|
clone=module.params['clone'],
|
||||||
clone_permissions=module.params['clone_permissions'],
|
clone_permissions=module.params['clone_permissions'],
|
||||||
)
|
)
|
||||||
|
vms_module.post_present(ret['id'])
|
||||||
ret = vms_module.action(
|
ret = vms_module.action(
|
||||||
action='suspend',
|
action='suspend',
|
||||||
pre_action=vms_module._pre_suspend_action,
|
pre_action=vms_module._pre_suspend_action,
|
||||||
|
|
Loading…
Reference in a new issue