Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
controller
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Code review analytics
Issue analytics
Insights
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
TFS
controller
Commits
ffb2d6f4
Commit
ffb2d6f4
authored
2 years ago
by
Lluis Gifre Renom
Browse files
Options
Downloads
Patches
Plain Diff
Test - Tools - IPM Mock Controller:
- First basic and functional version
parent
8ee31f1f
No related branches found
No related tags found
2 merge requests
!142
Release TeraFlowSDN 2.1
,
!71
OFC'23 + IETF L2VPN Device Driver + Device Controllers + Multiple small improvements
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py
+106
-45
106 additions, 45 deletions
src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py
with
106 additions
and
45 deletions
src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py
+
106
−
45
View file @
ffb2d6f4
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
# Mock IPM controller (implements minimal support)
# Mock IPM controller (implements minimal support)
import
functools
,
json
,
logging
,
sys
,
time
,
uuid
import
functools
,
json
,
logging
,
sys
,
time
,
uuid
from
typing
import
Any
,
Dict
,
Optional
,
Tuple
from
flask
import
Flask
,
jsonify
,
make_response
,
request
from
flask
import
Flask
,
jsonify
,
make_response
,
request
from
flask_restful
import
Api
,
Resource
from
flask_restful
import
Api
,
Resource
...
@@ -28,21 +29,57 @@ LOG_LEVEL = logging.DEBUG
...
@@ -28,21 +29,57 @@ LOG_LEVEL = logging.DEBUG
CONSTELLATION
=
{
CONSTELLATION
=
{
'
id
'
:
'
ofc-constellation
'
,
'
id
'
:
'
ofc-constellation
'
,
'
hubModule
'
:
{
'
state
'
:
{
'
hubModule
'
:
{
'
state
'
:
{
'
module
'
:
{
'
moduleName
'
:
'
OFC HUB 1
'
,
'
trafficMode
'
:
'
L1Mode
'
},
'
module
'
:
{
'
moduleName
'
:
'
OFC HUB 1
'
,
'
trafficMode
'
:
'
L1Mode
'
,
'
capacity
'
:
100
},
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}},
{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T4
'
}}]
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}},
{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T4
'
}}]
}},
}},
'
leafModules
'
:
[
'
leafModules
'
:
[
{
'
state
'
:
{
{
'
state
'
:
{
'
module
'
:
{
'
moduleName
'
:
'
OFC LEAF 1
'
,
'
trafficMode
'
:
'
L1Mode
'
},
'
module
'
:
{
'
moduleName
'
:
'
OFC LEAF 1
'
,
'
trafficMode
'
:
'
L1Mode
'
,
'
capacity
'
:
100
},
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}}]
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}}]
}},
}},
{
'
state
'
:
{
{
'
state
'
:
{
'
module
'
:
{
'
moduleName
'
:
'
OFC LEAF 2
'
,
'
trafficMode
'
:
'
L1Mode
'
},
'
module
'
:
{
'
moduleName
'
:
'
OFC LEAF 2
'
,
'
trafficMode
'
:
'
L1Mode
'
,
'
capacity
'
:
100
},
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}}]
'
endpoints
'
:
[{
'
moduleIf
'
:
{
'
clientIfAid
'
:
'
XR-T1
'
}}]
}}
}}
]
]
}
}
CONNECTIONS
:
Dict
[
str
,
Any
]
=
dict
()
STATE_NAME_TO_CONNECTION
:
Dict
[
str
,
str
]
=
dict
()
def
select_module_state
(
module_name
:
str
)
->
Optional
[
Dict
]:
hub_module_state
=
CONSTELLATION
.
get
(
'
hubModule
'
,
{}).
get
(
'
state
'
,
{})
if
module_name
==
hub_module_state
.
get
(
'
module
'
,
{}).
get
(
'
moduleName
'
):
return
hub_module_state
for
leaf_module
in
CONSTELLATION
.
get
(
'
leafModules
'
,
[]):
leaf_module_state
=
leaf_module
.
get
(
'
state
'
,
{})
if
module_name
==
leaf_module_state
.
get
(
'
module
'
,
{}).
get
(
'
moduleName
'
):
return
leaf_module_state
return
None
def
select_endpoint
(
module_state
:
Dict
,
module_if
:
str
)
->
Optional
[
Dict
]:
for
endpoint
in
module_state
.
get
(
'
endpoints
'
,
[]):
if
module_if
==
endpoint
.
get
(
'
moduleIf
'
,
{}).
get
(
'
clientIfAid
'
):
return
endpoint
return
None
def
select_module_endpoint
(
selector
:
Dict
)
->
Optional
[
Tuple
[
Dict
,
Dict
]]:
selected_module_name
=
selector
[
'
moduleIfSelectorByModuleName
'
][
'
moduleName
'
]
selected_module_if
=
selector
[
'
moduleIfSelectorByModuleName
'
][
'
moduleClientIfAid
'
]
module_state
=
select_module_state
(
selected_module_name
)
if
module_state
is
None
:
return
None
return
module_state
,
select_endpoint
(
module_state
,
selected_module_if
)
def
compose_endpoint
(
endpoint_selector
:
Dict
)
->
Dict
:
module
,
endpoint
=
select_module_endpoint
(
endpoint_selector
[
'
selector
'
])
return
{
'
href
'
:
'
/
'
+
str
(
uuid
.
uuid4
()),
'
state
'
:
{
'
moduleIf
'
:
{
'
moduleName
'
:
module
[
'
module
'
][
'
moduleName
'
],
'
clientIfAid
'
:
endpoint
[
'
moduleIf
'
][
'
clientIfAid
'
],
},
'
capacity
'
:
module
[
'
module
'
][
'
capacity
'
],
}
}
logging
.
basicConfig
(
level
=
LOG_LEVEL
,
format
=
"
[%(asctime)s] %(levelname)s:%(name)s:%(message)s
"
)
logging
.
basicConfig
(
level
=
LOG_LEVEL
,
format
=
"
[%(asctime)s] %(levelname)s:%(name)s:%(message)s
"
)
LOGGER
=
logging
.
getLogger
(
__name__
)
LOGGER
=
logging
.
getLogger
(
__name__
)
...
@@ -53,59 +90,85 @@ def log_request(logger : logging.Logger, response):
...
@@ -53,59 +90,85 @@ def log_request(logger : logging.Logger, response):
logger
.
info
(
'
%s %s %s %s %s
'
,
timestamp
,
request
.
remote_addr
,
request
.
method
,
request
.
full_path
,
response
.
status
)
logger
.
info
(
'
%s %s %s %s %s
'
,
timestamp
,
request
.
remote_addr
,
request
.
method
,
request
.
full_path
,
response
.
status
)
return
response
return
response
#class Health(Resource):
# def get(self):
# return make_response(jsonify({}), 200)
class
OpenIdConnect
(
Resource
):
class
OpenIdConnect
(
Resource
):
ACCESS_TOKENS
=
{}
ACCESS_TOKENS
=
{}
def
post
(
self
):
def
post
(
self
):
if
request
.
content_type
!=
'
application/x-www-form-urlencoded
'
:
return
make_response
(
'
bad content type
'
,
400
)
if
request
.
content_type
!=
'
application/x-www-form-urlencoded
'
:
return
make_response
(
'
bad content type
'
,
400
)
if
request
.
content_length
==
0
:
return
make_response
(
'
bad content length
'
,
400
)
if
request
.
content_length
==
0
:
return
make_response
(
'
bad content length
'
,
400
)
form_
request
=
request
.
form
request
_form
=
request
.
form
if
form_
request
.
get
(
'
client_id
'
)
!=
'
xr-web-client
'
:
return
make_response
(
'
bad client_id
'
,
403
)
if
request
_form
.
get
(
'
client_id
'
)
!=
'
xr-web-client
'
:
return
make_response
(
'
bad client_id
'
,
403
)
if
form_
request
.
get
(
'
client_secret
'
)
!=
'
xr-web-client
'
:
return
make_response
(
'
bad client_secret
'
,
403
)
if
request
_form
.
get
(
'
client_secret
'
)
!=
'
xr-web-client
'
:
return
make_response
(
'
bad client_secret
'
,
403
)
if
form_
request
.
get
(
'
grant_type
'
)
!=
'
password
'
:
return
make_response
(
'
bad grant_type
'
,
403
)
if
request
_form
.
get
(
'
grant_type
'
)
!=
'
password
'
:
return
make_response
(
'
bad grant_type
'
,
403
)
if
form_
request
.
get
(
'
username
'
)
!=
IPM_USERNAME
:
return
make_response
(
'
bad username
'
,
403
)
if
request
_form
.
get
(
'
username
'
)
!=
IPM_USERNAME
:
return
make_response
(
'
bad username
'
,
403
)
if
form_
request
.
get
(
'
password
'
)
!=
IPM_PASSWORD
:
return
make_response
(
'
bad password
'
,
403
)
if
request
_form
.
get
(
'
password
'
)
!=
IPM_PASSWORD
:
return
make_response
(
'
bad password
'
,
403
)
access_token
=
OpenIdConnect
.
ACCESS_TOKENS
.
setdefault
(
IPM_USERNAME
,
uuid
.
uuid4
())
access_token
=
OpenIdConnect
.
ACCESS_TOKENS
.
setdefault
(
IPM_USERNAME
,
uuid
.
uuid4
())
reply
=
{
'
access_token
'
:
access_token
,
'
expires_in
'
:
86400
}
reply
=
{
'
access_token
'
:
access_token
,
'
expires_in
'
:
86400
}
return
make_response
(
jsonify
(
reply
),
200
)
return
make_response
(
jsonify
(
reply
),
200
)
class
XrNetworks
(
Resource
):
class
XrNetworks
(
Resource
):
def
get
(
self
):
def
get
(
self
):
print
(
str
(
request
.
args
))
content
=
request
.
args
.
get
(
'
content
'
)
print
(
'
content
'
,
content
)
query
=
json
.
loads
(
request
.
args
.
get
(
'
q
'
))
query
=
json
.
loads
(
request
.
args
.
get
(
'
q
'
))
hub_module_name
=
query
.
get
(
'
hubModule.state.module.moduleName
'
)
hub_module_name
=
query
.
get
(
'
hubModule.state.module.moduleName
'
)
if
hub_module_name
!=
'
OFC HUB 1
'
:
return
make_response
(
'
unexpected hub module
'
,
404
)
if
hub_module_name
!=
'
OFC HUB 1
'
:
return
make_response
(
'
unexpected hub module
'
,
404
)
print
(
'
query
'
,
query
)
return
make_response
(
jsonify
([
CONSTELLATION
]),
200
)
return
make_response
(
jsonify
([
CONSTELLATION
]),
200
)
#class Services(Resource):
class
XrNetworkConnections
(
Resource
):
# def get(self):
def
get
(
self
):
# services = [service for service in NETWORK_SERVICES.values()]
query
=
json
.
loads
(
request
.
args
.
get
(
'
q
'
))
# return make_response(jsonify({'ietf-eth-tran-service:etht-svc': {'etht-svc-instances': services}}), 200)
state_name
=
query
.
get
(
'
state.name
'
)
#
if
state_name
is
None
:
# def post(self):
connections
=
[
connection
for
connection
in
CONNECTIONS
.
values
()]
# json_request = request.get_json()
else
:
# if not json_request: abort(400)
connection_uuid
=
STATE_NAME_TO_CONNECTION
.
get
(
state_name
)
# if not isinstance(json_request, dict): abort(400)
if
connection_uuid
is
None
:
return
make_response
(
'
state name not found
'
,
404
)
# if 'etht-svc-instances' not in json_request: abort(400)
connection
=
CONNECTIONS
.
get
(
connection_uuid
)
# json_services = json_request['etht-svc-instances']
if
connection
is
None
:
return
make_response
(
'
connection for state name not found
'
,
404
)
# if not isinstance(json_services, list): abort(400)
connections
=
[
connection
]
# if len(json_services) != 1: abort(400)
return
make_response
(
jsonify
(
connections
),
200
)
# svc_data = json_services[0]
# etht_svc_name = svc_data['etht-svc-name']
def
post
(
self
):
# NETWORK_SERVICES[etht_svc_name] = svc_data
if
request
.
content_type
!=
'
application/json
'
:
return
make_response
(
'
bad content type
'
,
400
)
# return make_response(jsonify({}), 201)
if
request
.
content_length
==
0
:
return
make_response
(
'
bad content length
'
,
400
)
request_json
=
request
.
json
#class DelServices(Resource):
if
not
isinstance
(
request_json
,
list
):
return
make_response
(
'
content is not list
'
,
400
)
# def delete(self, service_uuid : str):
reply
=
[]
# NETWORK_SERVICES.pop(service_uuid, None)
for
connection
in
request_json
:
# return make_response(jsonify({}), 204)
connection_uuid
=
str
(
uuid
.
uuid4
())
state_name
=
connection
[
'
name
'
]
if
state_name
is
not
None
:
STATE_NAME_TO_CONNECTION
[
state_name
]
=
connection_uuid
CONNECTIONS
[
connection_uuid
]
=
{
'
href
'
:
'
/network-connections/{:s}
'
.
format
(
str
(
connection_uuid
)),
'
config
'
:
{
'
implicitTransportCapacity
'
:
connection
[
'
implicitTransportCapacity
'
]
# 'mc': ??
},
'
state
'
:
{
'
name
'
:
state_name
,
'
serviceMode
'
:
connection
[
'
serviceMode
'
]
# 'outerVID' : ??
},
'
endpoints
'
:
[
compose_endpoint
(
endpoint
)
for
endpoint
in
connection
[
'
endpoints
'
]
]
}
reply
.
append
(
CONNECTIONS
[
connection_uuid
])
return
make_response
(
jsonify
(
reply
),
202
)
class
XrNetworkConnection
(
Resource
):
def
get
(
self
,
connection_uuid
:
str
):
connection
=
CONNECTIONS
.
get
(
connection_uuid
)
if
connection
is
None
:
return
make_response
(
'
unexpected connection id
'
,
404
)
return
make_response
(
jsonify
(
connection
),
200
)
def
delete
(
self
,
connection_uuid
:
str
):
connection
=
CONNECTIONS
.
pop
(
connection_uuid
,
None
)
if
connection
is
None
:
return
make_response
(
'
unexpected connection id
'
,
404
)
state_name
=
connection
[
'
state
'
][
'
name
'
]
STATE_NAME_TO_CONNECTION
.
pop
(
state_name
,
None
)
return
make_response
(
jsonify
({}),
202
)
def
main
():
def
main
():
LOGGER
.
info
(
'
Starting...
'
)
LOGGER
.
info
(
'
Starting...
'
)
...
@@ -114,12 +177,10 @@ def main():
...
@@ -114,12 +177,10 @@ def main():
app
.
after_request
(
functools
.
partial
(
log_request
,
LOGGER
))
app
.
after_request
(
functools
.
partial
(
log_request
,
LOGGER
))
api
=
Api
(
app
)
api
=
Api
(
app
)
#api.add_resource(Health, '/ietf-network:networks')
api
.
add_resource
(
OpenIdConnect
,
'
/realms/xr-cm/protocol/openid-connect/token
'
)
api
.
add_resource
(
OpenIdConnect
,
'
/realms/xr-cm/protocol/openid-connect/token
'
)
api
.
add_resource
(
XrNetworks
,
'
/api/v1/xr-networks
'
)
api
.
add_resource
(
XrNetworks
,
'
/api/v1/xr-networks
'
)
api
.
add_resource
(
XrNetworkConnections
,
'
/api/v1/network-connections
'
)
#api.add_resource(Network, '/ietf-network:networks/network=<string:network_uuid>')
api
.
add_resource
(
XrNetworkConnection
,
'
/api/v1/network-connections/<string:connection_uuid>
'
)
#api.add_resource(Services, '/ietf-eth-tran-service:etht-svc')
#api.add_resource(DelServices, '/ietf-eth-tran-service:etht-svc/etht-svc-instances=<string:service_uuid>')
LOGGER
.
info
(
'
Listening on {:s}...
'
.
format
(
str
(
STR_ENDPOINT
)))
LOGGER
.
info
(
'
Listening on {:s}...
'
.
format
(
str
(
STR_ENDPOINT
)))
app
.
run
(
debug
=
True
,
host
=
BIND_ADDRESS
,
port
=
BIND_PORT
,
ssl_context
=
'
adhoc
'
)
app
.
run
(
debug
=
True
,
host
=
BIND_ADDRESS
,
port
=
BIND_PORT
,
ssl_context
=
'
adhoc
'
)
...
...
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