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
2e612108
Commit
2e612108
authored
5 months ago
by
Shayan Hajipour
Browse files
Options
Downloads
Patches
Plain Diff
refactoring
parent
91166434
No related branches found
No related tags found
2 merge requests
!359
Release TeraFlowSDN 5.0
,
!302
Resolve "Elaborate IETF Slice NBI to support adding/deleting new sdp, connection group, and match criteria"
Changes
1
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf_slice_handler.py
+343
-283
343 additions, 283 deletions
...rver/nbi_plugins/ietf_network_slice/ietf_slice_handler.py
with
343 additions
and
283 deletions
src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf_slice_handler.py
+
343
−
283
View file @
2e612108
...
@@ -32,90 +32,177 @@ ADDRESS_PREFIX = 24
...
@@ -32,90 +32,177 @@ ADDRESS_PREFIX = 24
RAISE_IF_DIFFERS
=
False
RAISE_IF_DIFFERS
=
False
def
get_endpoint_controller_type
(
def
validate_ietf_slice_data
(
request_data
:
Dict
)
->
None
:
endpoint
:
EndPointId
,
context_client
:
ContextClient
"""
)
->
str
:
Validate the provided IETF slice data against the YANG model.
endpoint_device
:
Device
=
context_client
.
GetDevice
(
endpoint
.
device_id
)
"""
if
endpoint_device
.
controller_id
==
DeviceId
():
yang_validator
=
YangValidator
(
"
ietf-network-slice-service
"
)
return
""
_
=
yang_validator
.
parse_to_dict
(
request_data
)
controller
=
context_client
.
GetDevice
(
endpoint_device
.
controller_id
)
yang_validator
.
destroy
()
if
controller
is
None
:
controller_uuid
=
endpoint_device
.
controller_id
.
device_uuid
.
uuid
raise
Exception
(
"
Device({:s}) not found
"
.
format
(
str
(
controller_uuid
)))
return
controller
.
device_type
def
get_custom_config_rule
(
def
get_custom_config_rule
(
service_config
:
ServiceConfig
,
resource_key
:
str
service_config
:
ServiceConfig
,
resource_key
:
str
)
->
Optional
[
ConfigRule
]:
)
->
Optional
[
ConfigRule
]:
"""
Retrieve the custom config rule with the given resource_key from a ServiceConfig.
"""
for
cr
in
service_config
.
config_rules
:
for
cr
in
service_config
.
config_rules
:
if
(
if
(
cr
.
WhichOneof
(
"
config_rule
"
)
==
"
custom
"
cr
.
WhichOneof
(
"
config_rule
"
)
==
"
custom
"
and
cr
.
custom
.
resource_key
==
resource_key
and
cr
.
custom
.
resource_key
==
resource_key
):
):
return
cr
return
cr
return
None
def
get_ietf_data_from_config
(
slice_request
:
Slice
,
resource_key
:
str
)
->
Dict
:
"""
Retrieve the IETF data (as a Python dict) from a slice
'
s config rule for the specified resource_key.
Raises an exception if not found.
"""
config_rule
=
get_custom_config_rule
(
slice_request
.
slice_config
,
resource_key
)
if
not
config_rule
:
raise
Exception
(
f
"
IETF data not found for resource_key:
{
resource_key
}
"
)
return
json
.
loads
(
config_rule
.
custom
.
resource_value
)
def
update_ietf_data_in_config
(
slice_request
:
Slice
,
resource_key
:
str
,
ietf_data
:
Dict
)
->
None
:
"""
Update the slice config rule (identified by resource_key) with the provided IETF data.
"""
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
resource_key
,
fields
)
def
build_constraints_from_connection_group
(
connection_group
:
dict
)
->
List
[
Constraint
]:
"""
Build a list of Constraints from the
'
metric-bound
'
data in a connection group.
"""
constraints
=
[]
metric_bounds
=
connection_group
[
"
connectivity-construct
"
][
0
][
"
service-slo-sle-policy
"
][
"
slo-policy
"
][
"
metric-bound
"
]
for
metric
in
metric_bounds
:
metric_type
=
metric
[
"
metric-type
"
]
if
metric_type
==
"
ietf-nss:one-way-delay-maximum
"
:
bound_value
=
float
(
metric
[
"
bound
"
])
constraint
=
Constraint
()
constraint
.
sla_latency
.
e2e_latency_ms
=
bound_value
constraints
.
append
(
constraint
)
elif
metric_type
==
"
ietf-nss:one-way-bandwidth
"
:
bound_value
=
float
(
metric
[
"
bound
"
])
constraint
=
Constraint
()
# Convert from Mbps to Gbps if needed
constraint
.
sla_capacity
.
capacity_gbps
=
bound_value
/
1.0e3
constraints
.
append
(
constraint
)
return
constraints
def
get_endpoint_controller_type
(
endpoint
:
EndPointId
,
context_client
:
ContextClient
)
->
str
:
"""
Retrieve the device type of an endpoint
'
s controller device, if any; otherwise returns an empty string.
"""
endpoint_device
:
Device
=
context_client
.
GetDevice
(
endpoint
.
device_id
)
if
endpoint_device
.
controller_id
==
DeviceId
():
return
""
controller
=
context_client
.
GetDevice
(
endpoint_device
.
controller_id
)
if
controller
is
None
:
controller_uuid
=
endpoint_device
.
controller_id
.
device_uuid
.
uuid
raise
Exception
(
f
"
Controller device
{
controller_uuid
}
not found
"
)
return
controller
.
device_type
def
sort_endpoints
(
def
sort_endpoints
(
endpoin
s
t_list
:
List
[
EndPointId
],
endpoint
s
_list
:
List
[
EndPointId
],
sdps
:
List
,
sdps
:
List
,
connection_group
:
Dict
,
connection_group
:
Dict
,
context_client
:
ContextClient
,
context_client
:
ContextClient
,
)
->
List
[
EndPointId
]:
)
->
List
[
EndPointId
]:
first_ep
=
endpoinst_list
[
0
]
"""
Sort the endpoints_list based on controller type:
- If the first endpoint is an NCE, keep order.
- If the last endpoint is an NCE, reverse order.
- Otherwise, use the
'
p2p-sender-sdp
'
from the connection group to decide.
"""
if
not
endpoints_list
:
return
endpoints_list
first_ep
=
endpoints_list
[
0
]
last_ep
=
endpoints_list
[
-
1
]
first_controller_type
=
get_endpoint_controller_type
(
first_ep
,
context_client
)
first_controller_type
=
get_endpoint_controller_type
(
first_ep
,
context_client
)
last_ep
=
endpoinst_list
[
-
1
]
last_controller_type
=
get_endpoint_controller_type
(
last_ep
,
context_client
)
last_controller_type
=
get_endpoint_controller_type
(
last_ep
,
context_client
)
if
first_controller_type
==
DeviceTypeEnum
.
NCE
.
value
:
if
first_controller_type
==
DeviceTypeEnum
.
NCE
.
value
:
return
endpoin
s
t_list
return
endpoint
s
_list
elif
last_controller_type
==
DeviceTypeEnum
.
NCE
.
value
:
elif
last_controller_type
==
DeviceTypeEnum
.
NCE
.
value
:
return
endpoinst_list
[::
-
1
]
return
endpoints_list
[::
-
1
]
else
:
src_sdp_id
=
connection_group
[
"
connectivity-construct
"
][
0
][
"
p2p-sender-sdp
"
]
src_sdp_id
=
connection_group
[
"
connectivity-construct
"
][
0
][
"
p2p-sender-sdp
"
]
sdp_id_name_mapping
=
{
sdp
[
"
id
"
]:
sdp
[
"
node-id
"
]
for
sdp
in
sdps
}
sdp_id_name_mapping
=
{
sdp
[
"
id
"
]:
sdp
[
"
node-id
"
]
for
sdp
in
sdps
}
if
(
if
endpoints_list
[
0
].
device_id
.
device_uuid
.
uuid
==
sdp_id_name_mapping
[
src_sdp_id
]:
endpoinst_list
[
0
].
device_id
.
device_uuid
.
uuid
return
endpoints_list
==
sdp_id_name_mapping
[
src_sdp_id
]
return
endpoints_list
[::
-
1
]
):
return
endpoinst_list
return
endpoinst_list
[::
-
1
]
def
replace_ont_endpoint_with_emu_dc
(
def
replace_ont_endpoint_with_emu_dc
(
endpoint_list
:
List
,
context_client
:
ContextClient
endpoint_list
:
List
[
EndPointId
],
context_client
:
ContextClient
)
->
List
:
)
->
List
[
EndPointId
]:
"""
Replace an ONT endpoint in endpoint_list with an
'
emu-datacenter
'
endpoint if found.
One endpoint must be managed (controller_id != empty), the other must be unmanaged.
"""
if
len
(
endpoint_list
)
!=
2
:
raise
Exception
(
"
Expecting exactly two endpoints to handle ONT -> emu-dc replacement
"
)
link_list
=
context_client
.
ListLinks
(
Empty
())
link_list
=
context_client
.
ListLinks
(
Empty
())
links
=
list
(
link_list
.
links
)
links
=
list
(
link_list
.
links
)
devices_list
=
context_client
.
ListDevices
(
Empty
())
devices_list
=
context_client
.
ListDevices
(
Empty
())
devices
=
devices_list
.
devices
devices
=
devices_list
.
devices
uuid_name_map
=
{
d
.
device_id
.
device_uuid
.
uuid
:
d
.
name
for
d
in
devices
}
uuid_name_map
=
{
d
.
device_id
.
device_uuid
.
uuid
:
d
.
name
for
d
in
devices
}
uuid_device_map
=
{
d
.
device_id
.
device_uuid
.
uuid
:
d
for
d
in
devices
}
uuid_device_map
=
{
d
.
device_id
.
device_uuid
.
uuid
:
d
for
d
in
devices
}
name_device_map
=
{
d
.
name
:
d
for
d
in
devices
}
name_device_map
=
{
d
.
name
:
d
for
d
in
devices
}
endpoint_id_1
=
endpoint_list
[
0
]
endpoint_id_1
,
endpoint_id_2
=
endpoint_list
device_uuid_1
=
endpoint_id_1
.
device_id
.
device_uuid
.
uuid
device_uuid_1
=
endpoint_id_1
.
device_id
.
device_uuid
.
uuid
device_1
=
name_device_map
[
device_uuid_1
]
endpoint_id_2
=
endpoint_list
[
1
]
device_uuid_2
=
endpoint_id_2
.
device_id
.
device_uuid
.
uuid
device_uuid_2
=
endpoint_id_2
.
device_id
.
device_uuid
.
uuid
device_2
=
name_device_map
[
device_uuid_2
]
device_1
=
name_device_map
.
get
(
device_uuid_1
)
device_2
=
name_device_map
.
get
(
device_uuid_2
)
if
not
device_1
or
not
device_2
:
raise
Exception
(
"
One or both devices not found in name_device_map
"
)
# Check if the first endpoint is managed
if
device_1
.
controller_id
!=
DeviceId
():
if
device_1
.
controller_id
!=
DeviceId
():
for
link
in
links
:
for
link
in
links
:
link_endpoints
=
list
(
link
.
link_endpoint_ids
)
link_endpoints
=
list
(
link
.
link_endpoint_ids
)
link_ep_1
=
link_endpoints
[
0
]
link_ep_1
,
link_ep_2
=
link_endpoints
link_ep_2
=
link_endpoints
[
1
]
if
(
if
(
device_uuid_1
==
uuid_name_map
[
link_ep_1
.
device_id
.
device_uuid
.
uuid
]
device_uuid_1
==
uuid_name_map
.
get
(
link_ep_1
.
device_id
.
device_uuid
.
uuid
)
and
uuid_device_map
[
link_ep_2
.
device_id
.
device_uuid
.
uuid
].
device_type
and
uuid_device_map
[
link_ep_2
.
device_id
.
device_uuid
.
uuid
].
device_type
==
"
emu-datacenter
"
==
"
emu-datacenter
"
):
):
endpoint_list
[
0
]
=
link_ep_2
endpoint_list
[
0
]
=
link_ep_2
break
break
# Otherwise, check if the second endpoint is managed
elif
device_2
.
controller_id
!=
DeviceId
():
elif
device_2
.
controller_id
!=
DeviceId
():
for
link
in
links
:
for
link
in
links
:
link_endpoints
=
list
(
link
.
link_endpoint_ids
)
link_endpoints
=
list
(
link
.
link_endpoint_ids
)
link_ep_1
=
link_endpoints
[
0
]
link_ep_1
,
link_ep_2
=
link_endpoints
link_ep_2
=
link_endpoints
[
1
]
if
(
if
(
device_uuid_2
==
uuid_name_map
[
link_ep_1
.
device_id
.
device_uuid
.
uuid
]
device_uuid_2
==
uuid_name_map
.
get
(
link_ep_1
.
device_id
.
device_uuid
.
uuid
)
and
uuid_device_map
[
link_ep_2
.
device_id
.
device_uuid
.
uuid
].
device_type
and
uuid_device_map
[
link_ep_2
.
device_id
.
device_uuid
.
uuid
].
device_type
==
"
emu-datacenter
"
==
"
emu-datacenter
"
):
):
...
@@ -123,31 +210,34 @@ def replace_ont_endpoint_with_emu_dc(
...
@@ -123,31 +210,34 @@ def replace_ont_endpoint_with_emu_dc(
break
break
else
:
else
:
raise
Exception
(
raise
Exception
(
"
o
ne
of the sdps
should be managed by a controller and the other
one
should not be
controlled
"
"
O
ne
endpoint
should be managed by a controller and the other should not be
"
)
)
return
endpoint_list
def
validate_ietf_slice_data
(
request_data
:
Dict
)
->
None
:
return
endpoint_list
yang_validator
=
YangValidator
(
"
ietf-network-slice-service
"
)
_
=
yang_validator
.
parse_to_dict
(
request_data
)
yang_validator
.
destroy
()
class
IETFSliceHandler
:
class
IETFSliceHandler
:
@staticmethod
@staticmethod
def
get_all_ietf_slices
(
context_client
:
ContextClient
)
->
Dict
:
def
get_all_ietf_slices
(
context_client
:
ContextClient
)
->
Dict
:
"""
Retrieve all IETF slices from the (single) context. Expects exactly one context in the system.
"""
existing_context_ids
=
context_client
.
ListContextIds
(
Empty
())
existing_context_ids
=
context_client
.
ListContextIds
(
Empty
())
context_ids
=
list
(
existing_context_ids
.
context_ids
)
context_ids
=
list
(
existing_context_ids
.
context_ids
)
if
len
(
context_ids
)
!=
1
:
if
len
(
context_ids
)
!=
1
:
raise
Exception
(
"
Number of contexts should be 1
"
)
raise
Exception
(
"
Number of contexts should be exactly 1
"
)
slices_list
=
context_client
.
ListSlices
(
context_ids
[
0
])
slices_list
=
context_client
.
ListSlices
(
context_ids
[
0
])
slices
=
slices_list
.
slices
slices
=
slices_list
.
slices
ietf_slices
=
{
"
network-slice-services
"
:
{
"
slice-service
"
:
[]}}
ietf_slices
=
{
"
network-slice-services
"
:
{
"
slice-service
"
:
[]}}
for
sl
ice
in
slices
:
for
sl
c
in
slices
:
candidate_cr
=
get_custom_config_rule
(
candidate_cr
=
get_custom_config_rule
(
sl
ice
.
slice_config
,
CANDIDATE_RESOURCE_KEY
sl
c
.
slice_config
,
CANDIDATE_RESOURCE_KEY
)
)
if
not
candidate_cr
:
# Skip slices that don't have the candidate_ietf_slice data
continue
candidate_ietf_data
=
json
.
loads
(
candidate_cr
.
custom
.
resource_value
)
candidate_ietf_data
=
json
.
loads
(
candidate_cr
.
custom
.
resource_value
)
ietf_slices
[
"
network-slice-services
"
][
"
slice-service
"
].
append
(
ietf_slices
[
"
network-slice-services
"
][
"
slice-service
"
].
append
(
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
...
@@ -158,27 +248,37 @@ class IETFSliceHandler:
...
@@ -158,27 +248,37 @@ class IETFSliceHandler:
def
create_slice_service
(
def
create_slice_service
(
request_data
:
dict
,
context_client
:
ContextClient
request_data
:
dict
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
"""
Create a new slice service from the provided IETF data, applying validations and constructing a Slice object.
"""
# Ensure the top-level key is "network-slice-services"
if
"
network-slice-services
"
not
in
request_data
:
if
"
network-slice-services
"
not
in
request_data
:
request_data
=
{
"
network-slice-services
"
:
request_data
}
request_data
=
{
"
network-slice-services
"
:
request_data
}
validate_ietf_slice_data
(
request_data
)
validate_ietf_slice_data
(
request_data
)
slice_service
s
=
request_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
request_data
[
"
network-slice-services
"
][
"
slice-service
"
]
[
0
]
slice_service
=
slice_services
[
0
]
slice_id
=
slice_service
[
"
id
"
]
slice_id
=
slice_service
[
"
id
"
]
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
if
len
(
sdps
)
!=
2
:
if
len
(
sdps
)
!=
2
:
raise
Exception
(
"
Number of SDPs should be 2
"
)
raise
Exception
(
"
Number of SDPs should be exactly 2
"
)
slice_request
:
Slice
=
Slice
()
connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_request
=
Slice
()
slice_request
.
slice_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
slice_request
.
slice_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
slice_request
.
slice_id
.
slice_uuid
.
uuid
=
slice_id
slice_request
.
slice_id
.
slice_uuid
.
uuid
=
slice_id
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
list_endpoints
=
[]
list_endpoints
=
[]
endpoint_config_rules
=
[]
endpoint_config_rules
=
[]
connection_group_ids
=
set
()
connection_group_ids
=
set
()
# Build endpoints from SDPs
for
sdp
in
sdps
:
for
sdp
in
sdps
:
attachment_circuits
=
sdp
[
"
attachment-circuits
"
][
"
attachment-circuit
"
]
attachment_circuits
=
sdp
[
"
attachment-circuits
"
][
"
attachment-circuit
"
]
if
len
(
attachment_circuits
)
!=
1
:
if
len
(
attachment_circuits
)
!=
1
:
raise
Exception
(
"
All SDPs should have 1 attachment-circuit
"
)
raise
Exception
(
"
Each SDP must have exactly 1 attachment-circuit
"
)
endpoint
=
EndPointId
()
endpoint
=
EndPointId
()
endpoint
.
topology_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
endpoint
.
topology_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
device_uuid
=
sdp
[
"
node-id
"
]
device_uuid
=
sdp
[
"
node-id
"
]
...
@@ -186,11 +286,15 @@ class IETFSliceHandler:
...
@@ -186,11 +286,15 @@ class IETFSliceHandler:
endpoint_uuid
=
attachment_circuits
[
0
][
"
ac-tp-id
"
]
endpoint_uuid
=
attachment_circuits
[
0
][
"
ac-tp-id
"
]
endpoint
.
endpoint_uuid
.
uuid
=
endpoint_uuid
endpoint
.
endpoint_uuid
.
uuid
=
endpoint_uuid
list_endpoints
.
append
(
endpoint
)
list_endpoints
.
append
(
endpoint
)
# Keep track of connection-group-id from each SDP
connection_group_ids
.
add
(
connection_group_ids
.
add
(
sdp
[
"
service-match-criteria
"
][
"
match-criterion
"
][
0
][
sdp
[
"
service-match-criteria
"
][
"
match-criterion
"
][
0
][
"
target-connection-group-id
"
"
target-connection-group-id
"
]
]
)
)
# Endpoint-specific config rule fields
endpoint_config_rule_fields
=
{
endpoint_config_rule_fields
=
{
"
address_ip
"
:
(
endpoint_uuid
,
RAISE_IF_DIFFERS
),
"
address_ip
"
:
(
endpoint_uuid
,
RAISE_IF_DIFFERS
),
"
address_prefix
"
:
(
ADDRESS_PREFIX
,
RAISE_IF_DIFFERS
),
"
address_prefix
"
:
(
ADDRESS_PREFIX
,
RAISE_IF_DIFFERS
),
...
@@ -201,41 +305,36 @@ class IETFSliceHandler:
...
@@ -201,41 +305,36 @@ class IETFSliceHandler:
endpoint_config_rule_fields
,
endpoint_config_rule_fields
,
)
)
)
)
if
len
(
connection_group_ids
)
!=
1
:
if
len
(
connection_group_ids
)
!=
1
:
raise
Exception
(
"
SDPs target-connection-group-id do not match
"
)
raise
Exception
(
"
SDPs do not share a common connection-group-id
"
)
list_constraints
=
[]
for
cg
in
connection_groups
:
# Build constraints from the matching connection group
if
cg
[
"
id
"
]
!=
list
(
connection_group_ids
)[
0
]:
unique_cg_id
=
connection_group_ids
.
pop
()
continue
found_cg
=
next
(
metric_bounds
=
cg
[
"
connectivity-construct
"
][
0
][
"
service-slo-sle-policy
"
][
(
cg
for
cg
in
connection_groups
if
cg
[
"
id
"
]
==
unique_cg_id
),
None
"
slo-policy
"
)
][
"
metric-bound
"
]
if
not
found_cg
:
for
metric
in
metric_bounds
:
raise
Exception
(
"
The connection group referenced by the SDPs was not found
"
)
if
metric
[
"
metric-type
"
]
==
"
ietf-nss:one-way-delay-maximum
"
:
constraint
=
Constraint
()
list_constraints
=
build_constraints_from_connection_group
(
found_cg
)
constraint
.
sla_latency
.
e2e_latency_ms
=
float
(
metric
[
"
bound
"
])
list_constraints
.
append
(
constraint
)
# Sort endpoints and optionally replace the ONT endpoint
elif
metric
[
"
metric-type
"
]
==
"
ietf-nss:one-way-bandwidth
"
:
list_endpoints
=
sort_endpoints
(
list_endpoints
,
sdps
,
found_cg
,
context_client
)
constraint
=
Constraint
()
constraint
.
sla_capacity
.
capacity_gbps
=
(
float
(
metric
[
"
bound
"
])
/
1.0e3
)
list_constraints
.
append
(
constraint
)
break
else
:
raise
Exception
(
"
connection group not found
"
)
list_endpoints
=
sort_endpoints
(
list_endpoints
,
sdps
,
cg
,
context_client
)
list_endpoints
=
replace_ont_endpoint_with_emu_dc
(
list_endpoints
=
replace_ont_endpoint_with_emu_dc
(
list_endpoints
,
context_client
list_endpoints
,
context_client
)
)
slice_request
.
slice_endpoint_ids
.
extend
(
list_endpoints
)
slice_request
.
slice_endpoint_ids
.
extend
(
list_endpoints
)
slice_request
.
slice_constraints
.
extend
(
list_constraints
)
slice_request
.
slice_constraints
.
extend
(
list_constraints
)
# TODO adding owner, needs to be recoded after updating the bindings
owner
=
slice_id
# Set slice owner
slice_request
.
slice_owner
.
owner_string
=
owner
slice_request
.
slice_owner
.
owner_string
=
slice_id
slice_request
.
slice_owner
.
owner_uuid
.
uuid
=
str
(
slice_request
.
slice_owner
.
owner_uuid
.
uuid
=
str
(
uuid
.
uuid5
(
uuid
.
NAMESPACE_DNS
,
owner
)
uuid
.
uuid5
(
uuid
.
NAMESPACE_DNS
,
slice_id
)
)
)
# Update slice config with IETF data (both running and candidate)
ietf_slice_fields
=
{
ietf_slice_fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
request_data
.
items
()
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
request_data
.
items
()
}
}
...
@@ -250,6 +349,7 @@ class IETFSliceHandler:
...
@@ -250,6 +349,7 @@ class IETFSliceHandler:
ietf_slice_fields
,
ietf_slice_fields
,
)
)
# Update endpoint config rules
for
ep_cr_key
,
ep_cr_fields
in
endpoint_config_rules
:
for
ep_cr_key
,
ep_cr_fields
in
endpoint_config_rules
:
update_config_rule_custom
(
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
ep_cr_key
,
ep_cr_fields
slice_request
.
slice_config
.
config_rules
,
ep_cr_key
,
ep_cr_fields
...
@@ -261,120 +361,113 @@ class IETFSliceHandler:
...
@@ -261,120 +361,113 @@ class IETFSliceHandler:
def
create_sdp
(
def
create_sdp
(
request_data
:
dict
,
slice_uuid
:
str
,
context_client
:
ContextClient
request_data
:
dict
,
slice_uuid
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
"""
Add a new SDP to an existing slice, updating the candidate IETF data.
"""
sdps
=
request_data
[
"
sdp
"
]
sdps
=
request_data
[
"
sdp
"
]
if
len
(
sdps
)
!=
1
:
if
len
(
sdps
)
!=
1
:
raise
Exception
(
"
Number of SDPs should be 1
"
)
raise
Exception
(
"
Number of SDPs to create must be exactly 1
"
)
new_sdp
=
sdps
[
0
]
new_sdp
=
sdps
[
0
]
# slice_request = get_slice_by_uuid(context_client, slice_uuid)
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_uuid
,
rw_copy
=
False
context_client
,
slice_uuid
,
rw_copy
=
False
)
)
for
cr
in
slice_request
.
slice_config
.
config_rules
:
ietf_data
=
get_ietf_data_from_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
)
if
cr
.
WhichOneof
(
"
config_rule
"
)
!=
"
custom
"
:
continue
slice_service
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
if
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
:
ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
break
else
:
raise
Exception
(
"
ietf data not found
"
)
slice_services
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
slice_sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
slice_sdps
.
append
(
new_sdp
)
slice_sdps
.
append
(
new_sdp
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
update_config_rule_custom
(
# Save updated IETF data
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
update_ietf_data_in_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
,
ietf_data
)
)
return
slice_request
return
slice_request
@staticmethod
@staticmethod
def
delete_sdp
(
def
delete_sdp
(
slice_uuid
:
str
,
sdp_id
:
str
,
context_client
:
ContextClient
slice_uuid
:
str
,
sdp_id
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
# slice_request = get_slice_by_uuid(context_client, slice_uuid)
"""
Delete the specified SDP from an existing slice
'
s candidate IETF data.
"""
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_uuid
,
rw_copy
=
False
context_client
,
slice_uuid
,
rw_copy
=
False
)
)
for
cr
in
slice_request
.
slice_config
.
config_rules
:
ietf_data
=
get_ietf_data_from_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
)
if
cr
.
WhichOneof
(
"
config_rule
"
)
!=
"
custom
"
:
continue
slice_service
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
if
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
:
ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
break
else
:
raise
Exception
(
"
ietf data not found
"
)
slice_services
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
slice_sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
sdp_idx
=
list
((
slice_sdp
[
"
id
"
]
==
sdp_id
for
slice_sdp
in
slice_sdps
)).
index
(
True
# Find and remove the matching SDP
sdp_idx
=
next
(
(
i
for
i
,
sdp
in
enumerate
(
slice_sdps
)
if
sdp
[
"
id
"
]
==
sdp_id
),
None
)
)
if
sdp_idx
is
None
:
raise
Exception
(
f
"
SDP with id
'
{
sdp_id
}
'
not found in slice
'
{
slice_uuid
}
'"
)
slice_sdps
.
pop
(
sdp_idx
)
slice_sdps
.
pop
(
sdp_idx
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
update_config_rule_custom
(
update_ietf_data_in_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
,
ietf_data
)
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
)
return
slice_request
return
slice_request
@staticmethod
@staticmethod
def
create_connection_group
(
def
create_connection_group
(
request_data
:
dict
,
slice_id
:
str
,
context_client
:
ContextClient
request_data
:
dict
,
slice_id
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
"""
Add a new connection group to an existing slice
'
s candidate IETF data.
"""
connection_groups
=
request_data
[
"
connection-group
"
]
connection_groups
=
request_data
[
"
connection-group
"
]
if
len
(
connection_groups
)
!=
1
:
if
len
(
connection_groups
)
!=
1
:
raise
Exception
(
"
Number of connection groups should be 1
"
)
raise
Exception
(
"
Number of connection groups to create must be exactly 1
"
)
new_connection_group
=
connection_groups
[
0
]
new_connection_group
=
connection_groups
[
0
]
# slice = get_slice_by_uuid(context_client, slice_id)
slice_request
=
get_slice_by_defualt_name
(
slice
=
get_slice_by_defualt_name
(
context_client
,
slice_id
,
rw_copy
=
False
)
context_client
,
slice_id
,
rw_copy
=
False
for
cr
in
slice
.
slice_config
.
config_rules
:
)
if
cr
.
WhichOneof
(
"
config_rule
"
)
!=
"
custom
"
:
ietf_data
=
get_ietf_data_from_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
)
continue
if
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
:
slice_service
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
break
else
:
raise
Exception
(
"
ietf data not found
"
)
slice_services
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_connection_groups
.
append
(
new_connection_group
)
slice_connection_groups
.
append
(
new_connection_group
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
update_config_rule_custom
(
# Validate the updated data, then save
slice
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
)
validate_ietf_slice_data
(
ietf_data
)
validate_ietf_slice_data
(
ietf_data
)
return
slice
update_ietf_data_in_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
,
ietf_data
)
return
slice_request
@staticmethod
@staticmethod
def
update_connection_group
(
def
update_connection_group
(
slice_name
:
str
,
slice_name
:
str
,
updated_connection_group
:
dict
,
updated_connection_group
:
dict
,
context_client
:
ContextClient
,
context_client
:
ContextClient
,
):
)
->
Slice
:
"""
Update an existing connection group in the candidate IETF data.
"""
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_name
,
rw_copy
=
False
context_client
,
slice_name
,
rw_copy
=
False
)
)
slice_config
=
slice_request
.
slice_config
candidate_ietf_data
=
get_ietf_data_from_config
(
cr
=
get_custom_config_rule
(
slice_config
,
CANDIDATE_RESOURCE_KEY
)
slice_request
,
CANDIDATE_RESOURCE_KEY
candidate_ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
)
slice_services
=
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_service
=
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
connection_group_id
=
updated_connection_group
[
"
id
"
]
cg_idx
=
list
(
cg_id
=
updated_connection_group
[
"
id
"
]
(
cg_idx
=
next
(
slice_cg
[
"
id
"
]
==
connection_group_id
(
i
for
i
,
cg
in
enumerate
(
slice_connection_groups
)
if
cg
[
"
id
"
]
==
cg_id
),
for
slice_cg
in
slice_connection_groups
None
,
)
)
).
index
(
True
)
if
cg_idx
is
None
:
raise
Exception
(
f
"
Connection group with id
'
{
cg_id
}
'
not found
"
)
slice_connection_groups
[
cg_idx
]
=
updated_connection_group
slice_connection_groups
[
cg_idx
]
=
updated_connection_group
fields
=
{
update_ietf_data_in_config
(
name
:
(
value
,
RAISE_IF_DIFFERS
)
slice_request
,
CANDIDATE_RESOURCE_KEY
,
candidate_ietf_data
for
name
,
value
in
candidate_ietf_data
.
items
()
}
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
)
)
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
return
slice_request
return
slice_request
...
@@ -382,30 +475,39 @@ class IETFSliceHandler:
...
@@ -382,30 +475,39 @@ class IETFSliceHandler:
def
delete_connection_group
(
def
delete_connection_group
(
slice_uuid
:
str
,
connection_group_id
:
str
,
context_client
:
ContextClient
slice_uuid
:
str
,
connection_group_id
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
# slice_request = get_slice_by_uuid(context_client, slice_uuid)
"""
Remove an existing connection group from the candidate IETF data of a slice.
"""
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_uuid
,
rw_copy
=
False
context_client
,
slice_uuid
,
rw_copy
=
False
)
)
slice_config
=
slice_request
.
slice_config
candidate_ietf_data
=
get_ietf_data_from_config
(
cr
=
get_custom_config_rule
(
slice_config
,
CANDIDATE_RESOURCE_KEY
)
slice_request
,
CANDIDATE_RESOURCE_KEY
candidate_ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
)
slice_services
=
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_service
=
candidate_ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
sdp_idx
=
list
(
cg_idx
=
next
(
(
(
slice_cr
[
"
id
"
]
==
connection_group_id
i
for
slice_cr
in
slice_connection_groups
for
i
,
cg
in
enumerate
(
slice_connection_groups
)
if
cg
[
"
id
"
]
==
connection_group_id
),
None
,
)
if
cg_idx
is
None
:
raise
Exception
(
f
"
Connection group with id
'
{
connection_group_id
}
'
not found
"
)
)
).
index
(
True
)
removed_connection_group
=
slice_connection_groups
.
pop
(
sdp_idx
)
slice_connection_groups
.
pop
(
cg_idx
)
fields
=
{
update_ietf_data_in_config
(
name
:
(
value
,
RAISE_IF_DIFFERS
)
slice_request
,
CANDIDATE_RESOURCE_KEY
,
candidate_ietf_data
for
name
,
value
in
candidate_ietf_data
.
items
()
}
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
)
)
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
return
slice_request
return
slice_request
...
@@ -413,91 +515,55 @@ class IETFSliceHandler:
...
@@ -413,91 +515,55 @@ class IETFSliceHandler:
def
create_match_criteria
(
def
create_match_criteria
(
request_data
:
dict
,
slice_name
:
str
,
sdp_id
:
str
,
context_client
:
ContextClient
request_data
:
dict
,
slice_name
:
str
,
sdp_id
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
"""
Create a new match-criterion for the specified SDP in a slice
'
s candidate IETF data.
"""
match_criteria
=
request_data
[
"
match-criterion
"
]
match_criteria
=
request_data
[
"
match-criterion
"
]
if
len
(
match_criteria
)
!=
1
:
if
len
(
match_criteria
)
!=
1
:
raise
Exception
(
"
Number of SDPs should be 1
"
)
raise
Exception
(
"
Number of match-criterion entries to create must be exactly 1
"
)
new_match_criterion
=
match_criteria
[
0
]
new_match_criterion
=
match_criteria
[
0
]
target_connection_group_id
=
new_match_criterion
[
"
target-connection-group-id
"
]
target_connection_group_id
=
new_match_criterion
[
"
target-connection-group-id
"
]
# slice_request = get_slice_by_uuid(context_client, slice_id)
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_name
,
rw_copy
=
False
context_client
,
slice_name
,
rw_copy
=
False
)
)
for
cr
in
slice_request
.
slice_config
.
config_rules
:
ietf_data
=
get_ietf_data_from_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
)
if
cr
.
WhichOneof
(
"
config_rule
"
)
!=
"
custom
"
:
continue
slice_service
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
if
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
:
ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
break
else
:
raise
Exception
(
"
ietf data not found
"
)
slice_services
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
slice_id
=
slice_service
[
"
id
"
]
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
connection_groups
=
slice_service
[
"
connection-groups
"
][
"
connection-group
"
]
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
list_endpoints
=
[]
for
sdp
in
sdps
:
# Find the referenced connection group
if
(
found_cg
=
next
(
sdp
[
"
service-match-criteria
"
][
"
match-criterion
"
][
0
][
(
cg
for
cg
in
connection_groups
if
cg
[
"
id
"
]
==
target_connection_group_id
),
"
target-connection-group-id
"
None
,
]
)
==
target_connection_group_id
if
not
found_cg
:
):
raise
Exception
(
attachment_circuits
=
sdp
[
"
attachment-circuits
"
][
"
attachment-circuit
"
]
f
"
Connection group
'
{
target_connection_group_id
}
'
not found
"
if
len
(
attachment_circuits
)
!=
1
:
)
raise
Exception
(
"
All SDPs should have 1 attachment-circuit
"
)
endpoint
=
EndPointId
()
# Build constraints from that connection group
endpoint
.
topology_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
list_constraints
=
build_constraints_from_connection_group
(
found_cg
)
endpoint
.
device_id
.
device_uuid
.
uuid
=
sdp
[
"
node-id
"
]
endpoint
.
endpoint_uuid
.
uuid
=
attachment_circuits
[
0
][
"
ac-tp-id
"
]
# Add match-criterion to the relevant SDP
list_endpoints
.
append
(
endpoint
)
sdp_to_update
=
next
((
s
for
s
in
sdps
if
s
[
"
id
"
]
==
sdp_id
),
None
)
break
if
not
sdp_to_update
:
else
:
raise
Exception
(
f
"
SDP
'
{
sdp_id
}
'
not found
"
)
raise
Exception
(
"
Second SDP not found
"
)
for
sdp
in
sdps
:
sdp_to_update
[
"
service-match-criteria
"
][
"
match-criterion
"
].
append
(
if
sdp
[
"
id
"
]
==
sdp_id
:
new_match_criterion
sdp
[
"
service-match-criteria
"
][
"
match-criterion
"
].
append
(
)
new_match_criterion
)
# Update constraints at the slice level as needed
attachment_circuits
=
sdp
[
"
attachment-circuits
"
][
"
attachment-circuit
"
]
if
len
(
attachment_circuits
)
!=
1
:
raise
Exception
(
"
All SDPs should have 1 attachment-circuit
"
)
endpoint
=
EndPointId
()
endpoint
.
topology_id
.
context_id
.
context_uuid
.
uuid
=
DEFAULT_CONTEXT_NAME
endpoint
.
device_id
.
device_uuid
.
uuid
=
sdp
[
"
node-id
"
]
endpoint
.
endpoint_uuid
.
uuid
=
attachment_circuits
[
0
][
"
ac-tp-id
"
]
list_endpoints
.
append
(
endpoint
)
break
else
:
raise
Exception
(
"
SDP not found
"
)
list_constraints
=
[]
for
cg
in
connection_groups
:
if
cg
[
"
id
"
]
!=
target_connection_group_id
:
continue
metric_bounds
=
cg
[
"
connectivity-construct
"
][
0
][
"
service-slo-sle-policy
"
][
"
slo-policy
"
][
"
metric-bound
"
]
for
metric
in
metric_bounds
:
if
metric
[
"
metric-type
"
]
==
"
ietf-nss:one-way-delay-maximum
"
:
constraint
=
Constraint
()
constraint
.
sla_latency
.
e2e_latency_ms
=
float
(
metric
[
"
bound
"
])
list_constraints
.
append
(
constraint
)
elif
metric
[
"
metric-type
"
]
==
"
ietf-nss:one-way-bandwidth
"
:
constraint
=
Constraint
()
constraint
.
sla_capacity
.
capacity_gbps
=
(
float
(
metric
[
"
bound
"
])
/
1.0e3
)
list_constraints
.
append
(
constraint
)
break
else
:
raise
Exception
(
"
connection group not found
"
)
del
slice_request
.
slice_constraints
[:]
del
slice_request
.
slice_constraints
[:]
slice_request
.
slice_constraints
.
extend
(
list_constraints
)
slice_request
.
slice_constraints
.
extend
(
list_constraints
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
slice_request
.
slice_status
.
slice_status
=
SliceStatusEnum
.
SLICESTATUS_PLANNED
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
update_ietf_data_in_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
,
ietf_data
)
)
return
slice_request
return
slice_request
@staticmethod
@staticmethod
...
@@ -507,60 +573,54 @@ class IETFSliceHandler:
...
@@ -507,60 +573,54 @@ class IETFSliceHandler:
match_criterion_id
:
int
,
match_criterion_id
:
int
,
context_client
:
ContextClient
,
context_client
:
ContextClient
,
)
->
Slice
:
)
->
Slice
:
# slice_request = get_slice_by_uuid(context_client, slice_uuid)
"""
Delete the specified match-criterion from an SDP in the slice
'
s candidate IETF data.
"""
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_uuid
,
rw_copy
=
False
context_client
,
slice_uuid
,
rw_copy
=
False
)
)
for
cr
in
slice_request
.
slice_config
.
config_rules
:
ietf_data
=
get_ietf_data_from_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
)
if
cr
.
WhichOneof
(
"
config_rule
"
)
!=
"
custom
"
:
continue
slice_service
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
][
0
]
if
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
:
ietf_data
=
json
.
loads
(
cr
.
custom
.
resource_value
)
break
else
:
raise
Exception
(
"
ietf data not found
"
)
slice_services
=
ietf_data
[
"
network-slice-services
"
][
"
slice-service
"
]
slice_service
=
slice_services
[
0
]
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
sdps
=
slice_service
[
"
sdps
"
][
"
sdp
"
]
for
sdp
in
sdps
:
if
sdp
[
"
id
"
]
==
sdp_id
:
# Find and modify the specified SDP
match_criteria
=
sdp
[
"
service-match-criteria
"
][
"
match-criterion
"
]
sdp_to_update
=
next
((
s
for
s
in
sdps
if
s
[
"
id
"
]
=
=
sdp
_id
),
None
)
match_criterion_idx
=
[
if
not
sdp_to_update
:
match_criterion
[
"
index
"
]
==
match_criterion_id
raise
Exception
(
f
"
SDP
'
{
sdp_id
}
'
not found in slice
'
{
slice_uuid
}
'"
)
for
match_criterion
in
match_criteria
].
index
(
True
)
match_criteria
=
sdp_to_update
[
"
service-match-criteria
"
][
"
match-criterion
"
]
del
match_criteria
[
match_criterion_idx
]
mc_index
=
next
(
break
(
else
:
i
raise
Exception
(
"
Second SDP not found
"
)
for
i
,
m
in
enumerate
(
match_criteria
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
ietf_data
.
items
()}
if
m
[
"
index
"
]
==
match_criterion_id
update_config_rule_custom
(
),
slice_request
.
slice_config
.
config_rules
,
CANDIDATE_RESOURCE_KEY
,
fields
None
,
)
)
if
mc_index
is
None
:
raise
Exception
(
f
"
No match-criterion with index
'
{
match_criterion_id
}
'
found in SDP
'
{
sdp_id
}
'"
)
match_criteria
.
pop
(
mc_index
)
update_ietf_data_in_config
(
slice_request
,
CANDIDATE_RESOURCE_KEY
,
ietf_data
)
return
slice_request
return
slice_request
@staticmethod
@staticmethod
def
copy_candidate_ietf_slice_data_to_running
(
def
copy_candidate_ietf_slice_data_to_running
(
slice_uuid
:
str
,
context_client
:
ContextClient
slice_uuid
:
str
,
context_client
:
ContextClient
)
->
Slice
:
)
->
Slice
:
# slice_request = get_slice_by_uuid(context_client, slice_uuid)
"""
Copy candidate IETF slice data to the running IETF slice data for a given slice.
"""
slice_request
=
get_slice_by_defualt_name
(
slice_request
=
get_slice_by_defualt_name
(
context_client
,
slice_uuid
,
rw_copy
=
False
context_client
,
slice_uuid
,
rw_copy
=
False
)
)
for
cr
in
slice_request
.
slice_config
.
config_rules
:
candidate_ietf_data
=
get_ietf_data_from_config
(
if
(
slice_request
,
CANDIDATE_RESOURCE_KEY
cr
.
WhichOneof
(
"
config_rule
"
)
==
"
custom
"
)
and
cr
.
custom
.
resource_key
==
CANDIDATE_RESOURCE_KEY
update_ietf_data_in_config
(
):
slice_request
,
RUNNING_RESOURCE_KEY
,
candidate_ietf_data
candidate_resource_value_dict
=
json
.
loads
(
cr
.
custom
.
resource_value
)
fields
=
{
name
:
(
value
,
RAISE_IF_DIFFERS
)
for
name
,
value
in
candidate_resource_value_dict
.
items
()
}
break
else
:
raise
Exception
(
"
candidate ietf slice data not found
"
)
update_config_rule_custom
(
slice_request
.
slice_config
.
config_rules
,
RUNNING_RESOURCE_KEY
,
fields
)
)
return
slice_request
return
slice_request
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