1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Ansible module to manage PaloAltoNetworks Firewall
5# (c) 2016, techbizdev <techbizdev@paloaltonetworks.com>
6#
7# This file is part of Ansible
8#
9# Ansible is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# Ansible is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
21
22DOCUMENTATION = '''
23---
24module: panos_mgtconfig
25short_description: configure management settings of device
26description:
27    - Configure management settings of device
28author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)"
29version_added: "2.3"
30requirements:
31    - pan-python
32deprecated:
33    alternative: Use U(https://galaxy.ansible.com/PaloAltoNetworks/paloaltonetworks) instead.
34    removed_in: "2.12"
35    why: Consolidating code base.
36options:
37    dns_server_primary:
38        description:
39            - address of primary DNS server
40    dns_server_secondary:
41        description:
42            - address of secondary DNS server
43    panorama_primary:
44        description:
45            - address of primary Panorama server
46    panorama_secondary:
47        description:
48            - address of secondary Panorama server
49    commit:
50        description:
51            - commit if changed
52        type: bool
53        default: 'yes'
54extends_documentation_fragment: panos
55'''
56
57EXAMPLES = '''
58- name: set dns and panorama
59  panos_mgtconfig:
60    ip_address: "192.168.1.1"
61    password: "admin"
62    dns_server_primary: "1.1.1.1"
63    dns_server_secondary: "1.1.1.2"
64    panorama_primary: "1.1.1.3"
65    panorama_secondary: "1.1.1.4"
66'''
67
68RETURN = '''
69# Default return values
70'''
71
72ANSIBLE_METADATA = {'metadata_version': '1.1',
73                    'status': ['deprecated'],
74                    'supported_by': 'community'}
75
76
77from ansible.module_utils.basic import AnsibleModule
78from ansible.module_utils._text import to_native
79
80try:
81    import pan.xapi
82    from pan.xapi import PanXapiError
83    HAS_LIB = True
84except ImportError:
85    HAS_LIB = False
86
87_XPATH_DNS_SERVERS = "/config/devices/entry[@name='localhost.localdomain']" +\
88                     "/deviceconfig/system/dns-setting/servers"
89_XPATH_PANORAMA_SERVERS = "/config" +\
90                          "/devices/entry[@name='localhost.localdomain']" +\
91                          "/deviceconfig/system"
92
93
94def set_dns_server(xapi, new_dns_server, primary=True):
95    if primary:
96        tag = "primary"
97    else:
98        tag = "secondary"
99    xpath = _XPATH_DNS_SERVERS + "/" + tag
100
101    # check the current element value
102    xapi.get(xpath)
103    val = xapi.element_root.find(".//" + tag)
104    if val is not None:
105        # element exists
106        val = val.text
107    if val == new_dns_server:
108        return False
109
110    element = "<%(tag)s>%(value)s</%(tag)s>" %\
111              dict(tag=tag, value=new_dns_server)
112    xapi.edit(xpath, element)
113
114    return True
115
116
117def set_panorama_server(xapi, new_panorama_server, primary=True):
118    if primary:
119        tag = "panorama-server"
120    else:
121        tag = "panorama-server-2"
122    xpath = _XPATH_PANORAMA_SERVERS + "/" + tag
123
124    # check the current element value
125    xapi.get(xpath)
126    val = xapi.element_root.find(".//" + tag)
127    if val is not None:
128        # element exists
129        val = val.text
130    if val == new_panorama_server:
131        return False
132
133    element = "<%(tag)s>%(value)s</%(tag)s>" %\
134              dict(tag=tag, value=new_panorama_server)
135    xapi.edit(xpath, element)
136
137    return True
138
139
140def main():
141    argument_spec = dict(
142        ip_address=dict(required=True),
143        password=dict(required=True, no_log=True),
144        username=dict(default='admin'),
145        dns_server_primary=dict(),
146        dns_server_secondary=dict(),
147        panorama_primary=dict(),
148        panorama_secondary=dict(),
149        commit=dict(type='bool', default=True)
150    )
151    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False)
152    if not HAS_LIB:
153        module.fail_json(msg='pan-python is required for this module')
154
155    ip_address = module.params["ip_address"]
156    password = module.params["password"]
157    username = module.params['username']
158    dns_server_primary = module.params['dns_server_primary']
159    dns_server_secondary = module.params['dns_server_secondary']
160    panorama_primary = module.params['panorama_primary']
161    panorama_secondary = module.params['panorama_secondary']
162    commit = module.params['commit']
163
164    xapi = pan.xapi.PanXapi(
165        hostname=ip_address,
166        api_username=username,
167        api_password=password
168    )
169
170    changed = False
171    try:
172        if dns_server_primary is not None:
173            changed |= set_dns_server(xapi, dns_server_primary, primary=True)
174        if dns_server_secondary is not None:
175            changed |= set_dns_server(xapi, dns_server_secondary, primary=False)
176        if panorama_primary is not None:
177            changed |= set_panorama_server(xapi, panorama_primary, primary=True)
178        if panorama_secondary is not None:
179            changed |= set_panorama_server(xapi, panorama_secondary, primary=False)
180
181        if changed and commit:
182            xapi.commit(cmd="<commit></commit>", sync=True, interval=1)
183    except PanXapiError as exc:
184        module.fail_json(msg=to_native(exc))
185
186    module.exit_json(changed=changed, msg="okey dokey")
187
188
189if __name__ == '__main__':
190    main()
191