blob: ff5dd140d60fbc33865191a25c170220b4d76c01 [file] [log] [blame]
Mykyta Karpinfa53b302018-06-13 14:52:16 +03001import logging
2import os_client_config
Pavlo Shchelokovskyy27158b02019-07-24 22:11:33 +03003import time
Mykyta Karpinfa53b302018-06-13 14:52:16 +03004from uuid import UUID
5
6log = logging.getLogger(__name__)
7
8
9class GnocchiException(Exception):
10
11 _msg = "Gnocchi module exception occured."
12
13 def __init__(self, message=None, **kwargs):
14 super(GnocchiException, self).__init__(message or self._msg)
15
16
17class NoGnocchiEndpoint(GnocchiException):
18 _msg = "Gnocchi endpoint not found in keystone catalog."
19
20
21class NoAuthPluginConfigured(GnocchiException):
22 _msg = ("You are using keystoneauth auth plugin that does not support "
23 "fetching endpoint list from token (noauth or admin_token).")
24
25
26class NoCredentials(GnocchiException):
27 _msg = "Please provide cloud name present in clouds.yaml."
28
29
30class ResourceNotFound(GnocchiException):
31 _msg = "Uniq resource: {resource} with name: {name} not found."
32
33 def __init__(self, resource, name, **kwargs):
34 super(GnocchiException, self).__init__(
35 self._msg.format(resource=resource, name=name))
36
37
38class MultipleResourcesFound(GnocchiException):
39 _msg = "Multiple resource: {resource} with name: {name} found."
40
41 def __init__(self, resource, name, **kwargs):
42 super(GnocchiException, self).__init__(
43 self._msg.format(resource=resource, name=name))
44
45
46def get_raw_client(cloud_name):
47 service_type = 'metric'
48 config = os_client_config.OpenStackConfig()
49 cloud = config.get_one_cloud(cloud_name)
Mykyta Karpinfbefb702018-07-10 16:28:22 +030050 api_version = '1'
51 try:
52 # NOTE(pas-ha) for Queens and later,
53 # 'version' kwarg in absent for Pike and older
54 adapter = cloud.get_session_client(service_type, version=api_version)
55 except TypeError:
56 adapter = cloud.get_session_client(service_type)
57 adapter.version = api_version
Mykyta Karpinfa53b302018-06-13 14:52:16 +030058 try:
59 access_info = adapter.session.auth.get_access(adapter.session)
60 endpoints = access_info.service_catalog.get_endpoints()
61 except (AttributeError, ValueError) as exc:
62 log.exception('%s' % exc)
63 e = NoAuthPluginConfigured()
64 log.exception('%s' % e)
65 raise e
66 if service_type not in endpoints:
67 if not service_type:
68 e = NoGnocchiEndpoint()
69 log.error('%s' % e)
70 raise e
71 return adapter
72
73
74def send(method):
75 def wrap(func):
76 def wrapped_f(*args, **kwargs):
Pavlo Shchelokovskyy27158b02019-07-24 22:11:33 +030077 connect_retries = 30
78 connect_retry_delay = 1
Mykyta Karpinfa53b302018-06-13 14:52:16 +030079 cloud_name = kwargs.pop('cloud_name')
80 if not cloud_name:
81 e = NoCredentials()
82 log.error('%s' % e)
83 raise e
84 adapter = get_raw_client(cloud_name)
85 # Remove salt internal kwargs
86 kwarg_keys = list(kwargs.keys())
87 for k in kwarg_keys:
88 if k.startswith('__'):
89 kwargs.pop(k)
90 url, request_kwargs = func(*args, **kwargs)
Pavlo Shchelokovskyy27158b02019-07-24 22:11:33 +030091 response = None
92 for i in range(connect_retries):
93 try:
94 response = getattr(adapter, method)(
95 url, connect_retries=connect_retries,
96 **request_kwargs)
97 except Exception as e:
98 if not hasattr(e, 'http_status') or (
99 e.http_status >= 500 or e.http_status == 0):
100 msg = ("Got retriable exception when contacting "
101 "Gnocchi API. Sleeping for %s seconds. "
102 "Attepmpts %s of %s")
103 log.error(msg % (connect_retry_delay, i,
104 connect_retries))
105 time.sleep(connect_retry_delay)
106 continue
107 else:
108 raise
109 break
Vasyl Saienko8a05e922019-07-30 16:48:39 +0300110 try:
111 resp = response.json()
112 except ValueError:
113 resp = response.content
114 return resp
Mykyta Karpinfa53b302018-06-13 14:52:16 +0300115 return wrapped_f
116 return wrap
117
118
119def _check_uuid(val):
120 try:
121 return str(UUID(val)).replace('-', '') == val.replace('-', '')
122 except (TypeError, ValueError, AttributeError):
123 return False
124
125
126def get_by_name_or_uuid(resource_list, resp_key):
127 def wrap(func):
128 def wrapped_f(*args, **kwargs):
129 if 'name' in kwargs:
130 ref = kwargs.pop('name', None)
131 start_arg = 0
132 else:
133 start_arg = 1
134 ref = args[0]
135 if _check_uuid(ref):
136 uuid = ref
137 else:
138 # Then we have name not uuid
139 cloud_name = kwargs['cloud_name']
140 resp = resource_list(
141 name=ref, cloud_name=cloud_name)[resp_key]
142 if len(resp) == 0:
143 raise ResourceNotFound(resp_key, ref)
144 elif len(resp) > 1:
145 raise MultipleResourcesFound(resp_key, ref)
146 uuid = resp[0]['id']
147 return func(uuid, *args[start_arg:], **kwargs)
148 return wrapped_f
149 return wrap