Ejemplo n.º 1
0
        class VrfAttributes(VrfSubAttributes):

            rd = Vrf.rd.copy()

            @rd.defaulter
            def rd(self):
                vrf = self.vrf
                return vrf and vrf.rd

            address_families = managedattribute(
                name='address_families',
                finit=typedset(AddressFamily).copy,
                type=typedset(AddressFamily)._from_iterable)

            @address_families.defaulter
            def address_families(self):
                return self.parent.address_families.copy()

            class AddressFamilyAttributes(AddressFamilySubAttributes):
                pass

            address_family_attr = managedattribute(
                name='address_family_attr',
                read_only=True,
                doc=AddressFamilySubAttributes.__doc__)

            @address_family_attr.initter
            def address_family_attr(self):
                return SubAttributesDict(self.AddressFamilyAttributes,
                                        parent=self)

            class NeighborAttributes(IPNeighborSubAttributes):

                address_families = managedattribute(
                    name='address_families',
                    finit=typedset(AddressFamily).copy,
                    type=typedset(AddressFamily)._from_iterable)

                @address_families.defaulter
                def address_families(self):
                    return self.parent.address_families.copy()

                class AddressFamilyAttributes(AddressFamilySubAttributes):
                    pass

                address_family_attr = managedattribute(
                    name='address_family_attr',
                    read_only=True,
                    doc=AddressFamilySubAttributes.__doc__)

                @address_family_attr.initter
                def address_family_attr(self):
                    return SubAttributesDict(self.AddressFamilyAttributes,
                                             parent=self)


            neighbor_attr = managedattribute(
                name='neighbor_attr',
                read_only=True,
                doc=NeighborAttributes.__doc__)

            @neighbor_attr.initter
            def neighbor_attr(self):
                return SubAttributesDict(self.NeighborAttributes, parent=self)

            router_id = managedattribute(
                name='router_id',
                default=None,
                type=(None, IPv4Address))

            neighbors = managedattribute(
                name='neighbors',
                finit=set,
                type=managedattribute.test_set_of(IPNeighbor),
                gettype=frozenset)

            neighbors = managedattribute(
                name='neighbors',
                finit=typedset(IPNeighbor).copy,
                type=typedset(IPNeighbor)._from_iterable)

            def add_neighbor(self, neighbor):  # TODO DEPRECATE
                self.neighbors.add(neighbor)

            def remove_neighbor(self, neighbor):  # TODO DEPRECATE
                self.neighbors.remove(neighbor)
Ejemplo n.º 2
0
class Vfi(ConfigurableBase):

    container = None  # BridgeDomain

    device = managedattribute(
        name='device',
        read_only=True,
        gettype=managedattribute.auto_unref)

    name = managedattribute(
        name='name',
        read_only=True)  # read-only hash key

    virtual = managedattribute(
        name='virtual',
        default=False,
        type=(None, managedattribute.test_istype(bool)))

    shutdown = managedattribute(
        name='shutdown',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    vpn_id = managedattribute(
        name='vpn_id',
        default=None,
        type=(None, managedattribute.test_istype(int)))

    class AutodiscoveryBgpAttributes(ConfigurableVfiNamespace):

        enabled = managedattribute(
            name='enabled',
            default=False,
            type=managedattribute.test_istype(bool))

        control_word = managedattribute(
            name='control_word',
            default=None,
            type=(None, managedattribute.test_istype(bool)))

        rd = managedattribute(
            name='rd',
            default=None,
            type=(None, RouteDistinguisher,
                  managedattribute.test_in((
                      'auto',
                  ))))

        export_route_policy = managedattribute(
            name='export_route_policy',
            default=None,
            type=(None, managedattribute.test_istype(str)))

        export_route_targets = managedattribute(
            name='export_route_targets',
            finit=typedset(RouteTarget.ImportExport).copy,
            type=typedset(RouteTarget.ImportExport)._from_iterable)

        import_route_targets = managedattribute(
            name='import_route_targets',
            finit=typedset(RouteTarget.ImportExport).copy,
            type=typedset(RouteTarget.ImportExport)._from_iterable)

        table_policy = managedattribute(
            name='table_policy',
            default=None,
            type=(None, managedattribute.test_istype(str)))

        class SignalingProtocolBgpAttributes(ConfigurableVfiNamespace):

            enabled = managedattribute(
                name='enabled',
                default=False,
                type=managedattribute.test_istype(bool))

            ve_id = managedattribute(
                name='ve_id',
                default=None,
                type=(None, managedattribute.test_istype(int)))

            ve_range = managedattribute(
                name='ve_range',
                default=None,
                type=(None,
                      managedattribute.test_istype(int),
                      managedattribute.test_istype(str)))

        signaling_protocol_bgp = managedattribute(
            name='signaling_protocol_bgp',
            read_only=True,
            doc=SignalingProtocolBgpAttributes.__doc__)

        @signaling_protocol_bgp.initter
        def signaling_protocol_bgp(self):
            return self.SignalingProtocolBgpAttributes(vfi=self.vfi)

        class SignalingProtocolLdpAttributes(ConfigurableVfiNamespace):

            enabled = managedattribute(
                name='enabled',
                default=False,
                type=managedattribute.test_istype(bool))

            vpls_id = managedattribute(
                name='vpls_id',
                default=None,
                type=(None, RouteTarget))

        signaling_protocol_ldp = managedattribute(
            name='signaling_protocol_ldp',
            read_only=True,
            doc=SignalingProtocolLdpAttributes.__doc__)

        @signaling_protocol_ldp.initter
        def signaling_protocol_ldp(self):
            return self.SignalingProtocolLdpAttributes(vfi=self.vfi)

        def __init__(self, vfi):
            super().__init__(vfi=vfi)

    autodiscovery_bgp = managedattribute(
        name='autodiscovery_bgp',
        read_only=True,
        doc=AutodiscoveryBgpAttributes.__doc__)

    @autodiscovery_bgp.initter
    def autodiscovery_bgp(self):
        return self.AutodiscoveryBgpAttributes(vfi=self)

    class MulticastP2mpAttributes(ConfigurableVfiNamespace):

        class SignalingProtocolBgpAttributes(ConfigurableVfiNamespace):

            enabled = managedattribute(
                name='enabled',
                default=False,
                type=managedattribute.test_istype(bool))

        signaling_protocol_bgp = managedattribute(
            name='signaling_protocol_bgp',
            read_only=True,
            doc=SignalingProtocolBgpAttributes.__doc__)

        @signaling_protocol_bgp.initter
        def signaling_protocol_bgp(self):
            return self.SignalingProtocolBgpAttributes(vfi=self.vfi)

        class TransportRsvpTeAttributes(ConfigurableVfiNamespace):

            enabled = managedattribute(
                name='enabled',
                default=False,
                type=managedattribute.test_istype(bool))

            attribute_set_p2mp_te = managedattribute(
                name='attribute_set_p2mp_te',
                default=None,
                type=(None, managedattribute.test_istype(str)))

        transport_rsvp_te = managedattribute(
            name='transport_rsvp_te',
            read_only=True,
            doc=TransportRsvpTeAttributes.__doc__)

        @transport_rsvp_te.initter
        def transport_rsvp_te(self):
            return self.TransportRsvpTeAttributes(vfi=self.vfi)

        def __init__(self, vfi):
            super().__init__(vfi=vfi)

    multicast_p2mp = managedattribute(
        name='multicast_p2mp',
        read_only=True,
        doc=MulticastP2mpAttributes.__doc__)

    @multicast_p2mp.initter
    def multicast_p2mp(self):
        return self.MulticastP2mpAttributes(vfi=self)

    # TODO Cannot use typedset because segments need to be updated
    pseudowires = managedattribute(
        name='pseudowires',
        finit=set,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(Pseudowire)),
        gettype=frozenset,
        doc='A `set` of Pseudowire associated objects')

    def add_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires |= {pseudowire}
        self._on_segments_updated(prev_segments)

    def remove_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires -= {pseudowire}
        self._on_segments_updated(prev_segments)

    @property
    def pseudowire_neighbors(self):
        for pw in self.pseudowires:
            for nbr in pw.neighbors:
                if nbr.container is self:
                    # implied: nbr.device is self.device
                    yield nbr

    def create_pseudowire_neighbor(self, **kwargs):
        pwnbr = PseudowireNeighbor(container=self,
                                   device=self.device,
                                   **kwargs)
        return pwnbr

    @property
    def segments(self):
        segments = []
        segments += list(self.pseudowires)
        return frozenset(segments)

    def add_segment(self, segment):
        if isinstance(segment, Pseudowire):
            self.add_pseudowire(segment)
        else:
            raise ValueError(segment)

    def remove_segment(self, segment):
        if isinstance(segment, Pseudowire):
            self.remove_pseudowire(segment)
        else:
            raise ValueError(segment)

    def _on_segments_updated(self, prev_segments):
        pass  # TODO

    class NeighborAttributes(PseudowireNeighborSubAttributes):

        # ip -> self.neighbor.ip
        # pw_id -> self.neighbor.pw_id

        dhcp_ipv4_snooping_profile = managedattribute(
            name='dhcp_ipv4_snooping_profile',
            default=None,
            type=(None,
                  managedattribute.test_is(False),  # False
                  managedattribute.test_istype(str),  # <profile>
                  ))

        igmp_snooping_profile = managedattribute(
            name='igmp_snooping_profile',
            default=None,
            type=(None,
                  managedattribute.test_is(False),  # False
                  managedattribute.test_istype(str),  # <profile>
                  ))

        mld_snooping_profile = managedattribute(
            name='mld_snooping_profile',
            default=None,
            type=(None,
                  managedattribute.test_is(False),  # False
                  managedattribute.test_istype(str),  # <profile>
                  ))

        mpls_static_label = managedattribute(
            name='mpls_static_label',
            default=None,
            type=(None,
                  managedattribute.test_istype(int)))

        pw_class = managedattribute(
            name='pw_class',
            default=None,
            type=(None,
                  managedattribute.test_isinstance(PseudowireClass)))

        static_mac_address = managedattribute(
            name='static_mac_address',
            default=None,
            type=(None, MAC))

    neighbor_attr = managedattribute(
        name='neighbor_attr',
        read_only=True,
        doc=NeighborAttributes.__doc__)

    @neighbor_attr.initter
    def neighbor_attr(self):
        return SubAttributesDict(self.NeighborAttributes, parent=self)

    def __init__(self, name, device, bridge_domain=None, *args, **kwargs):
        assert isinstance(name, str)
        self._name = name
        assert isinstance(device, Device)
        self._device = weakref.ref(device)
        super().__init__(*args, **kwargs)
        if bridge_domain is not None:
            bridge_domain.add_vfi(self)

    def __eq__(self, other):
        if not isinstance(other, Vfi):
            return NotImplemented
        # return (self.device, self.name,
        #         self.container.__class__.__name__, self.container) \
        #     == (other.device, other.name,
        #         other.container.__class__.__name__, other.container)
        return (self.name, self.device,
                self.container.__class__.__name__, self.container) \
            == (other.name, other.device,
                other.container.__class__.__name__, other.container)

    def __lt__(self, other):
        if not isinstance(other, Vfi):
            return NotImplemented
        return (self.device, self.name,
                self.container.__class__.__name__, self.container) \
            < (other.device, other.name,
                other.container.__class__.__name__, other.container)

    def __hash__(self):
        # return hash((self.device, self.container, self.name))
        # return hash((self.name, self.device, self.container))
        return hash(self.name)
Ejemplo n.º 3
0
class TunnelTeInterface(TunnelInterface,
                        genie.libs.conf.interface.TunnelTeInterface):

    tunnel_mode = managedattribute(name='tunnel_mode',
                                   default='mpls traffic-eng',
                                   type=managedattribute.test_in(
                                       ('mpls traffic-eng', )))

    destination = managedattribute(name='destination',
                                   default=None,
                                   type=(None, IPv4Address))

    autoroute_announce = managedattribute(name='autoroute_announce',
                                          default=None,
                                          type=(None, bool))

    forwarding_adjacency = managedattribute(name='forwarding_adjacency',
                                            default=None,
                                            type=(None, bool))

    record_route = managedattribute(name='record_route',
                                    default=None,
                                    type=(None, bool))

    frr = managedattribute(name='frr', default=None, type=(None, bool))

    ipv4_unnumbered_interface = managedattribute(
        name='ipv4_unnumbered_interface',
        default=None,
        type=(None, managedattribute.test_isinstance(Interface)))

    priority_setup = managedattribute(name='priority_setup',
                                      default=None,
                                      type=(None, int))

    priority_hold = managedattribute(name='priority_hold',
                                     default=None,
                                     type=(None, int))

    affinity = managedattribute(name='affinity',
                                default=None,
                                type=(None, str))

    te_bw = managedattribute(name='te_bw', default=None, type=(None, int, str))

    te_backup_bw = managedattribute(name='te_backup_bw',
                                    default=None,
                                    type=(None, int, str))

    path_options = managedattribute(
        name='path_options',
        finit=set,
        type=managedattribute.test_set_of(
            # TODO managedattribute.test_isinstance(PathOption)),
            managedattribute.test_istype(str)),
        gettype=frozenset,
        doc='A `set` of PathOption associated objects')

    def add_path_option(self, path_option):
        self._path_options.add(path_option)

    def remove_path_option(self, path_option):
        self._path_options.remove(path_option)

    class PathOptionAttributes(KeyedSubAttributes):
        @classmethod
        def _sanitize_key(cls, key):
            return str(key)

        path_option = managedattribute(
            name='path_option',
            read_only=True,  # key
            doc='The path-option name (read-only key)')

        dynamic = managedattribute(name='dynamic',
                                   default=None,
                                   type=managedattribute.test_istype(bool))

        explicit_name = managedattribute(
            name='explicit_name',
            default=None,
            type=managedattribute.test_istype(str))

        def __init__(self, parent, key, **kwargs):
            self._path_option = key
            super().__init__(parent=parent, **kwargs)

        def build_config(self,
                         apply=True,
                         attributes=None,
                         unconfig=False,
                         **kwargs):
            assert not apply
            assert not kwargs
            attributes = AttributesHelper(self, attributes)
            configurations = CliConfigBuilder(unconfig=unconfig)

            # iosxe: interface tunnel1 / tunnel mpls traffic-eng path-option 1 dynamic
            if attributes.value('dynamic'):
                configurations.append_line(
                    attributes.format(
                        'tunnel mpls traffic-eng path-option {path_option} dynamic'
                    ))

            # iosxe: interface tunnel1 / tunnel mpls traffic-eng path-option 1 explicit name someword
            configurations.append_line(attributes.format\
                    ('tunnel mpls traffic-eng path-option {path_option} explicit name {explicit_name}'))

            return str(configurations)

        def build_unconfig(self, apply=True, attributes=None, **kwargs):
            return self.build_config(apply=apply,
                                     attributes=attributes,
                                     unconfig=True,
                                     **kwargs)

    path_option_attr = managedattribute(name='path_option_attr',
                                        read_only=True,
                                        doc=PathOptionAttributes.__doc__)

    @path_option_attr.initter
    def path_option_attr(self):
        return SubAttributesDict(self.PathOptionAttributes, parent=self)

    def __init__(self, *args, **kwargs):
        self.path_options  # init!
        super().__init__(*args, **kwargs)

    def _build_config_interface_submode(self, configurations, attributes,
                                        unconfig):

        #super()._build_config_interface_submode(configurations=configurations,
        #                                        attributes=attributes,
        #                                        unconfig=unconfig)

        # Virtual interfaces can be fully unconfigured
        if unconfig and attributes.iswildcard:
            configurations.submode_unconfig()

        # iosxe: interface {name} / shutdown
        shutdown = attributes.value('shutdown')
        if shutdown is not None:
            if shutdown:
                configurations.append_line('shutdown', raw=True)
            else:
                configurations.append_line('no shutdown', raw=True)

        # iosxe: interface tunnel1 / tunnel mode mpls traffic-eng
        configurations.append_line(
            attributes.format('tunnel mode {tunnel_mode}'))

        # iosxe: interface tunnel1 / ip unnumbered Loopback0
        configurations.append_line(
            attributes.format(
                'ip unnumbered {ipv4_unnumbered_interface.name}'))

        # iosxe: interface tunnel1 / tunnel destination 1.2.3.4
        configurations.append_line(
            attributes.format('tunnel destination {destination}'))

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng autoroute announce
        if attributes.value('autoroute_announce'):
            configurations.append_line(
                'tunnel mpls traffic-eng autoroute announce')

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng forwarding adjacency
        if attributes.value('forwarding_adjacency'):
            configurations.append_line(
                'tunnel mpls traffic-eng forwarding-adjacency')

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng record-route
        if attributes.value('record_route'):
            configurations.append_line('tunnel mpls traffic-eng record_route')

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng priority <0-7> <0-7>
        configurations.append_line(
            attributes.format(
                'tunnel mpls traffic-eng priority {priority_setup} {priority_hold}'
            ))

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng affinity 0xFFFF
        configurations.append_line(
            attributes.format('tunnel mpls traffic-eng affinity {affinity}'))

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng bandwidth 1000
        configurations.append_line(
            attributes.format('tunnel mpls traffic-eng affinity {te_bw}'))

        # iosxe: interface tunnel1 / tunnel mpls traffic-eng backup-bw 1000
        configurations.append_line(
            attributes.format(
                'tunnel mpls traffic-eng affinity {te_backup_bw}'))

        # iosxe: interface tunnel1 / tunnel mpls trafic-eng fast-reroute
        if attributes.value('frr'):
            configurations.append_line('tunnel mpls traffic-eng fast-reroute')

        # iosxe: interface tunnel-te1 / description some line data
        v = attributes.value('description')
        if v:
            if v is True:
                pass  # TODO Create a usefull default description
            else:
                configurations.append_line('description {}'.format(v))

        # iosxe: interface tunnel-te1 / ipv4 address 1.2.3.0/24

        # ADD PATH OPTIONS
        for ns, attributes2 in attributes.mapping_values(
                'path_option_attr', keys=self.path_options, sort=True):
            configurations.append_block(
                ns.build_config(apply=False,
                                unconfig=unconfig,
                                attributes=attributes2))
Ejemplo n.º 4
0
class Xconnect(DeviceFeature):

    group_name = managedattribute(name='group_name',
                                  type=managedattribute.test_istype(str))

    @group_name.defaulter
    def group_name(self):
        return self.name + 'g'

    name = managedattribute(
        name='name',
        read_only=True,  # read-only hash key
        doc='Bridge domain name (mandatory)')

    class Type(Enum):
        p2p = 1
        mp2mp = 2

    xconnect_type = managedattribute(name='xconnect_type',
                                     default=Type.p2p,
                                     type=Type)

    shutdown = managedattribute(name='shutdown',
                                default=None,
                                type=(None, bool))

    link = managedattribute(
        name='link',
        read_only=True,
        doc='The XconnectLink instance that represents the connected interfaces'
    )

    redundancy_predictive = managedattribute(name='redundancy_predictive',
                                             default=None,
                                             type=(None, bool))

    class DeviceAutodiscoveryBgpAttributesDefaults(XconnectNamespace):

        enabled = managedattribute(name='enabled',
                                   default=False,
                                   type=managedattribute.test_istype(bool))

        control_word = managedattribute(
            name='control_word',
            default=None,
            type=(None, managedattribute.test_istype(bool)))

        rd = managedattribute(name='rd',
                              default=None,
                              type=(None, RouteDistinguisher,
                                    managedattribute.test_in(('auto', ))))

        export_route_policy = managedattribute(
            name='export_route_policy',
            default=None,
            type=(None, managedattribute.test_istype(str)))

        export_route_targets = managedattribute(
            name='export_route_targets',
            finit=typedset(RouteTarget.ImportExport).copy,
            type=typedset(RouteTarget.ImportExport)._from_iterable)

        import_route_targets = managedattribute(
            name='import_route_targets',
            finit=typedset(RouteTarget.ImportExport).copy,
            type=typedset(RouteTarget.ImportExport)._from_iterable)

        table_policy = managedattribute(
            name='table_policy',
            default=None,
            type=(None, managedattribute.test_istype(str)))

        class DeviceSignalingProtocolBgpAttributesDefaults(XconnectNamespace):

            enabled = managedattribute(name='enabled',
                                       default=False,
                                       type=managedattribute.test_istype(bool))

            ce_range = managedattribute(
                name='ce_range',
                default=None,
                type=(None, managedattribute.test_istype(int),
                      managedattribute.test_istype(str)))

        signaling_protocol_bgp = managedattribute(
            name='signaling_protocol_bgp',
            read_only=True,
            doc=DeviceSignalingProtocolBgpAttributesDefaults.__doc__)

        @signaling_protocol_bgp.initter
        def signaling_protocol_bgp(self):
            return self.DeviceSignalingProtocolBgpAttributesDefaults(
                xconnect=self.xconnect)

        def __init__(self, xconnect):
            super().__init__(xconnect=xconnect)

    autodiscovery_bgp = managedattribute(
        name='autodiscovery_bgp',
        read_only=True,
        doc=DeviceAutodiscoveryBgpAttributesDefaults.__doc__)

    @autodiscovery_bgp.initter
    def autodiscovery_bgp(self):
        return self.DeviceAutodiscoveryBgpAttributesDefaults(xconnect=self)

    description = managedattribute(name='description',
                                   default=None,
                                   type=(None,
                                         managedattribute.test_istype(str)))

    # TODO Cannot use typedset because segments need to be updated
    interfaces = managedattribute(
        name='interfaces',
        finit=WeakList,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(Interface)),
        gettype=frozenset,
        doc='A `set` of Interface associated objects')

    def add_interface(self, interface):
        prev_segments = self.segments
        self.interfaces |= {interface}
        self._on_segments_updated(prev_segments)

    def remove_interface(self, interface):
        prev_segments = self.segments
        self.interfaces -= {interface}
        self._on_segments_updated(prev_segments)

    class Interworking(Enum):
        ethernet = 'ethernet'
        ipv4 = 'ipv4'

    interface = managedattribute(name='interface',
                                 default=None,
                                 type=(None, Interworking))

    # TODO Cannot use typedset because segments need to be updated
    pseudowires = managedattribute(
        name='pseudowires',
        finit=set,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(Pseudowire)),
        gettype=frozenset,
        doc='A `set` of Pseudowire associated objects')

    def add_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires |= {pseudowire}
        self._on_segments_updated(prev_segments)

    def remove_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires -= {pseudowire}
        self._on_segments_updated(prev_segments)

    @property
    def pseudowire_neighbors(self):
        for pw in self.pseudowires:
            for nbr in pw.neighbors:
                if nbr.container is self:
                    yield nbr

    @property
    def segments(self):
        segments = []
        segments += list(self.interfaces)
        segments += list(self.pseudowires)
        return frozenset(segments)

    def add_segment(self, segment):
        if isinstance(segment, Interface):
            self.add_interface(segment)
        elif isinstance(segment, Pseudowire):
            self.add_pseudowire(segment)
        else:
            raise ValueError(segment)

    def remove_segment(self, segment):
        if isinstance(segment, Interface):
            self.remove_interface(segment)
        elif isinstance(segment, Pseudowire):
            self.remove_pseudowire(segment)
        else:
            raise ValueError(segment)

    def _on_segments_updated(self, prev_segments):
        # UNUSED prev_segments = frozenset(prev_segments)
        cur_segments = frozenset(self.segments)
        prev_link_interfaces = frozenset(self.link.interfaces)
        new_link_interfaces = frozenset(
            interface for segment in cur_segments
            for interface in self.link_interfaces_from_segment(segment))
        for link_interface in prev_link_interfaces - new_link_interfaces:
            self.link._disconnect_interface_from_xconnect(link_interface)
        for link_interface in new_link_interfaces - prev_link_interfaces:
            self.link._connect_interface_from_xconnect(link_interface)

    def link_interfaces_from_segment(self, segment):
        link_interfaces = set()
        if isinstance(segment, Interface):
            # Links under Genie Interface object is deprecated
            # Placed the below workaround to bypass the Unittest
            from ats.datastructures import WeakList
            segment_links = set(WeakList()) - set([self])
            # Priority to L2 virtual links...
            if not link_interfaces:
                for link in segment_links:
                    if isinstance(link, (XconnectLink, XconnectLink)):
                        link_interfaces.update(link.interfaces)
                        link_interfaces.discard(segment)
            # ... then emulated links
            if not link_interfaces:
                for link in segment_links:
                    if isinstance(link, EmulatedLink):
                        link_interfaces.update(link.interfaces)
                        link_interfaces.discard(segment)
            # ... finally, all links
            if not link_interfaces:
                for link in segment_links:
                    link_interfaces.update(link.interfaces)
                    link_interfaces.discard(segment)
            # For VLAN TGEN connections, the CE interface is the peer of the AC interface's parent
            if not link_interfaces:
                parent_interface = segment.parent_interface
                if parent_interface:
                    # recurse
                    link_interfaces = self.link_interfaces_from_segment(
                        parent_interface)
        elif isinstance(segment, Pseudowire):
            pass
        else:
            raise ValueError(segment)
        return link_interfaces

    def create_pseudowire_neighbor(self, device, **kwargs):
        return self.device_attr[device].create_pseudowire_neighbor(**kwargs)

    class DeviceAttributes(genie.conf.base.attributes.DeviceSubAttributes):
        class NeighborAttributes(PseudowireNeighborSubAttributes):

            # ip -> self.neighbor.ip
            # pw_id -> self.neighbor.pw_id

            ipv6_source = managedattribute(name='ipv6_source',
                                           default=None,
                                           type=(None, IPv6Address))

            mpls_static_label = managedattribute(
                name='mpls_static_label',
                default=None,
                type=(None, managedattribute.test_istype(int)))

            pw_class = managedattribute(
                name='pw_class',
                default=None,
                type=(None, managedattribute.test_isinstance(PseudowireClass)))

            redundancy_group = managedattribute(name='redundancy_group',
                                                type=(None, str))

            redundancy_priority = managedattribute(name='redundancy_priority',
                                                   type=(None, int))

            encapsulation = managedattribute(name='encapsulation',
                                             default=EncapsulationType.mpls,
                                             type=(None, EncapsulationType))

        neighbor_attr = managedattribute(name='neighbor_attr',
                                         read_only=True,
                                         doc=NeighborAttributes.__doc__)

        @neighbor_attr.initter
        def neighbor_attr(self):
            return SubAttributesDict(self.NeighborAttributes, parent=self)

        # interfaces -- See DeviceSubAttributes

        class AutodiscoveryBgpAttributes(SubAttributes):

            export_route_targets = managedattribute(
                name='export_route_targets',
                type=typedset(RouteTarget.ImportExport)._from_iterable)

            @export_route_targets.defaulter
            def export_route_targets(self):
                return frozenset(self.parent.export_route_targets)

            import_route_targets = managedattribute(
                name='import_route_targets',
                type=typedset(RouteTarget.ImportExport)._from_iterable)

            @import_route_targets.defaulter
            def import_route_targets(self):
                return frozenset(self.parent.import_route_targets)

            @property
            def device_name(self):
                return self._device_attr.device_name

            @property
            def device(self):
                return self._device_attr.device

            class SignalingProtocolBgpAttributes(SubAttributes):

                ce_ids = managedattribute(name='ce_ids',
                                          finit=typedset(int).copy,
                                          type=typedset(int)._from_iterable)

                def add_ce_id(self, ce_id):  # TODO DEPRECATE
                    self.ce_ids.add(ce_id)

                def remove_ce_id(self, ce_id):  # TODO DEPRECATE
                    self.ce_ids.remove(ce_id)

                @property
                def device_name(self):
                    return self._device_attr.device_name

                @property
                def device(self):
                    return self._device_attr.device

                class CeAttributes(KeyedSubAttributes):
                    @classmethod
                    def _sanitize_key(cls, key):
                        return int(key)

                    ce_id = managedattribute(name='ce_id',
                                             read_only=True)  # read-only key

                    interfaces = managedattribute(
                        name='interfaces',
                        finit=typedset(
                            managedattribute.test_isinstance(Interface)).copy,
                        type=typedset(
                            managedattribute.test_isinstance(
                                Interface))._from_iterable)

                    def add_interface(self, intf):  # TODO DEPRECATE
                        self.interfaces.add(intf)

                    def remove_interface(self, intf):  # TODO DEPRECATE
                        self.interfaces.remove(intf)

                    class InterfaceAttributes(InterfaceSubAttributes):

                        remote_ce_id = None
                        #Always only one per interface
                        #    interface GigabitEthernet0/0/1/0 remote-ce-id 2000
                        #    !!% Invalid argument: AC already used by existing xconnect

                    interface_attr = None  # InterfaceAttributes

                    def __init__(self, parent, key):
                        self._ce_id = key
                        super().__init__(parent=parent)
                        self.interface_attr = SubAttributesDict(
                            self.InterfaceAttributes, parent=self)

                ce_attr = managedattribute(name='ce_attr',
                                           read_only=True,
                                           doc=CeAttributes.__doc__)

                @ce_attr.initter
                def ce_attr(self):
                    return SubAttributesDict(self.CeAttributes, parent=self)

                def __init__(self, device_attr):
                    self._device_attr = device_attr
                    super().__init__(parent=device_attr.parent.
                                     autodiscovery_bgp.signaling_protocol_bgp)

            signaling_protocol_bgp = managedattribute(
                name='signaling_protocol_bgp',
                read_only=True,
                doc=SignalingProtocolBgpAttributes.__doc__)

            @signaling_protocol_bgp.initter
            def signaling_protocol_bgp(self):
                return self.SignalingProtocolBgpAttributes(
                    device_attr=self._device_attr)

            def __init__(self, device_attr):
                self._device_attr = device_attr
                super().__init__(parent=device_attr.parent.autodiscovery_bgp)

        autodiscovery_bgp = managedattribute(
            name='autodiscovery_bgp',
            read_only=True,
            doc=AutodiscoveryBgpAttributes.__doc__)

        @autodiscovery_bgp.initter
        def autodiscovery_bgp(self):
            return self.AutodiscoveryBgpAttributes(device_attr=self)

        @property
        def pseudowires(self):
            container = self.parent
            device = self.device
            for pw in container.pseudowires:
                for nbr in pw.neighbors:
                    if nbr.container is container \
                            and nbr.device is device:
                        yield pw
                        break  # next pw

        @property
        def pseudowire_neighbors(self):
            device = self.device
            for nbr in self.parent.pseudowire_neighbors:
                if nbr.device is device:
                    yield nbr

        def create_pseudowire_neighbor(self, **kwargs):
            pwnbr = PseudowireNeighbor(container=self.parent,
                                       device=self.device,
                                       **kwargs)
            return pwnbr

        @property
        def segments(self):
            segments = []
            segments += list(self.interfaces)
            segments += list(self.pseudowires)
            return frozenset(segments)

        def __init__(self, parent, key, **kwargs):
            super().__init__(parent=parent, key=key, **kwargs)

    device_attr = managedattribute(name='device_attr',
                                   read_only=True,
                                   doc=DeviceAttributes.__doc__)

    @device_attr.initter
    def device_attr(self):
        return SubAttributesDict(self.DeviceAttributes, parent=self)

    def __eq__(self, other):
        if not isinstance(other, Xconnect):
            return NotImplemented
        # return (self.group_name, self.name, self.testbed) \
        #     == (other.group_name, other.name, other.testbed)
        return (self.name, self.group_name, self.testbed) \
            == (other.name, other.group_name, other.testbed)

    def __lt__(self, other):
        if not isinstance(other, Xconnect):
            return NotImplemented
        return (self.group_name, self.name, self.testbed) \
            < (other.group_name, other.name, self.testbed)

    def __hash__(self):
        # return hash((self.group_name, self.name))
        return hash(self.name)

    def __init__(self, name, *args, **kwargs):
        self._name = name
        segments = kwargs.pop('segments', ())
        super().__init__(*args, **kwargs)
        self._link = XconnectLink(xconnect=self)
        # TODO support self.segments = segments
        for segment in set(segments):
            self.add_segment(segment)

    def build_config(self,
                     devices=None,
                     apply=True,
                     attributes=None,
                     **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_config(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs

    def build_unconfig(self,
                       devices=None,
                       apply=True,
                       attributes=None,
                       **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_unconfig(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs
Ejemplo n.º 5
0
class SegmentRouting(Routing, DeviceFeature):

    address_families = managedattribute(
        name='address_families',
        finit=typedset(AddressFamily, {AddressFamily.ipv4_unicast}).copy,
        type=typedset(AddressFamily)._from_iterable)

    shutdown = managedattribute(
        name='shutdown',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    global_block = managedattribute(
        name='global_block',
        default=None,
        type=(None, managedattribute.test_istype(range)))

    sr_label_preferred = managedattribute(
        name='sr_label_preferred',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    explicit_null = managedattribute(
        name='explicit_null',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    mapping_server = managedattribute(
        name='mapping_server',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    connected_prefix_sid_map = managedattribute(
        name='connected_prefix_sid_map',
        finit=set,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(PrefixSidMapEntry)),
        gettype=frozenset,
        doc='A `set` of connected_prefix_sid_map entries')

    prefix_sid_map = managedattribute(
        name='prefix_sid_map',
        finit=set,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(PrefixSidMapEntry)),
        gettype=frozenset,
        doc='A `set` of prefix_sid_map entries')

    class DeviceAttributes(genie.conf.base.attributes.DeviceSubAttributes):

        address_families = managedattribute(
            name='address_families',
            type=typedset(AddressFamily)._from_iterable)

        @address_families.initter
        def address_families(self):
            return frozenset(self.parent.address_families)

        class AddressFamilyAttributes(AddressFamilySubAttributes):

            def __init__(self, parent, key):
                super().__init__(parent, key)

            def add_prefix_sid_map_entry(self,entry):
                self.prefix_sid_map |= {entry}

            def add_connected_prefix_sid_map_entry(self,entry):
                self.connected_prefix_sid_map |= {entry}

            def remove_prefix_sid_map_entry(self,entry):
                self.prefix_sid_map.remove(entry)

            def remove_connected_prefix_sid_map_entry(self,entry):
                self.connected_prefix_sid_map.remove(entry)

        address_family_attr = managedattribute(
            name='address_family_attr',
            read_only=True,
            doc=AddressFamilyAttributes.__doc__)

        @address_family_attr.initter
        def address_family_attr(self):
            return SubAttributesDict(self.AddressFamilyAttributes, parent=self)

        def __init__(self, parent, key):
            super().__init__(parent, key)

    device_attr = managedattribute(
        name='device_attr',
        read_only=True,
        doc=DeviceAttributes.__doc__)

    @device_attr.initter
    def device_attr(self):
        return SubAttributesDict(self.DeviceAttributes, parent=self)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def build_config(self, devices=None, apply=True, attributes=None,
                     **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items(
                'device_attr',
                keys=devices, sort=True):
            cfgs[key] = sub.build_config(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs

    def build_unconfig(self, devices=None, apply=True, attributes=None,
                       **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items(
                'device_attr',
                keys=devices, sort=True):
            cfgs[key] = sub.build_unconfig(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs
Ejemplo n.º 6
0
class BridgeDomain(DeviceFeature):

    group_name = managedattribute(name='group_name',
                                  type=managedattribute.test_istype(str))

    @group_name.defaulter
    def group_name(self):
        return self.name + 'g'

    name = managedattribute(
        name='name',
        read_only=True,  # read-only hash key
        doc='Bridge domain name (mandatory)')

    link = managedattribute(
        name='link',
        read_only=True,
        doc=
        'The BridgeDomainLink instance that represents the connected interfaces'
    )

    # TODO Cannot use typedset because segments need to be updated
    evis = managedattribute(name='evis',
                            finit=set,
                            type=managedattribute.test_set_of(
                                managedattribute.test_isinstance(Evi)),
                            gettype=frozenset,
                            doc='A `set` of Evi associated objects')

    def add_evi(self, evi):
        prev_segments = self.segments
        self.evis |= {evi}
        self._on_segments_updated(prev_segments)

    def remove_evi(self, evi):
        prev_segments = self.segments
        self.evis -= {evi}
        self._on_segments_updated(prev_segments)

    class DefaultDeviceAndInterfaceMacAttributes(object):
        pass

    mac = managedattribute(name='mac',
                           read_only=True,
                           finit=DefaultDeviceAndInterfaceMacAttributes,
                           doc=DefaultDeviceAndInterfaceMacAttributes.__doc__)

    # TODO Cannot use typedset because segments need to be updated
    interfaces = managedattribute(
        name='interfaces',
        finit=WeakList,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(Interface)),
        gettype=frozenset,
        doc='A `set` of Interface associated objects')

    def add_interface(self, interface):
        if isinstance(interface, Vni):
            self.add_vni(interface)
            return
        prev_segments = self.segments
        self.interfaces |= {interface}
        self._on_segments_updated(prev_segments)

    def remove_interface(self, interface):
        if isinstance(interface, Vni):
            self.remove_vni(interface)
            return
        prev_segments = self.segments
        self.interfaces -= {interface}
        self._on_segments_updated(prev_segments)

    aging_time = managedattribute(name='aging_time',
                                  default=None,
                                  type=(None,
                                        managedattribute.test_istype(int)))

    learning_disable = managedattribute(
        name='learning_disable',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    split_horizon_group = managedattribute(
        name='split_horizon_group',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    split_horizon_group_core = managedattribute(
        name='split_horizon_group_core',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    # TODO Cannot use typedset because segments need to be updated
    pseudowires = managedattribute(
        name='pseudowires',
        finit=set,
        type=managedattribute.test_set_of(
            managedattribute.test_isinstance(Pseudowire)),
        gettype=frozenset,
        doc='A `set` of Pseudowire associated objects')

    def add_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires |= {pseudowire}
        self._on_segments_updated(prev_segments)

    def remove_pseudowire(self, pseudowire):
        prev_segments = self.segments
        self.pseudowires -= {pseudowire}
        self._on_segments_updated(prev_segments)

    @property
    def pseudowire_neighbors(self):
        for pw in self.pseudowires:
            for nbr in pw.neighbors:
                if nbr.container is self:
                    yield nbr

    # TODO Cannot use typedset because segments need to be updated
    vnis = managedattribute(name='vnis',
                            finit=set,
                            type=managedattribute.test_set_of(
                                managedattribute.test_isinstance(Vni)),
                            gettype=frozenset,
                            doc='A `set` of Vni associated objects')

    def add_vni(self, vni):
        prev_segments = self.segments
        self.vnis |= {vni}
        self._on_segments_updated(prev_segments)

    def remove_vni(self, vni):
        prev_segments = self.segments
        self.vnis -= {vni}
        self._on_segments_updated(prev_segments)

    # TODO Cannot use typedset because segments need to be updated
    vfis = managedattribute(name='vfis',
                            finit=set,
                            type=managedattribute.test_set_of(
                                managedattribute.test_isinstance(Vfi)),
                            gettype=frozenset,
                            doc='A `set` of Vfi associated objects')

    def add_vfi(self, vfi):
        assert isinstance(vfi, Vfi)
        if vfi.container is not None:
            raise ValueError('%r is already assigned to %r' %
                             (vfi, vfi.container))
        prev_segments = self.segments
        self.vfis |= {vfi}
        vfi.container = self
        self._on_segments_updated(prev_segments)

    def remove_vfi(self, vfi):
        assert isinstance(vfi, Vfi)
        if vfi.container is not None and vfi.container is not self:
            raise ValueError('%r is assigned to %r, not %r' %
                             (vfi, vfi.container, self))
        prev_segments = self.segments
        self.vfis -= {vfi}
        vfi.container = None
        self._on_segments_updated(prev_segments)

    shutdown = managedattribute(name='shutdown',
                                default=None,
                                type=(None,
                                      managedattribute.test_istype(bool)))

    @property
    def segments(self):
        segments = set()
        segments |= self.interfaces
        segments |= self.pseudowires
        segments |= self.vnis
        segments |= self.vfis
        segments |= self.evis
        return frozenset(segments)

    def add_segment(self, segment):
        if isinstance(segment, Evi):
            self.add_evi(segment)
        elif isinstance(segment, Vni):
            self.add_vni(segment)
        elif isinstance(segment, Interface):
            self.add_interface(segment)
        elif isinstance(segment, Pseudowire):
            self.add_pseudowire(segment)
        elif isinstance(segment, Vfi):
            self.add_vfi(segment)
        else:
            raise ValueError(segment)

    def remove_segment(self, segment):
        if isinstance(segment, Evi):
            self.remove_evi(segment)
        elif isinstance(segment, Vni):
            self.remove_vni(segment)
        elif isinstance(segment, Interface):
            self.remove_interface(segment)
        elif isinstance(segment, Pseudowire):
            self.remove_pseudowire(segment)
        elif isinstance(segment, Vfi):
            self.remove_vfi(segment)
        else:
            raise ValueError(segment)

    def _on_segments_updated(self, prev_segments):
        # UNUSED prev_segments = frozenset(prev_segments)
        cur_segments = frozenset(self.segments)
        prev_link_interfaces = frozenset(self.link.interfaces)
        new_link_interfaces = frozenset(
            interface for segment in cur_segments
            for interface in self.link_interfaces_from_segment(segment))
        for link_interface in prev_link_interfaces - new_link_interfaces:
            self.link._disconnect_interface_from_bridge_domain(link_interface)
        for link_interface in new_link_interfaces - prev_link_interfaces:
            self.link._connect_interface_from_bridge_domain(link_interface)

    def link_interfaces_from_segment(self, segment):
        link_interfaces = set()
        if isinstance(segment, Evi):
            pass
        elif isinstance(segment, Vni):
            pass
        elif isinstance(segment, Interface):
            if isinstance(segment, BviInterface):
                link_interfaces.add(segment)
            else:
                # Links under Genie Interface object is deprecated
                # Placed the below workaround to bypass the Unittest
                from ats.datastructures import WeakList
                segment_links = set(WeakList()) - set([self.link])
                # Priority to L2 virtual links...
                if not link_interfaces:
                    for link in segment_links:
                        if isinstance(link,
                                      (BridgeDomainLink,
                                       genie.libs.conf.l2vpn.XconnectLink)):
                            link_interfaces.update(link.interfaces)
                            link_interfaces.discard(segment)
                # ... then emulated links
                if not link_interfaces:
                    for link in segment_links:
                        if isinstance(link, EmulatedLink):
                            link_interfaces.update(link.interfaces)
                            link_interfaces.discard(segment)
                # ... finally, all links
                if not link_interfaces:
                    for link in segment_links:
                        link_interfaces.update(link.interfaces)
                        link_interfaces.discard(segment)
                # For VLAN TGEN connections, the CE interface is the peer of
                # the AC interface's parent
                if not link_interfaces:
                    parent_interface = segment.parent_interface
                    if parent_interface:
                        # recurse
                        link_interfaces = self.link_interfaces_from_segment(
                            parent_interface)
        elif isinstance(segment, Pseudowire):
            pass
        elif isinstance(segment, Vfi):
            pass
        else:
            raise ValueError(segment)
        return link_interfaces

    def create_pseudowire_neighbor(self, device, **kwargs):
        return self.device_attr[device].create_pseudowire_neighbor(**kwargs)

    class DeviceAttributes(genie.conf.base.attributes.DeviceSubAttributes):
        class InterfaceAttributes(
                genie.conf.base.attributes.InterfaceSubAttributes):
            class MacAttributes(SubAttributes):
                def __init__(self, _interface_attr):
                    self._interface_attr = _interface_attr
                    super().__init__(
                        # BridgeDomain.device_attr[].mac
                        parent=_interface_attr.parent.mac)

                @property
                def interface_name(self):
                    return self._interface_attr.interface_name

                @property
                def interface(self):
                    return self._interface_attr.interface

            mac = managedattribute(name='mac',
                                   read_only=True,
                                   doc=MacAttributes.__doc__)

            @mac.initter
            def mac(self):
                return self.MacAttributes(_interface_attr=self)

            static_mac_address = managedattribute(name='static_mac_address',
                                                  default=None,
                                                  type=(None, MAC))

            def __init__(self, parent, key):
                super().__init__(parent, key)

        interface_attr = managedattribute(name='interface_attr',
                                          read_only=True,
                                          doc=InterfaceAttributes.__doc__)

        @interface_attr.initter
        def interface_attr(self):
            return SubAttributesDict(self.InterfaceAttributes, parent=self)

        class NeighborAttributes(PseudowireNeighborSubAttributes):

            # ip -> self.neighbor.ip
            # pw_id -> self.neighbor.pw_id
            # evi -> self.neighbor.evi
            # ac_id -> self.neighbor.ac_id
            # source_ac_id -> self.neighbor.source_ac_id

            dhcp_ipv4_snooping_profile = managedattribute(
                name='dhcp_ipv4_snooping_profile',
                default=None,
                type=(
                    None,
                    managedattribute.test_is(False),  # False
                    managedattribute.test_istype(str),  # <profile>
                ))

            igmp_snooping_profile = managedattribute(
                name='igmp_snooping_profile',
                default=None,
                type=(
                    None,
                    managedattribute.test_is(False),  # False
                    managedattribute.test_istype(str),  # <profile>
                ))

            mld_snooping_profile = managedattribute(
                name='mld_snooping_profile',
                default=None,
                type=(
                    None,
                    managedattribute.test_is(False),  # False
                    managedattribute.test_istype(str),  # <profile>
                ))

            mpls_static_label = managedattribute(
                name='mpls_static_label',
                default=None,
                type=(None, managedattribute.test_istype(int)))

            pw_class = managedattribute(
                name='pw_class',
                default=None,
                type=(None, managedattribute.test_isinstance(PseudowireClass)))

            split_horizon = managedattribute(
                name='split_horizon',
                default=None,
                type=(None, managedattribute.test_istype(bool)))

            static_mac_address = managedattribute(name='static_mac_address',
                                                  default=None,
                                                  type=(None, MAC))

        neighbor_attr = managedattribute(name='neighbor_attr',
                                         read_only=True,
                                         doc=NeighborAttributes.__doc__)

        @neighbor_attr.initter
        def neighbor_attr(self):
            return SubAttributesDict(self.NeighborAttributes, parent=self)

        class EviAttributes(EviSubAttributes):

            vlan = managedattribute(name='vlan',
                                    default=None,
                                    type=(None, int))

            def __init__(self, parent, key):
                super().__init__(parent=parent, key=key)

        evi_attr = managedattribute(name='evi_attr',
                                    read_only=True,
                                    doc=EviAttributes.__doc__)

        @evi_attr.initter
        def evi_attr(self):
            return SubAttributesDict(self.EviAttributes, parent=self)

        class VniAttributes(VniSubAttributes):
            def __init__(self, parent, key):
                super().__init__(parent, key)

        vni_attr = managedattribute(name='vni_attr',
                                    read_only=True,
                                    doc=VniAttributes.__doc__)

        @vni_attr.initter
        def vni_attr(self):
            return SubAttributesDict(self.VniAttributes, parent=self)

        class MacAttributes(SubAttributes):
            def __init__(self, _device_attr):
                self._device_attr = _device_attr
                super().__init__(
                    # BridgeDomain.mac
                    parent=_device_attr.parent.mac)

            @property
            def device_name(self):
                return self._device_attr.device_name

            @property
            def device(self):
                return self._device_attr.device

            @property
            def testbed(self):
                return self._device_attr.testbed

        mac = managedattribute(name='mac',
                               read_only=True,
                               doc=MacAttributes.__doc__)

        @mac.initter
        def mac(self):
            return self.MacAttributes(_device_attr=self)

        @property
        def evis(self):
            device = self.device
            for evi in self.parent.evis:
                if evi.device is device:
                    yield evi

        # interfaces -- See DeviceSubAttributes

        @property
        def vnis(self):
            device = self.device
            for vni in self.parent.vnis:
                if vni.device is device:
                    yield vni

        @property
        def pseudowires(self):
            container = self.parent
            device = self.device
            for pw in container.pseudowires:
                for nbr in pw.neighbors:
                    if nbr.container is container \
                            and nbr.device is device:
                        yield pw
                        break  # next pw

        @property
        def pseudowire_neighbors(self):
            device = self.device
            for nbr in self.parent.pseudowire_neighbors:
                if nbr.device is device:
                    yield nbr

        @property
        def vfis(self):
            device = self.device
            for vfi in self.parent.vfis:
                if vfi.device is device:
                    yield vfi

        @property
        def segments(self):
            yield from self.interfaces
            yield from self.pseudowires
            yield from self.vnis
            yield from self.vfis
            yield from self.evis

        def create_pseudowire_neighbor(self, **kwargs):
            pwnbr = PseudowireNeighbor(container=self.parent,
                                       device=self.device,
                                       **kwargs)
            return pwnbr

        def __init__(self, parent, key):
            super().__init__(parent, key)

    device_attr = managedattribute(name='device_attr',
                                   read_only=True,
                                   doc=DeviceAttributes.__doc__)

    @device_attr.initter
    def device_attr(self):
        return SubAttributesDict(self.DeviceAttributes, parent=self)

    def __eq__(self, other):
        if not isinstance(other, BridgeDomain):
            return NotImplemented
        # return (self.group_name, self.name) == (other.group_name, other.name)
        return (self.name, self.group_name, self.testbed) \
            == (other.name, other.group_name, other.testbed)

    def __lt__(self, other):
        if not isinstance(other, BridgeDomain):
            return NotImplemented
        return (self.group_name, self.name, self.testbed) \
            < (other.group_name, other.name, other.testbed)

    def __hash__(self):
        # return hash((self.group_name, self.name))
        return hash(self.name)

    def __init__(self, name, *args, **kwargs):
        self._name = name
        super().__init__(*args, **kwargs)
        self._link = BridgeDomainLink(bridge_domain=self)

    def build_config(self,
                     devices=None,
                     apply=True,
                     attributes=None,
                     **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_config(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs

    def build_unconfig(self,
                       devices=None,
                       apply=True,
                       attributes=None,
                       **kwargs):
        cfgs = {}
        assert not kwargs, kwargs
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_unconfig(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs
Ejemplo n.º 7
0
    class DeviceAttributes(genie.conf.base.attributes.DeviceSubAttributes):

        address_families = managedattribute(
            name='address_families',
            type=typedset(AddressFamily)._from_iterable)

        @address_families.defaulter
        def address_families(self):
            return frozenset(self.parent.address_families)

        area_addresses = managedattribute(
            name='area_addresses',
            type=managedattribute.test_set_of(IsisAreaAddress),
            doc='''Set of area address part of Network Entity Title (NET).

            Default value is taken from parent Isis object or, if None, a single area address unique value based on device name.
            ''')

        @area_addresses.defaulter
        def area_addresses(self):
            area_addresses = self.parent.area_addresses
            if area_addresses is None:
                unique_int = binascii.crc32(self.device_name.encode())
                area_addresses = [
                    IsisAreaAddress('47.{:04X}.{:04X}'.format(
                        (unique_int >> 16) & 0xFFFF,
                        unique_int & 0xFFFF,
                    ))
                ]
            return frozenset(area_addresses)

        @property
        def area_address(self):
            '''The area address part of the Network Entity Title (NET).

            `area_address` can be assigned to and will set `area_addresses` to a
            single item.

            `area_address`'s value is a single area address, or None. Use
            `area_addresses` to retrieve all the area addresses. Assign
            `area_addresses` to support multiple area addresses.
            '''
            for area_address in sorted(self.area_addresses):
                return area_address
            return None

        @area_address.setter
        def area_address(self, value):
            self.area_addresses = {value}

        @area_address.deleter
        def area_address(self):
            del self.area_addresses

        system_id = managedattribute(
            name='system_id',
            type=IsisSystemID,
            doc='The system ID. Default is a unique value per device name.')

        @system_id.defaulter
        def system_id(self):
            system_id = self.parent.system_id
            if system_id is None:
                unique_int = binascii.crc32(self.device_name.encode())
                system_id = IsisSystemID('FFFF.{:04X}.{:04X}'.format(
                    (unique_int >> 16) & 0xFFFF,
                    unique_int & 0xFFFF,
                ))
            return system_id

        @property
        def net_ids(self):
            '''The set of Network Entity Titles (NETs).

            Please assign using `system_id`, `area_addresses` or `net_id`.
            '''
            system_id = self.system_id
            return frozenset([
                IsisNET(area_address=area_address, system_id=system_id)
                for area_address in self.area_addresses
            ])

        @property
        def net_id(self):
            '''The Network Entity Title (NET).

            The NET is formatted as `{area_address}.{system_id}.00`

            There can be only 1 `system_id` but there can be multiple areas (`area_addresses`).

            `net_id` can be assigned to and will set `area_addresses` to a
            single item as well as `system_id` to the desired value.

            `net_id`'s value is a single NET, or None. Use `net_ids` to
            retrieve all the NETs. Assign `area_addresses` and `system_id` to
            support multiple NETs.
            '''
            for net_id in sorted(self.net_ids):
                return net_id
            return None

        @net_id.setter
        def net_id(self, value):
            if value is None:
                self.area_addresses = ()
            else:
                net_id = IsisNET(value)
                self.system_id = net_id.system_id
                self.area_address = net_id.area_address

        @net_id.deleter
        def net_id(self):
            try:
                del self.area_address
            except AttributeError:
                pass
            try:
                del self.system_id
            except AttributeError:
                pass

        class AddressFamilyAttributes(AddressFamilySubAttributes):
            def __init__(self, parent, key):
                super().__init__(parent, key)

        address_family_attr = managedattribute(
            name='address_family_attr',
            read_only=True,
            doc=AddressFamilyAttributes.__doc__)

        @address_family_attr.initter
        def address_family_attr(self):
            return SubAttributesDict(self.AddressFamilyAttributes, parent=self)

        class InterfaceAttributes(
                genie.conf.base.attributes.InterfaceSubAttributes):

            address_families = managedattribute(
                name='address_families',
                type=typedset(AddressFamily)._from_iterable)

            @address_families.defaulter
            def address_families(self):
                return frozenset(self.parent.address_families)

            class AddressFamilyAttributes(AddressFamilySubAttributes):
                def __init__(self, parent, key):
                    super().__init__(parent, key)

            address_family_attr = managedattribute(
                name='address_family_attr',
                read_only=True,
                doc=AddressFamilyAttributes.__doc__)

            @address_family_attr.initter
            def address_family_attr(self):
                return SubAttributesDict(self.AddressFamilyAttributes,
                                         parent=self)

            def __init__(self, parent, key):
                super().__init__(parent, key)

        interface_attr = managedattribute(name='interface_attr',
                                          read_only=True,
                                          doc=InterfaceAttributes.__doc__)

        @interface_attr.initter
        def interface_attr(self):
            return SubAttributesDict(self.InterfaceAttributes, parent=self)

        def __init__(self, parent, key):
            super().__init__(parent, key)
Ejemplo n.º 8
0
class Isis(Routing, DeviceFeature, InterfaceFeature, LinkFeature):

    pid = managedattribute(name='pid', type=str, doc='Process ID (mandatory)')

    address_families = managedattribute(
        name='address_families',
        finit=typedset(AddressFamily, {AddressFamily.ipv4_unicast}).copy,
        type=typedset(AddressFamily)._from_iterable)

    class MetricStyle(Enum):
        narrow = 'narrow'
        wide = 'wide'
        transition = 'transition'
        narrow_transition = 'narrow transition'
        wide_transition = 'wide transition'

    metric_style = managedattribute(name='metric_style',
                                    default=None,
                                    type=(None, MetricStyle))

    metric = managedattribute(name='metric',
                              default=None,
                              type=(None, int, str))

    class IsType(Enum):
        level_1 = 'level 1'
        level_1_2 = 'level 1 and 2'
        level_2 = 'level 2'

    is_type = managedattribute(name='is_type',
                               default=None,
                               type=(None, IsType))

    ispf_type = managedattribute(name='ispf_type',
                                 default=None,
                                 type=(None, IsType))

    circuit_type = managedattribute(name='circuit_type',
                                    default=None,
                                    type=(None, IsType))

    maximum_paths = managedattribute(name='maximum_paths',
                                     default=None,
                                     type=(None, int))

    ldp_auto_config = managedattribute(name='ldp_auto_config',
                                       default=None,
                                       type=(None, bool))

    ldp_sync = managedattribute(name='ldp_sync',
                                default=None,
                                type=(None, bool))

    ldp_sync_shortcut = managedattribute(name='ldp_sync_shortcut',
                                         default=None,
                                         type=(None, bool))

    ldp_auto_config_shortcut = managedattribute(
        name='ldp_auto_config_shortcut', default=None, type=(None, bool))

    distribute_link_state = managedattribute(name='distribute_link_state',
                                             default=None,
                                             type=(None, bool))

    mpls_te_level = managedattribute(name='mpls_te_level',
                                     default=None,
                                     type=(None, IsType))

    mpls_te_rtrid = managedattribute(
        name='mpls_te_rtrid',
        default=None,
        type=(None, managedattribute.test_isinstance(Interface)))

    net_id = managedattribute(
        name='net_id',
        read_only=True,
        doc='''Single Network Entity Title (NET). Only meaningful per device.'''
    )

    net_ids = managedattribute(
        name='net_ids',
        read_only=True,
        doc='''Set of Network Entity Title (NET). Only meaningful per device.'''
    )

    area_addresses = managedattribute(
        name='area_addresses',
        type=(None, managedattribute.test_set_of(IsisAreaAddress)),
        doc='''Set of area address part of Network Entity Title (NET).

        Default value is a single area address unique value based on ISIS process ID.

        Set to None to trigger each device to have a unique value based on individual device name.
        ''')

    @area_addresses.defaulter
    def area_addresses(self):
        unique_int = binascii.crc32(self.pid.encode())
        return frozenset([
            IsisAreaAddress('47.{:04X}.{:04X}'.format(
                (unique_int >> 16) & 0xFFFF,
                unique_int & 0xFFFF,
            ))
        ])

    @property
    def area_address(self):
        '''The area address part of the Network Entity Title (NET).

        `area_address` can be assigned to and will set `area_addresses` to a
        single item.

        `area_address`'s value is a single area address, or None. Use
        `area_addresses` to retrieve all the area addresses. Assign
        `area_addresses` to support multiple area addresses.
        '''
        area_addresses = self.area_addresses
        if area_addresses:
            for area_address in sorted(self.area_addresses):
                return area_address
        return None

    @area_address.setter
    def area_address(self, value):
        if value is None:
            self.area_addresses = None
        else:
            self.area_addresses = {value}

    @area_address.deleter
    def area_address(self):
        del self.area_addresses

    system_id = managedattribute(
        name='system_id',
        default=None,
        type=(None, IsisSystemID),
        doc=
        '''System ID. Assign to make all devices use the same System ID for level 1 operation.'''
    )

    class Nsf(Enum):
        cisco = 'cisco'
        ietf = 'ietf'

    nsf = managedattribute(name='nsf', default=None, type=(None, Nsf))

    nsf_lifetime = managedattribute(name='nsf_lifetime',
                                    default=None,
                                    type=(None, int))

    nsr = managedattribute(name='nsr',
                           default=None,
                           type=(None, managedattribute.test_istype(bool)))

    redistribute_connected = managedattribute(
        name='redistribute_connected',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    passive = managedattribute(name='passive',
                               default=None,
                               type=(None, managedattribute.test_istype(bool)))

    point_to_point = managedattribute(
        name='point_to_point',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    shutdown = managedattribute(name='shutdown',
                                default=None,
                                type=(None,
                                      managedattribute.test_istype(bool)))

    nsf_lifetime = managedattribute(name='lsp_mtu',
                                    default=None,
                                    type=(None, int))

    segment_routing_mpls = managedattribute(
        name='segment_routing_mpls',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    segment_routing_mpls_sr_prefer = managedattribute(
        name='segment_routing_mpls_sr_prefer',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    segment_routing_prefix_sid_map_advertise_local = managedattribute(
        name='segment_routing_prefix_sid_map_advertise_local',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    segment_routing_prefix_sid_map_receive = managedattribute(
        name='segment_routing_prefix_sid_map_receive',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    # NOTE: prefix_sid and prefix_sid_index are mutually exclusive
    prefix_sid = managedattribute(name='prefix_sid',
                                  default=None,
                                  type=(None,
                                        managedattribute.test_istype(int)))

    # NOTE: prefix_sid and prefix_sid_index are mutually exclusive
    prefix_sid_index = managedattribute(
        name='prefix_sid_index',
        default=None,
        type=(None, managedattribute.test_istype(int)))

    prefix_sid_explicit_null = managedattribute(
        name='prefix_sid_explicit_null',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    prefix_sid_n_flag_clear = managedattribute(
        name='prefix_sid_n_flag_clear',
        default=None,
        type=(None, managedattribute.test_istype(bool)))

    class DeviceAttributes(genie.conf.base.attributes.DeviceSubAttributes):

        address_families = managedattribute(
            name='address_families',
            type=typedset(AddressFamily)._from_iterable)

        @address_families.defaulter
        def address_families(self):
            return frozenset(self.parent.address_families)

        area_addresses = managedattribute(
            name='area_addresses',
            type=managedattribute.test_set_of(IsisAreaAddress),
            doc='''Set of area address part of Network Entity Title (NET).

            Default value is taken from parent Isis object or, if None, a single area address unique value based on device name.
            ''')

        @area_addresses.defaulter
        def area_addresses(self):
            area_addresses = self.parent.area_addresses
            if area_addresses is None:
                unique_int = binascii.crc32(self.device_name.encode())
                area_addresses = [
                    IsisAreaAddress('47.{:04X}.{:04X}'.format(
                        (unique_int >> 16) & 0xFFFF,
                        unique_int & 0xFFFF,
                    ))
                ]
            return frozenset(area_addresses)

        @property
        def area_address(self):
            '''The area address part of the Network Entity Title (NET).

            `area_address` can be assigned to and will set `area_addresses` to a
            single item.

            `area_address`'s value is a single area address, or None. Use
            `area_addresses` to retrieve all the area addresses. Assign
            `area_addresses` to support multiple area addresses.
            '''
            for area_address in sorted(self.area_addresses):
                return area_address
            return None

        @area_address.setter
        def area_address(self, value):
            self.area_addresses = {value}

        @area_address.deleter
        def area_address(self):
            del self.area_addresses

        system_id = managedattribute(
            name='system_id',
            type=IsisSystemID,
            doc='The system ID. Default is a unique value per device name.')

        @system_id.defaulter
        def system_id(self):
            system_id = self.parent.system_id
            if system_id is None:
                unique_int = binascii.crc32(self.device_name.encode())
                system_id = IsisSystemID('FFFF.{:04X}.{:04X}'.format(
                    (unique_int >> 16) & 0xFFFF,
                    unique_int & 0xFFFF,
                ))
            return system_id

        @property
        def net_ids(self):
            '''The set of Network Entity Titles (NETs).

            Please assign using `system_id`, `area_addresses` or `net_id`.
            '''
            system_id = self.system_id
            return frozenset([
                IsisNET(area_address=area_address, system_id=system_id)
                for area_address in self.area_addresses
            ])

        @property
        def net_id(self):
            '''The Network Entity Title (NET).

            The NET is formatted as `{area_address}.{system_id}.00`

            There can be only 1 `system_id` but there can be multiple areas (`area_addresses`).

            `net_id` can be assigned to and will set `area_addresses` to a
            single item as well as `system_id` to the desired value.

            `net_id`'s value is a single NET, or None. Use `net_ids` to
            retrieve all the NETs. Assign `area_addresses` and `system_id` to
            support multiple NETs.
            '''
            for net_id in sorted(self.net_ids):
                return net_id
            return None

        @net_id.setter
        def net_id(self, value):
            if value is None:
                self.area_addresses = ()
            else:
                net_id = IsisNET(value)
                self.system_id = net_id.system_id
                self.area_address = net_id.area_address

        @net_id.deleter
        def net_id(self):
            try:
                del self.area_address
            except AttributeError:
                pass
            try:
                del self.system_id
            except AttributeError:
                pass

        class AddressFamilyAttributes(AddressFamilySubAttributes):
            def __init__(self, parent, key):
                super().__init__(parent, key)

        address_family_attr = managedattribute(
            name='address_family_attr',
            read_only=True,
            doc=AddressFamilyAttributes.__doc__)

        @address_family_attr.initter
        def address_family_attr(self):
            return SubAttributesDict(self.AddressFamilyAttributes, parent=self)

        class InterfaceAttributes(
                genie.conf.base.attributes.InterfaceSubAttributes):

            address_families = managedattribute(
                name='address_families',
                type=typedset(AddressFamily)._from_iterable)

            @address_families.defaulter
            def address_families(self):
                return frozenset(self.parent.address_families)

            class AddressFamilyAttributes(AddressFamilySubAttributes):
                def __init__(self, parent, key):
                    super().__init__(parent, key)

            address_family_attr = managedattribute(
                name='address_family_attr',
                read_only=True,
                doc=AddressFamilyAttributes.__doc__)

            @address_family_attr.initter
            def address_family_attr(self):
                return SubAttributesDict(self.AddressFamilyAttributes,
                                         parent=self)

            def __init__(self, parent, key):
                super().__init__(parent, key)

        interface_attr = managedattribute(name='interface_attr',
                                          read_only=True,
                                          doc=InterfaceAttributes.__doc__)

        @interface_attr.initter
        def interface_attr(self):
            return SubAttributesDict(self.InterfaceAttributes, parent=self)

        def __init__(self, parent, key):
            super().__init__(parent, key)

    device_attr = managedattribute(name='device_attr',
                                   read_only=True,
                                   doc=DeviceAttributes.__doc__)

    @device_attr.initter
    def device_attr(self):
        return SubAttributesDict(self.DeviceAttributes, parent=self)

    def __init__(self, pid, *args, **kwargs):
        self.pid = pid
        super().__init__(*args, **kwargs)

    def build_config(self,
                     devices=None,
                     apply=True,
                     attributes=None,
                     **kwargs):
        cfgs = {}
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_config(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs

    def build_unconfig(self,
                       devices=None,
                       apply=True,
                       attributes=None,
                       **kwargs):
        cfgs = {}
        attributes = AttributesHelper(self, attributes)

        if devices is None:
            devices = self.devices
        devices = set(devices)

        for key, sub, attributes2 in attributes.mapping_items('device_attr',
                                                              keys=devices,
                                                              sort=True):
            cfgs[key] = sub.build_unconfig(apply=False, attributes=attributes2)

        if apply:
            self.testbed.config_on_devices(cfgs, fail_invalid=True)
        else:
            return cfgs