nova中的service 访问数据库的过程

nova中的访问数据库的接口都在E:\nova\nova\db\api.py,但是该模块只是一个代理,只剩的实现是IMPL
IMPL的赋值如下:
_BACKEND_MAPPING = {'sqlalchemy': 'nova.db.sqlalchemy.api'}


IMPL = concurrency.TpoolDbapiWrapper(CONF, backend_mapping=_BACKEND_MAPPING)
可见nova是使用python的sqlalchemy
但是在nova中所有的服务是不能直接调用这个接口的,需要通过nova-conductor中转一次.
这里以E:\nova\nova\compute\manager.py 中的stop_instance为例,在这个函数中,操作数据库的代码如下:
            instance.power_state = self._get_power_state(context, instance)
            instance.vm_state = vm_states.STOPPED
            instance.task_state = None
            instance.save(expected_task_state=expected_task_state)
从这段code看更新isntance的power_state/vm_state/task_state 后调用 E:\nova\nova\objects\instance.py的save方法保存到数据库
@base.remotable
    def save(self, expected_vm_state=None,
             expected_task_state=None, admin_state_reset=False):
        """Save updates to this instance

        Column-wise updates will be made based on the result of
        self.what_changed(). If expected_task_state is provided,
        it will be checked against the in-database copy of the
        instance before updates are made.

        :param:context: Security context
        :param:expected_task_state: Optional tuple of valid task states
        for the instance to be in
        :param:expected_vm_state: Optional tuple of valid vm states
        for the instance to be in
        :param admin_state_reset: True if admin API is forcing setting
        of task_state/vm_state

        """
  
            db.instance_extra_update_by_uuid(context, self.uuid,
                                            self._extra_values_to_save)

    
看看这里的base.remotable的实现
首先是from nova.objects import base。
在E:\nova\nova\objects\base.py 中可以发现
remotable_classmethod = ovoo_base.remotable_classmethod
remotable = ovoo_base.remotable
原来remotable 是在ovoo_base.remotable 中实现的
def remotable(fn):
    """Decorator for remotable object methods."""
    @six.wraps(fn)
    def wrapper(self, *args, **kwargs):
        ctxt = self._context
        if ctxt is None:
            raise exception.OrphanedObjectError(method=fn.__name__,
                                                objtype=self.obj_name())
        if self.indirection_api:
            updates, result = self.indirection_api.object_action(
                ctxt, self, fn.__name__, args, kwargs)
            for key, value in six.iteritems(updates):
                if key in self.fields:
                    field = self.fields[key]
                    # NOTE(ndipanov): Since VersionedObjectSerializer will have
                    # deserialized any object fields into objects already,
                    # we do not try to deserialize them again here.
                    if isinstance(value, VersionedObject):
                        setattr(self, key, value)
                    else:
                        setattr(self, key,
                                field.from_primitive(self, key, value))
            self.obj_reset_changes()
            self._changed_fields = set(updates.get('obj_what_changed', []))
            return result
        else:
            return fn(self, *args, **kwargs)

    wrapper.remotable = True
    wrapper.original_fn = fn
    return wrappe
由于我们目前在compute 这个进程中,因此self.indirection_api不为null,则调用object_action
object_action是一个rpc调用,其定义在E:\nova\nova\conductor\rpcapi.py
    def object_action(self, context, objinst, objmethod, args, kwargs):
        cctxt = self.client.prepare()
        return cctxt.call(context, 'object_action', objinst=objinst,
                          objmethod=objmethod, args=args, kwargs=kwargs)
根据rpc调用原理实现在E:\nova\nova\conductor\manager.py 中
  def object_action(self, context, objinst, objmethod, args, kwargs):
        """Perform an action on an object."""
        oldobj = objinst.obj_clone()
        result = self._object_dispatch(objinst, objmethod, args, kwargs)
        return updates, result

首先调用obj_clone 来备份原来的对象,然后调用_object_dispatch。
这个方法通用定义在E:\nova\nova\conductor\manager.py 中
    def _object_dispatch(self, target, method, args, kwargs):
        """Dispatch a call to an object method.

        This ensures that object methods get called and any exception
        that is raised gets wrapped in an ExpectedException for forwarding
        back to the caller (without spamming the conductor logs).
        """
        try:
            # NOTE(danms): Keep the getattr inside the try block since
            # a missing method is really a client problem
            return getattr(target, method)(*args, **kwargs)
        except Exception:
            raise messaging.ExpectedException()
根据反射机制,调用方法名,这里的方法就是save,但是目前已经在conductor这个进程中,因此此时
base.remotable 中的self.indirection_api为null
这样回到 E:\nova\nova\objects\instance.py的save方法保存到数据库
@base.remotable
    def save(self, expected_vm_state=None,
             expected_task_state=None, admin_state_reset=False):
        """Save updates to this instance

        Column-wise updates will be made based on the result of
        self.what_changed(). If expected_task_state is provided,
        it will be checked against the in-database copy of the
        instance before updates are made.

        :param:context: Security context
        :param:expected_task_state: Optional tuple of valid task states
        for the instance to be in
        :param:expected_vm_state: Optional tuple of valid vm states
        for the instance to be in
        :param admin_state_reset: True if admin API is forcing setting
        of task_state/vm_state

        """
  
            db.instance_extra_update_by_uuid(context, self.uuid,
                                            self._extra_values_to_save)
这里的db赋值为from nova import db。这样就
nova中的访问数据库的接口都在E:\nova\nova\db\api.py,但是该模块只是一个代理,只剩的实现是IMPL
IMPL的赋值如下:
_BACKEND_MAPPING = {'sqlalchemy': 'nova.db.sqlalchemy.api'}


IMPL = concurrency.TpoolDbapiWrapper(CONF, backend_mapping=_BACKEND_MAPPING)
可见nova是使用python的sqlalchemy
但是在nova中所有的服务是不能直接调用这个接口的,需要通过nova-conductor中转一次.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值