diff --git a/fabric_cf/__init__.py b/fabric_cf/__init__.py index 709fa443..5f2ae615 100644 --- a/fabric_cf/__init__.py +++ b/fabric_cf/__init__.py @@ -1,2 +1,2 @@ -__version__ = "1.6.2" +__version__ = "1.7.0b1" __VERSION__ = __version__ diff --git a/fabric_cf/actor/core/apis/abc_database.py b/fabric_cf/actor/core/apis/abc_database.py index b0451540..0d64f244 100644 --- a/fabric_cf/actor/core/apis/abc_database.py +++ b/fabric_cf/actor/core/apis/abc_database.py @@ -174,11 +174,18 @@ def get_reservations(self, *, slice_id: ID = None, graph_node_id: str = None, pr def get_components(self, *, node_id: str, states: list[int], rsv_type: list[str], component: str = None, bdf: str = None, start: datetime = None, end: datetime = None) -> Dict[str, List[str]]: """ - Retrieves the components. - - @return list of components - - @throws Exception in case of error + Returns components matching the search criteria + @param node_id: Worker Node ID to which components belong + @param states: list of states used to find reservations + @param rsv_type: type of reservations + @param component: component name + @param bdf: Component's PCI address + @param start: start time + @param end: end time + + NOTE# For P4 switches; node_id=node+renc-p4-sw component=ip+192.168.11.8 bdf=p1 + + @return Dictionary with component name as the key and value as list of associated PCI addresses in use. """ @abstractmethod diff --git a/fabric_cf/actor/core/kernel/reservation_client.py b/fabric_cf/actor/core/kernel/reservation_client.py index 74f44be8..199ef6e2 100644 --- a/fabric_cf/actor/core/kernel/reservation_client.py +++ b/fabric_cf/actor/core/kernel/reservation_client.py @@ -515,24 +515,29 @@ def prepare_ticket(self, extend: bool = False): if parent_res is not None and (parent_res.is_ticketed() or parent_res.is_active()): node_sliver = parent_res.get_resources().get_sliver() - component = node_sliver.attached_components_info.get_device(name=value1) - graph_id, bqm_component_id = component.get_node_map() - graph_id, node_id = node_sliver.get_node_map() - ifs.set_node_map(node_map=(node_id, bqm_component_id)) - - # For shared NICs grab the MAC & VLAN from corresponding Interface Sliver - # maintained in the Parent Reservation Sliver - if component.get_type() == ComponentType.SharedNIC: - parent_res_ifs_sliver = FimHelper.get_site_interface_sliver(component=component, - local_name=ifs.get_labels().local_name) - parent_labs = parent_res_ifs_sliver.get_label_allocations() - - if component.get_model() == Constants.OPENSTACK_VNIC_MODEL: - ifs.labels = Labels.update(ifs.labels, mac=parent_labs.mac, bdf=parent_labs.bdf, - instance_parent=f"{parent_res.get_reservation_id()}-{node_sliver.get_name()}") - else: - ifs.labels = Labels.update(ifs.labels, mac=parent_labs.mac, vlan=parent_labs.vlan, - bdf=parent_labs.bdf) + # P4 Switch + if node_sliver.get_type() == NodeType.Switch: + graph_id, node_id = node_sliver.get_node_map() + ifs.set_node_map(node_map=(str(NodeType.Switch), node_id)) + else: + component = node_sliver.attached_components_info.get_device(name=value1) + graph_id, bqm_component_id = component.get_node_map() + graph_id, node_id = node_sliver.get_node_map() + ifs.set_node_map(node_map=(node_id, bqm_component_id)) + + # For shared NICs grab the MAC & VLAN from corresponding Interface Sliver + # maintained in the Parent Reservation Sliver + if component.get_type() == ComponentType.SharedNIC: + parent_res_ifs_sliver = FimHelper.get_site_interface_sliver(component=component, + local_name=ifs.get_labels().local_name) + parent_labs = parent_res_ifs_sliver.get_label_allocations() + + if component.get_model() == Constants.OPENSTACK_VNIC_MODEL: + ifs.labels = Labels.update(ifs.labels, mac=parent_labs.mac, bdf=parent_labs.bdf, + instance_parent=f"{parent_res.get_reservation_id()}-{node_sliver.get_name()}") + else: + ifs.labels = Labels.update(ifs.labels, mac=parent_labs.mac, vlan=parent_labs.vlan, + bdf=parent_labs.bdf) self.logger.trace(f"Updated Network Res# {self.get_reservation_id()} {sliver}") diff --git a/fabric_cf/actor/core/manage/actor_management_object.py b/fabric_cf/actor/core/manage/actor_management_object.py index 597ce371..c8fb8dc0 100644 --- a/fabric_cf/actor/core/manage/actor_management_object.py +++ b/fabric_cf/actor/core/manage/actor_management_object.py @@ -459,10 +459,11 @@ def get_reservations(self, *, caller: AuthToken, states: List[int] = None, if res_list is not None: result.reservations = [] for r in res_list: - slice_id = r.get_slice_id() - slice_obj = self.get_slice_by_guid(guid=slice_id) + r_slice_id = r.get_slice_id() + slice_obj = self.get_slice_by_guid(guid=r_slice_id) r.restore(actor=self.actor, slice_obj=slice_obj) - rr = Converter.fill_reservation(reservation=r, full=True) + full = True if slice_id or rid else False + rr = Converter.fill_reservation(reservation=r, full=full) result.reservations.append(rr) except ReservationNotFoundException as e: self.logger.error("getReservations: {}".format(e)) diff --git a/fabric_cf/actor/core/policy/broker_simpler_units_policy.py b/fabric_cf/actor/core/policy/broker_simpler_units_policy.py index 40c6eafa..8b8276a1 100644 --- a/fabric_cf/actor/core/policy/broker_simpler_units_policy.py +++ b/fabric_cf/actor/core/policy/broker_simpler_units_policy.py @@ -494,6 +494,8 @@ def __candidate_nodes(self, *, sliver: NodeSliver) -> List[str]: node_props = {ABCPropertyGraphConstants.PROP_SITE: sliver.site, ABCPropertyGraphConstants.PROP_TYPE: str(NodeType.Server)} + if sliver.get_type() == NodeType.Switch: + node_props[ABCPropertyGraphConstants.PROP_TYPE] = str(NodeType.Switch) storage_components = [] # remove storage components before the check @@ -508,6 +510,16 @@ def __candidate_nodes(self, *, sliver: NodeSliver) -> List[str]: label=ABCPropertyGraphConstants.CLASS_NetworkNode, props=node_props, comps=sliver.attached_components_info) + + # Skip nodes without any delegations which would be data-switch in this case + if sliver.get_type() == NodeType.Switch: + exclude = [] + for n in result: + if "p4" not in n: + exclude.append(n) + for e in exclude: + result.remove(e) + # re-add storage components if len(storage_components) > 0: for c in storage_components: @@ -652,7 +664,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: error_msg = None owner_ns = None owner_ns_id = None - bqm_component = None + bqm_node = None is_vnic = False owner_mpls_ns = None owner_switch = None @@ -664,29 +676,31 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: node_map_id = self.combined_broker_model_graph_id # Fetch Network Node Id and BQM Component Id - node_id, bqm_component_id = ifs.get_node_map() + node_id, bqm_node_id = ifs.get_node_map() # Skipping the already allocated interface on a modify - #if node_id == self.combined_broker_model_graph_id: if self.combined_broker_model_graph_id in node_id: continue if node_id == str(NodeType.Facility): - bqm_component = self.get_facility_sliver(node_name=bqm_component_id) + bqm_node = self.get_facility_sliver(node_name=bqm_node_id) # Peered Interfaces are handled at the end elif node_id == str(Constants.PEERED): peered_ns_interfaces.append(ifs) continue + elif node_id == str(NodeType.Switch): + bqm_node = self.get_network_node_from_graph(node_id=bqm_node_id) + node_map_id = f"{node_map_id}:{bqm_node.get_name()}:{bqm_node_id}:{ifs.get_labels().local_name}" else: # For VM interfaces - bqm_component = self.get_component_sliver(node_id=bqm_component_id) - node_map_id = f"{node_map_id}:{node_id}:{bqm_component_id}:{ifs.get_labels().bdf}" + bqm_node = self.get_component_sliver(node_id=bqm_node_id) + node_map_id = f"{node_map_id}:{node_id}:{bqm_node_id}:{ifs.get_labels().bdf}" - if bqm_component is None: + if bqm_node is None: raise BrokerException(error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES) # Get BQM Connection Point in Site Delegation (c) - site_cp = FimHelper.get_site_interface_sliver(component=bqm_component, + site_cp = FimHelper.get_site_interface_sliver(component=bqm_node, local_name=ifs.get_labels().local_name, region=ifs.get_labels().region, device_name=ifs.get_labels().device_name) @@ -712,13 +726,13 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: owner_ns_id = owner_ns_id.replace('ipv6ext-ns', 'ipv6-ns') bqm_cp = net_cp - if bqm_component.get_type() == NodeType.Facility or \ + if bqm_node.get_type() == NodeType.Facility or \ (sliver.get_type() == ServiceType.L2Bridge and - bqm_component.get_model() == Constants.OPENSTACK_VNIC_MODEL): + bqm_node.get_model() == Constants.OPENSTACK_VNIC_MODEL): bqm_cp = site_cp - if bqm_component.get_type() == ComponentType.SharedNIC: - if bqm_component.get_model() == Constants.OPENSTACK_VNIC_MODEL: + if bqm_node.get_type() == ComponentType.SharedNIC: + if bqm_node.get_model() == Constants.OPENSTACK_VNIC_MODEL: is_vnic = True # VLAN is already set by the Orchestrator using the information from the Node Sliver Parent Reservation @@ -754,7 +768,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: # Set the NSO device-name ifs_labels = Labels.update(ifs_labels, device_name=device_name) adm_ids = owner_switch.get_structural_info().adm_graph_ids - site_adm_ids = bqm_component.get_structural_info().adm_graph_ids + site_adm_ids = bqm_node.get_structural_info().adm_graph_ids self.logger.debug(f"Owner Network Service: {owner_ns}") self.logger.debug(f"Owner Switch: {owner_switch}") @@ -762,7 +776,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: self.logger.debug(f"Owner Switch NS: {owner_switch.network_service_info.network_services.values()}") net_adm_ids = site_adm_ids - if bqm_component.get_type() != NodeType.Facility and not is_vnic: + if bqm_node.get_type() != NodeType.Facility and not is_vnic: net_adm_ids = [x for x in adm_ids if not x in site_adm_ids or site_adm_ids.remove(x)] # For sites like EDC which share switch with other sites like NCSA, # the net_adm_ids also includes delegation id from the other side, @@ -807,7 +821,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: # Allocate VLAN for the Network Service if is_vnic: - site_adm_ids = bqm_component.get_structural_info().adm_graph_ids + site_adm_ids = bqm_node.get_structural_info().adm_graph_ids delegation_id = site_adm_ids[0] inv.allocate_vnic(rid=rid, requested_ns=sliver, owner_ns=owner_ns, existing_reservations=existing_reservations) @@ -903,8 +917,6 @@ def ticket_inventory(self, *, reservation: ABCBrokerReservation, inv: InventoryF # intended link (and possibly interfaces connected to it) res_sliver = rset.get_sliver() - delegation_id = None - sliver = None if isinstance(res_sliver, NodeSliver): delegation_id, sliver, error_msg = self.__allocate_nodes(reservation=reservation, inv=inv, diff --git a/fabric_cf/actor/core/policy/network_node_control.py b/fabric_cf/actor/core/policy/network_node_control.py index 478bd531..ee2473aa 100644 --- a/fabric_cf/actor/core/policy/network_node_control.py +++ b/fabric_cf/actor/core/policy/network_node_control.py @@ -219,7 +219,6 @@ def assign(self, *, reservation: ABCAuthorityReservation, delegation_name: str, properties=reservation.get_slice().get_config_properties()) gained = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit}) else: - # FIX ME: handle modify self.logger.info(f"Extend Lease for now, no modify supported res# {reservation}") current_sliver = current.get_sliver() diff = current_sliver.diff(other_sliver=requested) diff --git a/fabric_cf/actor/core/policy/network_node_inventory.py b/fabric_cf/actor/core/policy/network_node_inventory.py index 5c4eb8f3..92304e8d 100644 --- a/fabric_cf/actor/core/policy/network_node_inventory.py +++ b/fabric_cf/actor/core/policy/network_node_inventory.py @@ -31,7 +31,7 @@ from fim.slivers.delegations import Delegations from fim.slivers.instance_catalog import InstanceCatalog from fim.slivers.interface_info import InterfaceSliver -from fim.slivers.network_node import NodeSliver +from fim.slivers.network_node import NodeSliver, NodeType from fim.slivers.network_service import NSLayer from fabric_cf.actor.core.apis.abc_reservation_mixin import ABCReservationMixin @@ -476,6 +476,60 @@ def __check_components(self, *, rid: ID, requested_components: AttachedComponent return requested_components + def __allocate_p4_switch(self, *, rid: ID, requested_sliver: NodeSliver, graph_id: str, graph_node: NodeSliver, + existing_reservations: List[ABCReservationMixin], existing_components: Dict[str, List[str]], + is_create: bool = False) -> Tuple[str, BaseSliver]: + """ + Allocate an extending or ticketing reservation for a P4 switch + + :param rid: reservation id of the reservation to be allocated + :param requested_sliver: requested sliver + :param graph_id: BQM graph id + :param graph_node: BQM graph node identified to serve the reservation + :param existing_components: Existing Components + :param existing_reservations: Existing Reservations served by the same BQM node + :param is_create: Indicates if this is create or modify + + :return: Tuple of Delegation Id and the Requested Sliver annotated with BQM Node Id and other properties + :raises: BrokerException in case the request cannot be satisfied + """ + delegation_id = None + + if not is_create: + # In case of modify, directly get delegation_id + if len(graph_node.get_capacity_delegations().get_delegation_ids()) > 0: + delegation_id = next(iter(graph_node.get_capacity_delegations().get_delegation_ids())) + + # Nothing to do, just return + return delegation_id, requested_sliver + + # Handle allocation to account for leaked Network Services + for n in existing_components.keys(): + if n in graph_node.node_id: + raise BrokerException(error_code=ExceptionErrorCode.INSUFFICIENT_RESOURCES, + msg=f"Node of type: {graph_node.get_type()} not available on site: " + f"{graph_node.get_site()}, already in use by another reservation") + + # For create, we need to allocate the P4 + requested_capacities = requested_sliver.get_capacities() + + # Check if Capacities can be satisfied + delegation_id = self.__check_capacities(rid=rid, + requested_capacities=requested_capacities, + delegated_capacities=graph_node.get_capacity_delegations(), + existing_reservations=existing_reservations) + requested_sliver.capacity_allocations = Capacities() + requested_sliver.capacity_allocations = Capacities.update(lab=requested_capacities) + requested_sliver.label_allocations = Labels(local_name=graph_node.get_name()) + + requested_sliver.set_node_map(node_map=(graph_id, graph_node.node_id)) + requested_sliver.management_ip = graph_node.management_ip + + self.logger.info(f"Reservation# {rid} is being served by delegation# {delegation_id} " + f"node# [{graph_id}/{graph_node.node_id}]") + + return delegation_id, requested_sliver + def allocate(self, *, rid: ID, requested_sliver: BaseSliver, graph_id: str, graph_node: BaseSliver, existing_reservations: List[ABCReservationMixin], existing_components: Dict[str, List[str]], is_create: bool = False) -> Tuple[str, BaseSliver]: @@ -492,17 +546,26 @@ def allocate(self, *, rid: ID, requested_sliver: BaseSliver, graph_id: str, grap :raises: BrokerException in case the request cannot be satisfied """ if graph_node.get_capacity_delegations() is None or rid is None: - raise BrokerException(error_code=Constants.INVALID_ARGUMENT, + raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg=f"capacity_delegations is missing or reservation is None") if not isinstance(requested_sliver, NodeSliver): - raise BrokerException(error_code=Constants.INVALID_ARGUMENT, + raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg=f"resource type: {requested_sliver.get_type()}") if not isinstance(graph_node, NodeSliver): - raise BrokerException(error_code=Constants.INVALID_ARGUMENT, + raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg=f"resource type: {graph_node.get_type()}") + if requested_sliver.get_type() not in [NodeType.VM, NodeType.Switch]: + raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, + msg=f"Unsupported resource type: {graph_node.get_type()}") + + if requested_sliver.get_type() == NodeType.Switch: + return self.__allocate_p4_switch(rid=rid, requested_sliver=requested_sliver, graph_id=graph_id, + graph_node=graph_node, existing_reservations=existing_reservations, + existing_components=existing_components, is_create=is_create) + delegation_id = None requested_capacities = None # For create, we need to allocate the VM @@ -547,4 +610,4 @@ def allocate(self, *, rid: ID, requested_sliver: BaseSliver, graph_id: str, grap return delegation_id, requested_sliver def free(self, *, count: int, request: dict = None, resource: dict = None) -> dict: - return + pass diff --git a/fabric_cf/actor/db/psql_database.py b/fabric_cf/actor/db/psql_database.py index 304e4a76..899c61d2 100644 --- a/fabric_cf/actor/db/psql_database.py +++ b/fabric_cf/actor/db/psql_database.py @@ -876,6 +876,20 @@ def get_reservations(self, *, slice_id: str = None, graph_node_id: str = None, p def get_components(self, *, node_id: str, states: list[int], rsv_type: list[str], component: str = None, bdf: str = None, start: datetime = None, end: datetime = None) -> Dict[str, List[str]]: + """ + Returns components matching the search criteria + @param node_id: Worker Node ID to which components belong + @param states: list of states used to find reservations + @param rsv_type: type of reservations + @param component: component name + @param bdf: Component's PCI address + @param start: start time + @param end: end time + + NOTE# For P4 switches; node_id=node+renc-p4-sw component=ip+192.168.11.8 bdf=p1 + + @return Dictionary with component name as the key and value as list of associated PCI addresses in use. + """ result = {} session = self.get_session() try: diff --git a/fabric_cf/actor/fim/fim_helper.py b/fabric_cf/actor/fim/fim_helper.py index c9998132..a8b5d1ca 100644 --- a/fabric_cf/actor/fim/fim_helper.py +++ b/fabric_cf/actor/fim/fim_helper.py @@ -441,6 +441,10 @@ def get_interface_sliver_mapping(ifs_node_id: str, slice_graph: ABCASMPropertyGr if peer_ifs.get_type() in [InterfaceType.DedicatedPort, InterfaceType.SharedPort]: component_name, component_id = slice_graph.get_parent(node_id=peer_ns_id, rel=ABCPropertyGraph.REL_HAS, parent=ABCPropertyGraph.CLASS_Component) + # Possibly P4 switch; parent will be a switch + if not component_name: + component_id = peer_ns_id + component_name = str(NodeType.Switch) node_name, node_id = slice_graph.get_parent(node_id=component_id, rel=ABCPropertyGraph.REL_HAS, parent=ABCPropertyGraph.CLASS_NetworkNode) @@ -535,6 +539,9 @@ def get_site_interface_sliver(*, component: ComponentSliver or NodeSliver, local """ result = None for ns in component.network_service_info.network_services.values(): + if not ns.interface_info: + continue + # Filter on region if region is not None: result = list(filter(lambda x: (region in x.labels.region), ns.interface_info.interfaces.values())) diff --git a/fabric_cf/actor/handlers/no_op_handler.py b/fabric_cf/actor/handlers/no_op_handler.py index 9c49cdb0..c61bcc13 100644 --- a/fabric_cf/actor/handlers/no_op_handler.py +++ b/fabric_cf/actor/handlers/no_op_handler.py @@ -28,7 +28,7 @@ from typing import Tuple from fim.slivers.attached_components import ComponentType -from fim.slivers.network_node import NodeSliver +from fim.slivers.network_node import NodeSliver, NodeType from fim.slivers.network_service import NetworkServiceSliver, ServiceType from fabric_cf.actor.core.common.constants import Constants @@ -125,7 +125,8 @@ def create(self, unit: ConfigToken) -> Tuple[dict, ConfigToken]: time.sleep(10) if isinstance(sliver, NodeSliver): - self.__process_node_sliver(sliver=sliver) + if sliver.get_type() == NodeType.VM: + self.__process_node_sliver(sliver=sliver) elif isinstance(sliver, NetworkServiceSliver): self.__process_ns_sliver(sliver=sliver) diff --git a/fabric_cf/authority/config.site.am.yaml b/fabric_cf/authority/config.site.am.yaml index d42a9ad6..b5e08c37 100644 --- a/fabric_cf/authority/config.site.am.yaml +++ b/fabric_cf/authority/config.site.am.yaml @@ -143,9 +143,18 @@ actor: class: VMHandler properties: config.properties.file: /etc/fabric/actor/config/vm_handler_config.yml + - resource: + type: Switch + label: Switch AM + description: Switch AM + handler: + module: fabric_am.handlers.switch_handler + class: VMHandler + properties: + config.properties.file: /etc/fabric/actor/config/switch_handler_config.yml controls: - control: - type: VM, Container, Baremetal + type: VM, Container, Baremetal, Switch module: fabric_cf.actor.core.policy.network_node_control class: NetworkNodeControl peers: diff --git a/fabric_cf/authority/docker-compose.yml b/fabric_cf/authority/docker-compose.yml index 3cecd2dc..86f8ffbf 100644 --- a/fabric_cf/authority/docker-compose.yml +++ b/fabric_cf/authority/docker-compose.yml @@ -52,7 +52,7 @@ services: network: host context: ../../../ dockerfile: Dockerfile-auth - image: authority:1.6.2 + image: authority:1.7.0 container_name: site1-am restart: always depends_on: diff --git a/fabric_cf/authority/switch_handler_config.yml b/fabric_cf/authority/switch_handler_config.yml new file mode 100644 index 00000000..616c249d --- /dev/null +++ b/fabric_cf/authority/switch_handler_config.yml @@ -0,0 +1,33 @@ +# MIT License +# +# Copyright (c) 2020 FABRIC Testbed +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# +# Author: Komal Thareja (kthare10@renci.org) +ansible: + ansible_python_interpreter: /usr/bin/python3.6 +runtime: +playbooks: + location: /etc/fabric/actor/playbooks + inventory_location: /etc/fabric/actor/playbooks/inventory + admin_ssh_key: /root/.ssh/id_rsa_nova + admin_user: rare + Switch: head_switch_provisioning.yml diff --git a/fabric_cf/authority/test/test.yaml b/fabric_cf/authority/test/test.yaml index 125ffea1..41a638d6 100644 --- a/fabric_cf/authority/test/test.yaml +++ b/fabric_cf/authority/test/test.yaml @@ -137,9 +137,16 @@ actor: handler: module: fabric_cf.actor.handlers.no_op_handler class: NoOpHandler + - resource: + type: Switch + label: P4 Switch AM + description: P4 Switch AM + handler: + module: fabric_cf.actor.handlers.no_op_handler + class: NoOpHandler controls: - control: - type: VM, Container, Baremetal + type: VM, Container, Baremetal, Switch module: fabric_cf.actor.core.policy.network_node_control class: NetworkNodeControl diff --git a/fabric_cf/broker/config.broker.yaml b/fabric_cf/broker/config.broker.yaml index 18218f74..2e841d6c 100644 --- a/fabric_cf/broker/config.broker.yaml +++ b/fabric_cf/broker/config.broker.yaml @@ -142,7 +142,7 @@ actor: algorithm: FirstFit controls: - control: - type: VM, Container, Baremetal + type: VM, Container, Baremetal, Switch class: NetworkNodeInventory module: fabric_cf.actor.core.policy.network_node_inventory - control: diff --git a/fabric_cf/broker/docker-compose.yml b/fabric_cf/broker/docker-compose.yml index dc8d1151..7df2cb2a 100644 --- a/fabric_cf/broker/docker-compose.yml +++ b/fabric_cf/broker/docker-compose.yml @@ -54,7 +54,7 @@ services: build: context: ../../../ dockerfile: Dockerfile-broker - image: broker:1.6.2 + image: broker:1.7.0 container_name: broker restart: always networks: diff --git a/fabric_cf/broker/test/test.yaml b/fabric_cf/broker/test/test.yaml index ea7e31f2..68b83af0 100644 --- a/fabric_cf/broker/test/test.yaml +++ b/fabric_cf/broker/test/test.yaml @@ -138,7 +138,7 @@ actor: algorithm: FirstFit controls: - control: - type: VM, Container, Baremetal + type: VM, Container, Baremetal, Switch class: NetworkNodeInventory module: fabric_cf.actor.core.policy.network_node_inventory - control: diff --git a/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py b/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py index 4bd09b13..f3f45c04 100644 --- a/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py +++ b/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py @@ -191,9 +191,12 @@ def __validate_node_sliver(*, sliver: NodeSliver): @param sliver Node Sliver @raises exception for invalid slivers """ - if sliver.get_capacities() is None and sliver.get_capacity_hints() is None: + if sliver.get_type() == NodeType.VM and sliver.get_capacities() is None and sliver.get_capacity_hints() is None: raise OrchestratorException(message="Either Capacity or Capacity Hints must be specified!", http_error_code=BAD_REQUEST) + if sliver.get_type() == NodeType.Switch and sliver.get_capacities() is None: + raise OrchestratorException(message="Either Capacity must be specified!", + http_error_code=BAD_REQUEST) def __build_ns_sliver_reservation(self, *, slice_graph: ABCASMPropertyGraph, node_id: str, node_res_mapping: Dict[str, str]) -> Tuple[LeaseReservationAvro or None, bool]: @@ -406,26 +409,27 @@ def __build_node_sliver_reservation(self, *, slice_graph: ABCASMPropertyGraph, # Build Network Node Sliver sliver = slice_graph.build_deep_node_sliver(node_id=node_id) - if sliver.get_type() not in [NodeType.VM]: + if sliver.get_type() not in [NodeType.VM, NodeType.Switch]: return None # Validate Node Sliver self.__validate_node_sliver(sliver=sliver) - # Compute Requested Capacities from Capacity Hints - requested_capacities = sliver.get_capacities() - requested_capacity_hints = sliver.get_capacity_hints() - catalog = InstanceCatalog() - if requested_capacities is None and requested_capacity_hints is not None: - requested_capacities = catalog.get_instance_capacities( - instance_type=requested_capacity_hints.instance_type) - sliver.set_capacities(cap=requested_capacities) - - # Compute Capacity Hints from Requested Capacities - if requested_capacity_hints is None and requested_capacities is not None: - instance_type = catalog.map_capacities_to_instance(cap=requested_capacities) - requested_capacity_hints = CapacityHints(instance_type=instance_type) - sliver.set_capacity_hints(caphint=requested_capacity_hints) + if sliver.get_type() == NodeType.VM: + # Compute Requested Capacities from Capacity Hints + requested_capacities = sliver.get_capacities() + requested_capacity_hints = sliver.get_capacity_hints() + catalog = InstanceCatalog() + if requested_capacities is None and requested_capacity_hints is not None: + requested_capacities = catalog.get_instance_capacities( + instance_type=requested_capacity_hints.instance_type) + sliver.set_capacities(cap=requested_capacities) + + # Compute Capacity Hints from Requested Capacities + if requested_capacity_hints is None and requested_capacities is not None: + instance_type = catalog.map_capacities_to_instance(cap=requested_capacities) + requested_capacity_hints = CapacityHints(instance_type=instance_type) + sliver.set_capacity_hints(caphint=requested_capacity_hints) # Generate reservation for the sliver reservation = self.reservation_converter.generate_reservation(sliver=sliver, diff --git a/fabric_cf/orchestrator/docker-compose.yml b/fabric_cf/orchestrator/docker-compose.yml index 4e69cb44..904eebbf 100644 --- a/fabric_cf/orchestrator/docker-compose.yml +++ b/fabric_cf/orchestrator/docker-compose.yml @@ -68,7 +68,7 @@ services: build: context: ../../../ dockerfile: Dockerfile-orchestrator - image: orchestrator:1.6.2 + image: orchestrator:1.7.0 container_name: orchestrator restart: always depends_on: diff --git a/fabric_cf/orchestrator/swagger_server/response/resources_controller.py b/fabric_cf/orchestrator/swagger_server/response/resources_controller.py index 942da8b7..d2749c16 100644 --- a/fabric_cf/orchestrator/swagger_server/response/resources_controller.py +++ b/fabric_cf/orchestrator/swagger_server/response/resources_controller.py @@ -63,7 +63,7 @@ def portalresources_get(graph_format: str, level: int = 1, force_refresh: bool = start = handler.validate_lease_time(lease_time=start_date) end = handler.validate_lease_time(lease_time=end_date) model = handler.list_resources(graph_format_str=graph_format, level=level, force_refresh=force_refresh, - start=start, end=end, includes=includes, excludes=excludes) + start=start, end=end, includes=includes, excludes=excludes, authorize=False) response = Resources() response.data = [Resource(model)] response.size = 1 diff --git a/pyproject.toml b/pyproject.toml index a7f0674d..1e1497be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "PyYAML", "fabric_fss_utils==1.5.0", "fabric-message-bus==1.7.0b1", - "fabric-fim==1.6.1", + "fabric-fim==1.7.0b2", "fabric-credmgr-client==1.6.0", "ansible" ]