Source code for pyeapi.api.stp

#
# 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 with spanning-tree in EOS

This module provides an API for working with spanning-tree configuration
in EOS.  This includes both global spanning-tree configuration as well as
interface config.

Global Parameters:
    mode (string): The spanning-tree operational mode.  Accepted values
        for this version are 'mstp' or 'none'.  This configuration
        parameter is not defaultable

    interfaces (StpInterfaces): The collection of STP enabled interfaces.

Interface Parameters:
    name (string): The name of the interface the STP configuration is in
        reference to.  The interface name is the full interface identifier

    portfast (string): The portfast configuration value for the interface.
        Accepted values are 'edge', 'network', or 'disabled'

    bpduguard (boolean): True if the BPDU Guard feature is enabled on the
        interface or False if it is disabled
"""

import re

from pyeapi.api import Entity, EntityCollection


[docs]class Stp(Entity): """The Stp class implements global configuration for spanning-tree The spanning-tree protocol provides both global and interface configuration options. This class is the top-level class that provides access to all spanning-tree configuration options supported. Example: The below example demonstrates how to use the STP class to work with both global configuration and interface configuration. >>> import pyeapi.resources.stp >>> stp = pyeapi.resources.stp.instance(node) >>> stp.set_mode('mstp') True >>> stp.interfaces.set_bpduguard('Ethernet1', True) True Attributes: interfaces (StpInterfaces): An instance for configuration spanning-tree configuration interfaces instances (StpInstances): An instance object for working with spanning-tree global instances """ def __init__(self, *args, **kwargs): super(Stp, self).__init__(*args, **kwargs) self._interfaces = None self._instances = None
[docs] def get(self): """Returns the spanning-tree configuration as a dict object The dictionary object represents the entire spanning-tree configuration derived from the nodes running config. This includes both globally configuration attributes as well as interfaces and instances. See the StpInterfaces and StpInstances classes for the key/value pair definitions. Note: See the individual classes for detailed message structures Returns: A Python dictionary object of key/value pairs the represent the entire supported spanning-tree configuration:: { "mode": [mstp, none], "interfaces": {...}, "instances": {...} } """ return dict(interfaces=self.interfaces.getall(), instances=self.instances.getall())
@property def interfaces(self): if self._interfaces is not None: return self._interfaces self._interfaces = StpInterfaces(self.node) return self._interfaces @property def instances(self): if self._instances is not None: return self._instances self._instances = StpInstances(self.node) return self._instances
[docs] def set_mode(self, value=None, default=False, disable=False): """Configures the global spanning-tree mode Note: This configuration parameter is not defaultable Args: value (string): The value to configure the global spanning-tree mode of operation. Valid values include 'mstp', 'none' default (bool): Set the global spanning-tree mode to default. disable (bool): Negate the global spanning-tree mode. Returns: True if the configuration operation succeeds otherwise False Raises: ValueError if the value is not in the accepted range """ if not default and not disable: if value not in ['mstp', 'none']: raise ValueError("Specified value must be one of " "'mstp', 'none'") cmds = self.command_builder('spanning-tree mode', value=value, default=default, disable=disable) return self.configure(cmds)
[docs]class StpInstances(EntityCollection): """Provides a configuration resource for spanning-tree instances This class provides an API for working with spanning-tree instances from the global configuration. Spanning tree instances work with MST configuration """
[docs] def getall(self): # TODO: (privateip, 20150106) stubbed out, needs implementation return dict()
[docs]class StpInterfaces(EntityCollection): """Provides a configuration resource for spanning-tree interfaces This class provides an API for working with spanning-tree interface configurations. It provides access to managing specific interface spanning-tree configuration options. Note that spanning-tree interfaces cannot be created or deleted. """
[docs] def get(self, name): """Returns the specified interfaces STP configuration resource The STP interface resource contains the following * name (str): The interface name * portfast (bool): The spanning-tree portfast admin state * bpduguard (bool): The spanning-tree bpduguard admin state * portfast_type (str): The spanning-tree portfast <type> value. Valid values include "edge", "network", "normal" Args: name (string): The interface identifier to retrieve the config for. Note: Spanning-tree interfaces are only supported on Ethernet and Port-Channel interfaces Returns: dict: A resource dict object that represents the interface configuration. None: If the specified interace is not a STP port """ if not isvalidinterface(name): return None config = self.get_block(r'^interface\s%s$' % name) resp = dict() resp.update(self._parse_bpduguard(config)) resp.update(self._parse_portfast(config)) resp.update(self._parse_portfast_type(config)) return resp
def _parse_bpduguard(self, config): value = 'spanning-tree bpduguard enable' in config return dict(bpduguard=value) def _parse_portfast(self, config): value = 'no spanning-tree portfast' not in config return dict(portfast=value) def _parse_portfast_type(self, config): if 'spanning-tree portfast network' in config: value = 'network' elif 'no spanning-tree portfast' in config: value = 'normal' else: value = 'edge' return dict(portfast_type=value)
[docs] def getall(self): """Returns the collection of STP interfaces This method will return all of the configured spanning-tree interfaces from the current nodes configuration. Returns: A Python dictionary object that represents all configured spanning-tree interfaces indexed by interface name. """ interfaces_re = re.compile(r'(?<=^interface\s)(.+)$', re.M) response = dict() for name in interfaces_re.findall(self.config): if name[0:2] in ['Et', 'Po']: interface = self.get(name) if interface: response[name] = interface return response
[docs] def configure_interface(self, name, cmds): if not isvalidinterface(name): raise ValueError('invalid interface value specified') return super(StpInterfaces, self).configure_interface(name, cmds)
[docs] def set_portfast_type(self, name, value='normal'): """Configures the portfast value for the specified interface Args: name (string): The interface identifier to configure. The name must be the full interface name (eg Ethernet1, not Et1). value (string): The value to configure the portfast setting to. Valid values include "edge", "network", "normal". The default value is "normal" Returns: True if the command succeeds, otherwise False Raises: ValueError: Raised if an invalid interface name or value is specified """ if value not in ['network', 'edge', 'normal', None]: raise ValueError('invalid portfast type value specified') cmds = ['spanning-tree portfast %s' % value] if value == 'edge': cmds.append('spanning-tree portfast auto') return self.configure_interface(name, cmds)
[docs] def set_portfast(self, name, value=None, default=False, disable=False): """Configures the portfast value for the specified interface Args: name (string): The interface identifier to configure. The name must be the full interface name (eg Ethernet1, not Et1) value (bool): True if portfast is enabled otherwise False default (bool): Configures the portfast parameter to its default value using the EOS CLI default config command disable (bool): Negates the portfast parameter using the EOS CLI no config command Returns: True if the command succeeds, otherwise False Raises: ValueError: Rasied if an invalid interface name is specified TypeError: Raised if the value keyword argument does not evaluate to a valid boolean """ if value is False: disable = True string = 'spanning-tree portfast' cmds = self.command_builder(string, value=value, default=default, disable=disable) return self.configure_interface(name, cmds)
[docs] def set_bpduguard(self, name, value=False, default=False, disable=False): """Configures the bpduguard value for the specified interface Args: name (string): The interface identifier to configure. The name must be the full interface name (eg Ethernet1, not Et1) value (bool): True if bpduguard is enabled otherwise False default (bool): Configures the bpduguard parameter to its default value using the EOS CLI default config command disable (bool): Negates the bpduguard parameter using the EOS CLI no config command Returns: True if the command succeeds, otherwise False Raises: ValueError: Rasied if an invalid interface name is specified TypeError: Raised if the value keyword argument does not evaluate to a valid boolean """ value = 'enable' if value else 'disable' string = 'spanning-tree bpduguard' cmds = self.command_builder(string, value=value, default=default, disable=disable) return self.configure_interface(name, cmds)
[docs]def isvalidinterface(value): """Checks value to see if it could be a spanning-tree interface This function will check the value and return a boolean whether or not the interface could be a spanning-tree interface Note: This function only checks *if* the interface could be a spanning-tree interface but does not check if it *is* configured as a spanning-tree interface Args: value (string): The interface name to validate Returns: True if it could be a spanning-tree interface, otherwise False """ return value[0:2] in ['Et', 'Po']
[docs]def instance(api): return Stp(api)