zoukankan      html  css  js  c++  java
  • oslo_config中的DuplicateOptError坑

    前言:

    最近在重写公司的Cinder Driver,我们driver是按照OpenStack的要求,依赖一个叫oslo_config的一个包。这个包的作用就是让driver申明所依赖的选项(可以来自文件,也可以来自命令行),oslo_config负责读取文件,并加载。

    具体的使用可以参考:

    http://www.giantflyingsaucer.com/blog/?p=4822

    或者:

    http://docs.openstack.org/developer/oslo.config/cfg.html

    安装oslo_config: 

    sudo pip install oslo_config

    问题:

    重写是把新的代码放到与原来代码的文件和目录里面,所以在一段时间内是,两份代码都会在Cinder的目录里面。新的driver所有option是不变的,于是我把原来的代码拷贝过来,然后小改了下,注意这里的小改,后面会debug我一天的时间!!!

    首先,重构前的代码是这样的:

     cfg.StrOpt('storage_vnx_pool_names',
                 deprecated_name='storage_vnx_pool_name',
                 help='Comma-separated list of storage pool names to be used.'),

    改动的地方是把“to be used”去掉,其实保持不变,因为我觉得比较冗余...

    改成了

     cfg.StrOpt('storage_vnx_pool_names',
                    deprecated_name='storage_vnx_pool_name',
                    help='Comma-separated list of storage pool names.'),

    然后我的悲剧就开始了:

    跑UT的时候 一直报:

    oslo_config.cfg.DuplicateOptError: duplicate option: storage_vnx_pool_names

    问题分析:

    经过不断的分析,发现oslo_config是重写了 __eq__和__ne__来判断两个选项是否一样,如下:

    # oslo_config/cfg.py
    
    def _is_opt_registered(opts, opt):
        """Check whether an opt with the same name is already registered.
    
        The same opt may be registered multiple times, with only the first
        registration having any effect. However, it is an error to attempt
        to register a different opt with the same name.
    
        :param opts: the set of opts already registered
        :param opt: the opt to be registered
        :returns: True if the opt was previously registered, False otherwise
        :raises: DuplicateOptError if a naming conflict is detected
        """
        if opt.dest in opts:
            if opts[opt.dest]['opt'] != opt:
                raise DuplicateOptError(opt.name)
            return True
        else:
            return False

    红色就是抛出这个ERROR的地方

    # oslo_config/cfg.py
    
    class Opt(object):
    ...
      def __ne__(self, another):
           return vars(self) != vars(another)
      def __eq__(self, another):
        
    return vars(self) == vars(another)


    我写了一个测试(代码在github 上)vars是如何进行比较的,dump下的数据如下:

    (Pdb) print vars(self)
    {'deprecated_for_removal': False, 'short': None, 'name': 'enable', 'dest': 'enable', 'required': False, '_logged_deprecation': False, 'sample_default': None, 'deprecated_opts': [], 'positional': False, 'default': False, 'secret': False, 'deprecated_reason': None, 'mutable': False, 'type': Boolean, 'metavar': None, 'help': 'True enables, False disables'}
    (Pdb) print vars(another)
    {'deprecated_for_removal': False, 'short': None, 'name': 'enable', 'dest': 'enable', 'required': False, '_logged_deprecation': False, 'sample_default': None, 'deprecated_opts': [], 'positional': False, 'default': False, 'secret': False, 'deprecated_reason': None, 'mutable': False, 'type': Boolean, 'metavar': None, 'help': 'True enables, False disables.'}

    注意红色的东西,下面的少了一个句号,于是会返回不相等. 我就是因为改了help里面的东西,所以oslo_config直接认为我在两个不同的option使用了同一个名字.

    现在抛出这个错误的原因也很明确了,把两个地方的cfg.StrOpt改成完全一样的就可以了。

    参考资料:

    http://docs.openstack.org/developer/oslo.config/cfg.html

    http://www.giantflyingsaucer.com/blog/?p=4822

  • 相关阅读:
    PPP协议 PAP认证
    交换机广播风暴,STP生成树协议,端口聚合
    传统远程注入线程,加载DLL
    EXE和DLL调用关系,DLL制作,钩子
    window bat批处理 实用脚本
    python利用scapy嗅探流量
    关于AWD线下攻防的经验
    APP 仿微信登录
    价值1500左右的毕业设计都开源啦
    EOS2.0环境搭建-centos7
  • 原文地址:https://www.cnblogs.com/sting2me/p/5307512.html
Copyright © 2011-2022 走看看