1#!/usr/bin/python
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17#
18
19ANSIBLE_METADATA = {'metadata_version': '1.1',
20                    'status': ['preview'],
21                    'supported_by': 'community'}
22
23DOCUMENTATION = '''
24---
25module: ce_evpn_global
26version_added: "2.4"
27short_description: Manages global configuration of EVPN on HUAWEI CloudEngine switches.
28description:
29    - Manages global configuration of EVPN on HUAWEI CloudEngine switches.
30author: Zhijin Zhou (@QijunPan)
31notes:
32    - Before configuring evpn_overlay_enable=disable, delete other EVPN configurations.
33    - Recommended connection is C(network_cli).
34    - This module also works with C(local) connections for legacy playbooks.
35options:
36    evpn_overlay_enable:
37        description:
38            - Configure EVPN as the VXLAN control plane.
39        required: true
40        choices: ['enable','disable']
41'''
42
43EXAMPLES = '''
44- name: evpn global module test
45  hosts: cloudengine
46  connection: local
47  gather_facts: no
48  vars:
49    cli:
50      host: "{{ inventory_hostname }}"
51      port: "{{ ansible_ssh_port }}"
52      username: "{{ username }}"
53      password: "{{ password }}"
54      transport: cli
55
56  tasks:
57
58  - name: Configure EVPN as the VXLAN control plan
59    ce_evpn_global:
60      evpn_overlay_enable: enable
61      provider: "{{ cli }}"
62
63  - name: Undo EVPN as the VXLAN control plan
64    ce_evpn_global:
65      evpn_overlay_enable: disable
66      provider: "{{ cli }}"
67'''
68
69RETURN = '''
70proposed:
71    description: k/v pairs of parameters passed into module
72    returned: always
73    type: dict
74    sample: {
75                "evpn_overlay_enable": "enable"
76            }
77existing:
78    description: k/v pairs of existing attributes on the device
79    returned: always
80    type: dict
81    sample: {
82                "evpn_overlay_enable": "disable"
83            }
84end_state:
85    description: k/v pairs of end attributes on the interface
86    returned: always
87    type: dict
88    sample: {
89                "evpn_overlay_enable": "enable"
90            }
91updates:
92    description: command list sent to the device
93    returned: always
94    type: list
95    sample: [
96                "evpn-overlay enable",
97            ]
98changed:
99    description: check to see if a change was made on the device
100    returned: always
101    type: bool
102    sample: true
103'''
104
105
106from ansible.module_utils.basic import AnsibleModule
107from ansible.module_utils.network.cloudengine.ce import exec_command, load_config
108from ansible.module_utils.network.cloudengine.ce import ce_argument_spec
109
110
111class EvpnGlobal(object):
112    """Manage global configuration of EVPN"""
113
114    def __init__(self, argument_spec, ):
115        self.spec = argument_spec
116        self.module = None
117        self.init_module()
118
119        # EVPN global configuration parameters
120        self.overlay_enable = self.module.params['evpn_overlay_enable']
121
122        self.commands = list()
123        self.global_info = dict()
124        self.conf_exist = False
125        # state
126        self.changed = False
127        self.updates_cmd = list()
128        self.results = dict()
129        self.proposed = dict()
130        self.existing = dict()
131        self.end_state = dict()
132
133    def init_module(self):
134        """init_module"""
135        self.module = AnsibleModule(
136            argument_spec=self.spec, supports_check_mode=True)
137
138    def cli_load_config(self, commands):
139        """load config by cli"""
140        if not self.module.check_mode:
141            load_config(self.module, commands)
142
143    def cli_add_command(self, command, undo=False):
144        """add command to self.update_cmd and self.commands"""
145        if undo and command.lower() not in ["quit", "return"]:
146            cmd = "undo " + command
147        else:
148            cmd = command
149
150        self.commands.append(cmd)          # set to device
151        if command.lower() not in ["quit", "return"]:
152            self.updates_cmd.append(cmd)   # show updates result
153
154    def get_evpn_global_info(self):
155        """ get current EVPN global configuration"""
156
157        self.global_info['evpnOverLay'] = 'disable'
158        cmd = "display current-configuration | include ^evpn-overlay enable"
159        rc, out, err = exec_command(self.module, cmd)
160        if rc != 0:
161            self.module.fail_json(msg=err)
162        if out:
163            self.global_info['evpnOverLay'] = 'enable'
164
165    def get_existing(self):
166        """get existing config"""
167        self.existing = dict(
168            evpn_overlay_enable=self.global_info['evpnOverLay'])
169
170    def get_proposed(self):
171        """get proposed config"""
172        self.proposed = dict(evpn_overlay_enable=self.overlay_enable)
173
174    def get_end_state(self):
175        """get end config"""
176        self.get_evpn_global_info()
177        self.end_state = dict(
178            evpn_overlay_enable=self.global_info['evpnOverLay'])
179
180    def show_result(self):
181        """ show result"""
182        self.results['changed'] = self.changed
183        self.results['proposed'] = self.proposed
184        self.results['existing'] = self.existing
185        self.results['end_state'] = self.end_state
186        if self.changed:
187            self.results['updates'] = self.updates_cmd
188        else:
189            self.results['updates'] = list()
190
191        self.module.exit_json(**self.results)
192
193    def judge_if_config_exist(self):
194        """ judge whether configuration has existed"""
195        if self.overlay_enable == self.global_info['evpnOverLay']:
196            return True
197
198        return False
199
200    def config_evnp_global(self):
201        """ set global EVPN configuration"""
202        if not self.conf_exist:
203            if self.overlay_enable == 'enable':
204                self.cli_add_command('evpn-overlay enable')
205            else:
206                self.cli_add_command('evpn-overlay enable', True)
207
208            if self.commands:
209                self.cli_load_config(self.commands)
210                self.changed = True
211
212    def work(self):
213        """execute task"""
214        self.get_evpn_global_info()
215        self.get_existing()
216        self.get_proposed()
217        self.conf_exist = self.judge_if_config_exist()
218
219        self.config_evnp_global()
220
221        self.get_end_state()
222        self.show_result()
223
224
225def main():
226    """main function entry"""
227
228    argument_spec = dict(
229        evpn_overlay_enable=dict(
230            required=True, type='str', choices=['enable', 'disable']),
231    )
232    argument_spec.update(ce_argument_spec)
233    evpn_global = EvpnGlobal(argument_spec)
234    evpn_global.work()
235
236
237if __name__ == '__main__':
238    main()
239