blob: 88c08b60b2bb60f447f9479ed59768c4f25ac326 [file] [log] [blame]
Oleksiy Petrenko5bfb8bc2018-08-23 15:08:17 +03001import functools
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +03002import logging
Vasyl Saienkocb788d42018-09-26 10:34:50 +00003import time
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +03004
Oleksiy Petrenkoa0894712019-02-06 13:10:24 +02005try:
6 import os_client_config
7except ImportError:
8 os_client_config = None
9from salt import exceptions
10
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +020011
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +030012log = logging.getLogger(__name__)
13
14NEUTRON_VERSION_HEADER = 'x-openstack-networking-version'
15ADAPTER_VERSION = '2.0'
16
17
18class NeutronException(Exception):
19
20 _msg = "Neutron module exception occured."
21
22 def __init__(self, message=None, **kwargs):
23 super(NeutronException, self).__init__(message or self._msg)
24
25
26class NoNeutronEndpoint(NeutronException):
27 _msg = "Neutron endpoint not found in keystone catalog."
28
29
30class NoAuthPluginConfigured(NeutronException):
31 _msg = ("You are using keystoneauth auth plugin that does not support "
32 "fetching endpoint list from token (noauth or admin_token).")
33
34
35class NoCredentials(NeutronException):
36 _msg = "Please provide cloud name present in clouds.yaml."
37
38
39class ResourceNotFound(NeutronException):
40 _msg = "Uniq resource: {resource} with name: {name} not found."
41
42 def __init__(self, resource, name, **kwargs):
43 super(NeutronException, self).__init__(
44 self._msg.format(resource=resource, name=name))
45
46
47class MultipleResourcesFound(NeutronException):
48 _msg = "Multiple resource: {resource} with name: {name} found."
49
50 def __init__(self, resource, name, **kwargs):
51 super(NeutronException, self).__init__(
52 self._msg.format(resource=resource, name=name))
53
54
55def _get_raw_client(cloud_name):
Oleksiy Petrenkoa0894712019-02-06 13:10:24 +020056 if not os_client_config:
57 raise exceptions.SaltInvocationError(
58 "Cannot load os-client-config. Please check your environment "
59 "configuration.")
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +030060 service_type = 'network'
61 config = os_client_config.OpenStackConfig()
62 cloud = config.get_one_cloud(cloud_name)
63 adapter = cloud.get_session_client(service_type)
64 adapter.version = ADAPTER_VERSION
65 try:
66 access_info = adapter.session.auth.get_access(adapter.session)
67 access_info.service_catalog.get_endpoints()
68 except (AttributeError, ValueError):
69 e = NoAuthPluginConfigured()
70 log.exception('%s' % e)
71 raise e
72 return adapter
73
74
75def send(method):
76 def wrap(func):
Oleksiy Petrenko5bfb8bc2018-08-23 15:08:17 +030077 @functools.wraps(func)
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +030078 def wrapped_f(*args, **kwargs):
79 cloud_name = kwargs.pop('cloud_name')
Vasyl Saienko65fb5d32018-10-24 12:51:51 +000080 connect_retries = 30
Vasyl Saienkocb788d42018-09-26 10:34:50 +000081 connect_retry_delay = 1
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +030082 if not cloud_name:
83 e = NoCredentials()
84 log.error('%s' % e)
85 raise e
86 adapter = _get_raw_client(cloud_name)
87 # Remove salt internal kwargs
88 kwarg_keys = list(kwargs.keys())
89 for k in kwarg_keys:
90 if k.startswith('__'):
91 kwargs.pop(k)
92 url, request_kwargs = func(*args, **kwargs)
93 if 'microversion' in kwargs:
94 request_kwargs['headers'][
95 NEUTRON_VERSION_HEADER] = kwargs['microversion']
Vasyl Saienko65fb5d32018-10-24 12:51:51 +000096 response = None
Vasyl Saienkocb788d42018-09-26 10:34:50 +000097 for i in range(connect_retries):
98 try:
99 response = getattr(adapter, method)(
100 url, connect_retries=connect_retries,
101 **request_kwargs)
102 except Exception as e:
Oleh Hryhorov42a930e2018-12-21 14:37:20 +0200103 if not hasattr(e, 'http_status') or (e.http_status >= 500
Vasyl Saienkocb788d42018-09-26 10:34:50 +0000104 or e.http_status == 0):
105 msg = ("Got retriable exception when contacting "
106 "Neutron API. Sleeping for %ss. Attepmpts "
107 "%s of %s")
108 log.error(msg % (connect_retry_delay, i, connect_retries))
109 time.sleep(connect_retry_delay)
110 continue
111 break
Vasyl Saienko65fb5d32018-10-24 12:51:51 +0000112 if not response or not response.content:
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +0300113 return {}
114 try:
115 resp = response.json()
116 except ValueError:
117 resp = response.content
118 return resp
119 return wrapped_f
120 return wrap
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +0200121
122def wait_for_api_ready(cloud_name, retries=1, retry_timeout=10, **kwargs):
123
124 adapter = _get_raw_client(cloud_name)
125 response = None
126 for i in range(1, retries+1):
127 try:
128 response = getattr(adapter, 'get')(
129 '/', connect_retries=retries,
130 **kwargs)
131 except Exception as e:
132 msg = ("Error: %s "
133 "Sleeping for %ss. "
134 "Attempts %s of %s ")
135 log.error(msg % (e, retry_timeout, i, retries))
136 time.sleep(retry_timeout)
137 continue
138 break
139 if not response or not response.content:
140 if e:
Oleksiy Petrenkoa0894712019-02-06 13:10:24 +0200141 raise exceptions.CommandExecutionError(e)
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +0200142 else:
143 return {}
144 try:
145 resp = response.json()
146 except ValueError:
147 resp = response.content
148 return resp
149