Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
Resource Manager
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
GÉANT Orchestration and Automation Team
GAP
Resource Manager
Commits
2cd5d918
Commit
2cd5d918
authored
2 years ago
by
Erik Reid
Browse files
Options
Downloads
Patches
Plain Diff
utils for loading phy/log interfaces
parent
2ad98c1a
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
resource_management/hardware/juniper.py
+128
-0
128 additions, 0 deletions
resource_management/hardware/juniper.py
test/conftest.py
+4
-2
4 additions, 2 deletions
test/conftest.py
test/test_parse_router.py
+32
-4
32 additions, 4 deletions
test/test_parse_router.py
with
164 additions
and
6 deletions
resource_management/hardware/juniper.py
+
128
−
0
View file @
2cd5d918
...
...
@@ -293,6 +293,134 @@ def _load_pic_connected_ports(
yield
_p
def
_load_aggregates
(
router
:
'
jnpr.junos.Device
'
):
"""
computes 802.3ad lag bundles
returns a dict formatted as:
{
lag interface name: set of physical interface names
}
"""
catalog_spec
=
{
'
InterfacesTable
'
:
{
'
rpc
'
:
'
get-configuration
'
,
'
item
'
:
'
//interface//gigether-options//ieee-802.3ad
'
,
'
key
'
:
[
"
ancestor::interface/name
"
,
'
bundle
'
],
'
view
'
:
'
_interfaces_view
'
},
'
_interfaces_view
'
:
{
'
fields
'
:
{
'
bundle
'
:
'
bundle
'
,
# "name" as a field is a reserved word
'
interface
'
:
'
ancestor::interface/name
'
,
}
}
}
loader
=
FactoryLoader
()
catalog
=
loader
.
load
(
catalog_spec
)
InterfacesTable
=
catalog
[
'
InterfacesTable
'
]
bundles
=
{}
for
ifc
in
InterfacesTable
(
router
).
get
():
assert
ifc
.
bundle
# sanity check
# bundles.setdefault(ifc.bundle, set()).add(ifc.interface)
bundles
.
setdefault
(
ifc
.
bundle
,
[]).
append
(
ifc
.
interface
)
return
bundles
def
_load_logical_interfaces
(
router
:
'
jnpr.junos.Device
'
):
"""
loads logical interfaces
returns a dict formatted as:
{
physical interface name: set of logical interface names
}
"""
catalog_spec
=
{
'
LogicalInterfacesTable
'
:
{
'
rpc
'
:
'
get-interface-information
'
,
'
item
'
:
'
//physical-interface/logical-interface
'
,
'
key
'
:
'
name
'
,
'
view
'
:
'
_logical_interfaces_view
'
},
'
_logical_interfaces_view
'
:
{
'
fields
'
:
{
'
logical
'
:
'
name
'
,
'
physical
'
:
'
ancestor::physical-interface/name
'
,
}
}
}
loader
=
FactoryLoader
()
catalog
=
loader
.
load
(
catalog_spec
)
LogicalInterfacesTable
=
catalog
[
'
LogicalInterfacesTable
'
]
interfaces
=
{}
for
lu
in
LogicalInterfacesTable
(
router
).
get
():
assert
lu
.
logical
.
startswith
(
lu
.
physical
)
# sanity
interfaces
.
setdefault
(
lu
.
physical
,
set
()).
add
(
lu
.
logical
)
return
interfaces
def
_load_installed_ethernet_ports
(
router
:
'
jnpr.junos.Device
'
):
"""
can
'
t just use jnpr.junos.op.ethport.EthPortTable
some routers in our network don
'
t return int for mtu from
that command, and the pyez view has some validation that fails
for each physical port on the router, yields a dict formatted like:
{
'
name
'
: str, # interface name
'
admin
'
: bool, # admin status (
'
up
'
== True)
'
oper
'
: bool, # operational status (
'
up
'
== True)
}
"""
catalog_spec
=
{
'
PhysicalInterfacesTable
'
:
{
'
rpc
'
:
'
get-interface-information
'
,
'
item
'
:
'
//physical-interface
'
,
'
key
'
:
'
name
'
,
'
view
'
:
'
_physical_interfaces_view
'
},
'
_physical_interfaces_view
'
:
{
'
fields
'
:
{
'
interface
'
:
'
name
'
,
'
admin
'
:
'
admin-status
'
,
'
oper
'
:
'
oper-status
'
}
}
}
loader
=
FactoryLoader
()
catalog
=
loader
.
load
(
catalog_spec
)
PhysicalInterfacesTable
=
catalog
[
'
PhysicalInterfacesTable
'
]
for
ifc
in
PhysicalInterfacesTable
(
router
).
get
():
yield
{
'
name
'
:
ifc
.
interface
,
'
admin
'
:
ifc
.
admin
==
'
up
'
,
'
oper
'
:
ifc
.
admin
==
'
up
'
}
def
load_router_ports
(
hostname
,
ssh_config
,
port
=
830
):
"""
merges the results of calls to:
...
...
This diff is collapsed.
Click to expand it.
test/conftest.py
+
4
−
2
View file @
2cd5d918
...
...
@@ -16,7 +16,7 @@ from resource_management.db import model
RPC_DATA_DIR
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'
rpc-data
'
)
HOSTNAMES
=
[
# 'vmx',
#
#
'vmx',
'
mx1.lab.office.geant.net
'
,
'
mx2.lab.office.geant.net
'
,
'
mx3.lab.office.geant.net
'
,
...
...
@@ -34,7 +34,7 @@ HOSTNAMES = [
'
mx1.lon.uk.geant.net
'
,
'
mx1.lon2.uk.geant.net
'
,
'
mx1.mad.es.geant.net
'
,
'
mx1.mil2.it.geant.net
'
,
#
'mx1.mil2.it.geant.net',
'
mx1.par.fr.geant.net
'
,
'
mx1.poz.pl.geant.net
'
,
'
mx1.sof.bg.geant.net
'
,
...
...
@@ -171,6 +171,8 @@ def mocked_router(netconf_rpc_replies):
# the test data format is documented
# in test/rpc-data/capture-test-data.py
if
rpc_command
.
tag
==
'
get-configuration
'
:
return
'
configuration
'
if
rpc_command
.
tag
==
'
get-system-information
'
:
return
'
system
'
if
rpc_command
.
tag
==
'
get-chassis-inventory
'
:
...
...
This diff is collapsed.
Click to expand it.
test/test_parse_router.py
+
32
−
4
View file @
2cd5d918
...
...
@@ -3,8 +3,7 @@ import re
from
jsonschema
import
validate
from
lxml
import
etree
from
resource_management.hardware.juniper
\
import
load_router_ports
,
LINE_CARDS_LIST_SCHEMA
from
resource_management.hardware
import
juniper
def
_remove_ns
(
xml
):
...
...
@@ -25,9 +24,9 @@ def test_router_ports(mocked_router, netconf_rpc_replies):
'
username
'
:
'
bogus
'
,
'
private-key
'
:
'
no file
'
}
fpcs
=
load_router_ports
(
hostname
=
'
bogus
'
,
ssh_config
=
ssh
)
fpcs
=
juniper
.
load_router_ports
(
hostname
=
'
bogus
'
,
ssh_config
=
ssh
)
fpcs
=
list
(
fpcs
)
validate
(
fpcs
,
LINE_CARDS_LIST_SCHEMA
)
validate
(
fpcs
,
juniper
.
LINE_CARDS_LIST_SCHEMA
)
inventory
=
_remove_ns
(
netconf_rpc_replies
[
'
inventory
'
])
expected_fpcs
=
list
(
inventory
.
xpath
(
...
...
@@ -46,3 +45,32 @@ def test_router_ports(mocked_router, netconf_rpc_replies):
# would be hard to maintain against code changes)
assert
set
(
map
(
_slot_number
,
expected_fpcs
))
\
==
{
f
[
'
slot
'
]
for
f
in
fpcs
}
def
test_new_load_interfaces
(
mocked_router
,
netconf_rpc_replies
):
"""
renewed design for this app: no chassis info for now
"""
ssh
=
{
'
username
'
:
'
bogus
'
,
'
private-key
'
:
'
no file
'
}
with
juniper
.
router
(
hostname
=
'
blah-bogus
'
,
port
=
12345
,
ssh_config
=
ssh
)
as
dev
:
# with contextlib.closing(dev.open()) as d:
# config = d.rpc.get_config()
# print(len(config))
# just sanity check there are non-empty responses
physical
=
list
(
juniper
.
_load_installed_ethernet_ports
(
dev
))
assert
physical
logical
=
juniper
.
_load_logical_interfaces
(
dev
)
assert
logical
aggregates
=
juniper
.
_load_aggregates
(
dev
)
assert
aggregates
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment