#
# Copyright (c) 2014, Arista Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Arista Networks nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""Module for working the logical IP interfaces in EOS
This module provides an API for configuring logical IP interfaces using
EOS and eAPI.
Parameters:
name (string): The interface name the configuration is in reference
to. The interface name is the full interface identifier
address (string): The interface IP address in the form of
address/len.
mtu (integer): The interface MTU value. The MTU value accepts
integers in the range of 68 to 65535 bytes
"""
import re
from pyeapi.api import EntityCollection
SWITCHPORT_RE = re.compile(r'no switchport$', re.M)
[docs]class Ipinterfaces(EntityCollection):
[docs] def get(self, name):
"""Returns the specific IP interface properties
The Ipinterface resource returns the following:
* name (str): The name of the interface
* address (str): The IP address of the interface in the form
of A.B.C.D/E
* mtu (int): The configured value for IP MTU.
Args:
name (string): The interface identifier to retrieve the
configuration for
Return:
A Python dictionary object of key/value pairs that represents
the current configuration of the node. If the specified
interface does not exist then None is returned.
"""
config = self.get_block('interface %s' % name)
if name[0:2] in ['Et', 'Po'] and not SWITCHPORT_RE.search(config,
re.M):
return None
resource = dict(name=name)
resource.update(self._parse_address(config))
resource.update(self._parse_mtu(config))
return resource
def _parse_address(self, config):
"""Parses the config block and returns the ip address value
The provided configuration block is scaned and the configured value
for the IP address is returned as a dict object. If the IP address
value is not configured, then None is returned for the value
Args:
config (str): The interface configuration block to parse
Return:
dict: A dict object intended to be merged into the resource dict
"""
match = re.search(r'ip address ([^\s]+)', config)
value = match.group(1) if match else None
return dict(address=value)
def _parse_mtu(self, config):
"""Parses the config block and returns the configured IP MTU value
The provided configuration block is scanned and the configured value
for the IP MTU is returned as a dict object. The IP MTU value is
expected to always be present in the provided config block
Args:
config (str): The interface configuration block to parse
Return:
dict: A dict object intended to be merged into the resource dict
"""
match = re.search(r'mtu (\d+)', config)
return dict(mtu=int(match.group(1)))
[docs] def getall(self):
""" Returns all of the IP interfaces found in the running-config
Returns:
A Python dictionary object of key/value pairs keyed by interface
name that represents all of the IP interfaces on
the current node::
{
'Ethernet1': {...},
'Ethernet2': {...}
}
"""
interfaces_re = re.compile(r'^interface\s(.+)', re.M)
response = dict()
for name in interfaces_re.findall(self.config):
interface = self.get(name)
if interface:
response[name] = interface
return response
[docs] def create(self, name):
""" Creates a new IP interface instance
This method will create a new logical IP interface for the specified
physical interface. If a logical IP interface already exists then
this operation will have no effect.
Note:
Configuring a logical IP interface on a physical interface will
remove any existing logical switchports have have been created
Args:
name (string): The interface identifier to create the logical
layer 3 IP interface for. The name must be the full interface
name and not an abbreviated interface name (eg Ethernet1, not
Et1).
Returns:
True if the create operation succeeds otherwise False. If the
specified interface is already created the this method will
have no effect but will still return True
"""
commands = ['interface %s' % name, 'no switchport']
return self.configure(commands)
[docs] def delete(self, name):
""" Deletes an IP interface instance from the running configuration
This method will delete the logical IP interface for the specified
physical interface. If the interface does not have a logical
IP interface defined, then this method will have no effect.
Args:
name (string): The interface identifier to create the logical
layer 3 IP interface for. The name must be the full interface
name and not an abbreviated interface name (eg Ethernet1, not
Et1).
Returns:
True if the delete operation succeeds otherwise False.
"""
commands = ['interface %s' % name, 'no ip address', 'switchport']
return self.configure(commands)
[docs] def set_address(self, name, value=None, default=False, disable=False):
""" Configures the interface IP address
Args:
name (string): The interface identifier to apply the interface
config to
value (string): The IP address and mask to set the interface to.
The value should be in the format of A.B.C.D/E
default (bool): Configures the address parameter to its default
value using the EOS CLI default command
disable (bool): Negates the address parameter value using the
EOS CLI no command
Returns:
True if the operation succeeds otherwise False.
"""
commands = ['interface %s' % name]
commands.append(self.command_builder('ip address', value=value,
default=default, disable=disable))
return self.configure(commands)
[docs] def set_mtu(self, name, value=None, default=False, disable=False):
""" Configures the interface IP MTU
Args:
name (string): The interface identifier to apply the interface
config to
value (integer): The MTU value to set the interface to. Accepted
values include 68 to 65535
default (bool): Configures the mtu parameter to its default
value using the EOS CLI default command
disable (bool); Negate the mtu parameter value using the EOS
CLI no command
Returns:
True if the operation succeeds otherwise False.
Raises:
ValueError: If the value for MTU is not an integer value or
outside of the allowable range
"""
if value is not None:
value = int(value)
if not 68 <= value <= 65535:
raise ValueError('invalid mtu value')
commands = ['interface %s' % name]
commands.append(self.command_builder('mtu', value=value,
default=default, disable=disable))
return self.configure(commands)
[docs]def instance(node):
"""Returns an instance of Ipinterfaces
This method will create and return an instance of the Ipinterfaces object
passing the value of node to the instance. This function is required
for the resource to be autoloaded by the Node object
Args:
node (Node): The node argument provides an instance of Node to
the Ipinterfaces instance
"""
return Ipinterfaces(node)