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

本文解析了OpenStack Nova组件中数据库操作的具体流程,包括如何通过nova-conductor进行中转调用,以及remotable装饰器的作用机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中转一次.

<think>嗯,用户遇到了OpenStack的nova-scheduler服务启动失败的问题,需要帮忙解决。首先,我应该回忆一下常见的服务启动失败的原因。通常,日志文件是第一步需要检查的,因为里面会有具体的错误信息。根据引用[1]里的例子,用户之前遇到nova-compute服务失败时,可能也是通过查看日志找到原因的。所以,我应该建议用户查看systemd的日志或者nova-scheduler的专用日志文件。 然后,配置文件的问题也很常见。比如,nova.conf中的数据库连接、消息队列设置是否有误,权限是否正确。用户可能配置了错误的RabbitMQ或者MySQL信息,导致服务无法启动。还要注意权限问题,比如SELinux或AppArmor可能会阻止服务访问某些资源,引用[1]中提到过类似的失败情况,可能需要检查这些安全设置。 另外,依赖服务是否正常运行也很重要。比如,数据库服务、消息队列(如RabbitMQ)是否可用。如果数据库连接不上,nova-scheduler自然启动不了。用户可能需要验证这些服务的状态,并确保端口开放,没有防火墙阻挡。 还有资源不足的情况,比如内存或磁盘空间不足。虽然可能性较低,但也不能排除。查看系统资源使用情况,使用top或df命令检查。 软件包版本冲突也可能导致问题,特别是如果用户最近升级了OpenStack或其他相关组件,可能存在依赖不兼容的情况。需要确认所有软件包版本是否兼容,并尝试重新安装或更新。 最后,如果以上步骤都没解决问题,可能需要更深入的调试,比如在手动启动时开启详细日志,或者查看堆栈跟踪。用户提供的引用中提到了CLI命令的使用,比如引用[4]中的创建负载均衡器,可能类似的CLI命令可以用来测试其他服务是否正常。 总结下来,解决步骤应该是:检查日志→验证配置文件→检查依赖服务→查看系统资源→检查软件包→安全设置→手动调试。需要逐步排查,每个步骤都可能有不同的解决方案。</think>### OpenStack Nova Scheduler服务启动失败排查步骤 --- #### 1. **检查日志定位具体错误** - **查看systemd日志**: ```bash journalctl -u openstack-nova-scheduler.service --since "10 minutes ago" -xe ``` 日志可能显示数据库连接失败、权限错误或依赖服务不可用等问题[^1]。 - **查看Nova专用日志**: ```bash tail -f /var/log/nova/nova-scheduler.log ``` 若日志中提示`AMQP server connection error`,可能是RabbitMQ配置错误[^1]。 --- #### 2. **验证配置文件** - **检查`/etc/nova/nova.conf`**: - 确认数据库连接参数(`[database]`节): ```ini connection = mysql+pymysql://nova:密码@控制节点IP/nova ``` - 检查消息队列配置(`[DEFAULT]`节): ```ini transport_url = rabbit://openstack:密码@控制节点IP:5672/ ``` - 确保`[scheduler]`节无语法错误。 - **权限验证**: ```bash ls -l /etc/nova/nova.conf chmod 640 /etc/nova/nova.conf # 若权限异常 ``` --- #### 3. **检查依赖服务状态** - **数据库服务**: ```bash systemctl status mysql # 或MariaDB mysql -u nova -p -h 控制节点IP # 测试连接 ``` - **消息队列服务**: ```bash systemctl status rabbitmq-server rabbitmqctl list_users # 验证用户是否存在 ``` --- #### 4. **资源与系统限制** - **检查内存/磁盘**: ```bash free -h # 内存使用 df -h /var # 磁盘空间 ``` - **关闭SELinux/AppArmor**(临时测试): ```bash setenforce 0 # SELinux systemctl stop apparmor # AppArmor ``` --- #### 5. **重装或更新软件包** 若日志提示Python依赖冲突: ```bash apt-get install --reinstall nova-scheduler # Ubuntu/Debian yum reinstall openstack-nova-scheduler # CentOS/RHEL ``` --- #### 6. **手动调试服务** 尝试直接运行进程: ```bash nova-scheduler --config-file=/etc/nova/nova.conf ``` 观察终端输出的错误堆栈。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值