Browse Source

Use changes-since parameter when polling Nova server details

Change-Id: Ia629286ab2c08fc3cb16a489142be79568590c34
Swann Croiset 2 years ago
parent
commit
2d819d12b7

+ 22
- 7
deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py View File

@@ -282,14 +282,19 @@ class AsyncPoller(threading.Thread):
282 282
            polling_function: a function to execute periodically
283 283
            interval: the interval in second
284 284
            name: (optional) the name of the thread
285
+           reset_on_read: (default False) if True, all results returned by the
286
+                          polling_function() are accumulated until they are
287
+                          read.
285 288
     """
286 289
 
287
-    def __init__(self, collectd, polling_function, interval, name=None):
290
+    def __init__(self, collectd, polling_function, interval, name=None,
291
+                 reset_on_read=False):
288 292
         super(AsyncPoller, self).__init__(name=name)
289 293
         self.collectd = collectd
290 294
         self.polling_function = polling_function
291 295
         self.interval = interval
292
-        self._results = None
296
+        self._results = []
297
+        self._reset_on_read = reset_on_read
293 298
 
294 299
     def run(self):
295 300
         self.collectd.info('Starting thread {}'.format(self.name))
@@ -297,8 +302,7 @@ class AsyncPoller(threading.Thread):
297 302
             try:
298 303
                 started_at = time.time()
299 304
 
300
-                self._results = self.polling_function()
301
-
305
+                self.results = self.polling_function()
302 306
                 tosleep = self.interval - (time.time() - started_at)
303 307
                 if tosleep > 0:
304 308
                     time.sleep(tosleep)
@@ -310,9 +314,20 @@ class AsyncPoller(threading.Thread):
310 314
                     )
311 315
 
312 316
             except Exception as e:
313
-                self._results = None
317
+                self.results = []
314 318
                 self.collectd.error('{} fails: {}'.format(self.name, e))
315 319
                 time.sleep(10)
316 320
 
317
-    def get_results(self):
318
-        return self._results
321
+    @property
322
+    def results(self):
323
+        r = self._results
324
+        if self._reset_on_read:
325
+            self._results = []
326
+        return r
327
+
328
+    @results.setter
329
+    def results(self, value):
330
+        if self._reset_on_read:
331
+            self._results.extend(value)
332
+        else:
333
+            self._results = value

+ 19
- 5
deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py View File

@@ -166,6 +166,8 @@ class CollectdPlugin(base.Base):
166 166
         self._threads = {}
167 167
         self.pagination_limit = None
168 168
         self.polling_interval = 60
169
+        self._last_run = None
170
+        self.changes_since = False
169 171
 
170 172
     def _build_url(self, service, resource):
171 173
         s = (self.get_service(service) or {})
@@ -251,7 +253,7 @@ class CollectdPlugin(base.Base):
251 253
         url = self._build_url(service, resource)
252 254
         if not url:
253 255
             return
254
-        self.logger.info("GET '%s'" % url)
256
+        self.logger.info('GET({}) {}'.format(url, params))
255 257
         return self.os_client.make_request('get', url, params=params)
256 258
 
257 259
     @property
@@ -287,7 +289,7 @@ class CollectdPlugin(base.Base):
287 289
                                   self.max_retries)
288 290
 
289 291
     def get_objects(self, project, object_name, api_version='',
290
-                    params=None, detail=False):
292
+                    params=None, detail=False, since=False):
291 293
         """ Return a list of OpenStack objects
292 294
 
293 295
             The API version is not always included in the URL endpoint
@@ -295,6 +297,7 @@ class CollectdPlugin(base.Base):
295 297
             api_version parameter to specify which version should be used.
296 298
 
297 299
         """
300
+        self.changes_since = since
298 301
         if params is None:
299 302
             params = {}
300 303
 
@@ -316,9 +319,18 @@ class CollectdPlugin(base.Base):
316 319
             _objects = []
317 320
             _opts = {}
318 321
             _opts.update(opts)
322
+
323
+            if self.changes_since and self._last_run:
324
+                _opts['changes-since'] = self._last_run.isoformat()
325
+
326
+            # Keep track of the initial request time
327
+            last_run = datetime.datetime.now(tz=dateutil.tz.tzutc())
328
+            has_failure = False
329
+
319 330
             while True:
320 331
                 r = self.get(project, resource, params=_opts)
321 332
                 if not r or object_name not in r.json():
333
+                    has_failure = True
322 334
                     if r is None:
323 335
                         err = ''
324 336
                     else:
@@ -354,6 +366,9 @@ class CollectdPlugin(base.Base):
354 366
 
355 367
                 _opts['marker'] = bulk_objs[-1]['id']
356 368
 
369
+            if not has_failure:
370
+                self._last_run = last_run
371
+
357 372
             return _objects
358 373
 
359 374
         poller_id = '{}:{}'.format(project, resource)
@@ -361,7 +376,7 @@ class CollectdPlugin(base.Base):
361 376
             t = base.AsyncPoller(self.collectd,
362 377
                                  openstack_api_poller,
363 378
                                  self.polling_interval,
364
-                                 poller_id)
379
+                                 poller_id, self.changes_since)
365 380
             t.start()
366 381
             self._threads[poller_id] = t
367 382
 
@@ -372,8 +387,7 @@ class CollectdPlugin(base.Base):
372 387
             del self._threads[poller_id]
373 388
             return []
374 389
 
375
-        results = t.get_results()
376
-        return [] if results is None else results
390
+        return t.results
377 391
 
378 392
     def count_objects_group_by(self,
379 393
                                list_object,

+ 25
- 12
deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py View File

@@ -17,6 +17,8 @@
17 17
 import collectd
18 18
 
19 19
 import collectd_openstack as openstack
20
+from itertools import groupby
21
+
20 22
 
21 23
 PLUGIN_NAME = 'nova'
22 24
 INTERVAL = openstack.INTERVAL
@@ -32,22 +34,33 @@ class NovaInstanceStatsPlugin(openstack.CollectdPlugin):
32 34
         self.plugin = PLUGIN_NAME
33 35
         self.interval = INTERVAL
34 36
         self.pagination_limit = 500
37
+        self._cache = {}
35 38
 
36 39
     def itermetrics(self):
37
-        servers_details = self.get_objects('nova', 'servers',
38
-                                           params={'all_tenants': 1},
39
-                                           detail=True)
40
-
41
-        def groupby(d):
42
-            return d.get('status', 'unknown').lower()
43
-
44
-        status = self.count_objects_group_by(servers_details,
45
-                                             group_by_func=groupby)
46
-        for s, nb in status.iteritems():
40
+        server_details = self.get_objects('nova', 'servers',
41
+                                          params={'all_tenants': 1},
42
+                                          detail=True, since=True)
43
+
44
+        for server in server_details:
45
+            _id = server.get('id')
46
+            status = server.get('status', 'unknown').lower()
47
+            if status == 'deleted':
48
+                try:
49
+                    self.logger.debug(
50
+                        'remove deleted instance {} from cache'.format(_id))
51
+                    del self._cache[_id]
52
+                except KeyError:
53
+                    self.logger.warning(
54
+                        'cannot find instance in cache {}'.format(_id))
55
+            else:
56
+                self._cache[_id] = status
57
+
58
+        servers = sorted(self._cache.values())
59
+        for status, g in groupby(servers):
47 60
             yield {
48 61
                 'plugin_instance': 'instances',
49
-                'values': nb,
50
-                'type_instance': s,
62
+                'values': len(list(g)),
63
+                'type_instance': status,
51 64
             }
52 65
 
53 66
 

Loading…
Cancel
Save