summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSwann Croiset <scroiset@mirantis.com>2017-02-16 14:54:27 +0100
committerSwann Croiset <scroiset@mirantis.com>2017-02-22 14:50:16 +0100
commit2d819d12b7abb40595ec2eba9b52ddc263bf1b7c (patch)
tree0279145f3a01812c918db84229a88c89a076d3ee
parent150d93e29b938a11e9d9bb1305794964d5f09528 (diff)
Use changes-since parameter when polling Nova server details
Notes
Notes (review): Code-Review+2: Simon Pasquier <spasquier@mirantis.com> Workflow+1: Swann Croiset <scroiset@mirantis.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Thu, 23 Feb 2017 14:42:33 +0000 Reviewed-on: https://review.openstack.org/434930 Project: openstack/fuel-plugin-lma-collector Branch: refs/heads/master
-rw-r--r--deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py29
-rw-r--r--deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py24
-rw-r--r--deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py37
3 files changed, 66 insertions, 24 deletions
diff --git a/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py b/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py
index 7923274..31adabb 100644
--- a/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py
+++ b/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_base.py
@@ -282,14 +282,19 @@ class AsyncPoller(threading.Thread):
282 polling_function: a function to execute periodically 282 polling_function: a function to execute periodically
283 interval: the interval in second 283 interval: the interval in second
284 name: (optional) the name of the thread 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 super(AsyncPoller, self).__init__(name=name) 292 super(AsyncPoller, self).__init__(name=name)
289 self.collectd = collectd 293 self.collectd = collectd
290 self.polling_function = polling_function 294 self.polling_function = polling_function
291 self.interval = interval 295 self.interval = interval
292 self._results = None 296 self._results = []
297 self._reset_on_read = reset_on_read
293 298
294 def run(self): 299 def run(self):
295 self.collectd.info('Starting thread {}'.format(self.name)) 300 self.collectd.info('Starting thread {}'.format(self.name))
@@ -297,8 +302,7 @@ class AsyncPoller(threading.Thread):
297 try: 302 try:
298 started_at = time.time() 303 started_at = time.time()
299 304
300 self._results = self.polling_function() 305 self.results = self.polling_function()
301
302 tosleep = self.interval - (time.time() - started_at) 306 tosleep = self.interval - (time.time() - started_at)
303 if tosleep > 0: 307 if tosleep > 0:
304 time.sleep(tosleep) 308 time.sleep(tosleep)
@@ -310,9 +314,20 @@ class AsyncPoller(threading.Thread):
310 ) 314 )
311 315
312 except Exception as e: 316 except Exception as e:
313 self._results = None 317 self.results = []
314 self.collectd.error('{} fails: {}'.format(self.name, e)) 318 self.collectd.error('{} fails: {}'.format(self.name, e))
315 time.sleep(10) 319 time.sleep(10)
316 320
317 def get_results(self): 321 @property
318 return self._results 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
diff --git a/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py b/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py
index 1aeeb36..2da8670 100644
--- a/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py
+++ b/deployment_scripts/puppet/modules/lma_collector/files/collectd/collectd_openstack.py
@@ -166,6 +166,8 @@ class CollectdPlugin(base.Base):
166 self._threads = {} 166 self._threads = {}
167 self.pagination_limit = None 167 self.pagination_limit = None
168 self.polling_interval = 60 168 self.polling_interval = 60
169 self._last_run = None
170 self.changes_since = False
169 171
170 def _build_url(self, service, resource): 172 def _build_url(self, service, resource):
171 s = (self.get_service(service) or {}) 173 s = (self.get_service(service) or {})
@@ -251,7 +253,7 @@ class CollectdPlugin(base.Base):
251 url = self._build_url(service, resource) 253 url = self._build_url(service, resource)
252 if not url: 254 if not url:
253 return 255 return
254 self.logger.info("GET '%s'" % url) 256 self.logger.info('GET({}) {}'.format(url, params))
255 return self.os_client.make_request('get', url, params=params) 257 return self.os_client.make_request('get', url, params=params)
256 258
257 @property 259 @property
@@ -287,7 +289,7 @@ class CollectdPlugin(base.Base):
287 self.max_retries) 289 self.max_retries)
288 290
289 def get_objects(self, project, object_name, api_version='', 291 def get_objects(self, project, object_name, api_version='',
290 params=None, detail=False): 292 params=None, detail=False, since=False):
291 """ Return a list of OpenStack objects 293 """ Return a list of OpenStack objects
292 294
293 The API version is not always included in the URL endpoint 295 The API version is not always included in the URL endpoint
@@ -295,6 +297,7 @@ class CollectdPlugin(base.Base):
295 api_version parameter to specify which version should be used. 297 api_version parameter to specify which version should be used.
296 298
297 """ 299 """
300 self.changes_since = since
298 if params is None: 301 if params is None:
299 params = {} 302 params = {}
300 303
@@ -316,9 +319,18 @@ class CollectdPlugin(base.Base):
316 _objects = [] 319 _objects = []
317 _opts = {} 320 _opts = {}
318 _opts.update(opts) 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 while True: 330 while True:
320 r = self.get(project, resource, params=_opts) 331 r = self.get(project, resource, params=_opts)
321 if not r or object_name not in r.json(): 332 if not r or object_name not in r.json():
333 has_failure = True
322 if r is None: 334 if r is None:
323 err = '' 335 err = ''
324 else: 336 else:
@@ -354,6 +366,9 @@ class CollectdPlugin(base.Base):
354 366
355 _opts['marker'] = bulk_objs[-1]['id'] 367 _opts['marker'] = bulk_objs[-1]['id']
356 368
369 if not has_failure:
370 self._last_run = last_run
371
357 return _objects 372 return _objects
358 373
359 poller_id = '{}:{}'.format(project, resource) 374 poller_id = '{}:{}'.format(project, resource)
@@ -361,7 +376,7 @@ class CollectdPlugin(base.Base):
361 t = base.AsyncPoller(self.collectd, 376 t = base.AsyncPoller(self.collectd,
362 openstack_api_poller, 377 openstack_api_poller,
363 self.polling_interval, 378 self.polling_interval,
364 poller_id) 379 poller_id, self.changes_since)
365 t.start() 380 t.start()
366 self._threads[poller_id] = t 381 self._threads[poller_id] = t
367 382
@@ -372,8 +387,7 @@ class CollectdPlugin(base.Base):
372 del self._threads[poller_id] 387 del self._threads[poller_id]
373 return [] 388 return []
374 389
375 results = t.get_results() 390 return t.results
376 return [] if results is None else results
377 391
378 def count_objects_group_by(self, 392 def count_objects_group_by(self,
379 list_object, 393 list_object,
diff --git a/deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py b/deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py
index 8cdd57d..48bbf0a 100644
--- a/deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py
+++ b/deployment_scripts/puppet/modules/lma_collector/files/collectd/openstack_nova.py
@@ -17,6 +17,8 @@
17import collectd 17import collectd
18 18
19import collectd_openstack as openstack 19import collectd_openstack as openstack
20from itertools import groupby
21
20 22
21PLUGIN_NAME = 'nova' 23PLUGIN_NAME = 'nova'
22INTERVAL = openstack.INTERVAL 24INTERVAL = openstack.INTERVAL
@@ -32,22 +34,33 @@ class NovaInstanceStatsPlugin(openstack.CollectdPlugin):
32 self.plugin = PLUGIN_NAME 34 self.plugin = PLUGIN_NAME
33 self.interval = INTERVAL 35 self.interval = INTERVAL
34 self.pagination_limit = 500 36 self.pagination_limit = 500
37 self._cache = {}
35 38
36 def itermetrics(self): 39 def itermetrics(self):
37 servers_details = self.get_objects('nova', 'servers', 40 server_details = self.get_objects('nova', 'servers',
38 params={'all_tenants': 1}, 41 params={'all_tenants': 1},
39 detail=True) 42 detail=True, since=True)
40 43
41 def groupby(d): 44 for server in server_details:
42 return d.get('status', 'unknown').lower() 45 _id = server.get('id')
43 46 status = server.get('status', 'unknown').lower()
44 status = self.count_objects_group_by(servers_details, 47 if status == 'deleted':
45 group_by_func=groupby) 48 try:
46 for s, nb in status.iteritems(): 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 yield { 60 yield {
48 'plugin_instance': 'instances', 61 'plugin_instance': 'instances',
49 'values': nb, 62 'values': len(list(g)),
50 'type_instance': s, 63 'type_instance': status,
51 } 64 }
52 65
53 66