ironic objects

ironic 的数据类型在ironic/objects包中,应该说是数据模型更合适,node,port,chassis,conductor,事实上,在hardware这一块上数据模型非常多, 大粒度上可以这么分,

然而很多模块不好归类,比如电源,内存,磁盘,风扇,扩展卡等等,我本来认为把这些模型加到node中去而不定义新的模型,这样node将会非常臃肿也不适合做数据的抽象,

期待ironic的改进。


数据模型定义了属性和一些方法(Port会在controller之后直接操作数据库,nodes会在controller中通过rpc到manager中去做一些东西,然后会通过nodes操作数据库)

controller中的module和数据模型一一对应,非常明确, 直接来看数据模型的父类ironic.objects.base.py中的IronicObject,,该类通过@six.add_metaclass(IronicObjectMetaclass) 添加了metaclass, 有一篇讲解metaclass的文章非常好,很经典

http://blog.jobbole.com/21351/

不仅是metaclass,也可以对python本身有更深的了解, 有几句话说的很好“在Python中,类也是对象,你可以动态的创建类。这就是当你使用关键字class时Python在幕后做的事情,而这就是通过元类来实现的”, “type就是Python在背后用来创建所有类的元类”, “Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来”,“元类就是创建类这种对象的东西”

type是python内建的元类,用来创建python中的类,我们也可以创建自己的元类,"Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类,如果没有找到,就会用内建的type来创建这个类",元类的作用就是拦截类的创建,修改类并返回修改后的类。

了解了元类之后来揣测一下IronicObjectMetaClass发挥了怎样的作用:

IronicObject的子类,例如Port,Node等创建的时候:

    def __init__(cls, names, bases, dict_):
        if not hasattr(cls, '_obj_classes'):
            # This will be set in the 'IronicObject' class.
            cls._obj_classes = collections.defaultdict(list)
        else:
            # Add the subclass to IronicObject._obj_classes
            make_class_properties(cls)
            cls._obj_classes[cls.obj_name()].append(cls)

在make_class_properties方法中,

def make_class_properties(cls):
    # NOTE(danms/comstud): Inherit fields from super classes.
    # mro() returns the current class first and returns 'object' last, so
    # those can be skipped.  Also be careful to not overwrite any fields
    # that already exist.  And make sure each cls has its own copy of
    # fields and that it is not sharing the dict with a super class.
    cls.fields = dict(cls.fields)      #拿到子类的fields,例如Port的id,uuid等等
    for supercls in cls.mro()[1:-1]:  #遍历父类
        if not hasattr(supercls, 'fields'):
            continue
        for name, field in supercls.fields.items():
            if name not in cls.fields:   #IronicObject也包含有fields,将父类fields中的created_at, updated_at加入子类的fields
                cls.fields[name] = field
    for name, typefn in cls.fields.iteritems():

        def getter(self, name=name):
            attrname = get_attrname(name)
            if not hasattr(self, attrname):
                self.obj_load_attr(name)  #报错, raise exception
            return getattr(self, attrname)

        def setter(self, value, name=name, typefn=typefn):
            self._changed_fields.add(name)  #记录被改变的attribute
            try:
                return setattr(self, get_attrname(name), typefn(value))
            except Exception:
                attr = "%s.%s" % (self.obj_name(), name)
                LOG.exception(_LE('Error setting %(attr)s'),
                              {'attr': attr})
                raise

        setattr(cls, name, property(getter, setter))   #给fields中的属性设置getter和setter方法,便于读取


IronicObjectSerializer 则在ironic中负责序列化和反序列化工作:

def serialize_entity(self, context, entity):
        if isinstance(entity, (tuple, list, set)):   #如果是普通的元组,list或者set就返回数据类型的实例,int就返回int(x)
            entity = self._process_iterable(context, self.serialize_entity,
                                            entity)
        elif (hasattr(entity, 'obj_to_primitive') and   #是IronicObject就调用IronicObject调用obj_to_promitive()方法
                callable(entity.obj_to_primitive)):
            entity = entity.obj_to_primitive()
        return entity

    def deserialize_entity(self, context, entity):
        if isinstance(entity, dict) and 'ironic_object.name' in entity:
            entity = IronicObject.obj_from_primitive(entity, context=context)
        elif isinstance(entity, (tuple, list, set)):
            entity = self._process_iterable(context, self.deserialize_entity,
                                            entity)
        return entity


remotable_classmethod和remotable两个方法目前在ironic中貌似没有使用,可能我没追出来还。。。



root@controller:/home/controller# cat /etc/nova/nova.conf [DEFAULT] log_dir = /var/log/nova lock_path = /var/lock/nova state_path = /var/lib/nova transport_url = rabbit://openstack:000000@controller:5672/ my_ip = 10.2.12.12 debug = True [api] auth_strategy = keystone [api_database] connection = mysql+pymysql://nova:ang@controller/nova_api [barbican] [barbican_service_user] [cache] [cinder] [compute] [conductor] [console] [consoleauth] [cors] [cyborg] [database] connection = mysql+pymysql://nova:ang@controller/nova [devices] [ephemeral_storage_encryption] [filter_scheduler] enabled_filters = RamFilter, DiskFilter, ComputeFilter scheduler_default_filters = AllHostsFilter [glance] api_servers = http://controller:9292 [guestfs] [healthcheck] [image_cache] [ironic] [key_manager] [keystone] [keystone_authtoken] www_authenticate_uri = http://controller:5000/ auth_url = http://controller:5000/ memcached_servers = controller:11211 auth_type = password project_domain_name = Default user_domain_name = Default project_name = service username = nova password = nova [libvirt] [manila] [metrics] [mks] [neutron] auth_url = http://controller:5000 auth_type = password project_domain_name = Default user_domain_name = Default region_name = RegionOne project_name = service username = neutron password = neutron service_metadata_proxy = true metadata_proxy_shared_secret = ang [notifications] [os_brick] [os_vif_linux_bridge] [os_vif_ovs] [oslo_concurrency] lock_path = /var/lib/nova/tmp [oslo_limit] [oslo_messaging_kafka] [oslo_messaging_notifications] [oslo_messaging_rabbit] [oslo_middleware] [oslo_policy] [oslo_reports] [oslo_versionedobjects] [pci] [placement] region_name = RegionOne project_domain_name = Default project_name = service auth_type = password user_domain_name = Default auth_url = http://controller:5000/v3 username = placement password = placement [privsep] [profiler] [profiler_jaeger] [profiler_otlp] [quota] [remote_debug] [scheduler] [serial_console] [service_user] send_service_user_token = true auth_url = http://controller:5000/v3 auth_strategy = keystone auth_type = password project_domain_name = Default project_name = service user_domain_name = Default username = nova password = nova [spice] [upgrade_levels] [vault] [vendordata_dynamic_auth] [vmware] [vnc] enabled = true server_listen = $my_ip server_proxyclient_address = $my_ip [workarounds] [wsgi] [zvm] [cells] enable = False [os_region_name] openstack = root@controller:/home/controller# 消息 MessagingTimeout 编码 500 详情 Traceback (most recent call last): File "/usr/lib/python3/dist-packages/nova/conductor/manager.py", line 1654, in schedule_and_build_instances host_lists = self._schedule_instances(context, request_specs[0], instance_uuids, return_alternates=True) File "/usr/lib/python3/dist-packages/nova/conductor/manager.py", line 942, in _schedule_instances host_lists = self.query_client.select_destinations( context, request_spec, instance_uuids, return_objects=True, return_alternates=return_alternates) File "/usr/lib/python3/dist-packages/nova/scheduler/client/query.py", line 41, in select_destinations return self.scheduler_rpcapi.select_destinations(context, spec_obj, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ instance_uuids, return_objects, return_alternates) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/nova/scheduler/rpcapi.py", line 160, in select_destinations return cctxt.call(ctxt, 'select_destinations', **msg_args) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/oslo_messaging/rpc/client.py", line 190, in call result = self.transport._send( self.target, msg_ctxt, msg, wait_for_reply=True, timeout=timeout, call_monitor_timeout=cm_timeout, retry=self.retry, transport_options=self.transport_options) File "/usr/lib/python3/dist-packages/oslo_messaging/transport.py", line 123, in _send return self._driver.send(target, ctxt, message, ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ wait_for_reply=wait_for_reply, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<2 lines>... retry=retry, ^^^^^^^^^^^^ transport_options=transport_options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 800, in send return self._send(target, ctxt, message, wait_for_reply, timeout, ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call_monitor_timeout, retry=retry, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ transport_options=transport_options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 789, in _send result = self._waiter.wait(msg_id, timeout, call_monitor_timeout, reply_q) File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 654, in wait message = self.waiters.get(msg_id, timeout=timeout) File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 520, in get raise oslo_messaging.MessagingTimeout( 'Timed out waiting for a reply ' 'to message ID %s' % msg_id) oslo_messaging.exceptions.MessagingTimeout: Timed out waiting for a reply to message ID 063b124ada814cc69904385371b6d6fb我已经配置了这个但是为什么还是会报错,如何详细的查看资源
09-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值