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

来源:互联网 发布:linux运维属于哪个行业 编辑:程序博客网 时间:2024/06/06 00:51
nova中的访问数据库的接口都在E:\nova\nova\db\api.py,但是该模块只是一个代理,只剩的实现是IMPLIMPL的赋值如下:_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_classmethodremotable = 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_actionobject_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,但是该模块只是一个代理,只剩的实现是IMPLIMPL的赋值如下:_BACKEND_MAPPING = {'sqlalchemy': 'nova.db.sqlalchemy.api'}IMPL = concurrency.TpoolDbapiWrapper(CONF, backend_mapping=_BACKEND_MAPPING)可见nova是使用python的sqlalchemy但是在nova中所有的服务是不能直接调用这个接口的,需要通过nova-conductor中转一次.