openstack:nova中的幾個問題分析

 1,nova中的兩條命令執行過程分析:

nova service-list

+------------------+--------------+----------+---------+-------+----------------------------+-----------------+
| Binary           | Host         | Zone     | Status  | State | Updated_at                 | Disabled Reason |
+------------------+--------------+----------+---------+-------+----------------------------+-----------------+
| nova-scheduler   | openstack2  | internal | enabled | up    | 2014-02-12T02:17:31.000000 | None            |
| nova-conductor   | openstack2  | internal | enabled | up    | 2014-02-12T02:17:32.000000 | None            |
| nova-cert        | openstack2  | internal | enabled | up    | 2014-02-12T02:17:31.000000 | None            |
| nova-consoleauth | openstack2  | internal | enabled | up    | 2014-02-12T02:17:31.000000 | None            |
| nova-compute     | openstack2  | nova     | enabled | up    | 2014-02-12T02:17:33.000000 | None            |
| nova-network     | openstack2  | internal | enabled | up    | 2014-02-12T02:17:29.000000 | None            |
| nova-compute     | openstack-1 | nova     | enabled | up    | 2014-02-12T02:17:27.000000 | None            |
| nova-network     | openstack-1 | internal | enabled | up    | 2014-02-12T02:17:32.000000 | None            |
+------------------+--------------+----------+---------+-------+----------------------------+-----------------+

nova host-list

+--------------+-------------+----------+
| host_name    | service     | zone     |
+--------------+-------------+----------+
| openstack2  | scheduler   | internal |
| openstack2  | conductor   | internal |
| openstack2  | cert        | internal |
| openstack2  | consoleauth | internal |
| openstack2  | compute     | nova     |
| openstack2  | network     | internal |
| openstack-1 | compute     | nova     |
| openstack-1 | network     | internal |
+--------------+-------------+----------+

那麼controller節點怎麼知道各個node的狀態呢?Controller怎麼知道各個node中運行的服務呢?

在nova-api服務中有以下介個REST-API:
Host-controller中提供了一下幾種方法:
class HostController(object):
    def __init__(self):
        self.api = compute.HostAPI()
        super(HostController, self).__init__()
 
    @wsgi.serializers(xml=HostIndexTemplate)
    def index(self, req):
        services = self.api.service_get_all(context, filters=filters,
                                            set_zones=True)
        for service in services:
            hosts.append({'host_name': service['host'],
                          'service': service['topic'],
                          'zone': service['availability_zone']})
        return {'hosts': hosts}
 
    @wsgi.serializers(xml=HostShowTemplate)
    def show(self, req, id):
        context = req.environ['nova.context']
        host_name = id
        try:
            service = self.api.service_get_by_compute_host(context, host_name)
 
    def update(self, req, id, body):
        return result
 
service-controller中提供了一下幾種方法
class ServiceController(object):
 
    def __init__(self, ext_mgr=None, *args, **kwargs):
        self.host_api = compute.HostAPI()
        self.servicegroup_api = servicegroup.API()
        self.ext_mgr = ext_mgr
 
    def _get_services(self, req):
        services = self.host_api.service_get_all(
            context, set_zones=True)
 
    def index(self, req):
        detailed = self.ext_mgr.is_loaded('os-extended-services')
        services = self._get_services_list(req, detailed)
        return {'services': services}
 
    @wsgi.deserializers(xml=ServiceUpdateDeserializer)
    @wsgi.serializers(xml=ServiceUpdateTemplate)
    def update(self, req, id, body):
       try:
            self.host_api.service_update(context, host, binary, status_detail)
        return ret_value
#從這裏可以看出,對於host和service的查詢和更新操作調用了hostAPI中的一些方法
#查看service_get_all和compute_node_get
    def service_get_all(self, context, filters=None, set_zones=False):
        services = service_obj.ServiceList.get_all(context, disabled,
                                                   set_zones=set_zones)
        return ret_services
 
    def compute_node_get(self, context, compute_id):
        return self.db.compute_node_get(context, int(compute_id))
可以看出,都是通過調用數據庫實現的;
 
注,service數據表中包含了主機host的信息

那麼service和host的數據是何時創建的呢?

首先看各個服務service啓動的時候,都做了什麼?

def main():
    config.parse_args(sys.argv)
    logging.setup("nova")
    utils.monkey_patch()
    server = service.Service.create(binary='nova-scheduler',
                                    topic=CONF.scheduler_topic)
    service.serve(server)
service.wait()
 
class Service(service.Service):
    def __init__(self, host, binary, topic, manager, report_interval=None,
                 periodic_enable=None, periodic_fuzzy_delay=None,
                 periodic_interval_max=None, db_allowed=True,
                 *args, **kwargs):
        super(Service, self).__init__()
        self.host = host
        self.binary = binary
        self.topic = topic
        self.manager_class_name = manager
        self.servicegroup_api = servicegroup.API(db_allowed=db_allowed)
        manager_class = importutils.import_class(self.manager_class_name)
        self.manager = manager_class(host=self.host, *args, **kwargs)
        self.report_interval = report_interval
        self.periodic_enable = periodic_enable
        self.periodic_fuzzy_delay = periodic_fuzzy_delay
        self.periodic_interval_max = periodic_interval_max
        self.saved_args, self.saved_kwargs = args, kwargs
        self.backdoor_port = None
        self.conductor_api = conductor.API(use_local=db_allowed)
        self.conductor_api.wait_until_ready(context.get_admin_context())
 
    def start(self):
        verstr = version.version_string_with_package()
        LOG.audit(_('Starting %(topic)s node (version %(version)s)'),
                  {'topic': self.topic, 'version': verstr})
        self.basic_config_check()
        self.manager.init_host()
        self.model_disconnected = False
        ctxt = context.get_admin_context()
        try:
            self.service_ref = self.conductor_api.service_get_by_args(ctxt,
                    self.host, self.binary)
            self.service_id = self.service_ref['id']
        except exception.NotFound:
            self.service_ref = self._create_service_ref(ctxt)
 
        self.manager.pre_start_hook()
 
        if self.backdoor_port is not None:
            self.manager.backdoor_port = self.backdoor_port
 
        self.conn = rpc.create_connection(new=True)
        LOG.debug(_("Creating Consumer connection for Service %s") %
                  self.topic)
 
        rpc_dispatcher = self.manager.create_rpc_dispatcher(self.backdoor_port)
 
        # Share this same connection for these Consumers
        self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=False)
 
        node_topic = '%s.%s' % (self.topic, self.host)
        self.conn.create_consumer(node_topic, rpc_dispatcher, fanout=False)
 
        self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=True)
 
        # Consume from all consumers in a thread
        self.conn.consume_in_thread()
 
        self.manager.post_start_hook()
 
        LOG.debug(_("Join ServiceGroup membership for this service %s")
                  % self.topic)
        # Add service to the ServiceGroup membership group.
        self.servicegroup_api.join(self.host, self.topic, self)
 
        if self.periodic_enable:
            if self.periodic_fuzzy_delay:
                initial_delay = random.randint(0, self.periodic_fuzzy_delay)
            else:
                initial_delay = None
 
            self.tg.add_dynamic_timer(self.periodic_tasks,
                                     initial_delay=initial_delay,
                                     periodic_interval_max=
                                        self.periodic_interval_max)
 
    def _create_service_ref(self, context):
        svc_values = {
            'host': self.host,
            'binary': self.binary,
            'topic': self.topic,
            'report_count': 0
        }
        service = self.conductor_api.service_create(context, svc_values)
        self.service_id = service['id']
        return service
 
    def __getattr__(self, key):
        manager = self.__dict__.get('manager', None)
        return getattr(manager, key)
 
    @classmethod
    def create(cls, host=None, binary=None, topic=None, manager=None,
               report_interval=None, periodic_enable=None,
               periodic_fuzzy_delay=None, periodic_interval_max=None,
               db_allowed=True):
        if not host:
            host = CONF.host
        if not binary:
            binary = os.path.basename(sys.argv[0])
        if not topic:
            topic = binary.rpartition('nova-')[2]
        if not manager:
            manager_cls = ('%s_manager' %
                           binary.rpartition('nova-')[2])
            manager = CONF.get(manager_cls, None)
        if report_interval is None:
            report_interval = CONF.report_interval
        if periodic_enable is None:
            periodic_enable = CONF.periodic_enable
        if periodic_fuzzy_delay is None:
            periodic_fuzzy_delay = CONF.periodic_fuzzy_delay
        service_obj = cls(host, binary, topic, manager,
                          report_interval=report_interval,
                          periodic_enable=periodic_enable,
                          periodic_fuzzy_delay=periodic_fuzzy_delay,
                          periodic_interval_max=periodic_interval_max,
                          db_allowed=db_allowed)
 
        return service_obj
 
    def kill(self):
        """Destroy the service object in the datastore."""
        self.stop()
        try:
            self.conductor_api.service_destroy(context.get_admin_context(),
                                               self.service_id)
        except exception.NotFound:
            LOG.warn(_('Service killed that has no database entry'))

啓動服務時,判斷數據庫中是否已經存在某個服務記錄,如果不存在則創建一條記錄!

services表的結構:



2  scheduler中的hostmanager是如何管理和調度計算節點的?

直接查詢數據庫中的compute_node來實現;

 

3  compute_node表中的數據何時CRUD?

nova-compute服務會通過一個定時任務period_task.perisod_task定期更新compute_node表中的數據,這些數據主要是關於compute節點目前的使用情況!

 compute_node表的結構:


 

發佈了59 篇原創文章 · 獲贊 6 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章