aboutsummaryrefslogtreecommitdiffstats
path: root/src/onaptests/steps/simulator
diff options
context:
space:
mode:
Diffstat (limited to 'src/onaptests/steps/simulator')
-rw-r--r--src/onaptests/steps/simulator/pnf/__init__.py0
-rw-r--r--src/onaptests/steps/simulator/pnf/pnf_config.yaml16
-rw-r--r--src/onaptests/steps/simulator/pnf/pnf_instantiate.py30
-rw-r--r--src/onaptests/steps/simulator/pnf/pnf_register.py38
-rw-r--r--src/onaptests/steps/simulator/pnf/utils.py157
-rw-r--r--src/onaptests/steps/simulator/pnf_simulator_cnf/__init__.py1
-rw-r--r--src/onaptests/steps/simulator/pnf_simulator_cnf/pnf_register.py144
7 files changed, 386 insertions, 0 deletions
diff --git a/src/onaptests/steps/simulator/pnf/__init__.py b/src/onaptests/steps/simulator/pnf/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf/__init__.py
diff --git a/src/onaptests/steps/simulator/pnf/pnf_config.yaml b/src/onaptests/steps/simulator/pnf/pnf_config.yaml
new file mode 100644
index 0000000..13b0289
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf/pnf_config.yaml
@@ -0,0 +1,16 @@
+setup:
+ count: 1
+ vesprotocol: http # use `https` for the real VES
+ vesip: 172.17.0.1 # use 172.17.0.1 to communicate with localhost
+ vesport: 10000
+ vesresource: eventListener
+ vesversion: v7
+ ipstart: 10.11.0.16
+ user: ""
+ password: ""
+ ipfileserver: 127.0.0.1
+ typefileserver: sftp
+data:
+ commonEventHeaderParams:
+ sourceName: pyint-000
+ reportingEntityName: pyint-000
diff --git a/src/onaptests/steps/simulator/pnf/pnf_instantiate.py b/src/onaptests/steps/simulator/pnf/pnf_instantiate.py
new file mode 100644
index 0000000..d9d2620
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf/pnf_instantiate.py
@@ -0,0 +1,30 @@
+"""Base step that runs a PNF simulator."""
+from onaptests.steps.simulator.pnf import utils
+from onaptests.steps.base import BaseStep
+
+class PNFInstanceStep(BaseStep):
+ """Run PNF simulator containers."""
+
+ @property
+ def description(self) -> str:
+ """Step description."""
+ return "Run PNF simulator containers."
+
+ @property
+ def component(self) -> str:
+ """Component name."""
+ return "Environment"
+
+ @BaseStep.store_state
+ def execute(self) -> None:
+ """Run PNF simulator containers."""
+ super().execute()
+ utils.build_image()
+ utils.bootstrap_simulator()
+ utils.run_container()
+
+ def cleanup(self) -> None:
+ """Remove containers and images."""
+ utils.stop_container()
+ utils.remove_simulator()
+ utils.remove_image()
diff --git a/src/onaptests/steps/simulator/pnf/pnf_register.py b/src/onaptests/steps/simulator/pnf/pnf_register.py
new file mode 100644
index 0000000..8d5467a
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf/pnf_register.py
@@ -0,0 +1,38 @@
+"""Base step that runs a PNF simulator."""
+from onaptests.steps.simulator.pnf import utils
+from onaptests.steps.base import BaseStep
+from onaptests.steps.simulator.pnf.pnf_instantiate import PNFInstanceStep
+
+class PNFRegisterStep(BaseStep):
+ """Run PNF simulator containers."""
+
+ def __init__(self, cleanup=True):
+ """Initialize step.
+
+ Substeps:
+ - PNFInstanceStep
+
+ """
+ super().__init__(cleanup=cleanup)
+ self.add_step(PNFInstanceStep(cleanup=cleanup))
+
+ @property
+ def description(self) -> str:
+ """Step description."""
+ return "Register PNF with VES."
+
+ @property
+ def component(self) -> str:
+ """Component name."""
+ return "Environment"
+
+ @BaseStep.store_state
+ def execute(self) -> None:
+ """Register with VES."""
+ super().execute()
+ utils.register()
+
+ @BaseStep.store_state
+ def cleanup(self) -> None:
+ """Substeps cleanup - no unregister."""
+ super().cleanup()
diff --git a/src/onaptests/steps/simulator/pnf/utils.py b/src/onaptests/steps/simulator/pnf/utils.py
new file mode 100644
index 0000000..efac46e
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf/utils.py
@@ -0,0 +1,157 @@
+"""Utility functions that invoke operations of simulator script."""
+import os
+import sys
+import time
+import urllib.parse
+import yaml
+from ipaddress import ip_address
+from typing import Dict, Optional
+from decorator import decorator
+import docker
+
+from onapsdk.configuration import settings
+from onaptests.masspnfsimulator.MassPnfSim import (
+ MassPnfSim, get_parser
+)
+
+def get_config() -> Dict:
+ """Read a config YAML file."""
+ config = None
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ with open(f"{dir_path}/pnf_config.yaml", "r") as ymlfile:
+ config = yaml.load(ymlfile)
+ return config
+
+def get_default_args() -> None:
+ """Prepare default arguments for required operations.
+
+ Returns:
+ args (argparse.Namespace): default arguments.
+
+ """
+ parser = get_parser()
+ args = parser.parse_args('')
+ return args
+
+def switch_workdir(back_pwd: str = None) -> Optional[str]:
+ """Switch work directory temporarily for PNF simulator operations.
+
+ When `back_pwd` path is provided, it means go back tp the repository
+ you came from.
+
+ Arguments:
+ back_pwd: path to go back to.
+
+ Returns:
+ old_pwd (str): previous path.
+
+ """
+ sim_file_path = sys.modules[MassPnfSim.__module__].__file__
+ sim_dir_path = os.path.dirname(sim_file_path)
+
+ old_pwd = os.getcwd()
+
+ if not back_pwd:
+ curr_pwd = sim_dir_path
+ else:
+ curr_pwd = back_pwd
+
+ os.chdir(curr_pwd)
+ return old_pwd
+
+@decorator
+def chdir(func, *args, **kwargs):
+ """Switches to and from the simulator workspace."""
+ old_pwd = switch_workdir()
+ ret = func(*args, **kwargs)
+ switch_workdir(old_pwd)
+ return ret
+
+@chdir
+def build_image() -> None:
+ """Build simulator image."""
+ build = getattr(MassPnfSim(), "build")
+ args = get_default_args()
+ build(args)
+
+@chdir
+def remove_image() -> None:
+ """Remove simulator image(s)."""
+ client = docker.from_env()
+ sim_image_name = "nexus3.onap.org:10003/onap/masspnf-simulator"
+ images = client.images.list(sim_image_name)
+ for obj in images:
+ client.images.remove(obj.id, force=True)
+
+@chdir
+def bootstrap_simulator() -> None:
+ """Setup simulator(s) repo, data and configs."""
+ args = get_default_args()
+ config = get_config()
+
+ # collect settings that will be placed in the simulator directory
+ vesprotocol = config["setup"].get('vesprotocol', "http")
+ ves_url = urllib.parse.urlparse(settings.VES_URL)
+ vesip = ves_url.hostname
+ vesport = ves_url.port
+ vesresource = config["setup"].get('vesresource', "")
+ vesversion = config["setup"].get('vesversion', "")
+
+ urlves = f"{vesprotocol}://{vesip}:{vesport}/{vesresource}/{vesversion}"
+
+ # assign to simulator's arguments
+ args.count = config["setup"].get('count', 1)
+ args.urlves = urlves
+ args.ipstart = ip_address(config["setup"].get('ipstart', ''))
+ args.ipfileserver = config["setup"].get('ipfileserver', '')
+ args.typefileserver = config["setup"].get('typefileserver', '')
+ args.user = config["setup"].get('user', '')
+ args.password = config["setup"].get('password', '')
+
+ # bootstrap with assigned arguments
+ bootstrap = getattr(MassPnfSim(), "bootstrap")
+ bootstrap(args)
+
+@chdir
+def run_container() -> None:
+ """Run simulator container(s)."""
+ start = getattr(MassPnfSim(), "start")
+ args = get_default_args()
+ start(args)
+
+@chdir
+def register() -> None:
+ """Send an event to VES.
+
+ Use time.sleep(seconds) if registering with VES right after run_container().
+ Containers take a few seconds to run properly. Normally 5 seconds should be
+ enough.
+
+ """
+ time.sleep(5)
+ config = get_config()
+ trigger = getattr(MassPnfSim(), "trigger")
+ args = get_default_args()
+
+ args.user = config['setup'].get('user', '')
+ args.password = config['setup'].get('password', '')
+
+ custom_data = config['data']
+ if custom_data:
+ args.data = custom_data
+
+ trigger(args)
+
+@chdir
+def stop_container() -> None:
+ """Stop simulator container(s)."""
+ stop = getattr(MassPnfSim(), "stop")
+ args = get_default_args()
+ stop(args)
+
+@chdir
+def remove_simulator() -> None:
+ """Remove simulator container(s)."""
+ clean = getattr(MassPnfSim(), "clean")
+ args = get_default_args()
+ clean(args)
diff --git a/src/onaptests/steps/simulator/pnf_simulator_cnf/__init__.py b/src/onaptests/steps/simulator/pnf_simulator_cnf/__init__.py
new file mode 100644
index 0000000..477f7ae
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf_simulator_cnf/__init__.py
@@ -0,0 +1 @@
+"""PNF simulator CNF package."""
diff --git a/src/onaptests/steps/simulator/pnf_simulator_cnf/pnf_register.py b/src/onaptests/steps/simulator/pnf_simulator_cnf/pnf_register.py
new file mode 100644
index 0000000..a73f668
--- /dev/null
+++ b/src/onaptests/steps/simulator/pnf_simulator_cnf/pnf_register.py
@@ -0,0 +1,144 @@
+# http://www.apache.org/licenses/LICENSE-2.0
+"""PNF simulator registration module."""
+
+import time
+from typing import Tuple
+
+import requests
+from kubernetes import client, config, watch
+from onapsdk.configuration import settings
+
+from onaptests.steps.base import BaseStep
+from onaptests.steps.instantiate.msb_k8s import CreateInstanceStep
+from onaptests.utils.exceptions import EnvironmentPreparationException
+
+
+class PnfSimulatorCnfRegisterStep(BaseStep):
+ """PNF simulator registration step."""
+
+ def __init__(self, cleanup: bool = False) -> None:
+ """Initialize step.
+
+ Substeps:
+ - CreateInstanceStep.
+ """
+ super().__init__(cleanup=cleanup)
+ self.add_step(CreateInstanceStep(cleanup=cleanup))
+
+ @property
+ def description(self) -> str:
+ """Step description."""
+ return "Register PNF simulator with VES."
+
+ @property
+ def component(self) -> str:
+ """Component name."""
+ return "Environment"
+
+ @staticmethod
+ def is_pnf_pod_running(timeout_seconds=120) -> bool:
+ """Check if PNF simulator pod is running.
+
+ Args:
+ timeout_seconds (int, optional): Timeout. Defaults to 120.
+
+ Returns:
+ bool: True if PNF simulator pod is running, False otherwise
+
+ """
+ config.load_kube_config(settings.K8S_CONFIG)
+ k8s_client: "CoreV1API" = client.CoreV1Api()
+ k8s_watch: "Watch" = watch.Watch()
+ for event in k8s_watch.stream(k8s_client.list_namespaced_pod,
+ namespace=settings.K8S_NAMESPACE,
+ timeout_seconds=timeout_seconds):
+ if event["object"].metadata.name == "pnf-simulator":
+ if not event["object"].status.phase in ["Pending", "Running"]:
+ # Invalid pod state
+ return False
+ return event["object"].status.phase == "Running"
+ return False
+
+ @staticmethod
+ def get_ves_ip_and_port() -> Tuple[str, str]:
+ """Static method to get VES ip address and port.
+
+ Raises:
+ EnvironmentPreparationException: VES pod is not running
+
+ Returns:
+ Tuple[str, str]: VES IP and port
+
+ """
+ config.load_kube_config(settings.K8S_CONFIG)
+ k8s_client: "CoreV1API" = client.CoreV1Api()
+ for service in k8s_client.list_namespaced_service(namespace=settings.K8S_NAMESPACE).items:
+ if service.metadata.name == "xdcae-ves-collector":
+ return service.spec.cluster_ip, service.spec.ports[0].port
+ raise EnvironmentPreparationException("Couldn't get VES ip and port")
+
+ @BaseStep.store_state
+ def execute(self) -> None:
+ """Send PNF registration event."""
+ super().execute()
+ if not self.is_pnf_pod_running():
+ EnvironmentPreparationException("PNF simulator is not running")
+ time.sleep(30.0) # Let's still wait for PNF simulator to make sure it's initialized
+ ves_ip, ves_port = self.get_ves_ip_and_port()
+ response = requests.post(
+ "http://portal.api.simpledemo.onap.org:30999/simulator/event",
+ json={
+ "vesServerUrl": f"https://{ves_ip}:{ves_port}/eventListener/v7",
+ "event": {
+ "event": {
+ "commonEventHeader": {
+ "domain": "pnfRegistration",
+ "eventId": "ORAN_SIM_400600927_2020-04-02T17:20:22.2Z",
+ "eventName": "pnfRegistration",
+ "eventType": "EventType5G",
+ "sequence": 0,
+ "priority": "Low",
+ "reportingEntityId": "",
+ "reportingEntityName": "ORAN_SIM_400600927",
+ "sourceId": "",
+ "sourceName": settings.SERVICE_INSTANCE_NAME,
+ "startEpochMicrosec": 94262132085746,
+ "lastEpochMicrosec": 94262132085746,
+ "nfNamingCode": "sdn controller",
+ "nfVendorName": "sdn",
+ "timeZoneOffset": "+00:00",
+ "version": "4.0.1",
+ "vesEventListenerVersion": "7.0.1"
+ },
+ "pnfRegistrationFields": {
+ "pnfRegistrationFieldsVersion": "2.0",
+ "lastServiceDate": "2019-08-16",
+ "macAddress": "D7:64:C8:CC:E9:32",
+ "manufactureDate": "2019-08-16",
+ "modelNumber": "Simulated Device",
+ "oamV4IpAddress": "172.30.1.6",
+ "oamV6IpAddress": "0:0:0:0:0:ffff:a0a:011",
+ "serialNumber": "Simulated Device",
+ "softwareVersion": "2.3.5",
+ "unitFamily": "Simulated Device",
+ "unitType": "ntsim_oran",
+ "vendorName": "Melacon",
+ "additionalFields": {
+ "oamPort": "830",
+ "protocol": "SSH",
+ "username": "netconf",
+ "password": "netconf",
+ "reconnectOnChangedSchema": "false",
+ "sleep-factor": "1.5",
+ "tcpOnly": "false",
+ "connectionTimeout": "20000",
+ "maxConnectionAttempts": "100",
+ "betweenAttemptsTimeout": "2000",
+ "keepaliveDelay": "120"
+ }
+ }
+ }
+ }
+ }
+ )
+ response.raise_for_status()