StarlingX NFVI Orchestration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

349 lines
9.4 KiB

#
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import datetime
import iso8601
import re
import six
from nfv_common import debug
from nfv_common.helpers import Constant
from nfv_common.helpers import Constants
from nfv_common.helpers import Singleton
DLOG = debug.debug_get_logger('nfv_vim.api.openstack')
@six.add_metaclass(Singleton)
class ServiceCategory(Constants):
"""
Service Category Constants
"""
PLATFORM = Constant('platform')
OPENSTACK = Constant('openstack')
# Service Category Constant
SERVICE_CATEGORY = ServiceCategory()
@six.add_metaclass(Singleton)
class PlatformServices(Constants):
"""
Platform Services Constants
"""
GUEST = Constant('guest')
KEYSTONE = Constant('keystone')
MTC = Constant('mtc')
SYSINV = Constant('sysinv')
PATCHING = Constant('patching')
FM = Constant('fm')
# Platform Services Constant
PLATFORM_SERVICE = PlatformServices()
@six.add_metaclass(Singleton)
class OpenStackServices(Constants):
"""
OpenStack Services Constants
"""
CEILOMETER = Constant('ceilometer')
CINDER = Constant('cinder')
GLANCE = Constant('glance')
KEYSTONE = Constant('keystone')
NEUTRON = Constant('neutron')
NOVA = Constant('nova')
HEAT = Constant('heat')
FM = Constant('fm')
# OpenStack Services Constant
OPENSTACK_SERVICE = OpenStackServices()
class Service(object):
"""
Service
"""
def __init__(self, region_name, service_name, service_type,
endpoint_type, endpoint_override):
self._region_name = region_name
self._service_name = service_name
self._service_type = service_type
self._endpoint_type = endpoint_type
self._endpoint_override = endpoint_override
@property
def region_name(self):
"""
Returns the region name associated with this entry
"""
return self._region_name
@property
def service_name(self):
"""
Returns the service name associated with this entry
"""
return self._service_name
@property
def service_type(self):
"""
Returns the service type associated with this entry
"""
return self._service_type
@property
def endpoint_type(self):
"""
Returns the endpoint type associated with this entry
"""
return self._endpoint_type
@property
def endpoint_override(self):
"""
Returns the endpoint override associated with this entry
"""
return self._endpoint_override
class Directory(object):
"""
Directory
"""
def __init__(self, service_category, keyring_service, auth_protocol,
auth_host, auth_port, auth_project,
auth_username, auth_password, auth_user_domain_name,
auth_project_domain_name, auth_uri=None):
self._service_category = service_category
self._keyring_service = keyring_service
self._auth_protocol = auth_protocol
self._auth_host = auth_host
self._auth_port = auth_port
self._auth_project = auth_project
self._auth_username = auth_username
self._auth_password = auth_password
self._auth_uri = auth_uri
self._auth_user_domain_name = auth_user_domain_name
self._auth_project_domain_name = auth_project_domain_name
self._entries = dict()
@property
def service_category(self):
"""
Returns the service category
"""
return self._service_category
@property
def keyring_service(self):
"""
Returns the keyring service
"""
return self._keyring_service
@property
def auth_protocol(self):
"""
Returns the authorization protocol
"""
return self._auth_protocol
@property
def auth_host(self):
"""
Returns the authorization host
"""
return self._auth_host
@property
def auth_port(self):
"""
Returns the authorization port
"""
return self._auth_port
@property
def auth_project(self):
"""
Returns the authorization project
"""
return self._auth_project
@property
def auth_username(self):
"""
Returns the authorization username
"""
return self._auth_username
@property
def auth_password(self):
"""
Returns the authorization password
"""
return self._auth_password
@property
def auth_uri(self):
"""
Returns the authorization uri
"""
return self._auth_uri
@property
def auth_user_domain_name(self):
"""
Returns the authorization user domain name
"""
return self._auth_user_domain_name
@property
def auth_project_domain_name(self):
"""
Returns the authorization project domain name
"""
return self._auth_project_domain_name
def set_service_info(self, service, region_name, service_name,
service_type, endpoint_type, endpoint_override):
"""
Set information for a particular service
"""
if self._entries.get(service, None) is not None:
del self._entries[service]
entry = Service(region_name, service_name, service_type,
endpoint_type, endpoint_override)
self._entries[service] = entry
def get_service_info(self, service):
"""
Get information for a particular service
"""
return self._entries.get(service, None)
class Token(object):
"""
Token
"""
def __init__(self, token_data, directory, token_id):
self._expired = False
self._data = token_data
self._directory = directory
self._token_id = token_id
def set_expired(self):
self._expired = True
def is_expired(self, within_seconds=300):
if not self._expired:
end = iso8601.parse_date(self._data['token']['expires_at'])
now = iso8601.parse_date(datetime.datetime.utcnow().isoformat())
if end <= now:
return True
delta = abs(end - now).seconds
return delta <= within_seconds
return True
def is_admin(self):
"""
Check if this token has the admin role.
"""
for role in self._data['token']['roles']:
if role['name'] == 'admin':
return True
return False
def get_id(self):
"""
Get the identifier of the token.
"""
return self._token_id
def get_tenant_id(self):
"""
Get the project identifier of the token.
"""
return self._data['token']['project']['id']
def get_project_name(self):
"""
Get the project name of the token.
"""
return self._data['token']['project']['name']
def get_project_domain_name(self):
"""
Get the project domain name of the token.
"""
return self._data['token']['project']['domain']['name']
def _url_strip_version(self, url):
"""
Strip the version information from the url
"""
# Get rid of the trailing '/' if present and remove the version
# information from the URL.
url = url.rstrip('/')
url_bits = url.split('/')
# Regular-Expression to match 'v1' or 'v2.0' etc
if re.match('v\d+\.?\d*', url_bits[-1]):
url = '/'.join(url_bits[:-1])
elif re.match('v\d+\.?\d*', url_bits[-2]):
url = '/'.join(url_bits[:-2])
return url
def _get_service_url(self, region_name, service_name, service_type,
endpoint_type):
"""
Search the catalog of a service in a region for the url
"""
for catalog in self._data['token']['catalog']:
if catalog['type'] == service_type:
if catalog['name'] == service_name:
if 0 != len(catalog['endpoints']):
for endpoint in catalog['endpoints']:
if (endpoint['region'] == region_name and
endpoint['interface'] == endpoint_type):
return endpoint['url']
return None
def get_service_url(self, service, strip_version=False):
"""
Get the service url for a service
"""
service_info = self._directory.get_service_info(service)
if service_info is not None:
region_name = service_info.region_name
service_name = service_info.service_name
service_type = service_info.service_type
endpoint_type = service_info.endpoint_type
endpoint = self._get_service_url(region_name, service_name,
service_type, endpoint_type)
if service_info.endpoint_override is not None:
if endpoint is None:
endpoint = service_info.endpoint_override
else:
from six.moves import urllib
# this is necessary to keep tenant_id in place
endpoint = \
service_info.endpoint_override + urllib.parse.urlparse(endpoint).path
if strip_version:
endpoint = self._url_strip_version(endpoint)
return endpoint
return None