blob: 5f99b61690613768f691a2d8757e132065ed10d7 [file] [log] [blame]
svavilap022f56f2015-12-04 14:05:39 -05001import requests
2from six.moves import urllib
3import urllib2
4import pytz
5import datetime
Srikanth Vavilapallidab96742016-02-09 18:40:48 -05006import time
svavilap022f56f2015-12-04 14:05:39 -05007from rest_framework.decorators import api_view
8from rest_framework.response import Response
9from rest_framework.reverse import reverse
10from rest_framework import serializers
11from rest_framework import generics
12from rest_framework.views import APIView
13from core.models import *
Scott Bakerb487e302015-12-31 11:13:21 -080014from services.ceilometer.models import *
svavilap022f56f2015-12-04 14:05:39 -050015from django.forms import widgets
16from django.utils import datastructures
17from django.utils.translation import ugettext_lazy as _
18from django.utils import timezone
svavilap022f56f2015-12-04 14:05:39 -050019from django.core.exceptions import PermissionDenied
Scott Baker0ae266e2016-01-14 15:30:20 -080020from xos.logger import observer_logger as logger
svavilap022f56f2015-12-04 14:05:39 -050021
22# This REST API endpoint provides information that the ceilometer view needs to display
svavilap022f56f2015-12-04 14:05:39 -050023
24def getTenantCeilometerProxyURL(user):
25 monitoring_channel = None
26 for obj in MonitoringChannel.get_tenant_objects().all():
27 if (obj.creator.username == user.username):
28 monitoring_channel = obj
29 break
30 if not monitoring_channel:
31 raise XOSMissingField("Monitoring channel is missing for this tenant...Create one and invoke this REST API")
32 #TODO: Wait until URL is completely UP
Srikanth Vavilapallidab96742016-02-09 18:40:48 -050033 MAX_ATTEMPTS = 5
34 attempts = 0
svavilap022f56f2015-12-04 14:05:39 -050035 while True:
36 try:
Srikanth Vavilapallidab96742016-02-09 18:40:48 -050037 response = urllib2.urlopen(monitoring_channel.ceilometer_url)
svavilap022f56f2015-12-04 14:05:39 -050038 break
39 except urllib2.HTTPError, e:
Srikanth Vavilapallidab96742016-02-09 18:40:48 -050040 logger.info('HTTP error %(reason)s' % {'reason':e.reason})
svavilap022f56f2015-12-04 14:05:39 -050041 break
42 except urllib2.URLError, e:
Srikanth Vavilapallidab96742016-02-09 18:40:48 -050043 attempts += 1
44 if attempts >= MAX_ATTEMPTS:
45 raise XOSServiceUnavailable("Ceilometer channel is not ready yet...Try again later")
46 logger.info('URL error %(reason)s' % {'reason':e.reason})
47 time.sleep(1)
svavilap022f56f2015-12-04 14:05:39 -050048 pass
Srikanth Vavilapallidab96742016-02-09 18:40:48 -050049 logger.info("Ceilometer proxy URL for user %(user)s is %(url)s" % {'user':user.username,'url':monitoring_channel.ceilometer_url})
svavilap022f56f2015-12-04 14:05:39 -050050 return monitoring_channel.ceilometer_url
51
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -050052def getTenantControllerTenantMap(user, slice=None):
svavilap022f56f2015-12-04 14:05:39 -050053 tenantmap={}
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -050054 if not slice:
55 slices = Slice.objects.filter(creator=user)
56 else:
57 slices = [slice]
58 for s in slices:
59 for cs in s.controllerslices.all():
svavilap022f56f2015-12-04 14:05:39 -050060 if cs.tenant_id:
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -050061 tenantmap[cs.tenant_id] = {"slice": cs.slice.name}
62 if cs.slice.service:
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -050063 tenantmap[cs.tenant_id]["service"] = cs.slice.service.name
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -050064 else:
65 logger.warn("SRIKANTH: Slice %(slice)s is not associated with any service" % {'slice':cs.slice.name})
66 tenantmap[cs.tenant_id]["service"] = "Other"
Srikanth Vavilapalli5bc1eb12016-02-07 14:18:51 -050067 #TEMPORARY WORK AROUND: There are some resource in network like whitebox switches does not belong to a specific tenant.
68 #They are all associated with "default_admin_tenant" tenant
69 tenantmap["default_admin_tenant"] = {"slice": "default_admin_tenant", "service": "Other"}
svavilap022f56f2015-12-04 14:05:39 -050070 return tenantmap
71
72def build_url(path, q, params=None):
73 """Convert list of dicts and a list of params to query url format.
74
75 This will convert the following:
76 "[{field=this,op=le,value=34},
77 {field=that,op=eq,value=foo,type=string}],
78 ['foo=bar','sna=fu']"
79 to:
80 "?q.field=this&q.field=that&
81 q.op=le&q.op=eq&
82 q.type=&q.type=string&
83 q.value=34&q.value=foo&
84 foo=bar&sna=fu"
85 """
86 if q:
87 query_params = {'q.field': [],
88 'q.value': [],
89 'q.op': [],
90 'q.type': []}
91
92 for query in q:
93 for name in ['field', 'op', 'value', 'type']:
94 query_params['q.%s' % name].append(query.get(name, ''))
95
96 # Transform the dict to a sequence of two-element tuples in fixed
97 # order, then the encoded string will be consistent in Python 2&3.
98 new_qparams = sorted(query_params.items(), key=lambda x: x[0])
99 path += "?" + urllib.parse.urlencode(new_qparams, doseq=True)
100
101 if params:
102 for p in params:
103 path += '&%s' % p
104 elif params:
105 path += '?%s' % params[0]
106 for p in params[1:]:
107 path += '&%s' % p
108 return path
109
110def concat_url(endpoint, url):
111 """Concatenate endpoint and final URL.
112
113 E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to
114 "http://keystone/v2.0/tokens".
115
116 :param endpoint: the base URL
117 :param url: the final URL
118 """
119 return "%s/%s" % (endpoint.rstrip("/"), url.strip("/"))
120
121def resource_list(request, query=None, ceilometer_url=None, ceilometer_usage_object=None):
122 """List the resources."""
123 url = concat_url(ceilometer_url, build_url('/v2/resources', query))
124 try:
125 response = requests.get(url)
126 except requests.exceptions.RequestException as e:
127 raise e
128 return response.json()
129
130def sample_list(request, meter_name, ceilometer_url=None, query=None, limit=None):
131 """List the samples for this meters."""
132 params = ['limit=%s' % limit] if limit else []
133 url = concat_url(ceilometer_url, build_url('/v2/samples', query, params))
134 try:
135 response = requests.get(url)
136 except requests.exceptions.RequestException as e:
137 raise e
138 return response.json()
139
140def meter_list(request, ceilometer_url=None, query=None):
141 """List the user's meters."""
142 url = concat_url(ceilometer_url, build_url('/v2/meters', query))
143 try:
144 response = requests.get(url)
145 except requests.exceptions.RequestException as e:
146 raise e
147 return response.json()
148
149
150def statistic_list(request, meter_name, ceilometer_url=None, query=None, period=None):
151 """List of statistics."""
152 p = ['period=%s' % period] if period else []
153 url = concat_url(ceilometer_url, build_url('/v2/meters/' + meter_name + '/statistics', query, p))
154 try:
155 response = requests.get(url)
156 except requests.exceptions.RequestException as e:
157 raise e
158 return response.json()
159
160def diff_lists(a, b):
161 if not a:
162 return []
163 elif not b:
164 return a
165 else:
166 return list(set(a) - set(b))
167
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -0500168def get_resource_map(request, ceilometer_url, query=None):
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500169 resource_map = {}
170 try:
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -0500171 resources = resource_list(request, ceilometer_url=ceilometer_url, query=query)
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500172 for r in resources:
173 if 'display_name' in r['metadata']:
174 name = r['metadata']['display_name']
175 elif 'name' in r['metadata']:
176 name = r['metadata']['name']
177 else:
178 name = r['resource_id']
179 resource_map[r['resource_id']] = name
180 except requests.exceptions.RequestException as e:
181 raise e
182
183 return resource_map
184
svavilap022f56f2015-12-04 14:05:39 -0500185class Meters(object):
186 """Class for listing of available meters.
187
188 It is listing meters defined in this class that are available
189 in Ceilometer meter_list.
190
191 It is storing information that is not available in Ceilometer, i.e.
192 label, description.
193
194 """
195
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -0500196 def __init__(self, request=None, ceilometer_meter_list=None, ceilometer_url=None, query=None, tenant_map=None, resource_map=None):
svavilap022f56f2015-12-04 14:05:39 -0500197 # Storing the request.
198 self._request = request
199 self.ceilometer_url = ceilometer_url
200 self.tenant_map = tenant_map
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500201 self.resource_map = resource_map
svavilap022f56f2015-12-04 14:05:39 -0500202
203 # Storing the Ceilometer meter list
204 if ceilometer_meter_list:
205 self._ceilometer_meter_list = ceilometer_meter_list
206 else:
207 try:
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -0500208 meter_query=[]
209 if query:
210 meter_query = query
211 self._ceilometer_meter_list = meter_list(request, self.ceilometer_url, meter_query)
svavilap022f56f2015-12-04 14:05:39 -0500212 except requests.exceptions.RequestException as e:
213 self._ceilometer_meter_list = []
214 raise e
215
216 # Storing the meters info categorized by their services.
217 self._nova_meters_info = self._get_nova_meters_info()
218 self._neutron_meters_info = self._get_neutron_meters_info()
219 self._glance_meters_info = self._get_glance_meters_info()
220 self._cinder_meters_info = self._get_cinder_meters_info()
221 self._swift_meters_info = self._get_swift_meters_info()
222 self._kwapi_meters_info = self._get_kwapi_meters_info()
223 self._ipmi_meters_info = self._get_ipmi_meters_info()
224 self._vcpe_meters_info = self._get_vcpe_meters_info()
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -0500225 self._volt_meters_info = self._get_volt_meters_info()
svavilap022f56f2015-12-04 14:05:39 -0500226 self._sdn_meters_info = self._get_sdn_meters_info()
227
228 # Storing the meters info of all services together.
229 all_services_meters = (self._nova_meters_info,
230 self._neutron_meters_info,
231 self._glance_meters_info,
232 self._cinder_meters_info,
233 self._swift_meters_info,
234 self._kwapi_meters_info,
235 self._ipmi_meters_info,
236 self._vcpe_meters_info,
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -0500237 self._volt_meters_info,
svavilap022f56f2015-12-04 14:05:39 -0500238 self._sdn_meters_info)
239 self._all_meters_info = {}
240 for service_meters in all_services_meters:
241 self._all_meters_info.update(dict([(meter_name, meter_info)
242 for meter_name, meter_info
243 in service_meters.items()]))
244
245 # Here will be the cached Meter objects, that will be reused for
246 # repeated listing.
247 self._cached_meters = {}
248
249 def list_all(self, only_meters=None, except_meters=None):
250 """Returns a list of meters based on the meters names.
251
252 :Parameters:
253 - `only_meters`: The list of meter names we want to show.
254 - `except_meters`: The list of meter names we don't want to show.
255 """
256
257 return self._list(only_meters=only_meters,
258 except_meters=except_meters)
259
260 def list_nova(self, except_meters=None):
261 """Returns a list of meters tied to nova.
262
263 :Parameters:
264 - `except_meters`: The list of meter names we don't want to show.
265 """
266
267 return self._list(only_meters=self._nova_meters_info.keys(),
268 except_meters=except_meters)
269
270 def list_neutron(self, except_meters=None):
271 """Returns a list of meters tied to neutron.
272
273 :Parameters:
274 - `except_meters`: The list of meter names we don't want to show.
275 """
276
277 return self._list(only_meters=self._neutron_meters_info.keys(),
278 except_meters=except_meters)
279
280 def list_glance(self, except_meters=None):
281 """Returns a list of meters tied to glance.
282
283 :Parameters:
284 - `except_meters`: The list of meter names we don't want to show.
285 """
286
287 return self._list(only_meters=self._glance_meters_info.keys(),
288 except_meters=except_meters)
289
290 def list_cinder(self, except_meters=None):
291 """Returns a list of meters tied to cinder.
292
293 :Parameters:
294 - `except_meters`: The list of meter names we don't want to show.
295 """
296
297 return self._list(only_meters=self._cinder_meters_info.keys(),
298 except_meters=except_meters)
299
300 def list_swift(self, except_meters=None):
301 """Returns a list of meters tied to swift.
302
303 :Parameters:
304 - `except_meters`: The list of meter names we don't want to show.
305 """
306
307 return self._list(only_meters=self._swift_meters_info.keys(),
308 except_meters=except_meters)
309
310 def list_kwapi(self, except_meters=None):
311 """Returns a list of meters tied to kwapi.
312
313 :Parameters:
314 - `except_meters`: The list of meter names we don't want to show.
315 """
316
317 return self._list(only_meters=self._kwapi_meters_info.keys(),
318 except_meters=except_meters)
319
320 def list_ipmi(self, except_meters=None):
321 """Returns a list of meters tied to ipmi
322
323 :Parameters:
324 - `except_meters`: The list of meter names we don't want to show
325 """
326
327 return self._list(only_meters=self._ipmi_meters_info.keys(),
328 except_meters=except_meters)
329
330 def list_vcpe(self, except_meters=None):
331 """Returns a list of meters tied to vcpe service
332
333 :Parameters:
334 - `except_meters`: The list of meter names we don't want to show
335 """
336
337 return self._list(only_meters=self._vcpe_meters_info.keys(),
338 except_meters=except_meters)
339
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -0500340 def list_volt(self, except_meters=None):
341 """Returns a list of meters tied to volt service
342
343 :Parameters:
344 - `except_meters`: The list of meter names we don't want to show
345 """
346
347 return self._list(only_meters=self._volt_meters_info.keys(),
348 except_meters=except_meters)
349
svavilap022f56f2015-12-04 14:05:39 -0500350 def list_sdn(self, except_meters=None):
351 """Returns a list of meters tied to sdn service
352
353 :Parameters:
354 - `except_meters`: The list of meter names we don't want to show
355 """
356
357 return self._list(only_meters=self._sdn_meters_info.keys(),
358 except_meters=except_meters)
359
360 def list_other_services(self, except_meters=None):
361 """Returns a list of meters tied to ipmi
362
363 :Parameters:
364 - `except_meters`: The list of meter names we don't want to show
365 """
366 other_service_meters = [m for m in self._ceilometer_meter_list
367 if m.name not in self._all_meters_info.keys()]
368 other_service_meters = diff_lists(other_service_meters, except_meters)
369
370 meters = []
371 for meter in other_service_meters:
372 self._cached_meters[meter.name] = meter
373 meters.append(meter)
374 return meters
375
376 def _list(self, only_meters=None, except_meters=None):
377 """Returns a list of meters based on the meters names.
378
379 :Parameters:
380 - `only_meters`: The list of meter names we want to show.
381 - `except_meters`: The list of meter names we don't want to show.
382 """
383
384 # Get all wanted meter names.
385 if only_meters:
386 meter_names = only_meters
387 else:
388 meter_names = [meter_name for meter_name
389 in self._all_meters_info.keys()]
390
391 meter_names = diff_lists(meter_names, except_meters)
392 # Collect meters for wanted meter names.
393 return self._get_meters(meter_names)
394
395 def _get_meters(self, meter_names):
396 """Obtain meters based on meter_names.
397
398 The meters that do not exist in Ceilometer meter list are left out.
399
400 :Parameters:
401 - `meter_names`: A list of meter names we want to fetch.
402 """
403
404 meters = []
405 for meter_name in meter_names:
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500406 meter_candidates = self._get_meter(meter_name)
407 if meter_candidates:
408 meters.extend(meter_candidates)
svavilap022f56f2015-12-04 14:05:39 -0500409 return meters
410
411 def _get_meter(self, meter_name):
412 """Obtains a meter.
413
414 Obtains meter either from cache or from Ceilometer meter list
415 joined with statically defined meter info like label and description.
416
417 :Parameters:
418 - `meter_name`: A meter name we want to fetch.
419 """
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500420 meter_candidates = self._cached_meters.get(meter_name, None)
421 if not meter_candidates:
svavilap022f56f2015-12-04 14:05:39 -0500422 meter_candidates = [m for m in self._ceilometer_meter_list
423 if m["name"] == meter_name]
424
425 if meter_candidates:
426 meter_info = self._all_meters_info.get(meter_name, None)
427 if meter_info:
428 label = meter_info["label"]
429 description = meter_info["description"]
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500430 meter_category = meter_info["type"]
svavilap022f56f2015-12-04 14:05:39 -0500431 else:
432 label = ""
433 description = ""
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500434 meter_category = "Other"
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500435 for meter in meter_candidates:
436 meter["label"] = label
437 meter["description"] = description
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500438 meter["category"] = meter_category
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500439 if meter["project_id"] in self.tenant_map.keys():
440 meter["slice"] = self.tenant_map[meter["project_id"]]["slice"]
441 meter["service"] = self.tenant_map[meter["project_id"]]["service"]
442 else:
443 meter["slice"] = meter["project_id"]
444 meter["service"] = "Other"
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -0500445 if meter["resource_id"] in self.resource_map.keys():
446 meter["resource_name"] = self.resource_map[meter["resource_id"]]
svavilap022f56f2015-12-04 14:05:39 -0500447
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500448 self._cached_meters[meter_name] = meter_candidates
svavilap022f56f2015-12-04 14:05:39 -0500449
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500450 return meter_candidates
svavilap022f56f2015-12-04 14:05:39 -0500451
452 def _get_nova_meters_info(self):
453 """Returns additional info for each meter.
454
455 That will be used for augmenting the Ceilometer meter.
456 """
457
458 # TODO(lsmola) Unless the Ceilometer will provide the information
459 # below, I need to define it as a static here. I will be joining this
460 # to info that I am able to obtain from Ceilometer meters, hopefully
461 # some day it will be supported all.
462 meters_info = datastructures.SortedDict([
463 ("instance", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500464 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500465 'label': '',
466 'description': _("Existence of instance"),
467 }),
468 ("instance:<type>", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500469 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500470 'label': '',
471 'description': _("Existence of instance <type> "
472 "(openstack types)"),
473 }),
474 ("memory", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500475 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500476 'label': '',
477 'description': _("Volume of RAM"),
478 }),
479 ("memory.usage", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500480 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500481 'label': '',
482 'description': _("Volume of RAM used"),
483 }),
484 ("cpu", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500485 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500486 'label': '',
487 'description': _("CPU time used"),
488 }),
489 ("cpu_util", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500490 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500491 'label': '',
492 'description': _("Average CPU utilization"),
493 }),
494 ("vcpus", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500495 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500496 'label': '',
497 'description': _("Number of VCPUs"),
498 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500499 ("disk.read.requests", {
500 'type': _("Nova"),
501 'label': '',
502 'description': _("Number of read requests"),
503 }),
504 ("disk.write.requests", {
505 'type': _("Nova"),
506 'label': '',
507 'description': _("Number of write requests"),
508 }),
509 ("disk.read.bytes", {
510 'type': _("Nova"),
511 'label': '',
512 'description': _("Volume of reads"),
513 }),
514 ("disk.write.bytes", {
515 'type': _("Nova"),
516 'label': '',
517 'description': _("Volume of writes"),
518 }),
519 ("disk.read.requests.rate", {
520 'type': _("Nova"),
521 'label': '',
522 'description': _("Average rate of read requests"),
523 }),
524 ("disk.write.requests.rate", {
525 'type': _("Nova"),
526 'label': '',
527 'description': _("Average rate of write requests"),
528 }),
529 ("disk.read.bytes.rate", {
530 'type': _("Nova"),
531 'label': '',
532 'description': _("Average rate of reads"),
533 }),
534 ("disk.write.bytes.rate", {
535 'type': _("Nova"),
536 'label': '',
537 'description': _("Average volume of writes"),
538 }),
539 ("disk.root.size", {
540 'type': _("Nova"),
541 'label': '',
542 'description': _("Size of root disk"),
543 }),
544 ("disk.ephemeral.size", {
545 'type': _("Nova"),
546 'label': '',
547 'description': _("Size of ephemeral disk"),
548 }),
549 ("network.incoming.bytes", {
550 'type': _("Nova"),
551 'label': '',
552 'description': _("Number of incoming bytes "
553 "on the network for a VM interface"),
554 }),
555 ("network.outgoing.bytes", {
556 'type': _("Nova"),
557 'label': '',
558 'description': _("Number of outgoing bytes "
559 "on the network for a VM interface"),
560 }),
561 ("network.incoming.packets", {
562 'type': _("Nova"),
563 'label': '',
564 'description': _("Number of incoming "
565 "packets for a VM interface"),
566 }),
567 ("network.outgoing.packets", {
568 'type': _("Nova"),
569 'label': '',
570 'description': _("Number of outgoing "
571 "packets for a VM interface"),
572 }),
svavilap022f56f2015-12-04 14:05:39 -0500573 ("network.incoming.bytes.rate", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500574 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500575 'label': '',
576 'description': _("Average rate per sec of incoming "
577 "bytes on a VM network interface"),
578 }),
579 ("network.outgoing.bytes.rate", {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500580 'type': _("Nova"),
svavilap022f56f2015-12-04 14:05:39 -0500581 'label': '',
582 'description': _("Average rate per sec of outgoing "
583 "bytes on a VM network interface"),
584 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500585 ("network.incoming.packets.rate", {
586 'type': _("Nova"),
587 'label': '',
588 'description': _("Average rate per sec of incoming "
589 "packets on a VM network interface"),
590 }),
591 ("network.outgoing.packets.rate", {
592 'type': _("Nova"),
593 'label': '',
594 'description': _("Average rate per sec of outgoing "
595 "packets on a VM network interface"),
596 }),
svavilap022f56f2015-12-04 14:05:39 -0500597 ])
598 # Adding flavor based meters into meters_info dict
599 # TODO(lsmola) this kind of meter will be probably deprecated
600 # https://bugs.launchpad.net/ceilometer/+bug/1208365 . Delete it then.
601 #for flavor in get_flavor_names(self._request):
602 # name = 'instance:%s' % flavor
603 # meters_info[name] = dict(meters_info["instance:<type>"])
604
605 # meters_info[name]['description'] = (
606 # _('Duration of instance type %s (openstack flavor)') %
607 # flavor)
608
609 # TODO(lsmola) allow to set specific in local_settings. For all meters
610 # because users can have their own agents and meters.
611 return meters_info
612
613 def _get_neutron_meters_info(self):
614 """Returns additional info for each meter.
615
616 That will be used for augmenting the Ceilometer meter.
617 """
618
619 # TODO(lsmola) Unless the Ceilometer will provide the information
620 # below, I need to define it as a static here. I will be joining this
621 # to info that I am able to obtain from Ceilometer meters, hopefully
622 # some day it will be supported all.
623 return datastructures.SortedDict([
624 ('network', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500625 'type': _("Neutron"),
svavilap022f56f2015-12-04 14:05:39 -0500626 'label': '',
627 'description': _("Existence of network"),
628 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500629 ('network.create', {
630 'type': _("Neutron"),
631 'label': '',
632 'description': _("Creation requests for this network"),
633 }),
634 ('network.update', {
635 'type': _("Neutron"),
636 'label': '',
637 'description': _("Update requests for this network"),
638 }),
svavilap022f56f2015-12-04 14:05:39 -0500639 ('subnet', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500640 'type': _("Neutron"),
svavilap022f56f2015-12-04 14:05:39 -0500641 'label': '',
642 'description': _("Existence of subnet"),
643 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500644 ('subnet.create', {
645 'type': _("Neutron"),
646 'label': '',
647 'description': _("Creation requests for this subnet"),
648 }),
649 ('subnet.update', {
650 'type': _("Neutron"),
651 'label': '',
652 'description': _("Update requests for this subnet"),
653 }),
svavilap022f56f2015-12-04 14:05:39 -0500654 ('port', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500655 'type': _("Neutron"),
svavilap022f56f2015-12-04 14:05:39 -0500656 'label': '',
657 'description': _("Existence of port"),
658 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500659 ('port.create', {
660 'type': _("Neutron"),
661 'label': '',
662 'description': _("Creation requests for this port"),
663 }),
664 ('port.update', {
665 'type': _("Neutron"),
666 'label': '',
667 'description': _("Update requests for this port"),
668 }),
669 ('router', {
670 'type': _("Neutron"),
671 'label': '',
672 'description': _("Existence of router"),
673 }),
674 ('router.create', {
675 'type': _("Neutron"),
676 'label': '',
677 'description': _("Creation requests for this router"),
678 }),
679 ('router.update', {
680 'type': _("Neutron"),
681 'label': '',
682 'description': _("Update requests for this router"),
683 }),
svavilap022f56f2015-12-04 14:05:39 -0500684 ('ip.floating', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500685 'type': _("Neutron"),
svavilap022f56f2015-12-04 14:05:39 -0500686 'label': '',
687 'description': _("Existence of floating ip"),
688 }),
Srikanth Vavilapalli6ff55982016-01-22 14:35:50 -0500689 ('ip.floating.create', {
690 'type': _("Neutron"),
691 'label': '',
692 'description': _("Creation requests for this floating ip"),
693 }),
694 ('ip.floating.update', {
695 'type': _("Neutron"),
696 'label': '',
697 'description': _("Update requests for this floating ip"),
698 }),
svavilap022f56f2015-12-04 14:05:39 -0500699 ])
700
701 def _get_glance_meters_info(self):
702 """Returns additional info for each meter.
703
704 That will be used for augmenting the Ceilometer meter.
705 """
706
707 # TODO(lsmola) Unless the Ceilometer will provide the information
708 # below, I need to define it as a static here. I will be joining this
709 # to info that I am able to obtain from Ceilometer meters, hopefully
710 # some day it will be supported all.
711 return datastructures.SortedDict([
712 ('image', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500713 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500714 'label': '',
715 'description': _("Image existence check"),
716 }),
717 ('image.size', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500718 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500719 'label': '',
720 'description': _("Uploaded image size"),
721 }),
722 ('image.update', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500723 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500724 'label': '',
725 'description': _("Number of image updates"),
726 }),
727 ('image.upload', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500728 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500729 'label': '',
730 'description': _("Number of image uploads"),
731 }),
732 ('image.delete', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500733 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500734 'label': '',
735 'description': _("Number of image deletions"),
736 }),
737 ('image.download', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500738 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500739 'label': '',
740 'description': _("Image is downloaded"),
741 }),
742 ('image.serve', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500743 'type': _("Glance"),
svavilap022f56f2015-12-04 14:05:39 -0500744 'label': '',
745 'description': _("Image is served out"),
746 }),
747 ])
748
749 def _get_cinder_meters_info(self):
750 """Returns additional info for each meter.
751
752 That will be used for augmenting the Ceilometer meter.
753 """
754
755 # TODO(lsmola) Unless the Ceilometer will provide the information
756 # below, I need to define it as a static here. I will be joining this
757 # to info that I am able to obtain from Ceilometer meters, hopefully
758 # some day it will be supported all.
759 return datastructures.SortedDict([
760 ('volume', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500761 'type': _("Cinder"),
svavilap022f56f2015-12-04 14:05:39 -0500762 'label': '',
763 'description': _("Existence of volume"),
764 }),
765 ('volume.size', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500766 'type': _("Cinder"),
svavilap022f56f2015-12-04 14:05:39 -0500767 'label': '',
768 'description': _("Size of volume"),
769 }),
770 ])
771
772 def _get_swift_meters_info(self):
773 """Returns additional info for each meter.
774
775 That will be used for augmenting the Ceilometer meter.
776 """
777
778 # TODO(lsmola) Unless the Ceilometer will provide the information
779 # below, I need to define it as a static here. I will be joining this
780 # to info that I am able to obtain from Ceilometer meters, hopefully
781 # some day it will be supported all.
782 return datastructures.SortedDict([
783 ('storage.objects', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500784 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500785 'label': '',
786 'description': _("Number of objects"),
787 }),
788 ('storage.objects.size', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500789 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500790 'label': '',
791 'description': _("Total size of stored objects"),
792 }),
793 ('storage.objects.containers', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500794 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500795 'label': '',
796 'description': _("Number of containers"),
797 }),
798 ('storage.objects.incoming.bytes', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500799 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500800 'label': '',
801 'description': _("Number of incoming bytes"),
802 }),
803 ('storage.objects.outgoing.bytes', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500804 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500805 'label': '',
806 'description': _("Number of outgoing bytes"),
807 }),
808 ('storage.api.request', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500809 'type': _("Swift"),
svavilap022f56f2015-12-04 14:05:39 -0500810 'label': '',
811 'description': _("Number of API requests against swift"),
812 }),
813 ])
814
815 def _get_kwapi_meters_info(self):
816 """Returns additional info for each meter.
817
818 That will be used for augmenting the Ceilometer meter.
819 """
820
821 # TODO(lsmola) Unless the Ceilometer will provide the information
822 # below, I need to define it as a static here. I will be joining this
823 # to info that I am able to obtain from Ceilometer meters, hopefully
824 # some day it will be supported all.
825 return datastructures.SortedDict([
826 ('energy', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500827 'type': _("Kwapi"),
svavilap022f56f2015-12-04 14:05:39 -0500828 'label': '',
829 'description': _("Amount of energy"),
830 }),
831 ('power', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500832 'type': _("Kwapi"),
svavilap022f56f2015-12-04 14:05:39 -0500833 'label': '',
834 'description': _("Power consumption"),
835 }),
836 ])
837
838 def _get_ipmi_meters_info(self):
839 """Returns additional info for each meter
840
841 That will be used for augmenting the Ceilometer meter
842 """
843
844 # TODO(lsmola) Unless the Ceilometer will provide the information
845 # below, I need to define it as a static here. I will be joining this
846 # to info that I am able to obtain from Ceilometer meters, hopefully
847 # some day it will be supported all.
848 return datastructures.SortedDict([
849 ('hardware.ipmi.node.power', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500850 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500851 'label': '',
852 'description': _("System Current Power"),
853 }),
854 ('hardware.ipmi.fan', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500855 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500856 'label': '',
857 'description': _("Fan RPM"),
858 }),
859 ('hardware.ipmi.temperature', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500860 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500861 'label': '',
862 'description': _("Sensor Temperature Reading"),
863 }),
864 ('hardware.ipmi.current', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500865 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500866 'label': '',
867 'description': _("Sensor Current Reading"),
868 }),
869 ('hardware.ipmi.voltage', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500870 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500871 'label': '',
872 'description': _("Sensor Voltage Reading"),
873 }),
874 ('hardware.ipmi.node.inlet_temperature', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500875 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500876 'label': '',
877 'description': _("System Inlet Temperature Reading"),
878 }),
879 ('hardware.ipmi.node.outlet_temperature', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500880 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500881 'label': '',
882 'description': _("System Outlet Temperature Reading"),
883 }),
884 ('hardware.ipmi.node.airflow', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500885 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500886 'label': '',
887 'description': _("System Airflow Reading"),
888 }),
889 ('hardware.ipmi.node.cups', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500890 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500891 'label': '',
892 'description': _("System CUPS Reading"),
893 }),
894 ('hardware.ipmi.node.cpu_util', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500895 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500896 'label': '',
897 'description': _("System CPU Utility Reading"),
898 }),
899 ('hardware.ipmi.node.mem_util', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500900 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500901 'label': '',
902 'description': _("System Memory Utility Reading"),
903 }),
904 ('hardware.ipmi.node.io_util', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500905 'type': _("IPMI"),
svavilap022f56f2015-12-04 14:05:39 -0500906 'label': '',
907 'description': _("System IO Utility Reading"),
908 }),
909 ])
910
911 def _get_vcpe_meters_info(self):
912 """Returns additional info for each meter
913
914 That will be used for augmenting the Ceilometer meter
915 """
916
917 # TODO(lsmola) Unless the Ceilometer will provide the information
918 # below, I need to define it as a static here. I will be joining this
919 # to info that I am able to obtain from Ceilometer meters, hopefully
920 # some day it will be supported all.
921 return datastructures.SortedDict([
922 ('vcpe', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500923 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500924 'label': '',
925 'description': _("Existence of vcpe instance"),
926 }),
927 ('vcpe.dns.cache.size', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500928 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500929 'label': '',
930 'description': _("Number of entries in DNS cache"),
931 }),
932 ('vcpe.dns.total_instered_entries', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500933 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500934 'label': '',
935 'description': _("Total number of inserted entries into the cache"),
936 }),
937 ('vcpe.dns.replaced_unexpired_entries', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500938 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500939 'label': '',
940 'description': _("Unexpired entries that were thrown out of cache"),
941 }),
942 ('vcpe.dns.queries_answered_locally', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500943 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500944 'label': '',
945 'description': _("Number of cache hits"),
946 }),
947 ('vcpe.dns.queries_forwarded', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500948 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500949 'label': '',
950 'description': _("Number of cache misses"),
951 }),
952 ('vcpe.dns.server.queries_sent', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500953 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500954 'label': '',
955 'description': _("For each upstream server, the number of queries sent"),
956 }),
957 ('vcpe.dns.server.queries_failed', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -0500958 'type': _("VCPE"),
svavilap022f56f2015-12-04 14:05:39 -0500959 'label': '',
960 'description': _("For each upstream server, the number of queries failed"),
961 }),
962 ])
963
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -0500964 def _get_volt_meters_info(self):
965 """Returns additional info for each meter
966
967 That will be used for augmenting the Ceilometer meter
968 """
969
970 # TODO(lsmola) Unless the Ceilometer will provide the information
971 # below, I need to define it as a static here. I will be joining this
972 # to info that I am able to obtain from Ceilometer meters, hopefully
973 # some day it will be supported all.
974 return datastructures.SortedDict([
975 ('volt.device', {
976 'type': _("VOLT"),
977 'label': '',
978 'description': _("Existence of olt device"),
979 }),
980 ('volt.device.disconnect', {
981 'type': _("VOLT"),
982 'label': '',
983 'description': _("Olt device disconnected"),
984 }),
985 ('volt.device.subscriber', {
986 'type': _("VOLT"),
987 'label': '',
988 'description': _("Existence of olt subscriber"),
989 }),
990 ('volt.device.subscriber.unregister', {
991 'type': _("VOLT"),
992 'label': '',
993 'description': _("Olt subscriber unregistered"),
994 }),
995 ])
996
svavilap022f56f2015-12-04 14:05:39 -0500997 def _get_sdn_meters_info(self):
998 """Returns additional info for each meter
999
1000 That will be used for augmenting the Ceilometer meter
1001 """
1002
1003 # TODO(lsmola) Unless the Ceilometer will provide the information
1004 # below, I need to define it as a static here. I will be joining this
1005 # to info that I am able to obtain from Ceilometer meters, hopefully
1006 # some day it will be supported all.
1007 return datastructures.SortedDict([
1008 ('switch', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001009 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001010 'label': '',
1011 'description': _("Existence of switch"),
1012 }),
1013 ('switch.port', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001014 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001015 'label': '',
1016 'description': _("Existence of port"),
1017 }),
1018 ('switch.port.receive.packets', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001019 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001020 'label': '',
1021 'description': _("Packets received on port"),
1022 }),
1023 ('switch.port.transmit.packets', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001024 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001025 'label': '',
1026 'description': _("Packets transmitted on port"),
1027 }),
1028 ('switch.port.receive.drops', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001029 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001030 'label': '',
1031 'description': _("Drops received on port"),
1032 }),
1033 ('switch.port.transmit.drops', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001034 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001035 'label': '',
1036 'description': _("Drops transmitted on port"),
1037 }),
1038 ('switch.port.receive.errors', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001039 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001040 'label': '',
1041 'description': _("Errors received on port"),
1042 }),
1043 ('switch.port.transmit.errors', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001044 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001045 'label': '',
1046 'description': _("Errors transmitted on port"),
1047 }),
1048 ('switch.flow', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001049 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001050 'label': '',
1051 'description': _("Duration of flow"),
1052 }),
1053 ('switch.flow.packets', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001054 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001055 'label': '',
1056 'description': _("Packets received"),
1057 }),
1058 ('switch.table', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001059 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001060 'label': '',
1061 'description': _("Existence of table"),
1062 }),
1063 ('switch.table.active.entries', {
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001064 'type': _("SDN"),
svavilap022f56f2015-12-04 14:05:39 -05001065 'label': '',
1066 'description': _("Active entries in table"),
1067 }),
1068 ])
1069
1070def make_query(user_id=None, tenant_id=None, resource_id=None,
1071 user_ids=None, tenant_ids=None, resource_ids=None):
1072 """Returns query built from given parameters.
1073
1074 This query can be then used for querying resources, meters and
1075 statistics.
1076
1077 :Parameters:
1078 - `user_id`: user_id, has a priority over list of ids
1079 - `tenant_id`: tenant_id, has a priority over list of ids
1080 - `resource_id`: resource_id, has a priority over list of ids
1081 - `user_ids`: list of user_ids
1082 - `tenant_ids`: list of tenant_ids
1083 - `resource_ids`: list of resource_ids
1084 """
1085 user_ids = user_ids or []
1086 tenant_ids = tenant_ids or []
1087 resource_ids = resource_ids or []
1088
1089 query = []
1090 if user_id:
1091 user_ids = [user_id]
1092 for u_id in user_ids:
1093 query.append({"field": "user_id", "op": "eq", "value": u_id})
1094
1095 if tenant_id:
1096 tenant_ids = [tenant_id]
1097 for t_id in tenant_ids:
1098 query.append({"field": "project_id", "op": "eq", "value": t_id})
1099
1100 if resource_id:
1101 resource_ids = [resource_id]
1102 for r_id in resource_ids:
1103 query.append({"field": "resource_id", "op": "eq", "value": r_id})
1104
1105 return query
1106
1107def calc_date_args(date_from, date_to, date_options):
1108 # TODO(lsmola) all timestamps should probably work with
1109 # current timezone. And also show the current timezone in chart.
1110 if date_options == "other":
1111 try:
1112 if date_from:
1113 date_from = pytz.utc.localize(
1114 datetime.datetime.strptime(str(date_from), "%Y-%m-%d"))
1115 else:
1116 # TODO(lsmola) there should be probably the date
1117 # of the first sample as default, so it correctly
1118 # counts the time window. Though I need ordering
1119 # and limit of samples to obtain that.
1120 pass
1121 if date_to:
1122 date_to = pytz.utc.localize(
1123 datetime.datetime.strptime(str(date_to), "%Y-%m-%d"))
1124 # It returns the beginning of the day, I want the end of
1125 # the day, so I add one day without a second.
1126 date_to = (date_to + datetime.timedelta(days=1) -
1127 datetime.timedelta(seconds=1))
1128 else:
1129 date_to = timezone.now()
1130 except Exception:
1131 raise ValueError(_("The dates haven't been recognized"))
1132 else:
1133 try:
1134 date_to = timezone.now()
1135 date_from = date_to - datetime.timedelta(days=float(date_options))
1136 except Exception as e:
1137 raise e
1138 #raise ValueError(_("The time delta must be a number representing "
1139 # "the time span in days"))
1140 return date_from, date_to
1141
1142class MetersList(APIView):
1143 method_kind = "list"
1144 method_name = "meters"
1145
1146 def get(self, request, format=None):
1147 if (not request.user.is_authenticated()):
1148 raise PermissionDenied("You must be authenticated in order to use this API")
1149 tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
1150 if (not tenant_ceilometer_url):
1151 raise XOSMissingField("Tenant ceilometer URL is missing")
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001152
1153 tenant_id = request.QUERY_PARAMS.get('tenant', None)
1154 resource_id = request.QUERY_PARAMS.get('resource', None)
1155
1156 query = []
1157 if tenant_id:
1158 query.extend(make_query(tenant_id=tenant_id))
1159 if resource_id:
1160 query.extend(make_query(resource_id=resource_id))
1161
svavilap022f56f2015-12-04 14:05:39 -05001162 tenant_map = getTenantControllerTenantMap(request.user)
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001163 resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url, query=query)
1164 meters = Meters(request, ceilometer_url=tenant_ceilometer_url, query=query, tenant_map=tenant_map, resource_map=resource_map)
svavilap022f56f2015-12-04 14:05:39 -05001165 services = {
1166 _('Nova'): meters.list_nova(),
1167 _('Neutron'): meters.list_neutron(),
1168 _('VCPE'): meters.list_vcpe(),
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -05001169 _('VOLT'): meters.list_volt(),
svavilap022f56f2015-12-04 14:05:39 -05001170 _('SDN'): meters.list_sdn(),
1171 }
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001172 meters = []
1173 for service,smeters in services.iteritems():
1174 meters.extend(smeters)
1175 return Response(meters)
svavilap022f56f2015-12-04 14:05:39 -05001176
1177class MeterStatisticsList(APIView):
1178 method_kind = "list"
1179 method_name = "meterstatistics"
1180
1181 def get(self, request, format=None):
1182 if (not request.user.is_authenticated()):
1183 raise PermissionDenied("You must be authenticated in order to use this API")
1184 tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
1185 if (not tenant_ceilometer_url):
1186 raise XOSMissingField("Tenant ceilometer URL is missing")
1187 tenant_map = getTenantControllerTenantMap(request.user)
1188
1189 date_options = request.QUERY_PARAMS.get('period', 1)
1190 date_from = request.QUERY_PARAMS.get('date_from', '')
1191 date_to = request.QUERY_PARAMS.get('date_to', '')
1192
1193 try:
1194 date_from, date_to = calc_date_args(date_from,
1195 date_to,
1196 date_options)
1197 except Exception as e:
1198 raise e
1199
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001200 additional_query = []
1201 if date_from:
1202 additional_query.append({'field': 'timestamp',
1203 'op': 'ge',
1204 'value': date_from})
1205 if date_to:
1206 additional_query.append({'field': 'timestamp',
1207 'op': 'le',
1208 'value': date_to})
1209
1210 meter_name = request.QUERY_PARAMS.get('meter', None)
1211 tenant_id = request.QUERY_PARAMS.get('tenant', None)
1212 resource_id = request.QUERY_PARAMS.get('resource', None)
1213
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001214 query = []
1215 if tenant_id:
1216 query.extend(make_query(tenant_id=tenant_id))
1217 if resource_id:
1218 query.extend(make_query(resource_id=resource_id))
1219
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001220 if meter_name:
1221 #Statistics query for one meter
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001222 if additional_query:
1223 query = query + additional_query
1224 statistics = statistic_list(request, meter_name,
1225 ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
1226 statistic = statistics[-1]
1227 row = {"name": 'none',
1228 "meter": meter_name,
1229 "time": statistic["period_end"],
1230 "value": statistic["avg"]}
1231 return Response(row)
1232
1233 #Statistics query for all meter
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001234 resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url, query=query)
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001235 meters = Meters(request, ceilometer_url=tenant_ceilometer_url, query=query, tenant_map=tenant_map, resource_map=resource_map)
svavilap022f56f2015-12-04 14:05:39 -05001236 services = {
1237 _('Nova'): meters.list_nova(),
1238 _('Neutron'): meters.list_neutron(),
1239 _('VCPE'): meters.list_vcpe(),
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -05001240 _('VOLT'): meters.list_volt(),
svavilap022f56f2015-12-04 14:05:39 -05001241 _('SDN'): meters.list_sdn(),
1242 }
1243 report_rows = []
1244 for service,meters in services.items():
1245 for meter in meters:
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001246 query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
1247 if additional_query:
1248 query = query + additional_query
svavilap022f56f2015-12-04 14:05:39 -05001249 statistics = statistic_list(request, meter["name"],
1250 ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
Srikanth Vavilapalli80425702015-12-04 17:56:53 -05001251 if not statistics:
1252 continue
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001253 statistic = statistics[-1]
svavilap022f56f2015-12-04 14:05:39 -05001254 row = {"name": 'none',
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001255 "slice": meter["slice"],
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001256 "project_id": meter["project_id"],
Srikanth Vavilapalli0bc65b32015-12-08 19:06:22 -05001257 "service": meter["service"],
1258 "resource_id": meter["resource_id"],
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001259 "resource_name": meter["resource_name"],
svavilap022f56f2015-12-04 14:05:39 -05001260 "meter": meter["name"],
1261 "description": meter["description"],
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001262 "category": service,
svavilap022f56f2015-12-04 14:05:39 -05001263 "time": statistic["period_end"],
1264 "value": statistic["avg"],
1265 "unit": meter["unit"]}
1266 report_rows.append(row)
1267
1268 return Response(report_rows)
1269
1270
1271class MeterSamplesList(APIView):
1272 method_kind = "list"
1273 method_name = "metersamples"
1274
1275 def get(self, request, format=None):
1276 if (not request.user.is_authenticated()):
1277 raise PermissionDenied("You must be authenticated in order to use this API")
1278 tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
1279 if (not tenant_ceilometer_url):
1280 raise XOSMissingField("Tenant ceilometer URL is missing")
1281 meter_name = request.QUERY_PARAMS.get('meter', None)
svavilap022f56f2015-12-04 14:05:39 -05001282 if not meter_name:
1283 raise XOSMissingField("Meter name in query params is missing")
Srikanth Vavilapalli80425702015-12-04 17:56:53 -05001284 limit = request.QUERY_PARAMS.get('limit', 10)
1285 tenant_id = request.QUERY_PARAMS.get('tenant', None)
1286 resource_id = request.QUERY_PARAMS.get('resource', None)
svavilap022f56f2015-12-04 14:05:39 -05001287 query = []
1288 if tenant_id:
Srikanth Vavilapalli80425702015-12-04 17:56:53 -05001289 query.extend(make_query(tenant_id=tenant_id))
1290 if resource_id:
1291 query.extend(make_query(resource_id=resource_id))
svavilap022f56f2015-12-04 14:05:39 -05001292 query.append({"field": "meter", "op": "eq", "value": meter_name})
1293 samples = sample_list(request, meter_name,
Srikanth Vavilapalli80425702015-12-04 17:56:53 -05001294 ceilometer_url=tenant_ceilometer_url, query=query, limit=limit)
Srikanth Vavilapalli73afe292015-12-14 17:35:04 -05001295 if samples:
1296 tenant_map = getTenantControllerTenantMap(request.user)
1297 resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url)
1298 for sample in samples:
1299 if sample["project_id"] in tenant_map.keys():
1300 sample["slice"] = tenant_map[sample["project_id"]]["slice"]
1301 else:
1302 sample["slice"] = sample["project_id"]
1303 if sample["resource_id"] in resource_map.keys():
1304 sample["resource_name"] = resource_map[sample["resource_id"]]
1305 else:
1306 sample["resource_name"] = sample["resource_id"]
svavilap022f56f2015-12-04 14:05:39 -05001307 return Response(samples)
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001308
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001309class XOSSliceServiceList(APIView):
1310 method_kind = "list"
1311 method_name = "xos-slice-service-mapping"
1312
1313 def get(self, request, format=None):
1314 if (not request.user.is_authenticated()):
1315 raise PermissionDenied("You must be authenticated in order to use this API")
1316 tenant_map = getTenantControllerTenantMap(request.user)
1317 service_map={}
1318 for k,v in tenant_map.iteritems():
1319 if not (v['service'] in service_map.keys()):
1320 service_map[v['service']] = {}
1321 service_map[v['service']]['service'] = v['service']
1322 service_map[v['service']]['slices'] = []
Srikanth Vavilapalli5bc1eb12016-02-07 14:18:51 -05001323 slice_details = {'slice':v['slice'], 'project_id':k}
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001324 service_map[v['service']]['slices'].append(slice_details)
1325 return Response(service_map.values())
1326
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001327class XOSInstanceStatisticsList(APIView):
1328 method_kind = "list"
1329 method_name = "xos-instance-statistics"
1330
1331 def get(self, request, format=None):
1332 if (not request.user.is_authenticated()):
1333 raise PermissionDenied("You must be authenticated in order to use this API")
1334 tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
1335 if (not tenant_ceilometer_url):
1336 raise XOSMissingField("Tenant ceilometer URL is missing")
1337 instance_uuid = request.QUERY_PARAMS.get('instance-uuid', None)
1338 if not instance_uuid:
1339 raise XOSMissingField("Instance UUID in query params is missing")
1340 if not Instance.objects.filter(instance_uuid=instance_uuid):
1341 raise XOSMissingField("XOS Instance object is missing for this uuid")
1342 xos_instance = Instance.objects.filter(instance_uuid=instance_uuid)[0]
1343 tenant_map = getTenantControllerTenantMap(request.user, xos_instance.slice)
1344 tenant_id = tenant_map.keys()[0]
1345 resource_ids = []
1346 resource_ids.append(instance_uuid)
1347 for p in xos_instance.ports.all():
1348 #neutron port resource id is represented in ceilometer as "nova instance-name"+"-"+"nova instance-id"+"-"+"tap"+first 11 characters of port-id
1349 resource_ids.append(xos_instance.instance_id+"-"+instance_uuid+"-tap"+p.port_id[:11])
1350
1351 date_options = request.QUERY_PARAMS.get('period', 1)
1352 date_from = request.QUERY_PARAMS.get('date_from', '')
1353 date_to = request.QUERY_PARAMS.get('date_to', '')
1354
1355 try:
1356 date_from, date_to = calc_date_args(date_from,
1357 date_to,
1358 date_options)
1359 except Exception as e:
1360 raise e
1361
1362 additional_query = []
1363 if date_from:
1364 additional_query.append({'field': 'timestamp',
1365 'op': 'ge',
1366 'value': date_from})
1367 if date_to:
1368 additional_query.append({'field': 'timestamp',
1369 'op': 'le',
1370 'value': date_to})
1371
1372 report_rows = []
1373 for resource_id in resource_ids:
1374 query = []
1375 if tenant_id:
1376 query.extend(make_query(tenant_id=tenant_id))
1377 if resource_id:
1378 query.extend(make_query(resource_id=resource_id))
1379
1380 #Statistics query for all meter
1381 resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url, query=query)
1382 meters = Meters(request, ceilometer_url=tenant_ceilometer_url, query=query, tenant_map=tenant_map, resource_map=resource_map)
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001383 exclude_nova_meters_info = [ "instance", "instance:<type>", "disk.read.requests", "disk.write.requests",
1384 "disk.read.bytes", "disk.write.bytes", "disk.read.requests.rate", "disk.write.requests.rate", "disk.read.bytes.rate",
1385 "disk.write.bytes.rate", "disk.root.size", "disk.ephemeral.size"]
1386 exclude_neutron_meters_info = [ 'network.create', 'network.update', 'subnet.create',
1387 'subnet.update', 'port.create', 'port.update', 'router.create', 'router.update',
1388 'ip.floating.create', 'ip.floating.update']
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001389 services = {
Srikanth Vavilapalli86e259f2016-02-03 16:37:31 -05001390 _('Nova'): meters.list_nova(except_meters=exclude_nova_meters_info),
1391 _('Neutron'): meters.list_neutron(except_meters=exclude_neutron_meters_info),
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001392 _('VCPE'): meters.list_vcpe(),
Srikanth Vavilapalli99073f82016-02-11 15:40:07 -05001393 _('VOLT'): meters.list_volt(),
Srikanth Vavilapalli2b2099c2016-02-01 18:01:56 -05001394 _('SDN'): meters.list_sdn(),
1395 }
1396 for service,meters in services.items():
1397 for meter in meters:
1398 query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
1399 if additional_query:
1400 query = query + additional_query
1401 statistics = statistic_list(request, meter["name"],
1402 ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
1403 if not statistics:
1404 continue
1405 statistic = statistics[-1]
1406 row = {"name": 'none',
1407 "slice": meter["slice"],
1408 "project_id": meter["project_id"],
1409 "service": meter["service"],
1410 "resource_id": meter["resource_id"],
1411 "resource_name": meter["resource_name"],
1412 "meter": meter["name"],
1413 "description": meter["description"],
1414 "category": service,
1415 "time": statistic["period_end"],
1416 "value": statistic["avg"],
1417 "unit": meter["unit"]}
1418 report_rows.append(row)
1419
1420 return Response(report_rows)
1421
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001422class ServiceAdjustScale(APIView):
1423 method_kind = "list"
1424 method_name = "serviceadjustscale"
1425
1426 def get(self, request, format=None):
Srikanth Vavilapalli73afe292015-12-14 17:35:04 -05001427 if (not request.user.is_authenticated()) or (not request.user.is_admin):
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001428 raise PermissionDenied("You must be authenticated admin user in order to use this API")
1429 service = request.QUERY_PARAMS.get('service', None)
1430 slice_hint = request.QUERY_PARAMS.get('slice_hint', None)
1431 scale = request.QUERY_PARAMS.get('scale', None)
1432 if not service or not slice_hint or not scale:
1433 raise XOSMissingField("Mandatory fields missing")
1434 services = Service.select_by_user(request.user)
1435 logger.info('SRIKANTH: Services for this user %(services)s' % {'services':services})
1436 if not services or (not services.get(name=service)):
1437 raise XOSMissingField("Service not found")
1438 service = services.get(name=service)
Srikanth Vavilapalli73afe292015-12-14 17:35:04 -05001439 service.adjust_scale(slice_hint, int(scale))
Srikanth Vavilapalli1ea11fc2015-12-14 00:52:57 -05001440 return Response("Success")