def _create_vnffg_post(self, context, sfc_instance_id, fc_instance_id, vnffg_dict): LOG.debug(_('SFC created instance is %s'), sfc_instance_id) LOG.debug(_('Flow Classifier created instance is %s'), fc_instance_id) nfp_dict = self.get_nfp(context, vnffg_dict['forwarding_paths']) sfc_id = nfp_dict['chain_id'] classifier_id = nfp_dict['classifier_id'] with context.session.begin(subtransactions=True): query = (self._model_query(context, VnffgChain). filter(VnffgChain.id == sfc_id). filter(VnffgChain.status == constants.PENDING_CREATE). one()) query.update({'instance_id': sfc_instance_id}) if sfc_instance_id is None: query.update({'status': constants.ERROR}) else: query.update({'status': constants.ACTIVE}) query = (self._model_query(context, VnffgClassifier). filter(VnffgClassifier.id == classifier_id). filter(VnffgClassifier.status == constants.PENDING_CREATE). one()) query.update({'instance_id': fc_instance_id}) if fc_instance_id is None: query.update({'status': constants.ERROR}) else: query.update({'status': constants.ACTIVE})
def load_class_by_alias_or_classname(namespace, name): """Load class using stevedore alias or the class name Load class using the stevedore driver manager :param namespace: namespace where the alias is defined :param name: alias or class name of the class to be loaded :returns: class if calls can be loaded :raises ImportError: if class cannot be loaded """ if not name: LOG.error("Alias or class name is not set") raise ImportError(_("Class not found.")) try: # Try to resolve class by alias mgr = driver.DriverManager(namespace, name) class_to_load = mgr.driver except RuntimeError: e1_info = sys.exc_info() # Fallback to class name try: class_to_load = importutils.import_class(name) except (ImportError, ValueError): LOG.error("Error loading class by alias", exc_info=e1_info) LOG.error("Error loading class by class name", exc_info=True) raise ImportError(_("Class not found.")) return class_to_load
def _make_vnffg_dict(self, vnffg_db, fields=None): LOG.debug(_('vnffg_db %s'), vnffg_db) LOG.debug(_('vnffg_db nfp %s'), vnffg_db.forwarding_paths) res = { 'forwarding_paths': vnffg_db.forwarding_paths[0]['id'] } key_list = ('id', 'tenant_id', 'name', 'description', 'vnf_mapping', 'status', 'vnffgd_id') res.update((key, vnffg_db[key]) for key in key_list) return self._fields(res, fields)
def _make_classifier_dict(self, classifier_db, fields=None): LOG.debug(_('classifier_db %s'), classifier_db) LOG.debug(_('classifier_db match %s'), classifier_db.match) res = { 'match': self._make_acl_match_dict(classifier_db.match) } key_list = ('id', 'tenant_id', 'instance_id', 'status', 'chain_id', 'nfp_id') res.update((key, classifier_db[key]) for key in key_list) return self._fields(res, fields)
def delete_vim_auth(self, vim_id): """Delete vim information Delete vim key stored in file system """ LOG.debug(_('Attempting to delete key for vim id %s'), vim_id) key_file = os.path.join(CONF.vim_keys.openstack, vim_id) try: os.remove(key_file) LOG.debug(_('VIM key deleted successfully for vim %s'), vim_id) except OSError: LOG.warning(_('VIM key deletion unsuccessful for vim %s'), vim_id)
def _get_vnf_mapping(self, context, vnf_mapping, vnf_members): """Creates/validates a mapping of VNFD names to VNF IDs for NFP. :param context: SQL session context :param vnf_mapping: dict of requested VNFD:VNF_ID mappings :param vnf_members: list of constituent VNFs from a VNFFG :return: dict of VNFD:VNF_ID mappings """ vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM'] new_mapping = dict() for vnfd in vnf_members: # there should only be one ID returned for a unique name try: vnfd_id = vnfm_plugin.get_vnfds(context, {'name': [vnfd]}, fields=['id']).pop()['id'] except Exception: raise nfvo.VnffgdVnfdNotFoundException(vnfd_name=vnfd) if vnfd_id is None: raise nfvo.VnffgdVnfdNotFoundException(vnfd_name=vnfd) else: # if no VNF mapping, we need to abstractly look for instances # that match VNFD if vnf_mapping is None or vnfd not in vnf_mapping.keys(): # find suitable VNFs from vnfd_id LOG.debug(_('Searching VNFS with id %s'), vnfd_id) vnf_list = vnfm_plugin.get_vnfs(context, {'vnfd_id': [vnfd_id]}, fields=['id']) if len(vnf_list) == 0: raise nfvo.VnffgInvalidMappingException(vnfd_name=vnfd) else: LOG.debug(_('Matching VNFs found %s'), vnf_list) vnf_list = [vnf['id'] for vnf in vnf_list] if len(vnf_list) > 1: new_mapping[vnfd] = random.choice(vnf_list) else: new_mapping[vnfd] = vnf_list[0] # if VNF mapping, validate instances exist and match the VNFD else: vnf_vnfd = vnfm_plugin.get_vnf(context, vnf_mapping[vnfd], fields=['vnfd_id']) if vnf_vnfd is not None: vnf_vnfd_id = vnf_vnfd['vnfd_id'] else: raise nfvo.VnffgInvalidMappingException(vnfd_name=vnfd) if vnfd_id != vnf_vnfd_id: raise nfvo.VnffgInvalidMappingException(vnfd_name=vnfd) else: new_mapping[vnfd] = vnf_mapping.pop(vnfd) self._validate_vim(context, new_mapping.values()) return new_mapping
def _validate_auth_url(self, auth_url): try: keystone_version = self.keystone.get_version(auth_url) except Exception as e: LOG.error(_('VIM Auth URL invalid')) raise nfvo.VimConnectionException(message=e.message) return keystone_version
def delete_chain(self, chain_id, auth_attr=None): if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) return None neutronclient_ = NeutronClient(auth_attr) neutronclient_.port_chain_delete(chain_id)
def flow_classifier_create(self, fc_dict): LOG.debug(_("fc_dict passed is {fc_dict}").format(fc_dict=fc_dict)) fc = self.client.create_flow_classifier({'flow_classifier': fc_dict}) if fc: return fc['flow_classifier']['id'] else: return None
def _make_chain_dict(self, chain_db, fields=None): LOG.debug(_('chain_db %s'), chain_db) res = {} key_list = ('id', 'tenant_id', 'symmetrical', 'status', 'chain', 'path_id', 'nfp_id', 'instance_id') res.update((key, chain_db[key]) for key in key_list) return self._fields(res, fields)
def _make_cluster_member_dict(self, cluster_id, index, role, vnf_info): cluster_member_dict = {} cluster_member_dict['cluster_id'] = cluster_id cluster_member_dict['index'] = index cluster_member_dict['role'] = role cluster_member_dict['vnf_info'] = vnf_info LOG.debug(_("_make_cluster_member_dict c : %s"), cluster_member_dict) return cluster_member_dict
def validate_tosca(self, template): if "tosca_definitions_version" not in template: raise nfvo.ToscaParserFailed( error_msg_details='tosca_definitions_version missing in ' 'template' ) LOG.debug(_('template yaml: %s'), template) toscautils.updateimports(template) try: tosca_template.ToscaTemplate( a_file=False, yaml_dict_tpl=template) except Exception as e: LOG.exception(_("tosca-parser error: %s"), str(e)) raise nfvo.ToscaParserFailed(error_msg_details=str(e))
def delete_flow_classifier(self, fc_id, auth_attr=None): if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) raise EnvironmentError('auth attribute required for' ' networking-sfc driver') neutronclient_ = NeutronClient(auth_attr) neutronclient_.flow_classifier_delete(fc_id)
def _make_nfp_dict(self, nfp_db, fields=None): LOG.debug(_('nfp_db %s'), nfp_db) res = {'chain_id': nfp_db.chain['id'], 'classifier_id': nfp_db.classifier['id']} key_list = ('name', 'id', 'tenant_id', 'symmetrical', 'status', 'path_id', 'vnffg_id') res.update((key, nfp_db[key]) for key in key_list) return self._fields(res, fields)
def create_vnffgd(self, context, vnffgd): template = vnffgd['vnffgd'] LOG.debug(_('template %s'), template) tenant_id = self._get_tenant_id_for_create(context, template) with context.session.begin(subtransactions=True): template_id = str(uuid.uuid4()) template_db = VnffgTemplate( id=template_id, tenant_id=tenant_id, name=template.get('name'), description=template.get('description'), template=template.get('template')) context.session.add(template_db) LOG.debug(_('template_db %(template_db)s'), {'template_db': template_db}) return self._make_template_dict(template_db)
def _get_policy_property(self, vnfd_dict, prop_name): polices = vnfd_dict['topology_template'].get('policies', []) prop = None for policy_dict in polices: for name, policy in policy_dict.items(): if(policy.get('type') == constants.POLICY_LOADBALANCE): prop = policy.get('properties')[prop_name] LOG.debug(_("create_vnfcluster prop: %s"), prop) return prop
def _create_secret_ref(self, object_id): """Creates the URL required for accessing a secret. :param object_id: the UUID of the key to copy :return: the URL of the requested secret """ if not object_id: msg = _("Key ID is None") raise exception.KeyManagerError(reason=msg) return "%ssecrets/%s" % (self._base_url, object_id)
def register_vim(self, vim_obj): """Validate and register VIM Store VIM information in Tacker for VNF placements """ ks_client = self.authenticate_vim(vim_obj) self.discover_placement_attr(vim_obj, ks_client) self.encode_vim_auth(vim_obj['id'], vim_obj['auth_cred']) LOG.debug(_('VIM registration completed for %s'), vim_obj)
def update_chain(self, chain_id, fc_ids, vnfs, symmetrical=False, auth_attr=None): # TODO(s3wong): chain can be updated either for # the list of fc and/or list of port-pair-group # since n-sfc driver does NOT track the ppg id # it will look it up (or reconstruct) from # networking-sfc DB --- but the caveat is that # the VNF name MUST be unique LOG.warning(_("n-sfc driver does not support sf chain update")) raise NotImplementedError('sf chain update not supported')
def create_flow_classifier(self, name, fc, symmetrical=False, auth_attr=None): def _translate_ip_protocol(ip_proto): if ip_proto == '1': return 'icmp' elif ip_proto == '6': return 'tcp' elif ip_proto == '17': return 'udp' else: return None if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) return None if symmetrical: LOG.warning(_("n-sfc driver does not support symmetrical")) raise NotImplementedError('symmetrical chain not supported') LOG.debug(_('fc passed is %s'), fc) sfc_classifier_params = {} for field in fc: if field in FC_MAP: sfc_classifier_params[FC_MAP[field]] = fc[field] elif field == 'ip_proto': protocol = _translate_ip_protocol(str(fc[field])) if not protocol: raise ValueError('protocol %s not supported' % fc[field]) sfc_classifier_params['protocol'] = protocol else: LOG.warning(_("flow classifier %s not supported by " "networking-sfc driver"), field) LOG.debug(_('sfc_classifier_params is %s'), sfc_classifier_params) if len(sfc_classifier_params) > 0: neutronclient_ = NeutronClient(auth_attr) fc_id = neutronclient_.flow_classifier_create( sfc_classifier_params) return fc_id raise ValueError('empty match field for input flow classifier')
def port_pair_create(self, port_pair_dict): try: pp = self.client.create_port_pair({'port_pair': port_pair_dict}) except nc_exceptions.BadRequest as e: LOG.error(_("create port pair returns %s") % e) raise ValueError(str(e)) if pp and len(pp): return pp['port_pair']['id'] else: return None
def _decode_vim_auth(self, vim_id, cred): """Decode Vim credentials Decrypt VIM cred. using Fernet Key """ vim_key = self._find_vim_key(vim_id) f = fernet.Fernet(vim_key) if not f: LOG.warning(_('Unable to decode VIM auth')) raise nfvo.VimNotFoundException('Unable to decode VIM auth key') return f.decrypt(cred)
def create_loadbalancer(self, lb_pool, lb_vip, auth_attr=None): result = {} if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) raise EnvironmentError('auth attribute required for' ' networking-sfc driver') neutronclient_ = NeutronClient(auth_attr) subnet_id = neutronclient_.subnet_get(lb_vip['subnet']) result['subnet_id'] = subnet_id lb = neutronclient_.loadbalancer_create(subnet_id, lb_vip.get('address', None)) lb_id = lb.get('loadbalancer').get('id') LOG.debug(_("create_loadbalancer lb_id : %s"), lb_id) res = self._wait_for_lb_ready(neutronclient_, lb_id) if res is False: return None result['loadbalancer'] = lb_id result['vip_address'] = lb['loadbalancer'].get('vip_address') listener = neutronclient_.listener_create(lb_id, lb_vip['protocol'], lb_vip['protocol_port'], lb_vip.get('connection_limit', None)) listener_id = listener.get('listener').get('id') result['listener'] = listener_id res = self._wait_for_lb_ready(neutronclient_, lb_id) if res is False: return None lb_pool = neutronclient_.pool_create(lb_pool['lb_method'], listener_id, lb_pool['protocol']) pool_id = lb_pool.get('pool').get('id') result['pool'] = pool_id res = self._wait_for_lb_ready(neutronclient_, lb_id) if res is False: return None result['protocol_port'] = lb_vip['protocol_port'] return result
def discover_placement_attr(self, vim_obj, ks_client): """Fetch VIM placement information Attributes can include regions, AZ. """ try: regions_list = self._find_regions(ks_client) except (exceptions.Unauthorized, exceptions.BadRequest) as e: LOG.warn(_("Authorization failed for user")) raise nfvo.VimUnauthorizedException(message=e.message) vim_obj['placement_attr'] = {'regions': regions_list} return vim_obj
def port_pair_group_create(self, ppg_dict): try: ppg = self.client.create_port_pair_group( {'port_pair_group': ppg_dict}) except nc_exceptions.BadRequest as e: LOG.warning(_('create port pair group returns %s') % e) raise ValueError(str(e)) if ppg and len(ppg): return ppg['port_pair_group']['id'] else: return None
def port_chain_create(self, port_chain_dict): try: pc = self.client.create_port_chain( {'port_chain': port_chain_dict}) except nc_exceptions.BadRequest as e: LOG.warning(_('create port chain returns %s') % e) raise ValueError(str(e)) if pc and len(pc): return pc['port_chain']['id'] else: return None
def _create_base_url(self, auth, sess, endpoint): discovery = auth.get_discovery(sess, url=endpoint) raw_data = discovery.raw_version_data() if len(raw_data) == 0: msg = _( "Could not find discovery information for %s") % endpoint LOG.error(msg) raise exception.KeyManagerError(reason=msg) latest_version = raw_data[-1] api_version = latest_version.get('id') base_url = "%s%s/" % (endpoint, api_version) return base_url
def _create_new_vnf_cluster(context, cluster_name, vnf_id): def _make_vnf_name(cluster_name): cluster_instance = str(uuid.uuid4()) return cluster_name + '-vnf-' + cluster_instance vnf = vnfm_plugin.get_vnf(context, vnf_id) vnfd_dict = yaml.load(vnf['vnfd']['attributes']['vnfd']) LOG.debug(_("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")) LOG.debug(_("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")) LOG.debug(_("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")) vnf_info = {} vnf_info['tenant_id'] = vnf['tenant_id'] vnf_info['vnfd_id'] = vnf['vnfd_id'] vnf_name = _make_vnf_name(cluster_name) pre_vnf_dict = self._make_vnf_create_dict(vnf_info, vnf_name) LOG.debug(_("_create_new_vnf_cluster vnfd_dict : %s"), vnfd_dict) LOG.debug(_("_create_new_vnf_cluster vnf : %s"), vnf) vnf_dict = vnfm_plugin.create_vnf(context, pre_vnf_dict) ## Need to find appropriate Func to wait for creating VNF while(1): LOG.debug(_("create_vnfcluster new_vnf_dict.get('status'): %s"), vnf_dict.get('status')) if vnf_dict.get('status') == 'ACTIVE': break time.sleep(4) return vnf_dict
def pool_member_add(self, net_port_id, lb_info, auth_attr=None): """Add a member to Neutron lbaas pool.""" if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) raise EnvironmentError('auth attribute required for' ' networking-sfc driver') lb_id = lb_info['loadbalancer'] neutronclient_ = NeutronClient(auth_attr) port_info = neutronclient_.find_port_info_by_port_id(net_port_id) address = port_info['port']['fixed_ips'][0]['ip_address'] LOG.debug(_("pool_member_add lb_id : %s"), lb_id) LOG.debug(_("pool_member_add address : %s"), address) res = self._wait_for_lb_ready(neutronclient_, lb_id) if not res: LOG.warning(_('Loadbalancer %s is not ready.'), lb_info['loadbalancer']) return None member = neutronclient_.pool_member_create(lb_info['pool'], address, lb_info['protocol_port'], lb_info['subnet_id']) member_id = member['member']['id'] LOG.debug(_("member_add member_id : %s"), member_id) res = self._wait_for_lb_ready(neutronclient_, lb_id) if res is False: LOG.warning(_('Failed in creating pool member (%s).'), member_id) return None return member_id
def update_flow_classifier(self, fc_id, fc, symmetrical=False, auth_attr=None): if not auth_attr: LOG.warning(_("auth information required for n-sfc driver")) return None if symmetrical: LOG.warning(_("n-sfc driver does not support symmetrical")) raise NotImplementedError('symmetrical chain not supported') # for now, the only parameters allowed for flow-classifier-update # is 'name' and/or 'description' sfc_classifier_params = {} sfc_classifier_params['name'] = fc['name'] sfc_classifier_params['description'] = fc['description'] LOG.debug(_('sfc_classifier_params is %s'), sfc_classifier_params) neutronclient_ = NeutronClient(auth_attr) return neutronclient_.flow_classifier_update(fc_id, sfc_classifier_params)
class VnfPolicyTypeInvalid(BadRequest): message = _("Invalid type %(type)s for policy %(policy)s, " "should be one of %(valid_types)s")
class VimGetResourceException(exceptions.TackerException): message = _("Error while trying to issue %(cmd)s to find resource type " "%(type)s by resource name %(name)s")
class VimInUseException(exceptions.TackerException): message = _("VIM %(vim_id)s is still in use by VNF")
class VimGetResourceNotFoundException(exceptions.TackerException): message = _("Getting resource id from VIM with resource name %(name)s " "by %(cmd)s returns nothing")
class ToscaParserFailed(exceptions.InvalidInput): message = _("tosca-parser failed: - %(error_msg_details)s")
class VnffgdDuplicateForwarderException(exceptions.InvalidInput): message = _("Invalid Forwarding Path contains duplicate forwarder not in " "order: %(forwarder)s")
class VimUnsupportedResourceTypeException(exceptions.TackerException): message = _("Resource type %(type)s is unsupported by VIM")
class TriggerNotFound(NotFound): message = _("Trigger %(trigger_name)s does not exist for VNF %(vnf_id)s")
class NotAuthorized(TackerException): message = _("Not authorized.")
class NotFound(TackerException): message = _('%(resource)s %(name)s not Found')
class BadRequest(TackerException): message = _('Bad %(resource)s request: %(msg)s')
class DuplicateEntity(Conflict): message = _("%(_type)s already exist with given %(entry)s")
class VnfPolicyNotFound(NotFound): message = _("Policy %(policy)s does not exist for VNF %(vnf_id)s")
class VimDefaultDuplicateException(exceptions.TackerException): message = _("Default VIM already exists %(vim_id)s.")
class AlarmUrlInvalid(BadRequest): message = _("Invalid alarm url for VNF %(vnf_id)s")
class VimRegionNotFoundException(exceptions.TackerException): message = _("Unknown VIM region name %(region_name)s")
class VnffgdInvalidTemplate(exceptions.InvalidInput): message = _("Invalid VNFFG template input: %(template)s")
class MgmtDriverException(TackerException): message = _("VNF configuration failed")
class VimDefaultNotDefined(exceptions.TackerException): message = _("Default VIM is not defined.")
class DuplicatedExtension(TackerException): message = _("Found duplicate extension: %(alias)s")
class VimFromVnfNotFoundException(exceptions.NotFound): message = _('VIM from VNF %(vnf_id)s could not be found')
class VimNotFoundException(exceptions.TackerException): message = _("Specified VIM id %(vim_id)s is invalid. Please verify and " "pass a valid VIM id")
class VimGetResourceNameNotUnique(exceptions.TackerException): message = _("Getting resource id from VIM with resource name %(name)s " "by %(cmd)s returns more than one")
class InvalidContentType(TackerException): message = _("Invalid content type %(content_type)s")
class VimConnectionException(exceptions.TackerException): message = _("%(message)s")
class InvalidInput(BadRequest): message = _("Invalid input for operation: %(error_message)s.")
class VimKeyNotFoundException(exceptions.TackerException): message = _("Unable to find key file for VIM %(vim_id)s")
class VnfPolicyActionInvalid(BadRequest): message = _("Invalid action %(action)s for policy %(policy)s, " "should be one of %(valid_actions)s")
class DuplicateResourceName(TackerException): message = _("%(resource)s with name %(name)s already exists")
class VimEncryptKeyError(exceptions.TackerException): message = _("Barbican must be enabled for VIM %(vim_id)s")