
On 04/24/2014 03:46 PM, Rodrigo Trujillo wrote:
On 04/22/2014 09:41 PM, Aline Manera wrote:
From: Aline Manera <alinefm@br.ibm.com>
GET /host/stats/history will return the host stats history - the last 60 values. That way the grid in UI can show the history when displaying the host tab and then use /host/stats to get the new updated values - item by item.
Signed-off-by: Aline Manera <alinefm@br.ibm.com> --- docs/API.md | 28 +++++++++++++++++++ src/kimchi/control/host.py | 10 +++++++ src/kimchi/mockmodel.py | 8 ++++++ src/kimchi/model/host.py | 66 ++++++++++++++++++++++++++++++-------------- 4 files changed, 91 insertions(+), 21 deletions(-)
diff --git a/docs/API.md b/docs/API.md index 716c983..1fd2c3c 100644 --- a/docs/API.md +++ b/docs/API.md @@ -768,6 +768,34 @@ Contains the host sample data.
*No actions defined*
+### Resource: HostStatsHistory + +**URI:** /host/stats/history + +It is the sub-resource of Host Stats and the client uses it to get the host +stats history + +**Methods:** + +* **GET**: Retrieve host sample data history + * cpu_utilization: CPU utilization history + * memory: Memory statistics history + * total: Total amount of memory. The unit is Bytes. + * free: The amount of memory left unused by the system. The unit is Bytes. + * buffers: The amount of memory used for file buffers. The unit is Bytes. + * cached: The amount of memory used as cache memory. The unit is Bytes. + * avail: The total amount of buffer, cache and free memory. The unit is Bytes. + * disk_read_rate: IO throughput for reads history + * disk_write_rate: IO throughput for writes history + * net_sent_rate: Network throughput for writes history + * net_recv_rate: Network throughput for reads history + +* **POST**: *See HostStatsHistory Actions* + +**Actions (POST):** + +*No actions defined* + ### Collection: Plugins
**URI:** /plugins diff --git a/src/kimchi/control/host.py b/src/kimchi/control/host.py index 003c4b9..ad34919 100644 --- a/src/kimchi/control/host.py +++ b/src/kimchi/control/host.py @@ -56,6 +56,16 @@ class Host(Resource):
class HostStats(Resource): + def __init__(self, model, id=None): + super(HostStats, self).__init__(model, id) + self.history = HostStatsHistory(self.model) + + @property + def data(self): + return self.info + + +class HostStatsHistory(Resource): @property def data(self): return self.info diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 866ad2c..ca1bea6 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -810,6 +810,14 @@ class MockModel(object): 'net_recv_rate': round(random.uniform(0, 4000), 1), 'net_sent_rate': round(random.uniform(0, 4000), 1)}
+ def hoststatshistory_lookup(self, *name): + return {'cpu_utilization': random.sample(range(100), 30), + 'memory': random.sample(range(4000), 30), + 'disk_read_rate': random.sample(range(4000), 30), + 'disk_write_rate': random.sample(range(4000), 30), + 'net_recv_rate': random.sample(range(4000), 30), + 'net_sent_rate': random.sample(range(4000), 30)} + def users_get_list(self): return ["userA", "userB", "userC"]
diff --git a/src/kimchi/model/host.py b/src/kimchi/model/host.py index e0ac760..3e2c827 100644 --- a/src/kimchi/model/host.py +++ b/src/kimchi/model/host.py @@ -119,18 +119,18 @@ class HostStatsModel(object): __metaclass__ = Singleton
def __init__(self, **kargs): - self.host_stats = defaultdict(int) + self.host_stats = defaultdict(list) self.host_stats_thread = BackgroundTask(HOST_STATS_INTERVAL, self._update_host_stats) self.host_stats_thread.start()
def lookup(self, *name): - return {'cpu_utilization': self.host_stats['cpu_utilization'], - 'memory': self.host_stats.get('memory'), - 'disk_read_rate': self.host_stats['disk_read_rate'], - 'disk_write_rate': self.host_stats['disk_write_rate'], - 'net_recv_rate': self.host_stats['net_recv_rate'], - 'net_sent_rate': self.host_stats['net_sent_rate']} + return {'cpu_utilization': self.host_stats['cpu_utilization'][-1], + 'memory': self.host_stats['memory'][-1], + 'disk_read_rate': self.host_stats['disk_read_rate'][-1], + 'disk_write_rate': self.host_stats['disk_write_rate'][-1], + 'net_recv_rate': self.host_stats['net_recv_rate'][-1], + 'net_sent_rate': self.host_stats['net_sent_rate'][-1]}
def _update_host_stats(self): preTimeStamp = self.host_stats['timestamp'] @@ -148,6 +148,12 @@ class HostStatsModel(object): self._get_percentage_host_cpu_usage() self._get_host_memory_stats()
+ # store only 60 stats (1 min) + for key, value in self.host_stats.iteritems(): + if isinstance(value, list): + if len(value) == 60: + self.host_stats[key] = value[10:] + def _get_percentage_host_cpu_usage(self): # This is cpu usage producer. This producer will calculate the usage # at an interval of HOST_STATS_INTERVAL. @@ -155,7 +161,7 @@ class HostStatsModel(object): # psutil.cpu_percent maintains a cpu time sample. # It will update the cpu time sample when it is called. # So only this producer can call psutil.cpu_percent in kimchi. - self.host_stats['cpu_utilization'] = psutil.cpu_percent(None) + self.host_stats['cpu_utilization'].append(psutil.cpu_percent(None))
def _get_host_memory_stats(self): virt_mem = psutil.virtual_memory() @@ -169,11 +175,13 @@ class HostStatsModel(object): 'cached': virt_mem.cached, 'buffers': virt_mem.buffers, 'avail': virt_mem.available} - self.host_stats['memory'] = memory_stats + self.host_stats['memory'].append(memory_stats)
def _get_host_disk_io_rate(self, seconds): - prev_read_bytes = self.host_stats['disk_read_bytes'] - prev_write_bytes = self.host_stats['disk_write_bytes'] + disk_read_bytes = self.host_stats['disk_read_bytes'] + disk_write_bytes = self.host_stats['disk_write_bytes'] + prev_read_bytes = disk_read_bytes[-1] if disk_read_bytes else 0 + prev_write_bytes = disk_write_bytes[-1] if disk_write_bytes else 0
disk_io = psutil.disk_io_counters(False) read_bytes = disk_io.read_bytes @@ -182,14 +190,16 @@ class HostStatsModel(object): rd_rate = int(float(read_bytes - prev_read_bytes) / seconds + 0.5) wr_rate = int(float(write_bytes - prev_write_bytes) / seconds + 0.5)
- self.host_stats.update({'disk_read_rate': rd_rate, - 'disk_write_rate': wr_rate, - 'disk_read_bytes': read_bytes, - 'disk_write_bytes': write_bytes}) + self.host_stats['disk_read_rate'].append(rd_rate) + self.host_stats['disk_write_rate'].append(wr_rate) + self.host_stats['disk_read_bytes'].append(read_bytes) + self.host_stats['disk_write_bytes'].append(write_bytes)
def _get_host_network_io_rate(self, seconds): - prev_recv_bytes = self.host_stats['net_recv_bytes'] - prev_sent_bytes = self.host_stats['net_sent_bytes'] + net_recv_bytes = self.host_stats['net_recv_bytes'] + net_sent_bytes = self.host_stats['net_sent_bytes'] + prev_recv_bytes = net_recv_bytes[-1] if net_recv_bytes else 0 + prev_sent_bytes = net_sent_bytes[-1] if net_sent_bytes else 0
net_ios = psutil.network_io_counters(True) recv_bytes = 0 @@ -202,10 +212,24 @@ class HostStatsModel(object): rx_rate = int(float(recv_bytes - prev_recv_bytes) / seconds + 0.5) tx_rate = int(float(sent_bytes - prev_sent_bytes) / seconds + 0.5)
- self.host_stats.update({'net_recv_rate': rx_rate, - 'net_sent_rate': tx_rate, - 'net_recv_bytes': recv_bytes, - 'net_sent_bytes': sent_bytes}) + self.host_stats['net_recv_rate'].append(rx_rate) + self.host_stats['net_sent_rate'].append(tx_rate) + self.host_stats['net_recv_bytes'].append(recv_bytes) + self.host_stats['net_sent_bytes'].append(sent_bytes) + + +class HostStatsHistoryModel(object): + def __init__(self, **kargs): + self.history = HostStatsModel(**kargs) + pass "Pass" is not necessary
ops... I will remove before applying
+ + def lookup(self, *name): + return {'cpu_utilization': self.history.host_stats['cpu_utilization'], + 'memory': self.history.host_stats['memory'], + 'disk_read_rate': self.history.host_stats['disk_read_rate'], + 'disk_write_rate': self.history.host_stats['disk_write_rate'], + 'net_recv_rate': self.history.host_stats['net_recv_rate'], + 'net_sent_rate': self.history.host_stats['net_sent_rate']}
class PartitionsModel(object):