예제 #1
0
파일: plugin.py 프로젝트: jshayne/apmec
    def create_mea(self, context, mea):
        mea_info = mea['mea']
        name = mea_info['name']

        # if mead_template specified, create mead from template
        # create template dictionary structure same as needed in create_mead()
        if mea_info.get('mead_template'):
            mead_name = utils.generate_resource_name(name, 'inline')
            mead = {
                'mead': {
                    'attributes': {
                        'mead': mea_info['mead_template']
                    },
                    'name': mead_name,
                    'template_source': 'inline',
                    'service_types': [{
                        'service_type': 'mead'
                    }]
                }
            }
            mea_info['mead_id'] = self.create_mead(context, mead).get('id')

        mea_attributes = mea_info['attributes']
        if mea_attributes.get('param_values'):
            param = mea_attributes['param_values']
            if isinstance(param, dict):
                # TODO(sripriya) remove this yaml dump once db supports storing
                # json format of yaml files in a separate column instead of
                #  key value string pairs in mea attributes table
                mea_attributes['param_values'] = yaml.safe_dump(param)
            else:
                self._report_deprecated_yaml_str()
        if mea_attributes.get('config'):
            config = mea_attributes['config']
            if isinstance(config, dict):
                # TODO(sripriya) remove this yaml dump once db supports storing
                # json format of yaml files in a separate column instead of
                #  key value string pairs in mea attributes table
                mea_attributes['config'] = yaml.safe_dump(config)
            else:
                self._report_deprecated_yaml_str()
        infra_driver, vim_auth = self._get_infra_driver(context, mea_info)
        if infra_driver not in self._mea_manager:
            LOG.debug(
                'unknown vim driver '
                '%(infra_driver)s in %(drivers)s', {
                    'infra_driver': infra_driver,
                    'drivers': cfg.CONF.apmec.infra_driver
                })
            raise mem.InvalidInfraDriver(vim_name=infra_driver)

        mea_dict = self._create_mea(context, mea_info, vim_auth, infra_driver)

        def create_mea_wait():
            self._create_mea_wait(context, mea_dict, vim_auth, infra_driver)
            if mea_dict['status'] is not constants.ERROR:
                self.add_mea_to_monitor(context, mea_dict)
            self.config_mea(context, mea_dict)

        self.spawn_n(create_mea_wait)
        return mea_dict
예제 #2
0
    def update_meca(self, context, meca_id, meca):
        meca_info = meca['meca']
        meca_old = super(MeoPlugin, self).get_meca(context, meca_id)
        name = meca_old['name']
        # create inline meafgd if given by user
        if meca_info.get('mecad_template'):
            meca_name = utils.generate_resource_name(name, 'inline')
            mecad = {'mecad': {'tenant_id': meca_old['tenant_id'],
                           'name': meca_name,
                           'attributes': {
                               'mecad': meca_info['mecad_template']},
                           'template_source': 'inline',
                           'description': meca_old['description']}}
            try:
                meca_info['mecad_id'] = \
                    self.create_mecad(context, mecad).get('id')
            except Exception:
                with excutils.save_and_reraise_exception():
                    super(MeoPlugin, self)._update_meca_status(
                        context, meca_id, constants.ACTIVE)

        mecad = self.get_mecad(context, meca_info['mecad_id'])
        mecad_dict = yaml.safe_load(mecad['attributes']['mecad'])
        mem_plugin = manager.ApmecManager.get_service_plugins()['MEM']
        onboarded_meads = mem_plugin.get_meads(context, [])
        region_name = meca.setdefault('placement_attr', {}).get(
            'region_name', None)
        vim_res = self.vim_client.get_vim(context, meca_old['vim_id'],
                                          region_name)
        driver_type = vim_res['vim_type']

        # Step-1
        param_values = dict()
        if 'get_input' in str(mecad_dict):
            self._process_parameterized_input(meca['meca']['attributes'],
                                              mecad_dict)

        # Step-2
        meads = mecad['meads']
        # mead_dict is used while generating workflow
        mead_dict = dict()
        for node_name, node_val in \
                (mecad_dict['topology_template']['node_templates']).items():
            if node_val.get('type') not in meads.keys():
                continue
            mead_name = meads[node_val.get('type')]
            if not mead_dict.get(mead_name):
                mead_dict[mead_name] = {
                    'id': self._get_mead_id(mead_name, onboarded_meads),
                    'instances': [node_name]
                }
            else:
                mead_dict[mead_name]['instances'].append(node_name)
            if not node_val.get('requirements'):
                continue
            if not param_values.get(mead_name):
                param_values[mead_name] = {}
            param_values[mead_name]['substitution_mappings'] = dict()
            req_dict = dict()
            requirements = node_val.get('requirements')
            for requirement in requirements:
                req_name = list(requirement.keys())[0]
                req_val = list(requirement.values())[0]
                res_name = req_val + meca['meca']['mecad_id'][:11]
                req_dict[req_name] = res_name
                if req_val in mecad_dict['topology_template']['node_templates']:   # noqa
                    param_values[mead_name]['substitution_mappings'][
                        res_name] = mecad_dict['topology_template'][
                        'node_templates'][req_val]

            param_values[mead_name]['substitution_mappings'][
                'requirements'] = req_dict
        meca['mead_details'] = mead_dict
        # Step-3
        kwargs = {'meca': meca, 'params': param_values}

        # NOTE NoTasksException is raised if no tasks.
        workflow = self._vim_drivers.invoke(
            driver_type,
            'prepare_and_create_workflow',
            resource='mea',
            action='create',
            auth_dict=self.get_auth_dict(context),
            kwargs=kwargs)
        try:
            mistral_execution = self._vim_drivers.invoke(
                driver_type,
                'execute_workflow',
                workflow=workflow,
                auth_dict=self.get_auth_dict(context))
        except Exception as ex:
            LOG.error('Error while executing workflow: %s', ex)
            self._vim_drivers.invoke(driver_type,
                                     'delete_workflow',
                                     workflow_id=workflow['id'],
                                     auth_dict=self.get_auth_dict(context))
            raise ex
        meca_dict = super(MeoPlugin, self)._update_meca_pre(context, meca_id)

        def _update_meca_wait(self_obj, meca_id, execution_id):
            exec_state = "RUNNING"
            mistral_retries = MISTRAL_RETRIES
            while exec_state == "RUNNING" and mistral_retries > 0:
                time.sleep(MISTRAL_RETRY_WAIT)
                exec_state = self._vim_drivers.invoke(
                    driver_type,
                    'get_execution',
                    execution_id=execution_id,
                    auth_dict=self.get_auth_dict(context)).state
                LOG.debug('status: %s', exec_state)
                if exec_state == 'SUCCESS' or exec_state == 'ERROR':
                    break
                mistral_retries = mistral_retries - 1
            error_reason = None
            if mistral_retries == 0 and exec_state == 'RUNNING':
                error_reason = _(
                    "MECA update is not completed within"
                    " {wait} seconds as creation of mistral"
                    " execution {mistral} is not completed").format(
                    wait=MISTRAL_RETRIES * MISTRAL_RETRY_WAIT,
                    mistral=execution_id)
            exec_obj = self._vim_drivers.invoke(
                driver_type,
                'get_execution',
                execution_id=execution_id,
                auth_dict=self.get_auth_dict(context))

            self._vim_drivers.invoke(driver_type,
                                     'delete_execution',
                                     execution_id=execution_id,
                                     auth_dict=self.get_auth_dict(context))
            self._vim_drivers.invoke(driver_type,
                                     'delete_workflow',
                                     workflow_id=workflow['id'],
                                     auth_dict=self.get_auth_dict(context))
            super(MeoPlugin, self)._update_meca_post(
                context, meca_id, exec_obj, mead_dict, error_reason)

        self.spawn_n(_update_meca_wait, self, meca_dict['id'],
                     mistral_execution.id)
        return meca_dict
예제 #3
0
    def create_mes(self, context, mes):
        """Create MES and corresponding MEAs.

        :param mes: mes dict which contains mesd_id and attributes
        This method has 3 steps:
        step-1: substitute all get_input params to its corresponding values
        step-2: Build params dict for substitution mappings case through which
        MEAs will actually substitute their requirements.
        step-3: Create mistral workflow and execute the workflow
        """
        mes_info = mes['mes']
        name = mes_info['name']

        if mes_info.get('mesd_template'):
            mesd_name = utils.generate_resource_name(name, 'inline')
            mesd = {
                'mesd': {
                    'attributes': {
                        'mesd': mes_info['mesd_template']
                    },
                    'description': mes_info['description'],
                    'name': mesd_name,
                    'template_source': 'inline',
                    'tenant_id': mes_info['tenant_id']
                }
            }
            mes_info['mesd_id'] = self.create_mesd(context, mesd).get('id')

        mesd = self.get_mesd(context, mes['mes']['mesd_id'])
        mesd_dict = yaml.safe_load(mesd['attributes']['mesd'])
        mem_plugin = manager.ApmecManager.get_service_plugins()['MEM']
        onboarded_meads = mem_plugin.get_meads(context, [])
        region_name = mes.setdefault('placement_attr',
                                     {}).get('region_name', None)
        vim_res = self.vim_client.get_vim(context, mes['mes']['vim_id'],
                                          region_name)
        driver_type = vim_res['vim_type']
        if not mes['mes']['vim_id']:
            mes['mes']['vim_id'] = vim_res['vim_id']

        nsds = mesd['attributes'].get('nsds')
        if nsds:
            for nsd in nsds:
                vim_obj = self.get_vim(context,
                                       mes['mes']['vim_id'],
                                       mask_password=False)
                self._build_vim_auth(context, vim_obj)
                client = tackerclient(vim_obj['auth_cred'])
                ns_name = nsd + name
                nsd_instance = client.nsd_get(nsd)
                ns_arg = {'ns': {'nsd_id': nsd_instance, 'name': ns_name}}
                ns_instance = client.ns_create(ns_arg)

        vnffgds = mesd['attributes'].get('vnffgds')
        if vnffgds:
            for vnffgd in vnffgds:
                vim_obj = self.get_vim(context,
                                       mes['mes']['vim_id'],
                                       mask_password=False)
                self._build_vim_auth(context, vim_obj)
                client = tackerclient(vim_obj['auth_cred'])
                vnffgd_name = vnffgd + name
                vnffgd_instance = client.vnffgd_get(vnffgd)
                vnffg_arg = {
                    'vnffg': {
                        'vnffgd_id': vnffgd_instance,
                        'name': vnffgd_name
                    }
                }
                time.sleep(300)
                vnffg_instance = client.vnffg_create(vnffg_arg)

        # Step-1
        param_values = mes['mes']['attributes'].get('param_values', {})
        if 'get_input' in str(mesd_dict):
            self._process_parameterized_input(mes['mes']['attributes'],
                                              mesd_dict)
        # Step-2
        meads = mesd['meads']
        # mead_dict is used while generating workflow
        mead_dict = dict()
        for node_name, node_val in \
                (mesd_dict['topology_template']['node_templates']).items():
            if node_val.get('type') not in meads.keys():
                continue
            mead_name = meads[node_val.get('type')]
            if not mead_dict.get(mead_name):
                mead_dict[mead_name] = {
                    'id': self._get_mead_id(mead_name, onboarded_meads),
                    'instances': [node_name]
                }
            else:
                mead_dict[mead_name]['instances'].append(node_name)
            if not node_val.get('requirements'):
                continue
            if not param_values.get(mead_name):
                param_values[mead_name] = {}
            param_values[mead_name]['substitution_mappings'] = dict()
            req_dict = dict()
            requirements = node_val.get('requirements')
            for requirement in requirements:
                req_name = list(requirement.keys())[0]
                req_val = list(requirement.values())[0]
                res_name = req_val + mes['mes']['mesd_id'][:11]
                req_dict[req_name] = res_name
                if req_val in mesd_dict['topology_template']['node_templates']:
                    param_values[mead_name]['substitution_mappings'][
                        res_name] = mesd_dict['topology_template'][
                            'node_templates'][req_val]

            param_values[mead_name]['substitution_mappings'][
                'requirements'] = req_dict
        mes['mead_details'] = mead_dict
        # Step-3
        kwargs = {'mes': mes, 'params': param_values}

        # NOTE NoTasksException is raised if no tasks.
        workflow = self._vim_drivers.invoke(
            driver_type,
            'prepare_and_create_workflow',
            resource='mea',
            action='create',
            auth_dict=self.get_auth_dict(context),
            kwargs=kwargs)
        try:
            mistral_execution = self._vim_drivers.invoke(
                driver_type,
                'execute_workflow',
                workflow=workflow,
                auth_dict=self.get_auth_dict(context))
        except Exception as ex:
            LOG.error('Error while executing workflow: %s', ex)
            self._vim_drivers.invoke(driver_type,
                                     'delete_workflow',
                                     workflow_id=workflow['id'],
                                     auth_dict=self.get_auth_dict(context))
            raise ex
        mes_dict = super(MeoPlugin, self).create_mes(context, mes)

        def _create_mes_wait(self_obj, mes_id, execution_id):
            exec_state = "RUNNING"
            mistral_retries = MISTRAL_RETRIES
            while exec_state == "RUNNING" and mistral_retries > 0:
                time.sleep(MISTRAL_RETRY_WAIT)
                exec_state = self._vim_drivers.invoke(
                    driver_type,
                    'get_execution',
                    execution_id=execution_id,
                    auth_dict=self.get_auth_dict(context)).state
                LOG.debug('status: %s', exec_state)
                if exec_state == 'SUCCESS' or exec_state == 'ERROR':
                    break
                mistral_retries = mistral_retries - 1
            error_reason = None
            if mistral_retries == 0 and exec_state == 'RUNNING':
                error_reason = _(
                    "MES creation is not completed within"
                    " {wait} seconds as creation of mistral"
                    " execution {mistral} is not completed").format(
                        wait=MISTRAL_RETRIES * MISTRAL_RETRY_WAIT,
                        mistral=execution_id)
            exec_obj = self._vim_drivers.invoke(
                driver_type,
                'get_execution',
                execution_id=execution_id,
                auth_dict=self.get_auth_dict(context))
            self._vim_drivers.invoke(driver_type,
                                     'delete_execution',
                                     execution_id=execution_id,
                                     auth_dict=self.get_auth_dict(context))
            self._vim_drivers.invoke(driver_type,
                                     'delete_workflow',
                                     workflow_id=workflow['id'],
                                     auth_dict=self.get_auth_dict(context))
            super(MeoPlugin, self).create_mes_post(context, mes_id, exec_obj,
                                                   mead_dict, error_reason)

        self.spawn_n(_create_mes_wait, self, mes_dict['id'],
                     mistral_execution.id)
        return mes_dict
예제 #4
0
    def update_mes(self, context, mes_id, mes):
        args = dict()
        mes_info = mes['mes']
        old_mes = super(MesoPlugin, self).get_mes(context, mes_id)
        name = old_mes['name']
        lftover = dict()
        # vm_capacity = 3
        # create inline mesd if given by user

        def _update_nsd_template(req_mesd_dict):
            build_nsd_dict = dict()
            if req_mesd_dict['imports'].get('nsds'):
                args['NS'] = dict()
                # Todo: Support multiple NSs
                # For framework evaluation
                nsd_templates = req_mesd_dict['imports']['nsds']['nsd_templates']      # noqa
                if isinstance(nsd_templates, dict):
                    if nsd_templates.get('requirements'):
                        old_reused = old_mes['reused']
                        vnf_mapping_list = nsd_templates['requirements']
                        for vnf_mapping_dict in vnf_mapping_list:
                            for old_vnf_name, old_nfins_list in old_reused.items():     # noqa
                                if vnf_mapping_dict['name'] == old_vnf_name:
                                    len_diff = len([lend for lend in old_nfins_list if lend > 0])    # noqa
                                    diff = len_diff - vnf_mapping_dict['nf_ins']           # noqa
                                    if diff < 0:
                                        lftover.update({old_vnf_name: -diff})
                                        vm_capacity = VM_CAPA[old_vnf_name]
                                        old_reused[old_vnf_name].extend([vm_capacity] * (-diff))       # noqa
                                    # old_reused[old_vnf_name] = diff
                                    temp = vnf_mapping_dict['nf_ins']
                                    for index, nfins in enumerate(old_nfins_list):      # noqa
                                        if nfins > 0:
                                            old_nfins_list[index] = old_nfins_list[index] - 1     # noqa
                                            temp = temp - 1
                                        if temp == 0:
                                            break

                formal_req = list()
                for nf_name, nf_ins in lftover.items():
                    vnfd_name = 'vnfd' + nf_name[3] + str(nf_ins)
                    formal_req.append(vnfd_name)

                if formal_req:
                    build_nsd_dict['tosca_definitions_version'] = 'tosca_simple_profile_for_nfv_1_0_0'   # noqa
                    build_nsd_dict['description'] = old_mes['description']
                    build_nsd_dict['imports'] = formal_req
                    build_nsd_dict['topology_template'] = dict()
                    build_nsd_dict['topology_template']['node_templates'] = dict()    # noqa
                    for nf_name, nf_ins in lftover.items():
                        node = 'tosca.nodes.nfv.' + nf_name
                        node_dict = dict()
                        node_dict['type'] = node
                        build_nsd_dict['topology_template']['node_templates'].update({nf_name: node_dict})    # noqa
            return build_nsd_dict

        if mes_info.get('mesd_template'):
            # Build vnf_dict here
            mes_name = utils.generate_resource_name(name, 'inline')
            mesd = {'mesd': {'tenant_id': old_mes['tenant_id'],
                           'name': mes_name,
                           'attributes': {
                               'mesd': mes_info['mesd_template']},
                           'template_source': 'inline',
                           'description': old_mes['description']}}
            try:
                mes_info['mesd_id'] = \
                    self.create_mesd(context, mesd).get('id')
            except Exception:
                with excutils.save_and_reraise_exception():
                    super(MesoPlugin, self)._update_mes_status(context, mes_id, constants.ACTIVE)      # noqa

        mesd = self.get_mesd(context, mes_info['mesd_id'])
        mesd_dict = yaml.safe_load(mesd['attributes']['mesd'])
        new_mesd_mapping = mesd['mesd_mapping']
        region_name = mes.setdefault('placement_attr', {}).get(
            'region_name', None)
        vim_res = self.vim_client.get_vim(context, old_mes['vim_id'],
                                          region_name)

        if mesd_dict['imports'].get('meads'):
            # Update MECA
            meo_plugin = manager.ApmecManager.get_service_plugins()['MEO']
            # Build the MECA template here
            mead_tpl_dict = dict()
            mead_tpl_dict['imports'] =\
                mesd_dict['imports']['meads']['mead_templates']
            mecad_dict = copy.deepcopy(mesd_dict)
            mecad_dict.pop('imports')
            mecad_dict.update(mead_tpl_dict)
            mecad_arg = {'meca': {'mecad_template': mecad_dict}}
            old_meca_id = old_mes['mes_mapping']['MECA']
            meca_id = meo_plugin.update_meca(context, old_meca_id, mecad_arg)     # noqa

        if mesd_dict['imports'].get('nsds'):
            nfv_driver = None
            nfv_driver = mesd_dict['imports']['nsds'].get('nfv_driver')
            if not nfv_driver:
                raise meso.NFVDriverNotFound(mesd_name=mesd_dict['name'])
            nfv_driver = nfv_driver.lower()

            req_mesd_dict = yaml.safe_load(mes_info['mesd_template'])
            new_nsd_template = _update_nsd_template(req_mesd_dict)
            nsd_template = None
            if isinstance(new_mesd_mapping.get('NSD'), list):
                nsd_name = new_mesd_mapping['NSD'][0]
                nsd_dict = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'nsd_get_by_name',
                    nsd_name=nsd_name,
                    auth_attr=vim_res['vim_auth'], )
                nsd_template = yaml.safe_load(nsd_dict['attributes']['nsd'])
            actual_nsd_template = new_nsd_template if new_nsd_template else nsd_template      # noqa
            if actual_nsd_template:
                old_ns_id = old_mes['mes_mapping']['NS'][0]
                ns_arg = {'ns': {'nsd_template': actual_nsd_template}}
                self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_update',
                    ns_id=old_ns_id,
                    ns_dict=ns_arg,
                    auth_attr=vim_res['vim_auth'], )

        if mesd_dict['imports'].get('vnffgds'):
            # Todo: Support multiple VNFFGs
            nfv_driver = None
            nfv_driver = mesd_dict['imports']['nsds'].get('nfv_driver')
            if not nfv_driver:
                raise meso.NFVDriverNotFound(mesd_name=mesd_dict['name'])
            nfv_driver = nfv_driver.lower()
            vnffgd_name = new_mesd_mapping['VNFFGD'][0]
            vnffgd_dict = self._nfv_drivers.invoke(
                nfv_driver,  # How to tell it is Tacker
                'vnffgd_get_by_name',
                vnffgd_name=vnffgd_name,
                auth_attr=vim_res['vim_auth'], )
            vnffgd_template = yaml.safe_load(
                vnffgd_dict['attributes']['vnffgd'])
            old_vnffg_id = old_mes['mes_mapping']['VNFFG'][0]
            vnffg_arg = {'vnffg': {'vnffgd_template': vnffgd_template}}
            self._nfv_drivers.invoke(
                nfv_driver,
                'vnffg_update',
                vnffg_id=old_vnffg_id,
                vnffg_dict=vnffg_arg,
                auth_attr=vim_res['vim_auth'], )

        mes_dict = super(MesoPlugin, self)._update_mes_pre(context, mes_id)

        def _update_mes_wait(self_obj, mes_id):
            args = dict()
            mes_status = "ACTIVE"
            ns_status = "PENDING_UPDATE"
            vnffg_status = "PENDING_UPDATE"
            mec_status = "PENDING_UPDATE"
            ns_retries = NS_RETRIES
            mec_retries = MEC_RETRIES
            vnffg_retries = VNFFG_RETRIES
            error_reason_meca = None
            error_reason_ns = None
            error_reason_vnffg = None
            # Check MECA
            if mesd_dict['imports'].get('meads'):
                while mec_status == "PENDING_UPDATE" and mec_retries > 0:
                    time.sleep(MEC_RETRY_WAIT)
                    meca_id = old_mes['mes_mapping']['MECA']
                    meca_list = meo_plugin.get_mecas(context)
                    is_deleted = True
                    for meca in meca_list:
                        if meca_id in meca['id']:
                            is_deleted = False
                    if is_deleted:
                        break
                    mec_status = meo_plugin.get_meca(context, meca_id)['status']         # noqa
                    LOG.debug('status: %s', mec_status)
                    if mec_status == 'ERROR':
                        break
                    mec_retries = mec_retries - 1
                if mec_retries == 0 and mec_status == 'PENDING_UPDATE':
                    error_reason_meca = _(
                        "MES update is not completed within"
                        " {wait} seconds as update of MECA").format(
                        wait=MEC_RETRIES * MEC_RETRY_WAIT)
            # Check NS/VNFFG status
            if mesd_dict['imports'].get('nsds'):
                while ns_status == "PENDING_UPDATE" and ns_retries > 0:
                    time.sleep(NS_RETRY_WAIT)
                    ns_list = old_mes['mes_mapping']['NS']
                    # Todo: support multiple NSs
                    is_existed = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'ns_check',
                        ns_id=ns_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    if not is_existed:
                        break
                    ns_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'ns_get',
                        ns_id=ns_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    ns_status = ns_instance['status']
                    LOG.debug('status: %s', ns_status)
                    if ns_status == 'ERROR':
                        break
                    ns_retries = ns_retries - 1
                if ns_retries == 0 and ns_status == 'PENDING_UPDATE':
                    error_reason_ns = _(
                        "MES update is not completed within"
                        " {wait} seconds as update of NS(s)").format(
                        wait=NS_RETRIES * NS_RETRY_WAIT)

            if mesd_dict['imports'].get('vnffgds'):
                while vnffg_status == "PENDING_UPDATE" and vnffg_retries > 0:
                    time.sleep(VNFFG_RETRY_WAIT)
                    vnffg_list = old_mes['mes_mapping']['VNFFG']
                    # Todo: support multiple VNFFGs
                    is_existed = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'vnffg_check',
                        vnffg_id=vnffg_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    if not is_existed:
                        break
                    vnffg_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'vnffg_get',
                        vnffg_id=vnffg_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    vnffg_status = vnffg_instance['status']
                    LOG.debug('status: %s', vnffg_status)
                    if vnffg_status == 'ERROR':
                        break
                    vnffg_retries = vnffg_retries - 1
                if vnffg_retries == 0 and vnffg_status == 'PENDING_UPDATE':
                    error_reason_vnffg = _(
                        "MES update is not completed within"
                        " {wait} seconds as update of VNFFG(s)").format(
                        wait=VNFFG_RETRIES * VNFFG_RETRY_WAIT)
            args['NS'] = old_mes['reused']
            if mec_status == "ERROR" or ns_status == "ERROR" or vnffg_status == "ERROR":        # noqa
                mes_status = "ERROR"
            error_reason = None
            for reason in [error_reason_meca, error_reason_ns, error_reason_vnffg]:       # noqa
                if reason:
                    error_reason = reason
                    mes_status = "PENDING_UPDATE"
            super(MesoPlugin, self)._update_mes_post(context, mes_id, error_reason, mes_status, args)      # noqa

        self.spawn_n(_update_mes_wait, self, mes_dict['id'])
        return mes_dict
예제 #5
0
    def create_mes(self, context, mes):
        """Create MES and corresponding MEAs.

        :param mes: mes dict which contains mesd_id and attributes
        This method has 2 steps:
        step-1: Call MEO API to create MEAs
        step-2: Call Tacker drivers to create NSs
        """
        mes_info = mes['mes']
        name = mes_info['name']
        mes_info['mes_mapping'] = dict()

        if mes_info.get('mesd_template'):
            mesd_name = utils.generate_resource_name(name, 'inline')
            mesd = {'mesd': {
                'attributes': {'mesd': mes_info['mesd_template']},
                'description': mes_info['description'],
                'name': mesd_name,
                'template_source': 'inline',
                'tenant_id': mes_info['tenant_id']}}
            mes_info['mesd_id'] = self.create_mesd(context, mesd).get('id')

        mesd = self.get_mesd(context, mes['mes']['mesd_id'])
        mesd_dict = yaml.safe_load(mesd['attributes']['mesd'])
        meo_plugin = manager.ApmecManager.get_service_plugins()['MEO']

        region_name = mes.setdefault('placement_attr', {}).get(
            'region_name', None)
        vim_res = self.vim_client.get_vim(context, mes['mes']['vim_id'],
                                          region_name)
        # driver_type = vim_res['vim_type']
        if not mes['mes']['vim_id']:
            mes['mes']['vim_id'] = vim_res['vim_id']

        ##########################################
        # Detect MANO driver here:
        # Defined in the Tosca template
        nfv_driver = None
        if mesd_dict['imports'].get('nsds'):
            nfv_driver = mesd_dict['imports']['nsds']['nfv_driver']
            nfv_driver = nfv_driver.lower()
        if mesd_dict['imports'].get('vnffgds'):
            nfv_driver = mesd_dict['imports']['vnffgds']['nfv_driver']
            nfv_driver = nfv_driver.lower()

        ##########################################
        def _find_vnf_ins(cd_mes):
            al_ns_id_list = cd_mes['mes_mapping'].get('NS')
            if not al_ns_id_list:
                return None, None
            al_ns_id = al_ns_id_list[0]
            try:
                ns_instance = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_get',
                    ns_id=al_ns_id,
                    auth_attr=vim_res['vim_auth'], )
            except Exception:
                return None, None
            if ns_instance['status'] != 'ACTIVE':
                return None, None
            al_vnf = ns_instance['vnf_ids']
            al_vnf_dict = ast.literal_eval(al_vnf)
            return ns_instance['id'], al_vnf_dict

        def _run_meso_algorithm(req_vnf_list):
            is_accepted = False
            al_mes_list = self.get_mess(context)
            ns_candidate = dict()
            for al_mes in al_mes_list:
                ns_candidate[al_mes['id']] = dict()
                if al_mes['status'] != "ACTIVE":
                    continue
                al_ns_id, al_vnf_dict = _find_vnf_ins(al_mes)
                if not al_ns_id:
                    continue
                ns_candidate[al_mes['id']][al_ns_id] = dict()
                for req_vnf_dict in req_vnf_list:
                    for vnf_name, al_vnf_id in al_vnf_dict.items():
                        if req_vnf_dict['name'] == vnf_name:
                            # Todo: remember to change this with VM capacity
                            len_diff =\
                                len([lend for lend in
                                     al_mes['reused'][vnf_name]
                                     if lend > 0])
                            avail = len_diff - req_vnf_dict['nf_ins']
                            ns_candidate[al_mes['id']][al_ns_id].\
                                update({vnf_name: avail})

            ns_cds = dict()
            deep_ns = dict()
            for mesid, ns_data_dict in ns_candidate.items():
                for nsid, resev_dict in ns_data_dict.items():
                    if len(resev_dict) == len(req_vnf_list):
                        nf_ins_list =\
                            [nf_ins for nf_name, nf_ins in
                             resev_dict.items() if nf_ins >= 0]
                        if len(nf_ins_list) == len(req_vnf_list):
                            total_ins = sum(nf_ins_list)
                            ns_cds[mesid] = total_ins
                        else:
                            extra_nf_ins_list =\
                                [-nf_ins for nf_name, nf_ins in
                                 resev_dict.items() if nf_ins < 0]
                            total_ins = sum(extra_nf_ins_list)
                            deep_ns[mesid] = total_ins
            if ns_cds:
                selected_mes1 = min(ns_cds, key=ns_cds.get)
                is_accepted = True
                return is_accepted, selected_mes1, None
            if deep_ns:
                selected_mes2 = min(deep_ns, key=deep_ns.get)
                is_accepted = True
                return is_accepted, selected_mes2, ns_candidate[selected_mes2]

            return is_accepted, None, None

        build_nsd_dict = dict()
        if mesd_dict['imports'].get('nsds'):
            # For framework evaluation
            nsd_template = mesd_dict['imports']['nsds']['nsd_templates']
            if isinstance(nsd_template, dict):
                if nsd_template.get('requirements'):
                    req_nf_dict = nsd_template['requirements']
                    req_nf_list = list()
                    for vnf_dict in req_nf_dict:
                        # Todo: make the requests more natural
                        req_nf_list.append(
                            {'name': vnf_dict['name'],
                             'nf_ins': int(vnf_dict['vnfd_template'][5])})
                    is_accepted, cd_mes_id, cd_vnf_dict =\
                        _run_meso_algorithm(req_nf_list)
                    if is_accepted:
                        new_mesd_dict = dict()
                        ref_mesd_dict = copy.deepcopy(mesd_dict)
                        ref_mesd_dict['imports']['nsds']['nsd_templates']['requirements'] = \
                            req_nf_list
                        new_mesd_dict['mes'] = dict()
                        new_mesd_dict['mes'] =\
                            {'mesd_template': yaml.safe_dump(ref_mesd_dict)}
                        self.update_mes(context, cd_mes_id, new_mesd_dict)
                        return cd_mes_id
                    else:
                        # Create the inline NS with the following template
                        import_list = list()
                        node_dict = dict()
                        for vnfd in req_nf_dict:
                            import_list.append(vnfd['vnfd_template'])
                            node = 'tosca.nodes.nfv.' + vnfd['name']
                            node_dict[vnfd['name']] = {'type': node}
                        build_nsd_dict['tosca_definitions_version'] =\
                            'tosca_simple_profile_for_nfv_1_0_0'
                        build_nsd_dict['description'] = mes_info['description']
                        build_nsd_dict['imports'] = import_list
                        build_nsd_dict['topology_template'] = dict()
                        build_nsd_dict['topology_template']['node_templates'] =\
                            node_dict

            nsds = mesd['attributes'].get('nsds')
            mes_info['mes_mapping']['NS'] = list()
            if nsds:
                nsds_list = nsds.split('-')
                for nsd in nsds_list:
                    ns_name = nsd + '-' + name + '-' + uuidutils.generate_uuid()  # noqa
                    nsd_instance = self._nfv_drivers.invoke(
                        nfv_driver,
                        'nsd_get_by_name',
                        nsd_name=nsd,
                        auth_attr=vim_res['vim_auth'],)
                    if nsd_instance:
                        ns_arg = {'ns': {'nsd_id': nsd_instance['id'],
                                         'name': ns_name}}
                        ns_id = self._nfv_drivers.invoke(
                            nfv_driver,  # How to tell it is Tacker
                            'ns_create',
                            ns_dict=ns_arg,
                            auth_attr=vim_res['vim_auth'], )
                        mes_info['mes_mapping']['NS'].append(ns_id)
            if build_nsd_dict:
                ns_name = 'nsd' + name + '-' + uuidutils.generate_uuid()
                ns_arg = {'ns': {'nsd_template': build_nsd_dict,
                                 'name': ns_name,
                                 'description': mes_info['description'],
                                 'vim_id': '',
                                 'tenant_id': mes_info['tenant_id'],
                                 'attributes': {}}}
                ns_id = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_create',
                    ns_dict=ns_arg,
                    auth_attr=vim_res['vim_auth'], )
                mes_info['mes_mapping']['NS'].append(ns_id)

        vnffgds = mesd['attributes'].get('vnffgds')
        if mesd_dict['imports'].get('vnffgds'):
            vnffgds_list = vnffgds.split('-')
            mes_info['mes_mapping']['VNFFG'] = list()
            for vnffgd in vnffgds_list:
                vnffg_name = vnffgds + '-' + name + '-' + uuidutils.generate_uuid()   # noqa
                vnffgd_instance = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'vnffgd_get_by_name',
                    vnffgd_name=vnffgd,
                    auth_attr=vim_res['vim_auth'], )
                if vnffgd_instance:
                    vnffg_arg = {'vnffg': {'vnffgd_id': vnffgd_instance['id'], 'name': vnffg_name}}  # noqa
                    vnffg_id = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'vnffg_create',
                        vnffg_dict=vnffg_arg,
                        auth_attr=vim_res['vim_auth'], )
                    mes_info['mes_mapping']['VNFFG'].append(vnffg_id)

        # meca_id = dict()
        # Create MEAs using MEO APIs
        try:
            meca_name = 'meca' + '-' + name + '-' + uuidutils.generate_uuid()
            # Separate the imports out from template
            mead_tpl_dict = dict()
            mead_tpl_dict['imports'] =\
                mesd_dict['imports']['meads']['mead_templates']
            mecad_dict = copy.deepcopy(mesd_dict)
            mecad_dict.pop('imports')
            mecad_dict.update(mead_tpl_dict)
            LOG.debug('mesd %s', mecad_dict)
            meca_arg = {'meca': {'mecad_template': mecad_dict, 'name': meca_name,   # noqa
                                 'description': mes_info['description'],
                                 'tenant_id': mes_info['tenant_id'],
                                 'vim_id': mes_info['vim_id'],
                                 'attributes': {}}}
            meca_dict = meo_plugin.create_meca(context, meca_arg)
            mes_info['mes_mapping']['MECA'] = meca_dict['id']
        except Exception as e:
            LOG.error('Error while creating the MECAs: %s', e)
            # Call Tacker client driver

        mes_dict = super(MesoPlugin, self).create_mes(context, mes)

        def _create_mes_wait(self_obj, mes_id):
            args = dict()
            mes_status = "ACTIVE"
            ns_status = "PENDING_CREATE"
            vnffg_status = "PENDING_CREATE"
            mec_status = "PENDING_CREATE"
            ns_retries = NS_RETRIES
            mec_retries = MEC_RETRIES
            vnffg_retries = VNFFG_RETRIES
            mes_mapping = self.get_mes(context, mes_id)['mes_mapping']
            # Check MECA
            meca_id = mes_mapping['MECA']
            while mec_status == "PENDING_CREATE" and mec_retries > 0:
                time.sleep(MEC_RETRY_WAIT)
                mec_status = meo_plugin.get_meca(context, meca_id)['status']
                LOG.debug('status: %s', mec_status)
                if mec_status == 'ACTIVE' or mec_status == 'ERROR':
                    break
                mec_retries = mec_retries - 1
            error_reason = None
            if mec_retries == 0 and mec_status == 'PENDING_CREATE':
                error_reason = _(
                    "MES creation is not completed within"
                    " {wait} seconds as creation of MECA").format(
                    wait=MEC_RETRIES * MEC_RETRY_WAIT)
            # Check NS/VNFFG status
            if mes_mapping.get('NS'):
                ns_list = mes_mapping['NS']
                while ns_status == "PENDING_CREATE" and ns_retries > 0:
                    time.sleep(NS_RETRY_WAIT)
                    # Todo: support multiple NSs
                    ns_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'ns_get',
                        ns_id=ns_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    ns_status = ns_instance['status']
                    LOG.debug('status: %s', ns_status)
                    if ns_status == 'ACTIVE' or ns_status == 'ERROR':
                        break
                    ns_retries = ns_retries - 1
                error_reason = None
                if ns_retries == 0 and ns_status == 'PENDING_CREATE':
                    error_reason = _(
                        "MES creation is not completed within"
                        " {wait} seconds as creation of NS(s)").format(
                        wait=NS_RETRIES * NS_RETRY_WAIT)

                # Determine args
                ns_cd = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_get',
                    ns_id=ns_list[0],
                    auth_attr=vim_res['vim_auth'], )
                ns_instance_dict = ns_cd['mgmt_urls']
                ns_instance_list = ast.literal_eval(ns_instance_dict)
                args['NS'] = dict()

                for vnf_name, mgmt_url_list in ns_instance_list.items():
                    # Todo: remember to change this with VM capacity
                    vm_capacity = VM_CAPA[vnf_name]
                    orig = [vm_capacity] * len(mgmt_url_list)
                    args['NS'][vnf_name] = [(val - 1) for val in orig]

            if mes_mapping.get('VNFFG'):
                while vnffg_status == "PENDING_CREATE" and vnffg_retries > 0:
                    time.sleep(VNFFG_RETRY_WAIT)
                    vnffg_list = mes_mapping['VNFFG']
                    # Todo: support multiple VNFFGs
                    vnffg_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'vnffg_get',
                        vnffg_id=vnffg_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    vnffg_status = vnffg_instance['status']
                    LOG.debug('status: %s', vnffg_status)
                    if vnffg_status == 'ACTIVE' or vnffg_status == 'ERROR':
                        break
                    vnffg_retries = vnffg_retries - 1
                error_reason = None
                if vnffg_retries == 0 and vnffg_status == 'PENDING_CREATE':
                    error_reason = _(
                        "MES creation is not completed within"
                        " {wait} seconds as creation of VNFFG(s)").format(
                        wait=VNFFG_RETRIES * VNFFG_RETRY_WAIT)
            if mec_status == "ERROR" or ns_status == "ERROR" or vnffg_status == "ERROR":   # noqa
                mes_status = "ERROR"
            if error_reason:
                mes_status = "PENDING_CREATE"

            super(MesoPlugin, self).create_mes_post(context, mes_id, mes_status, error_reason, args)   # noqa
        self.spawn_n(_create_mes_wait, self, mes_dict['id'])
        return mes_dict
예제 #6
0
    def create_mes(self, context, mes):
        """Create MES and corresponding MEAs.

        :param mes: mes dict which contains mesd_id and attributes
        This method has 2 steps:
        step-1: Call MEO API to create MEAs
        step-2: Call Tacker drivers to create NSs
        """
        mes_info = mes['mes']
        name = mes_info['name']
        mes_info['mes_mapping'] = dict()

        if mes_info.get('mesd_template'):
            mesd_name = utils.generate_resource_name(name, 'inline')
            mesd = {'mesd': {
                'attributes': {'mesd': mes_info['mesd_template']},
                'description': mes_info['description'],
                'name': mesd_name,
                'template_source': 'inline',
                'tenant_id': mes_info['tenant_id']}}
            mes_info['mesd_id'] = self.create_mesd(context, mesd).get('id')

        mesd = self.get_mesd(context, mes['mes']['mesd_id'])
        mesd_dict = yaml.safe_load(mesd['attributes']['mesd'])
        meo_plugin = manager.ApmecManager.get_service_plugins()['MEO']

        region_name = mes.setdefault('placement_attr', {}).get(
            'region_name', None)
        vim_res = self.vim_client.get_vim(context, mes['mes']['vim_id'],
                                          region_name)
        driver_type = vim_res['vim_type']
        if not mes['mes']['vim_id']:
            mes['mes']['vim_id'] = vim_res['vim_id']

        ##########################################
        # Detect MANO driver here:
        # Defined in the Tosca template
        nfv_driver = None
        if mesd_dict['imports'].get('nsds'):
            nfv_driver = mesd_dict['imports']['nsds']['nfv_driver']
            nfv_driver = nfv_driver.lower()
        if mesd_dict['imports'].get('vnffgds'):
            nfv_driver = mesd_dict['imports']['vnffgds']['nfv_driver']
            nfv_driver = nfv_driver.lower()

        ##########################################
        def _find_vnf_ins(cd_mes):
            al_ns_id_list = cd_mes['mes_mapping'].get('NS')
            if not al_ns_id_list:
                return None, None
            al_ns_id = al_ns_id_list[0]
            try:
                ns_instance = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_get',
                    ns_id=al_ns_id,
                    auth_attr=vim_res['vim_auth'], )
            except:
                return None, None
            if ns_instance['status'] != 'ACTIVE':
                return None, None
            al_vnf = ns_instance['vnf_ids']
            al_vnf_dict = ast.literal_eval(al_vnf)
            return ns_instance['id'], al_vnf_dict

        def _generic_ns_set(req_vnf_list):
            al_mes_list = self.get_mess(context)
            ns_candidate = dict()
            for al_mes in al_mes_list:
                if al_mes['status'] != "ACTIVE":
                    continue
                ns_candidate[al_mes['id']] = dict()
                al_ns_id, al_vnf_dict = _find_vnf_ins(al_mes)
                if not al_ns_id:
                    continue
                ns_candidate[al_mes['id']] = dict()
                for req_vnf_dict in req_vnf_list:
                    for vnf_name, al_vnf_id in al_vnf_dict.items():
                        if req_vnf_dict['name'] == vnf_name:
                            # Todo: remember to change this with VM capacity
                            len_diff = len([lend for lend in al_mes['reused'][vnf_name] if lend > 0])
                            avail = len_diff - req_vnf_dict['nf_ins']
                            ns_candidate[al_mes['id']].update({vnf_name: avail})
        #   The rest will be treated differently by the algorithms
            return ns_candidate

        def _run_meso_rsfca(req_vnf_list, ns_candidate=None):
            rsfca_is_accepted = False
            required_info_dict = dict()
            if not ns_candidate:
                ns_candidate = _generic_ns_set(req_nf_list)
            ns_cds = dict()
            deep_ns = dict()
            for ck_mes_id, ns_data_dict in ns_candidate.items():
                    # This is the heart of the rvnfa
                    if len(ns_data_dict) == len(req_vnf_list):
                        nf_ins_list = [nf_ins for nf_name, nf_ins in ns_data_dict.items() if nf_ins >= 0]
                        if len(nf_ins_list) == len(req_vnf_list):
                            total_ins = sum(nf_ins_list)
                            ns_cds[ck_mes_id] = total_ins
                        else:
                            extra_nf_ins_list = [-nf_ins for nf_name, nf_ins in ns_data_dict.items() if nf_ins < 0]
                            total_ins = sum(extra_nf_ins_list)
                            deep_ns[ck_mes_id] = total_ins
            if ns_cds:
                selected_mes1 = min(ns_cds, key=ns_cds.get)
                required_info_dict[selected_mes1] = ns_candidate[selected_mes1]
                rsfca_is_accepted = True
            if deep_ns:
                selected_mes2 = min(deep_ns, key=deep_ns.get)
                required_info_dict[selected_mes2] = ns_candidate[selected_mes2]
                rsfca_is_accepted = True

            return rsfca_is_accepted, required_info_dict

        def _run_meso_rvnfa(req_vnf_list):
            rvnfa_remain_list = list()
            rvnfa_is_accepted = False
            rvnfa_required_info = dict()
            final_candidate = dict()   # Consider using the OrderDict
            ns_candidate = _generic_ns_set(req_vnf_list)
            if not ns_candidate:
                return rvnfa_is_accepted, None, req_vnf_list
            for req_vnf_dict in req_vnf_list:
                req_vnf_name = req_vnf_dict['name']
                candidate_set = list()
                for ck_mes_id, mes_data_dict in ns_candidate.items():
                        if req_vnf_name in mes_data_dict:
                            slots = mes_data_dict[req_vnf_name]
                            candidate_set.append({'mes_id': ck_mes_id, 'slots': slots})
                exp_slot_list = [mes_candidate['slots'] for mes_candidate in candidate_set if mes_candidate['slots'] >= 0]    # noqa
                if exp_slot_list:
                    min_slot = min(exp_slot_list)
                    mes_list =\
                        [mes_candidate['mes_id'] for mes_candidate in candidate_set if mes_candidate['slots'] == min_slot]     # noqa
                    final_candidate[req_vnf_name] = {'mes_id':mes_list[0], 'slots':min_slot}
            if len(final_candidate) == len(req_nf_list):
                rvnfa_is_accepted = True
            else:
                for remain_vnf_dict in req_nf_list:
                    if remain_vnf_dict['name'] not in final_candidate:
                        rvnfa_remain_list.append(remain_vnf_dict)    # good one
            for req_vnf_name, mixed_mes_info in final_candidate:
                orig_mes_id = mixed_mes_info['mes_id']
                nf_slots = mixed_mes_info['slots']
                if orig_mes_id not in rvnfa_required_info:
                    rvnfa_required_info[orig_mes_id] = dict()
                    rvnfa_required_info[orig_mes_id].update({req_vnf_name: nf_slots})
                else:
                    rvnfa_required_info[orig_mes_id].update({req_vnf_name: nf_slots})
            # return the list of NSs must be updated, when to create new mes?
            return rvnfa_is_accepted, rvnfa_required_info, rvnfa_remain_list

        def _run_meso_ha(req_vnf_list):
            final_candidate_id = None
            ha_required_info = dict()
            ha_remain_list = list()
            ha_is_accepted = False
            ns_candidate = _generic_ns_set(req_vnf_list)
            if not ns_candidate:
                return ha_is_accepted, None, req_nf_list
            ha_is_accepted, ha_mes_dict = _run_meso_rsfca(req_nf_list, ns_candidate)
            if ha_is_accepted:
                return ha_is_accepted, ha_mes_dict, None
            else:
                ns_list = list()
                for ck_mes_id, mes_data_dict in ns_candidate.items():
                        lenNF = len(mes_data_dict)
                        ns_list.append({'mes_id': ck_mes_id, 'numNFs': lenNF})
                maxNFs = max([ns_info['numNFs'] for ns_info in ns_list])
                first_filter_list = list()
                second_filter_list = list()
                for ns_info in ns_list:
                    if ns_info['numNFs'] == maxNFs:
                        mes_id = ns_info['mes_id']
                        exp_NFs = [slots for exp_vnf_name, slots in ns_candidate[mes_id].items() if slots >= 0]
                        unexp_NFs = [-slots for exp_vnf_name, slots in ns_candidate[mes_id].items() if slots < 0]
                        if len(exp_NFs) == maxNFs:
                            first_filter_list.append(
                                {'mes_id': mes_id, 'slots': sum(exp_NFs)})
                        else:
                            second_filter_list.append(
                                {'mes_id': mes_id, 'slots': sum(unexp_NFs)})
                if first_filter_list:
                    exp_slot = min([exp_mes['slots'] for exp_mes in first_filter_list])
                    exp_mes_list = [exp_mes['mes_id'] for exp_mes in first_filter_list if exp_mes['slots'] == exp_slot]
                    final_candidate_id = exp_mes_list[0]
                if second_filter_list:
                    unexp_slot = min([exp_mes['slots'] for exp_mes in second_filter_list])
                    exp_mes_list = [exp_mes['mes_id'] for exp_mes in second_filter_list if
                                    exp_mes['slots'] == unexp_slot]
                    final_candidate_id = exp_mes_list[0]

                if final_candidate_id:
                    ha_required_info[final_candidate_id] = ns_candidate[final_candidate_id]
                    rvnf_remain_list = [exp_vnf_dict for exp_vnf_dict in req_vnf_list if exp_vnf_dict['name'] not in ns_candidate[final_candidate_id]]    # noqa
                    vnf_is_accepted, rvnf_required_info, rvnf_remain_list = _run_meso_rvnfa(rvnf_remain_list)
                    ha_remain_list.extend(rvnf_remain_list)
                    ha_required_info.update(rvnf_required_info)
            # only return the mes_id and the mes_info need to update

            return ha_is_accepted, ha_required_info, ha_remain_list

        build_nsd_dict = dict()
        if mesd_dict['imports'].get('nsds'):
            # For framework evaluation
            nsd_template = mesd_dict['imports']['nsds']['nsd_templates']
            if isinstance(nsd_template, dict):
                if nsd_template.get('requirements'):
                    req_nf_dict = nsd_template['requirements']
                    req_nf_list = list()
                    for vnf_dict in req_nf_dict:
                        # Todo: make the requests more natural
                        req_nf_list.append({'name': vnf_dict['name'], 'nf_ins': int(vnf_dict['vnfd_template'][5])})
                    is_accepted, mes_info_dict = _run_meso_rsfca(req_nf_list)
                    if is_accepted:
                        update_list = list()
                        for cd_mes_id, mes_dict in mes_info_dict.items():
                            new_mesd_dict = dict()
                            ref_mesd_dict = copy.deepcopy(mesd_dict)
                            ref_mesd_dict['imports']['nsds']['nsd_templates']['requirements'] = mes_dict
                            new_mesd_dict['mes'] = dict()
                            new_mesd_dict['mes'] = {'mesd_template': yaml.safe_dump(ref_mesd_dict)}
                            return self.update_mes(context,cd_mes_id, new_mesd_dict)
                            # update_list.append(cd_mes_id)
                        # return {}
                    else:
                        # Create the inline NS with the following template
                        import_list = list()
                        node_dict = dict()
                        for vnfd in req_nf_dict:
                            import_list.append(vnfd['vnfd_template'])
                            node = 'tosca.nodes.nfv.' + vnfd['name']
                            node_dict[vnfd['name']] = {'type': node}
                        build_nsd_dict['tosca_definitions_version'] = 'tosca_simple_profile_for_nfv_1_0_0'
                        build_nsd_dict['description'] = mes_info['description']
                        build_nsd_dict['imports'] = import_list
                        build_nsd_dict['topology_template'] = dict()
                        build_nsd_dict['topology_template']['node_templates'] = node_dict

                    # Temp update the new NFs
                    # For these cases, remember when to update the MEA

                    ha_is_accepted, required_info, remain_list = _run_meso_ha(req_nf_list)
                    rvnfa_is_accepted, required_info, remain_list = _run_meso_rvnfa(req_nf_list)
                    if required_info:
                        update_list = list()
                        for cd_mes_id, mes_dict in required_info.items():
                            new_mesd_dict = dict()
                            ref_mesd_dict = copy.deepcopy(mesd_dict)
                            ref_mesd_dict['imports']['nsds']['nsd_templates']['requirements'] = mes_dict
                            new_mesd_dict['mes'] = dict()
                            new_mesd_dict['mes'] = {'mesd_template': yaml.safe_dump(ref_mesd_dict)}
                            self.update_mes(context, cd_mes_id, new_mesd_dict)
                            update_list.append(cd_mes_id)
                        if not remain_list:
                            return {}
                    if remain_list:
                        # reform the vnf_dict
                        vnf_info_tpl = list()
                        for vnf_dict in remain_list:
                            vnf_ins = vnf_dict['nf_ins']
                            node_name = vnf_dict['name']
                            vnfd_tpl = 'vnfd' + node_name[3] + str(vnf_ins)
                            vnf_info_tpl.append({'name': node_name, 'vnfd_template': vnfd_tpl})
                        import_list = list()
                        node_dict = dict()
                        for vnfd in vnf_info_tpl:
                            import_list.append(vnfd['vnfd_template'])
                            node = 'tosca.nodes.nfv.' + vnfd['name']
                            node_dict[vnfd['name']] = {'type': node}
                        build_nsd_dict['tosca_definitions_version'] = 'tosca_simple_profile_for_nfv_1_0_0'
                        build_nsd_dict['description'] = mes_info['description']
                        build_nsd_dict['imports'] = import_list
                        build_nsd_dict['topology_template'] = dict()
                        build_nsd_dict['topology_template']['node_templates'] = node_dict

            nsds = mesd['attributes'].get('nsds')
            mes_info['mes_mapping']['NS'] = list()
            if nsds:
                nsds_list = nsds.split('-')
                for nsd in nsds_list:
                  ns_name = nsd + '-' + name + '-' + uuidutils.generate_uuid()
                  nsd_instance = self._nfv_drivers.invoke(
                      nfv_driver, # How to tell it is Tacker
                      'nsd_get_by_name',
                      nsd_name=nsd,
                      auth_attr=vim_res['vim_auth'],)
                  if nsd_instance:
                      ns_arg = {'ns': {'nsd_id': nsd_instance['id'], 'name': ns_name}}
                      ns_id = self._nfv_drivers.invoke(
                          nfv_driver,  # How to tell it is Tacker
                          'ns_create',
                          ns_dict=ns_arg,
                          auth_attr=vim_res['vim_auth'], )
                      mes_info['mes_mapping']['NS'].append(ns_id)
            if build_nsd_dict:
                ns_name = 'nsd' + name + '-' + uuidutils.generate_uuid()
                ns_arg = {'ns': {'nsd_template': build_nsd_dict, 'name': ns_name,
                                     'description': mes_info['description'], 'vim_id': '',
                                 'tenant_id': mes_info['tenant_id'], 'attributes': {}}}
                ns_id = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_create',
                    ns_dict=ns_arg,
                    auth_attr=vim_res['vim_auth'], )
                mes_info['mes_mapping']['NS'].append(ns_id)

        vnffgds = mesd['attributes'].get('vnffgds')
        if mesd_dict['imports'].get('vnffgds'):
          vnffgds_list = vnffgds.split('-')
          mes_info['mes_mapping']['VNFFG'] = list()
          for vnffgd in vnffgds_list:
            vnffg_name = vnffgds + '-' + name + '-' + uuidutils.generate_uuid()
            vnffgd_instance = self._nfv_drivers.invoke(
                nfv_driver,  # How to tell it is Tacker
                'vnffgd_get_by_name',
                vnffgd_name=vnffgd,
                auth_attr=vim_res['vim_auth'], )
            if vnffgd_instance:
                vnffg_arg = {'vnffg': {'vnffgd_id': vnffgd_instance['id'], 'name': vnffg_name}}
                vnffg_id = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'vnffg_create',
                    vnffg_dict=vnffg_arg,
                    auth_attr=vim_res['vim_auth'], )
                mes_info['mes_mapping']['VNFFG'].append(vnffg_id)

        meca_id = dict()
        # Create MEAs using MEO APIs
        try:
            meca_name = 'meca' + '-' + name + '-' + uuidutils.generate_uuid()
            # Separate the imports out from template
            mead_tpl_dict = dict()
            mead_tpl_dict['imports'] = mesd_dict['imports']['meads']['mead_templates']
            mecad_dict = copy.deepcopy(mesd_dict)
            mecad_dict.pop('imports')
            mecad_dict.update(mead_tpl_dict)
            LOG.debug('mesd %s', mecad_dict)
            meca_arg = {'meca': {'mecad_template': mecad_dict, 'name': meca_name,
                                 'description': mes_info['description'], 'tenant_id': mes_info['tenant_id'],
                                 'vim_id': mes_info['vim_id'], 'attributes': {}}}
            meca_dict = meo_plugin.create_meca(context, meca_arg)
            mes_info['mes_mapping']['MECA'] = meca_dict['id']
        except Exception as e:
            LOG.error('Error while creating the MECAs: %s', e)
            # Call Tacker client driver

        mes_dict = super(MesoPlugin, self).create_mes(context, mes)

        def _create_mes_wait(self_obj, mes_id):
            args = dict()
            mes_status = "ACTIVE"
            ns_status = "PENDING_CREATE"
            vnffg_status = "PENDING_CREATE"
            mec_status = "PENDING_CREATE"
            ns_retries = NS_RETRIES
            mec_retries = MEC_RETRIES
            vnffg_retries = VNFFG_RETRIES
            mes_mapping = self.get_mes(context, mes_id)['mes_mapping']
            # Check MECA
            meca_id = mes_mapping['MECA']
            while mec_status == "PENDING_CREATE" and mec_retries > 0:
                time.sleep(MEC_RETRY_WAIT)
                mec_status = meo_plugin.get_meca(context, meca_id)['status']
                LOG.debug('status: %s', mec_status)
                if mec_status == 'ACTIVE' or mec_status == 'ERROR':
                    break
                mec_retries = mec_retries - 1
            error_reason = None
            if mec_retries == 0 and mec_status == 'PENDING_CREATE':
                error_reason = _(
                    "MES creation is not completed within"
                    " {wait} seconds as creation of MECA").format(
                    wait=MEC_RETRIES * MEC_RETRY_WAIT)
            # Check NS/VNFFG status
            if mes_mapping.get('NS'):
                ns_list = mes_mapping['NS']
                while ns_status == "PENDING_CREATE" and ns_retries > 0:
                    time.sleep(NS_RETRY_WAIT)
                    # Todo: support multiple NSs
                    ns_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'ns_get',
                        ns_id=ns_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    ns_status = ns_instance['status']
                    LOG.debug('status: %s', ns_status)
                    if ns_status == 'ACTIVE' or ns_status == 'ERROR':
                        break
                    ns_retries = ns_retries - 1
                error_reason = None
                if ns_retries == 0 and ns_status == 'PENDING_CREATE':
                    error_reason = _(
                        "MES creation is not completed within"
                        " {wait} seconds as creation of NS(s)").format(
                        wait=NS_RETRIES * NS_RETRY_WAIT)

                # Determine args
                ns_cd = self._nfv_drivers.invoke(
                    nfv_driver,  # How to tell it is Tacker
                    'ns_get',
                    ns_id=ns_list[0],
                    auth_attr=vim_res['vim_auth'], )
                ns_instance_dict = ns_cd['mgmt_urls']
                ns_instance_list = ast.literal_eval(ns_instance_dict)
                args['NS'] = dict()

                for vnf_name, mgmt_url_list in ns_instance_list.items():
                    # Todo: remember to change this with VM capacity
                    vm_capacity = VM_CAPA[vnf_name]
                    orig = [vm_capacity] * len(mgmt_url_list)
                    args['NS'][vnf_name] = [(val - 1) for val in orig]

            if mes_mapping.get('VNFFG'):
                while vnffg_status == "PENDING_CREATE" and vnffg_retries > 0:
                    time.sleep(VNFFG_RETRY_WAIT)
                    vnffg_list = mes_mapping['VNFFG']
                    # Todo: support multiple VNFFGs
                    vnffg_instance = self._nfv_drivers.invoke(
                        nfv_driver,  # How to tell it is Tacker
                        'vnffg_get',
                        vnffg_id=vnffg_list[0],
                        auth_attr=vim_res['vim_auth'], )
                    vnffg_status = vnffg_instance['status']
                    LOG.debug('status: %s', vnffg_status)
                    if vnffg_status == 'ACTIVE' or vnffg_status == 'ERROR':
                        break
                    vnffg_retries = vnffg_retries - 1
                error_reason = None
                if vnffg_retries == 0 and vnffg_status == 'PENDING_CREATE':
                    error_reason = _(
                        "MES creation is not completed within"
                        " {wait} seconds as creation of VNFFG(s)").format(
                        wait=VNFFG_RETRIES * VNFFG_RETRY_WAIT)
            if mec_status == "ERROR" or ns_status == "ERROR" or vnffg_status == "ERROR":
                mes_status = "ERROR"
            if error_reason:
                mes_status = "PENDING_CREATE"

            super(MesoPlugin, self).create_mes_post(context, mes_id, mes_status, error_reason, args)
        self.spawn_n(_create_mes_wait, self, mes_dict['id'])
        return mes_dict