Skip to content

Commit 062e627

Browse files
authored
Merge pull request #391 from fabric-testbed/390-sub-interface-support
390 sub interface support
2 parents 66be3e3 + 261bd80 commit 062e627

File tree

8 files changed

+146
-47
lines changed

8 files changed

+146
-47
lines changed

fabric_cf/actor/core/policy/broker_simpler_units_policy.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,8 +1031,6 @@ def extend_private(self, *, reservation: ABCBrokerReservation, inv: InventoryFor
10311031
sliver = current_resources.get_sliver()
10321032
diff = sliver.diff(other_sliver=requested_resources.get_sliver())
10331033

1034-
#if diff is not None and (diff.added is None or
1035-
# (len(diff.added.components) == 0 and len(diff.added.interfaces) == 0)):
10361034
if diff is not None:
10371035
sliver = requested_resources.get_sliver()
10381036

fabric_cf/actor/core/policy/network_node_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def assign(self, *, reservation: ABCAuthorityReservation, delegation_name: str,
234234
actor_id=self.authority.get_guid(), sliver=requested, rtype=resource_type,
235235
properties=reservation.get_slice().get_config_properties())
236236
modified = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit})
237-
elif len(diff.removed.components) > 0:
237+
elif len(diff.removed.components) > 0 or len(diff.modified.components):
238238
unit = Unit(rid=reservation.get_reservation_id(), slice_id=reservation.get_slice_id(),
239239
actor_id=self.authority.get_guid(), sliver=requested, rtype=resource_type,
240240
properties=reservation.get_slice().get_config_properties())

fabric_cf/actor/core/util/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ def node_sliver_to_str(*, sliver: NodeSliver):
6868
if ns.interface_info is not None and ns.interface_info.interfaces is not None:
6969
for i in ns.interface_info.interfaces.values():
7070
result += f"\nIFS: {i}"
71+
if i.interface_info and i.interface_info.interfaces:
72+
for ch_ifc in i.interface_info.interfaces.values():
73+
result += f"\nSub IFS: {ch_ifc}"
7174
return result
7275

7376

fabric_cf/actor/db/psql_database.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,11 +855,21 @@ def get_reservations(self, *, slice_id: str = None, graph_node_id: str = None, p
855855
if category is not None:
856856
rows = rows.filter(Reservations.rsv_category.in_(category))
857857

858+
# Ensure start and end are datetime objects
859+
if start and isinstance(start, str):
860+
start = datetime.fromisoformat(start)
861+
if end and isinstance(end, str):
862+
end = datetime.fromisoformat(end)
863+
858864
# Construct filter condition for lease_end within the given time range
859865
if start is not None or end is not None:
860866
lease_end_filter = True # Initialize with True to avoid NoneType comparison
861867
if start is not None and end is not None:
862-
lease_end_filter = and_(start <= Reservations.lease_end, Reservations.lease_end <= end)
868+
lease_end_filter = or_(
869+
and_(start <= Reservations.lease_end, Reservations.lease_end <= end),
870+
and_(start <= Reservations.lease_start, Reservations.lease_start <= end),
871+
and_(Reservations.lease_start <= start, Reservations.lease_end >= end)
872+
)
863873
elif start is not None:
864874
lease_end_filter = start <= Reservations.lease_end
865875
elif end is not None:
@@ -897,7 +907,11 @@ def get_components(self, *, node_id: str, states: list[int], rsv_type: list[str]
897907
# Construct filter condition for lease_end within the given time range
898908
if start is not None or end is not None:
899909
if start is not None and end is not None:
900-
lease_end_filter = and_(start <= Reservations.lease_end, Reservations.lease_end <= end)
910+
lease_end_filter = or_(
911+
and_(start <= Reservations.lease_end, Reservations.lease_end <= end),
912+
and_(start <= Reservations.lease_start, Reservations.lease_start <= end),
913+
and_(Reservations.lease_start <= start, Reservations.lease_end >= end)
914+
)
901915
elif start is not None:
902916
lease_end_filter = start <= Reservations.lease_end
903917
elif end is not None:

fabric_cf/actor/fim/fim_helper.py

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -436,15 +436,23 @@ def get_interface_sliver_mapping(ifs_node_id: str, slice_graph: ABCASMPropertyGr
436436
raise Exception(f"More than one Peer Interface Sliver found for IFS: {ifs_node_id}!")
437437
peer_ifs = next(iter(peer_interfaces))
438438

439-
peer_ns_node_name, peer_ns_id = slice_graph.get_parent(node_id=peer_ifs.node_id,
440-
rel=ABCPropertyGraph.REL_CONNECTS,
441-
parent=ABCPropertyGraph.CLASS_NetworkService)
439+
if peer_ifs.get_type() == InterfaceType.SubInterface:
440+
parent_cp_node_name, parent_cp_node_id = slice_graph.get_parent(node_id=peer_ifs.node_id,
441+
rel=ABCPropertyGraph.REL_CONNECTS,
442+
parent=ABCPropertyGraph.CLASS_ConnectionPoint)
443+
peer_ns_node_name, peer_ns_id = slice_graph.get_parent(node_id=parent_cp_node_id,
444+
rel=ABCPropertyGraph.REL_CONNECTS,
445+
parent=ABCPropertyGraph.CLASS_NetworkService)
446+
else:
447+
peer_ns_node_name, peer_ns_id = slice_graph.get_parent(node_id=peer_ifs.node_id,
448+
rel=ABCPropertyGraph.REL_CONNECTS,
449+
parent=ABCPropertyGraph.CLASS_NetworkService)
442450

443451
component_name = None
444452
facility = False
445453
peer_site = None
446454

447-
if peer_ifs.get_type() in [InterfaceType.DedicatedPort, InterfaceType.SharedPort]:
455+
if peer_ifs.get_type() in [InterfaceType.DedicatedPort, InterfaceType.SharedPort, InterfaceType.SubInterface]:
448456
component_name, component_id = slice_graph.get_parent(node_id=peer_ns_id, rel=ABCPropertyGraph.REL_HAS,
449457
parent=ABCPropertyGraph.CLASS_Component)
450458
# Possibly P4 switch; parent will be a switch
@@ -467,6 +475,7 @@ def get_interface_sliver_mapping(ifs_node_id: str, slice_graph: ABCASMPropertyGr
467475

468476
# Peer Network Service is FABRIC L3VPN connected to a FABRIC Site
469477
# Determine the site to which AL2S Peered Interface is connected to
478+
470479
for ifs in peer_ns.interface_info.interfaces.values():
471480
# Skip the peered interface
472481
if ifs.node_id == peer_ifs.node_id:
@@ -600,23 +609,85 @@ def get_owners(*, bqm: ABCCBMPropertyGraph, node_id: str,
600609
return switch, mpls_ns, requested_ns
601610

602611
@staticmethod
603-
def get_parent_node(*, graph_model: ABCPropertyGraph, component: Component = None, interface: Interface = None,
612+
def get_parent_node(*, graph_model: ABCPropertyGraph, node: Union[Component, Interface],
604613
sliver: bool = True) -> Tuple[Union[NodeSliver, NetworkServiceSliver, None], str]:
605-
node = None
606-
if component is not None:
607-
node_name, node_id = graph_model.get_parent(node_id=component.node_id, rel=ABCPropertyGraph.REL_HAS,
608-
parent=ABCPropertyGraph.CLASS_NetworkNode)
609-
if sliver:
610-
node = graph_model.build_deep_node_sliver(node_id=node_id)
611-
elif interface is not None:
612-
node_name, node_id = graph_model.get_parent(node_id=interface.node_id, rel=ABCPropertyGraph.REL_CONNECTS,
613-
parent=ABCPropertyGraph.CLASS_NetworkService)
614-
if sliver:
615-
node = graph_model.build_deep_ns_sliver(node_id=node_id)
616-
else:
614+
"""
615+
Retrieve the parent node of a given component or interface in the graph model.
616+
617+
This method determines the parent node of a specified component or interface within the provided
618+
property graph model. It can return either a node sliver or a network service sliver based on the
619+
type of the input node and the `sliver` flag.
620+
621+
:param graph_model: The property graph model used to find parent nodes.
622+
:type graph_model: ABCPropertyGraph
623+
624+
:param node: The component or interface for which to find the parent node.
625+
:type node: Union[Component, Interface]
626+
627+
:param sliver: Flag indicating whether to build and return a sliver object for the parent node.
628+
Defaults to True.
629+
:type sliver: bool
630+
631+
:return: A tuple containing the parent node sliver (or network service sliver) and the parent node ID.
632+
If no parent node is found, returns (None, None).
633+
:rtype: Tuple[Union[NodeSliver, NetworkServiceSliver, None], str]
634+
635+
:raises Exception: If the `node` argument is None or is neither a Component nor an Interface.
636+
637+
Example:
638+
>>> parent_node, parent_node_id = get_parent_node(graph_model=my_graph_model, node=my_component)
639+
>>> print(parent_node, parent_node_id)
640+
"""
641+
if node is None:
617642
raise Exception("Invalid Arguments - component/interface both are None")
618643

619-
return node, node_id
644+
parent_node = None
645+
parent_node_id = None
646+
647+
if isinstance(node, Component):
648+
node_name, parent_node_id = graph_model.get_parent(
649+
node_id=node.node_id,
650+
rel=ABCPropertyGraph.REL_HAS,
651+
parent=ABCPropertyGraph.CLASS_NetworkNode
652+
)
653+
if sliver:
654+
parent_node = graph_model.build_deep_node_sliver(node_id=parent_node_id)
655+
elif isinstance(node, Interface):
656+
if node.type == InterfaceType.SubInterface:
657+
# Get the OVS Network Service attached to Sub Interface
658+
sub_cp_nbs = graph_model.get_first_and_second_neighbor(
659+
node_id=node.node_id,
660+
rel1=ABCPropertyGraph.REL_CONNECTS,
661+
node1_label=ABCPropertyGraph.CLASS_ConnectionPoint,
662+
rel2=ABCPropertyGraph.REL_CONNECTS,
663+
node2_label=ABCPropertyGraph.CLASS_NetworkService
664+
)
665+
if len(sub_cp_nbs) == 0:
666+
raise Exception(f"Parent (NS-OVS) for Sub Interface: {node.name} cannot be found!")
667+
668+
# Get the component and node associated with Sub Interface
669+
sub_node = graph_model.get_first_and_second_neighbor(
670+
node_id=sub_cp_nbs[0][1],
671+
rel1=ABCPropertyGraph.REL_HAS,
672+
node1_label=ABCPropertyGraph.CLASS_Component,
673+
rel2=ABCPropertyGraph.REL_HAS,
674+
node2_label=ABCPropertyGraph.CLASS_NetworkNode
675+
)
676+
if len(sub_node) == 0:
677+
raise Exception(f"Parent for Sub Interface: {node.name} cannot be found!")
678+
parent_node_id = sub_node[0][1]
679+
if sliver:
680+
parent_node = graph_model.build_deep_node_sliver(node_id=parent_node_id)
681+
else:
682+
node_name, parent_node_id = graph_model.get_parent(
683+
node_id=node.node_id,
684+
rel=ABCPropertyGraph.REL_CONNECTS,
685+
parent=ABCPropertyGraph.CLASS_NetworkService
686+
)
687+
if sliver:
688+
parent_node = graph_model.build_deep_ns_sliver(node_id=parent_node_id)
689+
690+
return parent_node, parent_node_id
620691

621692
@staticmethod
622693
def prune_graph(*, graph_id: str) -> ExperimentTopology:

fabric_cf/broker/test/test.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,13 @@ actor:
135135
module: fabric_cf.actor.core.policy.broker_simpler_units_policy
136136
class: BrokerSimplerUnitsPolicy
137137
properties:
138-
algorithm: FirstFit
138+
algorithm:
139+
FirstFit: # Default policy for all sites
140+
enabled: true
141+
Random: # Random policy for specific sites
142+
enabled: true
143+
sites: # Specify the sites where Random policy should be used
144+
- EDUKY
139145
controls:
140146
- control:
141147
type: VM, Container, Baremetal, Switch

fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from fim.slivers.network_node import NodeSliver, NodeType
4343
from fim.slivers.network_service import NetworkServiceSliver
4444
from fim.slivers.topology_diff import WhatsModifiedFlag
45-
from fim.user import ServiceType, ExperimentTopology
45+
from fim.user import ServiceType, ExperimentTopology, InterfaceType
4646

4747
from fabric_cf.actor.core.common.constants import ErrorCodes, Constants
4848
from fabric_cf.actor.core.kernel.reservation_states import ReservationPendingStates, ReservationStates
@@ -519,7 +519,7 @@ def modify(self, *, new_slice_graph: ABCASMPropertyGraph) -> List[LeaseReservati
519519

520520
# Add components
521521
for x in topology_diff.added.components:
522-
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=new_slice_graph, component=x)
522+
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=new_slice_graph, node=x)
523523
rid = sliver.reservation_info.reservation_id
524524
# If corresponding sliver also has add operations; it's already in the map
525525
# No need to rebuild it
@@ -529,7 +529,7 @@ def modify(self, *, new_slice_graph: ABCASMPropertyGraph) -> List[LeaseReservati
529529
# Remove components
530530
for x in topology_diff.removed.components:
531531
# Grab the old sliver
532-
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=existing_topology.graph_model, component=x)
532+
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=existing_topology.graph_model, node=x)
533533
rid = sliver.reservation_info.reservation_id
534534
# If corresponding sliver also has add operations; it's already in the map
535535
# No need to rebuild it
@@ -539,37 +539,44 @@ def modify(self, *, new_slice_graph: ABCASMPropertyGraph) -> List[LeaseReservati
539539

540540
# Added Interfaces
541541
for x in topology_diff.added.interfaces:
542-
new_sliver, parent_node_id = FimHelper.get_parent_node(graph_model=new_slice_graph, interface=x)
542+
new_sliver, parent_node_id = FimHelper.get_parent_node(graph_model=new_slice_graph, node=x)
543543
rid = new_sliver.reservation_info.reservation_id
544544
# If corresponding sliver also has add operations; it's already in the map
545545
# No need to rebuild it
546546
if rid not in self.computed_modify_reservations:
547-
new_reservation, dep_update_needed = self.__build_ns_sliver_reservation(slice_graph=new_slice_graph,
548-
node_id=parent_node_id,
549-
node_res_mapping=node_res_mapping)
550-
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_reservation.get_sliver(),
551-
dependencies=new_reservation.redeem_processors)
547+
if x.type == InterfaceType.SubInterface:
548+
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_sliver)
549+
else:
550+
new_reservation, dep_update_needed = self.__build_ns_sliver_reservation(slice_graph=new_slice_graph,
551+
node_id=parent_node_id,
552+
node_res_mapping=node_res_mapping)
553+
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_reservation.get_sliver(),
554+
dependencies=new_reservation.redeem_processors)
552555

553-
if dep_update_needed:
554-
ns_peered_reservations.append(new_reservation)
555-
ns_mapping[new_reservation.sliver.node_id] = rid
556+
if dep_update_needed:
557+
ns_peered_reservations.append(new_reservation)
558+
ns_mapping[new_reservation.sliver.node_id] = rid
556559

557560
# Removed Interfaces
558561
for x in topology_diff.removed.interfaces:
559-
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=existing_topology.graph_model, interface=x)
562+
sliver, parent_node_id = FimHelper.get_parent_node(graph_model=existing_topology.graph_model, node=x)
560563
rid = sliver.reservation_info.reservation_id
561564
# If corresponding sliver also has add operations; it's already in the map
562565
# No need to rebuild it
563566
if rid not in self.computed_modify_reservations:
564-
new_reservation, dep_update_needed = self.__build_ns_sliver_reservation(slice_graph=new_slice_graph,
565-
node_id=parent_node_id,
566-
node_res_mapping=node_res_mapping)
567-
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_reservation.get_sliver(),
568-
dependencies=new_reservation.redeem_processors)
569-
570-
if dep_update_needed:
571-
ns_peered_reservations.append(new_reservation)
572-
ns_mapping[new_reservation.sliver.node_id] = rid
567+
if x.type == InterfaceType.SubInterface:
568+
new_sliver = new_slice_graph.build_deep_node_sliver(node_id=parent_node_id)
569+
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_sliver)
570+
else:
571+
new_reservation, dep_update_needed = self.__build_ns_sliver_reservation(slice_graph=new_slice_graph,
572+
node_id=parent_node_id,
573+
node_res_mapping=node_res_mapping)
574+
self.computed_modify_reservations[rid] = ModifiedReservation(sliver=new_reservation.get_sliver(),
575+
dependencies=new_reservation.redeem_processors)
576+
577+
if dep_update_needed:
578+
ns_peered_reservations.append(new_reservation)
579+
ns_mapping[new_reservation.sliver.node_id] = rid
573580

574581
# Remove nodes
575582
for x in topology_diff.removed.nodes:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ dependencies = [
2828
"PyYAML",
2929
"fabric_fss_utils==1.5.0",
3030
"fabric-message-bus==1.7.0b1",
31-
"fabric-fim==1.7.0b6",
31+
"fabric-fim==1.7.0b13",
3232
"fabric-credmgr-client==1.6.0",
3333
"ansible"
3434
]

0 commit comments

Comments
 (0)