Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
I
inventory-provider
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
Show more breadcrumbs
geant-swd
dashboardv3
inventory-provider
Commits
2f3bc862
Commit
2f3bc862
authored
4 years ago
by
Robert Latta
Browse files
Options
Downloads
Patches
Plain Diff
added all juniper related classifications
parent
711cd409
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
inventory_provider/routes/ims_classifier.py
+197
-32
197 additions, 32 deletions
inventory_provider/routes/ims_classifier.py
with
197 additions
and
32 deletions
inventory_provider/routes/ims_classifier.py
+
197
−
32
View file @
2f3bc862
import
ipaddress
import
ipaddress
import
json
import
json
import
logging
import
logging
import
re
from
flask
import
Blueprint
,
Response
,
current_app
from
flask
import
Blueprint
,
Response
,
current_app
...
@@ -11,34 +12,7 @@ routes = Blueprint("ims-inventory-data-classifier-support-routes", __name__)
...
@@ -11,34 +12,7 @@ routes = Blueprint("ims-inventory-data-classifier-support-routes", __name__)
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
class
ClassifierRequestError
(
Exception
):
status_code
=
500
def
__init__
(
self
):
super
().
__init__
()
self
.
message
=
"
Unclassified Internal Error
"
class
ClassifierProcessingError
(
ClassifierRequestError
):
status_code
=
422
def
__init__
(
self
,
message
,
status_code
=
None
):
super
().
__init__
()
self
.
message
=
str
(
message
)
if
status_code
is
not
None
:
self
.
status_code
=
status_code
@routes.errorhandler
(
ClassifierRequestError
)
def
handle_request_error
(
error
):
return
Response
(
response
=
error
.
message
,
status
=
error
.
status_code
)
@routes.after_request
def
after_request
(
resp
):
return
common
.
after_request
(
resp
)
def
_LOCATION
(
equipment
,
name
,
abbreviation
):
def
_LOCATION
(
equipment
,
name
,
abbreviation
):
...
@@ -100,6 +74,36 @@ def _location_from_service_dict(s):
...
@@ -100,6 +74,36 @@ def _location_from_service_dict(s):
return
location
return
location
class
ClassifierRequestError
(
Exception
):
status_code
=
500
def
__init__
(
self
):
super
().
__init__
()
self
.
message
=
"
Unclassified Internal Error
"
class
ClassifierProcessingError
(
ClassifierRequestError
):
status_code
=
422
def
__init__
(
self
,
message
,
status_code
=
None
):
super
().
__init__
()
self
.
message
=
str
(
message
)
if
status_code
is
not
None
:
self
.
status_code
=
status_code
@routes.errorhandler
(
ClassifierRequestError
)
def
handle_request_error
(
error
):
return
Response
(
response
=
error
.
message
,
status
=
error
.
status_code
)
@routes.after_request
def
after_request
(
resp
):
return
common
.
after_request
(
resp
)
def
related_interfaces
(
hostname
,
interface
):
def
related_interfaces
(
hostname
,
interface
):
r
=
common
.
get_current_redis
()
r
=
common
.
get_current_redis
()
prefix
=
'
netconf-interfaces:%s:
'
%
hostname
prefix
=
'
netconf-interfaces:%s:
'
%
hostname
...
@@ -130,18 +134,28 @@ def get_top_level_services(circuit_id, r):
...
@@ -130,18 +134,28 @@ def get_top_level_services(circuit_id, r):
return
tls
return
tls
def
get_ims_equipment_name
(
equipment_name
:
str
)
->
str
:
ims_equipment_name
=
equipment_name
.
upper
()
if
ims_equipment_name
.
startswith
(
'
MX
'
):
ims_equipment_name
=
ims_equipment_name
.
split
(
'
.GEANT.NET
'
)[
0
]
return
ims_equipment_name
def
get_ims_interface
(
interface
:
str
)
->
str
:
return
interface
.
upper
()
@routes.route
(
"
/juniper-link-info/<source_equipment>/<path:interface>
"
,
@routes.route
(
"
/juniper-link-info/<source_equipment>/<path:interface>
"
,
methods
=
[
'
GET
'
,
'
POST
'
])
methods
=
[
'
GET
'
,
'
POST
'
])
@common.require_accepts_json
@common.require_accepts_json
def
get_juniper_link_info
(
source_equipment
:
str
,
interface
:
str
):
def
get_juniper_link_info
(
source_equipment
:
str
,
interface
:
str
):
ims_source_equipment
=
source_equipment
.
upper
()
ims_source_equipment
=
get_ims_equipment_name
(
source_equipment
)
ims_interface
=
interface
.
upper
()
ims_interface
=
get_ims_interface
(
interface
)
if
ims_source_equipment
.
startswith
(
'
MX
'
):
ims_source_equipment
=
ims_source_equipment
.
split
(
'
.GEANT.NET
'
)[
0
]
r
=
common
.
get_current_redis
()
r
=
common
.
get_current_redis
()
cache_key
=
f
'
ims-classifier-cache:juniper:
{
ims_source_equipment
}
:
{
ims_interface
}
'
cache_key
=
\
f
'
ims-classifier-cache:juniper:
{
ims_source_equipment
}
:
{
ims_interface
}
'
# result = r.get(cache_key)
# result = r.get(cache_key)
result
=
False
result
=
False
...
@@ -217,3 +231,154 @@ def get_juniper_link_info(source_equipment: str, interface: str):
...
@@ -217,3 +231,154 @@ def get_juniper_link_info(source_equipment: str, interface: str):
r
.
set
(
cache_key
,
result
.
encode
(
'
utf-8
'
))
r
.
set
(
cache_key
,
result
.
encode
(
'
utf-8
'
))
return
Response
(
result
,
mimetype
=
"
application/json
"
)
return
Response
(
result
,
mimetype
=
"
application/json
"
)
def
ix_peering_info
(
peer_info
):
"""
TODO: this is probably the least efficient way of doing this
(if it
'
s a problem, pre-compute these lists)
:param peer_info: an element from ix_public_peer:address
:return:
"""
result
=
{
'
peer
'
:
peer_info
,
'
group
'
:
[],
'
router
'
:
[]
}
try
:
address
=
ipaddress
.
ip_address
(
peer_info
[
'
name
'
])
except
ValueError
:
raise
ClassifierProcessingError
(
'
unable to parse %r as an ip address
'
%
address
)
description
=
peer_info
[
'
description
'
]
assert
description
is
not
None
# sanity
keyword
=
description
.
split
(
'
'
)[
0
]
# regex needed??? (e.g. tabs???)
for
doc
in
common
.
load_json_docs
(
config_params
=
current_app
.
config
[
'
INVENTORY_PROVIDER_CONFIG
'
],
key_pattern
=
'
ix_public_peer:*
'
,
num_threads
=
10
):
other
=
doc
[
'
value
'
]
if
other
[
'
router
'
]
==
peer_info
[
'
router
'
]:
result
[
'
router
'
].
append
(
other
[
'
name
'
])
assert
other
[
'
description
'
]
is
not
None
# sanity: as above...
if
other
[
'
description
'
].
startswith
(
keyword
):
result
[
'
group
'
].
append
(
other
[
'
name
'
])
return
result
def
find_interfaces
(
address
):
"""
TODO: this is probably the least efficient way of doing this
(if it
'
s a problem, pre-compute these lists)
:param address: an ipaddress object
:return:
"""
r
=
common
.
get_current_redis
()
for
k
in
r
.
keys
(
'
subnets:*
'
):
k
=
k
.
decode
(
'
utf-8
'
)
m
=
re
.
match
(
r
'
^subnets:(.*)$
'
,
k
)
assert
m
,
'
sanity failure: redis returned an invalid key name
'
interface
=
ipaddress
.
ip_interface
(
m
.
group
(
1
))
if
address
in
interface
.
network
:
info
=
r
.
get
(
k
).
decode
(
'
utf-8
'
)
info
=
json
.
loads
(
info
)
for
ifc
in
info
:
yield
ifc
def
find_interfaces_and_services
(
address_str
):
"""
:param address_str: an ipaddress object
:return:
"""
try
:
address
=
ipaddress
.
ip_address
(
address_str
)
except
ValueError
:
raise
ClassifierProcessingError
(
f
'
unable to parse
{
address_str
}
as an ip address
'
)
r
=
common
.
get_current_redis
()
for
interface
in
find_interfaces
(
address
):
ims_equipment
=
get_ims_equipment_name
(
interface
[
"
router
"
])
ims_interface
=
get_ims_interface
(
interface
[
"
interface name
"
])
services
=
r
.
get
(
f
'
ims:interface_services:
{
ims_equipment
}
:
{
ims_interface
}
'
)
if
not
services
:
services
=
[]
else
:
services
=
json
.
loads
(
services
.
decode
(
'
utf=8
'
))
yield
{
'
interface
'
:
interface
,
'
services
'
:
services
}
@routes.route
(
"
/peer-info/<address>
"
,
methods
=
[
'
GET
'
,
'
POST
'
])
@common.require_accepts_json
def
peer_info
(
address
):
# canonicalize the input address first ...
try
:
obj
=
ipaddress
.
ip_address
(
address
)
address
=
obj
.
exploded
except
ValueError
:
raise
ClassifierProcessingError
(
f
'
unable to parse
{
address
}
as an ip address
'
)
r
=
common
.
get_current_redis
()
cache_key
=
f
'
classifier-cache:peer:
{
address
}
'
# result = r.get(cache_key)
result
=
False
if
result
:
result
=
result
.
decode
(
'
utf-8
'
)
else
:
result
=
{
'
locations
'
:
[]
}
info
=
r
.
get
(
f
'
ix_public_peer:
{
address
}
'
)
if
info
:
info
=
info
.
decode
(
'
utf-8
'
)
info
=
json
.
loads
(
info
)
result
[
'
ix-public-peer-info
'
]
=
ix_peering_info
(
info
)
result
[
'
locations
'
]
+=
_locations_from_router
(
info
[
'
router
'
])
info
=
r
.
get
(
'
vpn_rr_peer:%s
'
%
address
)
if
info
:
info
=
info
.
decode
(
'
utf-8
'
)
info
=
json
.
loads
(
info
)
result
[
'
vpn-rr-peer-info
'
]
=
info
result
[
'
locations
'
]
+=
_locations_from_router
(
info
[
'
router
'
])
interfaces
=
list
(
find_interfaces_and_services
(
address
))
if
interfaces
:
result
[
'
interfaces
'
]
=
interfaces
for
i
in
interfaces
:
result
[
'
locations
'
]
+=
[
_location_from_service_dict
(
s
)
for
s
in
i
[
'
services
'
]]
result
[
'
locations
'
]
=
_remove_duplicates_from_list
(
result
[
'
locations
'
])
result
=
json
.
dumps
(
result
)
# cache this data for the next call
r
.
set
(
cache_key
,
result
.
encode
(
'
utf-8
'
))
return
Response
(
result
,
mimetype
=
"
application/json
"
)
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