[oVirt] Update/Add functionalities for import storage domain (#26568)

* ovirt_templates: Update the argument spec of templates.

Add id of template since it is needed for register.

* ovirt_vms: Register unregistered VM.

Use register of VM with id instead of name since an
unregitered entity can be registered also without name attribute.

* ovirt_hosts: Add iscsidiscover to ovirt_hosts

Adding functionality of iscsidiscover to be used to discover iscsi
targets.

* ovirt_storage_domains: Add support for import block storage domain.

* Add functionality of partial import to unregistered VMs.

* Add functionality of partial import to unregistered Templates.

* ovirt_hosts: Add iscsilogin to ovirt hosts.

Add functionality of iscsi login to ovirt hosts to be used to connect to
iscsi targets and to be able to import iSCSI storage domain eventually.

* Add ovirt_storage_templates_facts

Adding fact module for storage templates.
The module should help with registering unregistered templates.

* Add ovirt_storage_vms_facts

Adding fact module for storage VMs.
The module should help with registering unregistered VMs.
pull/27113/head
maorlipchuk 7 years ago committed by Ryan Brown
parent 2f3d9566f9
commit 07feec30d3

@ -746,6 +746,17 @@ class BaseModule(object):
'diff': self._diff, 'diff': self._diff,
} }
def wait_for_import(self):
if self._module.params['wait']:
start = time.time()
timeout = self._module.params['timeout']
poll_interval = self._module.params['poll_interval']
while time.time() < start + timeout:
entity = self.search_entity()
if entity:
return entity
time.sleep(poll_interval)
def search_entity(self, search_params=None): def search_entity(self, search_params=None):
""" """
Always first try to search by `ID`, if ID isn't specified, Always first try to search by `ID`, if ID isn't specified,
@ -755,10 +766,10 @@ class BaseModule(object):
entity = None entity = None
if 'id' in self._module.params and self._module.params['id'] is not None: if 'id' in self._module.params and self._module.params['id'] is not None:
entity = search_by_attributes(self._service, id=self._module.params['id']) entity = get_entity(self._service.service(self._module.params['id']))
elif search_params is not None: elif search_params is not None:
entity = search_by_attributes(self._service, **search_params) entity = search_by_attributes(self._service, **search_params)
elif 'name' in self._module.params and self._module.params['name'] is not None: elif self._module.params.get('name') is not None:
entity = search_by_attributes(self._service, name=self._module.params['name']) entity = search_by_attributes(self._service, name=self._module.params['name'])
return entity return entity

@ -40,9 +40,10 @@ options:
state: state:
description: description:
- "State which should a host to be in after successful completion." - "State which should a host to be in after successful completion."
- "I(iscsilogin) and I(iscsidiscover) are supported since version 2.4."
choices: [ choices: [
'present', 'absent', 'maintenance', 'upgraded', 'started', 'present', 'absent', 'maintenance', 'upgraded', 'started',
'restarted', 'stopped', 'reinstalled' 'restarted', 'stopped', 'reinstalled', 'iscsidiscover', 'iscsilogin'
] ]
default: present default: present
comment: comment:
@ -108,6 +109,13 @@ options:
- "Enable or disable power management of the host." - "Enable or disable power management of the host."
- "For more comprehensive setup of PM use C(ovirt_host_pm) module." - "For more comprehensive setup of PM use C(ovirt_host_pm) module."
version_added: 2.4 version_added: 2.4
iscsi:
description:
- "If C(state) is I(iscsidiscover) it means that the iscsi attribute is being
used to discover targets"
- "If C(state) is I(iscsilogin) it means that the iscsi attribute is being
used to login to the specified targets passed as part of the iscsi attribute"
version_added: "2.4"
extends_documentation_fragment: ovirt extends_documentation_fragment: ovirt
''' '''
@ -158,6 +166,29 @@ EXAMPLES = '''
state: upgraded state: upgraded
name: myhost name: myhost
# discover iscsi targets
- ovirt_hosts:
state: iscsidiscover
name: myhost
iscsi:
username: iscsi_user
password: secret
address: 10.34.61.145
port: 3260
# login to iscsi targets
- ovirt_hosts:
state: iscsilogin
name: myhost
iscsi:
username: iscsi_user
password: secret
address: 10.34.61.145
target: "iqn.2015-07.com.mlipchuk2.redhat:444"
port: 3260
# Reinstall host using public key # Reinstall host using public key
- ovirt_hosts: - ovirt_hosts:
state: reinstalled state: reinstalled
@ -182,6 +213,10 @@ host:
at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host." at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host."
returned: On success if host is found. returned: On success if host is found.
type: dict type: dict
iscsi_targets:
description: "List of host iscsi targets"
returned: On success if host is found and state is iscsidiscover.
type: list
''' '''
import time import time
@ -200,6 +235,7 @@ from ansible.module_utils.ovirt import (
check_sdk, check_sdk,
create_connection, create_connection,
equal, equal,
get_id_by_name,
ovirt_full_argument_spec, ovirt_full_argument_spec,
wait, wait,
) )
@ -327,7 +363,7 @@ def main():
state=dict( state=dict(
choices=[ choices=[
'present', 'absent', 'maintenance', 'upgraded', 'started', 'present', 'absent', 'maintenance', 'upgraded', 'started',
'restarted', 'stopped', 'reinstalled', 'restarted', 'stopped', 'reinstalled', 'iscsidiscover', 'iscsilogin'
], ],
default='present', default='present',
), ),
@ -346,10 +382,15 @@ def main():
kernel_params=dict(default=None, type='list'), kernel_params=dict(default=None, type='list'),
hosted_engine=dict(default=None, choices=['deploy', 'undeploy']), hosted_engine=dict(default=None, choices=['deploy', 'undeploy']),
power_management_enabled=dict(default=None, type='bool'), power_management_enabled=dict(default=None, type='bool'),
iscsi=dict(default=None, type='dict'),
) )
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,
required_if=[
['state', 'iscsidiscover', ['iscsi']],
['state', 'iscsilogin', ['iscsi']]
]
) )
check_sdk(module) check_sdk(module)
@ -396,6 +437,33 @@ def main():
post_action=lambda h: time.sleep(module.params['poll_interval']), post_action=lambda h: time.sleep(module.params['poll_interval']),
fail_condition=failed_state, fail_condition=failed_state,
) )
elif state == 'iscsidiscover':
host_id = get_id_by_name(hosts_service, module.params['name'])
iscsi_targets = hosts_service.service(host_id).iscsi_discover(
iscsi=otypes.IscsiDetails(
port=int(module.params['iscsi']['port']) if module.params['iscsi']['port'].isdigit() else None,
username=module.params['iscsi']['username'],
password=module.params['iscsi']['password'],
address=module.params['iscsi']['address'],
),
)
ret = {
'changed': False,
'id': host_id,
'iscsi_targets': iscsi_targets,
}
elif state == 'iscsilogin':
host_id = get_id_by_name(hosts_service, module.params['name'])
ret = hosts_module.action(
action='iscsi_login',
iscsi=otypes.IscsiDetails(
port=int(module.params['iscsi']['port']) if module.params['iscsi']['port'].isdigit() else None,
username=module.params['iscsi']['username'],
password=module.params['iscsi']['password'],
address=module.params['iscsi']['address'],
target=module.params['iscsi']['target'],
),
)
elif state == 'started': elif state == 'started':
ret = hosts_module.action( ret = hosts_module.action(
action='fence', action='fence',

@ -33,12 +33,17 @@ author: "Ondra Machacek (@machacekondra)"
description: description:
- "Module to manage storage domains in oVirt/RHV" - "Module to manage storage domains in oVirt/RHV"
options: options:
id:
description:
- "Id of the storage domain to be imported."
version_added: "2.4"
name: name:
description: description:
- "Name of the storage domain to manage." - "Name of the storage domain to manage."
state: state:
description: description:
- "Should the storage domain be present/absent/maintenance/unattached" - "Should the storage domain be present/absent/maintenance/unattached/imported"
- "I(imported) is supported since version 2.4."
choices: ['present', 'absent', 'maintenance', 'unattached'] choices: ['present', 'absent', 'maintenance', 'unattached']
default: present default: present
description: description:
@ -256,6 +261,8 @@ class StorageDomainModule(BaseModule):
name=self._module.params['name'], name=self._module.params['name'],
description=self._module.params['description'], description=self._module.params['description'],
comment=self._module.params['comment'], comment=self._module.params['comment'],
import_=True if (self._module.params['state'] == 'imported' and storage_type in ['iscsi', 'fcp']) else None,
id=self._module.params['id'] if (self._module.params['state'] == 'imported' and storage_type in ['iscsi', 'fcp']) else None,
type=otypes.StorageDomainType( type=otypes.StorageDomainType(
self._module.params['domain_function'] self._module.params['domain_function']
), ),
@ -423,9 +430,10 @@ def control_state(sd_module):
def main(): def main():
argument_spec = ovirt_full_argument_spec( argument_spec = ovirt_full_argument_spec(
state=dict( state=dict(
choices=['present', 'absent', 'maintenance', 'unattached'], choices=['present', 'absent', 'maintenance', 'unattached', 'imported'],
default='present', default='present',
), ),
id=dict(default=None),
name=dict(required=True), name=dict(required=True),
description=dict(default=None), description=dict(default=None),
comment=dict(default=None), comment=dict(default=None),
@ -465,7 +473,7 @@ def main():
format=module.params['format'], format=module.params['format'],
host=module.params['host'], host=module.params['host'],
) )
elif state == 'present': elif state == 'present' or state == 'imported':
sd_id = storage_domains_module.create()['id'] sd_id = storage_domains_module.create()['id']
storage_domains_module.post_create_check(sd_id) storage_domains_module.post_create_check(sd_id)
ret = storage_domains_module.action( ret = storage_domains_module.action(

@ -0,0 +1,123 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ovirt_storage_templates_facts
short_description: Retrieve facts about one or more oVirt/RHV templates relate to a storage domain.
author: "Maor Lipchuk"
version_added: "2.4"
description:
- "Retrieve facts about one or more oVirt/RHV templates relate to a storage domain."
notes:
- "This module creates a new top-level C(ovirt_storage_templates) fact, which
contains a list of templates."
options:
unregistered:
description:
- "Flag which indicates whether to get unregistered templates which contain one or more
disks which reside on a storage domain or diskless templates."
extends_documentation_fragment: ovirt_facts
'''
EXAMPLES = '''
# Examples don't contain auth parameter for simplicity,
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all Templates which relate to a storage domain and
# are unregistered:
- ovirt_storage_templates_facts:
unregistered=True
- debug:
var: ovirt_storage_templates
'''
RETURN = '''
ovirt_storage_templates:
description: "List of dictionaries describing the Templates. Template attribues are mapped to dictionary keys,
all Templates attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/template."
returned: On success.
type: list
'''
import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ovirt import (
check_sdk,
create_connection,
get_dict_of_struct,
ovirt_facts_full_argument_spec,
get_id_by_name
)
def main():
argument_spec = ovirt_facts_full_argument_spec(
all_content=dict(default=False, type='bool'),
case_sensitive=dict(default=True, type='bool'),
storage_domain=dict(default=None),
max=dict(default=None, type='int'),
unregistered=dict(default=False, type='bool'),
)
module = AnsibleModule(argument_spec)
check_sdk(module)
try:
auth = module.params.pop('auth')
connection = create_connection(auth)
storage_domains_service = connection.system_service().storage_domains_service()
sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain'])
storage_domain_service = storage_domains_service.storage_domain_service(sd_id)
templates_service = storage_domain_service.templates_service()
# Find the the unregistered Template we want to register:
if module.params.get('unregistered'):
templates = templates_service.list(unregistered=True)
else:
templates = templates_service.list()
module.exit_json(
changed=False,
ansible_facts=dict(
ovirt_storage_templates=[
get_dict_of_struct(
struct=c,
connection=connection,
fetch_nested=module.params.get('fetch_nested'),
attributes=module.params.get('nested_attributes'),
) for c in templates
],
),
)
except Exception as e:
module.fail_json(msg=str(e), exception=traceback.format_exc())
finally:
connection.close(logout=auth.get('token') is None)
if __name__ == '__main__':
main()

@ -0,0 +1,122 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ovirt_storage_vms_facts
short_description: Retrieve facts about one or more oVirt/RHV virtual machines relate to a storage domain.
author: "Maor Lipchuk"
version_added: "2.4"
description:
- "Retrieve facts about one or more oVirt/RHV virtual machines relate to a storage domain."
notes:
- "This module creates a new top-level C(ovirt_storage_vms) fact, which
contains a list of virtual machines."
options:
unregistered:
description:
- "Flag which indicates whether to get unregistered virtual machines which contain one or more
disks which reside on a storage domain or diskless virtual machines."
extends_documentation_fragment: ovirt_facts
'''
EXAMPLES = '''
# Examples don't contain auth parameter for simplicity,
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all VMs which relate to a storage domain and
# are unregistered:
- ovirt_vms_facts:
unregistered=True
- debug:
var: ovirt_storage_vms
'''
RETURN = '''
ovirt_storage_vms:
description: "List of dictionaries describing the VMs. VM attribues are mapped to dictionary keys,
all VMs attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm."
returned: On success.
type: list
'''
import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ovirt import (
check_sdk,
create_connection,
get_dict_of_struct,
ovirt_facts_full_argument_spec,
get_id_by_name
)
def main():
argument_spec = ovirt_facts_full_argument_spec(
all_content=dict(default=False, type='bool'),
case_sensitive=dict(default=True, type='bool'),
storage_domain=dict(default=None),
max=dict(default=None, type='int'),
unregistered=dict(default=False, type='bool'),
)
module = AnsibleModule(argument_spec)
check_sdk(module)
try:
auth = module.params.pop('auth')
connection = create_connection(auth)
storage_domains_service = connection.system_service().storage_domains_service()
sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain'])
storage_domain_service = storage_domains_service.storage_domain_service(sd_id)
vms_service = storage_domain_service.vms_service()
# Find the the unregistered VM we want to register:
if module.params.get('unregistered'):
vms = vms_service.list(unregistered=True)
else:
vms = vms_service.list()
module.exit_json(
changed=False,
ansible_facts=dict(
ovirt_storage_vms=[
get_dict_of_struct(
struct=c,
connection=connection,
fetch_nested=module.params.get('fetch_nested'),
attributes=module.params.get('nested_attributes'),
) for c in vms
],
),
)
except Exception as e:
module.fail_json(msg=str(e), exception=traceback.format_exc())
finally:
connection.close(logout=auth.get('token') is None)
if __name__ == '__main__':
main()

@ -36,13 +36,16 @@ options:
name: name:
description: description:
- "Name of the template to manage." - "Name of the template to manage."
required: true id:
description:
- "ID of the template to be registered."
version_added: "2.4"
state: state:
description: description:
- "Should the template be present/absent/exported/imported/registered. - "Should the template be present/absent/exported/imported/registered.
When C(state) is I(registered) and the unregistered template's name When C(state) is I(registered) and the unregistered template's name
belongs to an already registered in engine template then we fail belongs to an already registered in engine template in the same DC
to register the unregistered template." then we fail to register the unregistered template."
choices: ['present', 'absent', 'exported', 'imported', 'registered'] choices: ['present', 'absent', 'exported', 'imported', 'registered']
default: present default: present
vm: vm:
@ -57,6 +60,10 @@ options:
cluster: cluster:
description: description:
- "Name of the cluster, where template should be created/imported." - "Name of the cluster, where template should be created/imported."
allow_partial_import:
description:
- "Boolean indication whether to allow partial registration of a template when C(state) is registered."
version_added: "2.4"
exclusive: exclusive:
description: description:
- "When C(state) is I(exported) this parameter indicates if the existing templates with the - "When C(state) is I(exported) this parameter indicates if the existing templates with the
@ -120,9 +127,24 @@ EXAMPLES = '''
# Register template # Register template
- ovirt_templates: - ovirt_templates:
state: registered state: registered
storage_domain: mystorage
cluster: mycluster
name: mytemplate name: mytemplate
# Register template using id
- ovirt_templates:
state: registered
storage_domain: mystorage
cluster: mycluster
id: 1111-1111-1111-1111
# Register template, allowing partial import
- ovirt_templates:
state: registered
storage_domain: mystorage storage_domain: mystorage
allow_partial_import: "True"
cluster: mycluster cluster: mycluster
id: 1111-1111-1111-1111
# Import image from Glance s a template # Import image from Glance s a template
- ovirt_templates: - ovirt_templates:
@ -216,28 +238,18 @@ class TemplatesModule(BaseModule):
self._service = self._connection.system_service().templates_service() self._service = self._connection.system_service().templates_service()
def wait_for_import(module, templates_service):
if module.params['wait']:
start = time.time()
timeout = module.params['timeout']
poll_interval = module.params['poll_interval']
while time.time() < start + timeout:
template = search_by_name(templates_service, module.params['name'])
if template:
return template
time.sleep(poll_interval)
def main(): def main():
argument_spec = ovirt_full_argument_spec( argument_spec = ovirt_full_argument_spec(
state=dict( state=dict(
choices=['present', 'absent', 'exported', 'imported', 'registered'], choices=['present', 'absent', 'exported', 'imported', 'registered'],
default='present', default='present',
), ),
name=dict(default=None, required=True), id=dict(default=None),
name=dict(default=None),
vm=dict(default=None), vm=dict(default=None),
description=dict(default=None), description=dict(default=None),
cluster=dict(default=None), cluster=dict(default=None),
allow_partial_import=dict(default=None, type='bool'),
cpu_profile=dict(default=None), cpu_profile=dict(default=None),
disks=dict(default=[], type='list'), disks=dict(default=[], type='list'),
clone_permissions=dict(type='bool'), clone_permissions=dict(type='bool'),
@ -251,6 +263,7 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,
required_one_of=[['id', 'name']],
) )
check_sdk(module) check_sdk(module)
@ -328,7 +341,7 @@ def main():
) if module.params['cluster'] else None, ) if module.params['cluster'] else None,
**kwargs **kwargs
) )
template = wait_for_import(module, templates_service) template = templates_module.wait_for_import()
ret = { ret = {
'changed': True, 'changed': True,
'id': template.id, 'id': template.id,
@ -344,32 +357,32 @@ def main():
# Find the unregistered Template we want to register: # Find the unregistered Template we want to register:
templates = templates_service.list(unregistered=True) templates = templates_service.list(unregistered=True)
template = next( template = next(
(t for t in templates if t.name == module.params['name']), (t for t in templates if (t.id == module.params['id'] or t.name == module.params['name'])),
None None
) )
changed = False changed = False
if template is None: if template is None:
# Test if template is registered:
template = templates_module.search_entity() template = templates_module.search_entity()
if template is None: if template is None:
raise ValueError( raise ValueError(
"Template with name '%s' wasn't found." % module.params['name'] "Template '%s(%s)' wasn't found." % (module.params['name'], module.params['id'])
) )
else: else:
# Register the template into the system:
changed = True changed = True
template_service = templates_service.template_service(template.id) template_service = templates_service.template_service(template.id)
# Register the template into the system:
template_service.register( template_service.register(
allow_partial_import=module.params['allow_partial_import'],
cluster=otypes.Cluster( cluster=otypes.Cluster(
name=module.params['cluster'] name=module.params['cluster']
) if module.params['cluster'] else None, ) if module.params['cluster'] else None
template=otypes.Template(
name=module.params['name'],
),
) )
if module.params['wait']:
template = wait_for_import(module, templates_service)
if module.params['wait']:
template = templates_module.wait_for_import()
else:
# Fetch template to initialize return.
template = template_service.get()
ret = { ret = {
'changed': changed, 'changed': changed,
'id': template.id, 'id': template.id,

@ -43,15 +43,23 @@ options:
- "ID of the Virtual Machine to manage." - "ID of the Virtual Machine to manage."
state: state:
description: description:
- "Should the Virtual Machine be running/stopped/present/absent/suspended/next_run." - "Should the Virtual Machine be running/stopped/present/absent/suspended/next_run/registered.
When C(state) is I(registered) and the unregistered VM's name
belongs to an already registered in engine VM in the same DC
then we fail to register the unregistered template."
- "I(present) and I(running) are equal states." - "I(present) and I(running) are equal states."
- "I(next_run) state updates the VM and if the VM has next run configuration it will be rebooted." - "I(next_run) state updates the VM and if the VM has next run configuration it will be rebooted."
- "Please check I(notes) to more detailed description of states." - "Please check I(notes) to more detailed description of states."
choices: ['running', 'stopped', 'present', 'absent', 'suspended', 'next_run'] - "I(registered) is supported since 2.4"
choices: ['running', 'stopped', 'present', 'absent', 'suspended', 'next_run', 'registered']
default: present default: present
cluster: cluster:
description: description:
- "Name of the cluster, where Virtual Machine should be created. Required if creating VM." - "Name of the cluster, where Virtual Machine should be created. Required if creating VM."
allow_partial_import:
description:
- "Boolean indication whether to allow partial registration of Virtual Machine when C(state) is registered."
version_added: "2.4"
template: template:
description: description:
- "Name of the template, which should be used to create Virtual Machine. Required if creating VM." - "Name of the template, which should be used to create Virtual Machine. Required if creating VM."
@ -354,6 +362,28 @@ ovirt_vms:
name: myvm name: myvm
template: rhel7_template template: rhel7_template
# Register VM
ovirt_vms:
state: registered
storage_domain: mystorage
cluster: mycluster
name: myvm
# Register VM using id
ovirt_vms:
state: registered
storage_domain: mystorage
cluster: mycluster
id: 1111-1111-1111-1111
# Register VM, allowing partial import
ovirt_vms:
state: registered
storage_domain: mystorage
allow_partial_import: "True"
cluster: mycluster
id: 1111-1111-1111-1111
# Creates a stateless VM which will always use latest template version: # Creates a stateless VM which will always use latest template version:
ovirt_vms: ovirt_vms:
name: myvm name: myvm
@ -522,7 +552,6 @@ vm:
returned: On success if VM is found. returned: On success if VM is found.
type: dict type: dict
''' '''
import traceback import traceback
try: try:
@ -538,6 +567,7 @@ from ansible.module_utils.ovirt import (
convert_to_bytes, convert_to_bytes,
create_connection, create_connection,
equal, equal,
get_dict_of_struct,
get_entity, get_entity,
get_link_name, get_link_name,
get_id_by_name, get_id_by_name,
@ -1053,16 +1083,16 @@ def control_state(vm, vms_service, module):
condition=lambda vm: vm.status in [otypes.VmStatus.DOWN, otypes.VmStatus.UP], condition=lambda vm: vm.status in [otypes.VmStatus.DOWN, otypes.VmStatus.UP],
) )
def main(): def main():
argument_spec = ovirt_full_argument_spec( argument_spec = ovirt_full_argument_spec(
state=dict( state=dict(
choices=['running', 'stopped', 'present', 'absent', 'suspended', 'next_run'], choices=['running', 'stopped', 'present', 'absent', 'suspended', 'next_run', 'registered'],
default='present', default='present',
), ),
name=dict(default=None), name=dict(default=None),
id=dict(default=None), id=dict(default=None),
cluster=dict(default=None), cluster=dict(default=None),
allow_partial_import=dict(default=None, type='bool'),
template=dict(default=None), template=dict(default=None),
template_version=dict(default=None, type='int'), template_version=dict(default=None, type='int'),
use_latest_template_version=dict(default=None, type='bool'), use_latest_template_version=dict(default=None, type='bool'),
@ -1119,6 +1149,7 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,
required_one_of=[['id', 'name']],
) )
check_sdk(module) check_sdk(module)
check_params(module) check_params(module)
@ -1243,6 +1274,48 @@ def main():
) )
elif state == 'absent': elif state == 'absent':
ret = vms_module.remove() ret = vms_module.remove()
elif state == 'registered':
storage_domains_service = connection.system_service().storage_domains_service()
# Find the storage domain with unregistered VM:
sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain'])
storage_domain_service = storage_domains_service.storage_domain_service(sd_id)
vms_service = storage_domain_service.vms_service()
# Find the the unregistered VM we want to register:
vms = vms_service.list(unregistered=True)
vm = next(
(vm for vm in vms if (vm.id == module.params['id'] or vm.name == module.params['name'])),
None
)
changed = False
if vm is None:
vm = vms_module.search_entity()
if vm is None:
raise ValueError(
"VM '%s(%s)' wasn't found." % (module.params['name'], module.params['id'])
)
else:
# Register the vm into the system:
changed = True
vm_service = vms_service.vm_service(vm.id)
vm_service.register(
allow_partial_import=module.params['allow_partial_import'],
cluster=otypes.Cluster(
name=module.params['cluster']
) if module.params['cluster'] else None
)
if module.params['wait']:
vm = vms_module.wait_for_import()
else:
# Fetch vm to initialize return.
vm = vm_service.get()
ret = {
'changed': changed,
'id': vm.id,
'vm': get_dict_of_struct(vm)
}
module.exit_json(**ret) module.exit_json(**ret)
except Exception as e: except Exception as e:

Loading…
Cancel
Save