cinder service status up / down comb source

Ocata-based version of the source code carding

1) a user input command line cinder service-list, view the status of the service cinder, the cinder entry function cinder / api contrib / services.py /: Service: index method

class ServiceController(wsgi.Controller):
    def __init__(self, ext_mgr=None):
        self.ext_mgr = ext_mgr
        super(ServiceController, self).__init__()
        self.volume_api = volume.API()

    def index(self, req):
        """Return a list of all running services.

        Filter by host & service name.
        """
        context = req.environ['cinder.context']
        authorize(context, action='index')
        detailed = self.ext_mgr.is_loaded('os-extended-services')
        now = timeutils.utcnow(with_timezone=True)------------------//获取controller 当前的时间

        filters = {}

        if 'host' in req.GET:
            filters['host'] = req.GET['host']
        IF 'binary' in req.GET: 
            Filters [ 'binary'] = req.GET [ 'binary'] 
        elif '-Service' in req.GET: 
            Filters [ 'binary'] = req.GET [ '-Service'] 
            versionutils. report_deprecated_feature (LOG, _ ( 
                "Query Service by the Parameter IS deprecated." 
                "Please use the Parameter binary INSTEAD.")) 

        Services = objects.ServiceList.get_all (context, Filters) ---------- // from db get a list of all the cinder service

        svcs = []
        for svc in services:----------------------------//循环每个 service
            updated_at = svc.updated_at
            delta = now - (svc.updated_at or svc.created_at ) ------------- // get updated_at. Does not exist, obtaining the created_at, and calculate the time difference and the current time 
            delta_sec = delta.total_seconds () 
            IF svc.modified_at: 
                delta_mod = now - svc.modified_at 
            Active = 'Enabled ' 
            IF svc.disabled: 
                Active =' Disabled '
                ABS IF (delta_sec)> = ABS (delta_mod.total_seconds ()): 
                    for updated_at svc.modified_at = 
            absolute value alive = abs (delta_sec) <= CONF.service_down_time ------ / acquisition time difference, and checks whether less than server_down_time configuration, the configuration item the default is 60 seconds 
            art = (alive and "up" ) or "down" ---------------------- // if difference is less than 60, then the service status is up, otherwise Down 
            IF for updated_at: 
                for updated_at = timeutils.normalize_time (for updated_at) 
            ret_fields = { 'binary': svc.binary, 'Host': svc.host, 
                          'Zone': SVC. availability_zone, 
                          'Status': Active, 'State': Art, 
                          'for updated_at':updated_at}

            # On V3.7 we added cluster support
            if req.api_version_request.matches('3.7'):
                ret_fields['cluster'] = svc.cluster_name

            if detailed:
                ret_fields['disabled_reason'] = svc.disabled_reason
                if svc.binary == "cinder-volume":
                    ret_fields['replication_status'] = svc.replication_status
                    ret_fields['active_backend_id'] = svc.active_backend_id
                    ret_fields['frozen'] = svc.frozen
            svcs.append(ret_fields)
        return {'services': svcs}

 

Thus service of the up / down depending on the state of the range of the time difference value and the current controller node database table corresponding to a service of the service updated_at whether the columns in the row of the configuration, if the difference is within the range set, then that service is up, down is if the difference is not within the scope of the set, then that service, then the value of each service from updated_at how to update?

2, corresponding to each service update database cinder update_at value, the time value of this field, that the acquired service running on which physical nodes, to obtain the current time value of the physical nodes, the database is updated value, the count is incremented

various service cinder, such as cinder-api, cinder-backup, etc., are examples of a cinder / service.py file class Service (service.Service) of
(in this example, using a Manager, enable RPC, by listening on topic of the queue, and he also regularly run a task on manager, reported his condition to the database service table)
Start methods of the class as follows:

   Start DEF (Self): 
        the version_string = version.version_string () 
        log.info (_LI ( 'Starting% (Topic) S Node (Version% (the version_string) S)'), 
                 { 'Topic': self.topic, 'the version_string' : the version_string}) 
        self.model_disconnected = False 

        IF self.coordination: 
            coordination.COORDINATOR.start () 

        self.manager.init_host (added_to_cluster = self.added_to_cluster, -------- call manager module is init_host method, 
                               service_id = Service.service_id) ------------------ implementation of this method in turn invokes driver.do_setup, driver.check_for_setup_error, driver.init_capabilities three functions, which may in init_capabilities there will mobilize driven get_volume_stats function to get the information stored in the state storage backend

        LOG.debug("Creating RPC server for service %s", self.topic)

        ctxt = context.get_admin_context()
        endpoints = [self.manager]
        endpoints.extend(self.manager.additional_endpoints)
        obj_version_cap = objects.Service.get_minimum_obj_version(ctxt)
        LOG.debug("Pinning object versions for RPC server serializer to %s",
                  obj_version_cap)
        serializer = objects_base.CinderObjectSerializer(obj_version_cap)

        target = messaging.Target(topic=self.topic, server=self.host)
        self.rpcserver = rpc.get_server(target, endpoints, serializer)
        self.rpcserver.start()

        # NOTE(dulek): Kids, don't do that at home. We're relying here on
        # oslo.messaging implementation details to keep backward compatibility
        # with pre-Ocata services. This will not matter once we drop
        # compatibility with them.
        if self.topic == constants.VOLUME_TOPIC:
            target = messaging.Target(
                topic='%(topic)s.%(host)s' % {'topic': self.topic,
                                              'host': self.host},
                server=vol_utils.extract_host(self.host, 'host'))
            self.backend_rpcserver = rpc.get_server(target, endpoints,
                                                    serializer)
            self.backend_rpcserver.start()

        # TODO(geguileo): In O - Remove the is_svc_upgrading_to_n part
        if self.cluster and not self.is_svc_upgrading_to_n(self.binary):
            LOG.info(_LI('Starting %(topic)s cluster %(cluster)s (version '
                         '%(version)s)'),
                     {'topic': self.topic, 'version': version_string,
                      'cluster': self.cluster})
            = messaging.Target target ( 
                Topic = '% S. S%'% (self.topic, self.cluster), 
                Server = vol_utils.extract_host (self.cluster, 'Host')) 
            Serializer = objects_base.CinderObjectSerializer (obj_version_cap) 
            self.cluster_rpcserver = rpc.get_server(target, endpoints,
                                                    serializer)
            self.cluster_rpcserver.start()

        Self .manager.init_host_with_rpc () 

        IF self.report_interval: ------------------------- // If you set report_interval configuration items, then the service will start report_state infinite loop to perform a method, 
		run interval is report_interval, the default value is 10 seconds, which is the default state of 10 reported a 
            pulse = loopingcall.FixedIntervalLoopingCall (---------- which is a cyclic, self.report_state this task is to be executed in a loop 
                self.report_state) 
            pulse.start (= interval the self.report_interval, ----------- started this run this cycle, s1 
                        initial_delay = self.report_interval) 
            self.timers .append (Pulse) 

        IF self.periodic_interval: 
            IF self.periodic_fuzzy_delay: 
                initial_delay the random.randint = (0, self.periodic_fuzzy_delay)
            else:
                initial_delay = None

            periodic = loopingcall.FixedIntervalLoopingCall(
                self.periodic_tasks)
            periodic.start(interval=self.periodic_interval,
                           initial_delay=initial_delay)
            self.timers.append(periodic)

 

s1方法的实现
    def report_state(self):----更新服务的状态到数据库中
        """Update the state of this service in the datastore."""
        if not self.manager.is_working():
            # NOTE(dulek): If manager reports a problem we're not sending
            # heartbeats - to indicate that service is actually down.
            LOG.error(_LE('Manager for service %(binary)s %(host)s is '
                          'reporting problems, not sending heartbeat. '
                          'Service will appear "down".'),
                      {'binary': self.binary,
                       'host': self.host})
            return

        ctxt = context.get_admin_context()
        zone = CONF.storage_availability_zone
        try:
            try:
                service_ref = objects.Service.get_by_id(ctxt,Service.service_id)-----根据service_id从数据库中获取service信息
            except exception.NotFound:
                LOG.debug('The service database object disappeared, '
                          'recreating it.')
                self._create_service_ref(ctxt)
                service_ref = objects.Service.get_by_id(ctxt,Service.service_id)

            service_ref.report_count += 1--------------更新报告计数器,加1
            if zone != service_ref.availability_zone:
                service_ref.availability_zone = zone

            service_ref.save()

            # TODO(termie): make this pattern be more elegant.
            if getattr(self, 'model_disconnected', False):
                self.model_disconnected = False
                LOG.error(_LE('Recovered model server connection!'))

3, content services table field

mysql> desc services;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| created_at             | datetime     | YES  |     | NULL    |                |
| updated_at             | datetime     | YES  |     | NULL    |                |
| deleted_at             | datetime     | YES  |     | NULL    |                |
| deleted                | tinyint(1)   | YES  |     | NULL    |                |
| id                     | int(11)      | NO   | PRI | NULL    | auto_increment |
| host                   | varchar(255) | YES  |     | NULL    |                |
| binary                 | varchar(255) | YES  |     | NULL    |                |
| topic                  | varchar(255) | YES  |     | NULL    |                |
| report_count           | int(11)      | NO   |     | NULL    |                |
| disabled               | tinyint(1)   | YES  |     | NULL    |                |
| availability_zone      | varchar(255) | YES  |     | NULL    |                |
| disabled_reason        | varchar(255) | YES  |     | NULL    |                |
| modified_at            | datetime     | YES  |     | NULL    |                |
| rpc_current_version    | varchar(36)  | YES  |     | NULL    |                |
| object_current_version | varchar(36)  | YES  |     | NULL    |                |
| replication_status     | varchar(36)  | YES  |     | NULL    |                |
| frozen                 | tinyint(1)   | YES  |     | NULL    |                |
| active_backend_id      | varchar(255) | YES  |     | NULL    |                |
| cluster_name           | varchar(255) | YES  |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+
19 rows in set (0.01 sec)

 

样例
mysql> select * from services limit 2\G;
*************************** 1. row ***************************
            created_at: 2018-08-16 07:29:20
            updated_at: 2019-06-14 09:22:23
            deleted_at: NULL
               deleted: 0
                    id: 1
                  host: 10.24.1.9
                binary: cinder-scheduler
                 topic: cinder-scheduler
          report_count: 838433
              disabled: 0
     availability_zone: nova
       disabled_reason: NULL
           modified_at: NULL
   rpc_current_version: 3.5
object_current_version: 1.21
    replication_status: not-capable
                frozen: 0
     active_backend_id: NULL
          cluster_name: NULL
*************************** 2. row ***************************

  

 

 

 

Guess you like

Origin www.cnblogs.com/potato-chip/p/11024740.html