vmware-nsx/vmware_nsx_tempest/services/nsxv_client.py
Alex Kang 00c98dce02 init release of vmware-nsx tempest tests in tempest external plugin
installation procedure & tech-notes at vmware_nsx_tempest/README.rst
With this plugin method, vmware_nsx_tempest tests can be treated as
tempest tests and executed under tempest environment.

Fix nsxv_client to support multiple transport zones.

Change-Id: Id103c0ce03d75749fe6295108db48493f565b05a
Implements:  blueprint vmware-nsx-tempest-plugin
2016-01-21 10:02:00 -08:00

264 lines
9.4 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.
import base64
from oslo_log import log as logging
from oslo_serialization import jsonutils
import requests
from tempest import config
import vmware_nsx_tempest.services.utils as utils
requests.packages.urllib3.disable_warnings()
CONF = config.CONF
LOG = logging.getLogger(__name__)
class VSMClient(object):
"""NSX-v client.
The client provides the API operations on its components.
The purpose of this rest client is to query backend components after
issuing corresponding API calls from OpenStack. This is to make sure
the API calls has been realized on the NSX-v backend.
"""
API_VERSION = "2.0"
def __init__(self, host, username, password, *args, **kwargs):
self.force = True if 'force' in kwargs else False
self.host = host
self.username = username
self.password = password
self.version = None
self.endpoint = None
self.content_type = "application/json"
self.accept_type = "application/json"
self.verify = False
self.secure = True
self.interface = "json"
self.url = None
self.headers = None
self.api_version = VSMClient.API_VERSION
self.default_scope_id = None
self.__set_headers()
self._version = self.get_vsm_version()
def __set_endpoint(self, endpoint):
self.endpoint = endpoint
def get_endpoint(self):
return self.endpoint
def __set_content_type(self, content_type):
self.content_type = content_type
def get_content_type(self):
return self.content_type
def __set_accept_type(self, accept_type):
self.accept_type = accept_type
def get_accept_type(self):
return self.accept_type
def __set_api_version(self, api_version):
self.api_version = api_version
def get_api_version(self):
return self.api_version
def __set_url(self, version=None, secure=None, host=None, endpoint=None):
version = self.api_version if version is None else version
secure = self.secure if secure is None else secure
host = self.host if host is None else host
endpoint = self.endpoint if endpoint is None else endpoint
http_type = 'https' if secure else 'http'
self.url = '%s://%s/api/%s%s' % (http_type, host, version, endpoint)
def get_url(self):
return self.url
def __set_headers(self, content=None, accept=None):
content_type = self.content_type if content is None else content
accept_type = self.accept_type if accept is None else accept
auth_cred = self.username + ":" + self.password
auth = base64.b64encode(auth_cred)
headers = {}
headers['Authorization'] = "Basic %s" % auth
headers['Content-Type'] = content_type
headers['Accept'] = accept_type
self.headers = headers
def get(self, endpoint=None, params=None):
"""Basic query GET method for json API request."""
self.__set_url(endpoint=endpoint)
response = requests.get(self.url, headers=self.headers,
verify=self.verify, params=params)
return response
def delete(self, endpoint=None, params=None):
"""Basic delete API method on endpoint."""
self.__set_url(endpoint=endpoint)
response = requests.delete(self.url, headers=self.headers,
verify=self.verify, params=params)
return response
def post(self, endpoint=None, body=None):
"""Basic post API method on endpoint."""
self.__set_url(endpoint=endpoint)
response = requests.post(self.url, headers=self.headers,
verify=self.verify,
data=jsonutils.dumps(body))
return response
def get_all_vdn_scopes(self):
"""Retrieve existing network scopes"""
self.__set_api_version('2.0')
self.__set_endpoint("/vdn/scopes")
response = self.get()
return response.json()['allScopes']
# return the vdn_scope_id for the priamry Transport Zone
def get_vdn_scope_id(self):
"""Retrieve existing network scope id."""
scopes = self.get_all_vdn_scopes()
if len(scopes) == 0:
return scopes[0]['objectId']
return CONF.nsxv.vdn_scope_id
def get_vdn_scope_by_id(self, scope_id):
"""Retrieve existing network scopes id"""
self.__set_api_version('2.0')
self.__set_endpoint("/vdn/scopes/%s" % scope_id)
return self.get().json()
def get_vdn_scope_by_name(self, name):
"""Retrieve network scope id of existing scope name:
nsxv_client.get_vdn_scope_id_by_name('TZ1')
"""
scopes = self.get_all_vdn_scopes()
if name is None:
for scope in scopes:
if scope['objectId'] == CONF.nsxv.vdn_scope_id:
return scope
else:
for scope in scopes:
if scope['name'] == name:
return scope
return None
def get_all_logical_switches(self, vdn_scope_id=None):
lswitches = []
self.__set_api_version('2.0')
vdn_scope_id = vdn_scope_id or self.get_vdn_scope_id()
endpoint = "/vdn/scopes/%s/virtualwires" % (vdn_scope_id)
self.__set_endpoint(endpoint)
response = self.get()
paging_info = response.json()['dataPage']['pagingInfo']
page_size = int(paging_info['pageSize'])
total_count = int(paging_info['totalCount'])
msg = ("There are total %s logical switches and page size is %s"
% (total_count, page_size))
LOG.debug(msg)
pages = utils.ceil(total_count, page_size)
LOG.debug("Total pages: %s" % pages)
for i in range(pages):
start_index = page_size * i
params = {'startindex': start_index}
response = self.get(params=params)
lswitches += response.json()['dataPage']['data']
return lswitches
def get_logical_switch(self, name):
"""Get the logical switch based on the name.
The uuid of the OpenStack L2 network. Return ls if found,
otherwise return None.
"""
lswitches = self.get_all_logical_switches()
lswitch = [ls for ls in lswitches if ls['name'] == name]
if len(lswitch) == 0:
LOG.debug('logical switch %s NOT found!' % name)
lswitch = None
else:
ls = lswitch[0]
LOG.debug('Found lswitch: %s' % ls)
return ls
def delete_logical_switch(self, name):
"""Delete logical switch based on name.
The name of the logical switch on NSX-v is the uuid
of the openstack l2 network.
"""
ls = self.get_logical_switch(name)
if ls is not None:
endpoint = '/vdn/virtualwires/%s' % ls['objectId']
response = self.delete(endpoint=endpoint)
if response.status_code == 200:
LOG.debug('Successfully deleted logical switch %s' % name)
else:
LOG.debug('ERROR @delete ls=%s failed with reponse code %s' %
(name, response.status_code))
def get_all_edges(self):
"""Get all edges on NSX-v backend."""
self.__set_api_version('4.0')
self.__set_endpoint('/edges')
edges = []
response = self.get()
paging_info = response.json()['edgePage']['pagingInfo']
page_size = int(paging_info['pageSize'])
total_count = int(paging_info['totalCount'])
msg = "There are total %s edges and page size is %s" % (total_count,
page_size)
LOG.debug(msg)
pages = utils.ceil(total_count, page_size)
for i in range(pages):
start_index = page_size * i
params = {'startindex': start_index}
response = self.get(params=params)
edges += response.json()['edgePage']['data']
return edges
def get_edge(self, name):
"""Get edge based on the name, which is OpenStack router.
Return edge if found, else return None.
"""
edges = self.get_all_edges()
edge = [e for e in edges if e['name'] == name]
if len(edge) == 0:
LOG.debug('Edge %s NOT found!' % name)
edge = None
else:
edge = edge[0]
LOG.debug('Found edge: %s' % edge)
return edge
def get_vsm_version(self):
"""Get the VSM client version including major, minor, patch, & build#.
Build number, e.g. 6.2.0.2986609
return: vsm version
"""
self.__set_api_version('1.0')
self.__set_endpoint('/appliance-management/global/info')
response = self.get()
json_ver = response.json()['versionInfo']
return '.'.join([json_ver['majorVersion'], json_ver['minorVersion'],
json_ver['patchVersion'], json_ver['buildNumber']])