blob: 83d3ebe22654ac63796d69a3bf33363fd2241d93 [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
Mykyta Karpinfa53b302018-06-13 14:52:16 +0300110 return response.json()
111 return wrapped_f
112 return wrap
113
114
115def _check_uuid(val):
116 try:
117 return str(UUID(val)).replace('-', '') == val.replace('-', '')
118 except (TypeError, ValueError, AttributeError):
119 return False
120
121
122def get_by_name_or_uuid(resource_list, resp_key):
123 def wrap(func):
124 def wrapped_f(*args, **kwargs):
125 if 'name' in kwargs:
126 ref = kwargs.pop('name', None)
127 start_arg = 0
128 else:
129 start_arg = 1
130 ref = args[0]
131 if _check_uuid(ref):
132 uuid = ref
133 else:
134 # Then we have name not uuid
135 cloud_name = kwargs['cloud_name']
136 resp = resource_list(
137 name=ref, cloud_name=cloud_name)[resp_key]
138 if len(resp) == 0:
139 raise ResourceNotFound(resp_key, ref)
140 elif len(resp) > 1:
141 raise MultipleResourcesFound(resp_key, ref)
142 uuid = resp[0]['id']
143 return func(uuid, *args[start_arg:], **kwargs)
144 return wrapped_f
145 return wrap