def test_system_template(self): tpl_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/topology_template/system.yaml") system_tosca_template = ToscaTemplate(tpl_path) self.assertIsNotNone(system_tosca_template) self.assertEqual( len(system_tosca_template. nested_tosca_templates_with_topology), 4) self.assertTrue(system_tosca_template.has_nested_templates())
def test_local_template_with_url_import(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress_with_url_import.yaml") tosca = ToscaTemplate(tosca_tpl) self.assertTrue(tosca.topology_template.custom_defs)
def orchetration(path, parsed_params, a_file, stack_name): tosca = ToscaTemplate(path, parsed_params, a_file) translator = TOSCATranslator(tosca, parsed_params) translator.translate() decomposed_request = request_decomposition(tosca, translator, stack_name, False) '''Calling Placement Module''' s = requests.Session() print("[POSTing] from the orchestrator to the placement module: {} \n".format(PLACEMENT_URL)) placement_headers = {} placement_headers['content-type'] = 'application/json' placement_headers['algorithm'] = 'greedy' placement_headers['version'] = str(credentials.VERSION) placement_headers['username'] = credentials.USERNAME placement_headers['password'] = credentials.PASSWORD placement_headers['endpoint'] = credentials.ENDPOINT placement_headers['tenant_name'] = credentials.TENANT_NAME placement_headers['tenant_id'] = credentials.TENANT_ID placement_headers['service'] = credentials.SERVICE placement_headers['region'] = credentials.REGION r = s.post(PLACEMENT_URL, data=decomposed_request['request'], headers=placement_headers, stream=False) '''Calling Request Manager to update NCT template''' if r.status_code == 200: zone_to_host = MappingZoneHost() location = {} for key, value in json.loads(r.text).iteritems(): location[key] = str(zone_to_host[value]) decomposed_request['nct'] = add_vm_location(translator, location) decomposed_request['nct'] = add_odl_address(translator, location) '''Calling NCT Manager to instantiate NCT template''' s = requests.Session() print("[POSTing] from the orchestrator to the NCT Manager module: {} \n".format(NCT_Manager_stack_create_URL)) headers = {} headers['content-type'] = 'application/json' headers['version'] = str(credentials.VERSION) headers['username'] = credentials.USERNAME headers['password'] = credentials.PASSWORD headers['endpoint'] = credentials.ENDPOINT headers['tenant_name'] = credentials.TENANT_NAME headers['tenant_id'] = credentials.TENANT_ID headers['service'] = credentials.SERVICE headers['region'] = credentials.REGION headers['heat_url'] = credentials.HEAT_URL headers['stack_name'] = 'nct_' + stack_name r = s.post(NCT_Manager_stack_create_URL, data=decomposed_request['nct'], headers=headers, stream=False) if r.status_code == 200: uuid = r.text '''Calling NCT Manager to get NCT template output''' # uuid = 'cc4d6e33-d0aa-4fbd-9322-97d61f757a9f' s = requests.Session() print("[GETing] from the orchestrator to the NCT Manager module: {} \n".format(NCT_Manager_stack_output_URL)) headers['uuid'] = uuid r = s.get(NCT_Manager_stack_output_URL, data=decomposed_request['output'], headers=headers, stream=False) '''Calling Request Manager to update sf and sff templates''' if r.status_code == 200: sf_sff_template = update_sf_sff_templates(decomposed_request['sf'], decomposed_request['sff'], r.text) decomposed_request['sf'] = sf_sff_template['sf'] decomposed_request['sff'] = sf_sff_template['sff'] '''Calling SFC Manager to instantiate VNFs resources''' s = requests.Session() print("[POSTing] from the orchestrator to the SFC Manager module: {} \n".format(VNF_URL)) r = s.post(VNF_URL, data=json.dumps(decomposed_request['sf']), headers={'content-type': 'application/json'}, stream=False) if r.status_code in {200,201}: print("====>VNF Creation successfully") else: print("====>VNF Failure, status code: {} \n".format(r.status_code)) '''Calling SFC Manager to instantiate CPs resources''' print("[POSTing] from the orchestrator to the SFC Manager module: {} \n".format(CP_URL)) r = s.post(CP_URL, data=json.dumps(decomposed_request['sff']), headers={'content-type': 'application/json'}, stream=False) if r.status_code in {200,201}: print("====>CP Creation successfully") else: print("====>CP Failure, status code: {} \n".format(r.status_code)) '''Calling SFC Manager to instantiate SFC resources''' print("[POSTing] from the orchestrator to the SFC Manager module: {} \n".format(VNF_FG_URL)) r = s.post(VNF_FG_URL, data=json.dumps(decomposed_request['sfc']), headers={'content-type': 'application/json'}, stream=False) if r.status_code in {200,201}: print("====>VNF-FG Creation successfully") else: print("====>VNF-FG Failure, status code: {} \n".format(r.status_code)) '''Calling SFC Manager to instantiate SFPs resources''' print("[POSTing] from the orchestrator to the SFC Manager module: {} \n".format(FP_URL)) r = s.post(FP_URL, data=json.dumps(decomposed_request['sfp']), headers={'content-type': 'application/json'}, stream=False) if r.status_code in {200,201}: print("====>FP Creation successfully") else: print("====>FP Failure, status code: {} \n".format(r.status_code)) '''Calling SFC Manager to instantiate RSPs resources''' print("[POSTing] from the orchestrator to the SFC Manager module: {} \n".format(RFP_URL)) r = s.post(RFP_URL, data=json.dumps(decomposed_request['rsp']), headers={'content-type': 'application/json'}, stream=False) if r.status_code in {200,201}: print("====>RFP Creation successfully") else: print("====>RFP Failure, status code: {} \n".format(r.status_code))
def build_graph_from_project(self, json_project, model={}): """Creates a single graph for a whole project json_project is the dict representation of the project """ graph_object = { 'vertices': [], 'edges': [], 'graph_parameters': {}, 'model': model } try: positions = json_project[ 'positions'] if 'positions' in json_project else False log.debug('build graph from project json') # print json.dumps(json_project, sort_keys=True, indent=4, separators=(',', ': ')) # print json_project['toscayaml'] # print json.dumps(json_project['toscayaml'], sort_keys=True, indent=4, separators=(',', ': ')) #path = '/home/user/RDCL/heat-translator/translator/tests/data/network/tosca_two_servers_one_network.yaml' # tosca = ToscaTemplate(path, parsed_params, a_file) for toscayaml_name in json_project['toscayaml'].keys(): print("\ntoscayaml_nameeeeeeeeeeeeeeeeeeeeeeeeee: " + toscayaml_name) #tosca = ToscaTemplate('/home/kaarot_kalel_90/PycharmProjects/test-rdcl/code/usecases/TOSCA/Sample-tosca-nfv/YAML/ns.yaml') tosca = ToscaTemplate( None, {}, False, yaml_dict_tpl=json_project['toscayaml'][toscayaml_name], project=json_project['toscayaml']) #tosca = TOSCATranslator('/home/kaarot_kalel_90/PycharmProjects/test-rdcl/code/usecases/TOSCA/Sample-tosca-nfv/YAML/ns.yaml',{}) version = tosca.version if tosca.version: print("\nversion: " + version) if hasattr(tosca, 'description'): description = tosca.description if description: print("\ndescription: " + description) if hasattr(tosca, 'inputs'): inputs = tosca.inputs if inputs: print("\ninputs:") for input in inputs: print("\t" + input.name) if hasattr(tosca, 'nodetemplates'): nodetemplates = tosca.nodetemplates if nodetemplates: print("\nnodetemplates:") for node in nodetemplates: print("\t" + node.name) if hasattr(tosca, 'outputs'): outputs = tosca.outputs if outputs: print("\noutputs:") for output in outputs: print("\t" + output.name) if hasattr(tosca, 'graph'): # For the moment, we consider a single view called 'graph' #print tosca.nested_tosca_tpls_with_topology for node in tosca.graph.nodetemplates: if node.name in tosca.graph.vertices: print 'node ' + node.name + ' is related to:' # self.add_node(node.name, node.type, 'vnf', positions, graph_object) #def add_node(id, type, group, positions, graph_object): type = node.type parent_node = node while type not in model['nodes'].keys(): type = parent_node.parent_type.type parent_node = parent_node.parent_type self.add_node(node.name, type, toscayaml_name, positions, graph_object) print 'primaaaaaaaaaaa' related = tosca.graph.vertex( node.name).related_nodes print 'doppooooo' for related_node in related: print related_node.name + '->' + tosca.graph.vertex( node.name).related[related_node].type #def add_link(source, target, view, group, graph_object ) self.add_link(node.name, related_node.name, 'toscayaml', toscayaml_name, graph_object) else: log.debug('tosca template has no graph') # #THIS IS FOR THE TRANSLATION INTO HOT TEMPLATES # translator = TOSCATranslator(tosca, {}, False, # csar_dir=None) # yaml_files = translator.output_to_yaml_files_dict('output.yaml') # for name, content in six.iteritems(yaml_files): # if name != "output.yaml": # with open(name, 'w+') as f: # f.write(content) # print(yaml_files['output.yaml']) except Exception as e: print e log.error('Exception in build_graph_from_project') raise return graph_object
def setUp(self): """ Setup Validator object and prep a bad TOSCA template """ self.config_path = "tests/configs/key_config.yaml" self.bad_tpl = ToscaTemplate("tests/templates/bad_tosca.yaml") self.good_tpl = ToscaTemplate("tests/templates/good_tosca.yaml")
def test_custom_capability(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_custom_capabilty.yaml") ToscaTemplate(tosca_tpl)
def test_endpoint_on_compute(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_endpoint_on_compute.yaml") ToscaTemplate(tosca_tpl)
def test_custom_caps_with_custom_datatype(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_custom_caps_with_datatype.yaml") ToscaTemplate(tosca_tpl)
def main(self, argv): parser = self.get_parser(argv) (args, args_list) = parser.parse_known_args(argv) template_file = args.template_file template_type = args.template_type output_file = args.output_file validate_only = args.validate_only deploy = args.deploy stack_name = args.stack_name parsed_params = {} if args.parameters: parsed_params = self._parse_parameters(args.parameters) a_file = os.path.isfile(template_file) a_url = UrlUtils.validate_url(template_file) if not a_file else False if a_file or a_url: if validate_only: ToscaTemplate(template_file, parsed_params, a_file) msg = (_('The input "%(template_file)s" successfully passed ' 'validation.') % {'template_file': template_file}) print(msg) else: if keystone_client_avail: try: keystone_auth = ( loading.load_auth_from_argparse_arguments(args) ) keystone_session = ( loading.load_session_from_argparse_arguments( args, auth=keystone_auth ) ) images.SESSION = keystone_session flavors.SESSION = keystone_session except Exception: keystone_session = None hot = self._translate(template_type, template_file, parsed_params, a_file, deploy) if hot and deploy: if not keystone_client_avail or not heat_client_avail: raise RuntimeError(_('Could not find Heat or Keystone' 'client to deploy, aborting ')) if not keystone_session: raise RuntimeError(_('Impossible to login with ' 'Keystone to deploy on Heat, ' 'please check your credentials')) file_name = os.path.basename( os.path.splitext(template_file)[0]) self.deploy_on_heat(keystone_session, keystone_auth, hot, stack_name, file_name, parsed_params) self._write_output(hot, output_file) else: msg = (_('The path %(template_file)s is not a valid ' 'file or URL.') % {'template_file': template_file}) log.error(msg) raise ValueError(msg)
if __name__ == "__main__": logging.basicConfig(level=logging.INFO) if sys.argv[1] == "test_local": tosca_path = "../TOSCA/" input_tosca_file_path = tosca_path + '/application_example_updated.yaml' conf = {'url': "http://host"} spec_service = SpecService(conf) test_planner = Planner(input_tosca_file_path, spec_service) test_tosca_template = test_planner.resolve_requirements() test_tosca_template = test_planner.set_node_templates_properties() template_dict = tosca_helper.get_tosca_template_2_topology_template_dictionary( test_tosca_template) logger.info("template ----: \n" + yaml.dump(template_dict)) ToscaTemplate(yaml_dict_tpl=copy.deepcopy(template_dict)) test_response = {'toscaTemplate': template_dict} logger.info("Output message:" + json.dumps(test_response)) else: logger.info("Input args: " + sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2]) global channel global connection channel, connection = init_chanel(sys.argv) global queue_name queue_name = sys.argv[2] # thread = Thread(target=threaded_function, args=(1,)) # thread.start()
def translate(template_file, validate_only, provider, configuration_tool, cluster_name, is_delete=False, a_file=True, extra=None, log_level='info', host_ip_parameter='public_address', public_key_path='~/.ssh/id_rsa.pub', debug=False): """ Main function, is called by different shells, i.e. bash, Ansible module, grpc :param template_file: filename of TOSCA template or TOSCA template data if a_file is False :param validate_only: boolean, if template should be only validated :param provider: key of cloud provider :param configuration_tool: key of configuration tool :param cluster_name: name to point to desired infrastructure as one component :param is_delete: generate dsl scripts for infrastructure deletion :param a_file: if template_file is filename :param extra: extra for template :return: string that is a script to deploy or delete infrastructure """ log_map = dict(debug=logging.DEBUG, info=logging.INFO, warning=logging.WARNING, error=logging.ERROR, critical=logging.ERROR) logging_format = "%(asctime)s %(levelname)s %(message)s" logging.basicConfig(filename=os.path.join(os.getenv('HOME'), '.clouni.log'), filemode='a', level=log_map[log_level], format=logging_format, datefmt='%Y-%m-%d %H:%M:%S') logging.info( "Started translation of TOSCA template \'%s\' for provider \'%s\' and configuration tool \'%s\'" % (template_file if a_file else 'raw', provider, configuration_tool)) logging.info("Cluster name set to \'%s\'" % cluster_name) logging.info("Deploying script for cluster %s will be created" % 'deletion' if is_delete else 'creation') logging.info( "Extra parameters to the unit of deployment scripts will be added: %s" % json.dumps(extra)) logging.info("Log level is set to %s" % log_level) config = Configuration() for sec in REQUIRED_CONFIGURATION_PARAMS: if sec not in config.get_section(config.MAIN_SECTION).keys(): logging.error( 'Provider configuration parameter "%s" is missing in configuration file' % sec) sys.exit(1) if a_file: template_file = os.path.join(os.getcwd(), template_file) with open(template_file, 'r') as f: template_content = f.read() else: template_content = template_file try: template = yaml.load(template_content, Loader=yaml.SafeLoader) except yaml.scanner.ScannerError as e: logging.error("Error parsing TOSCA template: %s%s" % (e.problem, e.context_mark)) sys.exit(1) def_files = config.get_section( config.MAIN_SECTION).get(TOSCA_ELEMENTS_DEFINITION_FILE) if isinstance(def_files, six.string_types): def_files = [def_files] default_import_files = [] for def_file in def_files: default_import_files.append( os.path.join(utils.get_project_root_path(), def_file)) logging.info( "Default TOSCA template definition file to be imported \'%s\'" % json.dumps(default_import_files)) # Add default import of normative TOSCA types to the template template[IMPORTS] = template.get(IMPORTS, []) for i in range(len(template[IMPORTS])): if isinstance(template[IMPORTS][i], dict): for import_key, import_value in template[IMPORTS][i].items(): if isinstance(import_value, six.string_types): template[IMPORTS][i] = import_value elif isinstance(import_value, dict): if import_value.get('file', None) is None: logging.error( "Imports %s doesn't contain \'file\' key" % import_key) sys.exit(1) else: template[IMPORTS][i] = import_value['file'] if import_value.get('repository', None) is not None: logging.warning( "Clouni doesn't support imports \'repository\'") template[IMPORTS].extend(default_import_files) for i in range(len(template[IMPORTS])): template[IMPORTS][i] = os.path.abspath(template[IMPORTS][i]) try: tosca_parser_template_object = ToscaTemplate(yaml_dict_tpl=template, a_file=a_file) except: logging.exception("Got exception from OpenStack tosca-parser") sys.exit(1) # After validation, all templates are imported if validate_only: msg = 'The input "%(template_file)s" successfully passed validation.' \ % {'template_file': template_file if a_file else 'TOSCA template'} return msg if not provider: logging.error( "Provider must be specified unless \'validate-only\' flag is used") sys.exit(1) map_files = config.get_section( config.MAIN_SECTION).get(TOSCA_ELEMENTS_MAP_FILE) if isinstance(map_files, six.string_types): map_files = [map_files] default_map_files = [] for map_file in map_files: default_map_files.append( os.path.join(utils.get_project_root_path(), map_file)) logging.info("Default TOSCA template map file to be used \'%s\'" % json.dumps(default_map_files)) # Parse and generate new TOSCA service template with only provider specific TOSCA types from normative types tosca = ProviderToscaTemplate(tosca_parser_template_object, provider, configuration_tool, cluster_name, host_ip_parameter, public_key_path, is_delete, common_map_files=default_map_files) # Init configuration tool class tool = get_configuration_tool_class(configuration_tool)() default_artifacts_directory = config.get_section( config.MAIN_SECTION).get(DEFAULT_ARTIFACTS_DIRECTORY) # Copy used conditions from intermediate service template if tosca.used_conditions_set: tool.copy_conditions_to_the_directory(tosca.used_conditions_set, default_artifacts_directory) # Manage new artifacts for intermediate template tool_artifacts = [] for art in tosca.artifacts: executor = art.get(EXECUTOR) if bool(executor) and executor != configuration_tool: art_list = [art] configuration_class = get_configuration_tool_class( art['executor'])() _, new_art = utils.generate_artifacts(configuration_class, art_list, default_artifacts_directory) tosca.artifacts.append(new_art) else: tool_artifacts.append(art) if not extra: extra = {} extra_full = utils.deep_update_dict( extra, tosca.extra_configuration_tool_params.get(configuration_tool, {})) configuration_content = tool.to_dsl( tosca.provider, tosca.provider_operations, tosca.reversed_provider_operations, tosca.cluster_name, is_delete, artifacts=tool_artifacts, target_directory=default_artifacts_directory, inputs=tosca.inputs, outputs=tosca.outputs, extra=extra_full, debug=debug) return configuration_content
def test_csar_multilevel_imports_relative_path(self): csar_archive = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data/CSAR/csar_relative_path_import_check.zip') self.assertTrue(ToscaTemplate(csar_archive))
def parse(inputFile, outputFile): # parse TOSCA file app = ToscaTemplate(inputFile, None, True) # retrieve nodes and relationships nodes = [] hRels = [] vRels = [] for n in app.nodetemplates: # get current node - represented as [name, type] node = [] nodeName = n.name.replace("-", "_") node.append(nodeName) nodeTypeTokens = n.type.split(".") nodeType = nodeTypeTokens[0] for i in range(1, len(nodeTypeTokens)): token = nodeTypeTokens[i] upperToken = "" + token[0].upper() upperToken = upperToken + token[1:] nodeType = nodeType + upperToken node.append(nodeType) nodes.append(node) for requirementMap in n.requirements: # get current relationship - represented as [source, target] relationship = [] for requirementName in requirementMap.keys(): # get relationship's source relationship.append(n.name) # get relationship's target requirement = requirementMap.get(requirementName) try: relationship.append(requirement.get("node")) except AttributeError: relationship.append(requirement) # classify relationship as vertical or horizontal if requirementName == "host": vRels.append(relationship) else: hRels.append(relationship) # adds bottom node (if needed) bottomNodes = [] for node in nodes: nodeName = node[0] isBottom = True for vRel in vRels: source = vRel[0] if source == nodeName: isBottom = False if isBottom: bottomNodes.append(node) if len(bottomNodes) > 1: bottom = ["bottom", "bottom"] nodes.append(bottom) for node in bottomNodes: relToBottom = [] relToBottom.append(node[0]) relToBottom.append("bottom") vRels.append(relToBottom) # create "output" folder (if not existing yet) try: os.mkdir("output") except Exception as e: if e.errno != errno.EEXIST: print(e) # output nodes and relationship on file outputFileWithFolder = "output/" + outputFile output = open(outputFileWithFolder, "w") for node in nodes: writeNodeOnFile(output, node) output.write("\n") for hRel in hRels: writeRelationshipOnFile(output, hRel, "h") output.write("\n") for vRel in vRels: writeRelationshipOnFile(output, vRel, "v") output.close()
def renv(request): path = os.path.join(BASE_DIR, "userData") with open(os.path.join(path, "access.txt"), 'r') as source: DISP = (source.read() == "True") #if not DISP: originalToscaDefPath = os.path.join( BASE_DIR, "toscaparser/elements/TOSCA_definition_1_0.yaml") secureToscaDefPath = os.path.join( BASE_DIR, "toscaparser/secure/TOSCA_definition_1_0.yaml") #try: temp = ToscaTemplate(os.path.join(path, request.POST["path"])) #except: # restaurer le tosca definition original # with open(secureToscaDefPath, 'rb') as definition: # with open(originalToscaDefPath, 'wb+') as destination: # destination.write(definition.read()) # with open(path+'access.txt', 'w') as source: # source.write("True") # raise Http404("Erreur type node") graphe = temp.graph nodes = graphe.nodetemplates mon_fichier = open(os.path.join(path, request.POST["path"]), "r") file = mon_fichier.read() cpt = 0 id_node = 0 noeuds = dict() rel = dict() nature = str() src = 0 for noeud in nodes: noeuds[id_node] = { 'name': noeud.name, 'type': noeud.type.replace("tosca.nodes.", '') } id_node = id_node + 1 for noeud in nodes: for require in noeud.requirements: for key in require.keys(): if (key == "host"): for cle, val in noeuds.items(): if val["name"] == require.get(key): dest = cle if val["name"] == noeud.name: src = cle rel[cpt] = { 'type': 'hostedOn', 'nsrc': noeud.name, 'ndest': require.get(key), 'source': src, 'dest': dest } cpt = cpt + 1 else: values = require.get(key) for value in values: if (value == "node"): for cle, val in noeuds.items(): if val["name"] == values.get(value): dest = cle if val["name"] == noeud.name: src = cle if (value == "relationship"): nature = values.get(value).replace( "tosca.relationships.", '') rel[cpt] = { 'type': nature, 'nsrc': noeud.name, 'ndest': require.get(key), 'source': src, 'dest': dest } cpt = cpt + 1 print(noeuds) # restaurer le tosca definition original #with open(secureToscaDefPath, 'rb') as definition: # with open(originalToscaDefPath, 'wb+') as destination: # destination.write(definition.read()) with open(path + 'access.txt', 'w') as source: source.write("True") return render(request, 'graphGenerator/graph.html', { 'noeuds': noeuds, 'relations': rel, 'file': file })
def main(self, args): # TODO(spzala): set self.deploy based on passed args once support for # --deploy argument is enabled. self.deploy = False self._validate(args) path = args[0].split('--template-file=')[1] # e.g. --template_file=translator/tests/data/tosca_helloworld.yaml template_type = args[1].split('--template-type=')[1] # e.g. --template_type=tosca if not template_type: msg = _("Template type is needed. For example, 'tosca'") log.error(msg) raise ValueError(msg) elif template_type not in self.SUPPORTED_TYPES: msg = _("%(value)s is not a valid template type.") % { 'value': template_type } log.error(msg) raise ValueError(msg) parsed_params = {} validate_only = None output_file = None if len(args) > 2: parameters = None for arg in args: if "--validate-only=" in arg: validate_only = arg if "--parameters=" in arg: parameters = arg if "--output-file=" in arg: output = arg output_file = output.split('--output-file=')[1] if parameters: parsed_params = self._parse_parameters(parameters) a_file = os.path.isfile(path) a_url = UrlUtils.validate_url(path) if not a_file else False if a_file or a_url: run_only_validation = False if validate_only: value = validate_only.split('-validate-only=')[1].lower() if template_type == 'tosca' and value == 'true': run_only_validation = True if run_only_validation: ToscaTemplate(path, parsed_params, a_file) msg = (_('The input "%(path)s" successfully passed ' 'validation.') % { 'path': path }) print(msg) else: log.info( _('Checked whether template path is a file or url path.')) heat_tpl = self._translate(template_type, path, parsed_params, a_file) if heat_tpl: self._write_output(heat_tpl, output_file) else: msg = _("The path %(path)s is not a valid file or URL.") % { 'path': path } log.error(msg) raise ValueError(msg)
def test_repositories_definition(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/repositories/test_repositories_definition.yaml") ToscaTemplate(tosca_tpl)
def _load_template(self, filename): return ToscaTemplate(os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data', filename), parsed_params={'db_root_pwd': '1234'})
def test_containers(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/containers/test_container_docker_mysql.yaml") ToscaTemplate(tosca_tpl, parsed_params={"mysql_root_pwd": "12345678"})
class IntrinsicFunctionsTest(TestCase): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") params = { 'db_name': 'my_wordpress', 'db_user': '******', 'db_root_pwd': '12345678' } tosca = ToscaTemplate(tosca_tpl, parsed_params=params) def _get_node(self, node_name, tosca=None): if tosca is None: tosca = self.tosca return [ node for node in tosca.nodetemplates if node.name == node_name ][0] def _get_operation(self, interfaces, operation): return [ interface for interface in interfaces if interface.name == operation ][0] def _get_property(self, node_template, property_name): return [ prop.value for prop in node_template.get_properties_objects() if prop.name == property_name ][0] def _get_inputs_dict(self): inputs = {} for input in self.tosca.inputs: inputs[input.name] = input.default return inputs def _get_input(self, name): self._get_inputs_dict()[name] def test_get_property(self): wordpress = self._get_node('wordpress') operation = self._get_operation(wordpress.interfaces, 'configure') wp_db_password = operation.inputs['wp_db_password'] self.assertIsInstance(wp_db_password, functions.GetProperty) result = wp_db_password.result() self.assertEqual('wp_pass', result) def test_get_property_with_input_param(self): wordpress = self._get_node('wordpress') operation = self._get_operation(wordpress.interfaces, 'configure') wp_db_user = operation.inputs['wp_db_user'] self.assertIsInstance(wp_db_user, functions.GetProperty) result = wp_db_user.result() self.assertEqual('my_db_user', result) def test_unknown_capability_property(self): self.assertRaises(exception.ValidationError, self._load_template, 'functions/test_unknown_capability_property.yaml') exception.ExceptionCollector.assertExceptionMessage( KeyError, _('\'Property "unknown" was not found in capability ' '"database_endpoint" of node template "database" referenced ' 'from node template "database".\'')) def test_get_input_in_properties(self): mysql_dbms = self._get_node('mysql_dbms') expected_inputs = ['db_root_pwd', 'db_port'] props = mysql_dbms.get_properties() for key in props.keys(): prop = props[key] self.assertIsInstance(prop.value, functions.GetInput) expected_inputs.remove(prop.value.input_name) self.assertListEqual(expected_inputs, []) def test_get_input_validation(self): self.assertRaises(exception.ValidationError, self._load_template, 'functions/test_unknown_input_in_property.yaml') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownInputError, _('Unknown input "objectstore_name".')) self.assertRaises(exception.ValidationError, self._load_template, 'functions/test_unknown_input_in_interface.yaml') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownInputError, _('Unknown input "image_id".')) self.assertRaises(exception.ValidationError, self._load_template, 'functions/test_invalid_function_signature.yaml') exception.ExceptionCollector.assertExceptionMessage( ValueError, _('Expected one argument for function "get_input" but received ' '"[\'cpus\', \'cpus\']".')) def test_get_input_default_value_result(self): mysql_dbms = self._get_node('mysql_dbms') dbms_port = self._get_property(mysql_dbms, 'port') self.assertEqual(3306, dbms_port.result()) dbms_root_password = self._get_property(mysql_dbms, 'root_password') self.assertEqual(dbms_root_password.result(), '12345678') def test_get_property_with_host(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/functions/test_get_property_with_host.yaml") mysql_database = self._get_node( 'mysql_database', ToscaTemplate(tosca_tpl, parsed_params={'db_root_pwd': '123'})) operation = self._get_operation(mysql_database.interfaces, 'configure') db_port = operation.inputs['db_port'] self.assertIsInstance(db_port, functions.GetProperty) result = db_port.result() self.assertEqual(3306, result) test = operation.inputs['test'] self.assertIsInstance(test, functions.GetProperty) result = test.result() self.assertEqual(1, result) def test_get_property_with_nested_params(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/functions/tosca_nested_property_names_indexes.yaml") webserver = self._get_node( 'wordpress', ToscaTemplate(tosca_tpl, parsed_params={'db_root_pwd': '1234'})) operation = self._get_operation(webserver.interfaces, 'configure') wp_endpoint_prot = operation.inputs['wp_endpoint_protocol'] self.assertIsInstance(wp_endpoint_prot, functions.GetProperty) self.assertEqual('tcp', wp_endpoint_prot.result()) wp_list_prop = operation.inputs['wp_list_prop'] self.assertIsInstance(wp_list_prop, functions.GetProperty) self.assertEqual(3, wp_list_prop.result()) def test_get_property_with_capabilties_inheritance(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/functions/test_capabilties_inheritance.yaml") some_node = self._get_node( 'some_node', ToscaTemplate(tosca_tpl, parsed_params={'db_root_pwd': '1234'})) operation = self._get_operation(some_node.interfaces, 'configure') some_input = operation.inputs['some_input'] self.assertIsInstance(some_input, functions.GetProperty) self.assertEqual('someval', some_input.result()) def test_get_property_source_target_keywords(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/functions/test_get_property_source_target_keywords.yaml") tosca = ToscaTemplate(tosca_tpl, parsed_params={'db_root_pwd': '1234'}) for node in tosca.nodetemplates: for relationship in node.relationships: trgt = relationship[0].target rel_template = trgt.get_relationship_template()[0] break operation = self._get_operation(rel_template.interfaces, 'pre_configure_source') target_test = operation.inputs['target_test'] self.assertIsInstance(target_test, functions.GetProperty) self.assertEqual(1, target_test.result()) source_port = operation.inputs['source_port'] self.assertIsInstance(source_port, functions.GetProperty) self.assertEqual(3306, source_port.result()) def test_get_prop_cap_host(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/functions/test_get_prop_cap_host.yaml") some_node = self._get_node('some_node', ToscaTemplate(tosca_tpl)) some_prop = some_node.get_properties()['some_prop'] self.assertIsInstance(some_prop.value, functions.GetProperty) self.assertEqual('someval', some_prop.value.result()) def test_get_prop_cap_bool(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/functions/test_get_prop_cap_bool.yaml") some_node = self._get_node('software', ToscaTemplate(tosca_tpl)) some_prop = some_node.get_properties()['some_prop'] self.assertIsInstance(some_prop.value, functions.GetProperty) self.assertEqual(False, some_prop.value.result())
def test_nested_dsl_def(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/dsl_definitions/test_nested_dsl_def.yaml") self.assertIsNotNone(ToscaTemplate(tosca_tpl))
def _load_template(self, filename): return ToscaTemplate( os.path.join(os.path.dirname(os.path.abspath(__file__)), filename))
def test_substitution_mappings_valid_output(self): tpl_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/topology_template/validate/" "test_substitution_mappings_valid_output.yaml") self.assertIsNotNone(ToscaTemplate(tpl_path))
def test_create_delete_tosca_vnf_with_multiple_vdus(self): data = dict() input_yaml = read_file('sample-tosca-vnfd-multi-vdu.yaml') data['tosca'] = input_yaml toscal = data['tosca'] vnfd_name = 'sample-tosca-vnfd-multi-vdu' tosca_arg = { 'vnfd': { 'name': vnfd_name, 'attributes': { 'vnfd': toscal } } } # Create vnfd with tosca template vnfd_instance = self.client.create_vnfd(body=tosca_arg) self.assertIsNotNone(vnfd_instance) # Create vnf with vnfd_id vnfd_id = vnfd_instance['vnfd']['id'] vnf_arg = { 'vnf': { 'vnfd_id': vnfd_id, 'name': "test_tosca_vnf_with_multiple_vdus" } } vnf_instance = self.client.create_vnf(body=vnf_arg) vnf_id = vnf_instance['vnf']['id'] self.wait_until_vnf_active(vnf_id, constants.VNF_CIRROS_CREATE_TIMEOUT, constants.ACTIVE_SLEEP_TIME) self.assertEqual( self.client.show_vnf(vnf_id)['vnf']['status'], 'ACTIVE') self.validate_vnf_instance(vnfd_instance, vnf_instance) # Validate mgmt_url with input yaml file mgmt_url = self.client.show_vnf(vnf_id)['vnf']['mgmt_url'] self.assertIsNotNone(mgmt_url) mgmt_dict = yaml.load(str(mgmt_url)) input_dict = yaml.load(input_yaml) toscautils.updateimports(input_dict) tosca = ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=input_dict) vdus = toscautils.findvdus(tosca) self.assertEqual(len(mgmt_dict.keys()), len(vdus)) for vdu in vdus: self.assertIsNotNone(mgmt_dict[vdu.name]) self.assertEqual(True, utils.is_valid_ipv4(mgmt_dict[vdu.name])) # Delete vnf_instance with vnf_id try: self.client.delete_vnf(vnf_id) except Exception: assert False, "vnf Delete of test_vnf_with_multiple_vdus failed" # Delete vnfd_instance self.addCleanup(self.client.delete_vnfd, vnfd_id) self.addCleanup(self.wait_until_vnf_delete, vnf_id, constants.VNF_CIRROS_DELETE_TIMEOUT)
def create(self, plugin, context, device, auth_attr): LOG.debug(_('device %s'), device) attributes = device['device_template']['attributes'].copy() vnfd_yaml = attributes.pop('vnfd', None) fields = dict((key, attributes.pop(key)) for key in ('stack_name', 'template_url', 'template') if key in attributes) for key in ('files', 'parameters'): if key in attributes: fields[key] = jsonutils.loads(attributes.pop(key)) # overwrite parameters with given dev_attrs for device creation dev_attrs = device['attributes'].copy() fields.update( dict((key, dev_attrs.pop(key)) for key in ('stack_name', 'template_url', 'template') if key in dev_attrs)) for key in ('files', 'parameters'): if key in dev_attrs: fields.setdefault(key, {}).update( jsonutils.loads(dev_attrs.pop(key))) region_name = device.get('placement_attr', {}).get('region_name', None) heatclient_ = HeatClient(auth_attr, region_name) unsupported_res_prop = self.fetch_unsupported_resource_prop( heatclient_) LOG.debug('vnfd_yaml %s', vnfd_yaml) if vnfd_yaml is not None: vnfd_dict = yamlparser.simple_ordered_parse(vnfd_yaml) LOG.debug('vnfd_dict %s', vnfd_dict) monitoring_dict = {'vdus': {}} if 'tosca_definitions_version' in vnfd_dict: parsed_params = dev_attrs.pop('param_values', {}) toscautils.updateimports(vnfd_dict) try: tosca = ToscaTemplate(parsed_params=parsed_params, a_file=False, yaml_dict_tpl=vnfd_dict) except Exception as e: LOG.debug("tosca-parser error: %s", str(e)) raise vnfm.ToscaParserFailed(error_msg_details=str(e)) monitoring_dict = toscautils.get_vdu_monitoring(tosca) mgmt_ports = toscautils.get_mgmt_ports(tosca) res_tpl = toscautils.get_resources_dict( tosca, STACK_FLAVOR_EXTRA) toscautils.post_process_template(tosca) try: translator = TOSCATranslator(tosca, parsed_params) heat_template_yaml = translator.translate() except Exception as e: LOG.debug("heat-translator error: %s", str(e)) raise vnfm.HeatTranslatorFailed(error_msg_details=str(e)) heat_template_yaml = toscautils.post_process_heat_template( heat_template_yaml, mgmt_ports, res_tpl, unsupported_res_prop) else: assert 'template' not in fields assert 'template_url' not in fields template_dict = yaml.load(HEAT_TEMPLATE_BASE) outputs_dict = {} template_dict['outputs'] = outputs_dict if 'get_input' in vnfd_yaml: self._process_parameterized_input(dev_attrs, vnfd_dict) KEY_LIST = (('description', 'description'), ) for (key, vnfd_key) in KEY_LIST: if vnfd_key in vnfd_dict: template_dict[key] = vnfd_dict[vnfd_key] for vdu_id, vdu_dict in vnfd_dict.get('vdus', {}).items(): template_dict.setdefault('resources', {})[vdu_id] = { "type": "OS::Nova::Server" } resource_dict = template_dict['resources'][vdu_id] KEY_LIST = (('image', 'vm_image'), ('flavor', 'instance_type')) resource_dict['properties'] = {} properties = resource_dict['properties'] for (key, vdu_key) in KEY_LIST: properties[key] = vdu_dict[vdu_key] if 'network_interfaces' in vdu_dict: self._process_vdu_network_interfaces( vdu_id, vdu_dict, properties, template_dict, unsupported_res_prop) if ('user_data' in vdu_dict and 'user_data_format' in vdu_dict): properties['user_data_format'] = vdu_dict[ 'user_data_format'] properties['user_data'] = vdu_dict['user_data'] elif ('user_data' in vdu_dict or 'user_data_format' in vdu_dict): raise vnfm.UserDataFormatNotFound() if 'placement_policy' in vdu_dict: if 'availability_zone' in vdu_dict['placement_policy']: properties['availability_zone'] = vdu_dict[ 'placement_policy']['availability_zone'] if 'config' in vdu_dict: properties['config_drive'] = True metadata = properties.setdefault('metadata', {}) metadata.update(vdu_dict['config']) for key, value in metadata.items(): metadata[key] = value[:255] monitoring_policy = vdu_dict.get('monitoring_policy', 'noop') failure_policy = vdu_dict.get('failure_policy', 'noop') # Convert the old monitoring specification to the new # network. This should be removed after Mitaka if (monitoring_policy == 'ping' and failure_policy == 'respawn'): vdu_dict['monitoring_policy'] = { 'ping': { 'actions': { 'failure': 'respawn' } } } vdu_dict.pop('failure_policy') if monitoring_policy != 'noop': monitoring_dict['vdus'][vdu_id] = \ vdu_dict['monitoring_policy'] # to pass necessary parameters to plugin upwards. for key in ('service_type', ): if key in vdu_dict: device.setdefault('attributes', {})[vdu_id] = jsonutils.dumps( {key: vdu_dict[key]}) heat_template_yaml = yaml.dump(template_dict) fields['template'] = heat_template_yaml if not device['attributes'].get('heat_template'): device['attributes']['heat_template'] = \ heat_template_yaml if monitoring_dict.keys(): device['attributes']['monitoring_policy'] = \ jsonutils.dumps(monitoring_dict) if 'stack_name' not in fields: name = (__name__ + '_' + self.__class__.__name__ + '-' + device['id']) if device['attributes'].get('failure_count'): name += ('-RESPAWN-%s') % str( device['attributes']['failure_count']) fields['stack_name'] = name # service context is ignored LOG.debug(_('service_context: %s'), device.get('service_context', [])) LOG.debug(_('fields: %s'), fields) LOG.debug(_('template: %s'), fields['template']) stack = heatclient_.create(fields) return stack['stack']['id']
def test_csar_with_alternate_extenstion(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/CSAR/csar_elk.csar") tosca = ToscaTemplate(tosca_tpl, parsed_params={"my_cpus": 2}) self.assertTrue(tosca.topology_template.custom_defs)
def execute(self): try: # [] save the recipe to a tmp file with NamedTemporaryFile( mode="w", delete=False, suffix=".yaml", dir=TOSCA_RECIPES_DIR ) as recipe_file: try: recipe_file.write(self.recipe) recipe_file.close() # [] parse the recipe with TOSCA Parse self.template = ToscaTemplate(recipe_file.name) finally: # [] Make sure the temporary file is cleaned up os.remove(recipe_file.name) # [] get all models in the recipe self.templates_by_model_name = self.get_tosca_models_by_name(self.template) # [] compute requirements self.compute_dependencies(self.template, self.templates_by_model_name) # [] topsort requirements self.ordered_models_name = self.topsort_dependencies( self.templates_by_model_name ) # [] topsort templates self.ordered_models_template = self.get_ordered_models_template( self.ordered_models_name, self.templates_by_model_name ) for recipe in self.ordered_models_template: try: # get properties from tosca if "properties" not in recipe.templates[recipe.name]: data = {} else: data = recipe.templates[recipe.name]["properties"] if data is None: data = {} # [] get model by class name class_name = recipe.type.replace("tosca.nodes.", "") # augemnt data with relations data = self.add_dependencies( data, recipe.requirements, self.saved_model_by_name ) model = GRPCModelsAccessor.get_model_from_classname( class_name, data, self.username, self.password ) # [] populate model with data model = self.populate_model(model, data) # [] check if the model has requirements # [] if it has populate them model = self.populate_dependencies( model, recipe.requirements, self.saved_model_by_name ) # [] save, update or delete reference_only = False if "must-exist" in data: reference_only = True if self.delete and not model.is_new and not reference_only: log.info( "[XOS-Tosca] Deleting model %s[%s]" % (class_name, model.id) ) model.delete() elif not self.delete: log.info( "[XOS-Tosca] Saving model %s[%s]" % (class_name, model.id) ) model.save() self.saved_model_by_name[recipe.name] = model except GRPCModelsException as e: raise Exception( "[XOS-TOSCA] Failed to save or delete model %s [%s]: %s" % (class_name, recipe.name, str(e)) ) except ValidationError as e: if e.message: exception_msg = TOSCA_Parser._translate_exception(e.message) else: exception_msg = TOSCA_Parser._translate_exception(str(e)) raise Exception(exception_msg) except _Rendezvous as e: try: details = json.loads(e._state.details) exception_msg = details["error"] if "specific_error" in details: exception_msg = "%s: %s" % ( exception_msg, details["specific_error"], ) except Exception: exception_msg = e._state.details raise Exception(exception_msg)
def test_node_filter(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/node_filter/test_node_filter.yaml") ToscaTemplate(tosca_tpl)
class ToscaTemplateTest(TestCase): '''TOSCA template.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") tosca = ToscaTemplate(tosca_tpl) tosca_elk_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_elk.yaml") tosca_repo_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_repositories_test_definition.yaml") def test_version(self): self.assertEqual(self.tosca.version, "tosca_simple_yaml_1_0") def test_description(self): expected_description = "TOSCA simple profile with wordpress, " \ "web server and mysql on the same server." self.assertEqual(self.tosca.description, expected_description) def test_inputs(self): self.assertEqual( ['cpus', 'db_name', 'db_port', 'db_pwd', 'db_root_pwd', 'db_user'], sorted([input.name for input in self.tosca.inputs])) input_name = "db_port" expected_description = "Port for the MySQL database." for input in self.tosca.inputs: if input.name == input_name: self.assertEqual(input.description, expected_description) def test_node_tpls(self): '''Test nodetemplate names.''' self.assertEqual( ['mysql_database', 'mysql_dbms', 'server', 'webserver', 'wordpress'], sorted([tpl.name for tpl in self.tosca.nodetemplates])) tpl_name = "mysql_database" expected_type = "tosca.nodes.Database" expected_properties = ['name', 'password', 'user'] expected_capabilities = ['database_endpoint', 'feature'] expected_requirements = [{'host': 'mysql_dbms'}] ''' TODO: needs enhancement in tosca_elk.yaml.. expected_relationshp = ['tosca.relationships.HostedOn'] expected_host = ['mysql_dbms'] ''' expected_interface = [ifaces.LIFECYCLE_SHORTNAME] for tpl in self.tosca.nodetemplates: if tpl_name == tpl.name: '''Test node type.''' self.assertEqual(tpl.type, expected_type) '''Test properties.''' self.assertEqual( expected_properties, sorted(tpl.get_properties().keys())) '''Test capabilities.''' self.assertEqual( expected_capabilities, sorted(tpl.get_capabilities().keys())) '''Test requirements.''' self.assertEqual( expected_requirements, tpl.requirements) '''Test relationship.''' ''' needs enhancements in tosca_elk.yaml self.assertEqual( expected_relationshp, [x.type for x in tpl.relationships.keys()]) self.assertEqual( expected_host, [y.name for y in tpl.relationships.values()]) ''' '''Test interfaces.''' self.assertEqual( expected_interface, [x.type for x in tpl.interfaces]) if tpl.name == 'server': '''Test property value''' props = tpl.get_properties() if props and 'mem_size' in props.keys(): self.assertEqual(props['mem_size'].value, '4096 MB') '''Test capability''' caps = tpl.get_capabilities() self.assertIn('os', caps.keys()) os_props_objs = None os_props = None os_type_prop = None if caps and 'os' in caps.keys(): capability = caps['os'] os_props_objs = capability.get_properties_objects() os_props = capability.get_properties() os_type_prop = capability.get_property_value('type') break self.assertEqual( ['Linux'], [p.value for p in os_props_objs if p.name == 'type']) self.assertEqual( 'Linux', os_props['type'].value if 'type' in os_props else '') self.assertEqual('Linux', os_props['type'].value) self.assertEqual('Linux', os_type_prop) def test_outputs(self): self.assertEqual( ['website_url'], sorted([output.name for output in self.tosca.outputs])) def test_interfaces(self): wordpress_node = [ node for node in self.tosca.nodetemplates if node.name == 'wordpress'][0] interfaces = wordpress_node.interfaces self.assertEqual(2, len(interfaces)) for interface in interfaces: if interface.name == 'create': self.assertEqual(ifaces.LIFECYCLE_SHORTNAME, interface.type) self.assertEqual('wordpress/wordpress_install.sh', interface.implementation) self.assertIsNone(interface.inputs) elif interface.name == 'configure': self.assertEqual(ifaces.LIFECYCLE_SHORTNAME, interface.type) self.assertEqual('wordpress/wordpress_configure.sh', interface.implementation) self.assertEqual(3, len(interface.inputs)) TestCase.skip(self, 'bug #1440247') wp_db_port = interface.inputs['wp_db_port'] self.assertTrue(isinstance(wp_db_port, GetProperty)) self.assertEqual('get_property', wp_db_port.name) self.assertEqual(['SELF', 'database_endpoint', 'port'], wp_db_port.args) result = wp_db_port.result() self.assertTrue(isinstance(result, GetInput)) else: raise AssertionError( 'Unexpected interface: {0}'.format(interface.name)) def test_normative_type_by_short_name(self): # test template with a short name Compute template = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_tosca_normative_type_by_shortname.yaml") tosca_tpl = ToscaTemplate(template) expected_type = "tosca.nodes.Compute" for tpl in tosca_tpl.nodetemplates: self.assertEqual(tpl.type, expected_type) for tpl in tosca_tpl.nodetemplates: compute_type = NodeType(tpl.type) self.assertEqual( sorted(['tosca.capabilities.Container', 'tosca.capabilities.Node', 'tosca.capabilities.OperatingSystem', 'tosca.capabilities.network.Bindable', 'tosca.capabilities.Scalable']), sorted([c.type for c in compute_type.get_capabilities_objects()])) def test_template_with_no_inputs(self): tosca_tpl = self._load_template('test_no_inputs_in_template.yaml') self.assertEqual(0, len(tosca_tpl.inputs)) def test_template_with_no_outputs(self): tosca_tpl = self._load_template('test_no_outputs_in_template.yaml') self.assertEqual(0, len(tosca_tpl.outputs)) def test_relationship_interface(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'logstash': config_interface = 'Configure' artifact = 'logstash/configure_elasticsearch.py' relation = node_tpl.relationships for key in relation.keys(): rel_tpl = relation.get(key).get_relationship_template() if rel_tpl: interfaces = rel_tpl[0].interfaces for interface in interfaces: self.assertEqual(config_interface, interface.type) self.assertEqual('pre_configure_source', interface.name) self.assertEqual(artifact, interface.implementation) def test_relationship(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'paypal_pizzastore': expected_relationships = ['tosca.relationships.ConnectsTo', 'tosca.relationships.HostedOn'] expected_hosts = ['tosca.nodes.Database', 'tosca.nodes.WebServer'] self.assertEqual(len(node_tpl.relationships), 2) self.assertEqual( expected_relationships, sorted([k.type for k in node_tpl.relationships.keys()])) self.assertEqual( expected_hosts, sorted([v.type for v in node_tpl.relationships.values()])) def test_repositories(self): template = ToscaTemplate(self.tosca_repo_tpl) self.assertEqual( ['repo_code0', 'repo_code1', 'repo_code2'], sorted([input.name for input in template.repositories])) input_name = "repo_code2" expected_url = "https://github.com/nandinivemula/intern/master" for input in template.repositories: if input.name == input_name: self.assertEqual(input.url, expected_url) def test_template_macro(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'mongo_server': self.assertEqual( ['disk_size', 'mem_size', 'num_cpus'], sorted(node_tpl.get_capability('host'). get_properties().keys())) def test_template_requirements(self): """Test different formats of requirements The requirements can be defined in few different ways, 1. Requirement expressed as a capability with an implicit relationship. 2. Requirement expressed with explicit relationship. 3. Requirement expressed with a relationship template. 4. Requirement expressed via TOSCA types to provision a node with explicit relationship. 5. Requirement expressed via TOSCA types with a filter. """ tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_requirements.yaml") tosca = ToscaTemplate(tosca_tpl) for node_tpl in tosca.nodetemplates: if node_tpl.name == 'my_app': expected_relationship = [ ('tosca.relationships.ConnectsTo', 'mysql_database'), ('tosca.relationships.HostedOn', 'my_webserver')] actual_relationship = sorted([ (relation.type, node.name) for relation, node in node_tpl.relationships.items()]) self.assertEqual(expected_relationship, actual_relationship) if node_tpl.name == 'mysql_database': self.assertEqual( [('tosca.relationships.HostedOn', 'my_dbms')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()]) if node_tpl.name == 'my_server': self.assertEqual( [('tosca.relationships.AttachesTo', 'my_storage')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()]) def test_template_requirements_not_implemented(self): # TODO(spzala): replace this test with new one once TOSCA types look up # support is implemented. """Requirements that yet need to be implemented The following requirement formats are not yet implemented, due to look up dependency: 1. Requirement expressed via TOSCA types to provision a node with explicit relationship. 2. Requirement expressed via TOSCA types with a filter. """ tpl_snippet_1 = ''' node_templates: mysql_database: type: tosca.nodes.Database description: Requires a particular node type and relationship. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.DBMS relationship: tosca.relationships.HostedOn ''' tpl_snippet_2 = ''' node_templates: my_webserver: type: tosca.nodes.WebServer description: Requires a particular node type with a filter. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.Compute target_filter: properties: num_cpus: { in_range: [ 1, 4 ] } mem_size: { greater_or_equal: 2 } capabilities: - tosca.capabilities.OS: properties: architecture: x86_64 type: linux ''' tpl_snippet_3 = ''' node_templates: my_webserver2: type: tosca.nodes.WebServer description: Requires a node type with a particular capability. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.Compute relationship: tosca.relationships.HostedOn capability: tosca.capabilities.Container ''' self._requirements_not_implemented(tpl_snippet_1, 'mysql_database') self._requirements_not_implemented(tpl_snippet_2, 'my_webserver') self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2') def _requirements_not_implemented(self, tpl_snippet, tpl_name): nodetemplates = (toscaparser.utils.yamlparser. simple_parse(tpl_snippet))['node_templates'] self.assertRaises( NotImplementedError, lambda: NodeTemplate(tpl_name, nodetemplates).relationships) # Test the following: # 1. Custom node type derived from 'WebApplication' named 'TestApp' # with a custom Capability Type 'TestCapability' # 2. Same as #1, but referencing a custom 'TestCapability' Capability Type # that is not defined def test_custom_capability_type_definition(self): tpl_snippet = ''' node_templates: test_app: type: tosca.nodes.WebApplication.TestApp capabilities: test_cap: properties: test: 1 ''' # custom node type definition with custom capability type definition custom_def = ''' tosca.nodes.WebApplication.TestApp: derived_from: tosca.nodes.WebApplication capabilities: test_cap: type: tosca.capabilities.TestCapability tosca.capabilities.TestCapability: derived_from: tosca.capabilities.Root properties: test: type: integer required: false ''' expected_capabilities = ['app_endpoint', 'feature', 'test_cap'] nodetemplates = (toscaparser.utils.yamlparser. simple_parse(tpl_snippet))['node_templates'] custom_def = (toscaparser.utils.yamlparser. simple_parse(custom_def)) name = list(nodetemplates.keys())[0] tpl = NodeTemplate(name, nodetemplates, custom_def) self.assertEqual( expected_capabilities, sorted(tpl.get_capabilities().keys())) # custom definition without valid capability type definition custom_def = ''' tosca.nodes.WebApplication.TestApp: derived_from: tosca.nodes.WebApplication capabilities: test_cap: type: tosca.capabilities.TestCapability ''' custom_def = (toscaparser.utils.yamlparser. simple_parse(custom_def)) tpl = NodeTemplate(name, nodetemplates, custom_def) err = self.assertRaises( exception.InvalidTypeError, lambda: NodeTemplate(name, nodetemplates, custom_def).get_capabilities_objects()) self.assertEqual('Type "tosca.capabilities.TestCapability" is not ' 'a valid type.', six.text_type(err)) def test_local_template_with_local_relpath_import(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") tosca = ToscaTemplate(tosca_tpl) self.assertTrue(tosca.topology_template.custom_defs) def test_local_template_with_url_import(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress_with_url_import.yaml") tosca = ToscaTemplate(tosca_tpl) self.assertTrue(tosca.topology_template.custom_defs) def test_url_template_with_local_relpath_import(self): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress.yaml') tosca = ToscaTemplate(tosca_tpl, None, False) self.assertTrue(tosca.topology_template.custom_defs) def test_url_template_with_local_abspath_import(self): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress_with_local_abspath_' 'import.yaml') self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl, None, False) err_msg = (_('Absolute file name "/tmp/tosca-parser/toscaparser/tests' '/data/custom_types/wordpress.yaml" cannot be used in a ' 'URL-based input template "%(tpl)s".') % {'tpl': tosca_tpl}) exception.ExceptionCollector.assertExceptionMessage(ImportError, err_msg) def test_url_template_with_url_import(self): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress_with_url_import.yaml') tosca = ToscaTemplate(tosca_tpl, None, False) self.assertTrue(tosca.topology_template.custom_defs) def test_csar_parsing_wordpress(self): csar_archive = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data/CSAR/csar_wordpress.zip') self.assertTrue(ToscaTemplate(csar_archive)) def test_csar_parsing_elk_url_based(self): csar_archive = ('https://github.com/openstack/tosca-parser/raw/master/' 'toscaparser/tests/data/CSAR/csar_elk.zip') self.assertTrue(ToscaTemplate(csar_archive, None, False)) def test_nested_imports_in_templates(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_instance_nested_imports.yaml") tosca = ToscaTemplate(tosca_tpl) expected_custom_types = ['tosca.nodes.WebApplication.WordPress', 'test_namespace_prefix.Rsyslog', 'Test2ndRsyslogType', 'test_2nd_namespace_prefix.Rsyslog', 'tosca.nodes.SoftwareComponent.Logstash', 'tosca.nodes.SoftwareComponent.Rsyslog.' 'TestRsyslogType'] self.assertItemsEqual(tosca.topology_template.custom_defs.keys(), expected_custom_types) def test_invalid_template_file(self): template_file = 'invalid template file' expected_msg = (_('"%s" is not a valid file.') % template_file) self.assertRaises( exception.ValidationError, ToscaTemplate, template_file, None, False) exception.ExceptionCollector.assertExceptionMessage(ValueError, expected_msg) def test_multiple_validation_errors(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_multiple_validation_errors.yaml") self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl, None) valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS) err1_msg = (_('The template version "tosca_simple_yaml_1" is invalid. ' 'Valid versions are "%s".') % valid_versions) exception.ExceptionCollector.assertExceptionMessage( exception.InvalidTemplateVersion, err1_msg) err2_msg = _('Import "custom_types/not_there.yaml" is not valid.') exception.ExceptionCollector.assertExceptionMessage( ImportError, err2_msg) err3_msg = _('Type "tosca.nodes.WebApplication.WordPress" is not a ' 'valid type.') exception.ExceptionCollector.assertExceptionMessage( exception.InvalidTypeError, err3_msg) err4_msg = _('Node template "wordpress" contains unknown field ' '"requirement". Refer to the definition to verify valid ' 'values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err4_msg) err5_msg = _('\'Property "passwords" was not found in node template ' '"mysql_database".\'') exception.ExceptionCollector.assertExceptionMessage( KeyError, err5_msg) err6_msg = _('Template "mysql_dbms" is missing required field "type".') exception.ExceptionCollector.assertExceptionMessage( exception.MissingRequiredFieldError, err6_msg) err7_msg = _('Node template "mysql_dbms" contains unknown field ' '"type1". Refer to the definition to verify valid ' 'values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err7_msg) err8_msg = _('\'Node template "server1" was not found.\'') exception.ExceptionCollector.assertExceptionMessage( KeyError, err8_msg) err9_msg = _('"relationship" used in template "webserver" is missing ' 'required field "type".') exception.ExceptionCollector.assertExceptionMessage( exception.MissingRequiredFieldError, err9_msg) def test_invalid_section_names(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_invalid_section_names.yaml") self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl, None) err1_msg = _('Template contains unknown field ' '"tosca_definitions_versions". Refer to the definition ' 'to verify valid values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err1_msg) err2_msg = _('Template contains unknown field "descriptions". ' 'Refer to the definition to verify valid values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err2_msg) err3_msg = _('Template contains unknown field "import". Refer to ' 'the definition to verify valid values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err3_msg) err4_msg = _('Template contains unknown field "topology_templates". ' 'Refer to the definition to verify valid values.') exception.ExceptionCollector.assertExceptionMessage( exception.UnknownFieldError, err4_msg) def test_csar_with_alternate_extenstion(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/CSAR/csar_elk.csar") tosca = ToscaTemplate(tosca_tpl) self.assertTrue(tosca.topology_template.custom_defs) def test_available_rel_tpls(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_available_rel_tpls.yaml") tosca = ToscaTemplate(tosca_tpl) for node in tosca.nodetemplates: for relationship, target in node.relationships.items(): try: target.relationships except TypeError as error: self.fail(error) def test_no_input(self): self.assertRaises(exception.ValidationError, ToscaTemplate, None, None, False, None) err_msg = (('No path or yaml_dict_tpl was provided. ' 'There is nothing to parse.')) exception.ExceptionCollector.assertExceptionMessage(ValueError, err_msg) def test_path_and_yaml_dict_tpl_input(self): test_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_helloworld.yaml") yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl) tosca = ToscaTemplate(test_tpl, yaml_dict_tpl=yaml_dict_tpl) self.assertEqual(tosca.version, "tosca_simple_yaml_1_0") def test_yaml_dict_tpl_input(self): test_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_helloworld.yaml") yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl) tosca = ToscaTemplate(yaml_dict_tpl=yaml_dict_tpl) self.assertEqual(tosca.version, "tosca_simple_yaml_1_0") def test_yaml_dict_tpl_with_params_and_url_import(self): test_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress_with_url_import.yaml") yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl) params = {'db_name': 'my_wordpress', 'db_user': '******', 'db_root_pwd': 'mypasswd'} tosca = ToscaTemplate(parsed_params=params, yaml_dict_tpl=yaml_dict_tpl) self.assertEqual(tosca.version, "tosca_simple_yaml_1_0") def test_yaml_dict_tpl_with_rel_import(self): test_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl) self.assertRaises(exception.ValidationError, ToscaTemplate, None, None, False, yaml_dict_tpl) err_msg = (_('Relative file name "custom_types/wordpress.yaml" ' 'cannot be used in a pre-parsed input template.')) exception.ExceptionCollector.assertExceptionMessage(ImportError, err_msg) def test_yaml_dict_tpl_with_fullpath_import(self): test_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") yaml_dict_tpl = toscaparser.utils.yamlparser.load_yaml(test_tpl) yaml_dict_tpl['imports'] = [os.path.join(os.path.dirname( os.path.abspath(__file__)), "data/custom_types/wordpress.yaml")] params = {'db_name': 'my_wordpress', 'db_user': '******', 'db_root_pwd': 'mypasswd'} tosca = ToscaTemplate(parsed_params=params, yaml_dict_tpl=yaml_dict_tpl) self.assertEqual(tosca.version, "tosca_simple_yaml_1_0") def test_policies_for_node_templates(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/policies/tosca_policy_template.yaml") tosca = ToscaTemplate(tosca_tpl) for policy in tosca.topology_template.policies: if policy.name == 'my_compute_placement_policy': self.assertEqual('tosca.policies.Placement', policy.type) self.assertEqual(['my_server_1', 'my_server_2'], policy.targets) self.assertEqual('node_templates', policy.get_targets_type()) for node in policy.targets_list: if node.name == 'my_server_1': '''Test property value''' props = node.get_properties() if props and 'mem_size' in props.keys(): self.assertEqual(props['mem_size'].value, '4096 MB') def test_policies_for_groups(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/policies/tosca_policy_template.yaml") tosca = ToscaTemplate(tosca_tpl) for policy in tosca.topology_template.policies: if policy.name == 'my_groups_placement': self.assertEqual('mycompany.mytypes.myScalingPolicy', policy.type) self.assertEqual(['webserver_group'], policy.targets) self.assertEqual('groups', policy.get_targets_type()) group = policy.get_targets_list()[0] for node in group.get_member_nodes(): if node.name == 'my_server_2': '''Test property value''' props = node.get_properties() if props and 'mem_size' in props.keys(): self.assertEqual(props['mem_size'].value, '4096 MB') def test_node_filter(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_node_filter.yaml") ToscaTemplate(tosca_tpl) def test_attributes_inheritance(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_attributes_inheritance.yaml") ToscaTemplate(tosca_tpl) def test_repositories_definition(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_repositories_definition.yaml") ToscaTemplate(tosca_tpl) def test_custom_caps_def(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_custom_caps_def.yaml") ToscaTemplate(tosca_tpl) def test_custom_rel_with_script(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_tosca_custom_rel_with_script.yaml") tosca = ToscaTemplate(tosca_tpl) rel = tosca.relationship_templates[0] self.assertEqual(len(rel.interfaces), 1) self.assertEqual(rel.interfaces[0].type, "Configure") def test_various_portspec_errors(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/datatypes/test_datatype_portspec_add_req.yaml") self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl, None) # TODO(TBD) find way to reuse error messages from constraints.py msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of ' 'range "(min:%(vmin)s, max:%(vmax)s)".') % dict(pname=PortSpec.SOURCE, pvalue='0', vmin='1', vmax='65535')) exception.ExceptionCollector.assertExceptionMessage( exception.ValidationError, msg) # Test value below range min. msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of ' 'range "(min:%(vmin)s, max:%(vmax)s)".') % dict(pname=PortSpec.SOURCE, pvalue='1', vmin='2', vmax='65534')) exception.ExceptionCollector.assertExceptionMessage( exception.RangeValueError, msg) # Test value above range max. msg = (_('The value "%(pvalue)s" of property "%(pname)s" is out of ' 'range "(min:%(vmin)s, max:%(vmax)s)".') % dict(pname=PortSpec.SOURCE, pvalue='65535', vmin='2', vmax='65534')) exception.ExceptionCollector.assertExceptionMessage( exception.RangeValueError, msg)
def test_attributes_inheritance(self): tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_attributes_inheritance.yaml") ToscaTemplate(tosca_tpl)
def test_url_template_with_local_relpath_import(self): tosca_tpl = ('https://raw.githubusercontent.com/openstack/' 'tosca-parser/master/toscaparser/tests/data/' 'tosca_single_instance_wordpress.yaml') tosca = ToscaTemplate(tosca_tpl, None, False) self.assertTrue(tosca.topology_template.custom_defs)
class TestToscaUtils(testtools.TestCase): tosca_openwrt = _get_template('test_tosca_openwrt.yaml') vnfd_dict = yaml.load(tosca_openwrt) toscautils.updateimports(vnfd_dict) tosca = ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=vnfd_dict) tosca_flavor = _get_template('test_tosca_flavor.yaml') def setUp(self): super(TestToscaUtils, self).setUp() def test_updateimport(self): importspath = os.path.abspath('./tacker/vm/tosca/lib/') file1 = importspath + '/tacker_defs.yaml' file2 = importspath + '/tacker_nfv_defs.yaml' expected_imports = [file1, file2] self.assertEqual(self.vnfd_dict['imports'], expected_imports) def test_get_mgmt_driver(self): expected_mgmt_driver = 'openwrt' mgmt_driver = toscautils.get_mgmt_driver(self.tosca) self.assertEqual(mgmt_driver, expected_mgmt_driver) def test_get_vdu_monitoring(self): expected_monitoring = { 'vdus': { 'VDU1': { 'ping': { 'actions': { 'failure': 'respawn' }, 'name': 'ping', 'parameters': { 'count': 3, 'interval': 10 }, 'monitoring_params': { 'count': 3, 'interval': 10 } } } } } monitoring = toscautils.get_vdu_monitoring(self.tosca) self.assertEqual(monitoring, expected_monitoring) def test_get_mgmt_ports(self): expected_mgmt_ports = {'mgmt_ip-VDU1': 'CP1'} mgmt_ports = toscautils.get_mgmt_ports(self.tosca) self.assertEqual(mgmt_ports, expected_mgmt_ports) def test_post_process_template(self): tosca2 = ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=self.vnfd_dict) toscautils.post_process_template(tosca2) invalidNodes = 0 for nt in tosca2.nodetemplates: if (nt.type_definition.is_derived_from(toscautils.MONITORING) or nt.type_definition.is_derived_from(toscautils.FAILURE) or nt.type_definition.is_derived_from( toscautils.PLACEMENT)): invalidNodes += 1 self.assertEqual(invalidNodes, 0) deletedProperties = 0 if nt.type in toscautils.delpropmap.keys(): for prop in toscautils.delpropmap[nt.type]: for p in nt.get_properties_objects(): if prop == p.name: deletedProperties += 1 self.assertEqual(deletedProperties, 0) convertedProperties = 0 if nt.type in toscautils.convert_prop: for prop in toscautils.convert_prop[nt.type].keys(): for p in nt.get_properties_objects(): if prop == p.name: convertedProperties += 1 self.assertEqual(convertedProperties, 0) def test_post_process_heat_template(self): tosca1 = ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=self.vnfd_dict) toscautils.post_process_template(tosca1) translator = TOSCATranslator(tosca1, {}) heat_template_yaml = translator.translate() expected_heat_tpl = _get_template('hot_tosca_openwrt.yaml') mgmt_ports = toscautils.get_mgmt_ports(self.tosca) heat_tpl = toscautils.post_process_heat_template( heat_template_yaml, mgmt_ports, {}, {}) heatdict = yaml.load(heat_tpl) expecteddict = yaml.load(expected_heat_tpl) self.assertEqual(heatdict, expecteddict) def test_findvdus(self): vdus = toscautils.findvdus(self.tosca) self.assertEqual(len(vdus), 1) for vdu in vdus: self.assertEqual( vdu.type_definition.is_derived_from(toscautils.TACKERVDU), True) def test_get_flavor_dict(self): vnfd_dict = yaml.load(self.tosca_flavor) toscautils.updateimports(vnfd_dict) tosca = ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) expected_flavor_dict = {"VDU1": {"vcpus": 2, "disk": 10, "ram": 512}} actual_flavor_dict = toscautils.get_flavor_dict(tosca) self.assertEqual(expected_flavor_dict, actual_flavor_dict) def test_add_resources_tpl_for_flavor(self): dummy_heat_dict = yaml.load( _get_template('hot_flavor_and_capabilities.yaml')) expected_dict = yaml.load(_get_template('hot_flavor.yaml')) dummy_heat_res = { "flavor": { "VDU1": { "vcpus": 2, "ram": 512, "disk": 10 } } } toscautils.add_resources_tpl(dummy_heat_dict, dummy_heat_res) self.assertEqual(dummy_heat_dict, expected_dict) def test_get_flavor_dict_extra_specs_all_numa_count(self): tosca_fes_all_numa_count = _get_template( 'tosca_flavor_all_numa_count.yaml') vnfd_dict = yaml.load(tosca_fes_all_numa_count) toscautils.updateimports(vnfd_dict) tosca = ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) expected_flavor_dict = { "VDU1": { "vcpus": 8, "disk": 10, "ram": 4096, "extra_specs": { 'hw:cpu_policy': 'dedicated', 'hw:mem_page_size': 'any', 'hw:cpu_sockets': 2, 'hw:cpu_threads': 2, 'hw:numa_nodes': 2, 'hw:cpu_cores': 2, 'hw:cpu_threads_policy': 'avoid' } } } actual_flavor_dict = toscautils.get_flavor_dict(tosca) self.assertEqual(expected_flavor_dict, actual_flavor_dict) def test_tacker_conf_heat_extra_specs_all_numa_count(self): tosca_fes_all_numa_count = _get_template( 'tosca_flavor_all_numa_count.yaml') vnfd_dict = yaml.load(tosca_fes_all_numa_count) toscautils.updateimports(vnfd_dict) tosca = ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) expected_flavor_dict = { "VDU1": { "vcpus": 8, "disk": 10, "ram": 4096, "extra_specs": { 'hw:cpu_policy': 'dedicated', 'hw:mem_page_size': 'any', 'hw:cpu_sockets': 2, 'hw:cpu_threads': 2, 'hw:numa_nodes': 2, 'hw:cpu_cores': 2, 'hw:cpu_threads_policy': 'avoid', 'aggregate_instance_extra_specs:nfv': 'true' } } } actual_flavor_dict = toscautils.get_flavor_dict( tosca, {"aggregate_instance_extra_specs:nfv": "true"}) self.assertEqual(expected_flavor_dict, actual_flavor_dict) def test_add_resources_tpl_for_image(self): dummy_heat_dict = yaml.load( _get_template('hot_image_before_processed_image.yaml')) expected_dict = yaml.load( _get_template('hot_image_after_processed_image.yaml')) dummy_heat_res = { "image": { "VDU1": { "location": "http://URL/v1/openwrt.qcow2", "container_format": "bare", "disk_format": "raw" } } } toscautils.add_resources_tpl(dummy_heat_dict, dummy_heat_res) self.assertEqual(dummy_heat_dict, expected_dict) def test_convert_unsupported_res_prop_kilo_ver(self): unsupported_res_prop_dict = { 'OS::Neutron::Port': { 'port_security_enabled': 'value_specs', }, } dummy_heat_dict = yaml.load(_get_template('hot_tosca_openwrt.yaml')) expected_heat_dict = yaml.load( _get_template('hot_tosca_openwrt_kilo.yaml')) toscautils.convert_unsupported_res_prop(dummy_heat_dict, unsupported_res_prop_dict) self.assertEqual(dummy_heat_dict, expected_heat_dict)