what happened while start nova compute service

来源:互联网 发布:怎样进入上层社会 知乎 编辑:程序博客网 时间:2024/06/05 21:12

前面已经对nova创建instance和其他操作讲了不少,回到detail上,

在nova中,api,conductor,scheduler,compute都有对应的manager,在cmd包中启动各种service时,除了api是WSGI service,其他的都是Service,

更直接一点儿的话启动的是RPC的service,但这些服务中,compute的地位是不一样的,特别是启动时,做了很多工作,下面从细节上trace一下看看。

至于启动rpc service时候rpc server对应的target是什么,收到message处理的逻辑是什么,之前都讲过,主要看三个动作:

1. self.manager.init_host()

2. self.manager.pre_start_hook()

3. self.manager.post_start_hook()

对nova-compute来说这里manage自然是compute-manager,先看init_host:

        self.driver.init_host(host=self.host)

#self.driver默认情况为libvirt.LibvirtDriver,因此执行libvirt driver的init_host方法,其他的driver也需要执行对应的init_host, 传入的参数

host=self.host,host从nova.netconf中读出,在compute node则是读取配置文件中的host,而driver的init_host又执行了一大串动作:

initialize:注册driver的error handler,并将libvirt产生的event进行dispatch并处理,即不同的event对应不同的处理方式,比如连接失败之类的

_do_quality_warnings:连接libvirt driver得到cpu feature,分析cpu架构,若配置的virt type不是qemu或者kvm,或者cpu 的arch不是“arch.I686, arch.X86_64”,

给出警告的log

接下来对不同的virt type做不同的处理,若是lxc则判断容器是否有user/group 的namespace,若不是kvm则不进行kvm 加速,检查libvirt version的版本,不能

过低等。


        context = nova.context.get_admin_context()

#得到admin的context,user/project都是null,要的是admin context去objects里面做一些数据库的查询

        instances = objects.InstanceList.get_by_host(
            context, self.host, expected_attrs=['info_cache'])

#得到host中包含的instance list,如果是boot from image,只有临时数据,临时数据之类的都会存在coompute node上,boot from volume则存在volume所在处,

其临时数据?

        if CONF.defer_iptables_apply:
            self.driver.filter_defer_apply_on()

#执行firewall driver的filter_defer_apply_on, 对LibVirtDriver来说,默认的是IptablesFirewallDriver, 最终执行:

self.iptables.defer_apply_on(), self.iptables=linux_net.iptables_manager

只是将iptables_apply_deferred置为True,置为True之后,推迟使用当前iptable rule(当L3 driver使用linux_net作为backend时候,会调到

linux_net.metadata_forward(),应用防火墙规则,若这里defer了的话,就暂时不apply了)


        self.init_virt_events()
#若配置CONF.workarounds.handle_virt_lifecycle_events, 注册对virt driver的event listener

        try:
            # checking that instance was not already evacuated to other host
            self._destroy_evacuated_instances(context)

#这一段逻辑比较绕,先获得本机现有的所有instance(virt driver在本机获得),然后判断每个instance现在的host还是否是当前的host,如果不是,

但是instance的task state属于迁移/resize相关的状态,则不删除该instance; 如果设置CONF.workarounds.destroy_after_evacuate是False,警告,修改为True

之后重启方可;否则获得instance的网络/block device/共享存储,之后删除该instance

            for instance in instances:
                self._init_instance(context, instance)

#初始化所有的instance,这个判断的种类非常多, 很多种情况,针对不对情况,初始化虚机。

        finally:
            if CONF.defer_iptables_apply:
                self.driver.filter_defer_apply_off()
            self._update_scheduler_instance_info(context, instances)

#最后,应用iptables,并执行nova.scheduler.client.query.SchedulerQueryClient.update_instance_info,即通过scheduler去update instance(

对应HostManager中的_instance_info)信息



再来看看pre_start_hook:

只有一句:self.update_available_resource(nova.context.get_admin_context()),注意到这个方法是period_task,

想起ironic里面的period_task:@periodic_task.periodic_task(spacing=CONF.update_resources_interval)

compute_nodes_in_db = self._get_compute_nodes_in_db(context, use_slave=True)

#首先根据self.host拿到host中的所有compute_node(可能使用虚机做hypervisor?不然一个host如何多个compute node?),

nodenames = set(self.driver.get_available_nodes())

#拿到hypervisor对应的host name,然后根据host,driver,hostname对每个node得到一个resource tracker:

rt = self._get_resource_tracker(nodename)
rt.update_available_resource(context)

在resource tracker中,根据前面传入的driver,获得实际available resource(使用libvirt拿到一系列的值),这些数据包括vcpu,memory,local_gb,

vcpu_used等等,使用log记录(report),最重要的是执行_update_available_resource(注意前面有下划线),这里的最重要的步骤是:

_init_compute_node:

#如果compute不存在数据库中,就创建它,所以如果新加入的节点,经过一段时间或者重启nova-compute之后会自检测出来

主要更新的信息包括:

self.stats = importutils.import_object(CONF.compute_stats_class)
self.tracked_instances = {}
self.tracked_migrations = {}


最后看post_start_hook:

不是所有的manager都实现了,cellmanager实现了一些功能


0 0
原创粉丝点击