Skip to content
Snippets Groups Projects
Commit 72078a0e authored by Pablo Armingol's avatar Pablo Armingol
Browse files

changes to add PECP module

parent c6fce9ae
No related branches found
No related tags found
1 merge request!205Draft: Resolve "(TID) New PCEP component"
Showing
with 985 additions and 3 deletions
# Copyright 2022-2023 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.
apiVersion: apps/v1
kind: Deployment
metadata:
name: pcepservice
spec:
selector:
matchLabels:
app: pcepservice
replicas: 1
template:
metadata:
labels:
app: pcepservice
spec:
terminationGracePeriodSeconds: 5
containers:
- name: server
image: localhost:32000/tfs/pcep:dev
imagePullPolicy: Always
ports:
- containerPort: 10050
- containerPort: 9192
env:
- name: LOG_LEVEL
value: "DEBUG"
readinessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:10050"]
livenessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:10050"]
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: pcepservice
labels:
app: pcepservice
spec:
type: ClusterIP
selector:
app: pcepservice
ports:
- name: grpc
protocol: TCP
port: 10050
targetPort: 10050
- name: metrics
protocol: TCP
port: 9192
targetPort: 9192
...@@ -34,6 +34,14 @@ service ContextService { ...@@ -34,6 +34,14 @@ service ContextService {
rpc RemoveTopology (TopologyId ) returns ( Empty ) {} rpc RemoveTopology (TopologyId ) returns ( Empty ) {}
rpc GetTopologyEvents (Empty ) returns (stream TopologyEvent ) {} rpc GetTopologyEvents (Empty ) returns (stream TopologyEvent ) {}
rpc ListInventoryIds (Empty ) returns ( InventoryIdList ) {}
rpc ListInventory (Empty ) returns ( InventoryList ) {}
rpc ListInventoryNames (InventoryIdList) returns( InventoryNameList ) {}
rpc GetInventory (InventoryId ) returns ( Inventory ) {}
rpc SetInventory (Inventory ) returns ( InventoryId ) {}
rpc RemoveInventory (InventoryId ) returns ( Empty ) {}
rpc GetInventoryEvents (InventoryId ) returns (stream InventoryEvent ) {}
rpc ListDeviceIds (Empty ) returns ( DeviceIdList ) {} rpc ListDeviceIds (Empty ) returns ( DeviceIdList ) {}
rpc ListDevices (Empty ) returns ( DeviceList ) {} rpc ListDevices (Empty ) returns ( DeviceList ) {}
rpc GetDevice (DeviceId ) returns ( Device ) {} rpc GetDevice (DeviceId ) returns ( Device ) {}
...@@ -174,12 +182,17 @@ message Device { ...@@ -174,12 +182,17 @@ message Device {
DeviceOperationalStatusEnum device_operational_status = 5; DeviceOperationalStatusEnum device_operational_status = 5;
repeated DeviceDriverEnum device_drivers = 6; repeated DeviceDriverEnum device_drivers = 6;
repeated EndPoint device_endpoints = 7; repeated EndPoint device_endpoints = 7;
repeated Component component = 8; // Used for inventory // Used for inventory:
DeviceId controller_id = 9; // Identifier of node controlling the actual device map<string, Component> components = 8; // dict[comp.name => Component]
DeviceId controller_id = 9; // Identifier of node controlling the actual device
} }
message Component { message Component {
repeated string comp_string = 1; Uuid uuid = 1;
string name = 2;
string type = 3;
repeated string child = 4; // list[sub-component.name]
map<string, string> attributes = 5; // dict[attr.name => json.dumps(attr.value)]
} }
message DeviceConfig { message DeviceConfig {
...@@ -589,3 +602,42 @@ message AuthenticationResult { ...@@ -589,3 +602,42 @@ message AuthenticationResult {
ContextId context_id = 1; ContextId context_id = 1;
bool authenticated = 2; bool authenticated = 2;
} }
// -----Inventory ------------------------------------------------------------------------------------------------------
message InventoryId{
TopologyId topology_id = 1;
DeviceId device_id = 2;
Uuid inventory_uuid = 3;
}
message Inventory{
InventoryId inventory_id = 1;
string name = 2;
string inventory_type = 3;
repeated kpi_sample_types.KpiSampleType kpi_sample_types = 4;
string datos = 5;
}
message InventoryName {
InventoryId inventory_id = 1;
string device_name = 2;
string inventory_name = 3;
string inventory_type = 4;
}
message InventoryIdList {
repeated InventoryId inventory_ids = 1;
}
message InventoryNameList {
repeated InventoryName inventory_names = 1;
}
message InventoryList {
repeated Inventory inventory = 1;
}
message InventoryEvent {
Inventory event = 1;
InventoryId inventory_id = 2;
}
\ No newline at end of file
// Copyright 2022-2023 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.
syntax = "proto3";
package pcep;
service PcepService {
rpc sendRequest ( RequestRq ) returns ( RequestRp ) {}
rpc configuratePCE ( PceIpRq ) returns ( PceIpRp ) {}
}
message RequestRq {
string command = 1;
}
message RequestRp {
string commandRp = 1;
}
message PceIpRq {
string address=1;
string port= 2;
string asNumber=3;
}
message PceIpRp{
string addressRp=1;
}
...@@ -56,6 +56,7 @@ class ServiceNameEnum(Enum): ...@@ -56,6 +56,7 @@ class ServiceNameEnum(Enum):
OPTICALATTACKDETECTOR = 'opticalattackdetector' OPTICALATTACKDETECTOR = 'opticalattackdetector'
OPTICALATTACKMITIGATOR = 'opticalattackmitigator' OPTICALATTACKMITIGATOR = 'opticalattackmitigator'
CACHING = 'caching' CACHING = 'caching'
PCEP = 'pcep'
# Used for test and debugging only # Used for test and debugging only
DLT_GATEWAY = 'dltgateway' DLT_GATEWAY = 'dltgateway'
...@@ -80,6 +81,7 @@ DEFAULT_SERVICE_GRPC_PORTS = { ...@@ -80,6 +81,7 @@ DEFAULT_SERVICE_GRPC_PORTS = {
ServiceNameEnum.OPTICALATTACKMANAGER .value : 10005, ServiceNameEnum.OPTICALATTACKMANAGER .value : 10005,
ServiceNameEnum.INTERDOMAIN .value : 10010, ServiceNameEnum.INTERDOMAIN .value : 10010,
ServiceNameEnum.PATHCOMP .value : 10020, ServiceNameEnum.PATHCOMP .value : 10020,
ServiceNameEnum.PCEP .value : 10050,
# Used for test and debugging only # Used for test and debugging only
ServiceNameEnum.DLT_GATEWAY .value : 50051, ServiceNameEnum.DLT_GATEWAY .value : 50051,
......
# Copyright 2022-2023 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.
# Build, tag, and push the Docker image to the GitLab Docker registry
build service:
variables:
IMAGE_NAME: 'pcep' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: build
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
- docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
- docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
after_script:
- docker images --filter="dangling=true" --quiet | xargs -r docker rmi
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
- changes:
- src/common/**/*.py
- proto/*.proto
- src/$IMAGE_NAME/**/*.{py,in,yml}
- src/$IMAGE_NAME/Dockerfile
- src/$IMAGE_NAME/tests/*.py
- manifests/${IMAGE_NAME}service.yaml
- .gitlab-ci.yml
# Apply unit test to the component
unit_test service:
variables:
IMAGE_NAME: 'pcep' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: unit_test
needs:
- build service
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge teraflowbridge; fi
# Context-related
- if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi
- if docker volume ls | grep crdb; then docker volume rm -f crdb; else echo "CockroachDB volume is not in the system"; fi
- if docker container ls | grep nats; then docker rm -f nats; else echo "NATS container is not in the system"; fi
# Device-related
- if docker container ls | grep context; then docker rm -f context; else echo "context image is not in the system"; fi
- if docker container ls | grep device; then docker rm -f device; else echo "device image is not in the system"; fi
# Pathcomp-related
- if docker container ls | grep pathcomp-frontend; then docker rm -f pathcomp-frontend; else echo "pathcomp-frontend image is not in the system"; fi
- if docker container ls | grep pathcomp-backend; then docker rm -f pathcomp-backend; else echo "pathcomp-backend image is not in the system"; fi
# Service-related
- if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi
script:
- docker pull "cockroachdb/cockroach:latest-v22.2"
- docker pull "nats:2.9"
- docker pull "$CI_REGISTRY_IMAGE/context:$IMAGE_TAG"
- docker pull "$CI_REGISTRY_IMAGE/device:$IMAGE_TAG"
- docker pull "$CI_REGISTRY_IMAGE/pathcomp-frontend:$IMAGE_TAG"
- docker pull "$CI_REGISTRY_IMAGE/pathcomp-backend:$IMAGE_TAG"
- docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
# Context preparation
- docker volume create crdb
- >
docker run --name crdb -d --network=teraflowbridge -p 26257:26257 -p 8080:8080
--env COCKROACH_DATABASE=tfs_test --env COCKROACH_USER=tfs --env COCKROACH_PASSWORD=tfs123
--volume "crdb:/cockroach/cockroach-data"
cockroachdb/cockroach:latest-v22.2 start-single-node
- >
docker run --name nats -d --network=teraflowbridge -p 4222:4222 -p 8222:8222
nats:2.9 --http_port 8222 --user tfs --pass tfs123
- echo "Waiting for initialization..."
- while ! docker logs crdb 2>&1 | grep -q 'finished creating default user \"tfs\"'; do sleep 1; done
- docker logs crdb
- while ! docker logs nats 2>&1 | grep -q 'Server is ready'; do sleep 1; done
- docker logs nats
- docker ps -a
- CRDB_ADDRESS=$(docker inspect crdb --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $CRDB_ADDRESS
- NATS_ADDRESS=$(docker inspect nats --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $NATS_ADDRESS
- >
docker run --name context -d -p 1010:1010
--env "CRDB_URI=cockroachdb://tfs:tfs123@${CRDB_ADDRESS}:26257/tfs_test?sslmode=require"
--env "MB_BACKEND=nats"
--env "NATS_URI=nats://tfs:tfs123@${NATS_ADDRESS}:4222"
--network=teraflowbridge
$CI_REGISTRY_IMAGE/context:$IMAGE_TAG
- CONTEXTSERVICE_SERVICE_HOST=$(docker inspect context --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $CONTEXTSERVICE_SERVICE_HOST
# Device preparation
- >
docker run --name device -d -p 2020:2020
--env "CONTEXTSERVICE_SERVICE_HOST=${CONTEXTSERVICE_SERVICE_HOST}"
--network=teraflowbridge
$CI_REGISTRY_IMAGE/device:$IMAGE_TAG
- DEVICESERVICE_SERVICE_HOST=$(docker inspect device --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $DEVICESERVICE_SERVICE_HOST
# PathComp preparation
- >
docker run --name pathcomp-backend -d -p 8081:8081
--network=teraflowbridge
$CI_REGISTRY_IMAGE/pathcomp-backend:$IMAGE_TAG
- PATHCOMP_BACKEND_HOST=$(docker inspect pathcomp-backend --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $PATHCOMP_BACKEND_HOST
- sleep 1
- >
docker run --name pathcomp-frontend -d -p 10020:10020
--env "CONTEXTSERVICE_SERVICE_HOST=${CONTEXTSERVICE_SERVICE_HOST}"
--env "PATHCOMP_BACKEND_HOST=${PATHCOMP_BACKEND_HOST}"
--env "PATHCOMP_BACKEND_PORT=8081"
--network=teraflowbridge
$CI_REGISTRY_IMAGE/pathcomp-frontend:$IMAGE_TAG
- sleep 1
- PATHCOMPSERVICE_SERVICE_HOST=$(docker inspect pathcomp-frontend --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $PATHCOMPSERVICE_SERVICE_HOST
# Service preparation
- >
docker run --name $IMAGE_NAME -d -p 3030:3030
--env "CONTEXTSERVICE_SERVICE_HOST=${CONTEXTSERVICE_SERVICE_HOST}"
--env "DEVICESERVICE_SERVICE_HOST=${DEVICESERVICE_SERVICE_HOST}"
--env "PATHCOMPSERVICE_SERVICE_HOST=${PATHCOMPSERVICE_SERVICE_HOST}"
--volume "$PWD/src/$IMAGE_NAME/tests:/opt/results"
--network=teraflowbridge
$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
# Check status before the tests
- sleep 5
- docker ps -a
- docker logs context
- docker logs device
- docker logs pathcomp-frontend
- docker logs pathcomp-backend
- docker logs $IMAGE_NAME
# Run the tests
- >
docker exec -i $IMAGE_NAME bash -c
"coverage run -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/opt/results/${IMAGE_NAME}_report.xml"
- docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing"
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
after_script:
# Check status after the tests
- docker ps -a
- docker logs context
- docker logs device
- docker logs pathcomp-frontend
- docker logs pathcomp-backend
- docker logs $IMAGE_NAME
- docker rm -f $IMAGE_NAME
- docker rm -f pathcomp-frontend
- docker rm -f pathcomp-backend
- docker rm -f device
- docker rm -f context
- docker rm -f $IMAGE_NAME crdb nats
- docker volume rm -f crdb
- docker network rm teraflowbridge
- docker volume prune --force
- docker image prune --force
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
- changes:
- src/common/**/*.py
- proto/*.proto
- src/$IMAGE_NAME/**/*.{py,in,yml}
- src/$IMAGE_NAME/Dockerfile
- src/$IMAGE_NAME/tests/*.py
- manifests/${IMAGE_NAME}service.yaml
- .gitlab-ci.yml
artifacts:
when: always
reports:
junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml
## Deployment of the service in Kubernetes Cluster
#deploy service:
# variables:
# IMAGE_NAME: 'service' # name of the microservice
# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
# stage: deploy
# needs:
# - unit test service
# # - integ_test execute
# script:
# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml'
# - kubectl version
# - kubectl get all
# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml"
# - kubectl get all
# # environment:
# # name: test
# # url: https://example.com
# # kubernetes:
# # namespace: test
# rules:
# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
# when: manual
# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
# when: manual
# Copyright 2022-2023 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.
# Copyright 2022-2023 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.
FROM python:3.9-slim
# Install dependencies
RUN apt-get --yes --quiet --quiet update && \
apt-get --yes --quiet --quiet install wget g++ && \
rm -rf /var/lib/apt/lists/*
# Set Python to show logs as they occur
ENV PYTHONUNBUFFERED=0
# Download the gRPC health probe
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
# Get generic Python packages
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install --upgrade setuptools wheel
RUN python3 -m pip install --upgrade pip-tools
# Install OpenJDK-11
RUN apt-get update && \
apt-get install -y openjdk-11-jre-headless && \
apt-get clean;
# Get common Python packages
# Note: this step enables sharing the previous Docker build steps among all the Python components
WORKDIR /var/teraflow
COPY common_requirements.in common_requirements.in
RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in
RUN python3 -m pip install -r common_requirements.txt
# Add common files into working directory
WORKDIR /var/teraflow/common
COPY src/common/. ./
RUN rm -rf proto
# Create proto sub-folder, copy .proto files, and generate Python code
RUN mkdir -p /var/teraflow/common/proto
WORKDIR /var/teraflow/common/proto
RUN touch __init__.py
COPY proto/*.proto ./
RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto
RUN rm *.proto
RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \;
# Create component sub-folders, get specific Python packages
RUN mkdir -p /var/teraflow/pcep
WORKDIR /var/teraflow/pcep
COPY src/pcep/requirements.in requirements.in
RUN pip-compile --quiet --output-file=requirements.txt requirements.in
RUN python3 -m pip install -r requirements.txt
# Java module necessary config files
WORKDIR /var/teraflow/pcep
RUN mkdir -p /resources
COPY src/pcep/service/resources/. resources/
# Add component files into working directory
WORKDIR /var/teraflow
COPY src/context/. context/
COPY src/device/. device/
COPY src/pathcomp/frontend/. pathcomp/frontend/
COPY src/service/. service/
COPY src/pcep/. pcep/
# Start the service
ENTRYPOINT ["python", "-m", "pcep.service"]
# Copyright 2022-2023 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.
# Copyright 2022-2023 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.
import grpc, logging
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
from common.tools.client.RetryDecorator import retry, delay_exponential
from common.tools.grpc.Tools import grpc_message_to_json_string
LOGGER = logging.getLogger(__name__)
MAX_RETRIES = 15
DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
class PcepClient:
def __init__(self, host=None, port=None):
if not host: host = get_service_host(ServiceNameEnum.PCEP)
if not port: port = get_service_port_grpc(ServiceNameEnum.PCEP)
self.endpoint = '{:s}:{:s}'.format(str(host), str(port))
LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint)))
self.channel = None
self.stub = None
self.connect()
LOGGER.debug('Channel created')
def connect(self):
self.channel = grpc.insecure_channel(self.endpoint)
self.stub = PcepServiceStub(self.channel)
def close(self):
if self.channel is not None: self.channel.close()
self.channel = None
self.stub = None
@RETRY_DECORATOR
def sendRequest(self, request : RequestRq) -> RequestRp:
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)))
return response
@RETRY_DECORATOR
def configuratePCE(self, request : PceIpRq) -> PceIpRp:
LOGGER.debug('Configurate PCE: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.configuratePCE(request)
LOGGER.debug('Configurate PCE result: {:s}'.format(grpc_message_to_json_string(response)))
return response
# Copyright 2022-2023 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.
# Copyright 2022-2023 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.
anytree==2.8.0
APScheduler==3.8.1
#networkx==2.6.3
#pydot==1.4.2
#redis==4.1.2
#fastcache==1.1.0
ncclient==0.6.13
python-json-logger==2.0.2
pytz==2021.3
xmltodict==0.12.0
# pip's dependency resolver does not take into account installed packages.
# p4runtime does not specify the version of grpcio/protobuf it needs, so it tries to install latest one
# adding here again grpcio==1.47.* and protobuf==3.20.* with explicit versions to prevent collisions
grpcio==1.47.*
protobuf==3.20.*
prometheus_client==0.13.0
\ No newline at end of file
# Copyright 2022-2023 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.
from pcep.service.tools.GrpcServer import GrpcServer
from common.Constants import ServiceNameEnum
from common.Settings import get_service_port_grpc
from common.proto.pcep_pb2_grpc import add_PcepServiceServicer_to_server
from common.tools.service.GenericGrpcService import GenericGrpcService
from .PcepServiceServicerImpl import PcepServiceServicerImpl
class PcepService(GenericGrpcService):
def __init__(self, pcepServer : GrpcServer,cls_name: str = __name__) -> None:
port = get_service_port_grpc(ServiceNameEnum.PCEP) # El enum en common.constants
super().__init__(port, cls_name=cls_name)
self.pcep_servicer = PcepServiceServicerImpl(pcepServer)
def install_servicers(self):
add_PcepServiceServicer_to_server(self.pcep_servicer, self.server)
# Copyright 2022-2023 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.
import grpc, json, logging
from typing import Optional
from pcep.service.tools.GrpcServer import GrpcServer
from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method
from common.method_wrappers.ServiceExceptions import AlreadyExistsException, InvalidArgumentException
from common.proto.context_pb2 import (DeviceId, Empty, EndPointId, Link, Service, ServiceId, ServiceStatusEnum, ServiceTypeEnum, TopologyId,ContextId,Topology
,Device,DeviceDriverEnum, Uuid)
from common.proto.pathcomp_pb2 import PathCompRequest
from common.proto.service_pb2_grpc import ServiceServiceServicer
from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string
from context.client.ContextClient import ContextClient
from pathcomp.frontend.client.PathCompClient import PathCompClient
from common.proto.pcep_pb2 import (RequestRq, RequestRp, PceIpRq, PceIpRp)
from common.proto.pcep_pb2_grpc import PcepServiceServicer
# from .task_scheduler.TaskScheduler import TasksScheduler
# from .tools.ContextGetters import get_service
LOGGER = logging.getLogger(__name__)
METRICS_POOL = MetricsPool('Service', 'RPC')
class PcepServiceServicerImpl(PcepServiceServicer):
def __init__(self, pcepServer : GrpcServer) -> None:
LOGGER.debug('Creating Servicer...')
self.pcepServer=pcepServer
LOGGER.debug('Servicer Created')
@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)
return PceIpRp(addressRp=configurateIP)
@safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
def sendRequest(self, request : RequestRq, context : grpc.ServicerContext) -> RequestRp:
message=self.pcepServer.requestToJavaPcep(request.command)
return RequestRp(commandRp=message)
# Copyright 2022-2023 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.
# Copyright 2022-2023 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.
import logging, signal, sys, threading, time
from prometheus_client import start_http_server
from common.Constants import ServiceNameEnum
from common.Settings import (
ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port,
wait_for_environment_variables)
from .PcepService import PcepService
from .tools.JavaRunner import JavaRunner
from .tools.GrpcServer import GrpcServer
terminate = threading.Event()
LOGGER : logging.Logger = None
def signal_handler(signal, frame): # pylint: disable=redefined-outer-name
LOGGER.warning('Terminate signal received')
LOGGER.warning(signal)
terminate.set()
def main():
global LOGGER # pylint: disable=global-statement
log_level = get_log_level()
logging.basicConfig(level=log_level, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s")
LOGGER = logging.getLogger(__name__)
###wait_for_environment_variables([
###get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST ),
###get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC),
###get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_HOST ),
###get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC),
###get_env_var_name(ServiceNameEnum.PATHCOMP, ENVVAR_SUFIX_SERVICE_HOST ),
###get_env_var_name(ServiceNameEnum.PATHCOMP, ENVVAR_SUFIX_SERVICE_PORT_GRPC),
###])
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
LOGGER.info('Starting...')
# Start metrics server
metrics_port = get_metrics_port()
start_http_server(metrics_port)
# Initialize ServiceHandler Factory
###service_handler_factory = ServiceHandlerFactory(SERVICE_HANDLERS)
#DB=DiscoveredDBManager()
pcep_server = GrpcServer()
#pcep_server.Connect()
pcep_server.connectToJavaPcep("10.95.41.240")
time.sleep(30)
n = "initiate lsp directo 10.95.86.214 1.1.1.1 1.1.1.3 m1228800 na192.168.3.11-192.168.3.13"
pcep_server.requestToJavaPcep(n)
# Starting pcep service
pcep_service = PcepService(pcep_server)
pcep_service.start()
# Wait for Ctrl+C or termination signal
while not terminate.wait(timeout=0.1): pass
LOGGER.info('Terminating...')
pcep_server.terminateGrpcServer()
pcep_service.stop()
LOGGER.info('Bye')
return 0
if __name__ == '__main__':
sys.exit(main())
<?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>
File added
<?xml version="1.0" encoding="UTF-8"?>
<config>
<PCEServerPort>4189</PCEServerPort>
<PCEManagementPort>6666</PCEManagementPort>
<!--<LocalPCEAddress>192.168.1.200</LocalPCEAddress>-->
<!--<LocalPCEAddress>10.95.40.175</LocalPCEAddress>-->
<!--<LocalPCEAddress>127.0.0.1</LocalPCEAddress>-->
<LocalPCEAddress>10.95.43.150</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>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>
"/home/ubuntu/downloads/apache-maven-3.8.8/bin/mvn" clean package -P pcep assembly:single -DskipTests=True -f "/home/ubuntu/tfs-ctrl/src/pcep/service/resources/java/netphony-pce/pom.xml"
\ No newline at end of file
<?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>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment