diff --git a/fabric_cf/actor/core/apis/abc_actor_management_object.py b/fabric_cf/actor/core/apis/abc_actor_management_object.py index 9e8a807f..f993d081 100644 --- a/fabric_cf/actor/core/apis/abc_actor_management_object.py +++ b/fabric_cf/actor/core/apis/abc_actor_management_object.py @@ -239,7 +239,7 @@ def get_reservations(self, *, caller: AuthToken, states: List[int] = None, slice_id: ID = None, rid: ID = None, oidc_claim_sub: str = None, email: str = None, rid_list: List[str] = None, type: str = None, site: str = None, node_id: str = None, - host: str = None, ip_subnet: str = None) -> ResultReservationAvro: + host: str = None, ip_subnet: str = None, full: bool = False) -> ResultReservationAvro: """ Get Reservations @param states states @@ -255,6 +255,7 @@ def get_reservations(self, *, caller: AuthToken, states: List[int] = None, @param caller caller @param host host @param ip_subnet ip subnet + @param full @return returns list of the reservations """ diff --git a/fabric_cf/actor/core/apis/abc_mgmt_actor.py b/fabric_cf/actor/core/apis/abc_mgmt_actor.py index daf17a32..c4a675c9 100644 --- a/fabric_cf/actor/core/apis/abc_mgmt_actor.py +++ b/fabric_cf/actor/core/apis/abc_mgmt_actor.py @@ -151,7 +151,7 @@ def accept_update_slice(self, *, slice_id: ID) -> bool: def get_reservations(self, *, states: List[int] = None, slice_id: ID = None, rid: ID = None, oidc_claim_sub: str = None, email: str = None, rid_list: List[str] = None, type: str = None, site: str = None, node_id: str = None, - host: str = None, ip_subnet: str = None) -> List[ReservationMng]: + host: str = None, ip_subnet: str = None, full: bool = False) -> List[ReservationMng]: """ Get Reservations @param states states @@ -165,6 +165,7 @@ def get_reservations(self, *, states: List[int] = None, slice_id: ID = None, @param node_id node id @param ip_subnet ip subnet @param host host + @param full Obtains all reservations @return returns list of the reservations """ diff --git a/fabric_cf/actor/core/common/constants.py b/fabric_cf/actor/core/common/constants.py index a1735b4c..e6bb9dad 100644 --- a/fabric_cf/actor/core/common/constants.py +++ b/fabric_cf/actor/core/common/constants.py @@ -200,6 +200,7 @@ class Constants: MAINT_PROJECT_ID = 'maint.project.id' INFRASTRUCTURE_PROJECT_ID = "infrastructure.project.id" TOTAL_SLICE_COUNT_SEED = "total_slice_count_seed" + EXCLUDED_PROJECTS = "excluded.projects" ELASTIC_TIME = "request.elasticTime" ELASTIC_SIZE = "request.elasticSize" diff --git a/fabric_cf/actor/core/kernel/poa.py b/fabric_cf/actor/core/kernel/poa.py index c0faa308..8e9ec2df 100644 --- a/fabric_cf/actor/core/kernel/poa.py +++ b/fabric_cf/actor/core/kernel/poa.py @@ -139,7 +139,8 @@ def restore(self, *, actor: ABCActorMixin, reservation: ABCReservationMixin): """ self.reservation = reservation self.actor = actor - self.logger = self.actor.get_logger() + if actor: + self.logger = self.actor.get_logger() # Update slice/sliver info if available if reservation is not None: diff --git a/fabric_cf/actor/core/kernel/reservation_client.py b/fabric_cf/actor/core/kernel/reservation_client.py index 7e0769a9..43c3dda8 100644 --- a/fabric_cf/actor/core/kernel/reservation_client.py +++ b/fabric_cf/actor/core/kernel/reservation_client.py @@ -1837,9 +1837,10 @@ def update_slice_graph(self, *, sliver: BaseSliver): if asm_thread is not None: asm_thread.enqueue(graph_id=self.slice.get_graph_id(), sliver=sliver, rid=str(self.rid), - reservation_state=self.state.name, + reservation_state=str(self.state), error_message=error_message) - self.logger.debug(f"Update ASM completed for Reservation# {self.rid} State# {self.get_reservation_state()} " + self.logger.debug(f"Update ASM completed for Reservation# {self.rid} " + f"State# {self.get_reservation_state()} " f"Slice Graph# {self.slice.get_graph_id()}") except Exception as e: diff --git a/fabric_cf/actor/core/kernel/rpc_manager.py b/fabric_cf/actor/core/kernel/rpc_manager.py index fb262f31..691e3692 100644 --- a/fabric_cf/actor/core/kernel/rpc_manager.py +++ b/fabric_cf/actor/core/kernel/rpc_manager.py @@ -488,9 +488,9 @@ def do_dispatch_incoming_rpc(self, *, actor: ABCActorMixin, rpc: IncomingRPC): rpc.set_response_handler(response_handler=request.handler) actor.get_logger().debug(f"Inbound {rpc.get_request_type()} request from " - f"<{rpc.get_caller().get_name()}>:{rpc.get()}") + f"<{rpc.get_caller().get_name()}>:{rpc.get()}") - self.__log_sliver(reservation=rpc.get(), logger=actor.get_logger()) + #self.__log_sliver(reservation=rpc.get(), logger=actor.get_logger()) if rpc.get_request_type() == RPCRequestType.QueryResult: if request is None: @@ -564,7 +564,7 @@ def enqueue(self, *, rpc: RPCRequest): from fabric_cf.actor.core.container.globals import GlobalsSingleton logger = GlobalsSingleton.get().get_logger() logger.debug(f"Outbound {rpc.get_request_type()} : {rpc.get()}") - self.__log_sliver(reservation=rpc.get(), logger=logger) + #self.__log_sliver(reservation=rpc.get(), logger=logger) if not self.started: logger.warning("Ignoring RPC request: container is shutting down") return diff --git a/fabric_cf/actor/core/manage/actor_management_object.py b/fabric_cf/actor/core/manage/actor_management_object.py index 8f304837..45d9e4e6 100644 --- a/fabric_cf/actor/core/manage/actor_management_object.py +++ b/fabric_cf/actor/core/manage/actor_management_object.py @@ -185,7 +185,8 @@ def increment_metrics(self, *, project_id: str, oidc_sub: str, slice_count: int def get_slice_count(self, *, caller: AuthToken, email: str = None, states: List[int] = None, project: str = None, user_id: str = None, excluded_projects: List[str] = None) -> int: try: - return self.db.get_slice_count(email=email, states=states, project_id=project, oidc_sub=user_id) + return self.db.get_slice_count(email=email, states=states, project_id=project, oidc_sub=user_id, + excluded_projects=excluded_projects) except Exception as e: self.logger.error("get_slice_count {}".format(e)) return -1 @@ -431,7 +432,7 @@ def get_reservations(self, *, caller: AuthToken, states: List[int] = None, slice_id: ID = None, rid: ID = None, oidc_claim_sub: str = None, email: str = None, rid_list: List[str] = None, type: str = None, site: str = None, node_id: str = None, host: str = None, - ip_subnet: str = None) -> ResultReservationAvro: + ip_subnet: str = None, full: bool = False) -> ResultReservationAvro: result = ResultReservationAvro() result.status = ResultAvro() @@ -464,7 +465,8 @@ def get_reservations(self, *, caller: AuthToken, states: List[int] = None, 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) - full = True if slice_id or rid else False + if not full: + 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: diff --git a/fabric_cf/actor/core/manage/kafka/kafka_actor.py b/fabric_cf/actor/core/manage/kafka/kafka_actor.py index 129d7ee5..91603113 100644 --- a/fabric_cf/actor/core/manage/kafka/kafka_actor.py +++ b/fabric_cf/actor/core/manage/kafka/kafka_actor.py @@ -132,7 +132,7 @@ def delete_slice(self, *, slice_id: ID) -> bool: def get_reservations(self, *, states: List[int] = None, slice_id: ID = None, rid: ID = None, oidc_claim_sub: str = None, email: str = None, rid_list: List[str] = None, type: str = None, site: str = None, node_id: str = None, - host: str = None, ip_subnet: str = None) -> List[ReservationMng]: + host: str = None, ip_subnet: str = None, full: bool = False) -> List[ReservationMng]: request = GetReservationsRequestAvro() request = self.fill_request_by_id_message(request=request, slice_id=slice_id, states=states, email=email, rid=rid, diff --git a/fabric_cf/actor/core/manage/local/local_actor.py b/fabric_cf/actor/core/manage/local/local_actor.py index ae80b11e..d8ef51c7 100644 --- a/fabric_cf/actor/core/manage/local/local_actor.py +++ b/fabric_cf/actor/core/manage/local/local_actor.py @@ -111,13 +111,13 @@ def remove_slice(self, *, slice_id: ID) -> bool: def get_reservations(self, *, states: List[int] = None, slice_id: ID = None, rid: ID = None, oidc_claim_sub: str = None, email: str = None, rid_list: List[str] = None, type: str = None, site: str = None, node_id: str = None, - host: str = None, ip_subnet: str = None) -> List[ReservationMng]: + host: str = None, ip_subnet: str = None, full: bool = False) -> List[ReservationMng]: self.clear_last() try: result = self.manager.get_reservations(caller=self.auth, states=states, slice_id=slice_id, rid=rid, oidc_claim_sub=oidc_claim_sub, email=email, rid_list=rid_list, type=type, site=site, node_id=node_id, host=host, - ip_subnet=ip_subnet) + ip_subnet=ip_subnet, full=full) self.last_status = result.status if result.status.get_code() == 0: 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 bac382bb..cac0a409 100644 --- a/fabric_cf/actor/core/policy/broker_simpler_units_policy.py +++ b/fabric_cf/actor/core/policy/broker_simpler_units_policy.py @@ -873,6 +873,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: self.logger.info(f"Allocated Interface Sliver: {ifs} delegation: {delegation_id}") owner_v4_service = self.get_ns_from_switch(switch=owner_switch, ns_type=ServiceType.FABNetv4) + self.logger.info(f"owner_v4_service: {owner_v4_service}") if owner_v4_service and owner_v4_service.get_labels(): ero_source_end_info.append((owner_switch.node_id, owner_v4_service.get_labels().ipv4)) @@ -891,8 +892,12 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: if ServiceType.MPLS == ns.get_type(): owner_mpls_ns = ns break - delegation_id, delegated_label = InventoryForType.get_delegations(lab_cap_delegations= - owner_ns.get_label_delegations()) + if owner_ns and ServiceType.MPLS == owner_ns.get_type(): + delegation_id, delegated_label = InventoryForType.get_delegations(lab_cap_delegations= + owner_switch.get_label_delegations()) + else: + delegation_id, delegated_label = InventoryForType.get_delegations(lab_cap_delegations= + owner_ns.get_label_delegations()) # Set the Subnet and gateway from the Owner Switch (a) existing_reservations = self.get_existing_reservations(node_id=owner_ns_id, @@ -917,7 +922,7 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: node_id_to_reservations=node_id_to_reservations, term=term) if sliver.ero and len(sliver.ero.get()) and len(ero_source_end_info) == 2: - self.logger.info(f"Requested ERO: {sliver.ero}") + self.logger.info(f"Requested ERO: {sliver.ero} {ero_source_end_info}") ero_hops = [] new_path = [ero_source_end_info[0][1]] type, path = sliver.ero.get() @@ -939,11 +944,13 @@ def __allocate_services(self, *, rid: ID, inv: NetworkServiceInventory, sliver: new_path.append(ero_source_end_info[1][1]) if len(new_path): + ''' if not self.validate_requested_ero_path(source_node=ero_source_end_info[0][0], end_node=ero_source_end_info[1][0], hops=ero_hops): raise BrokerException(error_code=ExceptionErrorCode.INVALID_ARGUMENT, msg=f"Requested ERO path: {sliver.ero} is invalid!") + ''' ero_path = Path() ero_path.set_symmetric(new_path) sliver.ero.set(ero_path) @@ -997,7 +1004,7 @@ def __allocate_peered_interfaces(self, *, rid: ID, peered_interfaces: List[Inter ns_type=sliver.get_type()) peer_mpls, peer_sw = self.get_network_service_from_graph(node_id=peer_ns_id, parent=True) - peer_mpls, peer_ns = self.get_ns(switch=peer_sw, ns_type=sliver.get_type()) + peer_ns = self.get_ns_from_switch(switch=peer_sw, ns_type=sliver.get_type()) bqm_interface = None for bifs in owner_mpls.interface_info.interfaces.values(): @@ -1020,7 +1027,8 @@ def __allocate_peered_interfaces(self, *, rid: ID, peered_interfaces: List[Inter pfs.set_node_map(node_map=(self.combined_broker_model_graph_id, bqm_interface.node_id)) if pfs.peer_labels is None: pfs.peer_labels = Labels() - pfs.peer_labels = Labels.update(pfs.peer_labels, asn=peer_ns.labels.asn) + if peer_ns and peer_ns.labels: + pfs.peer_labels = Labels.update(pfs.peer_labels, asn=peer_ns.labels.asn) self.logger.info(f"Allocated Peered Interface Sliver: {pfs}") # Update the Network Service Sliver Node Map @@ -1380,16 +1388,6 @@ def get_shortest_path(self, *, src_node_id: str, dest_node_id: str): finally: self.lock.release() - def get_ns(self, *, switch: NodeSliver, ns_type: ServiceType) -> Tuple[NetworkServiceSliver, NetworkServiceSliver]: - peer_mpls = peer_ns = None - for ns in switch.network_service_info.network_services.values(): - if ServiceType.MPLS == ns.get_type(): - peer_mpls = ns - if ns.get_type() == ns_type: - peer_ns = ns - - return peer_mpls, peer_ns - def get_peer_node(self, *, site: str, node_type: str, node_name: str) -> NodeSliver: if node_type == str(NodeType.Facility): peer_node = self.get_facility_sliver(node_name=f'{site},{node_name}') diff --git a/fabric_cf/actor/core/policy/network_node_control.py b/fabric_cf/actor/core/policy/network_node_control.py index a2e2af8e..524bea89 100644 --- a/fabric_cf/actor/core/policy/network_node_control.py +++ b/fabric_cf/actor/core/policy/network_node_control.py @@ -28,7 +28,7 @@ from fim.slivers.attached_components import AttachedComponentsInfo from fim.slivers.base_sliver import BaseSliver from fim.slivers.network_node import NodeSliver -from fim.user import Capacities, ComponentType +from fim.user import Capacities, ComponentType, Labels from fabric_cf.actor.core.apis.abc_authority_reservation import ABCAuthorityReservation from fabric_cf.actor.core.apis.abc_reservation_mixin import ABCReservationMixin @@ -219,12 +219,18 @@ 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: - 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) if diff is not None: + if requested.get_label_allocations() and current_sliver.get_label_allocations(): + requested.label_allocations = Labels.update(current_sliver.label_allocations) + else: + requested.set_label_allocations(current_sliver.get_label_allocations()) + requested.set_management_ip(current_sliver.get_management_ip()) + # Modify MVP - only handle add components for now if len(diff.added.components) > 0: + self.logger.info(f"Extend Lease - modify add res# {reservation}") self.__check_components(rid=reservation.get_reservation_id(), requested_components=requested.attached_components_info, graph_node=graph_node, @@ -235,13 +241,16 @@ def assign(self, *, reservation: ABCAuthorityReservation, delegation_name: str, properties=reservation.get_slice().get_config_properties()) modified = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit}) elif len(diff.removed.components) > 0 or len(diff.modified.components): + self.logger.info(f"Extend Lease - modify rem/modify res# {reservation}") unit = Unit(rid=reservation.get_reservation_id(), slice_id=reservation.get_slice_id(), actor_id=self.authority.get_guid(), sliver=requested, rtype=resource_type, properties=reservation.get_slice().get_config_properties()) modified = UnitSet(plugin=self.authority.get_plugin(), units={unit.reservation_id: unit}) else: + self.logger.info(f"Extend Lease res# {reservation}") return current else: + self.logger.info(f"Extend Lease res# {reservation}") return current result = ResourceSet(gained=gained, modified=modified, lost=lost, rtype=resource_type) diff --git a/fabric_cf/actor/core/policy/network_service_inventory.py b/fabric_cf/actor/core/policy/network_service_inventory.py index d5456b09..ac912b74 100644 --- a/fabric_cf/actor/core/policy/network_service_inventory.py +++ b/fabric_cf/actor/core/policy/network_service_inventory.py @@ -360,7 +360,7 @@ def allocate(self, *, rid: ID, requested_ns: NetworkServiceSliver, owner_ns: Net return requested_ns gateway_labels = self._assign_gateway_labels(ip_network=ip_network, subnet_list=subnet_list, - requested_ns_type=requested_ns.get_type()) + requested_ns=requested_ns) self.logger.debug(f"Gateway Labels: {gateway_labels}") @@ -487,25 +487,41 @@ def _get_allocated_sliver(self, reservation: ABCReservationMixin) -> NetworkServ self.logger.error("Could not find the allocated Sliver - should not reach here!") def _assign_gateway_labels(self, *, ip_network: Union[IPv4Network, IPv6Network], subnet_list: List, - requested_ns_type: str) -> Labels: + requested_ns: NetworkServiceSliver) -> Labels: """ Assign gateway labels based on the requested network service type. :param ip_network: The IP network from which subnets are derived, either IPv4Network or IPv6Network. :param subnet_list: A list of subnets derived from the ip_network. - :param requested_ns_type: The type of the requested network service. + :param requested_ns: Network Service sliver. :return: Gateway labels populated with the appropriate subnet and IP address. """ gateway_labels = Labels() - if requested_ns_type == ServiceType.FABNetv4: + if requested_ns.get_type() == ServiceType.FABNetv4: + # Allocate the requested network if available else allocate new network + if requested_ns.gateway and requested_ns.gateway.lab and requested_ns.gateway.lab.ipv4_subnet: + requested_subnet = IPv4Network(requested_ns.gateway.lab.ipv4_subnet) + if requested_subnet in subnet_list: + gateway_labels.ipv4_subnet = requested_subnet.with_prefixlen + gateway_labels.ipv4 = str(next(requested_subnet.hosts())) + return gateway_labels + gateway_labels.ipv4_subnet = subnet_list[0].with_prefixlen gateway_labels.ipv4 = str(list(subnet_list[0].hosts())[0]) - elif requested_ns_type == ServiceType.FABNetv4Ext: + elif requested_ns.get_type() == ServiceType.FABNetv4Ext: gateway_labels.ipv4_subnet = ip_network.with_prefixlen gateway_labels.ipv4 = str(subnet_list[0]) - elif requested_ns_type in Constants.L3_FABNETv6_SERVICES: + elif requested_ns.get_type() in Constants.L3_FABNETv6_SERVICES: + # Allocate the requested network if available else allocate new network + if requested_ns.gateway and requested_ns.gateway.lab and requested_ns.gateway.lab.ipv6_subnet: + requested_subnet = IPv6Network(requested_ns.gateway.lab.ipv6_subnet) + if requested_subnet in subnet_list: + gateway_labels.ipv6_subnet = requested_subnet.with_prefixlen + gateway_labels.ipv6 = str(next(requested_subnet.hosts())) + return gateway_labels + gateway_labels.ipv6_subnet = subnet_list[0].with_prefixlen gateway_labels.ipv6 = str(next(subnet_list[0].hosts())) diff --git a/fabric_cf/actor/core/proxies/kafka/kafka_authority_proxy.py b/fabric_cf/actor/core/proxies/kafka/kafka_authority_proxy.py index 6091351e..b25c8649 100644 --- a/fabric_cf/actor/core/proxies/kafka/kafka_authority_proxy.py +++ b/fabric_cf/actor/core/proxies/kafka/kafka_authority_proxy.py @@ -133,8 +133,7 @@ def prepare_close(self, *, reservation: ABCControllerReservation, callback: Kafk caller: AuthToken) -> ABCRPCRequestState: return self._prepare(reservation=reservation, callback=callback, caller=caller) - @staticmethod - def pass_authority_reservation(reservation: ABCReservationMixin, caller: AuthToken) -> ReservationAvro: + def pass_authority_reservation(self, reservation: ABCReservationMixin, caller: AuthToken) -> ReservationAvro: concrete = reservation.get_resources().get_resources() if concrete is None: raise ProxyException(Constants.NOT_SPECIFIED_PREFIX.format("ticket")) @@ -154,5 +153,6 @@ def pass_authority_reservation(reservation: ABCReservationMixin, caller: AuthTok rset.unit_set = Translate.translate_unit_set(unit_set=concrete) avro_reservation.resource_set = rset - + if self.logger: + self.logger.debug(f"Resource Set: {rset}") return avro_reservation diff --git a/fabric_cf/actor/core/proxies/kafka/kafka_retun.py b/fabric_cf/actor/core/proxies/kafka/kafka_retun.py index 51926169..1ccd36dd 100644 --- a/fabric_cf/actor/core/proxies/kafka/kafka_retun.py +++ b/fabric_cf/actor/core/proxies/kafka/kafka_retun.py @@ -130,8 +130,7 @@ def prepare_poa_result(self, *, poa: Poa, callback: KafkaProxy, caller: AuthToke request.caller = caller return request - @staticmethod - def pass_reservation(reservation: ABCServerReservation, auth: AuthToken) -> ReservationAvro: + def pass_reservation(self, reservation: ABCServerReservation, auth: AuthToken) -> ReservationAvro: avro_reservation = ReservationAvro() avro_reservation.slice = Translate.translate_slice_to_avro(slice_obj=reservation.get_slice()) if reservation.get_term() is None: @@ -158,6 +157,8 @@ def pass_reservation(reservation: ABCServerReservation, auth: AuthToken) -> Rese rset.unit_set = Translate.translate_unit_set(unit_set=cset) avro_reservation.resource_set = rset + if self.logger: + self.logger.info(f"Resource Set: {rset}") return avro_reservation @staticmethod diff --git a/fabric_cf/actor/fim/asm_update_thread.py b/fabric_cf/actor/fim/asm_update_thread.py index 9a558c0d..dfd17555 100644 --- a/fabric_cf/actor/fim/asm_update_thread.py +++ b/fabric_cf/actor/fim/asm_update_thread.py @@ -42,12 +42,17 @@ class AsmUpdateException(Exception): class AsmEvent: - def __init__(self, *, graph_id: str, sliver: BaseSliver): + def __init__(self, *, graph_id: str, sliver: BaseSliver, reservation_id: str, + state: str, error_message: str): self.graph_id = graph_id self.sliver = sliver + self.reservation_id = reservation_id + self.state = state + self.error_message = error_message def process(self): - FimHelper.update_node(graph_id=self.graph_id, sliver=self.sliver) + FimHelper.update_node(graph_id=self.graph_id, sliver=self.sliver, reservation_id=self.reservation_id, + state=self.state, error_message=self.error_message) class AsmUpdateThread: @@ -118,13 +123,8 @@ def stop(self): def enqueue(self, *, graph_id: str, sliver: BaseSliver, rid: str, reservation_state: str, error_message: str): try: - if sliver.reservation_info is None: - sliver.reservation_info = ReservationInfo() - sliver.reservation_info.reservation_id = rid - sliver.reservation_info.reservation_state = reservation_state - sliver.reservation_info.error_message = error_message - - event = AsmEvent(graph_id=graph_id, sliver=sliver) + event = AsmEvent(graph_id=graph_id, sliver=sliver, reservation_id=rid, + state=reservation_state, error_message=error_message) self.event_queue.put_nowait(event) with self.condition: self.condition.notify_all() diff --git a/fabric_cf/actor/fim/fim_helper.py b/fabric_cf/actor/fim/fim_helper.py index d29e9550..478e7a3c 100644 --- a/fabric_cf/actor/fim/fim_helper.py +++ b/fabric_cf/actor/fim/fim_helper.py @@ -316,11 +316,15 @@ def get_delegation(delegated_capacities: Delegations, delegation_name: str) -> C return delegation.get_details() if delegation is not None else None @staticmethod - def update_node(*, graph_id: str, sliver: BaseSliver): + def update_node(*, graph_id: str, sliver: BaseSliver, reservation_id: str, + state: str, error_message: str): """ Update Sliver Node in ASM :param graph_id: :param sliver: + :param reservation_id: + :param state: + :param error_message: :return: """ if sliver is None: @@ -330,13 +334,18 @@ def update_node(*, graph_id: str, sliver: BaseSliver): neo4j_topo = ExperimentTopology() neo4j_topo.cast(asm_graph=asm_graph) + res_info = ReservationInfo() + res_info.reservation_id = reservation_id + res_info.reservation_state = state + res_info.error_message = error_message + node_name = sliver.get_name() if isinstance(sliver, NodeSliver) and node_name in neo4j_topo.nodes: node = neo4j_topo.nodes[node_name] node.set_properties(labels=sliver.labels, label_allocations=sliver.label_allocations, capacity_allocations=sliver.capacity_allocations, - reservation_info=sliver.reservation_info, + reservation_info=res_info, node_map=sliver.node_map, management_ip=sliver.management_ip, capacity_hints=sliver.capacity_hints) @@ -346,6 +355,7 @@ def update_node(*, graph_id: str, sliver: BaseSliver): if diff is not None: for cname in diff.removed.components: reservation_info = ReservationInfo() + reservation_info.reservation_id = reservation_id reservation_info.reservation_state = ReservationStates.Failed.name node.components[cname].set_properties(reservation_info=reservation_info) @@ -379,7 +389,7 @@ def update_node(*, graph_id: str, sliver: BaseSliver): node.set_properties(labels=sliver.labels, label_allocations=sliver.label_allocations, capacity_allocations=sliver.capacity_allocations, - reservation_info=sliver.reservation_info, + reservation_info=res_info, node_map=sliver.node_map, gateway=sliver.gateway) if sliver.interface_info is not None: diff --git a/fabric_cf/authority/vm_handler_config.yml b/fabric_cf/authority/vm_handler_config.yml index 85bcaa67..c77b5995 100644 --- a/fabric_cf/authority/vm_handler_config.yml +++ b/fabric_cf/authority/vm_handler_config.yml @@ -52,7 +52,6 @@ runtime: docker_rocky_9: rocky docker_ubuntu_20: ubuntu docker_ubuntu_22: ubuntu - attestable_bmv2_v1_ubuntu_20: ubuntu attestable_bmv2_v2_ubuntu_20: ubuntu playbooks: location: /etc/fabric/actor/playbooks diff --git a/fabric_cf/orchestrator/config.orchestrator.yaml b/fabric_cf/orchestrator/config.orchestrator.yaml index 60e2ec43..40317563 100644 --- a/fabric_cf/orchestrator/config.orchestrator.yaml +++ b/fabric_cf/orchestrator/config.orchestrator.yaml @@ -55,6 +55,7 @@ runtime: commit.batch.size: 1 enable.auto.commit: False consumer.poll.timeout: 250 + excluded.projects: 990d8a8b-7e50-4d13-a3be-0f133ffa8653, 4604cab7-41ff-4c1a-a935-0ca6f20cceeb, 990d8a8b-7e50-4d13-a3be-0f133ffa8653 logging: ## The directory in which actor should create log files. diff --git a/fabric_cf/orchestrator/core/orchestrator_handler.py b/fabric_cf/orchestrator/core/orchestrator_handler.py index 39b2c99b..0f476de0 100644 --- a/fabric_cf/orchestrator/core/orchestrator_handler.py +++ b/fabric_cf/orchestrator/core/orchestrator_handler.py @@ -69,6 +69,8 @@ def __init__(self): self.total_slice_count_seed = self.config.get_runtime_config().get(Constants.TOTAL_SLICE_COUNT_SEED, 0) self.local_bqm = self.globals.get_config().get_global_config().get_bqm_config().get( Constants.LOCAL_BQM, False) + excluded_projects = self.config.get_runtime_config().get(Constants.EXCLUDED_PROJECTS, "") + self.excluded_projects = [e.strip() for e in excluded_projects.split(",") if e.strip()] def get_logger(self): """ @@ -119,7 +121,8 @@ def get_broker(self, *, controller: ABCMgmtControllerMixin) -> ID: def discover_broker_query_model(self, *, controller: ABCMgmtControllerMixin, token: str = None, level: int = 10, graph_format: GraphFormat = GraphFormat.GRAPHML, force_refresh: bool = False, start: datetime = None, - end: datetime = None, includes: str = None, excludes: str = None) -> str or None: + end: datetime = None, includes: str = None, excludes: str = None, + email: str = None) -> str or None: """ Discover all the available resources by querying Broker :param controller Management Controller Object @@ -135,8 +138,7 @@ def discover_broker_query_model(self, *, controller: ABCMgmtControllerMixin, tok """ broker_query_model = None # Always get Fresh copy for advanced resource requests - if not start and not end and not includes and not excludes and \ - (level <= 1 or graph_format == GraphFormat.JSON_NODELINK): + if not start and not end and not includes and not excludes: saved_bqm = self.controller_state.get_saved_bqm(graph_format=graph_format, level=level) if saved_bqm is not None: if not force_refresh and not saved_bqm.can_refresh() and not saved_bqm.refresh_in_progress: @@ -144,6 +146,7 @@ def discover_broker_query_model(self, *, controller: ABCMgmtControllerMixin, tok else: saved_bqm.start_refresh() + ''' if broker_query_model is None: if self.local_bqm and level == 2 and not force_refresh: saved_bqm = self.controller_state.get_saved_bqm(graph_format=GraphFormat.GRAPHML, level=0) @@ -152,25 +155,28 @@ def discover_broker_query_model(self, *, controller: ABCMgmtControllerMixin, tok level=level, graph_format=graph_format, start=start, end=end, includes=includes, excludes=excludes) - # Request the model from Broker as a fallback - if not broker_query_model: - broker = self.get_broker(controller=controller) - if broker is None: - raise OrchestratorException("Unable to determine broker proxy for this controller. " - "Please check Orchestrator container configuration and logs.") - - model = controller.get_broker_query_model(broker=broker, id_token=token, level=level, - graph_format=graph_format, start=start, end=end, - includes=includes, excludes=excludes) - if model is None or model.get_model() is None or model.get_model() == '': - raise OrchestratorException(http_error_code=NOT_FOUND, message=f"Resource(s) not found for " - f"level: {level} format: {graph_format}!") - - broker_query_model = model.get_model() + ''' + # Request the model from Broker as a fallback + if not broker_query_model: + broker = self.get_broker(controller=controller) + if broker is None: + raise OrchestratorException("Unable to determine broker proxy for this controller. " + "Please check Orchestrator container configuration and logs.") + + self.logger.info(f"Sending Query to broker on behalf of {email} Start: {start}, End: {end}, " + f"Force: {force_refresh}, Level: {level}") + + model = controller.get_broker_query_model(broker=broker, id_token=token, level=level, + graph_format=graph_format, start=start, end=end, + includes=includes, excludes=excludes) + if model is None or model.get_model() is None or model.get_model() == '': + raise OrchestratorException(http_error_code=NOT_FOUND, message=f"Resource(s) not found for " + f"level: {level} format: {graph_format}!") + + broker_query_model = model.get_model() # Do not update cache for advance requests - if not start and not end and not includes and not excludes and \ - (level <= 1 or graph_format == GraphFormat.JSON_NODELINK): + if not start and not end and not includes and not excludes: self.controller_state.save_bqm(bqm=broker_query_model, graph_format=graph_format, level=level) return broker_query_model @@ -199,11 +205,14 @@ def list_resources(self, *, level: int, force_refresh: bool = False, start: date graph_format = self.__translate_graph_format(graph_format=graph_format_str) if graph_format_str else GraphFormat.GRAPHML if authorize: - self.__authorize_request(id_token=token, action_id=ActionId.query) + fabric_token = self.__authorize_request(id_token=token, action_id=ActionId.query) + email = fabric_token.email + else: + email = None broker_query_model = self.discover_broker_query_model(controller=controller, token=token, level=level, force_refresh=force_refresh, start=start, end=end, includes=includes, excludes=excludes, - graph_format=graph_format) + graph_format=graph_format, email=email) return broker_query_model except Exception as e: @@ -682,20 +691,22 @@ def get_slice_graph(self, *, token: str, slice_id: str, graph_format_str: str, a slice_obj = next(iter(slice_list)) - if slice_obj.get_graph_id() is None: - raise OrchestratorException(f"Slice# {slice_obj} does not have graph id") + slice_model_str = None + if graph_format_str != "NONE": + if slice_obj.get_graph_id() is None: + raise OrchestratorException(f"Slice# {slice_obj} does not have graph id") - slice_model = FimHelper.get_graph(graph_id=slice_obj.get_graph_id()) + slice_model = FimHelper.get_graph(graph_id=slice_obj.get_graph_id()) - graph_format = self.__translate_graph_format(graph_format=graph_format_str) - if graph_format == GraphFormat.JSON_NODELINK: - slice_model_str = slice_model.serialize_graph() - slice_model = FimHelper.get_networkx_graph_from_string(graph_str=slice_model_str) + graph_format = self.__translate_graph_format(graph_format=graph_format_str) + if graph_format == GraphFormat.JSON_NODELINK: + slice_model_str = slice_model.serialize_graph() + slice_model = FimHelper.get_networkx_graph_from_string(graph_str=slice_model_str) - if slice_model is None: - raise OrchestratorException(f"Slice# {slice_obj} graph could not be loaded") + if slice_model is None: + raise OrchestratorException(f"Slice# {slice_obj} graph could not be loaded") - slice_model_str = slice_model.serialize_graph(format=graph_format) + slice_model_str = slice_model.serialize_graph(format=graph_format) return ResponseBuilder.get_slice_summary(slice_list=slice_list, slice_model=slice_model_str)[0] except Exception as e: self.logger.error(traceback.format_exc()) @@ -978,6 +989,8 @@ def get_poas(self, *, token: str, sliver_id: str = None, poa_id: str = None, sta def get_metrics_overview(self, *, token: str = None, excluded_projects: List[str] = None): """ Get metrics overview + :param token: token + :param excluded_projects: list of projects to exclude """ try: controller = self.controller_state.get_management_actor() @@ -993,6 +1006,11 @@ def get_metrics_overview(self, *, token: str = None, excluded_projects: List[str project, tags, project_name = fabric_token.first_project user_id = fabric_token.uuid + if excluded_projects: + excluded_projects.extend(self.excluded_projects) + else: + excluded_projects = self.excluded_projects + active_states = SliceState.list_values_ex_closing_dead() active_slice_count = controller.get_slice_count(states=active_states, user_id=user_id, project=project, excluded_projects=excluded_projects) diff --git a/fabric_cf/orchestrator/core/orchestrator_kernel.py b/fabric_cf/orchestrator/core/orchestrator_kernel.py index 18f59a7e..5fbaac68 100644 --- a/fabric_cf/orchestrator/core/orchestrator_kernel.py +++ b/fabric_cf/orchestrator/core/orchestrator_kernel.py @@ -157,10 +157,12 @@ def start_threads(self): Start threads :return: """ + ''' if not len(self.bqm_cache): self.save_bqm(bqm="", graph_format=GraphFormat.GRAPHML, level=0) saved_bqm = self.get_saved_bqm(graph_format=GraphFormat.GRAPHML, level=0) saved_bqm.last_query_time = None + ''' from fabric_cf.actor.core.container.globals import GlobalsSingleton GlobalsSingleton.get().get_container().register(tickable=self) diff --git a/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py b/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py index a8fc6865..d04faf1c 100644 --- a/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py +++ b/fabric_cf/orchestrator/core/orchestrator_slice_wrapper.py @@ -640,7 +640,8 @@ def __check_modify_on_fabnetv4ext(self, *, rid: str, req_sliver: NetworkServiceS if req_sliver.labels is not None and req_sliver.labels.ipv4 is not None and len(req_sliver.labels.ipv4) > 0: bqm_graph_id, owner_mpls_node_id = req_sliver.get_node_map() - existing_reservations = self.controller.get_reservations(node_id=owner_mpls_node_id, states=states) + existing_reservations = self.controller.get_reservations(node_id=owner_mpls_node_id, states=states, + full=True) ip_network = IPv4Network(req_sliver.gateway.lab.ipv4_subnet) ipaddress_list = list(ip_network.hosts()) ipaddress_list.pop(0) @@ -650,6 +651,10 @@ def __check_modify_on_fabnetv4ext(self, *, rid: str, req_sliver: NetworkServiceS if rid == reservation.get_reservation_id(): continue + if not reservation.get_sliver(): + self.logger.warning(f"No sliver found, Skipping reservation: {reservation.get_reservation_id()}") + continue + if reservation.get_sliver().get_type() != req_sliver.get_type(): continue @@ -715,5 +720,5 @@ def update_topology(self, *, topology: ExperimentTopology): capacities=sliver.capacities) def has_sliver_updates_at_authority(self): - return len(self.computed_reservations) and len(self.computed_remove_reservations) or \ + return len(self.computed_reservations) or len(self.computed_remove_reservations) or \ len(self.computed_modify_reservations) or len(self.computed_modify_properties_reservations) diff --git a/fabric_cf/orchestrator/fabricTags.OrchestratorTags.xml b/fabric_cf/orchestrator/fabricTags.OrchestratorTags.xml index b0426211..12b2f090 100644 --- a/fabric_cf/orchestrator/fabricTags.OrchestratorTags.xml +++ b/fabric_cf/orchestrator/fabricTags.OrchestratorTags.xml @@ -1 +1 @@ -http://www.w3.org/TR/1999/REC-xpath-19991116http://www.w3.org/TR/1999/REC-xpath-19991116createhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliver2VM.NoLimitCPUPolicy Violation: Your project is lacking VM.NoLimitCPU or VM.NoLimit tag to provision VM with more than 2 cores.Policy Violation: Policy returned deny for an unknown reason. This is an internal error.10VM.NoLimitDiskPolicy Violation: Your project is lacking VM.NoLimitDisk or VM.NoLimit tag to provision VM with disk over 10GB.10VM.NoLimitRAMPolicy Violation: Your project is lacking VM.NoLimitRAM or VM.NoLimit tag to provision VM with more than 10GB of RAM.http://www.w3.org/TR/1999/REC-xpath-19991116sliver21010VM.NoLimithttp://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverGPUComponent.GPUPolicy Violation: Your project is lacking Component.GPU tag to provision a VM with GPU.SmartNICComponent.SmartNICPolicy Violation: Your project is lacking Component.SmartNIC tag to provision a VM with SmartNIC.StorageComponent.StoragePolicy Violation: Your project is lacking Component.Storage tag to provision a VM with attached storage.FPGAComponent.FPGAPolicy Violation: Your project is lacking Component.FPGA tag to provision a VM with FPGA.NVMEComponent.NVMEPolicy Violation: Your project is lacking Component.NVME tag to provision a VM with NVME.http://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliver0Net.FABNetv4ExtPolicy Violation: Your project is lacking Net.FABNetv4Ext tag to request a slice with external IPv4 connectivity.0Net.FABNetv6ExtPolicy Violation: Your project is lacking Net.FABNetv6Ext tag to request a slice with external IPv6 connectivity.0Net.PortMirroringPolicy Violation: Your project is lacking Net.PortMirroring tag to request a slice that uses port mirroring.1Slice.MultisitePolicy Violation: Your project is lacking Slice.Multisite tag to request a slice spanning multiple sites.EDUKYSlice.OnlyEDUKYPolicy Violation: Your project is tagged as OnlyEDUKY and cannot use resources on sites other than EDUKY.10Net.NoLimitBWPolicy Violation: Your project is lacking Net.NoLimitBW tag to request links with bandwidth over 10Gbps.0Net.FacilityPort.Policy Violation: Your project is lacking Net.FacilityPort.<facility-port-name> tag to request a connection to one or more of the facilities.http://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116slivertrueSlice.MeasurementsPolicy Violation: Your project is lacking Slice.Measurements tag to request measurement resources.P14DT5MSlice.NoLimitLifetimePolicy Violation: Your project is lacking Slice.NoLimitLifetime tag so you cannot request resource lifetime longer than two weeks.http://www.w3.org/TR/1999/REC-xpath-19991116modifyhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and not the member of the same project so you cannot modify it.http://www.w3.org/TR/1999/REC-xpath-19991116deletehttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and cannot delete it.http://www.w3.org/TR/1999/REC-xpath-19991116renewhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and not the member of the same project so you cannot renew it.http://www.w3.org/TR/1999/REC-xpath-19991116sliverP14DT5MSlice.NoLimitLifetimePolicy Violation: Your project is lacking Slice.NoLimitLifetime tag so you cannot renew resource lifetime by longer than two weeks.http://www.w3.org/TR/1999/REC-xpath-19991116querystatusredeemPOAdemandupdatecloseclaimreclaimticketextendrelinquishhttp://www.w3.org/TR/1999/REC-xpath-19991116querystatusredeemPOAdemandupdatecloseclaimreclaimticketextendrelinquish \ No newline at end of file +http://www.w3.org/TR/1999/REC-xpath-19991116http://www.w3.org/TR/1999/REC-xpath-19991116createhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverSwitch.P4Policy Violation: Your project is lacking Switch.P4 tag to provision a P4 switch.Policy Violation: Policy returned deny for an unknown reason. This is an internal error.http://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliver2VM.NoLimitCPUPolicy Violation: Your project is lacking VM.NoLimitCPU or VM.NoLimit tag to provision VM with more than 2 cores.10VM.NoLimitDiskPolicy Violation: Your project is lacking VM.NoLimitDisk or VM.NoLimit tag to provision VM with disk over 10GB.10VM.NoLimitRAMPolicy Violation: Your project is lacking VM.NoLimitRAM or VM.NoLimit tag to provision VM with more than 10GB of RAM.http://www.w3.org/TR/1999/REC-xpath-19991116sliver21010VM.NoLimithttp://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverGPUComponent.GPUPolicy Violation: Your project is lacking Component.GPU tag to provision a VM with GPU.SmartNICComponent.SmartNICPolicy Violation: Your project is lacking Component.SmartNIC tag to provision a VM with SmartNIC.StorageComponent.StoragePolicy Violation: Your project is lacking Component.Storage tag to provision a VM with attached storage.FPGAComponent.FPGAPolicy Violation: Your project is lacking Component.FPGA tag to provision a VM with FPGA.NVMEComponent.NVMEPolicy Violation: Your project is lacking Component.NVME tag to provision a VM with NVME.http://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116sliver0Net.FABNetv4ExtPolicy Violation: Your project is lacking Net.FABNetv4Ext tag to request a slice with external IPv4 connectivity.0Net.FABNetv6ExtPolicy Violation: Your project is lacking Net.FABNetv6Ext tag to request a slice with external IPv6 connectivity.0Net.PortMirroringPolicy Violation: Your project is lacking Net.PortMirroring tag to request a slice that uses port mirroring.1Slice.MultisitePolicy Violation: Your project is lacking Slice.Multisite tag to request a slice spanning multiple sites.EDUKYSlice.OnlyEDUKYPolicy Violation: Your project is tagged as OnlyEDUKY and cannot use resources on sites other than EDUKY.10Net.NoLimitBWPolicy Violation: Your project is lacking Net.NoLimitBW tag to request links with bandwidth over 10Gbps.0Net.FacilityPort.Policy Violation: Your project is lacking Net.FacilityPort.<facility-port-name> tag to request a connection to one or more of the facilities.http://www.w3.org/TR/1999/REC-xpath-19991116sliverhttp://www.w3.org/TR/1999/REC-xpath-19991116slivertrueSlice.MeasurementsPolicy Violation: Your project is lacking Slice.Measurements tag to request measurement resources.P14DT5MSlice.NoLimitLifetimePolicy Violation: Your project is lacking Slice.NoLimitLifetime tag so you cannot request resource lifetime longer than two weeks.http://www.w3.org/TR/1999/REC-xpath-19991116modifyhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and not the member of the same project so you cannot modify it.http://www.w3.org/TR/1999/REC-xpath-19991116deletehttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and cannot delete it.http://www.w3.org/TR/1999/REC-xpath-19991116renewhttp://www.w3.org/TR/1999/REC-xpath-19991116sliverPolicy Violation: You are not the creator of this resource and not the member of the same project so you cannot renew it.http://www.w3.org/TR/1999/REC-xpath-19991116sliverP14DT5MSlice.NoLimitLifetimePolicy Violation: Your project is lacking Slice.NoLimitLifetime tag so you cannot renew resource lifetime by longer than two weeks.http://www.w3.org/TR/1999/REC-xpath-19991116querystatusredeemPOAdemandupdatecloseclaimreclaimticketextendrelinquishhttp://www.w3.org/TR/1999/REC-xpath-19991116querystatusredeemPOAdemandupdatecloseclaimreclaimticketextendrelinquish \ No newline at end of file diff --git a/fabric_cf/orchestrator/openapi.json b/fabric_cf/orchestrator/openapi.json index 5eb1610d..0e2908a9 100644 --- a/fabric_cf/orchestrator/openapi.json +++ b/fabric_cf/orchestrator/openapi.json @@ -704,7 +704,8 @@ "enum": [ "GRAPHML", "JSON_NODELINK", - "CYTOSCAPE" + "CYTOSCAPE", + "NONE" ] } } diff --git a/fabric_cf/orchestrator/swagger_server/response/resources_controller.py b/fabric_cf/orchestrator/swagger_server/response/resources_controller.py index d2749c16..d6a8b759 100644 --- a/fabric_cf/orchestrator/swagger_server/response/resources_controller.py +++ b/fabric_cf/orchestrator/swagger_server/response/resources_controller.py @@ -23,6 +23,8 @@ # # # Author: Komal Thareja (kthare10@renci.org) +from datetime import timedelta, datetime, timezone +from http.client import BAD_REQUEST from fabric_cf.orchestrator.core.exceptions import OrchestratorException from fabric_cf.orchestrator.core.orchestrator_handler import OrchestratorHandler @@ -62,6 +64,20 @@ def portalresources_get(graph_format: str, level: int = 1, force_refresh: bool = try: start = handler.validate_lease_time(lease_time=start_date) end = handler.validate_lease_time(lease_time=end_date) + + # Check if 'start' is defined but 'end' is not + if start and not end: + now = datetime.now(timezone.utc) + + # Check if the current time is within 10 minutes from 'start' + if now - start < timedelta(minutes=10): + # Reset start to None so as the cache is used + start = None + + if start and end and (end - start) < timedelta(minutes=60): + raise OrchestratorException(http_error_code=BAD_REQUEST, + message="Time range should be at least 60 minutes long!") + model = handler.list_resources(graph_format_str=graph_format, level=level, force_refresh=force_refresh, start=start, end=end, includes=includes, excludes=excludes, authorize=False) response = Resources() @@ -108,6 +124,20 @@ def resources_get(level: int = 1, force_refresh: bool = False, start_date: str = token = get_token() start = handler.validate_lease_time(lease_time=start_date) end = handler.validate_lease_time(lease_time=end_date) + + # Check if 'start' is defined but 'end' is not + if start and not end: + now = datetime.now(timezone.utc) + + # Check if the current time is within 10 minutes from 'start' + if now - start < timedelta(minutes=10): + # Reset start to None so as the cache is used + start = None + + if start and end and (end - start) < timedelta(minutes=60): + raise OrchestratorException(http_error_code=BAD_REQUEST, + message="Time range should be at least 60 minutes long!") + model = handler.list_resources(token=token, level=level, force_refresh=force_refresh, start=start, end=end, includes=includes, excludes=excludes) response = Resources() diff --git a/fabric_cf/orchestrator/swagger_server/response/slices_controller.py b/fabric_cf/orchestrator/swagger_server/response/slices_controller.py index 4abd9104..b8ebd37b 100644 --- a/fabric_cf/orchestrator/swagger_server/response/slices_controller.py +++ b/fabric_cf/orchestrator/swagger_server/response/slices_controller.py @@ -23,6 +23,8 @@ # # # Author: Komal Thareja (kthare10@renci.org) +from datetime import timedelta +from http.client import BAD_REQUEST from typing import List from fabric_cf.orchestrator.core.exceptions import OrchestratorException @@ -70,6 +72,10 @@ def slices_create_post(body: SlicesPost, name: str, lease_start_time: str = None ssh_key = ','.join(body.ssh_keys) start = handler.validate_lease_time(lease_time=lease_start_time) end = handler.validate_lease_time(lease_time=lease_end_time) + if start and end and (end - start) < timedelta(minutes=60): + raise OrchestratorException(http_error_code=BAD_REQUEST, + message="Requested Lease should be at least 60 minutes long!") + slivers_dict = handler.create_slice(token=token, slice_name=name, slice_graph=body.graph_model, lease_start_time=start, lease_end_time=end, ssh_key=ssh_key) diff --git a/fabric_cf/orchestrator/swagger_server/swagger/swagger.yaml b/fabric_cf/orchestrator/swagger_server/swagger/swagger.yaml index 687ef854..0bb28f86 100644 --- a/fabric_cf/orchestrator/swagger_server/swagger/swagger.yaml +++ b/fabric_cf/orchestrator/swagger_server/swagger/swagger.yaml @@ -230,6 +230,7 @@ paths: - GRAPHML - JSON_NODELINK - CYTOSCAPE + - NONE default: GRAPHML - name: level in: query @@ -492,6 +493,7 @@ paths: - GRAPHML - JSON_NODELINK - CYTOSCAPE + - NONE default: GRAPHML responses: "200": diff --git a/tools/audit.py b/tools/audit.py index a4f58559..5b78508e 100644 --- a/tools/audit.py +++ b/tools/audit.py @@ -240,6 +240,30 @@ def execute_ansible(self, *, inventory_path: str, playbook_path: str, extra_vars ansible_helper.run_playbook(playbook_path=playbook_path, private_key_file=private_key_file, user=user) return ansible_helper.get_result_callback() + def clean_sliver_close_fail(self): + try: + actor_type = self.actor_config[Constants.TYPE] + if actor_type.lower() != ActorType.Broker.name.lower(): + return + actor_db = ActorDatabase(user=self.database_config[Constants.PROPERTY_CONF_DB_USER], + password=self.database_config[Constants.PROPERTY_CONF_DB_PASSWORD], + database=self.database_config[Constants.PROPERTY_CONF_DB_NAME], + db_host=self.database_config[Constants.PROPERTY_CONF_DB_HOST], + logger=self.logger) + + states = [ReservationStates.CloseFail.value] + slivers = actor_db.get_reservations(states=states) + for s in slivers: + term = s.get_term() + end = term.get_end_time() if term else None + now = datetime.now(timezone.utc) + if end and end <= now: + actor_db.remove_reservation(rid=s.get_reservation_id()) + + except Exception as e: + self.logger.error(f"Failed to cleanup inconsistencies: {e}") + self.logger.error(traceback.format_exc()) + def clean_sliver_inconsistencies(self): try: actor_type = self.actor_config[Constants.TYPE] @@ -371,6 +395,7 @@ def handle_command(self, args): # Close operation if args.operation is not None and args.operation == "audit": self.delete_dead_closing_slice(days=args.days) + self.clean_sliver_close_fail() self.clean_sliver_inconsistencies() else: print(f"Unsupported operation: {args.operation}") diff --git a/tools/db_cli.py b/tools/db_cli.py index 2288b98c..9ef15467 100644 --- a/tools/db_cli.py +++ b/tools/db_cli.py @@ -94,6 +94,10 @@ def get_slice_topology(self, graph_id: str): logger=self.logger) slice_model = Neo4jPropertyGraph(graph_id=graph_id, importer=neo4j_graph_importer) + slice_model_str = slice_model.serialize_graph() + + with open("slice_model_str.txt", "w") as file: + file.write(slice_model_str) print(f"Slice Model: {slice_model}") except Exception as e: @@ -151,9 +155,13 @@ def get_reservations(self, slice_id: str = None, res_id: str = None, email: str if res_list is not None and len(res_list) > 0: for r in res_list: print(r) + print(type(r)) print(f"RES Sliver: {r.get_resources().get_sliver()}") print(f"REQ RES Sliver: {r.get_requested_resources()} {r.get_requested_resources().get_sliver()}") print(f"APPR RES Sliver: {r.get_approved_resources()} {r.get_approved_resources().get_sliver()}") + from fabric_cf.actor.core.kernel.reservation_client import ReservationClient + if isinstance(r, ReservationClient): + print(r.get_leased_resources().get_sliver()) print() else: print(f"No reservations found: {res_list}")