blob: 08447fb38d28ca4df2e54ee7261ba73d0f01daa2 [file] [log] [blame]
kairat_kushaev5c8626d2018-06-09 18:15:15 +04001import six
2import logging
3import uuid
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +00004import time
kairat_kushaev5c8626d2018-06-09 18:15:15 +04005
6import os_client_config
7from salt import exceptions
8
9
10log = logging.getLogger(__name__)
11
12SERVICE_KEY = 'volumev3'
13
14
15def get_raw_client(cloud_name):
16 config = os_client_config.OpenStackConfig()
17 cloud = config.get_one_cloud(cloud_name)
18 adapter = cloud.get_session_client(SERVICE_KEY)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040019 try:
20 access_info = adapter.session.auth.get_access(adapter.session)
21 endpoints = access_info.service_catalog.get_endpoints()
22 except (AttributeError, ValueError) as exc:
23 six.raise_from(exc, exceptions.SaltInvocationError(
24 "Cannot load keystoneauth plugin. Please check your environment "
25 "configuration."))
26 if SERVICE_KEY not in endpoints:
27 raise exceptions.SaltInvocationError("Cannot find cinder endpoint in "
28 "environment endpoint list.")
29 return adapter
30
31
32def send(method):
33 def wrap(func):
34 @six.wraps(func)
35 def wrapped_f(*args, **kwargs):
36 cloud_name = kwargs.pop('cloud_name', None)
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +000037 connect_retries = 30
38 connect_retry_delay = 1
kairat_kushaev5c8626d2018-06-09 18:15:15 +040039 if not cloud_name:
40 raise exceptions.SaltInvocationError(
41 "No cloud_name specified. Please provide cloud_name "
42 "parameter")
43 adapter = get_raw_client(cloud_name)
44 kwarg_keys = list(kwargs.keys())
45 for k in kwarg_keys:
46 if k.startswith('__'):
47 kwargs.pop(k)
48 url, request_kwargs = func(*args, **kwargs)
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +000049 response = None
50 for i in range(connect_retries):
51 try:
52 response = getattr(adapter, method.lower())(
53 url, connect_retries=connect_retries,
54 **request_kwargs)
55 except Exception as e:
56 if hasattr(e, 'http_status') and (e.http_status >= 500
57 or e.http_status == 0):
58 msg = ("Got retriable exception when contacting "
59 "Cinder API. Sleeping for %ss. Attepmpts "
60 "%s of %s")
61 log.error(msg % (connect_retry_delay, i, connect_retries))
62 time.sleep(connect_retry_delay)
63 continue
64 break
65 if not response or not response.content:
66 return {}
kairat_kushaev5c8626d2018-06-09 18:15:15 +040067 try:
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +000068 resp = response.json()
69 except ValueError:
70 resp = response.content
71 return resp
kairat_kushaev5c8626d2018-06-09 18:15:15 +040072 return wrapped_f
73 return wrap
74
75
76def _check_uuid(val):
77 try:
78 return str(uuid.UUID(val)) == val
79 except (TypeError, ValueError, AttributeError):
80 return False
81
82
83def get_by_name_or_uuid(resource_list, resp_key):
84 def wrap(func):
85 @six.wraps(func)
86 def wrapped_f(*args, **kwargs):
87 if 'name' in kwargs:
88 ref = kwargs.pop('name', None)
89 start_arg = 0
90 else:
91 start_arg = 1
92 ref = args[0]
93 item_id = None
94 if _check_uuid(ref):
95 item_id = ref
96 else:
97 cloud_name = kwargs['cloud_name']
98 # seems no filtering on volume type name in cinder
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +000099 resp = resource_list(cloud_name=cloud_name)[resp_key]
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400100 # so need to search in list directly
101 for item in resp:
102 if item["name"] == ref:
103 if item_id is not None:
Oleh Hryhorov1aeb0c82018-10-26 14:51:30 +0000104 msg = ("Multiple resource: {resource} "
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400105 "with name: {name} found ").format(
106 resource=resp_key, name=ref)
107 return {"result": False,
108 "body": msg,
109 "status_code": 400}
110 item_id = item["id"]
111 if not item_id:
112 msg = ("Uniq {resource} resource "
113 "with name={name} not found.").format(
114 resource=resp_key, name=ref)
115 return {"result": False,
116 "body": msg,
117 "status_code": 404}
118 return func(item_id, *args[start_arg:], **kwargs)
119 return wrapped_f
120 return wrap