Add ipadm_addr module (#19411)

* Add ipadm_addr module

* Add ANSIBLE_METADATA
Document return values
Make imports explicit
Use native YAML syntax in EXAMPLES

* Fix version to 2.3
pull/20066/head
Adam Števko 8 years ago committed by Peter Sprygada
parent ad9c25a54f
commit ebd7e03425

@ -0,0 +1,411 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2016, Adam Števko <adam.stevko@gmail.com>
#
# 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 = {'status': ['preview'],
'supported_by': 'community',
'version': '1.0'}
DOCUMENTATION = '''
---
module: ipadm_addr
short_description: Manage IP addresses on an interface.
description:
- Create/delete static/dynamic IP addresses on network interfaces on Solaris/illumos systems.
- Up/down static/dynamic IP addresses on network interfaces on Solaris/illumos systems.
- Manage IPv6 link-local addresses on network interfaces on Solaris/illumos systems.
version_added: "2.3"
author: Adam Števko (@xen0l)
options:
address:
description:
- Specifiies an IP address to configure in CIDR notation.
required: false
aliases: [ "addr" ]
addrtype:
description:
- Specifiies a type of IP address to configure.
required: false
default: static
choices: [ 'static', 'dhcp', 'addrconf' ]
addrobj:
description:
- Specifies an unique IP address on the system.
required: true
temporary:
description:
- Specifies that the configured IP address is temporary. Temporary
IP addresses do not persist across reboots.
required: false
default: false
wait:
description:
- Specifies the time in seconds we wait for obtaining address via DHCP.
required: false
default: 60
state:
description:
- Create/delete/enable/disable an IP address on the network interface.
required: false
default: present
choices: [ 'absent', 'present', 'up', 'down', 'enabled', 'disabled', 'refreshed' ]
'''
EXAMPLES = '''
name: Configure IP address 10.0.0.1 on e1000g0
ipadm_addr: addr=10.0.0.1/32 addrobj=e1000g0/v4 state=present
name: Delete addrobj
ipadm_addr: addrobj=e1000g0/v4 state=absent
name: Configure link-local IPv6 address
ipadm_addr: addtype=addrconf addrobj=vnic0/v6
name: Configure address via DHCP and wait 180 seconds for address obtaining
ipadm_addr: addrobj=vnic0/dhcp addrtype=dhcp wait=180
'''
RETURN = '''
addrobj:
description: address object name
returned: always
type: string
sample: bge0/v4
state:
description: state of the target
returned: always
type: string
sample: present
temporary:
description: specifies if operation will persist across reboots
returned: always
type: boolean
sample: True
addrtype:
description: address type
returned: always
type: string
sample: static
address:
description: IP address
returned: only if addrtype is 'static'
type: string
sample: 1.3.3.7/32
wait:
description: time we wait for DHCP
returned: only if addrtype is 'dhcp'
type: string
sample: 10
'''
import socket
from ansible.module_utils.basic import AnsibleModule
SUPPORTED_TYPES = ['static', 'addrconf', 'dhcp']
class Addr(object):
def __init__(self, module):
self.module = module
self.address = module.params['address']
self.addrtype = module.params['addrtype']
self.addrobj = module.params['addrobj']
self.temporary = module.params['temporary']
self.state = module.params['state']
self.wait = module.params['wait']
def is_cidr_notation(self):
return self.address.count('/') == 1
def is_valid_address(self):
ip_address = self.address.split('/')[0]
try:
if len(ip_address.split('.')) == 4:
socket.inet_pton(socket.AF_INET, ip_address)
else:
socket.inet_pton(socket.AF_INET6, ip_address)
except socket.error:
return False
return True
def is_dhcp(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('show-addr')
cmd.append('-p')
cmd.append('-o')
cmd.append('type')
cmd.append(self.addrobj)
(rc, out, err) = self.module.run_command(cmd)
if rc == 0:
if out.rstrip() != 'dhcp':
return False
return True
else:
self.module.fail_json(msg='Wrong addrtype %s for addrobj "%s": %s' % (out, self.addrobj, err),
rc=rc,
stderr=err)
def addrobj_exists(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('show-addr')
cmd.append(self.addrobj)
(rc, _, _) = self.module.run_command(cmd)
if rc == 0:
return True
else:
return False
def delete_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('delete-addr')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def create_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('create-addr')
cmd.append('-T')
cmd.append(self.addrtype)
if self.temporary:
cmd.append('-t')
if self.addrtype == 'static':
cmd.append('-a')
cmd.append(self.address)
if self.addrtype == 'dhcp' and self.wait:
cmd.append('-w')
cmd.append(self.wait)
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def up_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('up-addr')
if self.temporary:
cmd.append('-t')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def down_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('down-addr')
if self.temporary:
cmd.append('-t')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def enable_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('enable-addr')
cmd.append('-t')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def disable_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('disable-addr')
cmd.append('-t')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def refresh_addr(self):
cmd = [self.module.get_bin_path('ipadm')]
cmd.append('refresh-addr')
cmd.append(self.addrobj)
return self.module.run_command(cmd)
def main():
module = AnsibleModule(
argument_spec=dict(
address=dict(aliases=['addr']),
addrtype=dict(default='static', choices=SUPPORTED_TYPES),
addrobj=dict(required=True),
temporary=dict(default=False, type='bool'),
state=dict(
default='present', choices=['absent', 'present', 'up', 'down', 'enabled', 'disabled', 'refreshed']),
wait=dict(default=60),
),
mutually_exclusive=[
('address', 'wait'),
],
supports_check_mode=True
)
addr = Addr(module)
rc = None
out = ''
err = ''
result = {}
result['addrobj'] = addr.addrobj
result['state'] = addr.state
result['temporary'] = addr.temporary
result['addrtype'] = addr.addrtype
if addr.addrtype == 'static' and addr.address:
if addr.is_cidr_notation() and addr.is_valid_address():
result['address'] = addr.address
else:
module.fail_json(msg='Invalid IP address: %s' % addr.address)
if addr.addrtype == 'dhcp' and addr.wait:
result['wait'] = addr.wait
if addr.state == 'absent':
if addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.delete_addr()
if rc != 0:
module.fail_json(msg='Error while deleting addrobj: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
elif addr.state == 'present':
if not addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.create_addr()
if rc != 0:
module.fail_json(msg='Error while configuring IP address: "%s"' % err,
addrobj=addr.addrobj,
addr=addr.address,
stderr=err,
rc=rc)
elif addr.state == 'up':
if addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.up_addr()
if rc != 0:
module.fail_json(msg='Error while bringing IP address up: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
elif addr.state == 'down':
if addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.down_addr()
if rc != 0:
module.fail_json(msg='Error while bringing IP address down: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
elif addr.state == 'refreshed':
if addr.addrobj_exists():
if addr.is_dhcp():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.refresh_addr()
if rc != 0:
module.fail_json(msg='Error while refreshing IP address: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
else:
module.fail_json(msg='state "refreshed" cannot be used with "%s" addrtype' % addr.addrtype,
addrobj=addr.addrobj,
stderr=err,
rc=1)
elif addr.state == 'enabled':
if addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.enable_addr()
if rc != 0:
module.fail_json(msg='Error while enabling IP address: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
elif addr.state == 'disabled':
if addr.addrobj_exists():
if module.check_mode:
module.exit_json(changed=True)
(rc, out, err) = addr.disable_addr()
if rc != 0:
module.fail_json(msg='Error while disabling IP address: "%s"' % err,
addrobj=addr.addrobj,
stderr=err,
rc=rc)
if rc is None:
result['changed'] = False
else:
result['changed'] = True
if out:
result['stdout'] = out
if err:
result['stderr'] = err
module.exit_json(**result)
if __name__ == '__main__':
main()
Loading…
Cancel
Save