diff --git a/manifests/netphony-external-service.yaml b/manifests/netphony-external-service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..43356c533843de1fdf329eb95b2559f5e696f796 --- /dev/null +++ b/manifests/netphony-external-service.yaml @@ -0,0 +1,101 @@ +# apiVersion: v1 +# kind: Service +# metadata: +# name: netphony-service +# spec: +# type: LoadBalancer # Cambia a NodePort o ClusterIP según la necesidad +# selector: +# app: netphony +# loadBalancerIP: 10.0.2.150 # Ajusta según la configuración de MetalLB o tu entorno +# ports: +# - name: grpc +# port: 4189 # Puerto externo accesible +# targetPort: 4189 # Puerto donde escucha Netphony-PCE en el pod +# protocol: TCP +# --- +# apiVersion: apps/v1 +# kind: Deployment +# metadata: +# name: netphony-deployment +# spec: +# replicas: 1 +# selector: +# matchLabels: +# app: netphony +# template: +# metadata: +# labels: +# app: netphony +# spec: +# containers: +# - name: netphony +# image: <tu-imagen-netphony> # Reemplaza con la imagen correcta +# ports: +# - containerPort: 4189 +# apiVersion: v1 +# kind: Service +# metadata: +# name: netphony-external-service +# spec: +# type: ClusterIP +# ports: +# - port: 4189 +# targetPort: 4189 +# protocol: TCP +# --- +# apiVersion: v1 +# kind: Endpoints +# metadata: +# name: netphony-external-service +# subsets: +# - addresses: +# - ip: 192.168.1.100 # IP de VM A +# ports: +# - port: 4189 +apiVersion: v1 +kind: Service +metadata: + name: netphony-external-service +spec: + type: ClusterIP + ports: + - name: grpc + protocol: TCP + port: 20050 + targetPort: 20050 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 + - name: pcep + protocol: TCP + port: 4189 + targetPort: 4189 + - name: managm + protocol: TCP + port: 6666 + targetPort: 6666 + - name: grpcnetphony + protocol: TCP + port: 10060 + targetPort: 10060 +--- +apiVersion: v1 +kind: Endpoints +metadata: + name: netphony-external-service +subsets: + - addresses: + - ip: 192.168.159.225 # IP de la VM donde está Netphony + ports: + - name: grpc + port: 20050 + - name: metrics + port: 9192 + - name: pcep + port: 4189 + - name: managm + port: 6666 + - name: grpcnetphony + port: 10060 + diff --git a/manifests/pcepservice.yaml b/manifests/pcepservice.yaml index 32848974616ca2afd2c2b78b4998cd9ca41cb0f7..05f23c843838c43052ced66b9150992f06b90511 100644 --- a/manifests/pcepservice.yaml +++ b/manifests/pcepservice.yaml @@ -43,6 +43,8 @@ spec: env: - name: LOG_LEVEL value: "DEBUG" + # - name: CRDB_DATABASE + # value: "tfs_pcep" envFrom: - secretRef: name: crdb-lsp-data @@ -67,11 +69,11 @@ metadata: labels: app: pcepservice spec: - type: LoadBalancer - externalTrafficPolicy: Local + type: ClusterIP + # externalTrafficPolicy: Local selector: app: pcepservice - loadBalancerIP: 192.168.159.65 + # loadBalancerIP: 192.168.159.65 ports: - name: grpc protocol: TCP diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml index 19317323f2a60293a33d740b28b3795627846642..6187b682f823b0bdeaf5ba086d8d551603ba80c5 100644 --- a/manifests/webuiservice.yaml +++ b/manifests/webuiservice.yaml @@ -39,9 +39,21 @@ spec: - containerPort: 8004 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" - name: WEBUISERVICE_SERVICE_BASEURL_HTTP value: "/webui/" + - name: CRDB_NAMESPACE + value: "crdb" + - name: CRDB_SQL_PORT + value: "26257" + - name: CRDB_DATABASE_LSP_MGMT + value: "tfs_lsp_mgmt" + - name: CRDB_USERNAME + value: "tfs" + - name: CRDB_PASSWORD + value: "tfs123" + - name: CRDB_SSLMODE + value: "require" readinessProbe: httpGet: path: /healthz/ready diff --git a/proto/pcep.proto b/proto/pcep.proto index 0801c02bd9bc60d4e9068beca5e1862671e6a24f..265cf47d0cd135f7ed91e2378b33d13d97577e69 100644 --- a/proto/pcep.proto +++ b/proto/pcep.proto @@ -20,18 +20,28 @@ import "context.proto"; service PcepService { - rpc sendRequest ( RequestRq ) returns ( RequestRp ) {} + rpc sendRequest ( RequestRq ) returns ( commandResponse ) {} rpc configuratePCE ( PceIpRq ) returns ( PceIpRp ) {} rpc getLSPdb (LSPdb_Request) returns (LSPdb_Response) {} - rpc SetLsp (LspDescriptor ) returns (LspID ) {} - rpc DeleteLsp (LspID ) returns (context.Empty ) {} - rpc GetLsp (LspID ) returns (LspDescriptor ) {} + rpc SetLsp (LspDescriptor ) returns (LspId ) {} + rpc DeleteLsp (LspId ) returns (context.Empty ) {} + rpc GetLsp (LspId ) returns (LspDescriptor ) {} // RPC method for retrieving LSP database rpc getSessionsInfo(Session_Request) returns (Session_Response); } +// Command request from the client +message commandRequest{ + string command = 1; +} + +// Response after a Command Request (If bad request show error log) +message commandResponse{ + bool success = 1; + string error_message = 2; +} message RequestRq { string command = 1; @@ -52,26 +62,16 @@ message PceIpRp{ } -message LspID { - context.Uuid lsp_id = 1; +message LspId { + context.Uuid lsp_uuid = 1; } message LspDescriptor { - LspID lsp_id = 1; // ID del LSP - bool delegate_flag = 2; // Delegate Flag - bool sync_flag = 3; // Sync Flag - bool remove_flag = 4; // Remove Flag - bool administrative_flag = 5; // Administrative Flag - int32 op_flags = 6; // Operational Flags - bool create_flag = 7; // Create Flag - bool p2mp_flag = 8; // P2MP Flag - bool fragmentation_flag = 9; // Fragmentation Flag - bool ero_compression_flag = 10; // ERO Compression Flag - string symbolic_path_name_tlv = 11; // Symbolic Path Name TLV - string lsp_identifiers_tlv = 12; // LSP Identifiers TLV - string lsp_error_codes_tlv = 13; // LSP Error Codes TLV - string rsvp_error_spec_tlv = 14; // RSVP Error Spec TLV - string lsp_db_version_tlv = 15; // LSP DB Version TLV + LspId lsp_id = 1; // ID del LSP (UUID en formato string) + string srp = 2; // SRP + string lsp = 3; // LSP (almacenado como JSON, en formato string) + string path = 4; // Path (almacenado como JSON, en formato string) + string associationlist = 5; // Lista de asociaciones (almacenada como JSON, en formato string) } // LSP database request from the client diff --git a/quick_deploy.sh b/quick_deploy.sh index 634d5df955a401aba0167951f6627b4a364a7060..17d06e8fdb55608233d9a95c55c1b55d58a3dd46 100755 --- a/quick_deploy.sh +++ b/quick_deploy.sh @@ -27,7 +27,7 @@ export TFS_REGISTRY_IMAGES=${TFS_REGISTRY_IMAGES:-"http://localhost:32000/tfs/"} # If not already set, set the list of components, separated by spaces, you want to build images for, and deploy. # By default, only basic components are deployed -export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice nbi webui load_generator pcep"} +export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice nbi webui pcep"} # If not already set, set the tag you want to use for your images. export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"} @@ -47,7 +47,7 @@ export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-"YES"} # If TFS_SKIP_BUILD is "YES", select the containers to be build # Any other container will use previous docker images -export TFS_QUICK_COMPONENTS="pcep webui" +export TFS_QUICK_COMPONENTS="webui" # ----- CockroachDB ------------------------------------------------------------ diff --git a/src/pcep/Dockerfile b/src/pcep/Dockerfile index c4f4c2ea923e3fdcc7e2d9d44b6407375659032a..6b6d92cc5e2e6c2eebaa66bc84a3d35e0989dded 100644 --- a/src/pcep/Dockerfile +++ b/src/pcep/Dockerfile @@ -72,10 +72,10 @@ RUN python3 -m pip install -r requirements.txt # # Install Kubernetes Python client # RUN python3 -m pip install kubernetes -# Java module necessary config files -WORKDIR /var/teraflow/pcep -RUN mkdir -p /resources -COPY src/pcep/service/resources/. resources/ +# # Java module necessary config files +# WORKDIR /var/teraflow/pcep +# RUN mkdir -p /resources +# COPY src/pcep/service/resources/. resources/ # Add the Tools Module WORKDIR /var/teraflow/pcep diff --git a/src/pcep/client/PcepClient.py b/src/pcep/client/PcepClient.py index 2932fef2c513db3d9274a21f67a2ff35b3872f63..967a7c5e73d9e71cbb10a4b28841aac7821c1408 100644 --- a/src/pcep/client/PcepClient.py +++ b/src/pcep/client/PcepClient.py @@ -17,15 +17,15 @@ from common.Constants import ServiceNameEnum from common.Settings import get_service_host, get_service_port_grpc from common.proto.context_pb2 import Empty, Service, ServiceId from common.proto.pcep_pb2_grpc import PcepServiceStub -from common.proto.pcep_pb2 import RequestRq, RequestRp, PceIpRq, PceIpRp, LSPdb_Response, LSPdb_Request +from common.proto.pcep_pb2 import RequestRq, RequestRp, PceIpRq, PceIpRp, LSPdb_Response, LSPdb_Request, commandResponse from common.tools.client.RetryDecorator import retry, delay_exponential from common.tools.grpc.Tools import grpc_message_to_json_string from pcep.service.tools.protos.grpcService_pb2 import Session_Request, commandRequest from pcep.service.tools.protos.grpcService_pb2_grpc import pceServiceStub +from pcep.database.LSP_DB import LspDB -# from kubernetes import client, config LOGGER = logging.getLogger(__name__) MAX_RETRIES = 15 @@ -45,11 +45,17 @@ class PcepClient: # if not port: port = port = PcepClient.get_loadbalancer_port('pcepservice', namespace='tfs', target_port_name='grpc') self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) - LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) + LOGGER.info('Creating channel to {:s}...'.format(str(self.endpoint))) self.channel = None self.stub = None self.connect() - LOGGER.debug('Channel created') + LOGGER.info('Channel created') + + # # # Inicializamos LspDB para acceder a la base de datos + # self.lsp_db = LspDB() + # self.lsp_db.create_database() + # self.lsp_db.create_tables() + # self.lsp_db.verify_tables() def connect(self): LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) @@ -63,38 +69,12 @@ class PcepClient: self.channel = None self.stub = None - # @staticmethod - # def get_loadbalancer_ip(service_name, namespace='tfs'): - # config.load_kube_config() # Cargar configuración de kubeconfig - # v1 = client.CoreV1Api() - # service = v1.read_namespaced_service(service_name, namespace) - # return service.status.load_balancer.ingress[0].ip - # @staticmethod - # def get_loadbalancer_port(service_name, namespace='tfs', target_port_name=None): - # """Obtiene el puerto del LoadBalancer de un servicio en Kubernetes.""" - # config.load_kube_config() - # v1 = client.CoreV1Api() - # service = v1.read_namespaced_service(service_name, namespace) - # # Extraer el puerto de la especificación - # ports = service.spec.ports - # if not ports: - # raise RuntimeError(f"No ports defined for service {service_name}") - - # # Si se especifica un target_port_name, buscarlo - # if target_port_name: - # for port in ports: - # if port.name == target_port_name: - # return port.port # Devuelve el puerto externo - # raise RuntimeError(f"No port found with name {target_port_name} in service {service_name}") - - # # Si no se especifica, devuelve el primer puerto - # return ports[0].port @RETRY_DECORATOR - def sendRequest(self, request : RequestRq) -> RequestRp: + def sendRequest(self, request : RequestRq) -> commandResponse: LOGGER.debug('Send request: {:s}'.format(grpc_message_to_json_string(request))) response = self.stub.sendRequest(request) LOGGER.debug('Send request result: {:s}'.format(grpc_message_to_json_string(response))) @@ -119,13 +99,28 @@ class PcepClient: # # responselsp = self.stub.getLSPdb(request) # LOGGER.warning("IAM IN SHOWLSP: {:s}".format(str(responselsp))) # return responselsp + @RETRY_DECORATOR def showLSPDB(self): - LOGGER.debug("Showing the LSP Paths in the PCE") - requestlsp = LSPdb_Request() - responselsp = self.stub.getLSPdb(requestlsp) - LOGGER.warning("IAM IN SHOWLSP: {:s}".format(str(responselsp))) - return responselsp + """Método para mostrar los LSP Paths desde la base de datos""" + LOGGER.debug("Showing the LSP Paths from the database") + # Llamamos a LspDB para obtener la lista de LSPs + try: + lsp_info = LspDB.show_lsp_db() + LOGGER.info(f"Información de LSPs: {lsp_info}") + return lsp_info + except Exception as e: + LOGGER.error(f"Error al obtener la información de LSP desde la base de datos: {str(e)}") + return None + + #EL BUENO + # @RETRY_DECORATOR + # def showLSPDB(self): + # LOGGER.debug("Showing the LSP Paths in the PCE") + # requestlsp = LSPdb_Request() + # responselsp = self.stub.getLSPdb(requestlsp) + # LOGGER.warning("IAM IN SHOWLSP: {:s}".format(str(responselsp))) + # return responselsp @RETRY_DECORATOR def showSessions(self): @@ -154,5 +149,33 @@ class PcepClient: LOGGER.warning("Error Message: %s", str(commandresponse.error_message)) return commandresponse + + # @staticmethod + # def get_loadbalancer_ip(service_name, namespace='tfs'): + # config.load_kube_config() # Cargar configuración de kubeconfig + # v1 = client.CoreV1Api() + # service = v1.read_namespaced_service(service_name, namespace) + # return service.status.load_balancer.ingress[0].ip + + # @staticmethod + # def get_loadbalancer_port(service_name, namespace='tfs', target_port_name=None): + # """Obtiene el puerto del LoadBalancer de un servicio en Kubernetes.""" + # config.load_kube_config() + # v1 = client.CoreV1Api() + # service = v1.read_namespaced_service(service_name, namespace) + # # Extraer el puerto de la especificación + # ports = service.spec.ports + # if not ports: + # raise RuntimeError(f"No ports defined for service {service_name}") + + # # Si se especifica un target_port_name, buscarlo + # if target_port_name: + # for port in ports: + # if port.name == target_port_name: + # return port.port # Devuelve el puerto externo + # raise RuntimeError(f"No port found with name {target_port_name} in service {service_name}") + + # # Si no se especifica, devuelve el primer puerto + # return ports[0].port diff --git a/src/pcep/database/LSPEngine.py b/src/pcep/database/LSPEngine.py index 9d69683adcec9cd82e626e864d297b2d0cbdcf0f..cc54b07b6ecfe42cdecf9d1265cfa38913b45a3e 100644 --- a/src/pcep/database/LSPEngine.py +++ b/src/pcep/database/LSPEngine.py @@ -20,7 +20,7 @@ class LSPEngine: CRDB_USERNAME, CRDB_PASSWORD, CRDB_NAMESPACE, CRDB_SQL_PORT, CRDB_DATABASE_LSP_MGMT, CRDB_SSLMODE) try: engine = sqlalchemy.create_engine(crdb_uri, echo=False) - LOGGER.info(' KpiDBmanager initalized with DB URL: {:}'.format(crdb_uri)) + LOGGER.info(' LspDB initalized with DB URL: {:}'.format(crdb_uri)) except: # pylint: disable=bare-except # pragma: no cover LOGGER.exception('Failed to connect to database: {:s}'.format(str(crdb_uri))) return None # type: ignore diff --git a/src/pcep/database/LSPModel.py b/src/pcep/database/LSPModel.py index d56d03bf6693f491b0177ec34fa6a5b34aee3306..eb94db9f42cae982dc054074505212d0657c2728 100644 --- a/src/pcep/database/LSPModel.py +++ b/src/pcep/database/LSPModel.py @@ -1,7 +1,7 @@ import logging from sqlalchemy.dialects.postgresql import UUID from sqlalchemy import Column, Integer, String, Text, Boolean -from sqlalchemy.orm import registry +from sqlalchemy.orm import registry, Session from common.proto.pcep_pb2 import LspDescriptor import uuid @@ -11,35 +11,36 @@ LOGGER = logging.getLogger(__name__) # Base para los modelos declarativos Base = registry().generate_base() - class LspModel(Base): __tablename__ = 'lsp' - lsp_id = Column(UUID(as_uuid=True), primary_key=True) # Cambiado a as_uuid=True - delegate_flag = Column(Boolean, nullable=False) - sync_flag = Column(Boolean, nullable=False) - remove_flag = Column(Boolean, nullable=False) - administrative_flag = Column(Boolean, nullable=False) - op_flags = Column(Integer, nullable=False) - create_flag = Column(Boolean, nullable=False) - p2mp_flag = Column(Boolean, nullable=False) - fragmentation_flag = Column(Boolean, nullable=False) - ero_compression_flag = Column(Boolean, nullable=False) - symbolic_path_name_tlv = Column(Text, nullable=True) - lsp_identifiers_tlv = Column(Text, nullable=True) - lsp_error_codes_tlv = Column(Text, nullable=True) - rsvp_error_spec_tlv = Column(Text, nullable=True) - lsp_db_version_tlv = Column(Text, nullable=True) + lsp_uuid = Column(UUID(as_uuid=True), primary_key=True) + srp = Column(Text, nullable=True) # Puede ser null + lsp = Column(Text, nullable=True) # Se almacena en JSON + path = Column(Text, nullable=True) # Se almacena en JSON + associationlist = Column(Text, nullable=True) # Se almacena en JSON def __repr__(self): - return (f"<Lsp(lsp_id='{self.lsp_id}', delegate_flag='{self.delegate_flag}', " - f"sync_flag='{self.sync_flag}', remove_flag='{self.remove_flag}', " - f"administrative_flag='{self.administrative_flag}', op_flags='{self.op_flags}', " - f"create_flag='{self.create_flag}', p2mp_flag='{self.p2mp_flag}', " - f"fragmentation_flag='{self.fragmentation_flag}', ero_compression_flag='{self.ero_compression_flag}', " - f"symbolic_path_name_tlv='{self.symbolic_path_name_tlv}', lsp_identifiers_tlv='{self.lsp_identifiers_tlv}', " - f"lsp_error_codes_tlv='{self.lsp_error_codes_tlv}', rsvp_error_spec_tlv='{self.rsvp_error_spec_tlv}', " - f"lsp_db_version_tlv='{self.lsp_db_version_tlv}')>") + return (f"<Lsp(lsp_uuid='{self.lsp_uuid}', srp='{self.srp}', lsp='{self.lsp}', " + f"path='{self.path}', associationlist='{self.associationlist}')>") + + @staticmethod + def get_all_columns(): + return LspModel.__table__.columns.keys() + + # @staticmethod + # def get_all_data(): + # """Ejecuta 'SELECT * FROM lsp' y devuelve los resultados.""" + # session = Session() + # try: + # result = session.execute(text("SELECT * FROM lsp")) # Ejecuta la consulta SQL pura + # rows = result.fetchall() # Obtiene todas las filas + # session.close() + # return rows # Devuelve una lista de tuplas con los datos + # except Exception as e: + # session.rollback() + # LOGGER.error(f"Error al obtener los datos de la base de datos: {e}") + # return None @classmethod def convert_LspDescriptor_to_row(cls, request): @@ -53,21 +54,11 @@ class LspModel(Base): An instance of Lsp initialized with data from the request. """ return cls( - lsp_id = uuid.UUID(request.lsp_id.lsp_id.uuid), # Convertir a UUID de la request - delegate_flag = request.delegate_flag, - sync_flag = request.sync_flag, - remove_flag = request.remove_flag, - administrative_flag = request.administrative_flag, - op_flags = request.op_flags, - create_flag = request.create_flag, - p2mp_flag = request.p2mp_flag, - fragmentation_flag = request.fragmentation_flag, - ero_compression_flag = request.ero_compression_flag, - symbolic_path_name_tlv = request.symbolic_path_name_tlv, - lsp_identifiers_tlv = request.lsp_identifiers_tlv, - lsp_error_codes_tlv = request.lsp_error_codes_tlv, - rsvp_error_spec_tlv = request.rsvp_error_spec_tlv, - lsp_db_version_tlv = request.lsp_db_version_tlv + lsp_uuid = uuid.UUID(request.lsp_uuid), # Convertir a UUID de la request + srp = request.srp, + lsp = request.lsp, + path = request.path, + associationlist = request.associationlist ) @classmethod @@ -82,19 +73,9 @@ class LspModel(Base): LspDescriptor object """ response = LspDescriptor() - response.lsp_id = str(row.lsp_id) # Si lsp_id es UUID, convertir a string - response.delegate_flag = row.delegate_flag - response.sync_flag = row.sync_flag - response.remove_flag = row.remove_flag - response.administrative_flag = row.administrative_flag - response.op_flags = row.op_flags - response.create_flag = row.create_flag - response.p2mp_flag = row.p2mp_flag - response.fragmentation_flag = row.fragmentation_flag - response.ero_compression_flag = row.ero_compression_flag - response.symbolic_path_name_tlv = row.symbolic_path_name_tlv - response.lsp_identifiers_tlv = row.lsp_identifiers_tlv - response.lsp_error_codes_tlv = row.lsp_error_codes_tlv - response.rsvp_error_spec_tlv = row.rsvp_error_spec_tlv - response.lsp_db_version_tlv = row.lsp_db_version_tlv + response.lsp_uuid = str(row.lsp_uuid) # Si lsp_uuid es UUID, convertir a string + response.srp = row.srp + response.lsp = row.lsp + response.path = row.path + response.associationlist = row.associationlist return response diff --git a/src/pcep/database/LSP_DB.py b/src/pcep/database/LSP_DB.py index ce9414b625a9d467cc13140f48ba5c22b4cd2d80..63926a5a39d0547ef629f6cccb2741ac95940bbc 100644 --- a/src/pcep/database/LSP_DB.py +++ b/src/pcep/database/LSP_DB.py @@ -1,4 +1,5 @@ import logging +from sqlalchemy import inspect import sqlalchemy_utils from sqlalchemy.orm import sessionmaker from pcep.database.LSPEngine import LSPEngine @@ -22,7 +23,7 @@ class LspDB: def create_database(self) -> None: if not sqlalchemy_utils.database_exists(self.db_engine.url): sqlalchemy_utils.create_database(self.db_engine.url) - LOGGER.debug("Database created. {:}".format(self.db_engine.url)) + LOGGER.info("Database created. {:}".format(self.db_engine.url)) def drop_database(self) -> None: if sqlalchemy_utils.database_exists(self.db_engine.url): @@ -31,7 +32,7 @@ class LspDB: def create_tables(self): try: LspModel.metadata.create_all(self.db_engine) # type: ignore - LOGGER.debug("Tables created in the DB Name: {:}".format(self.db_name)) + LOGGER.info("Tables created in the DB Name: {:}".format(self.db_name)) except Exception as e: LOGGER.debug("Tables cannot be created in the lsp database. {:s}".format(str(e))) raise OperationFailedException ("Tables can't be created", extra_details=["unable to create table {:}".format(e)]) @@ -123,3 +124,58 @@ class LspDB: raise OperationFailedException ("Select by filter", extra_details=["unable to apply the filter {:}".format(e)]) finally: session.close() + from sqlalchemy import asc, desc + + @staticmethod + def select_all_as_dict(self): + session = self.Session() + try: + query = session.query(LspModel) + rows = query.all() + + # Obtenemos los nombres de las columnas + columns = [column.name for column in LspModel.__table__.columns] + + # Convertimos las filas en diccionarios usando los nombres de las columnas + result = [dict(zip(columns, row)) for row in rows] + + if result: + LOGGER.debug(f"Fetched all rows from {LspModel.__name__} table as dict.") + else: + LOGGER.debug(f"No rows found in {LspModel.__name__} table.") + + return result + + except Exception as e: + LOGGER.error(f"Error fetching rows from {LspModel.__name__} table: {e}") + raise OperationFailedException("Select all", extra_details=["unable to fetch all rows {:}".format(e)]) + finally: + session.close() + @staticmethod + def get_all_columns(): + """Obtiene todos los nombres de las columnas de la tabla 'lsp'.""" + try: + # Usamos el inspeccionador de SQLAlchemy para obtener la información de la tabla + inspector = inspect(LSPEngine.get_engine()) + columns = inspector.get_columns('lsp') + + column_names = [column['name'] for column in columns] # Extraemos solo los nombres de las columnas + return column_names + + except Exception as e: + LOGGER.error(f"Error al obtener las columnas de la tabla 'lsp': {str(e)}") + return None + @staticmethod + def show_lsp_db(): + """Método estático para obtener los LSP Paths desde la base de datos""" + db_engine = LSPEngine.get_engine() + if db_engine is None: + LOGGER.error("No database engine available.") + return None + try: + lsp_info = db_engine.execute("SELECT * FROM lsp").fetchall() + LOGGER.info(f"Información de LSPs: {lsp_info}") + return lsp_info + except Exception as e: + LOGGER.error(f"Error al obtener la información de LSP desde la base de datos: {str(e)}") + return None \ No newline at end of file diff --git a/src/pcep/database/test_variables.py b/src/pcep/database/test_variables.py index b8a5a0999ea2e4edd8c8820347ba39c9340a9ee7..aed46cb3b106739dd8aa8a458bb36d5f8d0db666 100644 --- a/src/pcep/database/test_variables.py +++ b/src/pcep/database/test_variables.py @@ -1,10 +1,41 @@ import os +import unittest +from sqlalchemy.orm import sessionmaker +from pcep.database.LSP_DB import LspDB, LspModel -key = 'CRDB_NAMESPACE' -value = os.environ.get(key) +# Establecer la variable de entorno dentro de las pruebas +os.environ['CRDB_SQL_PORT'] = '26257' # Establece el puerto SQL necesario +os.environ['CRDB_SSLMODE'] = 'require' -if value is None: - print(f"{key} no está configurada en el entorno.") -else: - print(f"{key}: {value}") +class TestLspDatabase(unittest.TestCase): + @classmethod + def setUpClass(cls): + """ + Esta función se ejecuta una vez antes de todas las pruebas. + Aquà se puede configurar la base de datos. + """ + cls.db = LspDB() # Se conecta a la base de datos real + + # Crear la base de datos y las tablas si es necesario + cls.db.create_database() # Crea la base de datos si no existe + cls.db.create_tables() # Crea las tablas necesarias + + + def test_select_all_lsp(self): + """ + Realiza una prueba de selección de todos los registros de la tabla 'lsp'. + """ + session = self.db.Session() + try: + # Ejecutar la consulta SQL directamente + result = session.execute("SELECT * FROM lsp").fetchall() + print(result) # Para ver los resultados en la consola + self.assertIsInstance(result, list) # Asegura que el resultado es una lista + self.assertGreater(len(result), 0) # Asegura que hay al menos un registro + finally: + session.close() # Cierra la sesión + +# Ejecutar las pruebas +if __name__ == '__main__': + unittest.main() diff --git a/src/pcep/service/PcepService.py b/src/pcep/service/PcepService.py index 04b8702d3ed7bd8697490d61c4333e32feac3d76..c0d3052293acbf887b4923748e795316204239f7 100644 --- a/src/pcep/service/PcepService.py +++ b/src/pcep/service/PcepService.py @@ -38,3 +38,20 @@ class PcepService(GenericGrpcService): def install_servicers(self): add_PcepServiceServicer_to_server(self.pcep_servicer, self.server) + +# class PcepService(GenericGrpcService): +# def __init__(self, pcepServer: GrpcServer, cls_name: str = __name__) -> None: +# # Direcciones y puerto fijos +# host = '192.168.159.225' # Dirección IP fija +# port = '10060' # Puerto fijo + +# LOGGER.debug(f'HOST... (PCEP Service): {host}') +# LOGGER.debug(f'PORT... (PCEP Service): {port}') + +# # Llamada al constructor de la clase base, pasando el host y el puerto directamente +# super().__init__(port, cls_name=cls_name) +# self.pcep_servicer = PcepServiceServicerImpl(pcepServer) +# LOGGER.debug('Creating Servicer... (PCEP Service)') + +# def install_servicers(self): +# add_PcepServiceServicer_to_server(self.pcep_servicer, self.server) \ No newline at end of file diff --git a/src/pcep/service/PcepServiceServicerImpl.py b/src/pcep/service/PcepServiceServicerImpl.py index b0db895f9bdfea4f5ff327e003259f5ebc3a2b2a..af7036a6fbe2f9774ca9e30305ac6984f6b09acc 100644 --- a/src/pcep/service/PcepServiceServicerImpl.py +++ b/src/pcep/service/PcepServiceServicerImpl.py @@ -17,11 +17,10 @@ from common.proto.context_pb2 import Empty from pcep.service.tools.GrpcServer import GrpcServer from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from common.proto.pcep_pb2 import RequestRq, RequestRp, PceIpRq, PceIpRp, LSPdb_Request, LSPdb_Response, \ - Session_Request, Session_Response, LspID, LspDescriptor + Session_Request, Session_Response, LspId, LspDescriptor, commandResponse from common.proto.pcep_pb2_grpc import PcepServiceServicer -from pcep.database.LSP_DB import LspDB -from pcep.database.LSPModel import LspModel +# from pcep.database.LSP_DB import LspDB LOGGER = logging.getLogger(__name__) @@ -32,29 +31,27 @@ class PcepServiceServicerImpl(PcepServiceServicer): LOGGER.debug('Creating Servicer...') self.pcepServer=pcepServer LOGGER.debug('Servicer Created') - LOGGER.info("Init LSP Database service") - self.lsp_db_obj = LspDB() - @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def configuratePCE(self, request : PceIpRq, context : grpc.ServicerContext) -> PceIpRp: LOGGER.debug("(ConfiguratePCE) Create pce instance %s",request) - configurateIP=self.pcepServer.connectToJavaPcep(request.address) + # configurateIP=self.pcepServer.connectToJavaPcep(request.address) #return PceIpRp(addressRp=configurateIP) return PceIpRp(addressRp="10.95.90.150") @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) - def sendRequest(self, request : RequestRq, context : grpc.ServicerContext) -> RequestRp: + def sendRequest(self, request : RequestRq, context : grpc.ServicerContext) -> commandResponse: LOGGER.debug("(Send Request) Send: %s",request.command) - message=self.pcepServer.requestToJavaPcep(request.command) - return RequestRp(commandRp=message) + response =self.pcepServer.request_to_java(request.command) + return commandResponse(success=response.success, error_message=response.error_message) @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def getLSPdb(self, request: LSPdb_Request, context : grpc.ServicerContext) -> LSPdb_Response: LOGGER.debug("GET LSPDB") response = self.pcepServer.get_lspdb_from_java(request) return response + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def getSessionsInfo(self, request: Session_Request, context : grpc.ServicerContext) -> Session_Response: LOGGER.debug("GET SESSIONS INFO") diff --git a/src/pcep/service/__main__.py b/src/pcep/service/__main__.py index 91661a229d0305034a9fd53d9c0bf5768aa2364c..67065d1d6371efe879093c2609a40fd76d400c43 100644 --- a/src/pcep/service/__main__.py +++ b/src/pcep/service/__main__.py @@ -19,6 +19,9 @@ from .PcepService import PcepService from .tools.GrpcServer import GrpcServer import socket import subprocess +from pcep.database.LSP_DB import LspDB +# from pcep.database.LSPModel import LspModel +# from pcep.client.PcepClient import PcepClient @@ -51,28 +54,20 @@ def main(): pcep_server = GrpcServer() #Create instance of the GRPC Server # pcep_server.Connect() + LOGGER.info("Init LSP Database service") + lsp_db_obj = LspDB() + lsp_db_obj.create_database() + lsp_db_obj.create_tables() + lsp_db_obj.verify_tables() - - # def get_load_balancer_ip(): - # command = ["kubectl", "get", "svc", "pcepservice", "-n", "tfs", "-o", "jsonpath='{.status.loadBalancer.ingress[0].ip}'"] - # result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # if result.returncode == 0: - # return result.stdout.decode('utf-8').strip() - # else: - # return None - - - # ip_address = get_load_balancer_ip() - # - # service_name = "pcepservice.tfs.svc.cluster.local" - #ip_address = socket.gethostbyname(service_name) + # pcep_client = PcepClient() ip_address = socket.gethostbyname(socket.gethostname()) LOGGER.debug("IP address of the PCEP POD: %s", ip_address) LOGGER.debug(ip_address) - pcep_server.connectToJavaPcep(ip_address) + # pcep_server.connectToJavaPcep(ip_address) # Starting pcep service pcep_service = PcepService(pcep_server) diff --git a/src/pcep/service/resources/BGP4Parameters_2.xml b/src/pcep/service/resources/BGP4Parameters_2.xml deleted file mode 100644 index f59ea1f3bd1c3a91ff606bbac9c4d770ce8395a2..0000000000000000000000000000000000000000 --- a/src/pcep/service/resources/BGP4Parameters_2.xml +++ /dev/null @@ -1,66 +0,0 @@ - <!-- Copyright 2022-2024 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --> - - <?xml version="1.0" encoding="UTF-8"?> -<config> - <!-- TCP port where the BGP is listening for incoming bgp4 connections. Optional Parameter. Default value: 179 (BGP Port) --> - <BGP4Port>22179</BGP4Port> - <BGPIdentifier>1.1.1.1</BGPIdentifier> -<!-- TCP port to connect to manage the BGP connection. Default value: 1112 --> - <BGP4ManagementPort>1112</BGP4ManagementPort> - <!-- Peers to which this Peer is going to establish connection --> - <configPeer> - <peer>localhost</peer> - <export>false</export> - <import>true</import> - <peerPort>11179</peerPort> - </configPeer> - - <!-- Ficheros log (servidor, protocolo PCEP y OSPF). Campos opcionales--> - <BGP4LogFile>BGP4Parser2.log</BGP4LogFile><!-- Default value: BGP4Parser.log --> - <BGP4LogFileClient>BGP4Client2.log</BGP4LogFileClient><!-- Default value: BGP4Client.log--> - <BGP4LogFileServer>BGP4Server2.log</BGP4LogFileServer><!-- Default value: BGP4Server.log--> - <!-- If the tcp no delay option is used or not. Optional Parameter. Default value: false. --> - <nodelay>true</nodelay> - <!-- Waiting Time to re-connect to clients. Default value: 6000 ms. --> - <delay>40000</delay> - <setTraces>true</setTraces> - <!-- OPEN Parameters --> - <!-- RFC 4271. This 2-octet unsigned integer indicates the number of seconds the sender proposes for the value of the Hold Timer. - Upon receipt of an OPEN message, a BGP speaker MUST calculate the value of the Hold Timer by using the smaller of its configured - Hold Time and the Hold Time received in the OPEN message. The Hold Time MUST be either zero or at least three seconds. An - implementation MAY reject connections on the basis of the Hold Time. The calculated value indicates the maximum number of - seconds that may elapse between the receipt of successive KEEPALIVE and/or UPDATE messages from the sender. --> - <holdTime>180</holdTime><!-- Optional Parameter. Default value: 3. --> - <!-- RFC 4271. This 1-octet unsigned integer indicates the protocol version number of the message. The current BGP version number is 4. --> - <version>4</version><!-- Optional Parameter. Default value: 4. --> - <!-- RFC 4271. This 2-octet unsigned integer indicates the Autonomous System number of the sender.--> - <myAutonomousSystem>1</myAutonomousSystem> - <!-- RFC 4271. This 4-octet unsigned integer indicates the BGP Identifier of the sender. A given BGP speaker sets the value of its BGP - Identifier to an IP address that is assigned to that BGP speaker. The value of the BGP Identifier is determined upon - startup and is the same for every local interface and BGP peer. --> - <!--<BGPIdentifier>192.168.1.200</BGPIdentifier> --> - <!-- If the peer is in charge of sending its topology (only the interdomain Links) to the other BGP peer it is connected to. Default: false --> - <sendTopology>false</sendTopology> - <!-- If the peer is in charge of sending its whole topology to the other BGP peer it is connected to. Default: false --> - <sendIntradomainLinks>true</sendIntradomainLinks> - <!-- Optional Parameter. How to learn the topology. Possibilities: fromXML, fromBGP. Default: fromBGP --> - <learnTopology>fromBGP</learnTopology> - <!-- Topology network to read. It is mandatory if and only if learnTopology parameter is fromXML. --> - <!--<topologyFile>src/test/resources/network1.xml</topologyFile>--> - <!-- Optional Parameter. Instance Identifier for node and link NLRI. See rfc 6549. Default value: 0--> - <!--<instanceID>0</instanceID>--> - <!-- Optional Parameter. Default value: localhost --> - <localBGPAddress>0.0.0.0</localBGPAddress> -</config> diff --git a/src/pcep/service/resources/Ejecutable.jar b/src/pcep/service/resources/Ejecutable.jar deleted file mode 100644 index 52cd4230167f6e261fbec6384b2c975c9f696c09..0000000000000000000000000000000000000000 Binary files a/src/pcep/service/resources/Ejecutable.jar and /dev/null differ diff --git a/src/pcep/service/resources/PCE-jar-with-dependencies.jar b/src/pcep/service/resources/PCE-jar-with-dependencies.jar deleted file mode 100644 index 05de0a2f9e79188256b9e45af058320b04b7b732..0000000000000000000000000000000000000000 Binary files a/src/pcep/service/resources/PCE-jar-with-dependencies.jar and /dev/null differ diff --git a/src/pcep/service/resources/PCEServerConfiguration.xml b/src/pcep/service/resources/PCEServerConfiguration.xml deleted file mode 100644 index 44199cad75facdde9521ed05f72a2a3c76fdc0c1..0000000000000000000000000000000000000000 --- a/src/pcep/service/resources/PCEServerConfiguration.xml +++ /dev/null @@ -1,115 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<config> - <PCEServerPort>4189</PCEServerPort> - <PCEManagementPort>6666</PCEManagementPort> - <!--<LocalPCEAddress>192.168.1.200</LocalPCEAddress>--> - <!-- <LocalPCEAddress>127.0.0.1</LocalPCEAddress> --> - <!-- <LocalPCEAddress>192.168.165.172</LocalPCEAddress> --> - <!-- LocalPCEAddress>192.168.165.88</LocalPCEAddress>--> - <LocalPCEAddress>192.168.159.225</LocalPCEAddress> - - <ConnectTimer> - <!-- Connect: the timer (in seconds) started after having initialized a - TCP connection using the PCEP-registered TCP port. The value of - the Connect timer is 60 seconds. --> - 60 - </ConnectTimer> - <KeepAliveTimer> - 30 - </KeepAliveTimer> - <DeadTimer> - 120 - </DeadTimer> - <ConnectMaxRetry> - <!-- ConnectMaxRetry: the maximum number of times the system tries to - establish a TCP connection using the PCEP-registered TCP port - before going back to the Idle state. The value of the - ConnectMaxRetry is 5.--> - 5 - </ConnectMaxRetry> - <OpenWait> - <!-- OpenWait: the timer that corresponds to the amount of time a PCEP - peer will wait to receive an Open message from the PCEP peer after - the expiration of which the system releases the PCEP resource and - goes back to the Idle state. The OpenWait timer has a fixed value - of 60 seconds.--> - 60 - </OpenWait> - <KeepWait> - <!-- KeepWait: the timer that corresponds to the amount of time a PCEP - peer will wait to receive a Keepalive or a PCErr message from the - PCEP peer after the expiration of which the system releases the - PCEP resource and goes back to the Idle state. The KeepWait timer - has a fixed value of 60 seconds.--> - </KeepWait> - <parentPCE> - <!-- <parentPCEAddress>10.95.30.29</parentPCEAddress> --> - <!-- <parentPCEAddress>2.2.2.2</parentPCEAddress>--> - <!--<parentPCEAddress>10.95.30.29</parentPCEAddress> --> - <!--<parentPCEAddress>10.95.15.126</parentPCEAddress>--> - <!-- <parentPCEPort>4172</parentPCEPort> --> - </parentPCE> - <!-- Ficheros log (servidor, protocolo PCEP y OSPF). Campos opcionales --> - <PCEServerLogFile>PCEServer.log</PCEServerLogFile> - <PCEPParserLogFile>PCEPParserServer.log</PCEPParserLogFile> - <OSPFParserLogFile>OSPFParser.log</OSPFParserLogFile> - <isStateful>true</isStateful> - <isActive>true</isActive> - <PCCRequestsProcessors>1</PCCRequestsProcessors> - <ParentPCERequestProcessors>1</ParentPCERequestProcessors> - <!--<networkDescriptionFile>networks\Network_8_nodes.xml</networkDescriptionFile>--> - <!--<networkDescriptionFile>networks\network_NSFNet.xml</networkDescriptionFile>--> - <!--<networkDescriptionFile>/usr/local/nodeConfig/topologia.xml</networkDescriptionFile>--> - <networkDescriptionFile>/home/ubuntu/tfs-ctrl/src/pcep/service/resources/topologia_ifusion.xml</networkDescriptionFile> - - <actingAsBGP4Peer>false</actingAsBGP4Peer> - <BGP4File>BGP4Parameters_2.xml</BGP4File> - - <initialSessionID>1000</initialSessionID> - <nodelay>true</nodelay> - <reservation>false</reservation> - <optimizedRead>false</optimizedRead> - <analyzeRequestTime>true</analyzeRequestTime> - <multilayer>false</multilayer> - <setTraces>true</setTraces> - <!--OSPF> - <OSPFSession>true</OSPFSession> - <OSPFListenerIP>192.168.1.200</OSPFListenerIP> - <OSPFMulticast>true</OSPFMulticast> - <OSPFUnicast>false</OSPFUnicast> - <OSPFTCPSession>false</OSPFTCPSession> - <OSPFTCPPort>7762</OSPFTCPPort> - </OSPF--> - <!--WSON NETWORK--> - <!--<layer type="gmpls" default="true" encodingType="1" switchingType="150">77</layer>--> - <layer type="mpls" default="true" ></layer> - <!--<algorithmRule of="0" svec="false" name="mpls.MPLS_MinTH_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="false"/>--> - - <!--<algorithmRule of="1000" svec="false" name="wson.SP_FF_RWA_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<<algorithmRule of="1002" svec="false" name="sson.AURE_SSON_algorithm" isParentPCEAlgorithm="false" isSSONAlgorithm="true"/>--> - - <!--<algorithmRule of="998" svec="true" name="wson.svec.SVEC_SP_FF_WSON_PathComputing" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="1100" svec="false" name="multiLayer.Multilayer_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="900" svec="false" name="wson.KSPprecomp_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<algorithmRule of="1001" svec="false" name="wson.AURE_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<algorithmRule of="901" svec="false" name="wson.AURE_PACK_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="903" svec="false" name="wson.AURE_RANDOM_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<algorithmRule of="902" svec="false" name="wson.AURE_SPREAD_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="800" svec="false" name="wson.KSP_FF_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<algorithmRule of="801" svec="false" name="wson.KSP_PACK_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - <!--<algorithmRule of="803" svec="false" name="wson.KSP_RANDOM_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="802" svec="false" name="wson.KSP_SPREAD_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="900" svec="false" name="wson.AURE_FF_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="true"/>--> - - <!--<algorithmRule of="1001" svec="false" name="wson.AURE_Algorithm" isParentPCEAlgorithm="false" isWSONAlgorithm="false"/>--> - <!--<algorithmRule of="999" svec="true" name="CPLEXOptimizedPathComputing" isParentPCEAlgorithm="false" isWSONAlgorithm="false"/>--> - <!-- <layer type="mpls" default="true"/>--> - <!--<layer type="mpls" default="true"/>--> - -</config> diff --git a/src/pcep/service/resources/java/netphony-pce b/src/pcep/service/resources/java/netphony-pce deleted file mode 160000 index cbe620a728db0e2e1e0473d4ba88e4f60360e8e6..0000000000000000000000000000000000000000 --- a/src/pcep/service/resources/java/netphony-pce +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cbe620a728db0e2e1e0473d4ba88e4f60360e8e6 diff --git a/src/pcep/service/resources/log4j2.xml b/src/pcep/service/resources/log4j2.xml deleted file mode 100644 index 9f166ac7e078bffc13ea9f751274dd92dbe4ec2e..0000000000000000000000000000000000000000 --- a/src/pcep/service/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="DEBUG"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> - </Console> - </Appenders> - <Loggers> - <Logger name="BGP4Peer" level="trace" additivity="false"> - <AppenderRef ref="Console"/> - </Logger> - <Root level="DEBUG"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> \ No newline at end of file diff --git a/src/pcep/service/resources/topologia_ifusion.xml b/src/pcep/service/resources/topologia_ifusion.xml deleted file mode 100644 index 7c1f9ad3d3d039b2caf04ce7d83d1bf6eae763df..0000000000000000000000000000000000000000 --- a/src/pcep/service/resources/topologia_ifusion.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<network> - <domain> - <layer type="mpls" ></layer> - - <domain_id>0.0.0.1</domain_id> - <reachability_entry> - <ipv4_address>1.1.1.0</ipv4_address> - <prefix>12</prefix> - </reachability_entry> - - <node> - <router_id>1.1.1.1</router_id> - </node> - <node> - <router_id>1.1.1.2</router_id> - </node> - <node> - <router_id>1.1.1.3</router_id> - </node> - - <!-- 1 al 2 --> - <edge type="intradomain"> - <source> - <router_id>1.1.1.1</router_id> - <NumIf_id>192.168.1.11</NumIf_id> - </source> - <destination> - <router_id>1.1.1.2</router_id> - <NumIf_id>192.168.1.12</NumIf_id> - </destination> - <delay> - 3.13 - </delay> - <maximum_bandwidth> - 100 - </maximum_bandwidth> - <unreserved_bandwidth priority="0"> - 100 - </unreserved_bandwidth> - </edge> - - <edge type="intradomain"> - <source> - <router_id>1.1.1.1</router_id> - <NumIf_id>192.168.3.11</NumIf_id> - </source> - <destination> - <router_id>1.1.1.3</router_id> - <NumIf_id>192.168.3.13</NumIf_id> - </destination> - <delay> - 3.13 - </delay> - <maximum_bandwidth> - 100 - </maximum_bandwidth> - <unreserved_bandwidth priority="0"> - 100 - </unreserved_bandwidth> - </edge> - - <edge type="intradomain"> - <source> - <router_id>1.1.1.3</router_id> - <NumIf_id>192.168.2.13</NumIf_id> - </source> - <destination> - <router_id>1.1.1.2</router_id> - <NumIf_id>192.168.2.12</NumIf_id> - </destination> - <delay> - 3.13 - </delay> - <maximum_bandwidth> - 100 - </maximum_bandwidth> - <unreserved_bandwidth priority="0"> - 100 - </unreserved_bandwidth> - </edge> - - - </domain> -</network> diff --git a/src/pcep/service/tools/GrpcServer.py b/src/pcep/service/tools/GrpcServer.py index 40a98785fa09773203a85d5269ceb11ff31df401..7f7443be5aa08cd36f0f6ec707589f45466a5721 100644 --- a/src/pcep/service/tools/GrpcServer.py +++ b/src/pcep/service/tools/GrpcServer.py @@ -29,12 +29,17 @@ import subprocess from multiprocessing import Pool import logging -from .JavaRunner import JavaRunner +# from .JavaRunner import JavaRunner LOGGER = logging.getLogger(__name__) _ONE_DAY_IN_SECONDS = 60 * 60 * 24 -SERVER_ADDRESS = 'localhost:10060' + + +# SERVER_ADDRESS = 'localhost:10060' + + +SERVER_ADDRESS = '192.168.159.225:10060' class GrpcServer(): @@ -46,17 +51,17 @@ class GrpcServer(): self.__server=grpc.aio.server() self.__runnerList=[] - def connectToJavaPcep(self, address): - runner = JavaRunner(address) + # def connectToJavaPcep(self, address): + # runner = JavaRunner(address) - # Sets IpAddress in XML config file for java program - runner.setPeer(address) + # # Sets IpAddress in XML config file for java program + # runner.setPeer(address) - process_thread = threading.Thread(target=runner.execPcep) - process_thread.start() - self.__runnerList.append(runner) + # process_thread = threading.Thread(target=runner.execPcep) + # process_thread.start() + # self.__runnerList.append(runner) - return process_thread + # return process_thread def ConnectThread(self) -> bool: @@ -95,7 +100,7 @@ class GrpcServer(): return True def update(): - with grpc.insecure_channel('localhost:10060') as channel: + with grpc.insecure_channel('192.168.159.225:10060') as channel: n = "initiate lsp directo 10.95.90.56 1.1.1.1 1.1.1.3 m1228800 na192.168.3.11-192.168.3.13" #n = "terminate lsp 10.95.90.56 0 nombre" #n="create candidatepath 10.95.90.56 1.1.1.1 4 97 m69644288 nn1.1.1.3 m69640192 nn1.1.1.2" @@ -104,31 +109,6 @@ class GrpcServer(): print("updateService req: " ,request) response = stub.update(request) print("updateService client received: " ,response.commandResp) - - # def getLSPDB(): - # with grpc.insecure_channel('localhost:10060') as channel: - # #n = "initiate lsp directo 10.95.90.56 1.1.1.1 1.1.1.3 m1228800 na192.168.3.11-192.168.3.13" - # #n = "terminate lsp 10.95.90.56 0 nombre" - # #n="create candidatepath 10.95.90.56 1.1.1.1 4 97 m69644288 nn1.1.1.3 m69640192 nn1.1.1.2" - # stub = grpcService_pb2_grpc.pceServiceStub(channel) - # request = grpcService_pb2.LSPdb_Request() - # print("updateService req: " ,request) - # response = stub.getLSPdb(request) - # print("GetLSPDB") - - def requestToJavaPcep(self,message): - with grpc.insecure_channel('localhost:10060') as channel: - #n = "initiate lsp largo2 10.95.90.56 1.1.1.1 1.1.1.2 m69644288 nn1.1.1.3 m69640192 nn1.1.1.2" - #n = "initiate lsp directo 10.95.90.56 1.1.1.1 1.1.1.3 m1228800 na192.168.3.11-192.168.3.13" - LOGGER.debug("LLego al request") - stub = pceServiceStub(channel) - LOGGER.debug("updateService req 2: %s" ,message) - request = commandRequest(command=message) - LOGGER.debug("updateService req 2: %s" ,request) - response = stub.update(request) - # LOGGER.debug("updateServide client received: %s" ,response) - # LOGGER.debug("updateServide client received IP: %s" ,response) - return response def terminateRunners(self): for runner in self.__runnerList: @@ -155,19 +135,33 @@ class GrpcServer(): return True - def get_lspdb_from_java(self, request): - with grpc.insecure_channel('localhost:10060') as channel: + def request_to_java(self,message): + with grpc.insecure_channel('192.168.159.225:10060') as channel: + #n = "initiate lsp largo2 10.95.90.56 1.1.1.1 1.1.1.2 m69644288 nn1.1.1.3 m69640192 nn1.1.1.2" + #n = "initiate lsp directo 10.95.90.56 1.1.1.1 1.1.1.3 m1228800 na192.168.3.11-192.168.3.13" stub = pceServiceStub(channel) - # Realizar la llamada al servidor Java - request = LSPdb_Request() - print("updateService req: " ,request) - response = stub.getLSPdb(request) - print("GetLSPDB") - # Devuelve los datos de LSP obtenidos del servidor Java + LOGGER.debug("updateService req 2: %s" ,message) + request = commandRequest(command=message) + LOGGER.debug("updateService req 2: %s" ,request) + response = stub.update(request) + # LOGGER.debug("updateServide client received: %s" ,response) + # LOGGER.debug("updateServide client received IP: %s" ,response) return response + + + # def get_lspdb_from_java(self, request): + # with grpc.insecure_channel('192.168.159.225:10060') as channel: + # stub = pceServiceStub(channel) + # # Realizar la llamada al servidor Java + # request = LSPdb_Request() + # print("updateService req: " ,request) + # response = stub.getLSPdb(request) + # print("GetLSPDB") + # # Devuelve los datos de LSP obtenidos del servidor Java + # return response def get_sessions_info_java(self, request): - with grpc.insecure_channel('localhost:10060') as channel: + with grpc.insecure_channel('192.168.159.225:10060') as channel: stub = pceServiceStub(channel) # Realizar la llamada al servidor Java request = Session_Request() diff --git a/src/pcep/tests/Grpc_TestClient/gRPC_PCEPClient.py b/src/pcep/tests/Grpc_TestClient/gRPC_PCEPClient.py index e6519193b9afae266f42f295daffdee350f888ec..3212bc9916b421c757d0cede70974eb4f57f5cdc 100644 --- a/src/pcep/tests/Grpc_TestClient/gRPC_PCEPClient.py +++ b/src/pcep/tests/Grpc_TestClient/gRPC_PCEPClient.py @@ -26,7 +26,7 @@ RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, PORT = 10060 class GrpcPcepClient: - def __init__(self, host="127.0.0.1", port=None): + def __init__(self, host="192.168.159.225", port=None): if not host: host = get_service_host(ServiceNameEnum.PCEP) #if not port: port = get_service_port_grpc(ServiceNameEnum.PCEP) if not port: port = PORT #Maybe should not be hardcoded diff --git a/src/pcep/tests/Grpc_TestClient/test_gRPC_client.py b/src/pcep/tests/Grpc_TestClient/test_gRPC_client.py index 98019dc6bc61bfa4af67d06b361c929967e3a198..22e2d74dda5e716637a78a100c91bdf110fbdeff 100644 --- a/src/pcep/tests/Grpc_TestClient/test_gRPC_client.py +++ b/src/pcep/tests/Grpc_TestClient/test_gRPC_client.py @@ -23,8 +23,8 @@ from pcep.service.tools.protos.grpcService_pb2 import LSPdb_Request, Session_Req from pcep.service.tools.protos.grpcService_pb2_grpc import pceServiceStub def run(): # Create a gRPC channel - channel = grpc.insecure_channel('localhost:31816') - # channel = grpc.insecure_channel('localhost:10060') + # channel = grpc.insecure_channel('localhost:31816') + channel = grpc.insecure_channel('192.168.159.225:10060') # Create a gRPC stub stub = pceServiceStub(channel) diff --git a/src/webui/Dockerfile b/src/webui/Dockerfile index 40f075241f6d5b99acbeacfc624e0a9d57556744..94540bfbbc5af1cc1f7e65cb0f173e62d807adfa 100644 --- a/src/webui/Dockerfile +++ b/src/webui/Dockerfile @@ -85,12 +85,15 @@ COPY --chown=webui:webui src/service/client/. service/client/ COPY --chown=webui:webui src/slice/__init__.py slice/__init__.py COPY --chown=webui:webui src/slice/client/. slice/client/ COPY --chown=webui:webui src/webui/. webui/ + COPY --chown=webui:webui src/pcep/__init__.py pcep/__init__.py COPY --chown=webui:webui src/pcep/client/. pcep/client/ COPY --chown=webui:webui src/pcep/service/tools/. pcep/service/tools/ +COPY --chown=webui:webui src/pcep/database/. pcep/database/ + COPY --chown=webui:webui src/bgpls_speaker/__init__.py bgpls_speaker/__init__.py COPY --chown=webui:webui src/bgpls_speaker/client/. bgpls_speaker/client/ -COPY --chown=webui:webui src/pcep/__init__.py pcep/__init__.py -COPY --chown=webui:webui src/pcep/client/. pcep/client/ + + # Start the service ENTRYPOINT ["python", "-m", "webui.service"] diff --git a/src/webui/requirements.in b/src/webui/requirements.in index ab512dedb16d95c21d8807732f4ef386475aa32e..f48f9f1f5935aaf072c78643b62011590f13429f 100644 --- a/src/webui/requirements.in +++ b/src/webui/requirements.in @@ -18,3 +18,11 @@ flask-healthz<2 flask-unittest==0.1.3 lorem-text==2.1 werkzeug==2.3.7 + + + +#DB +psycopg2-binary==2.9.* +SQLAlchemy==1.4.* +sqlalchemy-cockroachdb==1.4.* +SQLAlchemy-Utils==0.38.* diff --git a/src/webui/service/pcep/routes.py b/src/webui/service/pcep/routes.py index 037035803107430507999f0955170d7330d3b602..91b029f43a0e861a90e6936b4c029756272a7d20 100644 --- a/src/webui/service/pcep/routes.py +++ b/src/webui/service/pcep/routes.py @@ -79,10 +79,9 @@ def home(): def managePCEP(): pcep_manage_form = SendPathForm() if pcep_manage_form.validate_on_submit(): - command_data = pcep_manage_form.command.data - logger.info('Send Path ip:%s',command_data) pcep_client.connect() - command_response = pcep_client.sendUpdate(command_data) + logger.info('Send Path ip:%s',pcep_manage_form.command.data) + command_response = pcep_client.sendRequest(RequestRq(command=pcep_manage_form.command.data)) #logger.info('THIS IS THE RESPONSE:%s',command_response) #logger.info('THIS IS THE RESPONSE BOOL:%s',command_response.success) #logger.info('THIS IS THE RESPONSE ERROR:%s',command_response.error_message) @@ -101,13 +100,6 @@ def managePCEP(): @pcep.route('lspdbPCEP', methods=['GET', 'POST']) def lspdbPCEP(): - # logger.info('pcep_grpc_client.connect %s', grpc_pcep_client) - # grpc_pcep_client.connect() - # lspdb = grpc_pcep_client.showLSPDB() - # if lspdb: - # flash(f'LSPDB data retrieved', 'success') - # grpc_pcep_client.close() - pcep_client.connect() logger.info('pcep_client.connect %s',pcep_client) @@ -117,6 +109,18 @@ def lspdbPCEP(): pcep_client.close() return render_template('pcep/lspdb.html', lspdb=lspdb) +@pcep.route('sendPath', methods=['GET', 'POST']) +def sendPath(): + pcep_client.connect() + form = SendPathForm() + response = None + if form.validate_on_submit(): + logger.info('Send Path ip:%s',form.command.data) + response = pcep_client.sendRequest(RequestRq(command=form.command.data)) + flash(f'Command "{form.command.data}" added successfully!', 'success') + pcep_client.close() + return render_template('pcep/sendPath.html',form=form,response=response) + @pcep.route('add/<path:device_name>', methods=['GET', 'POST']) def add(device_name): @@ -245,20 +249,7 @@ def addPcep(): return render_template('pcep/addPcep.html',form=form) -@pcep.route('sendPath', methods=['GET', 'POST']) -def sendPath(): - pcep_client.connect() - form = SendPathForm() - if form.validate_on_submit(): - logger.info('Send Path ip:%s',form.command.data) - pcep_client.sendRequest(RequestRq(command=form.command.data)) - logger.info('Prueba 1') - flash(f'Command "{form.command.data}" added successfully!', 'success') - logger.info('Prueba 2') - pcep_client.close() - logger.info('Prueba 3') - return render_template('pcep/sendPath.html',form=form) @pcep.route('formPcep', methods=['GET','POST']) def formPcep(): diff --git a/src/webui/service/templates/pcep/home.html b/src/webui/service/templates/pcep/home.html index ad4ac4f769ba4d72f97d3676c1530ca7c7b6da21..7fde0c7d9e9835ff543b788f0c7793808b520655 100644 --- a/src/webui/service/templates/pcep/home.html +++ b/src/webui/service/templates/pcep/home.html @@ -16,9 +16,11 @@ {% extends 'base.html' %} {% block content %} - <h1>Path Computation Element Protocol (PCEP)</h1> - <div class="row"> + <h1 class="text-center mb-4">Path Computation Element Protocol (PCEP)</h1> + + <!-- Sección de botones --> + <div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 g-3 text-center"> <div class="col"> <a href="{{ url_for('pcep.managePCEP') }}" class="btn btn-primary"> <i class="bi bi-pencil"></i> Manage PCE @@ -29,19 +31,21 @@ <a href="{{ url_for('pcep.lspdbPCEP') }}" class="btn btn-primary"> <i class="bi bi-table"></i> Show LSPDB </a> - </div> + </div> <div class="col"> - <a href="{{ url_for('pcep.addPcep') }}" class="btn btn-primary"> - <i class="bi bi-plus"></i> Configure PCE IP + <a href="{{ url_for('pcep.sendPath') }}" class="btn btn-primary"> + <i class="bi bi-pencil-square"></i> Send Command to Configure Route </a> </div> - + <div class="col"> - <a href="{{ url_for('pcep.sendPath') }}" class="btn btn-primary"> - <i class="bi bi-pencil-square"></i> Send Command to Configure Route + <a href="{{ url_for('pcep.addPcep') }}" class="btn btn-primary"> + <i class="bi bi-plus"></i> Configure PCE IP </a> </div> + + </div> <div id="topology" style="margin-top: 20px;"></div> diff --git a/src/webui/service/templates/pcep/lspdb.html b/src/webui/service/templates/pcep/lspdb.html index 016379327eced7452b0a92eabe1cc130b8b99e63..972d334e918e0764a066954827b7ef14754fe440 100644 --- a/src/webui/service/templates/pcep/lspdb.html +++ b/src/webui/service/templates/pcep/lspdb.html @@ -13,12 +13,38 @@ See the License for the specific language governing permissions and limitations under the License. --> - {% extends 'base.html' %} + {% block content %} <h1>Label Switched Paths Database (LSPDB)</h1> <br> - <div> - <h2>{{ lspdb }}</h2> - </div> + + {% if lspdb %} + <table border="1"> + <thead> + <tr> + <th>LSP UUID</th> + <th>SRP</th> + <th>LSP</th> + <th>Path</th> + <th>Association List</th> + </tr> + </thead> + <tbody> + {% for lsp in lspdb %} + <tr> + <td>{{ lsp.lsp_uuid }}</td> + <td>{{ lsp.srp }}</td> + <td>{{ lsp.lsp }}</td> + <td>{{ lsp.path }}</td> + <td>{{ lsp.associationlist }}</td> + </tr> + {% endfor %} + </tbody> + </table> + {% else %} + <p>No LSP data available.</p> + {% endif %} {% endblock %} + + diff --git a/src/webui/service/templates/pcep/sendPath.html b/src/webui/service/templates/pcep/sendPath.html index 1fb1a4212633e73a3537aa076f7183fbbec72b91..ace2745ed5ee54522093d89fb3786ca20e5ca8a0 100644 --- a/src/webui/service/templates/pcep/sendPath.html +++ b/src/webui/service/templates/pcep/sendPath.html @@ -17,10 +17,7 @@ {% extends 'base.html' %} {% block content %} <h1>Send Path </h1> - <!-- TEST --> <h5>Create, delete or modify paths</h5> - - <br /> <div> <form action='{{ url_for("pcep.sendPath")}}' method="post"> {{ form.hidden_tag() }} @@ -48,4 +45,11 @@ </button> </form> </div> + {% if response %} + <div class="mt-4"> + <h5>Response</h5> + <p><strong>Success:</strong> {{ response.success }}</p> + <p><strong>Error Message:</strong> {{ response.error_message }}</p> + </div> + {% endif %} {% endblock %}