community.general/lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py
Nijin Ashok 449fdf44b9 ovirt_storage_connection: Fix issue in detaching the connection (#50005)
Currently deleting the storage connection just tries to delete the
connection but it doesn't detach the connection from storage domain.
The patch first tries to detach the connection from storage domain
before attempting to delete the same if the storage domain parameter
is provided.
2019-01-08 06:53:20 -05:00

283 lines
9.6 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ovirt_storage_connection
short_description: Module to manage storage connections in oVirt
version_added: "2.4"
author: "Ondra Machacek (@machacekondra)"
description:
- "Module to manage storage connections in oVirt"
options:
id:
description:
- "Id of the storage connection to manage."
state:
description:
- "Should the storage connection be present or absent."
choices: ['present', 'absent']
default: present
storage:
description:
- "Name of the storage domain to be used with storage connection."
address:
description:
- "Address of the storage server. E.g.: myserver.mydomain.com"
path:
description:
- "Path of the mount point of the storage. E.g.: /path/to/my/data"
nfs_version:
description:
- "NFS version. One of: I(auto), I(v3), I(v4) or I(v4_1)."
nfs_timeout:
description:
- "The time in tenths of a second to wait for a response before retrying NFS requests. Range 0 to 65535."
nfs_retrans:
description:
- "The number of times to retry a request before attempting further recovery actions. Range 0 to 65535."
mount_options:
description:
- "Option which will be passed when mounting storage."
password:
description:
- "A CHAP password for logging into a target."
username:
description:
- "A CHAP username for logging into a target."
port:
description:
- "Port of the iSCSI storage server."
target:
description:
- "The target IQN for the storage device."
type:
description:
- "Storage type. For example: I(nfs), I(iscsi), etc."
vfs_type:
description:
- "Virtual File System type."
force:
description:
- "This parameter is relevant only when updating a connection."
- "If I(true) the storage domain don't have to be in I(MAINTENANCE)
state, so the storage connection is updated."
type: bool
extends_documentation_fragment: ovirt
'''
EXAMPLES = '''
# Examples don't contain auth parameter for simplicity,
# look at ovirt_auth module to see how to reuse authentication:
# Add new storage connection:
- ovirt_storage_connection:
storage: myiscsi
address: 10.34.63.199
target: iqn.2016-08-09.domain-01:nickname
port: 3260
type: iscsi
# Update the existing storage connection address:
- ovirt_storage_connection:
id: 26915c96-92ff-47e5-9e77-b581db2f2d36
address: 10.34.63.204
force: true
# Remove storage connection:
- ovirt_storage_connection:
id: 26915c96-92ff-47e5-9e77-b581db2f2d36
'''
RETURN = '''
id:
description: ID of the storage connection which is managed
returned: On success if storage connection is found.
type: str
sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c
storage_connection:
description: "Dictionary of all the storage connection attributes. Storage connection attributes can be found on your oVirt instance
at following url: https://ovirt.example.com/ovirt-engine/api/model#types/storage_connection."
returned: On success if storage connection is found.
type: dict
'''
try:
import ovirtsdk4.types as otypes
except ImportError:
pass
import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ovirt import (
BaseModule,
check_sdk,
create_connection,
equal,
ovirt_full_argument_spec,
search_by_name,
)
class StorageConnectionModule(BaseModule):
def build_entity(self):
return otypes.StorageConnection(
address=self.param('address'),
path=self.param('path'),
nfs_version=self.param('nfs_version'),
nfs_timeo=self.param('nfs_timeout'),
nfs_retrans=self.param('nfs_retrans'),
mount_options=self.param('mount_options'),
password=self.param('password'),
username=self.param('username'),
port=self.param('port'),
target=self.param('target'),
type=otypes.StorageType(
self.param('type')
) if self.param('type') is not None else None,
vfs_type=self.param('vfs_type'),
)
def _get_storage_domain_service(self):
sds_service = self._connection.system_service().storage_domains_service()
sd = search_by_name(sds_service, self.param('storage'))
if sd is None:
raise Exception(
"Storage '%s' was not found." % self.param('storage')
)
return sd, sds_service.storage_domain_service(sd.id)
def post_present(self, entity_id):
if self.param('storage'):
sd, sd_service = self._get_storage_domain_service()
if entity_id not in [
sd_conn.id for sd_conn in self._connection.follow_link(sd.storage_connections)
]:
scs_service = sd_service.storage_connections_service()
if not self._module.check_mode:
scs_service.add(
connection=otypes.StorageConnection(
id=entity_id,
),
)
self.changed = True
def pre_remove(self, entity_id):
if self.param('storage'):
sd, sd_service = self._get_storage_domain_service()
if entity_id in [
sd_conn.id for sd_conn in self._connection.follow_link(sd.storage_connections)
]:
scs_service = sd_service.storage_connections_service()
sc_service = scs_service.connection_service(entity_id)
if not self._module.check_mode:
sc_service.remove()
self.changed = True
def update_check(self, entity):
return (
equal(self.param('address'), entity.address) and
equal(self.param('path'), entity.path) and
equal(self.param('nfs_version'), entity.nfs_version) and
equal(self.param('nfs_timeout'), entity.nfs_timeo) and
equal(self.param('nfs_retrans'), entity.nfs_retrans) and
equal(self.param('mount_options'), entity.mount_options) and
equal(self.param('username'), entity.username) and
equal(self.param('port'), entity.port) and
equal(self.param('target'), entity.target) and
equal(self.param('type'), str(entity.type)) and
equal(self.param('vfs_type'), entity.vfs_type)
)
def find_sc_by_attributes(module, storage_connections_service):
for sd_conn in [
sc for sc in storage_connections_service.list()
if str(sc.type) == module.params['type']
]:
sd_conn_type = str(sd_conn.type)
if sd_conn_type in ['nfs', 'posixfs', 'glusterfs', 'localfs']:
if (
module.params['address'] == sd_conn.address and
module.params['path'] == sd_conn.path
):
return sd_conn
elif sd_conn_type in ['iscsi', 'fcp']:
if (
module.params['address'] == sd_conn.address and
module.params['target'] == sd_conn.target
):
return sd_conn
def main():
argument_spec = ovirt_full_argument_spec(
state=dict(
choices=['present', 'absent'],
default='present',
),
id=dict(default=None),
address=dict(default=None),
path=dict(default=None),
nfs_version=dict(default=None),
nfs_timeout=dict(default=None, type='int'),
nfs_retrans=dict(default=None, type='int'),
mount_options=dict(default=None),
password=dict(default=None, no_log=True),
username=dict(default=None),
port=dict(default=None, type='int'),
target=dict(default=None),
type=dict(default=None),
vfs_type=dict(default=None),
force=dict(type='bool', default=False),
storage=dict(default=None),
)
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
)
check_sdk(module)
try:
auth = module.params.pop('auth')
connection = create_connection(auth)
storage_connections_service = connection.system_service().storage_connections_service()
storage_connection_module = StorageConnectionModule(
connection=connection,
module=module,
service=storage_connections_service,
)
entity = None
if module.params['id'] is None:
entity = find_sc_by_attributes(module, storage_connections_service)
state = module.params['state']
if state == 'present':
ret = storage_connection_module.create(
entity=entity,
update_params={'force': True},
)
storage_connection_module.post_present(ret['id'])
elif state == 'absent':
storage_connection_module.pre_remove(module.params['id'])
ret = storage_connection_module.remove(entity=entity)
module.exit_json(**ret)
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()