00f43c2b63
Since py2 is no longer supported, built in methods can replace the six package usage, as been done in the neutron project Change-Id: I922963fbbcc0ab263e1f6e56907b73b007015a75
140 lines
5.6 KiB
Python
140 lines
5.6 KiB
Python
# Copyright 2012 VMware, Inc.
|
|
#
|
|
# All Rights Reserved
|
|
#
|
|
# 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.
|
|
#
|
|
from http import client as httplib
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from vmware_nsx.api_client import base
|
|
from vmware_nsx.api_client import eventlet_client
|
|
from vmware_nsx.api_client import eventlet_request
|
|
from vmware_nsx.api_client import exception
|
|
from vmware_nsx.api_client import version
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class NsxApiClient(eventlet_client.EventletApiClient):
|
|
"""The Nsx API Client."""
|
|
|
|
def __init__(self, api_providers, user, password,
|
|
concurrent_connections=base.DEFAULT_CONCURRENT_CONNECTIONS,
|
|
gen_timeout=base.GENERATION_ID_TIMEOUT,
|
|
use_https=True,
|
|
connect_timeout=base.DEFAULT_CONNECT_TIMEOUT,
|
|
http_timeout=75, retries=2, redirects=2):
|
|
'''Constructor. Adds the following:
|
|
|
|
:param http_timeout: how long to wait before aborting an
|
|
unresponsive controller (and allow for retries to another
|
|
controller in the cluster)
|
|
:param retries: the number of concurrent connections.
|
|
:param redirects: the number of concurrent connections.
|
|
'''
|
|
super(NsxApiClient, self).__init__(
|
|
api_providers, user, password,
|
|
concurrent_connections=concurrent_connections,
|
|
gen_timeout=gen_timeout, use_https=use_https,
|
|
connect_timeout=connect_timeout)
|
|
|
|
self._request_timeout = http_timeout * retries
|
|
self._http_timeout = http_timeout
|
|
self._retries = retries
|
|
self._redirects = redirects
|
|
self._version = None
|
|
|
|
# NOTE(salvatore-orlando): This method is not used anymore. Login is now
|
|
# performed automatically inside the request eventlet if necessary.
|
|
def login(self, user=None, password=None):
|
|
'''Login to NSX controller.
|
|
|
|
Assumes same password is used for all controllers.
|
|
|
|
:param user: controller user (usually admin). Provided for
|
|
backwards compatibility. In the normal mode of operation
|
|
this should be None.
|
|
:param password: controller password. Provided for backwards
|
|
compatibility. In the normal mode of operation this should
|
|
be None.
|
|
'''
|
|
if user:
|
|
self._user = user
|
|
if password:
|
|
self._password = password
|
|
|
|
return self._login()
|
|
|
|
def request(self, method, url, body="", content_type="application/json"):
|
|
'''Issues request to controller.'''
|
|
|
|
g = eventlet_request.GenericRequestEventlet(
|
|
self, method, url, body, content_type, auto_login=True,
|
|
http_timeout=self._http_timeout,
|
|
retries=self._retries, redirects=self._redirects)
|
|
g.start()
|
|
response = g.join()
|
|
LOG.debug('Request returns "%s"', response)
|
|
|
|
# response is a modified HTTPResponse object or None.
|
|
# response.read() will not work on response as the underlying library
|
|
# request_eventlet.ApiRequestEventlet has already called this
|
|
# method in order to extract the body and headers for processing.
|
|
# ApiRequestEventlet derived classes call .read() and
|
|
# .getheaders() on the HTTPResponse objects and store the results in
|
|
# the response object's .body and .headers data members for future
|
|
# access.
|
|
|
|
if response is None:
|
|
# Timeout.
|
|
LOG.error('Request timed out: %(method)s to %(url)s',
|
|
{'method': method, 'url': url})
|
|
raise exception.RequestTimeout()
|
|
|
|
status = response.status
|
|
if status == httplib.UNAUTHORIZED:
|
|
raise exception.UnAuthorizedRequest()
|
|
|
|
# Fail-fast: Check for exception conditions and raise the
|
|
# appropriate exceptions for known error codes.
|
|
if status in exception.ERROR_MAPPINGS:
|
|
LOG.error("Received error code: %s", status)
|
|
LOG.error("Server Error Message: %s", response.body)
|
|
exception.ERROR_MAPPINGS[status](response)
|
|
|
|
# Continue processing for non-error condition.
|
|
if (status != httplib.OK and status != httplib.CREATED and
|
|
status != httplib.NO_CONTENT):
|
|
LOG.error("%(method)s to %(url)s, unexpected response code: "
|
|
"%(status)d (content = '%(body)s')",
|
|
{'method': method, 'url': url,
|
|
'status': response.status, 'body': response.body})
|
|
return None
|
|
|
|
if not self._version:
|
|
self._version = version.find_version(response.headers)
|
|
return response.body
|
|
|
|
def get_version(self):
|
|
if not self._version:
|
|
# Determine the controller version by querying the
|
|
# cluster nodes. Currently, the version will be the
|
|
# one of the server that responds.
|
|
self.request('GET', '/ws.v1/control-cluster/node')
|
|
if not self._version:
|
|
LOG.error('Unable to determine NSX version. '
|
|
'Plugin might not work as expected.')
|
|
return self._version
|