mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2024-09-14 20:13:21 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			307 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/python
 | 
						|
# -*- coding: utf-8 -*-
 | 
						|
#    
 | 
						|
# Copyright (C) 2013, Arista Networks <netdevops@aristanetworks.com>
 | 
						|
# 
 | 
						|
# This program is free software: you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License as published by
 | 
						|
# the Free Software Foundation, either version 3 of the License, or
 | 
						|
# (at your option) any later version.
 | 
						|
#
 | 
						|
# This program is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
# GNU General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
#
 | 
						|
DOCUMENTATION = '''
 | 
						|
---
 | 
						|
module: arista_vlan
 | 
						|
version_added: "1.3"
 | 
						|
author: Peter Sprygada
 | 
						|
short_description: Manage VLAN resources
 | 
						|
requirements:
 | 
						|
    - Arista EOS 4.10
 | 
						|
    - Netdev extension for EOS
 | 
						|
description:
 | 
						|
    - Manage VLAN resources on Arista EOS network devices.  This module 
 | 
						|
      requires the Netdev EOS extension to be installed in EOS.  For detailed
 | 
						|
      instructions for installing and using the Netdev module please see 
 | 
						|
      [link]
 | 
						|
options:
 | 
						|
    vlan_id:
 | 
						|
        description:
 | 
						|
            - the vlan id 
 | 
						|
        required: true
 | 
						|
    state:
 | 
						|
        description:
 | 
						|
            - describe the desired state of the vlan related to the config
 | 
						|
        required: false
 | 
						|
        default: 'present'
 | 
						|
        choices: [ 'present', 'absent' ]
 | 
						|
    logging:
 | 
						|
        description:
 | 
						|
            - enables or disables the syslog facility for this module
 | 
						|
        required: false
 | 
						|
        choices: [ 'true', 'false', 'yes', 'no' ]
 | 
						|
    name:
 | 
						|
        description:
 | 
						|
            - a descriptive name for the vlan
 | 
						|
        required: false
 | 
						|
notes:
 | 
						|
    - Requires EOS 4.10 or later 
 | 
						|
    - The Netdev extension for EOS must be installed and active in the 
 | 
						|
      available extensions (show extensions from the EOS CLI)
 | 
						|
    - See http://eos.aristanetworks.com for details
 | 
						|
'''
 | 
						|
 | 
						|
EXAMPLES = '''
 | 
						|
Example playbook entries using the arista_vlan module to manage resource 
 | 
						|
state.  
 | 
						|
   
 | 
						|
  tasks:
 | 
						|
  - name: create vlan 999
 | 
						|
    action: arista_vlan vlan_id=999 logging=true
 | 
						|
    
 | 
						|
  - name: create / edit vlan 999
 | 
						|
    action: arista_vlan vlan_id=999 name=test logging=true
 | 
						|
    
 | 
						|
  - name: remove vlan 999
 | 
						|
    action: arista_vlan vlan_id=999 state=absent logging=true
 | 
						|
    
 | 
						|
'''
 | 
						|
import syslog
 | 
						|
import json
 | 
						|
 | 
						|
class AristaVlan(object):
 | 
						|
    """ This is the base class for managing VLAN resources in EOS network 
 | 
						|
        devices.   This class provides basic CRUD functions for VLAN 
 | 
						|
        resources.  This class acts as a wrapper around the netdev extension
 | 
						|
        in EOS.  You must have the netdev extension installed in order for
 | 
						|
        this module to work properly.   
 | 
						|
        
 | 
						|
        The following commands are implemented in this module:
 | 
						|
            * netdev vlan create
 | 
						|
            * netdev vlan list
 | 
						|
            * netdev vlan show
 | 
						|
            * netdev vlan edit
 | 
						|
            * netdev vlan delete
 | 
						|
    """
 | 
						|
    
 | 
						|
    attributes = ['name']
 | 
						|
 | 
						|
    def __init__(self, module):
 | 
						|
        self.module     = module
 | 
						|
        self.vlan_id    = module.params['vlan_id']
 | 
						|
        self.name       = module.params['name']
 | 
						|
        self.state      = module.params['state']
 | 
						|
        self.logging    = module.boolean(module.params['logging'])
 | 
						|
        
 | 
						|
        
 | 
						|
    @property
 | 
						|
    def changed(self):
 | 
						|
        """ The changed property provides a boolean response if the currently
 | 
						|
            loaded resouces has changed from the resource running in EOS.
 | 
						|
            
 | 
						|
            Returns True if the object is not in sync 
 | 
						|
            Returns False if the object is in sync.
 | 
						|
        """
 | 
						|
        return len(self.updates()) > 0
 | 
						|
        
 | 
						|
    def log(self, entry):
 | 
						|
        """ This method is responsible for sending log messages to the local
 | 
						|
            syslog.
 | 
						|
        """
 | 
						|
        if self.logging:
 | 
						|
            syslog.openlog('ansible-%s' % os.path.basename(__file__))
 | 
						|
            syslog.syslog(syslog.LOG_INFO, entry)
 | 
						|
    
 | 
						|
    def run_command(self, cmd):
 | 
						|
        """ Calls the Ansible module run_command method.  This method will
 | 
						|
            also send a message to syslog with the command name
 | 
						|
        """        
 | 
						|
        self.log("Command: %s" % cmd)
 | 
						|
        return self.module.run_command(cmd.split())
 | 
						|
        
 | 
						|
        
 | 
						|
    def delete(self):
 | 
						|
        """ Deletes an existing VLAN resource from the current running 
 | 
						|
            configuration.  A nonexistent VLAN will return successful for this
 | 
						|
            operation.
 | 
						|
            
 | 
						|
            This method implements the following commands:
 | 
						|
                * netdev vlan delete {vlan_id}
 | 
						|
            
 | 
						|
            Returns nothing if the delete was successful
 | 
						|
            Returns error message if there was a problem deleting the vlan 
 | 
						|
        """
 | 
						|
        cmd = "netdev vlan delete %s" % self.vlan_id
 | 
						|
        (rc, out, err) = self.run_command(cmd)
 | 
						|
        resp = json.loads(out)
 | 
						|
        if resp.get('status') != 200: 
 | 
						|
            rc = resp['status']
 | 
						|
            err = resp['message']
 | 
						|
            out = None
 | 
						|
        return (rc, out, err)
 | 
						|
        
 | 
						|
    def create(self):
 | 
						|
        """ Creates a VLAN resource in the current running configuration.  If 
 | 
						|
            the VLAN already exists, the function will return successfully.
 | 
						|
            
 | 
						|
            This function implements the following commands:
 | 
						|
                * netdev vlan create {vlan_id} [--name <name>]
 | 
						|
            
 | 
						|
            Returns the VLAN resource if the create function was successful
 | 
						|
            Returns an error message if there as a problem creating the vlan
 | 
						|
        """
 | 
						|
        attribs = []
 | 
						|
        for attrib in self.attributes:
 | 
						|
            if getattr(self, attrib):
 | 
						|
                attribs.append("--%s" % attrib)
 | 
						|
                attribs.append(getattr(self, attrib))
 | 
						|
        
 | 
						|
            cmd = "netdev vlan create %s " % self.vlan_id
 | 
						|
            cmd += " ".join(attribs)
 | 
						|
            
 | 
						|
            (rc, out, err) = self.run_command(cmd)
 | 
						|
            resp = json.loads(out)
 | 
						|
            if resp.get('status') != 201:
 | 
						|
                rc = int(resp['status'])
 | 
						|
                err = resp['message']
 | 
						|
                out = None
 | 
						|
            else:
 | 
						|
                out = resp['result']
 | 
						|
        return (rc, out, err)
 | 
						|
        
 | 
						|
    def update(self):
 | 
						|
        """ Updates an existing VLAN resource in the current running 
 | 
						|
            configuration.   If the VLAN resource does not exist, this method
 | 
						|
            will return an error.
 | 
						|
            
 | 
						|
            This method implements the following commands:
 | 
						|
                * netdev vlan edit {vlan_id} [--name <name>]
 | 
						|
            
 | 
						|
            Returns an updated VLAN resoure if the create method was successful
 | 
						|
        """
 | 
						|
        attribs = list()        
 | 
						|
        for attrib in self.updates():
 | 
						|
            attribs.append("--%s" % attrib)
 | 
						|
            attribs.append(getattr(self, attrib))
 | 
						|
        
 | 
						|
        if attribs:
 | 
						|
            cmd = "netdev vlan edit %s " % self.vlan_id
 | 
						|
            cmd += " ".join(attribs)
 | 
						|
        
 | 
						|
            (rc, out, err) = self.run_command(cmd)
 | 
						|
            resp = json.loads(out)
 | 
						|
            if resp.get('status') != 200:
 | 
						|
                rc = int(resp['status'])
 | 
						|
                err = resp['message']
 | 
						|
                out = None
 | 
						|
            else:
 | 
						|
                out = resp['result']
 | 
						|
            return (rc, out, err)
 | 
						|
          
 | 
						|
        return (0, None, "No attributes have been modified")
 | 
						|
    
 | 
						|
    def updates(self):
 | 
						|
        """ This method will check the current VLAN resource in the running
 | 
						|
            configuration and return a list of attributes that are not in sync
 | 
						|
            with the current resource from the running configuration.
 | 
						|
        """
 | 
						|
        obj = self.get()
 | 
						|
        update = lambda a, z: a != z
 | 
						|
        
 | 
						|
        updates = list()
 | 
						|
        for attrib in self.attributes:
 | 
						|
            value = getattr(self, attrib)
 | 
						|
            if update(obj[attrib], update) and value is not None:
 | 
						|
                updates.append(attrib)
 | 
						|
        self.log("updates: %s" % updates)
 | 
						|
        return updates
 | 
						|
        
 | 
						|
    def exists(self):
 | 
						|
        """ Returns True if the current VLAN resource exists and returns False
 | 
						|
            if it does not.   This method only checks for the existence of the
 | 
						|
            VLAN ID.
 | 
						|
        """
 | 
						|
        (rc, out, err) = self.run_command("netdev vlan list")
 | 
						|
        collection = json.loads(out)
 | 
						|
        return str(self.vlan_id) in collection.get('result')
 | 
						|
        
 | 
						|
    def get(self):
 | 
						|
        """ This method will return a dictionary with the attributes of the
 | 
						|
            VLAN resource identified in vlan_id.   The VLAN resource has the 
 | 
						|
            following stucture:
 | 
						|
            
 | 
						|
              {
 | 
						|
                "vlan_id": <vlan_id>,
 | 
						|
                "name": <name>
 | 
						|
              }
 | 
						|
            
 | 
						|
            If the VLAN ID specified by vlan_id does not exist in the system, 
 | 
						|
            this method will return None
 | 
						|
        """
 | 
						|
        cmd = "netdev vlan show %s" % self.vlan_id
 | 
						|
        (rc, out, err) = self.run_command(cmd)
 | 
						|
        obj = json.loads(out)
 | 
						|
        if obj.get('status') != 200: 
 | 
						|
            return None
 | 
						|
        return obj['result']
 | 
						|
        
 | 
						|
        
 | 
						|
 | 
						|
def main():
 | 
						|
 | 
						|
    module = AnsibleModule(
 | 
						|
        argument_spec = dict(
 | 
						|
            vlan_id=dict(default=None, required=True, type='int'),
 | 
						|
            name=dict(default=None, type='str'),
 | 
						|
            state=dict(default='present', choices=['present', 'absent']),
 | 
						|
            logging=dict(default=False, type='bool')
 | 
						|
        ),
 | 
						|
        supports_check_mode = True
 | 
						|
    )
 | 
						|
    
 | 
						|
    obj = AristaVlan(module)
 | 
						|
    
 | 
						|
    rc = None
 | 
						|
    result = dict()
 | 
						|
    
 | 
						|
    if obj.state == 'absent':
 | 
						|
        if obj.exists():
 | 
						|
            if module.check_mode: 
 | 
						|
                module.exit_json(changed=True)
 | 
						|
            (rc, out, err) = obj.delete()
 | 
						|
            if rc !=0: 
 | 
						|
                module.fail_json(msg=err, rc=rc)                
 | 
						|
            
 | 
						|
    elif obj.state == 'present':
 | 
						|
        if not obj.exists():
 | 
						|
            if module.check_mode: 
 | 
						|
                module.exit_json(changed=True)
 | 
						|
            (rc, out, err) = obj.create()
 | 
						|
            result['results'] = out
 | 
						|
        else:
 | 
						|
            if obj.changed:
 | 
						|
                if module.check_mode: 
 | 
						|
                    module.exit_json(changed=obj.changed)
 | 
						|
                (rc, out, err) = obj.update()
 | 
						|
                result['results'] = out
 | 
						|
            
 | 
						|
        if rc is not None and rc != 0:
 | 
						|
            module.fail_json(msg=err, rc=rc)
 | 
						|
    
 | 
						|
    if rc is None:
 | 
						|
        result['changed'] = False
 | 
						|
    else:
 | 
						|
        result['changed'] = True
 | 
						|
    
 | 
						|
    module.exit_json(**result)
 | 
						|
    
 | 
						|
 | 
						|
# import module snippets
 | 
						|
from ansible.module_utils.basic import *
 | 
						|
main()
 |