add the module collection

This commit is contained in:
Valentin Gurmeza 2017-05-25 16:30:10 -07:00
parent 3609e520c5
commit 428dd5e0e2
22 changed files with 3741 additions and 0 deletions

105
library/mt_command.py Normal file
View file

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_command
author:
- "Valentin Gurmeza"
version_added: "2.3"
short_description: Issue mikrotik command
requirements:
- mt_api
description:
- Issue a mikrotik command
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
command:
description:
- command to be sent to the router. The command must be a command path using
- '/' for word separation
required: True
command_arguments:
description:
- parameters to pass with the command. Must be a dictionary
'''
EXAMPLES = '''
- mt_command:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
name: /system/backup/save
command_arguments:
name: ansible_test
password: 123
'''
import mt_api
from mt_common import clean_params
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True),
username=dict(required=True),
password=dict(required=True),
command=dict(required=True, type='str'),
command_arguments=dict(required=False, type='dict'),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
changed = False
changed_message = []
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
api_path = module.params['command']
if module.params['command_arguments'] != None:
response = mk.api_command(base_path=api_path, params=module.params['command_arguments'])
else:
response = mk.api_command(base_path=api_path)
if response[-1][0] == '!done':
changed = True
changed_message.append(response)
changed_message.append(api_path)
if module.params['command_arguments'] != None:
changed_message.append(module.params['command_arguments'])
if changed:
module.exit_json(
failed=False,
changed=True,
msg=changed_message
)
else:
module.exit_json(
failed=False,
changed=False,
msg="Command failed"
)
if __name__ == '__main__':
main()

127
library/mt_dhcp_server.py Normal file
View file

@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_dhcp_server.py
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik dhcp-server endpoints
requirements:
- mt_api
description:
- Mikrotik dhcp-server generic module
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik tool
required: True
options:
- netwatch
- e-mail
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_dhcp_server:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: network
settings:
address: 192.168.1.0/24
dns: 192.168.1.20
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['network', 'option', 'dhcp-server'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
if params['parameter'] == 'network':
idempotent_parameter = 'address'
params['parameter'] = "dhcp-server/network"
if params['parameter'] == 'option':
idempotent_parameter = 'name'
params['parameter'] = "dhcp-server/option"
if params['parameter'] == 'dhcp-server':
idempotent_parameter = 'name'
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/ip/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

124
library/mt_hotspot.py Normal file
View file

@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_snmp
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik hotspot endpoints
requirements:
- mt_api
description:
- Generic mikrotik hotspot module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik hotspot
required: True
options:
- netwatch
- e-mail
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_hotspot:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: profile
settings:
name: Hotspot_Crew
use-radius: yes
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['hotspot', 'profile', 'walled-garden'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
idempotent_parameter = 'name'
if params['parameter'] == 'profile':
params['parameter'] = "hotspot/profile"
if params['parameter'] == 'walled-garden':
idempotent_parameter = 'comment'
params['parameter'] = "hotspot/walled-garden"
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/ip/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,291 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_interface_bridge
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik bridge
requirements:
- mt_api
description:
- add, remove, or modify a bridge.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- bridge present or absent
required: True # if modifying bridge
choices:
- present
- absent
name:
description:
- name of the bridge
comment:
description:
- brige comment
admin_mac:
description:
- Static MAC address of the bridge (takes effect if auto-mac=no)
ageing_time:
description:
- How long a host's information will be kept in the bridge database
arp:
description:
- Address Resolution Protocol setting
choices:
- disabled
- enabled
- proxy-arp
- reply-only
auto_mac:
description:
- Automatically select one MAC address of bridge ports as a bridge MAC address
choices:
- yes
- no
forward_delay:
description:
- Time which is spent during the initialization phase of the bridge interface (i.e., after router startup or enabling the interface) in listening/learning state before the bridge will start functioning normally
max_message_age:
description:
- How long to remember Hello messages received from other bridges
mtu:
description:
- Maximum Transmission Unit
priority:
description:
- Spanning tree protocol priority for bridge interface
protocol_mode:
description:
- Select Spanning tree protocol (STP) or Rapid spanning tree protocol (RSTP) to ensure a loop-free topology for any bridged LAN
choices:
- none
- rstp
- stp
transmit_hold_count:
description:
- The Transmit Hold Count used by the Port Transmit state machine to limit transmission rate
settings:
description:
- Bridge settings. If defined this argument is a key/value dictionary
choices:
- allow-fast-path: yes/no
- use-ip-firewall: yes/no
- use-ip-firewall-for-ppoe: yes/no
- use-ip-firewall-for-bridge: yes/no
'''
EXAMPLES = '''
- mt_interface_bridge:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
name: bridge_native
interface: ether7
comment: ansible_test
'''
import mt_api
from mt_common import clean_params
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
name = dict(required=False, type='str'),
comment = dict(required=False, type='str'),
admin_mac = dict(required=False, type='str'),
auto_mac = dict(required=False, type='str'),
ageing_time = dict(required=False, type='str'),
forward_delay = dict(required=False, type='str'),
max_message_age=dict(required=False, type='str'),
transmit_hold_count=dict(required=False, type='str'),
arp = dict(
required = False,
choices = ['disabled', 'enabled', 'proxy-arp', 'reply-only'],
type='str'
),
protocol_mode= dict(
required = False,
choices = ['none', 'rstp', 'stp'],
type='str'
),
settings= dict(
required = False,
type='dict'
),
state= dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
state = module.params['state']
ansible_bridge_name = module.params['name']
changed = False
changed_message = []
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
bridge_path = '/interface/bridge'
response = mk.api_print(base_path=bridge_path)
bridge_params = module.params
mikrotik_bridge = {}
for item in response:
if 'name' in item[1]:
if ansible_bridge_name == item[1]['name']:
mikrotik_bridge = item[1]
########################################################
# Check if we need to edit the bridge settings
########################################################
if bridge_params['settings'] is not None:
settings_path = '/interface/bridge/settings'
settings_response = mk.api_print(settings_path)
settings_response = settings_response[0][1]
settings = bridge_params['settings']
bridge_settings_diff_keys = {}
for key in settings:
if isinstance(settings[key], bool):
settings[key] = str(settings[key])
settings[key] = str.lower(settings[key])
else:
if settings[key] == "yes":
settings[key] = "true"
if settings[key] == "no":
settings[key] = "false"
for key in settings:
if key in settings_response:
if settings[key] != settings_response[key]:
bridge_settings_diff_keys[key] = settings[key]
else:
bridge_settings_diff_keys[key] = settings[key]
if bridge_settings_diff_keys != {}:
mk.api_edit(base_path=settings_path, params=bridge_settings_diff_keys)
changed_message.append(bridge_settings_diff_keys)
changed = True
else:
changed = False
#######################################
# remove unneeded parameters
# clean up parameters
######################################
remove_params = ['hostname', 'username', 'password', 'state', 'settings']
for i in remove_params:
del bridge_params[i]
clean_params(bridge_params)
if '.id' in mikrotik_bridge:
client_id = mikrotik_bridge['.id']
else:
client_id = False
##################################################################
# We need to make sure that bridge_bridge name is a string
# if it's null then it has not been defined.
###################################################################
if (state == "present" and isinstance(ansible_bridge_name, str)):
if mikrotik_bridge == {}:
mk.api_add(
base_path=bridge_path,
params=bridge_params
)
changed_message.append(ansible_bridge_name + " added")
changed = True,
else:
bridge_diff_keys = {}
for key in bridge_params:
if key in mikrotik_bridge:
if bridge_params[key] != mikrotik_bridge[key]:
bridge_diff_keys[key] = bridge_params[key]
else:
bridge_diff_keys[key] = bridge_params[key]
if bridge_diff_keys != {}:
bridge_diff_keys['numbers'] = client_id
mk.api_edit(base_path=bridge_path, params=bridge_diff_keys)
changed = True
changed_message.append("Changed bridge: " + bridge_params['name'])
else:
####################
# Already up date
###################
if not changed:
changed = False
elif state == "absent":
if client_id:
mk.api_remove(base_path=bridge_path, remove_id=client_id)
changed_message.append(bridge_params['name'] + " removed")
changed = True
#####################################################
# if client_id is not set there is nothing to remove
#####################################################
else:
if not changed:
changed = False
elif settings:
########################################################
# if settings were set we were modifying bridge settings
# only
pass
else:
module.exit_json(
failed=True,
changed=False,
)
if changed:
module.exit_json(
failed=False,
changed=True,
msg=changed_message
)
else:
module.exit_json(
failed=False,
changed=False,
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,243 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_interface_bridge_port
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik bridge_port
requirements:
- mt_api
description:
- add, remove, or modify a bridge_port.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- inteface present or absent in the bridge
required: True
choices:
- present
- absent
comment:
description:
- brige comment
auto_isolate:
description:
- Prevents STP blocking port from erroneously moving into a forwarding state if no BPDU's are received on the bridge
choices:
- yes
- no
bridge:
description:
- The bridge interface the respective interface is grouped in
edge:
description:
- Set port as edge port or non-edge port, or enable automatic detection. Edge ports are connected to a LAN that has no other bridge attached. If the port is configured to discover edge port then as soon as the bridge_ detects a BPDU coming to an edge port, the port becomes a non-edge port
choices:
- auto
- no
- no-discover
- yes
- yes-discover
external_fdb:
description:
- Whether to use wireless registration table to speed up bridge host learning
choices:
- yes
- no
- auto
horizon:
description:
- Use split horizon bridging to prevent bridging loops
interface:
description:
- Name of the interface
path_cost:
description:
- Path cost to the interface, used by STP to determine the "best" path
point_to_point:
description:
- point to point
choices:
- yes
- no
- auto
priority:
description:
- The priority of the interface in comparison with other going to the same subnet
'''
EXAMPLES = '''
- mt_interface_bridge_port:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
name: bridge_port_native
interface: ether7
comment: ansible_test
'''
import mt_api
from mt_common import clean_params
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname =dict(required=True),
username =dict(required=True),
password =dict(required=True),
interface =dict(required=True, type='str'),
bridge =dict(required=False, type='str'),
comment =dict(required=False, type='str'),
path_cost =dict(required=False, type='str'),
priority =dict(required=False, type='str'),
horizon =dict(required=False, type='str'),
external_fdb=dict(
required=False,
choices=['yes', 'no', 'auto'],
type='str'
),
auto_isolate=dict(
required=False,
choices=['yes', 'no'],
type='str'
),
edge=dict(
required=False,
choices=['auto', 'yes', 'no', 'no-discover', 'yes-discover'],
type='str'
),
point_to_point=dict(
required=False,
choices=['yes', 'no', 'auto'],
type='str'
),
state=dict(
required=True,
choices=['present', 'absent'],
type='str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
state = module.params['state']
ansible_bridge_port_interface = module.params['interface']
changed = False
changed_message = []
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
bridge_port_path = '/interface/bridge/port'
response = mk.api_print(base_path=bridge_port_path)
bridge_port_params = module.params
mikrotik_bridge_port = {}
for item in response:
if 'interface' in item[1].keys():
if ansible_bridge_port_interface == item[1]['interface']:
mikrotik_bridge_port = item[1]
#######################################
# remove unneeded parameters
######################################
remove_params = ['hostname', 'username', 'password', 'state']
for i in remove_params:
del bridge_port_params[i]
##########################################
# modify clean_params in place
############################################
clean_params(bridge_port_params)
if '.id' in mikrotik_bridge_port:
client_id = mikrotik_bridge_port['.id']
else:
client_id = False
if state == "present":
if mikrotik_bridge_port == {}:
mk.api_add(
base_path=bridge_port_path,
params=bridge_port_params
)
changed_message.append(ansible_bridge_port_interface + " added to bridge")
changed = True,
else:
bridge_port_diff_keys = {}
for key in bridge_port_params:
if key in mikrotik_bridge_port:
if bridge_port_params[key] != mikrotik_bridge_port[key]:
bridge_port_diff_keys[key] = bridge_port_params[key]
else:
bridge_port_diff_keys[key] = bridge_port_params[key]
if bridge_port_diff_keys != {}:
bridge_port_diff_keys['numbers'] = client_id
mk.api_edit(base_path=bridge_port_path, params=bridge_port_diff_keys)
changed = True
changed_message.append("Changed bridge port: " + bridge_port_params['bridge'])
else:
####################
# Already up date
###################
if not changed:
changed = False
elif state == "absent":
if client_id:
mk.api_remove(base_path=bridge_port_path, remove_id=client_id)
changed_message.append(bridge_port_params['interface'] + " removed")
changed = True
#####################################################
# if client_id is not set there is nothing to remove
#####################################################
else:
if not changed:
changed = False
else:
module.exit_json(
failed=True,
changed=False,
)
if changed:
module.exit_json(
failed=False,
changed=True,
msg=changed_message
)
else:
module.exit_json(
failed=False,
changed=False,
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,277 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_interface_ovpn_client
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik openvpn client
requirements:
- mt_api
description:
- add, remove, or modify an openvpn client. Mikrotik uses ovpn alias for openvpn.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- ovpn client present or absent
required: True
choices:
- present
- absent
comment:
description:
- ovpn client comment
required: False
name:
description:
- name of the ovpn client
user:
description:
- vpn user name
required: True # if state is present
connect_to:
description:
- Remote address of the OVPN server
required: True # if state is present
vpn_password:
description:
- ovpn client password
required: True # if state is present
port:
description:
- ovpn client port
required: False
max_mtu:
description:
- Maximum Transmission Unit. Max packet size that OVPN interface will be able to send without packet fragmentation.
required: False
profile:
description:
- Used PPP profile
required: False
certificate:
description:
- Name of the client certificate
required: False
mac_address:
description:
- Mac address of OVPN interface
required: False
add_default_route:
description:
- Whether to add OVPN remote address as a default route
required: False
choices:
- yes
- no
cipher:
description:
- Allowed ciphers
required: False
choices:
- blowfish128
- aes128
- aes192
- aes256
auth:
description:
- Allowed authentication methods
required: False
choices:
- sha1
- md5
- null
- aes256
mode:
description:
- Layer3 or layer2 tunnel mode (alternatively tun, tap)
required: False
choices:
- ip
- ethernet
'''
EXAMPLES = '''
- mt_interface_ovpn_client:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
vpn_user: ansible_admin
connect_to: 192.168.230.1
client_name: ansible_test
vpn_password: 'password'
'''
import mt_api
import re
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
name = dict(required=True, type='str'),
user = dict(required=False, type='str'),
connect_to = dict(required=False, type='str'),
comment = dict(required=False, type='str'),
vpn_password = dict(required=False, type='str'),
port = dict(required=False, type='str'),
max_mtu = dict(required=False, type='str'),
profile = dict(required=False, type='str'),
certificate = dict(required=False, type='str'),
mac_address = dict(required=False, type='str'),
add_default_route = dict(
required = False,
choices = ['yes', 'no'],
type='str'
),
cipher = dict(
required = False,
choices = ['blowfish128', 'aes128', 'aes192', 'aes256'],
type='str'
),
auth = dict(
required = False,
choices = ['sha1', 'md5', 'null'],
type='str'
),
mode = dict(
required = False,
choices = ['ip', 'ethernet'],
type='str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
state = module.params['state']
ansible_client_name = module.params['name']
ansible_mac_address = module.params['mac_address']
changed = False
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
ovpn_client_path = '/interface/ovpn-client'
response = mk.api_print(base_path=ovpn_client_path)
ovpn_client_params = module.params
mikrotik_client_name = ""
mikrotik_ovpn_client = {}
for item in response:
if 'name' in item[1].keys():
if ansible_client_name == item[1]['name']:
mikrotik_client_name = item[1]['name']
mikrotik_ovpn_client = item[1]
#######################################
# remove keys with empty values
# remove unneeded parameters
# modify keys with '_' to match mikrotik parameters
######################################
remove_params = ['hostname', 'username', 'password', 'state']
for i in remove_params:
del ovpn_client_params[i]
for key in ovpn_client_params.keys():
if ovpn_client_params[key] is None:
del ovpn_client_params[key]
for key in ovpn_client_params.keys():
if 'vpn_password' == key:
ovpn_client_params['password'] = ovpn_client_params[key]
del ovpn_client_params[key]
for key in ovpn_client_params.keys():
new_key = re.sub('_','-', key)
if new_key != key:
ovpn_client_params[new_key] = ovpn_client_params[key]
del ovpn_client_params[key]
if state == "present":
if mikrotik_ovpn_client == {}:
mk.api_add(
base_path=ovpn_client_path,
params=ovpn_client_params
)
module.exit_json(
changed=True,
failed=False,
msg=ansible_client_name + " client added"
)
else:
mikrotik_ovpn_client['add-default-route'] = 'no'
if 'comment' in ovpn_client_params and 'comment' not in mikrotik_ovpn_client:
mikrotik_ovpn_client['comment'] = None
client_id = mikrotik_ovpn_client['.id']
for i in ['.id', 'running']:
mikrotik_ovpn_client.pop(i)
update_keys = {}
for key, value in ovpn_client_params.items():
if value != mikrotik_ovpn_client[key]:
update_keys[key] = value
if update_keys == {}:
module.exit_json(
changed=False,
failed=False,
)
else:
update_keys['numbers'] = client_id
mk.api_edit(
base_path=ovpn_client_path,
params=update_keys
)
module.exit_json(
changed=True,
failed=False,
msg=update_keys,
)
else:
if mikrotik_ovpn_client == {}:
module.exit_json(
changed=False,
failed=False,
)
else:
remove_response = mk.api_remove(
base_path=ovpn_client_path,
remove_id=mikrotik_ovpn_client['.id']
)
module.exit_json(
changed=True,
failed=False,
msg=remove_response[0]
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_interface_wireless
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik interface_wireless endpoints
requirements:
- mt_api
description:
- Generic mikrotik interface wireless module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik interface wireless
required: True
options:
- security-profiles
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_interface_wireless:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: security-profiles
state: present
settings:
name: test1
supplicant-identity: test
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['security-profiles'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
idempotent_parameter = 'name'
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/interface/wireless/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

127
library/mt_interfaces.py Normal file
View file

@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_interface.py
author:
- "Shaun Smiley"
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik interfaces
requirements:
- mt_api
description:
- manage settings on interfaces
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik tool
required: True
options:
- ethernet
- vlan
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
required: True
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_interfaces:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: "ethernet"
state: present
settings:
name: ether2
comment: Ansible controlled ether2
mtu: 1501
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True),
username=dict(required=True),
password=dict(required=True),
settings=dict(required=True, type='dict'),
parameter = dict(
required = True,
choices = ['ethernet', 'vlan'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
)
),
supports_check_mode=True
)
params = module.params
idempotent_parameter = 'name'
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/interface/' + str(params['parameter']),
check_mode = module.check_mode,
)
# exit if login failed
if not mt_obj.login_success:
module.fail_json(
msg = mt_obj.failed_msg
)
# add, remove or edit things
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

183
library/mt_ip_address.py Normal file
View file

@ -0,0 +1,183 @@
DOCUMENTATION = '''
module: mt_ip_address
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik /ip/addresses
requirements:
- rosapi
description:
- FILL ME OUT
options:
hostname:
description:
-
username:
description:
-
password:
description:
-
interface:
description:
-
address:
description:
-
network:
description:
-
state:
description:
-
force:
description:
- True/False value to force removing the address on an interface
even if the address does not match.
'''
EXAMPLES = '''
- mt_ip_address:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
interface: "ether2"
address: "192.168.88.2/24"
network: "192.168.88.0/24"
state: "present"
comment: "link 3"
'''
import mt_api
import socket
#import mt_action #TODO: get this working
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
interface = dict(required=True, type='str'),
address = dict(required=True, type='str', aliases=['ip', 'addr', 'ip_address']),
network = dict(required=False, type='str', default=""),
comment = dict(required=False, type='str', default=""),
state = dict(
required = False,
default = "present",
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
ip_address = module.params['address']
interface = module.params['interface']
network = module.params['network']
ip_state = module.params['state']
comment = module.params['comment']
changed = False
msg = ""
interface_path = '/interface'
address_path = '/ip/address'
address_print_params = {
".proplist": "interface,address,.id,network,netmask,comment"
}
interface_print_params = {
".proplist": "name,.id,type"
}
mk = mt_api.Mikrotik(hostname,username,password)
try:
mk.login()
interfaces = mk.api_print(interface_path, interface_print_params)
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
###################################
# Check if interface is present
# exit if interface is not present
###################################
interfacelist = []
exitmessage = []
for i in range(0, len(interfaces) - 1):
interfacelist.append(interfaces[i][1]["name"])
intExists = False
if (interface in interfacelist):
intExists = True
# module.exit_json(failed=False, changed=False, msg=interfacelist)
if intExists:
pass
#exitmessage.append("Interface " + interface + " exists.") #this is never used
else:
exitmessage.append("Interface " + interface + " does not exist.")
module.fail_json(failed=True, msg=exitmessage)
##############################################
# Check if IP address is set on the interface
# make no changes if address already set
##############################################
ip_addresses = mk.api_print(address_path, address_print_params)
iplist = []
for i in range(0, len(ip_addresses) - 1):
iplist.append(ip_addresses[i][1]["address"])
if ip_addresses[i][1]["address"] == ip_address:
ip_id = ip_addresses[i][1][".id"]
if ip_state == "present":
if ip_address in iplist:
module.exit_json(
failed=False,
#msg="IP Address: " + ip_address +
#" is already configured" +
#" on interface " + interface,
)
else:
add_dict = {
'address': ip_address,
'interface': interface,
'comment': comment
}
response = mk.api_add(address_path, add_dict)
module.exit_json(
failed=False,
changed=True,
#msg="IP address: " + ip_address + " has been configured" +
#" on interface " + interface
)
if ip_state == "absent":
if ip_address in iplist:
response = mk.api_remove(address_path, ip_id)
module.exit_json(
failed=False,
changed=True,
#msg="IP Address: " + ip_address +
#" has been removed"
)
else:
module.exit_json(
failed=False,
changed=False,
#msg="IP Address: " + ip_address +
#" is already absent"
)
if __name__ == '__main__':
main()

254
library/mt_ip_firewall.py Normal file
View file

@ -0,0 +1,254 @@
DOCUMENTATION = '''
module: mt_ip_firewall
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik /ip/firewall/
requirements:
- mt_api
description:
- Generic mikrotik firewall module
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik tool
required: True
options:
- netwatch
- e-mail
rule:
description:
- a list containing dictionary parameters.
action, chain, comment, and place-before keys are required
parameter:
description:
- sub endpoint for mikrotik firewall
required: True
options:
- filter
- nat
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
- if a firewall list containing dictionary parameters,
action, chain, comment, and place-before keys are required
state:
description:
- absent or present
force:
description:
- True/False value to force remove the rule regardless of the position in the rule list.
'''
EXAMPLES = '''
- mt_ip_firewall:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
parameter: filter
settings:
action: accept
chain: forward
comment: controlled by ansible
place-before: "2"
'''
from ansible.module_utils.basic import AnsibleModule
import mt_api
import re
from copy import copy
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
rule = dict(required=False, type='dict'),
parameter = dict(required=True, type='str'),
state = dict(
required = False,
default = "present",
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
rule = module.params['rule']
state = module.params['state']
api_path = '/ip/firewall/' + module.params['parameter']
# ##############################################
# Check if "place-before" is an integer
# #############################################
try:
desired_order = int(rule['place-before'])
except:
module.exit_json(
failed=True,
changed=False,
msg="place-before is not set or is not set to an integer",
)
changed = False
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
filter_response = mk.api_print(api_path)
current_rule = None
current_id = None
existing_order = None
last_item = len(filter_response) - 2
changed_msg = []
# Always set the comment to the order_number
if 'comment' in rule:
rule['comment'] = str(desired_order) + " " + str(rule['comment'])
else:
rule['comment'] = str(desired_order)
if desired_order <= last_item:
placed_at_the_end = False
else:
placed_at_the_end = True
# remove the place-before if we are placing
# the rule at the bottom of the chain
rule.pop('place-before', None)
# Check rule is not present
# find existing rule
# current_rule is what's on mikrotik right now
for index, current_param in enumerate(filter_response):
if 'comment' in current_param[1]:
if re.search(r"^" + str(desired_order) + "\s+", current_param[1]['comment']):
current_id = current_param[1]['.id']
existing_order = index
current_rule = current_param[1]
# remove the place-before since we'll be editing not moving it
rule.pop('place-before', None)
# ensure the rule if state is present
if state == "present":
# if we don't have an existing rule to match
# the desired we create a new one
if not current_rule:
mk.api_add(api_path, rule)
changed = True,
# if current_rule is true we need to ensure the changes
else:
out_params = {}
old_params = {}
for desired_param in rule:
rule[desired_param] = str(rule[desired_param])
if desired_param in current_rule:
if current_rule[desired_param] != rule[desired_param]:
out_params[desired_param] = rule[desired_param]
old_params[desired_param] = current_rule[desired_param]
else:
out_params[desired_param] = rule[desired_param]
if desired_param in current_rule:
old_params[desired_param] = current_rule[desired_param]
# When out_params has been set it means we found our diff
# and will set it on the mikrotik
if out_params:
if current_id is not None:
out_params['.id'] = current_id
mk.api_edit(
base_path = api_path,
params = out_params
)
# we don't need to show the .id in the changed message
if '.id' in out_params:
del out_params['.id']
changed = True
changed_msg.append({
"new_params": out_params,
"old_params": old_params,
})
# ensure the rule is in right position
if current_id:
if int(existing_order) != int(desired_order):
api_path += '/move'
params = False
if placed_at_the_end:
if existing_order > last_item:
params = {
'.id': current_id,
}
else:
params = {
'.id': current_id,
'destination': desired_order
}
if params:
mk.api_command(api_path, params)
changed_msg.append({
"moved": existing_order,
"to": old_params,
})
changed = True
#####################################
# Remove the rule
#####################################
elif state == "absent":
if current_rule:
mk.api_remove(api_path, current_id)
changed = True
changed_msg.append("removed rule: " + str(desired_order))
else:
failed = True
if changed:
module.exit_json(
failed=False,
changed=True,
msg=changed_msg
)
elif not changed:
module.exit_json(
failed=False,
changed=False,
)
else:
module.fail_json()
##########################################
# To DO:
# Clean up duplicate items
###########################################
if __name__ == '__main__':
main()

View file

@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_ip_firewall_filter
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik /ip/firewall/filter
requirements:
- mt_api
description:
- FILL ME OUT
options:
hostname:
description:
-
username:
description:
-
password:
description:
-
list-name:
description:
- name of the address-list
state:
description:
- present or absent
address_list:
description:
- A list of single IP addresses or range of IPs to add to address-list.
Can also be a set to a hostname which will create a dynamic entry
in the list with the proper IP address for the record (as of 6.38.1)
'''
EXAMPLES = '''
- mt_ip_firewall_addresslist:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state:   "present"
name:   "block_all"
dynamic: false
address_list:
- 192.168.10.1
- yahoo.com
- 19.134.52.23/23
'''
import mt_api
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
list_name = dict(required=True, type='str'),
address_list = dict(required=False, type='list'),
state = dict(
required = False,
default = "present",
choices = ['present', 'absent', 'force'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
ansible_list_name = module.params['list_name']
ansible_address_list = module.params['address_list']
state = module.params['state']
changed = False
msg = ""
address_list_path = '/ip/firewall/address-list'
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
response = mk.api_print(address_list_path)
mikrotik_address_list = []
mikrotik_address_id = {}
list_name = ansible_list_name
for item in response:
if 'list' in item[1].keys():
address = item[1]['address']
if item[1]['list'] == list_name:
temp_dict = {}
temp_dict['address'] = item[1]['address']
if 'comment' in item[1].keys():
temp_dict['comment'] = item[1]['comment']
mikrotik_address_list.append(dict(temp_dict))
mikrotik_address_id[address] = item[1]['.id']
if state == "present":
if ansible_address_list == mikrotik_address_list:
module.exit_json(
changed = False,
failed = False,
msg = "list up to date",
)
common_list = []
for item in ansible_address_list:
for item2 in mikrotik_address_list:
if item['address'] in item2['address']:
common_list.append(item['address'])
if item['comment'] in item2['comment']:
##################
# update comment
#################
pass
#################################
# build add_list
# add item missing from mikrotik
#################################
add_list = []
for item in ansible_address_list:
if item['address'] not in common_list:
temp_dict = {}
temp_dict['address'] = item['address']
temp_dict['comment'] = item['comment']
add_list.append(dict(temp_dict))
for i in add_list:
#address = i['address']
#comment = i['comment']
add_dictionary = {
"address": i['address'],
"list": list_name,
"comment": i['comment']
}
mk.api_add(address_list_path, add_dictionary)
changed = True
#####################
# build remove list
######################
remove_list = []
for item in mikrotik_address_list:
if item['address'] not in common_list:
remove_list.append(item['address'])
#######################################
# Remove every item in the address_list
#######################################
for i in remove_list:
remove_id = mikrotik_address_id[i]
mk.api_remove(address_list_path, remove_id)
if not changed:
changed = True
else:
#######################################
# Remove every item
#######################################
for remove_id in mikrotik_address_id.values():
mk.api_remove(address_list_path, remove_id)
if not changed:
changed = True
if changed:
module.exit_json(
changed = True,
failed = False,
msg = ansible_list_name + "has been modified",
)
else:
module.exit_json(
changed = False,
failed = False,
msg = ansible_list_name + " is up to date",
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,178 @@
DOCUMENTATION = '''
module: mt_ip_firewall_filter
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik /ip/firewall/filter
requirements:
- mt_api
description:
- FILL ME OUT
options:
hostname:
description:
-
username:
description:
-
password:
description:
-
rule:
description:
- a list containing dictionary parameters.
action, chain, comment, and place-before keys are required
force:
description:
- True/False value to force remove the rule regardless of the position in the rule list.
'''
EXAMPLES = '''
- mt_ip_firewall_filter:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
rule:
action: accept
chain: forward
comment: controlled by ansible
place-before: "2"
'''
import mt_api
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
rule = dict(required=False, type='dict'),
state = dict(
required = False,
default = "present",
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
rule = module.params['rule']
rule_state = module.params['state']
changed = False
msg = ""
filter_path = '/ip/firewall/filter'
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
# ##############################################
# Check if "place-before" is an integer
# #############################################
try:
placement = int(rule['place-before'])
if isinstance(placement, int):
pass
except:
module.exit_json(
failed=True,
changed=False,
msg="place-before is not set or is not set to an integer",
)
#######################################################
# Construct the fluff to ignore the extras from mikrotik response
########################################################
if "log" not in rule:
rule['log'] = "false"
if "log-prefix" not in rule:
rule['log-prefix'] = ""
fluff = (
"bytes",
"disabled",
"invalid",
"packets",
"dynamic",
"invalid",
".id",
)
###################################
# Check if rule is present
# exit if rule is not present
###################################
filter_response = mk.api_print(filter_path)
last_item = len(filter_response) - 2
order_number = int(rule['place-before'])
if order_number <= last_item:
clean_response = filter_response[order_number][1]
clean_response['place-before'] = rule['place-before']
placed_at_the_end = False
remove_id = clean_response['.id']
for f in fluff:
clean_response.pop(f, None)
else:
placed_at_the_end = True
if rule_state == "present":
if placed_at_the_end is False:
if rule == clean_response:
module.exit_json(
failed=False,
changed=False,
)
################################
# add the rule
##################################
else:
mk.api_remove(filter_path, remove_id)
mk.api_add(filter_path, rule)
module.exit_json(
failed=False,
changed=True,
)
else:
rule.pop('place-before', None)
mk.api_add(filter_path, rule)
module.exit_json(
failed=False,
changed=True,
)
#####################################
# Remove the rule
#####################################
elif rule_state == "absent":
if placed_at_the_end:
module.exit_json(
failed=False,
changed=False
)
else:
if rule == clean_response:
mk.api_remove(filter_path, remove_id)
module.exit_json(
failed=False,
changed=True
)
else:
module.exit_json(
failed=False,
changed=False
)
if __name__ == '__main__':
main()

202
library/mt_ip_pool.py Normal file
View file

@ -0,0 +1,202 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_dhcp_server
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik ip pools
requirements:
- mt_api
description:
- Add or remove ip pool
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- ip pool present or absent
required: True
name:
description:
- name of the ip pool
required: True
ranges:
description:
- IP address list of non-overlapping IP address ranges
required: False
next_pool:
description:
- When address is acquired from pool that has no free addresses, and next_pool property is set to another pool, then next IP address will be acquired from next_pool
required: False
'''
EXAMPLES = '''
# Add a new dhcp server
- mt_dhcp_server:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
name: ansible_test
address_pool: 'pool1'
interface: vlan15
'''
import mt_api
from ansible.module_utils.basic import AnsibleModule
import re
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True),
username=dict(required=True),
password=dict(required=True),
name=dict(required=True, type='str'),
ranges=dict(required=False, type='str'),
next_pool=dict(required=False, type='str'),
state=dict(
required = True,
choices = ['present', 'absent'],
type = 'str'
)
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
ip_pool_name = module.params['name']
state = module.params['state']
changed = False
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
ip_pool_path = '/ip/pool'
response = mk.api_print(base_path=ip_pool_path)
ip_pool_params = module.params
mikrotik_ip_pool= {}
for item in response:
if 'name' in item[1]:
if ip_pool_name == item[1]['name']:
ip_pool_name = item[1]['name']
mikrotik_ip_pool = item[1]
#################################################################
# Since we are grabbing all the parameters passed by the module
# We need to remove the one that won't be used
# as mikrotik parameters
#################################################
remove_params = ['hostname', 'username', 'password', 'state']
for i in remove_params:
ip_pool_params.pop(i)
#######################################
# remove keys with empty values
# convert vars with '_' to '-'
# convert yes/no to true/false
######################################
for key in ip_pool_params.keys():
if ip_pool_params[key] is None:
ip_pool_params.pop(key)
for key in ip_pool_params.keys():
new_key = re.sub('_','-', key)
if new_key != key:
ip_pool_params[new_key] = ip_pool_params[key]
del ip_pool_params[key]
for key in ip_pool_params:
if ip_pool_params[key] == "yes":
ip_pool_params[key] = "true"
if ip_pool_params[key] == "no":
ip_pool_params[key] = "false"
##########################################################
# Define client_id to be used by remove and edit function
##########################################################
if '.id' in mikrotik_ip_pool:
client_id = mikrotik_ip_pool['.id']
else:
client_id = False
if state == "present":
if mikrotik_ip_pool == {}:
mk.api_add(base_path=ip_pool_path, params=ip_pool_params)
module.exit_json(
failed=False,
changed=True,
msg="Added dhcp server " + ip_pool_name
)
###################################################
# If an item exists we check if all the parameters
# match what we have in ansible
######################################
else:
ip_pool_diff_keys = {}
for key in ip_pool_params:
if key in mikrotik_ip_pool:
if ip_pool_params[key] != mikrotik_ip_pool[key]:
ip_pool_diff_keys[key] = ip_pool_params[key]
else:
ip_pool_diff_keys[key] = ip_pool_params[key]
if ip_pool_diff_keys != {}:
ip_pool_diff_keys['numbers'] = client_id
mk.api_edit(base_path=ip_pool_path, params=ip_pool_diff_keys)
module.exit_json(
failed=False,
changed=True,
msg="Changed dhcp sever item: " + ip_pool_params['name'],
)
else:
####################
# Already up date
module.exit_json(
failed=False,
changed=False,
)
elif state == "absent":
if client_id:
mk.api_remove(base_path=ip_pool_path, remove_id=client_id)
module.exit_json(
failed=False,
changed=True,
msg=ip_pool_params['name'] + " removed"
)
#####################################################
# if client_id is not set there is nothing to remove
#####################################################
else:
module.exit_json(
failed=False,
changed=False,
ms=mikrotik_ip_pool
)
else:
module.exit_json(
failed=True,
changed=False,
)
if __name__ == '__main__':
main()

41
library/mt_login_test.py Normal file
View file

@ -0,0 +1,41 @@
#! /usr/bin/python
import json
import mt_api
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True),
username=dict(required=True),
password=dict(required=True),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
changed = False
msg = ""
mk = mt_api.Mikrotik(hostname,username,password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device. Check the username and password."
)
# response = apiros.talk([b'/ip/address/add', b'=address=192.168.15.2/24', b'=interface=ether7'])
module.exit_json(
changed=False,
failed=False,
)
if __name__ == '__main__':
main()

118
library/mt_neighbor.py Normal file
View file

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_snmp
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik neighbor endpoints
requirements:
- mt_api
description:
- Generic mikrotik neighbor module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik neighbor
required: True
options:
- netwatch
- e-mail
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_hotspot:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: discovery
settings:
name: ether7
discover: "yes"
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['discovery'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
idempotent_parameter = 'name'
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/ip/neighbor/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

259
library/mt_radius.py Normal file
View file

@ -0,0 +1,259 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_radius
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik radius client
requirements:
- mt_api
description:
- Add or remove a radius client
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- client present or absent
required: True
choices:
- present
- absent
comment:
description:
- This module only ensures entries that match the comment field.
Thus, you should make unique comments for every entry.
required: True # only if state is present
address:
description:
- IPv4 or IPv6 address of RADIUS server
required: False
secret:
description:
- Shared secret used to access the RADIUS server
required: False
default: null
timeout:
description:
- Timeout after which the request should be resend
required: False
default: null
service:
description:
- Router services that will use this RADIUS server:
choices:
- 'hotspot' # HotSpot authentication service
- 'login' # router's local user authentication
- 'ppp # Point-to-Point clients authentication
- 'wireless # wireless client authentication (client's MAC address is sent as User-Name)
- 'dhcp # DHCP protocol client authentication (client's MAC address is sent as User-Name)IPv4 or IPv6 address of RADIUS server
required: False
default: null
incoming:
accept:
choices: ['true', 'false' ]
port: "3799"
description:
- Whether to accept the unsolicited messages.
Also include the port number to listen for the requests on.
Accept and port values must be strings
required: False
default: null
'''
EXAMPLES = '''
# Add a new radius entry
- mt_radius:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
address: 192.168.230.1
comment: ansible_test
secret: 'password'
service:
- login
- hotspot
- wireless
timeout: '2s500ms'
'''
import mt_api
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname= dict(required=True),
username= dict(required=True),
password= dict(required=True),
address = dict(required=False, type='str'),
comment = dict(required=True, type='str'),
secret = dict(required=False, type='str'),
service = dict(required=False, type='list'),
timeout = dict(required=False, type='str'),
incoming= dict(required=False, type='dict'),
state = dict(
required = True,
choices = ['present', 'absent'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
state = module.params['state']
changed = False
msg = ""
radius_path = '/radius'
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
response = mk.api_print(radius_path)
radius_params = module.params
########################################################
# Check if we need to edit the incoming radius settings
########################################################
if radius_params['incoming'] is not None:
incoming_path = '/radius/incoming'
incoming_response = mk.api_print(incoming_path)
incoming = radius_params['incoming']
if incoming_response[0][1]['accept'] == incoming['accept']:
if incoming_response[0][1]['port'] == incoming['port']:
# nothing to do
pass
else:
# edit port
mk.api_edit(base_path=incoming_path, params=incoming)
else:
# edit the accept and the port
mk.api_edit(base_path=incoming_path, params=incoming)
#######################################
# Since we are grabbing all the parameters passed by the module
# We need to remove the one that won't be used
# as mikrotik parameters
remove_params = ['hostname', 'username', 'password', 'state', 'incoming']
for i in remove_params:
radius_params.pop(i)
#######################################
# remove keys with empty values
# convert service list to stings
######################################
for key in radius_params.keys():
if radius_params[key] is None:
radius_params.pop(key)
#################################################
# Convert service list to comma separated string
#################################################
list_to_string = ""
if 'service' in radius_params:
list_to_string = ','.join(map(str, radius_params['service']))
radius_params['service'] = list_to_string
################################################
# mikrotik_radius is the dictionary with the parameters
# we get from mikrotik
#################################
# We grab the first radius item to
# match the comment
#################################
mikrotik_radius = {}
for i in response:
if 'comment' in i[1]:
if i[1]['comment'] == radius_params['comment']:
mikrotik_radius = i[1]
break
##########################################################
# Define radius_id to be used by remove and edit function
##########################################################
if '.id' in mikrotik_radius:
radius_id = mikrotik_radius['.id']
else:
radius_id = False
######################################################
# If the state is present and we can't find matching
# radius comment we add a new item with all the parameters
# from Ansible
#######################################################
if state == "present":
if mikrotik_radius == {}:
mk.api_add(base_path=radius_path, params=radius_params)
module.exit_json(
failed=False,
changed=True,
msg="Added radius item",
)
###################################################
# If an item exists we check if all the parameters
# match what we have in ansible
######################################
else:
radius_diff_keys = {}
for key in radius_params:
if radius_params[key] != mikrotik_radius[key]:
radius_diff_keys[key] = radius_params[key]
if radius_diff_keys != {}:
radius_diff_keys['numbers'] = radius_id
mk.api_edit(base_path=radius_path, params=radius_diff_keys)
module.exit_json(
failed=False,
changed=True,
msg="Changed radius item: " + radius_params['comment']
)
else:
####################
# Already up date
module.exit_json(
failed=False,
changed=False,
)
elif state == "absent":
if radius_id:
mk.api_remove(base_path=radius_path, remove_id=radius_id)
module.exit_json(
failed=False,
changed=True,
msg=radius_params['comment'] + " removed"
)
#####################################################
# if radius_id is not set there is nothing to remove
#####################################################
else:
module.exit_json(
failed=False,
changed=False,
)
else:
module.exit_json(
failed=True,
changed=False,
)
if __name__ == '__main__':
main()

190
library/mt_service.py Normal file
View file

@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_service
author:
- "Valentin Gurmeza"
- "Shaun Smiley"
version_added: "2.3"
short_description: Manage mikrotik ip service
requirements:
- mt_api
description:
- enable, disable, or modify a ip service
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
disabled:
description:
- service enabled or disabled
required: True
choices:
- no
- yes
name:
description:
- name of the service
required: True
choices:
- api
- api-ssl
- ftp
- ssh
- telnet
- winbox
- www
- www-ssl
address:
description:
- List of IP/IPv6 prefixes from which the service is accessible
certificate:
description:
- The name of the certificate used by particular service. Applicable only for services that depends on certificates (www-ssl, api-ssl)
port:
description:
- The port particular service listens on
'''
EXAMPLES = '''
- mt_service:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
disabled: no
name: ftp
address: 192.168.52.3
'''
import mt_api
import re
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
interface = dict(required=False, type='str'),
address = dict(required=False, type='str'),
certificate= dict(required=False, type='str'),
name = dict(
required=True,
choices=[
'api',
'api-ssl',
'ftp',
'ssh',
'telnet',
'winbox',
'www',
'www-ssl'
],
type='str'
),
disabled=dict(
required = True,
choices = ['yes', 'no'],
type = 'str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
ansible_service_name = module.params['name']
changed = False
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
service_path = '/ip/service'
response = mk.api_print(base_path=service_path)
service_params = module.params
mikrotik_service = {}
for item in response:
if 'name' in item[1].keys():
if ansible_service_name == item[1]['name']:
mikrotik_service = item[1]
#######################################
# remove keys with empty values
# remove unneeded parameters
# modify keys with '_' to match mikrotik parameters
# convert yes/no to true/false
######################################
remove_params = ['hostname', 'username', 'password']
for i in remove_params:
del service_params[i]
for key in service_params.keys():
if service_params[key] is None:
del service_params[key]
for key in service_params:
if service_params[key] == "yes":
service_params[key] = "true"
if service_params[key] == "no":
service_params[key] = "false"
if '.id' in mikrotik_service:
client_id = mikrotik_service['.id']
else:
client_id = False
service_diff_keys = {}
for key in service_params:
if key in mikrotik_service:
if service_params[key] != mikrotik_service[key]:
service_diff_keys[key] = service_params[key]
else:
service_diff_keys[key] = service_params[key]
if service_diff_keys == {}:
####################
# Already up date
###################
module.exit_json(
failed=False,
changed=False,
)
elif service_diff_keys != {}:
service_diff_keys['numbers'] = client_id
mk.api_edit(base_path=service_path, params=service_diff_keys)
module.exit_json(
failed=False,
changed=True,
msg="Changed service item: " + service_params['name'],
)
else:
####################
# Failure
###################
module.exit_json(
failed=True,
changed=False
)
if __name__ == '__main__':
main()

121
library/mt_snmp.py Normal file
View file

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_snmp
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik snmp endpoints
requirements:
- mt_api
description:
- Generic mikrotik snmp module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik snmp
required: True
options:
- netwatch
- e-mail
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_snmp:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: e-mail
settings:
address: 192.168.1.1
from: foo@bar.com
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['community', 'snmp'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
if params['parameter'] == 'community':
idempotent_parameter = 'name'
params['parameter'] = "snmp/community"
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

123
library/mt_system.py Normal file
View file

@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_system.py
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik system endpoints
requirements:
- mt_api
description:
- manage mikrotik system parameters
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub enpoint for mikrotik system
required: True
options:
- ntp_client
- clock
- logging
- routerboard
- identity
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_system:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: identity
settings:
name: test_ansible
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['ntp_client', 'clock', 'identity', 'logging', 'routerboard_settings'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
params = module.params
if params['parameter'] == 'routerboard_settings':
params['parameter'] = 'routerboard/settings'
if params['parameter'] == 'ntp_client':
params['parameter'] = 'ntp/client'
clean_params(params['settings'])
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param= None,
api_path = '/system/' + params['parameter'],
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,232 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_system_scheduler
author:
- "Valentin Gurmeza"
version_added: "2.3"
short_description: Manage mikrotik system scheduler
requirements:
- mt_api
description:
- add, remove, or modify a system scheduler task
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
state:
description:
- scheduler task present or absent
required: True
choices:
- present
- absent
comment:
description:
- task comment
interval:
description:
- interval between two script executions, if time interval is set to zero, the script is only executed at its start time, otherwise it is executed repeatedly at the time interval is specified
name:
description:
- name of the task
required: True
on_event:
description:
- name of the script to execute.
start_date:
description:
- date of the first script execution
start_time:
description:
- time of the first script execution
policy:
description:
- policy
'''
EXAMPLES = '''
- mt_system_scheduler:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
state: present
name: test_by_ansible
comment: ansible_test
on_event: put "hello"
'''
import mt_api
from mt_common import clean_params
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
hostname =dict(required=True),
username =dict(required=True),
password =dict(required=True),
name =dict(required=True, type='str'),
on_event =dict(required=False, type='str'),
comment =dict(required=False, type='str'),
interval =dict(required=False, type='str'),
policy =dict(required=False, type='list'),
start_date=dict(required=False, type='str'),
start_time=dict(required=False, type='str'),
state=dict(
required=True,
choices=['present', 'absent'],
type='str'
),
)
)
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
state = module.params['state']
ansible_scheduler_name = module.params['name']
changed = False
changed_message = []
msg = ""
mk = mt_api.Mikrotik(hostname, username, password)
try:
mk.login()
except:
module.fail_json(
msg="Could not log into Mikrotik device." +
" Check the username and password.",
)
api_path = '/system/scheduler'
response = mk.api_print(base_path=api_path)
ansible_scheduler_params = module.params
mikrotik_scheduler_task = {}
for item in response:
if 'name' in item[1]:
if ansible_scheduler_name == item[1]['name']:
mikrotik_scheduler_task = item[1]
#######################################
# remove unneeded parameters
######################################
remove_params = ['hostname', 'username', 'password', 'state']
for i in remove_params:
del ansible_scheduler_params[i]
##########################################
# modify params in place
############################################
clean_params(ansible_scheduler_params)
if '.id' in mikrotik_scheduler_task:
client_id = mikrotik_scheduler_task['.id']
else:
client_id = False
if state == "present":
#################################################
# Convert policy list to comma separated string
#################################################
if mikrotik_scheduler_task == {}:
if 'policy' in ansible_scheduler_params:
list_to_string = ""
list_to_string = ','.join(map(str, ansible_scheduler_params['policy']))
ansible_scheduler_params['policy'] = list_to_string
mk.api_add(
base_path=api_path,
params=ansible_scheduler_params
)
changed_message.append(ansible_scheduler_name + " added to bridge")
changed = True,
else:
scheduler_diff_keys = {}
########################################################################
# policy parameter is a comma separated list of values in a string that
# we receive from mikrotik
# we need to convert it to a list and then do a comparison against
# ansible policy list to get the difference
# if there is a difference between the two we need to convert the
# ansible_scheduler_params['policy'] to a string with comma separated values
#########################################################################
if 'policy' in ansible_scheduler_params:
dif_list = []
if 'policy' in mikrotik_scheduler_task:
policy = mikrotik_scheduler_task['policy'].split(',')
dif_list = set(ansible_scheduler_params['policy']) & set(policy)
if dif_list == []:
list_to_string = ""
list_to_string = ','.join(map(str, ansible_scheduler_params['policy']))
scheduler_diff_keys['policy'] = list_to_string
for key in ansible_scheduler_params:
if key != 'policy':
if key in mikrotik_scheduler_task:
if ansible_scheduler_params[key] != mikrotik_scheduler_task[key]:
scheduler_diff_keys[key] = ansible_scheduler_params[key]
else:
scheduler_diff_keys[key] = ansible_scheduler_params[key]
if scheduler_diff_keys != {}:
scheduler_diff_keys['numbers'] = client_id
mk.api_edit(base_path=api_path, params=scheduler_diff_keys)
changed = True
changed_message.append(
"Changed scheduler task : " + ansible_scheduler_params['name']
)
else:
####################
# Already up date
###################
if not changed:
changed = False
elif state == "absent":
if client_id:
mk.api_remove(base_path=api_path, remove_id=client_id)
changed_message.append(ansible_scheduler_params['name'] + " removed")
changed = True
#####################################################
# if client_id is not set there is nothing to remove
#####################################################
else:
if not changed:
changed = False
else:
module.exit_json(
failed=True,
changed=False,
msg="state is invalid"
)
if changed:
module.exit_json(
failed=False,
changed=True,
msg=changed_message
)
else:
module.exit_json(
failed=False,
changed=False,
)
if __name__ == '__main__':
main()

121
library/mt_tool.py Normal file
View file

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_tool
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik tool endpoints
requirements:
- mt_api
description:
- Generic mikrotik tool module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik tool
required: True
options:
- netwatch
- e-mail
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_tool:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: e-mail
settings:
address: 192.168.1.1
from: foo@bar.com
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['e-mail', 'netwatch'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
if params['parameter'] == 'netwatch':
idempotent_parameter = 'host'
# clean_params(params['settings'])
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/tool/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()

120
library/mt_user.py Normal file
View file

@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: mt_user
author:
- "Valentin Gurmeza"
version_added: "2.4"
short_description: Manage mikrotik user endpoints
requirements:
- mt_api
description:
- Generic mikrotik user module.
options:
hostname:
description:
- hotstname of mikrotik router
required: True
username:
description:
- username used to connect to mikrotik router
required: True
password:
description:
- password used for authentication to mikrotik router
required: True
parameter:
description:
- sub endpoint for mikrotik user
required: True
options:
- user
- active
- aaa
settings:
description:
- All Mikrotik compatible parameters for this particular endpoint.
Any yes/no values must be enclosed in double quotes
state:
description:
- absent or present
'''
EXAMPLES = '''
- mt_user:
hostname: "{{ inventory_hostname }}"
username: "{{ mt_user }}"
password: "{{ mt_pass }}"
parameter: user
settings:
name: test1
group: read
'''
from mt_common import clean_params, MikrotikIdempotent
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec = dict(
hostname = dict(required=True),
username = dict(required=True),
password = dict(required=True),
settings = dict(required=False, type='dict'),
parameter = dict(
required = True,
choices = ['user', 'active', 'aaa'],
type = 'str'
),
state = dict(
required = False,
choices = ['present', 'absent'],
type = 'str'
),
)
)
idempotent_parameter = None
params = module.params
idempotent_parameter = 'name'
if params['parameter'] == 'group':
params['parameter'] = 'user/group'
mt_obj = MikrotikIdempotent(
hostname = params['hostname'],
username = params['username'],
password = params['password'],
state = params['state'],
desired_params = params['settings'],
idempotent_param = idempotent_parameter,
api_path = '/' + str(params['parameter']),
)
mt_obj.sync_state()
if mt_obj.failed:
module.fail_json(
msg = mt_obj.failed_msg
)
elif mt_obj.changed:
module.exit_json(
failed=False,
changed=True,
msg=mt_obj.changed_msg,
diff={ "prepared": {
"old": mt_obj.old_params,
"new": mt_obj.new_params,
}},
)
else:
module.exit_json(
failed=False,
changed=False,
#msg='',
msg=params['settings'],
)
if __name__ == '__main__':
main()