1#!/usr/bin/python
2
3# (c) 2018-2019, NetApp, Inc
4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6from __future__ import absolute_import, division, print_function
7__metaclass__ = type
8
9ANSIBLE_METADATA = {'metadata_version': '1.1',
10                    'status': ['preview'],
11                    'supported_by': 'certified'}
12
13DOCUMENTATION = '''
14module: na_ontap_net_vlan
15short_description: NetApp ONTAP network VLAN
16extends_documentation_fragment:
17    - netapp.na_ontap
18version_added: '2.6'
19author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com>
20description:
21- Create or Delete a network VLAN
22options:
23  state:
24    description:
25    - Whether the specified network VLAN should exist or not
26    choices: ['present', 'absent']
27    default: present
28  parent_interface:
29    description:
30    - The interface that hosts the VLAN interface.
31    required: true
32  vlanid:
33    description:
34    - The VLAN id. Ranges from 1 to 4094.
35    required: true
36  node:
37    description:
38    - Node name of VLAN interface.
39    required: true
40notes:
41  - The C(interface_name) option has been removed and should be deleted from playbooks
42'''
43
44EXAMPLES = """
45    - name: create VLAN
46      na_ontap_net_vlan:
47        state: present
48        vlanid: 13
49        node: "{{ vlan node }}"
50        parent_interface: "{{ vlan parent interface name }}"
51        username: "{{ netapp_username }}"
52        password: "{{ netapp_password }}"
53        hostname: "{{ netapp_hostname }}"
54"""
55
56RETURN = """
57
58"""
59
60from ansible.module_utils.basic import AnsibleModule
61import ansible.module_utils.netapp as netapp_utils
62
63HAS_NETAPP_LIB = netapp_utils.has_netapp_lib()
64
65
66class NetAppOntapVlan(object):
67    """
68    Created, and destorys Net Vlans's
69    """
70    def __init__(self):
71        """
72        Initializes the NetAppOntapVlan function
73        """
74        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
75        self.argument_spec.update(dict(
76            state=dict(required=False, choices=['present', 'absent'], default='present'),
77            parent_interface=dict(required=True, type='str'),
78            vlanid=dict(required=True, type='str'),
79            node=dict(required=True, type='str'),
80        ))
81
82        self.module = AnsibleModule(
83            argument_spec=self.argument_spec,
84            supports_check_mode=True
85        )
86        p = self.module.params
87
88        # set up state variables
89        self.state = p['state']
90        self.parent_interface = p['parent_interface']
91        self.vlanid = p['vlanid']
92        self.node = p['node']
93        self.interface_name = str(p['parent_interface']) + '-' + str(self.vlanid)
94
95        if HAS_NETAPP_LIB is False:
96            self.module.fail_json(msg="the python NetApp-Lib module is required")
97        else:
98            self.server = netapp_utils.setup_na_ontap_zapi(module=self.module)
99        return
100
101    def create_vlan(self):
102        """
103        Creates a new vlan
104        """
105        vlan_obj = netapp_utils.zapi.NaElement("net-vlan-create")
106        vlan_info = self.create_vlan_info()
107
108        vlan_obj.add_child_elem(vlan_info)
109        self.server.invoke_successfully(vlan_obj, True)
110
111    def delete_vlan(self):
112        """
113        Deletes a vland
114        """
115        vlan_obj = netapp_utils.zapi.NaElement("net-vlan-delete")
116        vlan_info = self.create_vlan_info()
117
118        vlan_obj.add_child_elem(vlan_info)
119        self.server.invoke_successfully(vlan_obj, True)
120
121    def does_vlan_exist(self):
122        """
123        Checks to see if a vlan already exists or not
124        :return: Returns True if the vlan exists, false if it doesn't
125        """
126        vlan_obj = netapp_utils.zapi.NaElement("net-vlan-get")
127        vlan_obj.add_new_child("interface-name", self.interface_name)
128        vlan_obj.add_new_child("node", self.node)
129        try:
130            result = self.server.invoke_successfully(vlan_obj, True)
131            result.get_child_by_name("attributes").get_child_by_name("vlan-info").get_child_by_name("interface-name")
132        except netapp_utils.zapi.NaApiError:
133            return False
134        return True
135
136    def create_vlan_info(self):
137        """
138        Create a vlan_info object to be used in a create/delete
139        :return:
140        """
141        vlan_info = netapp_utils.zapi.NaElement("vlan-info")
142
143        #  set up the vlan_info object:
144        vlan_info.add_new_child("parent-interface", self.parent_interface)
145        vlan_info.add_new_child("vlanid", self.vlanid)
146        vlan_info.add_new_child("node", self.node)
147        return vlan_info
148
149    def apply(self):
150        """
151        check the option in the playbook to see what needs to be done
152        :return:
153        """
154        changed = False
155        result = None
156        results = netapp_utils.get_cserver(self.server)
157        cserver = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=results)
158        netapp_utils.ems_log_event("na_ontap_net_vlan", cserver)
159        existing_vlan = self.does_vlan_exist()
160        if existing_vlan:
161            if self.state == 'absent':  # delete
162                changed = True
163        else:
164            if self.state == 'present':  # create
165                changed = True
166        if changed:
167            if self.module.check_mode:
168                pass
169            else:
170                if self.state == 'present':
171                    self.create_vlan()
172                elif self.state == 'absent':
173                    self.delete_vlan()
174        self.module.exit_json(changed=changed, meta=result)
175
176
177def main():
178    """
179    Creates the NetApp Ontap vlan object, and runs the correct play task.
180    """
181    v = NetAppOntapVlan()
182    v.apply()
183
184
185if __name__ == '__main__':
186    main()
187