首页 > 其他分享 >Create port ip分配流程梳理

Create port ip分配流程梳理

时间:2023-02-17 11:14:25浏览次数:36  
标签:subnet ip Create port self ips id

Create port ip分配流程梳理

  1. self.ipam.allocate_ips_for_port_and_store( context, port, port_id)

  2. #/usr/lib/python2.7/site-packages/neutron/db/ipam_pluggable_backend.py
    def allocate_ips_for_port_and_store(self, context, port, port_id):
            # Make a copy of port dict to prevent changing
            # incoming dict by adding 'id' to it.
            # Deepcopy doesn't work correctly in this case, because copy of
            # ATTR_NOT_SPECIFIED object happens. Address of copied object doesn't
            # match original object, so 'is' check fails
            port_copy = {'port': port['port'].copy()}
            port_copy['port']['id'] = port_id
            network_id = port_copy['port']['network_id']
            ips = []
            try:
                #tip 1
                ips = self._allocate_ips_for_port(context, port_copy)
                # ips:[{'subnet_id': u'3dc7c748-99ac-471f-bfb6-fcebbee4d223', 'ip_address': '192.168.193.2'}]
                # ips has been allocated by self._allocate_ips_for_port(context, port_copy)
                for ip in ips:
                    ip_address = ip['ip_address']
                    subnet_id = ip['subnet_id']
                    IpamPluggableBackend._store_ip_allocation(
                        context, ip_address, network_id,
                        subnet_id, port_id)
                return ips
            except Exception:
                with excutils.save_and_reraise_exception():
                    if ips:
                        ipam_driver = driver.Pool.get_instance(None, context)
                        if not ipam_driver.needs_rollback():
                            return
    
                        LOG.debug("An exception occurred during port creation. "
                                  "Reverting IP allocation")
                        self._safe_rollback(self._ipam_deallocate_ips, context,
                                            ipam_driver, port_copy['port'], ips,
                                            revert_on_fail=False)
    
  3. _allocate_ips_for_port()

  4.     def _allocate_ips_for_port(self, context, port):
            """Allocate IP addresses for the port. IPAM version.
    
            If port['fixed_ips'] is set to 'ATTR_NOT_SPECIFIED', allocate IP
            addresses for the port. If port['fixed_ips'] contains an IP address or
            a subnet_id then allocate an IP address accordingly.
            """
            p = port['port']
            fixed_configured = p['fixed_ips'] is not constants.ATTR_NOT_SPECIFIED
         	#NOTE(zcc):get all eligible subnets   
            subnets = self._ipam_get_subnets(context,
                                             network_id=p['network_id'],
                                             host=p.get(portbindings.HOST_ID),
                                             service_type=p.get('device_owner'),
                                             fixed_configured=fixed_configured)
            #NOTE(zcc):classify subnets by ip-version
            v4, v6_stateful, v6_stateless = self._classify_subnets(
                context, subnets)
            if fixed_configured:
            #TODO(zcc):if the fixed_ips:
                ips = self._test_fixed_ips_for_port(context,
                                                    p["network_id"],
                                                    p['fixed_ips'],
                                                    p['device_owner'],
                                                    subnets)
            else:
                ips = []
                version_subnets = [v4, v6_stateful]
                for subnets in version_subnets:
                    if subnets:
                        ips.append([{'subnet_id': s['id']}
                                    for s in subnets])
    		# ips: [[{'subnet_id': u'3dc7c748-99ac-471f-bfb6-fcebbee4d223'}, {'subnet_id': u'00316985-d755-4df0-a301-90b925764ec9'}]]
            ips.extend(self._get_auto_address_ips(v6_stateless, p))
            ipam_driver = driver.Pool.get_instance(None, context)
            return self._ipam_allocate_ips(context, ipam_driver, p, ips)
    
  5. ._ipam_allocate_ips(context, ipam_driver, p, ips)

  6. def _ipam_allocate_ips(self, context, ipam_driver, port, ips,
                               revert_on_fail=True):
            """Allocate set of ips over IPAM.
    
            If any single ip allocation fails, tries to deallocate all
            allocated ip addresses.
            """
            allocated = []
            # we need to start with entries that asked for a specific IP in case
            # those IPs happen to be next in the line for allocation for ones that
            # didn't ask for a specific IP
            #NOTE(zcc):sorted by subnet-id
            ips.sort(key=lambda x: 'ip_address' not in x)
            try:
                for ip in ips:
                    # By default IP info is dict, used to allocate single ip
                    # from single subnet.
                    # IP info can be list, used to allocate single ip from
                    # multiple subnets
                    ip_list = [ip] if isinstance(ip, dict) else ip
                    #'ip_list:', [{'subnet_id': u'3dc7c748-99ac-471f-bfb6-fcebbee4d223'}, {'subnet_id': u'00316985-d755-4df0-a301-90b925764ec9'}]
                    subnets = [ip_dict['subnet_id'] for ip_dict in ip_list]
                    try:
                        factory = ipam_driver.get_address_request_factory()
                        #NOTE(zcc):judage ip type with port and ip_list[0]
                        ip_request = factory.get_request(context, port, ip_list[0])
                        #NOTE(zcc): /usr/lib/python2.7/site-packages/neutron/ipam/subnet_alloc.py def get_allocator(self, subnet_ids): return IpamSubnetGroup(self, subnet_ids)
                        ipam_allocator = ipam_driver.get_allocator(subnets)
                        ip_address, subnet_id = ipam_allocator.allocate(ip_request)
                        #(ip_address:'192.168.191.3', subnet_id: '00316985-d755-4df0-a301-90b925764ec9')
                    except ipam_exc.IpAddressGenerationFailureAllSubnets:
                        raise n_exc.IpAddressGenerationFailure(
                            net_id=port['network_id'])
    
                    allocated.append({'ip_address': ip_address,
                                      'subnet_id': subnet_id})
            except Exception:
                with excutils.save_and_reraise_exception():
                    if not ipam_driver.needs_rollback():
                        return
    
                    LOG.debug("An exception occurred during IP allocation.")
    
                    if revert_on_fail and allocated:
                        LOG.debug("Reverting allocation")
                        # In case of deadlock deallocation fails with db error
                        # and rewrites original exception preventing db_retry
                        # wrappers from restarting entire api request.
                        self._safe_rollback(self._ipam_deallocate_ips, context,
                                            ipam_driver, port, allocated,
                                            revert_on_fail=False)
                    elif not revert_on_fail and ips:
                        addresses = ', '.join(self._get_failed_ips(ips,
                                                                   allocated))
                        LOG.error("IP allocation failed on "
                                  "external system for %s", addresses)
    
            return allocated
    
  7. IpamsubnetGroup(driver.SubnetGroup)

  8. #/usr/lib/python2.7/site-packages/neutron/ipam/subnet_alloc.py
    class IpamSubnetGroup(driver.SubnetGroup):
        def __init__(self, driver, subnet_ids):
            self._driver = driver
            self._subnet_ids = subnet_ids
    
        def allocate(self, address_request):
            '''Originally, the Neutron pluggable IPAM backend would ask the driver
               to try to allocate an IP from each subnet in turn, one by one.  This
               implementation preserves that behavior so that existing drivers work
               as they did before while giving them the opportunity to optimize it
               by overridding the implementation.
            '''
            for subnet_id in self._subnet_ids:
                try:
                    #NOTE(zcc):judage this subnet has avaliable ips, if has ,return
                    ipam_subnet = self._driver.get_subnet(subnet_id)
                    return ipam_subnet.allocate(address_request), subnet_id
                except ipam_exc.IpAddressGenerationFailure:
                    continue
            raise ipam_exc.IpAddressGenerationFailureAllSubnets()
    
  9. ipam_subnet.allocate(address_request)

  10.     #/usr/lib/python2.7/site-packages/neutron/ipam/drivers/neutrondb_ipam/driver.py
        def allocate(self, address_request):
            # NOTE(pbondar): Ipam driver is always called in context of already
            # running transaction, which is started on create_port or upper level.
            # To be able to do rollback/retry actions correctly ipam driver
            # should not create new nested transaction blocks.
            all_pool_id = None
            # NOTE(salv-orlando): It would probably better to have a simpler
            # model for address requests and just check whether there is a
            # specific IP address specified in address_request
            if isinstance(address_request, ipam_req.SpecificAddressRequest):
                # This handles both specific and automatic address requests
                # Check availability of requested IP
                ip_address = str(address_request.address)
                self._verify_ip(self._context, ip_address)
            else:  
                prefer_next = isinstance(address_request,
                                         ipam_req.PreferNextAddressRequest)
                # prefer_next: False
                # NOTE(jetlee): Now, we use tooz to resolve the collision
                # of allocate ip address
                # do else
                if cfg.CONF.tooz.enabled and cfg.CONF.tooz.ip_lock and \
                        self._context.external_net_flag:
                    LOG.debug("before generate ip by tooz lock.")
                    self._context.lock_dict = {}
                    ip_address, all_pool_id, used_ip = \
                        self._generate_ip_by_tooz_lock(self._context,
                                                       prefer_next)
                    LOG.debug("Those ip %s was ocupied by other process.",
                              used_ip)
                else:
                    #generate ip_address
                    ip_address, all_pool_id = self._generate_ip(self._context,
                                                                prefer_next)
    
            # Create IP allocation request object
            # The only defined status at this stage is 'ALLOCATED'.
            # More states will be available in the future - e.g.: RECYCLABLE
            try:
                # TODO(ataraday): revisit this after objects switched to
                # new enginefacade
                with self._context.session.begin(subtransactions=True):
                    # NOTE(kevinbenton): we use a subtransaction to force
                    # a flush here so we can capture DBReferenceErrors due
                    # to concurrent subnet deletions. (galera would deadlock
                    # later on final commit)
                    self.subnet_manager.create_allocation(self._context,
                                                          ip_address)
            except db_exc.DBReferenceError:
                raise n_exc.SubnetNotFound(
                    subnet_id=self.subnet_manager.neutron_id)
            return ip_address
    
  11. _generate_ip()

  12.     #/usr/lib/python2.7/site-packages/neutron/ipam/drivers/neutrondb_ipam/driver.py
        def _generate_ip(self, context, prefer_next=False):
            """Generate an IP address from the set of available addresses."""
            ip_allocations = netaddr.IPSet()
            #get all used ip under this subnet
            for ipallocation in self.subnet_manager.list_allocations(context):
                ip_allocations.add(ipallocation.ip_address)
            #get all ips between first_ip and last_ip
            for ip_pool in self.subnet_manager.list_pools(context):
                ip_set = netaddr.IPSet()
                ip_set.add(netaddr.IPRange(ip_pool.first_ip, ip_pool.last_ip))
                #get avaliable ips
                av_set = ip_set.difference(ip_allocations)
                if av_set.size == 0:
                    continue
    
                if prefer_next:
                    window = 1
                else:
                    # Compute a value for the selection window
                    window = min(av_set.size, 30)
                ip_index = random.randint(1, window)
                #get candidate_ips
                candidate_ips = list(itertools.islice(av_set, ip_index))
                #get random ip from candidate_ips
                allocated_ip = candidate_ips[
                    random.randint(0, len(candidate_ips) - 1)]
    
                return str(allocated_ip), ip_pool.id
    
            raise ipam_exc.IpAddressGenerationFailure(
                      subnet_id=self.subnet_manager.neutron_id)
    
  13. 流程图梳理

标签:subnet,ip,Create,port,self,ips,id
From: https://www.cnblogs.com/fazzer/p/17129384.html

相关文章

  • typescript 声明、获取dom元素
    获取已有的dom元素constarrows=document.querySelectorAll('.arrows');获取DOM数组,比如有时候只有在请求数据后界面才渲染,我是在vue里面需要处理一些罗里吧嗦的功能......
  • [javascript]端序(endian)和Buffer对象的read|write系列函数
    假设有如下对象:varbuf=Buffer.from("Hello.\n");其保存在内存当中的形式实际上是这样的,这里我们假设该对象的内存地址从0x00开始:地址0x000x010x020x030x04......
  • 2023前端开发最新面试题收集-Javascript篇
    前台、中台、后台-前台:面向用户、客户可以感知的,如商城-中台:可以看着对前台的补充,公共服务功能,如支付系统、搜索系统、客服-后台:面向运营、比如商品管理、物流管理1......
  • pytest + yaml 框架 -20.支持全局代理proxies_ip的配置
    前言在实际的工作中,有些系统的接口我们无法直接访问,需使用代理去访问,那么就需要在整个项目的用例中配置一个全局代理ip环境准备环境要求Python大于等于3.8版本,(低于pyt......
  • Vue3+vite项目在局域网内通过ip在手机端访问
    使用vite启动项目后,想在手机端访问项目,此时是访问不到的在网上查阅了相关内容,小结一下1.修改vite.confifg,js(未使用ts,使用的修改vite,config.ts)exportdefaultdefineCo......
  • got multiple values for keyword argument 'to_fields'
    django.db.models.fields.related.ForeignObject.__init__()gotmultiplevaluesforkeywordargument'to_fields'原因:使用了to_fields说明:使用外键关联字段时,应该使......
  • python zipfile 排除指定文件类型后的文件夹压缩
    """压缩指定文件夹排除指定格式的文件"""importzipfilefrompathlibimportPathpath='./aaa.zip'#压缩文件路径path=Path(path)xya_file=Path('./te......
  • ChIP-seq 分析:Mapped 数据可视化(4)
    1.Mappedreads现在我们有了BAM文件的索引,我们可以使用idxstatsBam()函数检索和绘制映射读取的数量。mappedReads<-idxstatsBam("SR_Myc_Mel_rep1.bam")TotalMap......
  • 如何在 Debian 11 上设置一个静态 IP 地址
    当你在电脑上安装一个新的操作系统时,DHCP服务器会给你分配一个动态IP地址。然而,在各种情况下,你可能需要在你的机器上设置一个静态IP地址,例如,当你正在托管一个网络服务器,......
  • 78JavaScript基础
    JavaScript操作DOM节点包括:JavaScript处理事件、操作节点、操作节点样式#demo.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><me......