
This patch set enables PEP8 standard check for project Valet, and corrects all outstanding PEP8 issues. Story: #2001040 Task: #4602 Co-Authored-By: Omar Rivera <gomarivera@gmail.com> Change-Id: I4b987ff28b02ea8a6da77fb0f29eda1515d212ac
199 lines
7.1 KiB
Python
199 lines
7.1 KiB
Python
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
'''Valet API Wrapper'''
|
|
|
|
from heat.common.i18n import _
|
|
import json
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
import requests
|
|
import sys
|
|
|
|
CONF = cfg.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def _exception(exc, exc_info, req):
|
|
'''Handle an exception'''
|
|
response = None
|
|
try:
|
|
if req is not None:
|
|
response = json.loads(req.text)
|
|
except Exception as e:
|
|
# FIXME(GJ): if Valet returns error
|
|
LOG.error("Exception is: %s, body is: %s" % (e, req.text))
|
|
return None
|
|
|
|
if response and 'error' in response:
|
|
# FIXME(GJ): if Valet returns error
|
|
error = response.get('error')
|
|
msg = "%(explanation)s (valet-api: %(message)s)" % {
|
|
'explanation': response.get('explanation',
|
|
_('No remediation available')),
|
|
'message': error.get('message', _('Unknown error'))
|
|
}
|
|
LOG.error("Response with error: " + msg)
|
|
return "error"
|
|
else:
|
|
# TODO(JD): Re-evaluate if this clause is necessary.
|
|
exc_class, exc, traceback = exc_info # pylint: disable=W0612
|
|
msg = (_("%(exc)s for %(method)s %(url)s with body %(body)s") %
|
|
{'exc': exc, 'method': exc.request.method,
|
|
'url': exc.request.url, 'body': exc.request.body})
|
|
LOG.error("Response is none: " + msg)
|
|
return "error"
|
|
|
|
|
|
# TODO(JD): Improve exception reporting back up to heat
|
|
class ValetAPIError(Exception):
|
|
'''Valet API Error'''
|
|
pass
|
|
|
|
|
|
class ValetAPIWrapper(object):
|
|
'''Valet API Wrapper'''
|
|
|
|
def __init__(self):
|
|
'''Initializer'''
|
|
self.headers = {'Content-Type': 'application/json'}
|
|
self.opt_group_str = 'valet'
|
|
self.opt_name_str = 'url'
|
|
self.opt_conn_timeout = 'connect_timeout'
|
|
self.opt_read_timeout = 'read_timeout'
|
|
self._register_opts()
|
|
|
|
def _api_endpoint(self):
|
|
'''Returns API endpoint'''
|
|
try:
|
|
opt = getattr(cfg.CONF, self.opt_group_str)
|
|
endpoint = opt[self.opt_name_str]
|
|
if endpoint:
|
|
return endpoint
|
|
else:
|
|
# FIXME: Possibly not wanted (misplaced-bare-raise)
|
|
raise # pylint: disable=E0704
|
|
except Exception:
|
|
raise # exception.Error(_('API Endpoint not defined.'))
|
|
|
|
def _get_timeout(self):
|
|
'''Returns Valet plugin API request timeout.
|
|
|
|
Returns the timeout values tuple (conn_timeout, read_timeout)
|
|
'''
|
|
read_timeout = 600
|
|
try:
|
|
opt = getattr(cfg.CONF, self.opt_group_str)
|
|
# conn_timeout = opt[self.opt_conn_timeout]
|
|
read_timeout = opt[self.opt_read_timeout]
|
|
except Exception:
|
|
pass
|
|
# Timeout accepts tupple on 'requests' version 2.4.0 and above -
|
|
# adding *connect* timeouts
|
|
# return conn_timeout, read_timeout
|
|
return read_timeout
|
|
|
|
def _register_opts(self):
|
|
'''Register options'''
|
|
opts = []
|
|
option = cfg.StrOpt(
|
|
self.opt_name_str, default=None, help=_('Valet API endpoint'))
|
|
opts.append(option)
|
|
option = cfg.IntOpt(
|
|
self.opt_conn_timeout, default=3,
|
|
help=_('Valet Plugin Connect Timeout'))
|
|
opts.append(option)
|
|
option = cfg.IntOpt(
|
|
self.opt_read_timeout, default=5,
|
|
help=_('Valet Plugin Read Timeout'))
|
|
opts.append(option)
|
|
|
|
opt_group = cfg.OptGroup(self.opt_group_str)
|
|
cfg.CONF.register_group(opt_group)
|
|
cfg.CONF.register_opts(opts, group=opt_group)
|
|
|
|
# TODO(JD): Keep stack param for now. We may need it again.
|
|
def plans_create(self, stack, plan, auth_token=None):
|
|
'''Create a plan'''
|
|
response = None
|
|
try:
|
|
req = None
|
|
timeout = self._get_timeout()
|
|
url = self._api_endpoint() + '/plans/'
|
|
payload = json.dumps(plan)
|
|
self.headers['X-Auth-Token'] = auth_token
|
|
req = requests.post(
|
|
url, data=payload, headers=self.headers, timeout=timeout)
|
|
req.raise_for_status()
|
|
response = json.loads(req.text)
|
|
except (requests.exceptions.HTTPError, requests.exceptions.Timeout,
|
|
requests.exceptions.ConnectionError) as exc:
|
|
return _exception(exc, sys.exc_info(), req)
|
|
except Exception as e:
|
|
LOG.error("Exception (at plans_create) is: %s" % e)
|
|
return None
|
|
return response
|
|
|
|
# TODO(JD): Keep stack param for now. We may need it again.
|
|
def plans_delete(self, stack, auth_token=None): # pylint: disable=W0613
|
|
'''Delete a plan'''
|
|
try:
|
|
req = None
|
|
timeout = self._get_timeout()
|
|
url = self._api_endpoint() + '/plans/' + stack.id
|
|
self.headers['X-Auth-Token'] = auth_token
|
|
req = requests.delete(url, headers=self.headers, timeout=timeout)
|
|
except (requests.exceptions.HTTPError, requests.exceptions.Timeout,
|
|
requests.exceptions.ConnectionError) as exc:
|
|
return _exception(exc, sys.exc_info(), req)
|
|
except Exception as e:
|
|
LOG.error("Exception (plans_delete) is: %s" % e)
|
|
return None
|
|
# Delete does not return a response body.
|
|
|
|
def placement(self, orch_id, res_id, hosts=None, auth_token=None):
|
|
'''Reserve previously made placement.'''
|
|
try:
|
|
req = None
|
|
payload = None
|
|
timeout = self._get_timeout()
|
|
url = self._api_endpoint() + '/placements/' + orch_id
|
|
self.headers['X-Auth-Token'] = auth_token
|
|
if hosts:
|
|
kwargs = {
|
|
"locations": hosts,
|
|
"resource_id": res_id
|
|
}
|
|
payload = json.dumps(kwargs)
|
|
req = requests.post(
|
|
url, data=payload, headers=self.headers, timeout=timeout)
|
|
else:
|
|
req = requests.get(url, headers=self.headers, timeout=timeout)
|
|
|
|
# TODO(JD): Raise an exception IFF the scheduler can handle it
|
|
# req.raise_for_status()
|
|
|
|
response = json.loads(req.text)
|
|
except (requests.exceptions.HTTPError, requests.exceptions.Timeout,
|
|
requests.exceptions.ConnectionError) as exc:
|
|
return _exception(exc, sys.exc_info(), req)
|
|
except Exception as e: # pylint: disable=W0702
|
|
LOG.error("Exception (placement) is: %s" % e)
|
|
# FIXME: Find which exceptions we should really handle here.
|
|
response = None
|
|
|
|
return response
|