drivers

package
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: AGPL-3.0 Imports: 38 Imported by: 0

Documentation

Index

Constants

View Source
const (

	// DefaultSessionSocket is the unix path factum2-driver start binds and
	// callers probe. Independent of the worker hub socket.
	DefaultSessionSocket = "/run/factum2-driver/session.sock"
)

Variables

View Source
var SupportedPlatforms = map[string]DriverFactory{}

SupportedPlatforms are the Netbox platform names (lower-cased) NewDriver can build a driver for, exported so callers like internal/device-sync can filter devices by platform up front rather than failing per-device. Each driver registers itself here via registerDriver in its own file's init(), so adding a platform never requires touching this file.

Functions

func CloseSSHPool added in v1.1.1

func CloseSSHPool()

CloseSSHPool closes every in-process SSH client. Used by factum2-driver start on SIGTERM.

func CommitCLI added in v1.1.0

func CommitCLI(comment string, quoted bool) string

CommitCLI is the last command of a candidate-session apply. Platforms that support a commit comment (EOS, SR OS, IOS-XR) get `commit comment "..."` (quoted=true) or `commit comment ...` (quoted=false, XR) when comment is non-empty; otherwise a bare "commit".

func DeviceFQDN

func DeviceFQDN(name string, defaultDomain string) string

DeviceFQDN returns name as-is if it already looks like an FQDN (contains a dot); otherwise it appends defaultDomain, since drivers dial the device over the network and need a resolvable name while factum/Netbox device names are often stored as short hostnames.

func ELINETemplateData added in v1.0.2

func ELINETemplateData(intent *ELINEIntent, platform string) (any, error)

ELINETemplateData returns the value ELINE templates execute against. SR OS gets SDPID derived from the remote neighbor; other platforms get intent.

func InitSSHPool added in v1.1.1

func InitSSHPool(cfg SSHPoolConfig) error

InitSSHPool installs the process-lifetime in-process SSH CLI pool. It returns an error on invalid knobs and panics on double-init.

func InitSSHPoolFromDriver added in v1.1.1

func InitSSHPoolFromDriver(d util.ConfigDriver) error

InitSSHPoolFromDriver compiles YAML knobs and calls InitSSHPool.

func RenderCLITemplate added in v1.0.2

func RenderCLITemplate(tmplText string, data any) ([]string, error)

RenderCLITemplate is the CLI line renderer used by ELINE apply/remove.

func ResetSSHPoolForTest added in v1.1.1

func ResetSSHPoolForTest()

ResetSSHPoolForTest closes the process pool and re-inits compiled defaults with remote probe off so tests stay in-process.

func ServeSSHSession added in v1.1.1

func ServeSSHSession(ctx context.Context, d util.ConfigDriver) error

ServeSSHSession binds unix and/or TCP listeners and serves until ctx is done. InitSSHPool must already have client remote off so sshRunCLI* stay in-process.

func SessionSocketPath added in v1.1.1

func SessionSocketPath(yamlOverride string) string

SessionSocketPath resolves the session-owner unix socket for both factum2-driver start (listen) and callers (probe). yamlOverride is driver.socket. FACTUM_DRIVER_SESSION_SOCKET relocates or disables when yaml is empty. "none" and "0" disable unix. Must not use HubSocketPath.

func UnmarshalNodes

func UnmarshalNodes(nodes []*ConfigNode, target any) error

UnmarshalNodes fills target (a pointer to a struct) from nodes - a top-level *ConfigNode slice, e.g. ParseConfigContext's return value, or any node's own Children for a partial/scoped parse.

Types

type AristaDriver

type AristaDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

func NewAristaDriver

func NewAristaDriver(p DriverParam) (*AristaDriver, error)

func (*AristaDriver) ApplyCLISession added in v1.0.2

func (driver *AristaDriver) ApplyCLISession(sessionName string, cmds []string, comment string) error

ApplyCLISession implements CLISessionApplier for Arista EOS.

func (*AristaDriver) ApplyELINE

func (driver *AristaDriver) ApplyELINE(intent *ELINEIntent) error

ApplyELINE implements ELINEApplier for Arista EOS.

func (*AristaDriver) Exec

func (driver *AristaDriver) Exec(cmd string) (*ExecModel, error)

Exec runs one command on the device and returns its output as text. Text format rather than JSON because cmd is arbitrary and plenty of EOS commands have no JSON representation (the device answers 1003 "not supported" for those).

func (*AristaDriver) GetDeviceConfig

func (driver *AristaDriver) GetDeviceConfig() (*DeviceConfig, error)

GetDeviceConfig fetches "show running-config" over eAPI and parses it into interfaces/VRFs/ELINE/ELAN/L3VPN.

func (*AristaDriver) GetInterfacesStatus

func (driver *AristaDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

GetInterfacesStatus returns the operational state of every interface via NETCONF against openconfig-interfaces, or via eAPI's "show interfaces description" if NETCONF isn't available.

func (*AristaDriver) GetNeighbors

func (driver *AristaDriver) GetNeighbors() ([]*Neighbor, error)

GetNeighbors returns LLDP neighbors via eAPI.

func (*AristaDriver) RemoveELINE

func (driver *AristaDriver) RemoveELINE(removal *ELINERemoval) error

RemoveELINE implements ELINERemover for Arista EOS: tears down removal.Name's pseudowire/patch plus any subinterfaces still attributed to it, without configuring anything new - used when an ELINE endpoint moves off this device entirely (see web/handler_service_eline.go's ApiServiceElinePush), so the device is no longer touched by an ApplyELINE call that could otherwise carry the cleanup. Renders only the shared "cleanup" define from templates/eos_eline.tmpl.

func (*AristaDriver) RunningConfigGet

func (driver *AristaDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

RunningConfigGet returns the running config as CLI text, or - with jsonformat - as EOS's own structured JSON rendering of it (a header/ comments/cmds object), passed through verbatim.

func (*AristaDriver) RunningConfigSave

func (driver *AristaDriver) RunningConfigSave() error

func (*AristaDriver) SetInterfaceDescription

func (driver *AristaDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*AristaDriver) SetInterfaceDescriptions

func (driver *AristaDriver) SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error

func (*AristaDriver) SetInterfaceVLANs

func (driver *AristaDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

SetInterfaceVLANs pushes switchport mode and VLAN membership to a set of interfaces, mirroring the config-mode CLI a human operator would type - same eAPI transport as setInterfaceDescriptionsEAPI. Every VID referenced by any target interface is first ensured to exist in EOS's own VLAN database (a top-level "vlan <id>" block, matching eosParseGlobalVlans' read shape) - EOS rejects "switchport access vlan"/"switchport trunk allowed vlan" for a VID with no such block.

func (*AristaDriver) Version

func (driver *AristaDriver) Version() (*VersionModel, error)

type CLISessionApplier added in v1.0.2

type CLISessionApplier interface {
	ApplyCLISession(sessionName string, cmds []string, comment string) error
}

CLISessionApplier applies already-rendered CLI lines in a config session. EOS uses sessionName for "configure session"; other platforms ignore it. comment names the operator when the platform supports it: EOS session description, SR OS/IOS-XR `commit comment`. Empty means no annotation.

type CiscoSMBDriver added in v1.0.6

type CiscoSMBDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

func NewCiscoSMBDriver added in v1.0.6

func NewCiscoSMBDriver(p DriverParam) (*CiscoSMBDriver, error)

func (*CiscoSMBDriver) ApplyCLISession added in v1.0.6

func (driver *CiscoSMBDriver) ApplyCLISession(_ string, cmds []string, _ string) error

ApplyCLISession implements CLISessionApplier for Cisco SMB.

func (*CiscoSMBDriver) Exec added in v1.0.6

func (driver *CiscoSMBDriver) Exec(cmd string) (*ExecModel, error)

func (*CiscoSMBDriver) GetDeviceConfig added in v1.0.6

func (driver *CiscoSMBDriver) GetDeviceConfig() (*DeviceConfig, error)

func (*CiscoSMBDriver) GetInterfacesStatus added in v1.0.6

func (driver *CiscoSMBDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

func (*CiscoSMBDriver) GetNeighbors added in v1.0.6

func (driver *CiscoSMBDriver) GetNeighbors() ([]*Neighbor, error)

func (*CiscoSMBDriver) RunningConfigGet added in v1.0.6

func (driver *CiscoSMBDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

func (*CiscoSMBDriver) RunningConfigSave added in v1.0.6

func (driver *CiscoSMBDriver) RunningConfigSave() error

RunningConfigSave answers the "Overwrite file [startup-config].... (Y/N)" prompt with "y".

func (*CiscoSMBDriver) SetInterfaceDescription added in v1.0.6

func (driver *CiscoSMBDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*CiscoSMBDriver) SetInterfaceDescriptions added in v1.0.6

func (driver *CiscoSMBDriver) SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error

func (*CiscoSMBDriver) SetInterfaceVLANs added in v1.0.6

func (driver *CiscoSMBDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

func (*CiscoSMBDriver) Version added in v1.0.6

func (driver *CiscoSMBDriver) Version() (*VersionModel, error)

Version scrapes "show version", "show inventory" and "show system". SG300 prints "SW version <ver>"; SG350/C1200/C1300 print an Active-image block with "Version: <ver>". PID/VID/SN come from inventory; MAC from "show system". Fields those commands don't expose are left zero-valued.

type ConfigNode

type ConfigNode struct {
	Line     string
	Children []*ConfigNode
}

ConfigNode is one line of config plus whatever's indented under it.

func FindChild

func FindChild(nodes []*ConfigNode, prefix string) *ConfigNode

FindChild returns the first node in nodes whose Line has prefix as a prefix, or nil if none matches.

func GetContextLevel

func GetContextLevel(nodes []*ConfigNode, path ...string) []*ConfigNode

GetContextLevel walks down path, each step matching the first child whose Line has that step as a prefix (startswith-based). Returns nil if any step isn't found.

func ParseConfigContext

func ParseConfigContext(lines []string, commentPrefix string) []*ConfigNode

ParseConfigContext splits lines into a tree by leading-whitespace indentation: a line indented more than the line above it becomes that line's child, less-or-equal indentation ends the current context. Blank lines and lines starting with commentPrefix (once commentPrefix != "") are skipped entirely - they neither start nor end a context.

type DeviceConfig

type DeviceConfig struct {
	Interfaces       []*Interface
	InterfacesByName map[string]*Interface
	VRFs             map[string]*VRF
	ELINEs           map[string]*ELINE
	ELANs            map[string]*ELAN
	L3VPNs           map[string]*L3VPN
	GlobalVLANs      map[int]*VLAN
}

DeviceConfig is a device's fully parsed running config, returned by DriverClient.GetDeviceConfig().

func NewDeviceConfig

func NewDeviceConfig() *DeviceConfig

NewDeviceConfig returns an empty, initialized DeviceConfig - callers should build through this rather than a zero value so the maps are never nil.

func (*DeviceConfig) AddInterface

func (dc *DeviceConfig) AddInterface(interfaceObj *Interface)

AddInterface appends interface to both Interfaces and InterfacesByName.

type DeviceModel

type DeviceModel struct {
	Name     string
	Platform string
}

type DriverClient

type DriverClient interface {
	Exec(cmd string) (*ExecModel, error)
	RunningConfigGet(json bool) (*RunningConfigModel, error)
	RunningConfigSave() error
	GetInterfacesStatus() ([]*netboxtool.NBInterface, error)
	SetInterfaceDescription(intf *netboxtool.NBInterface) error
	SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error
	// SetInterfaceVLANs pushes switchport/VLAN config to a set of interfaces
	// - only implemented for global-VLAN platforms (EOS, VRP, Cisco SMB);
	// every other platform returns an error, since they have no per-interface
	// global VLAN concept (see Interface.SwitchportMode's doc comment).
	SetInterfaceVLANs(name []string, params []*VLANConfig) error
	Version() (*VersionModel, error)

	// GetDeviceConfig fetches and parses the device's running config into
	// interfaces/VRFs/pseudowires/ELINE/ELAN/L3VPN, for internal/device-sync
	// to compare against Netbox.
	GetDeviceConfig() (*DeviceConfig, error)
	// GetNeighbors returns the device's LLDP-discovered neighbors.
	GetNeighbors() ([]*Neighbor, error)
}

func NewDriver

func NewDriver(deviceParam DriverParam) (DriverClient, error)

func NewDriverName

func NewDriverName(factumConfig *util.ConfigFactum, name string, username string, password string) (DriverClient, error)

NewDriverName builds a driver for the device called name, looking up everything it needs over the primary's REST API rather than from Postgres: the device itself (GET /api/device/name/:name, for its platform) and util.CommonConfig (GET /api/common-config, for the default domain used to turn a short device name into something resolvable). That's what lets factum2-driver-cli run on a host that can reach the devices but has no database access - the same remote-config pattern the DNS/Icinga/LibreNMS/ Oxidized tools use, see internal/util.FetchRemoteConfig.

type DriverFactory

type DriverFactory func(DriverParam) (DriverClient, error)

DriverFactory builds a DriverClient for one platform.

type DriverParam

type DriverParam struct {
	Name     string // name on device
	Port     string
	Username string
	Password string
	Platform string
	// contains filtered or unexported fields
}

Parameters needed to create a device instance

func WithActor added in v1.1.1

func WithActor(p DriverParam, name string) DriverParam

WithActor returns a copy of p with the SSH session actor set. The field is unexported so JSON/constructors are not required to supply it.

type ELAN

type ELAN struct {
	Name        string
	Description string
	RD          string
	RTImport    string
	RTExport    string
	Interfaces  []string
}

ELAN is a multipoint L2 service (BGP VLAN / VPLS / bridge-domain). Interfaces holds interface/SAP names rather than resolved *Interface pointers, even though every name here also has a matching entry in DeviceConfig.InterfacesByName (SR OS's SAP ids included - see srosAddSapInterface) - callers that need the full Interface look it up there by name rather than this field carrying pointers itself.

type ELINE

type ELINE struct {
	Name        string
	Description string
	Conn1       any
	Conn2       any
}

ELINE is a point-to-point service (patch panel / epipe / xconnect); each of Conn1/Conn2 is either a *Interface or a *Pseudowire - callers type-switch on it.

type ELINEApplier

type ELINEApplier interface {
	ApplyELINE(intent *ELINEIntent) error
}

ELINEApplier is implemented by drivers that can provision an ELINE. Deliberately not part of DriverClient: adding ELINE support to one driver should never force every other driver to grow a stub method. Callers type-assert for it (drv.(ELINEApplier)) and report a clean "not supported on this platform" error when the assertion fails.

type ELINEIntent

type ELINEIntent struct {
	Name        string // ServiceID, used as the pseudowire/patch name
	Description string // "ID=<ServiceID> <customer name>" - set on every subinterface this intent touches
	LocalIface  string // this device's physical interface, e.g. "Ethernet1"
	LocalVLAN   int

	// ServiceNumericID is the same numeric ID as Remote.PseudowireID
	// (web/handler_service_eline.go's pseudowireIDFromServiceID), but set
	// unconditionally - including for a same-device ELINE, where Remote is
	// nil. EOS has no use for it (a same-device patch needs no numeric ID
	// at all), but SR OS does: every epipe needs a numeric service-id
	// regardless of whether it carries a spoke-sdp, so this is the only
	// place a same-device apply on that platform can get one from.
	ServiceNumericID int

	// Exactly one of PeerLocalIface or Remote is set: PeerLocalIface when
	// the ELINE's other endpoint is on this same device (no pseudowire
	// needed, the patch cross-connects two local subinterfaces directly),
	// Remote when it's on a different device.
	PeerLocalIface string
	PeerLocalVLAN  int
	Remote         *ELINERemotePeer

	// StaleSubinterfaces lists "<iface>.<vlan>" subinterfaces a previous
	// apply of this same service (by Name) created on this device and the
	// current one no longer wants - e.g. after the service's interface or
	// VLAN was edited. ELINEApplier removes them in the same atomic
	// session as the rest of this apply, so a re-provision never leaves an
	// orphaned subinterface behind. See ELINERemoval for the case where a
	// whole device stops being an endpoint of this service.
	StaleSubinterfaces []ELINEStaleSubinterface
}

ELINEIntent is one device's local half of a point-to-point ELINE service to provision - the input to an ELINEApplier. Vendor-agnostic: any future driver (SR OS, IOS-XR, ...) renders this through its own template rather than needing a new intent shape.

type ELINEPrepareChecker added in v1.0.2

type ELINEPrepareChecker interface {
	PrepareELINEApply(intent *ELINEIntent) error
}

ELINEPrepareChecker runs platform guards that ApplyELINE would have executed before commit. The pack/CLISession path skips ApplyELINE, so callers must still invoke this (NokiaDriver refuses to repoint a shared SDP when last-octet IDs collide).

type ELINERemotePeer

type ELINERemotePeer struct {
	NeighborIP   string
	PseudowireID int

	// MTU/ControlWord are EOS-only: its pseudowire config sets both
	// explicitly per service. SR OS doesn't use either - its spoke-sdp's
	// MTU and control-word are inherited from its apply-group instead (see
	// driver_nokia_sros_eline.go), so there's nowhere for a per-service
	// value to go on that platform even if a service needed a different
	// one.
	MTU         int
	ControlWord bool

	// DeviceName/RemoteIface/RemoteVLAN describe the far end for SR OS's
	// human-readable "PEER=<name> interface=<iface>.<vlan>" description
	// convention (driver_nokia_sros_eline.go, confirmed against a real
	// device) - EOS doesn't use them. RemoteIface/RemoteVLAN are the
	// remote device's own LocalIface/LocalVLAN, i.e. the other side's
	// intent - not to be confused with PeerLocalIface/PeerLocalVLAN above,
	// which is this same device's other local port in the same-device
	// case.
	DeviceName  string
	RemoteIface string
	RemoteVLAN  int
}

ELINERemotePeer describes the ELINE's other endpoint when it's on a different device, reachable over an MPLS LDP pseudowire.

type ELINERemoval

type ELINERemoval struct {
	Name               string // ServiceID, matches the pseudowire/patch name ApplyELINE used
	StaleSubinterfaces []ELINEStaleSubinterface
}

ELINERemoval is passed to ELINERemover.RemoveELINE to fully tear down a service's config on a device that no longer participates in it at all (its endpoint moved to a different device) - unlike ApplyELINE, nothing new is configured afterward.

type ELINERemover

type ELINERemover interface {
	RemoveELINE(removal *ELINERemoval) error
}

ELINERemover is implemented by drivers that can tear down an abandoned ELINE endpoint. Separate from ELINEApplier for the same reason ELINEApplier is separate from DriverClient: a driver can gain ELINE support incrementally. Callers type-assert for it the same way as ELINEApplier.

type ELINEStaleSubinterface

type ELINEStaleSubinterface struct {
	Iface string
	VLAN  int
}

ELINEStaleSubinterface identifies one "<iface>.<vlan>" subinterface to remove as part of an ELINE apply or removal.

type ExecModel

type ExecModel struct {
	Result string
}

type IOSXRDriver

type IOSXRDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

func NewIosXRDriver

func NewIosXRDriver(p DriverParam) (*IOSXRDriver, error)

func (*IOSXRDriver) ApplyCLISession added in v1.0.2

func (driver *IOSXRDriver) ApplyCLISession(_ string, cmds []string, comment string) error

ApplyCLISession implements CLISessionApplier for Cisco IOS-XR.

func (*IOSXRDriver) ApplyELINE

func (driver *IOSXRDriver) ApplyELINE(intent *ELINEIntent) error

ApplyELINE implements ELINEApplier for Cisco IOS-XR.

func (*IOSXRDriver) Exec

func (driver *IOSXRDriver) Exec(cmd string) (*ExecModel, error)

run command on device over classic CLI, return output.

func (*IOSXRDriver) GetDeviceConfig

func (driver *IOSXRDriver) GetDeviceConfig() (*DeviceConfig, error)

GetDeviceConfig fetches and parses the device's running config.

func (*IOSXRDriver) GetInterfacesStatus

func (driver *IOSXRDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

GetInterfacesStatus returns the operational state of every interface via NETCONF against openconfig-interfaces.

func (*IOSXRDriver) GetNeighbors

func (driver *IOSXRDriver) GetNeighbors() ([]*Neighbor, error)

GetNeighbors runs "show lldp neighbors detail" and parses the "---"- separated blocks. Local interfaces that are subinterfaces (name contains ".") are skipped.

func (*IOSXRDriver) RemoveELINE

func (driver *IOSXRDriver) RemoveELINE(removal *ELINERemoval) error

RemoveELINE implements ELINERemover for Cisco IOS-XR: tears down removal.Name's xconnect entry plus any subinterfaces still attributed to it, without configuring anything new - used when an ELINE endpoint moves off this device entirely (see web/handler_service_eline.go's ApiServiceElinePush). Renders only the shared "cleanup" define from templates/iosxr_eline.tmpl.

func (*IOSXRDriver) RunningConfigGet

func (driver *IOSXRDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

RunningConfigGet always returns CLI text (jsonformat is ignored) - NETCONF has no RPC that returns config the way an operator would read it (as CLI script), only the YANG tree as XML, so this goes over SSH CLI instead.

func (*IOSXRDriver) RunningConfigSave

func (driver *IOSXRDriver) RunningConfigSave() error

RunningConfigSave has no XR equivalent: SetInterfaceDescriptions already commits straight to the running datastore, which persists across reload on its own - there's no separate "save" step to run.

func (*IOSXRDriver) SetInterfaceDescription

func (driver *IOSXRDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*IOSXRDriver) SetInterfaceDescriptions

func (driver *IOSXRDriver) SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error

func (*IOSXRDriver) SetInterfaceVLANs

func (driver *IOSXRDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

SetInterfaceVLANs is unsupported on IOS-XR - it has no per-interface global-VLAN concept (see Interface.SwitchportMode's doc comment), only bridge-domain/EVI-scoped L2, which the web layer's "global VLAN platforms" gate is meant to keep this from ever being called for.

func (*IOSXRDriver) Version

func (driver *IOSXRDriver) Version() (*VersionModel, error)

Version reads the chassis component's serial/hardware/software fields via NETCONF against openconfig-platform.

type Interface

type Interface struct {
	Name        string
	Description string
	Type        string // netbox interface type bucket: "virtual", "lag", ...
	VRF         string
	LagID       string
	LagParent   string
	VlanID      string
	IPAddresses []InterfaceAddress

	// Parent is another parsed Interface's Name that this one nests under in
	// Netbox (Netbox's own "parent" interface relationship) - "" if this
	// interface has no parent. Currently only set for SR OS SAP interfaces
	// (see srosAddSapInterface), whose Parent is the physical port the SAP
	// is bound to.
	Parent string
	// Label is Netbox's free-text interface label, distinct from Name -
	// currently only set for SR OS SAP interfaces, to "SAP" (see
	// srosAddSapInterface), since SR OS has no real subinterfaces and the
	// Netbox interface standing in for one would otherwise look like it is.
	Label string

	// L2 switchport config, for global-VLAN platforms (EOS, VRP, Cisco SMB) where an
	// access/trunk port references DeviceConfig.GlobalVLANs by ID - bridge-
	// domain platforms (IOS-XR, SR OS) don't use these, since their VLANs
	// are scoped per bridge-domain/ELAN instead, not global to the device.
	SwitchportMode string // "access", "trunk" or "dot1q-tunnel" (Q-in-Q); "" if not an L2 switchport
	UntaggedVLAN   int    // access VLAN (access mode), native/PVID VLAN (trunk mode), or outer/S-VLAN tag (dot1q-tunnel mode); 0 if none
	TaggedVLANs    []int  // VLANs carried tagged on a trunk port

	// L2Transport is true if this subinterface is configured as pure L2
	// transport rather than L3/IP routing - IOS-XR's "interface X
	// l2transport" and VRP's "interface X mode l2", both trailing tokens on
	// the interface line itself rather than a child line. Distinct from
	// SwitchportMode above, which is the global-VLAN platforms' (EOS, VRP,
	// Cisco SMB physical ports) equivalent concept - a bridge-domain platform's L2
	// subinterface has no global VLAN membership to express that way. Not
	// consumed anywhere yet; captured so a caller like internal/device-sync
	// can later tell "no IPAddresses because this is an L2 leg" apart from
	// "no IPAddresses because config is incomplete".
	L2Transport bool
}

Interface is one parsed interface (physical, subinterface or LAG).

type InterfaceAddress

type InterfaceAddress struct {
	Address netip.Prefix
	VRF     string
}

InterfaceAddress is one IP address configured on an interface, together with the VRF it belongs to (Netbox models VRF on the address; this application follows the device and keeps VRF on the interface instead - see Interface.VRF - but a device can technically configure a different VRF per address family, hence it's carried here too).

type InterfaceModel

type InterfaceModel struct {
	Name               string
	Description        string
	LineProtocolStatus string
	InterfaceStatus    string
}

type L3VPN

type L3VPN struct {
	Name        string
	Description string
	VRF         *VRF
}

L3VPN is a VRF-attached BGP/MPLS L3 service (router bgp vrf / vprn).

type MyDevice

type MyDevice struct {
	Id           int
	Name         string
	Manufacturer string
	DeviceType   string
	Platform     string
}

type Neighbor

type Neighbor struct {
	LocalInterface  string
	SystemID        string
	RemoteName      string
	RemoteInterface string
}

Neighbor is one LLDP-discovered neighbor.

type NokiaDriver

type NokiaDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

func NewNokiaDriver

func NewNokiaDriver(p DriverParam) (*NokiaDriver, error)

func (*NokiaDriver) ApplyCLISession added in v1.0.2

func (driver *NokiaDriver) ApplyCLISession(_ string, cmds []string, comment string) error

ApplyCLISession implements CLISessionApplier for Nokia SR OS.

func (*NokiaDriver) ApplyELINE

func (driver *NokiaDriver) ApplyELINE(intent *ELINEIntent) error

ApplyELINE implements ELINEApplier for Nokia SR OS.

func (*NokiaDriver) Exec

func (driver *NokiaDriver) Exec(cmd string) (*ExecModel, error)

SR OS's NETCONF interface has no RPC to run an arbitrary CLI command (that's Arista eAPI's runCmds), so like RunningConfigGet this goes over SSH instead. Only the paging-disable step is forced through the classic CLI engine via "//" - cmd itself is sent as-is, since it's the caller's choice of command/engine, not ours to override.

func (*NokiaDriver) GetDeviceConfig

func (driver *NokiaDriver) GetDeviceConfig() (*DeviceConfig, error)

GetDeviceConfig fetches and parses the device's MD-CLI JSON running config.

func (*NokiaDriver) GetInterfacesStatus

func (driver *NokiaDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

GetInterfacesStatus returns the operational state of every interface.

func (*NokiaDriver) GetNeighbors

func (driver *NokiaDriver) GetNeighbors() ([]*Neighbor, error)

GetNeighbors runs "show port * ethernet lldp remote-info" and block- parses it - each neighbor starts at a "Port 1..." line, and "Port Id"'s real value (unlike every other field) is on the line *after* its header, quoted.

func (*NokiaDriver) PrepareELINEApply added in v1.0.2

func (driver *NokiaDriver) PrepareELINEApply(intent *ELINEIntent) error

PrepareELINEApply implements ELINEPrepareChecker: same SDP far-end guard ApplyELINE runs, for the pack/CLISession path that does not call ApplyELINE.

func (*NokiaDriver) RemoveELINE

func (driver *NokiaDriver) RemoveELINE(removal *ELINERemoval) error

RemoveELINE implements ELINERemover for Nokia SR OS: deletes removal.Name's epipe (and everything nested under it) without configuring anything new. Renders only the shared "cleanup" define from templates/sros_eline.tmpl.

func (*NokiaDriver) RunningConfigGet

func (driver *NokiaDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

func (*NokiaDriver) RunningConfigSave

func (driver *NokiaDriver) RunningConfigSave() error

SR OS's <commit> (see SetInterfaceDescriptions) lands directly in the running datastore - there's no separate startup datastore involved at the NETCONF layer, so there is no separate "save running as startup" step. Persisting running config across a reboot is a distinct, unrelated step on SR OS (MD-CLI "admin save"), which this driver doesn't implement.

func (*NokiaDriver) SetInterfaceDescription

func (driver *NokiaDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*NokiaDriver) SetInterfaceDescriptions

func (driver *NokiaDriver) SetInterfaceDescriptions(name []string, description []*netboxtool.NBInterface) error

func (*NokiaDriver) SetInterfaceVLANs

func (driver *NokiaDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

SetInterfaceVLANs is unsupported on SR OS - it has no per-interface global-VLAN concept (see Interface.SwitchportMode's doc comment); every VLAN-tagged construct on this platform is a SAP scoped inside a service (epipe/vpls/vprn), not a standalone interface property. The web layer's "global VLAN platforms" gate is meant to keep this from ever being called.

func (*NokiaDriver) Version

func (driver *NokiaDriver) Version() (*VersionModel, error)

type OpenROADMDriver added in v1.0.4

type OpenROADMDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

OpenROADMDriver talks NETCONF (RFC 6241 over SSH 830) to an Open ROADM MSA device. It is read-only: inventory, interface status, neighbors and the YANG tree are fetched with <get>; every write method returns an error. The YANG namespace (http://org/openroadm/device) has been stable from MSA 1.2 through current device-model revisions; leaf names used here exist across that range. Frequency lives on later-model NMC-CTP / OCH / OTSi augment containers and is simply absent on 1.2/2.2 replies.

func NewOpenROADMDriver added in v1.0.4

func NewOpenROADMDriver(p DriverParam) (*OpenROADMDriver, error)

func (*OpenROADMDriver) Exec added in v1.0.4

func (driver *OpenROADMDriver) Exec(cmd string) (*ExecModel, error)

func (*OpenROADMDriver) GetDeviceConfig added in v1.0.4

func (driver *OpenROADMDriver) GetDeviceConfig() (*DeviceConfig, error)

func (*OpenROADMDriver) GetInterfacesStatus added in v1.0.4

func (driver *OpenROADMDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

func (*OpenROADMDriver) GetNeighbors added in v1.0.4

func (driver *OpenROADMDriver) GetNeighbors() ([]*Neighbor, error)

func (*OpenROADMDriver) GetOpticalInventory added in v1.0.4

func (driver *OpenROADMDriver) GetOpticalInventory() (*OpticalInventory, error)

GetOpticalInventory maps org-openroadm-device onto Factum optical kinds, port roles and xconnects. Persist via optical.ApplyInventory (device-sync and `factum2-driver optical-inventory-apply`).

func (*OpenROADMDriver) RunningConfigGet added in v1.0.4

func (driver *OpenROADMDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

RunningConfigGet returns the raw org-openroadm-device XML from <get>. jsonformat is ignored: there is no CLI-text or CLI-JSON equivalent.

func (*OpenROADMDriver) RunningConfigSave added in v1.0.4

func (driver *OpenROADMDriver) RunningConfigSave() error

func (*OpenROADMDriver) SetInterfaceDescription added in v1.0.4

func (driver *OpenROADMDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*OpenROADMDriver) SetInterfaceDescriptions added in v1.0.4

func (driver *OpenROADMDriver) SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error

func (*OpenROADMDriver) SetInterfaceVLANs added in v1.0.4

func (driver *OpenROADMDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

func (*OpenROADMDriver) Version added in v1.0.4

func (driver *OpenROADMDriver) Version() (*VersionModel, error)

type OpticalClient added in v1.0.4

type OpticalClient interface {
	GetOpticalInventory() (*OpticalInventory, error)
}

OpticalClient is implemented by drivers that can read optical inventory (ROADM degrees/SRGs, transponder ports, intra-device xconnects). Deliberately not part of DriverClient: adding optical support to one driver should never force every other driver to grow a stub method.

type OpticalInventory added in v1.0.4

type OpticalInventory struct {
	NodeID           string                `json:"node_id"`
	NodeType         string                `json:"node_type"`
	OpticalKind      string                `json:"optical_kind"`
	Vendor           string                `json:"vendor"`
	Model            string                `json:"model"`
	Serial           string                `json:"serial"`
	SoftwareVersion  string                `json:"software_version"`
	OpenROADMVersion string                `json:"openroadm_version"`
	Ports            []OpticalPortView     `json:"ports"`
	XConnects        []OpticalXConnectView `json:"xconnects"`
}

OpticalInventory is one device's Open ROADM inventory, keyed with the same kind/role/xconnect strings as models.OpticalKind* / Port* / XC*.

func (*OpticalInventory) ApplyInventory added in v1.0.4

func (inv *OpticalInventory) ApplyInventory() optical.Inventory

ApplyInventory is the Factum optical.Inventory shape of this dump, for optical.ApplyInventory / PUT /api/optical/device/:id/inventory.

type OpticalPortView added in v1.0.4

type OpticalPortView struct {
	Name        string `json:"name"`
	CircuitPack string `json:"circuit_pack"`
	PortName    string `json:"port_name"`
	Role        string `json:"role"`
	Description string `json:"description"`
	AdminStatus string `json:"admin_status"`
	OperStatus  string `json:"oper_status"`
	FreqHz      uint64 `json:"freq_hz"`
	Qual        string `json:"qual"`
}

OpticalPortView is one physical circuit-pack port with a Factum optical role. Name is "circuit-pack-name/port-name".

type OpticalXConnectView added in v1.0.4

type OpticalXConnectView struct {
	Name      string `json:"name"`
	Kind      string `json:"kind"`
	PortA     string `json:"port_a"`
	PortB     string `json:"port_b"`
	FreqHz    uint64 `json:"freq_hz"`
	CircuitID string `json:"circuit_id"`
}

OpticalXConnectView is one intra-device optical adjacency. PortA/PortB are OpticalPortView.Name values. Kind is models.XC*.

type Pseudowire

type Pseudowire struct {
	Name        string
	Neighbor    string
	Type        string
	PWID        int
	MTU         int
	ControlWord bool
}

Pseudowire is one MPLS/SDP pseudowire, used as one end of an ELINE.

type RunningConfigModel

type RunningConfigModel struct {
	ConfigStr string
}

type RunningConfigStructured

type RunningConfigStructured struct {
	ConfigStruct any
}

type SSHPoolConfig added in v1.1.1

type SSHPoolConfig struct {
	Platforms      *[]string
	IdleTimeout    time.Duration
	MaxSessions    int
	QueueDepth     int
	AcquireTimeout time.Duration
	Keepalive      time.Duration
	SessionURL     string
	SessionToken   string
	TLSCA          string
	Socket         string
}

SSHPoolConfig is the process-lifetime pool knobs. Zero / empty values mean compiled defaults. Negative ints and durations are rejected by InitSSHPool.

func PoolConfigFromDriver added in v1.1.1

func PoolConfigFromDriver(d util.ConfigDriver) (SSHPoolConfig, error)

PoolConfigFromDriver maps YAML ConfigDriver onto SSHPoolConfig. Empty duration strings stay zero (compiled defaults at InitSSHPool).

type VLAN

type VLAN struct {
	ID   int
	Name string
}

VLAN is a global (device-wide) VLAN definition.

type VLANConfig

type VLANConfig struct {
	SwitchportMode string // "access", "trunk" or "dot1q-tunnel" (Q-in-Q); "" to remove switchport config
	UntaggedVLAN   int    // access VLAN, native/PVID VLAN, or outer/S-VLAN tag; 0 if none
	TaggedVLANs    []int  // VLANs carried tagged on a trunk port
}

VLANConfig is the desired switchport/VLAN state for one interface, passed to DriverClient.SetInterfaceVLANs - the write-side counterpart of Interface's SwitchportMode/UntaggedVLAN/TaggedVLANs fields above. Only meaningful on global-VLAN platforms (EOS, VRP, Cisco SMB) - see SetInterfaceVLANs.

type VRF

type VRF struct {
	Name        string
	Description string
	RD          string
	RTImport    string
	RTExport    string
	Interfaces  []string
}

VRF is a routing/forwarding instance. Interfaces holds the names of parsed interfaces that reference this VRF.

type VersionModel

type VersionModel struct {
	ModelName        string
	InternalVersion  string
	SystemMacAddress string
	SerialNumber     string
	MemTotal         float64
	BootupTimestap   float64
	MemFree          float64
	Version          string
	Architecture     string
	InternalBuildId  string
	HardwareRevision string
}

type VrpDriver

type VrpDriver struct {
	DriverClient
	// contains filtered or unexported fields
}

func NewVrpDriver

func NewVrpDriver(p DriverParam) (*VrpDriver, error)

func (*VrpDriver) ApplyCLISession added in v1.0.6

func (driver *VrpDriver) ApplyCLISession(_ string, cmds []string, _ string) error

ApplyCLISession implements CLISessionApplier for Huawei VRP.

func (*VrpDriver) Exec

func (driver *VrpDriver) Exec(cmd string) (*ExecModel, error)

func (*VrpDriver) GetDeviceConfig

func (driver *VrpDriver) GetDeviceConfig() (*DeviceConfig, error)

func (*VrpDriver) GetInterfacesStatus

func (driver *VrpDriver) GetInterfacesStatus() ([]*netboxtool.NBInterface, error)

func (*VrpDriver) GetNeighbors

func (driver *VrpDriver) GetNeighbors() ([]*Neighbor, error)

GetNeighbors runs "display lldp neighbor" and parses it: each "<ifname> has N neighbor(s):" line starts a new neighbor block.

func (*VrpDriver) RunningConfigGet

func (driver *VrpDriver) RunningConfigGet(jsonformat bool) (*RunningConfigModel, error)

func (*VrpDriver) RunningConfigSave

func (driver *VrpDriver) RunningConfigSave() error

RunningConfigSave answers VRP's "save" confirmation prompt with "y".

func (*VrpDriver) SetInterfaceDescription

func (driver *VrpDriver) SetInterfaceDescription(intf *netboxtool.NBInterface) error

func (*VrpDriver) SetInterfaceDescriptions

func (driver *VrpDriver) SetInterfaceDescriptions(name []string, intf []*netboxtool.NBInterface) error

func (*VrpDriver) SetInterfaceVLANs

func (driver *VrpDriver) SetInterfaceVLANs(name []string, params []*VLANConfig) error

SetInterfaceVLANs pushes switchport mode and VLAN membership to a set of interfaces. Every VID referenced by any target interface is first declared via "vlan batch <ids>" (matching vrpReVlanBatch's read shape) - VRP rejects "port default vlan"/"port trunk allow-pass vlan" for a VID that hasn't been declared.

func (*VrpDriver) Version

func (driver *VrpDriver) Version() (*VersionModel, error)

Version scrapes a handful of fields out of "display version" text - VRP has no structured (JSON/NETCONF) equivalent to ask instead. Fields VRP's "display version" doesn't clearly expose (MemTotal/MemFree/ BootupTimestap/Architecture/InternalBuildId/SystemMacAddress/ SerialNumber/HardwareRevision) are left zero-valued rather than guessed.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL