def _add_mp_vnfd_to_project(self, mp, ec, template=TEMPLATE_VNFD_MP): """ Uses templates/tango_vnfd_mp.yml as basis, extends it and stores it in project folder. Finally the project.yml is updated. """ tpath = os.path.join( os.path.dirname(os.path.abspath(__file__)), template) vnfd = read_yaml(tpath) # TODO better use template engine like Jinja # replace placeholder fields (this highly depends on used template!) vnfd["name"] = mp.get("name") # allow different containers as parameter study vnfd["virtual_deployment_units"][0]["vm_image"] = mp.get("container") # add manually defined data interface address if mp.get("address"): for cp in vnfd["connection_points"]: if cp.get("id") == "data": cp["address"] = mp.get("address") # write vnfd to project vname = "{}.yaml".format(mp.get("name")) write_yaml(os.path.join(ec.project_path, vname), vnfd) # add vnfd to project.yml ppath = os.path.join(ec.project_path, "project.yml") projd = read_yaml(ppath) projd.get("files").append({ "path": vname, "type": "application/vnd.5gtango.vnfd", "tags": ["eu.5gtango", "mp"] }) write_yaml(ppath, projd) LOG.debug("Added MP VNFD {} to project {}" .format(vname, projd.get("name")))
def load(path): """ Loads the service package contents from the given path. :param path: path to a folder with service package contents. :return: SonataService object. """ # load manifest manifest = read_yaml(os.path.join(path, "META-INF/MANIFEST.MF")) # load nsd nsd = read_yaml( os.path.join(path, relative_path( manifest.get("entry_service_template")))) # load vnfds vnfd_list = list() for ctx in manifest.get("package_content"): if "function_descriptor" in ctx.get("content-type"): vnfd_list.append( read_yaml( os.path.join(path, relative_path(ctx.get("name"))))) # add some meta information metadata = dict() metadata["project_disk_path"] = path # create SonataServicePackage object s = SonataService(manifest, nsd, vnfd_list, metadata) LOG.info( "Loaded SONATA service package contents: {} ({} VNFDs).".format( s, len(vnfd_list))) # create SonataServicePackage object return s
def _load_config(self, path): try: return read_yaml(path) except BaseException as ex: self.logger.error( "Couldn't read config file: '{}'. Abort.".format(path)) self.logger.debug(ex) exit(1)
def _read_vnfds(self, ec): """ Real all VNFDs from given project. Return {path, dict(vnfd)}. """ r = dict() for p in self._get_vnfd_paths(ec): r[p] = read_yaml(p) return r
def _load_config(self, path): try: self.logger.info("Using config: {}".format(path)) return read_yaml(path) except BaseException as ex: self.logger.exception( "Couldn't read config file: '{}'. Abort.".format(path)) self.logger.debug(ex) raise BaseException("Config not found.")
def _get_paths_from_projectdescriptor(self, ec, mime_type): """ Get paths from project.yml for given mime_type. """ projd = read_yaml(os.path.join(ec.project_path, "project.yml")) r = list() for f in projd.get("files"): if f.get("type") == mime_type: r.append(os.path.join(ec.project_path, f.get("path"))) return r
def _gather_project_infos(self, ec): """ Collect additional infors about project and store to ec. e.g. mapping between VNF IDs and names """ # VNF names to ID mapping based on NSD nsd = read_yaml(self._get_nsd_path(ec)) for nf in nsd.get("network_functions"): k = "{}.{}.{}".format(nf.get("vnf_vendor"), nf.get("vnf_name"), nf.get("vnf_version")) ec.function_ids[k] = nf.get("vnf_id")
def _collect_container_results(self, rd): """ Collect ECs from '<container_name>/PATH_CONTAINER_RESULT' """ r = dict() # iterate over all container directories for cd in self._get_container_from_rd(rd): yml = read_yaml(os.path.join(rd, cd, PATH_CONTAINER_RESULT)) for k, v in yml.items(): # add container name as key prefix k = "metric__{}__{}".format(self._get_clean_cname(cd), k) r[k] = v return r
def measurement_point_to_vnfd(mp, ec, template="template/sonata_vnfd_mp.yml"): """ Generates a VNFD data structure using measurement point information from a PED file. VNFD is based on given template. """ template_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), template) vnfd = read_yaml(template_path) # replace placeholder fields (this highly depends on used template!) vnfd["name"] = mp.get("name") # allow different containers as parameter study vnfd["virtual_deployment_units"][0]["vm_image"] = ec.parameter.get( "measurement_point:{}:container".format(mp.get("name"))) return vnfd
def _add_mp_to_nsd(self, mp, ec): """ Add MP to NSD: - add VNF to functions section - connect measurement points w. virt. links - update forwarding graph """ # 1. load NSD nsd = read_yaml(self._get_nsd_path(ec)) # 2. add MP VNF to NSD nsd.get("network_functions").append({ "vnf_id": mp.get("name"), "vnf_name": mp.get("name"), "vnf_vendor": "eu.5gtango.benchmark", "vnf_version": "1.0" }) # 3. connect measurement point to service (replace virt. links) mp_cp = mp.get("connection_point") new_cp = "{}:data".format(mp.get("name")) # update links for vl in nsd.get("virtual_links"): cprs = vl.get("connection_points_reference") # replace ns in/out link endpoints in NSD for i in range(0, len(cprs)): if cprs[i] == mp_cp: cprs[i] = new_cp LOG.debug( "Replaced virtual link CPR '{}' by '{}'" .format(mp_cp, cprs[i])) # 4. update forwarding graph (replace ns in and out) for fg in nsd.get("forwarding_graphs"): # add MP VNF to constituent VNF list fg.get("constituent_vnfs").append(mp.get("name")) # update forwarding paths for fp in fg.get("network_forwarding_paths"): # search and replace connection points specified in PED for fp_cp in fp.get("connection_points"): if fp_cp.get("connection_point_ref") == mp_cp: fp_cp["connection_point_ref"] = new_cp # update number of endpoints fg["number_of_endpoints"] -= 1 LOG.debug("Updated forwarding graph '{}': {}" .format(fg.get("fg_id"), fg)) # 5. store updated nsd write_yaml(self._get_nsd_path(ec), nsd) ec.nsd = nsd # 6. log LOG.debug("Added measurement point VNF '{}' to NDS '{}'" .format(mp.get("name"), nsd.get("name")))
def _collect_vm_results(self, rd): """ Collect ECs from '<vm_name>/PATH_VM_RESULT' """ r = dict() # iterate over all vm directories for cd in self._get_vm_from_rd(rd): try: yml = read_yaml(os.path.join(rd, cd, PATH_VM_RESULT)) for k, v in yml.items(): # add vm name as key prefix k = "metric__{}__{}".format(self._get_clean_cname(cd), k) r[k] = v except BaseException as ex: LOG.warning("Couldn't process all vm results: {}".format(ex)) return r
def _load_ped_file(self, ped_path): """ Loads the specified PED file. :param ped_path: path to file :return: dictionary """ yml = None try: yml = read_yaml(ped_path) if yml is None: raise BaseException("PED file YAML error.") except BaseException: self.logger.error("Couldn't load PED file %r. Abort." % ped_path) exit(1) # add path annotation to ped file (simpler # handling of referenced artifacts) yml["ped_path"] = ped_path self.logger.info("Loaded PED file %r." % ped_path) return yml
def _embed_function_into_experiment_nsd( self, service, ec, template="template/sonata_nsd_function_experiment.yml"): """ Generates a NSD that contains the single VNF of the given function experiment and embeds the specified function into it. The new NSD overwrites the existing NSD in service. This unifies the follow up procedures for measurement point inclusion etc. The NSD template for this can be found in the template/ folder. """ template_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), template) new_nsd = read_yaml(template_path) # 1. update VNF section old_vnf_dict = None for vnf in service.nsd.get("network_functions"): if str(vnf.get("vnf_name")) in ec.experiment.function: old_vnf_dict = vnf if old_vnf_dict is None: LOG.error("Couldn't find function '{}' in service '{}'".format( ec.experiment.function, service)) new_vnf_dict = new_nsd.get("network_functions")[0] new_vnf_dict.update(old_vnf_dict) LOG.debug("Updated VNF section in '{}': {}".format( service, new_vnf_dict)) # 1.5 remove obsolete VNFDs old_list = service.vnfd_list.copy() service.vnfd_list = list() for vnfd in old_list: if vnfd.get("name") == new_vnf_dict.get("vnf_name"): service.vnfd_list.append(vnfd) LOG.debug("Updated VNFD list in '{}': {}".format( service, service.vnfd_list)) # 2. update virtual link section (get first three CPs from VNFD) # TODO remove order assumptions (current version is more a HACK!) vnfd = service.get_vnfd_by_uid(ec.experiment.function) new_link_list = new_nsd.get("virtual_links") cp_ids = [cp.get("id") for cp in vnfd.get("connection_points")] for i in range(0, min(len(new_link_list), len(cp_ids))): cpr = new_link_list[i]["connection_points_reference"] for j in range(0, len(cpr)): if "test_vnf" in cpr[j]: cpr[j] = "{}:{}".format(new_vnf_dict.get("vnf_id"), cp_ids[i]) LOG.debug("Updated VLink section in '{}': {}".format( service, new_link_list)) # 3. update forwarding path section # TODO remove order assumptions (current version is more a HACK!) for fg in new_nsd.get("forwarding_graphs"): fg.get("constituent_vnfs")[0] = new_vnf_dict.get("vnf_id") for nfp in fg.get("network_forwarding_paths"): nfp_cp_list = nfp.get("connection_points") for i in range(1, min(len(nfp_cp_list), len(cp_ids))): if "test_vnf" in nfp_cp_list[i].get( "connection_point_ref"): nfp_cp_list[i]["connection_point_ref"] = ( "{}:{}".format(new_vnf_dict.get("vnf_id"), cp_ids[i])) LOG.debug("Updated forwarding graph section in '{}': {}".format( service, new_nsd.get("forwarding_graphs"))) # 4. replace NSD service.nsd = new_nsd
import pickle # from tngsdk.benchmark import * from unittest.mock import Mock from tngsdk.benchmark.helper import read_yaml # tng-bench startup arguments args = [ "--ped", "path/to/some/pedfile.yml", "--generator", "opensourcemano", "--config", ".tng-bench.conf", ] ped_file = os.path.join(os.getcwd(), 'examples-osm/peds/ped_example_vnf.yml') ped = read_yaml(ped_file) service_ex_fpath = os.path.join( os.getcwd(), 'src/tngsdk/benchmark/tests/test_osm_pdriver/fixtures/service_ex.obj') with open(service_ex_fpath, 'rb') as config_dictionary_file: service_ex = pickle.load(config_dictionary_file) print(service_ex) args_fpath = os.path.join( os.getcwd(), 'src/tngsdk/benchmark/tests/test_osm_pdriver/fixtures/args.obj') with open(args_fpath, 'rb') as config_dictionary_file: args_obj = pickle.load(config_dictionary_file) print(args_obj)
def test_generate_projects(self): """ Test the generation of experiment projects / packages using the give base package / project and test experiments. """ args = parse_args(["-p", TEST_PED_FILE, "-v"]) # generate test experiments based on PED ex_list = self._generate_experiments_from_ped(args) self.assertEqual(1, len(ex_list)) for ex in ex_list: self.assertEqual(32, len(ex.experiment_configurations)) # run the generator with test experiments g = TangoServiceConfigurationGenerator(args) g.generate(TEST_TNG_PKG, None, ex_list) # check results # import pdb; pdb.set_trace() for ex in ex_list: for ec in ex.experiment_configurations: prj_p = ec.project_path self.assertTrue(os.path.exists(prj_p)) self.assertIsNotNone(prj_p) # check generated project artifacts exist self.assertTrue(os.path.exists( os.path.join(prj_p, "project.yml"))) self.assertTrue(os.path.exists( os.path.join(prj_p, "sources/Definitions/mynsd.yaml"))) self.assertTrue(os.path.exists( os.path.join(prj_p, "sources/Definitions/myvnfd.yaml"))) self.assertTrue(os.path.exists( os.path.join(prj_p, "mp.input.yaml"))) self.assertTrue(os.path.exists( os.path.join(prj_p, "mp.output.yaml"))) # check MPs are in NSD nsd = read_yaml( os.path.join(prj_p, "sources/Definitions/mynsd.yaml")) self.assertIn("mp.input", [nf.get("vnf_name") for nf in nsd.get("network_functions")]) self.assertIn("mp.output", [nf.get("vnf_name") for nf in nsd.get("network_functions")]) # TODO check correct forwarding path, CPs, and links # check config. params. of ec are in VNFD vnfd = read_yaml( os.path.join(prj_p, "sources/Definitions/myvnfd.yaml")) vdu = vnfd.get( "virtual_deployment_units")[0] # self.assertIn("vm_cmd_start", vdu) # disabled # self.assertIn("vm_cmd_stop", vdu) # disabled # self.assertIn("cmd_start", vdu.get("vm_cmd_start")) # self.assertIn("cmd_stop", vdu.get("vm_cmd_stop")) # self.assertIn(vnfd.get("name"), vdu.get("vm_cmd_start")) # self.assertIn(vnfd.get("name"), vdu.get("vm_cmd_stop")) rl = vdu.get("resource_requirements") self.assertIsNotNone(rl) self.assertIn("cpu", rl) self.assertIn("memory", rl) self.assertIn("storage", rl) self.assertIn("cpu_bw", rl.get("cpu")) self.assertIn("vcpus", rl.get("cpu")) self.assertIn("size", rl.get("memory")) self.assertIn("size", rl.get("storage")) self.assertIsInstance(rl.get("cpu").get("cpu_bw"), float) self.assertIsInstance(rl.get("cpu").get("vcpus"), str) self.assertIsInstance(rl.get("memory").get("size"), int) self.assertIsInstance(rl.get("storage").get("size"), int) # TODO check if values are the same as in ec # check generated package artifacts exist pkg_p = ec.package_path self.assertTrue(os.path.exists(pkg_p))