CAL refactoring
[osm/SO.git] / rwcal / plugins / vala / rwcal_openstack / rift / rwcal / openstack / ceilometer / ceilometer_drv.py
1 #!/usr/bin/python
2
3 #
4 # Copyright 2017 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 import logging
19 import json
20
21 from ceilometerclient import client as ceclient
22
23
24 class CeilometerAPIVersionException(Exception):
25 def __init__(self, errors):
26 self.errors = errors
27 super(CeilometerAPIVersionException, self).__init__("Multiple Exception Received")
28
29 def __str__(self):
30 return self.__repr__()
31
32 def __repr__(self):
33 msg = "{} : Following Exception(s) have occured during Neutron API discovery".format(self.__class__)
34 for n,e in enumerate(self.errors):
35 msg += "\n"
36 msg += " {}: {}".format(n, str(e))
37 return msg
38
39 class CeilometerDriver(object):
40 """
41 CeilometerDriver Class for image management
42 """
43 ### List of supported API versions in prioritized order
44 supported_versions = ["2"]
45
46 def __init__(self,
47 sess_handle,
48 region_name = 'RegionOne',
49 service_type = 'metering',
50 logger = None):
51 """
52 Constructor for CeilometerDriver class
53 Arguments:
54 sess_handle (instance of class SessionDriver)
55 region_name (string ): Region name
56 service_type(string) : Service type name
57 logger (instance of logging.Logger)
58 """
59
60 if logger is None:
61 self.log = logging.getLogger('rwcal.openstack.ceilometer')
62 logger.setLevel(logging.DEBUG)
63 else:
64 self.log = logger
65
66 self._sess_handle = sess_handle
67 #### Attempt to use API versions in prioritized order defined in
68 #### CeilometerDriver.supported_versions
69 def select_version(version):
70 try:
71 self.log.info("Attempting to use Ceilometer v%s APIs", version)
72 cedrv = ceclient.Client(version=version,
73 region_name = region_name,
74 service_type = service_type,
75 session=self._sess_handle.session)
76 except Exception as e:
77 self.log.info(str(e))
78 raise
79 else:
80 self.log.info("Ceilometer API v%s selected", version)
81 return (version, cedrv)
82
83 errors = []
84 for v in CeilometerDriver.supported_versions:
85 try:
86 (self._version, self._ce_drv) = select_version(v)
87 except Exception as e:
88 errors.append(e)
89 else:
90 break
91 else:
92 raise CeilometerAPIVersionException(errors)
93
94 @property
95 def ceilometer_endpoint(self):
96 return self._ce_drv.http_client.get_endpoint()
97
98 def _get_ceilometer_connection(self):
99 """
100 Returns instance of object ceilometerclient.client.Client
101 Use for DEBUG ONLY
102 """
103 return self._ce_drv
104
105 @property
106 def client(self):
107 """
108 Returns instance of object ceilometerclient.client.Client
109 Use for DEBUG ONLY
110 """
111 return self._ce_drv
112
113 @property
114 def meters(self):
115 """A list of the available meters"""
116 try:
117 return self.client.meters.list()
118 except Exception as e:
119 self.log.exception("List meters operation failed. Exception: %s", str(e))
120 raise
121
122 @property
123 def alarms(self):
124 """The ceilometer client alarms manager"""
125 return self.client.alarms
126
127 def nfvi_metrics(self, vim_id):
128 """Returns a dict of NFVI metrics for a given VM
129
130 Arguments:
131 vim_id - the VIM ID of the VM to retrieve the metrics for
132
133 Returns:
134 A dict of NFVI metrics
135
136 """
137 def query_latest_sample(counter_name):
138 try:
139 filter = json.dumps({
140 "and": [
141 {"=": {"resource": vim_id}},
142 {"=": {"counter_name": counter_name}}
143 ]
144 })
145 orderby = json.dumps([{"timestamp": "DESC"}])
146 result = self.client.query_samples.query(filter=filter,
147 orderby=orderby,
148 limit=1)
149 return result[0]
150
151 except IndexError:
152 pass
153
154 except Exception as e:
155 self.log.exception("Got exception while querying ceilometer, exception details:%s", str(e))
156
157 return None
158
159 memory_usage = query_latest_sample("memory.usage")
160 disk_usage = query_latest_sample("disk.usage")
161 cpu_util = query_latest_sample("cpu_util")
162
163 metrics = dict()
164
165 if memory_usage is not None:
166 memory_usage.volume = 1e6 * memory_usage.volume
167 metrics["memory_usage"] = memory_usage.to_dict()
168
169 if disk_usage is not None:
170 metrics["disk_usage"] = disk_usage.to_dict()
171
172 if cpu_util is not None:
173 metrics["cpu_util"] = cpu_util.to_dict()
174 # RIFT-14041 when ceilometer returns value of more than 100, make it 100
175 if metrics["cpu_util"]["volume"] > 100:
176 metrics["cpu_util"]["volume"] = 100
177
178 return metrics
179
180 def query_samples(self, vim_instance_id, counter_name, limit=1):
181 """Returns a list of samples
182
183 Arguments:
184 vim_instance_id - the ID of the VIM that the samples are from
185 counter_name - the counter that the samples will come from
186 limit - a limit on the number of samples to return
187 (default: 1)
188
189 Returns:
190 A list of samples
191
192 """
193 try:
194 filter = json.dumps({
195 "and": [
196 {"=": {"resource": vim_instance_id}},
197 {"=": {"counter_name": counter_name}}
198 ]
199 })
200 try:
201 result = self.client.query_samples.query(filter=filter, limit=limit)
202 except Exception as e:
203 self.log.exception("Query samples operation failed. Exception: %s",str(e))
204 return result[-limit:]
205
206 except Exception as e:
207 self.log.exception(e)
208
209 return []